[dali_2.2.37] Merge branch 'devel/master' 92/296492/1
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 28 Jul 2023 13:52:47 +0000 (14:52 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 28 Jul 2023 13:52:47 +0000 (14:52 +0100)
Change-Id: Ic71aec4a694c1163df9671e14b6ddb6d3ccf0b34

852 files changed:
.gitignore
automated-tests/resources/test-empty.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy0.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy1.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy2.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy3.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy4.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy5.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy6.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-hierarchy7.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-motion0.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-motion1.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-motion2.bvh [new file with mode: 0644]
automated-tests/resources/test-invalid-motion3.bvh [new file with mode: 0644]
automated-tests/src/dali-scene3d/utc-Dali-BvhLoader.cpp
build/tizen/CMakeLists.txt
build/tizen/dali-physics/CMakeLists.txt [new file with mode: 0644]
build/tizen/dali-physics/dali2-physics-2d.pc.in [new file with mode: 0644]
build/tizen/dali-physics/dali2-physics-3d.pc.in [new file with mode: 0644]
dali-physics-2d.manifest [new file with mode: 0644]
dali-physics-2d.manifest-smack [new file with mode: 0644]
dali-physics-3d.manifest [new file with mode: 0644]
dali-physics-3d.manifest-smack [new file with mode: 0644]
dali-physics/third-party/.clang-format [new file with mode: 0644]
dali-physics/third-party/bullet3/.ci/docker/env.list [new file with mode: 0644]
dali-physics/third-party/bullet3/.ci/docker/ubuntu-bionic [new file with mode: 0644]
dali-physics/third-party/bullet3/.ci/docker/ubuntu-xenial [new file with mode: 0644]
dali-physics/third-party/bullet3/.ci/script.sh [new file with mode: 0755]
dali-physics/third-party/bullet3/.github/workflows/cmake.yml [new file with mode: 0644]
dali-physics/third-party/bullet3/.gitignore [new file with mode: 0644]
dali-physics/third-party/bullet3/.style.yapf [new file with mode: 0644]
dali-physics/third-party/bullet3/AUTHORS.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/BulletConfig.cmake.in [new file with mode: 0644]
dali-physics/third-party/bullet3/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/Config.cmake.in [new file with mode: 0644]
dali-physics/third-party/bullet3/LICENSE.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/MANIFEST.in [new file with mode: 0644]
dali-physics/third-party/bullet3/README.md [new file with mode: 0644]
dali-physics/third-party/bullet3/UseBullet.cmake [new file with mode: 0644]
dali-physics/third-party/bullet3/VERSION [new file with mode: 0644]
dali-physics/third-party/bullet3/_clang-format [new file with mode: 0644]
dali-physics/third-party/bullet3/appveyor.yml [new file with mode: 0644]
dali-physics/third-party/bullet3/bullet3.pc.cmake [new file with mode: 0644]
dali-physics/third-party/bullet3/clang-format-all.sh [new file with mode: 0755]
dali-physics/third-party/bullet3/setup.py [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3Config.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Collision/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3AlignedAllocator.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3AlignedAllocator.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3AlignedObjectArray.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3CommandLineArgs.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3FileUtils.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3HashMap.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3Logging.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3Logging.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3Matrix3x3.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3MinMax.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3PoolAllocator.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3QuadWord.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3Quaternion.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3Random.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3ResizablePool.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3Scalar.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3StackAlloc.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3Transform.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3TransformUtil.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3Vector3.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/b3Vector3.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Float4.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Int2.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Int4.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Mat3x3.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3PlatformDefinitions.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Quat.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3ContactConstraint4.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3ConvertConstraint4.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3Inertia.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3IntegrateTransforms.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Geometry/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Geometry/b3AabbUtil.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Geometry/b3ConvexHullComputer.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Geometry/b3ConvexHullComputer.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Geometry/b3GeometryUtil.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Geometry/b3GeometryUtil.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Geometry/b3GrahamScan2dConvexHull.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Geometry/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/Initialize/b3OpenCLInclude.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/b3GpuRaycast.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3Solver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3Solver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveContact.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3OpenCL/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Common.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Defines.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3File.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvt.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvt.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDispatcher.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionObject.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorld.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btGhostObject.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btGhostObject.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btManifoldResult.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btUnionFind.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btUnionFind.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBox2dShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBox2dShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCapsuleShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCollisionMargin.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCollisionShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCollisionShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCompoundShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCompoundShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConcaveShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConcaveShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConeShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConeShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvex2dShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexHullShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexInternalShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCylinderShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCylinderShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btEmptyShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btEmptyShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMaterial.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMiniSDF.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMiniSDF.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultiSphereShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btOptimizedBvh.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSdfCollisionShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btShapeHull.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btShapeHull.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSphereShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSphereShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTetrahedronShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleBuffer.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleCallback.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMesh.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btUniformScalingShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btBoxCollision.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btClipPolygon.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btCompoundFromGimpact.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btContactProcessing.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btContactProcessing.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btContactProcessingStructs.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactBvh.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactBvh.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactBvhStructs.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactMassUtil.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactShape.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactShape.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGenericPoolAllocator.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGeometryOperations.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btQuantization.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btTriangleShapeEx.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_array.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_bitset.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_box_collision.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_box_set.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_box_set.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_clip_polygon.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_contact.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_contact.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_geom_types.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_geometry.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_hash_table.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_linear_math.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_math.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_memory.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_memory.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_pair.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_radixsort.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_tri_collision.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_tri_collision.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btMprPenetration.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletCollision/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Character/btCharacterControllerInterface.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Character/btKinematicCharacterController.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Character/btKinematicCharacterController.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btBatchedConstraints.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btContactConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGearConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp [new file with mode: 0755]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h [new file with mode: 0755]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolverBody.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btActionInterface.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDynamicsWorld.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btRigidBody.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btRigidBody.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBody.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBody.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyLink.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointLimit.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointLimit.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btLemkeSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btPATHSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btRaycastVehicle.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btVehicleRaycaster.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btWheelInfo.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btWheelInfo.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletDynamics/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDConfig.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDConfigBuiltin.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDConfigEigen.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDErrorMessages.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDMath.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDMath.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/MultiBodyTree.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/MultiBodyTree.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/IDEigenInterface.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/IDLinearMathInterface.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/IDMatVec.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletInverseDynamics/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBody.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBody.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodyHelpers.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodyHelpers.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodySolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodySolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableContactConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableContactConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btCGProjection.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btConjugateGradient.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btConjugateResidual.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDefaultSoftBodySolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDefaultSoftBodySolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBackwardEulerObjective.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBackwardEulerObjective.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBodySolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBodySolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactConstraint.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactConstraint.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactProjection.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactProjection.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableCorotatedForce.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableGravityForce.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableLagrangianForce.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableLinearElasticityForce.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMassSpringForce.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMousePickingForce.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableNeoHookeanForce.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btKrylovSolver.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btPreconditioner.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBody.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBody.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyData.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyHelpers.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyHelpers.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyInternals.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodySolvers.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidDynamicsWorld.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/btSparseSDF.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/poly34.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/poly34.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/BulletSoftBody/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btTaskScheduler.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btThreadSupportInterface.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btThreadSupportPosix.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btThreadSupportWin32.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btAabbUtil2.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btAlignedAllocator.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btAlignedAllocator.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btAlignedObjectArray.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btConvexHull.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btConvexHull.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btConvexHullComputer.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btConvexHullComputer.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btCpuFeatureUtility.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btDefaultMotionState.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btGeometryUtil.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btGeometryUtil.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btGrahamScan2dConvexHull.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btHashMap.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btIDebugDraw.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btImplicitQRSVD.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btList.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btMatrix3x3.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btMatrixX.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btMinMax.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btModifiedGramSchmidt.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btMotionState.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btPolarDecomposition.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btPolarDecomposition.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btPoolAllocator.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btQuadWord.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btQuaternion.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btQuickprof.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btQuickprof.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btRandom.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btReducedVector.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btReducedVector.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btScalar.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btSerializer.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btSerializer.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btSerializer64.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btSpatialAlgebra.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btStackAlloc.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btThreads.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btThreads.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btTransform.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btTransformUtil.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btVector3.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/btVector3.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/LinearMath/premake4.lua [new file with mode: 0644]
dali-physics/third-party/bullet3/src/btBulletCollisionAll.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/btBulletCollisionCommon.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/btBulletDynamicsAll.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/btBulletDynamicsCommon.h [new file with mode: 0644]
dali-physics/third-party/bullet3/src/btLinearMathAll.cpp [new file with mode: 0644]
dali-physics/third-party/bullet3/src/clew/clew.c [new file with mode: 0644]
dali-physics/third-party/bullet3/src/clew/clew.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/.gitignore [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/LICENSE.txt [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/README.md [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/TODO.txt [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/VERSION.txt [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/android/Android.mk [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/codeblocks/Chipmunk.cbp [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_ffi.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_private.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_structs.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_types.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_unsafe.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpArbiter.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpBB.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpBody.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpConstraint.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpDampedRotarySpring.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpDampedSpring.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpGearJoint.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpGrooveJoint.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpHastySpace.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpMarch.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpPinJoint.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpPivotJoint.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpPolyShape.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpPolyline.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpRatchetJoint.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpRobust.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpRotaryLimitJoint.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpShape.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpSimpleMotor.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpSlideJoint.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpSpace.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpSpatialIndex.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpTransform.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/include/chipmunk/cpVect.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkAutoGeometry.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkBody.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkConstraint.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkImageSampler.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkMultiGrab.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkPointCloudSampler.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkShape.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkSpace.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkTileCache.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ObjectiveChipmunk.h [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkAutoGeometry.m [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkBody.m [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkConstraint.m [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkImageSampler.m [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkMultiGrab.m [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkPointCloudSampler.m [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkShape.m [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkSpace.m [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkTileCache.m [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/CMakeLists.txt [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/chipmunk.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/chipmunk2d.pc.in [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpArbiter.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpArray.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpBBTree.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpBody.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpCollision.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpConstraint.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpDampedRotarySpring.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpDampedSpring.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpGearJoint.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpGrooveJoint.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpHashSet.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpHastySpace.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpMarch.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpPinJoint.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpPivotJoint.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpPolyShape.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpPolyline.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpRatchetJoint.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpRobust.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpRotaryLimitJoint.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpShape.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpSimpleMotor.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpSlideJoint.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpSpace.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpSpaceComponent.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpSpaceDebug.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpSpaceHash.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpSpaceQuery.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpSpaceStep.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpSpatialIndex.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/cpSweep1D.c [new file with mode: 0644]
dali-physics/third-party/chipmunk2d/src/prime.h [new file with mode: 0644]
dali-scene3d/public-api/loader/bvh-loader.cpp
dali-toolkit/devel-api/visuals/animated-image-visual-actions-devel.h
dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h
dali-toolkit/devel-api/visuals/image-visual-actions-devel.h
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index 27436e2..2c8d0d1 100644 (file)
@@ -40,6 +40,8 @@ install_manifest.txt
 /docs/generated/*
 /build/tizen/doc
 /build/tizen/.cov
+/build/tizen/CPack*.cmake
+/build/tizen/dali-physics/*
 /build/desktop
 /packaging/home*
 compile_commands.json
diff --git a/automated-tests/resources/test-empty.bvh b/automated-tests/resources/test-empty.bvh
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/automated-tests/resources/test-invalid-hierarchy0.bvh b/automated-tests/resources/test-invalid-hierarchy0.bvh
new file mode 100644 (file)
index 0000000..c8c0cb8
--- /dev/null
@@ -0,0 +1,19 @@
+HIERARCHY
+ROOT root
+{
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+    {
+      OFFSET 0 0 0
+    }
+  }
+MOTION
+Frames:        2
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-hierarchy1.bvh b/automated-tests/resources/test-invalid-hierarchy1.bvh
new file mode 100644 (file)
index 0000000..be6cd56
--- /dev/null
@@ -0,0 +1,19 @@
+HIERARCHY
+ROOT root
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+    {
+      OFFSET 0 0 0
+    }
+  }
+}
+MOTION
+Frames:        2
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-hierarchy2.bvh b/automated-tests/resources/test-invalid-hierarchy2.bvh
new file mode 100644 (file)
index 0000000..3bb962a
--- /dev/null
@@ -0,0 +1,18 @@
+HIERARCHY
+ROOT root
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+    {
+      OFFSET 0 0 0
+    }
+  }
+MOTION
+Frames:        2
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-hierarchy3.bvh b/automated-tests/resources/test-invalid-hierarchy3.bvh
new file mode 100644 (file)
index 0000000..3ff6a12
--- /dev/null
@@ -0,0 +1,19 @@
+HIERARCHY
+ROOT root
+{
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+    {
+      OFFSET 0 0 0
+  }
+}
+MOTION
+Frames:        2
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-hierarchy4.bvh b/automated-tests/resources/test-invalid-hierarchy4.bvh
new file mode 100644 (file)
index 0000000..3175816
--- /dev/null
@@ -0,0 +1,19 @@
+HIERARCHY
+ROOT root
+{
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+      OFFSET 0 0 0
+    }
+  }
+}
+MOTION
+Frames:        2
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-hierarchy5.bvh b/automated-tests/resources/test-invalid-hierarchy5.bvh
new file mode 100644 (file)
index 0000000..576adae
--- /dev/null
@@ -0,0 +1,18 @@
+HIERARCHY
+ROOT root
+{
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+      OFFSET 0 0 0
+  }
+}
+MOTION
+Frames:        2
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-hierarchy6.bvh b/automated-tests/resources/test-invalid-hierarchy6.bvh
new file mode 100644 (file)
index 0000000..6f64833
--- /dev/null
@@ -0,0 +1,22 @@
+HIERARCHY
+ROOT root
+{
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+    {
+      {
+        OFFSET 0 0 0
+      }
+    }
+  }
+}
+MOTION
+Frames:        2
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-hierarchy7.bvh b/automated-tests/resources/test-invalid-hierarchy7.bvh
new file mode 100644 (file)
index 0000000..058fde0
--- /dev/null
@@ -0,0 +1,22 @@
+HIERARCHY
+ROOT root
+{
+  {
+    OFFSET 0.0 -0.948831 1.32574
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    JOINT first
+    {
+      OFFSET -0.0 4.130377 -0.008512
+      CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+      End Site
+      {
+        OFFSET 0 0 0
+      }
+    }
+  }
+}
+MOTION
+Frames:        2
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-motion0.bvh b/automated-tests/resources/test-invalid-motion0.bvh
new file mode 100644 (file)
index 0000000..37a8bdc
--- /dev/null
@@ -0,0 +1,21 @@
+HIERARCHY
+ROOT root
+{
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+    {
+      OFFSET 0 0 0
+    }
+  }
+}
+MOTION
+Frames:        3
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-motion1.bvh b/automated-tests/resources/test-invalid-motion1.bvh
new file mode 100644 (file)
index 0000000..1bba75a
--- /dev/null
@@ -0,0 +1,20 @@
+HIERARCHY
+ROOT root
+{
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+    {
+      OFFSET 0 0 0
+    }
+  }
+}
+MOTION
+Frames:        1
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-motion2.bvh b/automated-tests/resources/test-invalid-motion2.bvh
new file mode 100644 (file)
index 0000000..c003a2d
--- /dev/null
@@ -0,0 +1,19 @@
+HIERARCHY
+ROOT root
+{
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+    {
+      OFFSET 0 0 0
+    }
+  }
+}
+MOTION
+Frame Time:    0.3
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
diff --git a/automated-tests/resources/test-invalid-motion3.bvh b/automated-tests/resources/test-invalid-motion3.bvh
new file mode 100644 (file)
index 0000000..0a4a582
--- /dev/null
@@ -0,0 +1,19 @@
+HIERARCHY
+ROOT root
+{
+  OFFSET 0.0 -0.948831 1.32574
+  CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+  JOINT first
+  {
+    OFFSET -0.0 4.130377 -0.008512
+    CHANNELS 6 Xposition Yposition Zposition Zrotation Xrotation Yrotation
+    End Site
+    {
+      OFFSET 0 0 0
+    }
+  }
+}
+MOTION
+Frames:        2
+0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+0.0 10.0 0.0 0.0 0.0 0.0 10.0 0.0 0.0 90.0 0.0 0.0
\ No newline at end of file
index d642ef4..4fb5a79 100644 (file)
@@ -154,4 +154,37 @@ int UtcDaliLoadBvhFailed02(void)
   AnimationDefinition animDef = LoadBvhFromBuffer(nullptr, 0, "testBvh");
   DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION);
   END_TEST;
+}
+
+int UtcDaliLoadBvhFailed03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Parse error for hierarchy1");
+  uint32_t caseHierarchyCount = 8;
+  for(uint32_t tc = 0; tc < caseHierarchyCount; ++tc)
+  {
+    tet_printf("Parse error for hierarchy %u\n", tc);
+    std::ostringstream oss;
+    oss << TEST_RESOURCE_DIR << "/test-invalid-hierarchy" << tc << ".bvh";
+    AnimationDefinition animDef = LoadBvh(oss.str(), "testBvh");
+    DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION);
+  }
+
+  uint32_t caseMotionCount = 4;
+  for(uint32_t tc = 0; tc < caseMotionCount; ++tc)
+  {
+    tet_printf("Parse error for motion %u\n", tc);
+    std::ostringstream oss;
+    oss << TEST_RESOURCE_DIR << "/test-invalid-motion" << tc << ".bvh";
+    AnimationDefinition animDef = LoadBvh(oss.str(), "testBvh");
+    DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION);
+  }
+
+  {
+    tet_infoline("empty file");
+    AnimationDefinition animDef = LoadBvh(TEST_RESOURCE_DIR "/test-empty.bvh", "testBvh");
+    DALI_TEST_EQUALS(0u, animDef.GetPropertyCount(), TEST_LOCATION);
+  }
+  END_TEST;
 }
\ No newline at end of file
index ba91bb2..dbfc431 100644 (file)
@@ -35,6 +35,7 @@ OPTION(INSTALL_DOXYGEN_DOC       "Install doxygen doc" ON)
 OPTION(CONFIGURE_AUTOMATED_TESTS "Configure automated tests" ON)
 OPTION(USE_DEFAULT_RESOURCE_DIR  "Whether to use the default resource folders. Otherwise set environment variables for DALI_IMAGE_DIR, DALI_SOUND_DIR, DALI_STYLE_DIR, DALI_STYLE_IMAGE_DIR and DALI_DATA_READ_ONLY_DIR" ON)
 OPTION(BUILD_SCENE3D             "Whether to build dali-scene3d." ON)
+OPTION(BUILD_PHYSICS             "Whether to build dali-physics." ON)
 
 IF( ENABLE_PKG_CONFIGURE )
   FIND_PACKAGE( PkgConfig REQUIRED )
@@ -218,19 +219,7 @@ ELSE()
   # Set up compiler flags and warnings
   ADD_COMPILE_OPTIONS( -Wno-ignored-qualifiers )
 
-  # TODO: Clang is a lot more strict with warnings, we should address
-  # those issues at some point.
-  # Matches "Clang" or "AppleClang"
-  IF( NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
-    ADD_COMPILE_OPTIONS( -Werror )
-  ENDIF()
-
-  ADD_COMPILE_OPTIONS( -Wall -Wno-unused-parameter -Wno-float-equal )
   ADD_COMPILE_OPTIONS( -Wall -Wno-unused-parameter -Wno-float-equal )
-  CHECK_CXX_COMPILER_FLAG(-Wno-class-memaccess HAVE_NO_CLASS_MEMACCESS)
-  IF (HAVE_NO_CLASS_MEMACCESS)
-    ADD_COMPILE_OPTIONS( -Wno-class-memaccess )
-  ENDIF()
 
   IF( ENABLE_COVERAGE OR "$ENV{CXXFLAGS}" MATCHES --coverage )
     ADD_COMPILE_OPTIONS( --coverage )
@@ -371,6 +360,23 @@ IF ( WIN32 )
 ENDIF()
 
 ADD_LIBRARY( ${name} ${LIBTYPE} ${SOURCES} )
+
+SET(CUSTOM_COMPILE_OPTIONS "")
+
+# TODO: Clang is a lot more strict with warnings, we should address
+# those issues at some point.
+# Matches "Clang" or "AppleClang"
+IF( NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
+  SET(CUSTOM_COMPILE_OPTIONS ${MY_COMPILE_OPTIONS} -Werror)
+ENDIF()
+
+CHECK_CXX_COMPILER_FLAG(-Wno-class-memaccess HAVE_NO_CLASS_MEMACCESS)
+IF (HAVE_NO_CLASS_MEMACCESS)
+  SET(CUSTOM_COMPILE_OPTIONS ${MY_COMPILE_OPTIONS} -Wno-class-memaccess)
+ENDIF()
+
+target_compile_options(${name} PRIVATE ${CUSTOM_COMPILE_OPTIONS})
+
 TARGET_LINK_LIBRARIES( ${name}
   ${DALICORE_LDFLAGS}
   ${DALIADAPTOR_LDFLAGS}
@@ -560,6 +566,9 @@ IF ( BUILD_SCENE3D )
   ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/dali-scene3d )
 ENDIF()
 
+IF ( BUILD_PHYSICS )
+  ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/dali-physics )
+ENDIF()
 
 # Build documentation if doxygen tool is available
 SET( doxygenEnabled OFF )
@@ -644,6 +653,7 @@ MESSAGE( STATUS "Vector Based Text Rendering:   " ${ENABLE_VECTOR_BASED_TEXT_REN
 MESSAGE( STATUS "Enable link test:              " ${ENABLE_LINK_TEST} )
 MESSAGE( STATUS "Configure automated tests:     " ${CONFIGURE_AUTOMATED_TESTS} )
 MESSAGE( STATUS "Build Dali Scene3D:            " ${BUILD_SCENE3D} )
+MESSAGE( STATUS "Build Dali Physics:            " ${BUILD_PHYSICS} )
 MESSAGE( STATUS "CXXFLAGS:                      " ${CMAKE_CXX_FLAGS} )
 MESSAGE( STATUS "LDFLAGS:                       " ${CMAKE_SHARED_LINKER_FLAGS_INIT}${CMAKE_SHARED_LINKER_FLAGS} )
 
diff --git a/build/tizen/dali-physics/CMakeLists.txt b/build/tizen/dali-physics/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f835962
--- /dev/null
@@ -0,0 +1,83 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 3.8.2)
+set(name "dali2-physics")
+
+project(${name} CXX)
+
+set(${name}_VERSION_MAJOR 1)
+set(${name}_VERSION_MINOR 0)
+set(${name}_VERSION_PATCH 0)
+set(${name}_VERSION ${${name}_VERSION_MAJOR}.${${name}_VERSION_MINOR}.${${name}_VERSION_PATCH} )
+
+SET(DALI_SCENE3D_VERSION ${${name}_VERSION} )
+
+if(CMAKE_BUILD_TYPE MATCHES Debug)
+    add_definitions("-DDEBUG_ENABLED")
+endif()
+
+add_definitions("-DBUILDING_DALI_PHYSICS")
+
+foreach(flag ${PKGS_CFLAGS})
+    set(extra_flags "${extra_flags} ${flag}")
+endforeach(flag)
+
+set(prj_cxx_std c++17)
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+    set(extra_flags "${extra_flags} -fPIC -std=${prj_cxx_std}")
+elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    set(extra_flags "${extra_flags} -fPIC -std=${prj_cxx_std}")
+elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
+    set(extra_flags "${extra_flags} /std:${prj_cxx_std} /vmg /D_USE_MATH_DEFINES /D_CRT_SECURE_NO_WARNINGS /MP /GS /Oi /GL /EHsc")
+endif()
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${extra_flags}")
+
+set(prefix ${CMAKE_INSTALL_PREFIX})
+
+set(repo_root_dir "${CMAKE_CURRENT_LIST_DIR}/../../../")
+set(physics_dir "${repo_root_dir}/dali-physics")
+
+option(ENABLE_PKG_CONFIGURE "Use pkgconfig" ON)
+option(ENABLE_COVERAGE "Coverage" OFF)
+
+if (ENABLE_PKG_CONFIGURE)
+    find_package(PkgConfig REQUIRED)
+
+    pkg_check_modules(DALICORE REQUIRED dali2-core)
+    pkg_check_modules(DALIADAPTOR REQUIRED dali2-adaptor)
+
+    # Configure the pkg-config file
+    # Requires the following variables to be setup:
+    # @PREFIX@ @EXEC_PREFIX@ @DALI_VERSION@ @LIB_DIR@ @DEV_INCLUDE_PATH@
+    set( LIB_DIR $ENV{libdir} )
+    if( NOT LIB_DIR )
+        set( LIB_DIR ${CMAKE_INSTALL_LIBDIR} )
+    endif()
+    if( NOT LIB_DIR )
+        set( LIB_DIR ${prefix}/lib )
+    endif()
+
+    set(PREFIX ${prefix})
+    set(EXEC_PREFIX ${CMAKE_INSTALL_PREFIX})
+    set(DEV_INCLUDE_PATH ${INCLUDE_DIR})
+
+    set(core_pkg_cfg_file_2d dali2-physics-2d.pc)
+    configure_file(${CMAKE_CURRENT_LIST_DIR}/${core_pkg_cfg_file_2d}.in ${core_pkg_cfg_file_2d} @ONLY)
+
+    set(core_pkg_cfg_file_3d dali2-physics-3d.pc)
+    configure_file(${CMAKE_CURRENT_LIST_DIR}/${core_pkg_cfg_file_3d}.in ${core_pkg_cfg_file_3d} @ONLY)
+endif()
+
+add_subdirectory("${physics_dir}/third-party/chipmunk2d" chipmunk2d)
+add_subdirectory("${physics_dir}/third-party/bullet3" bullet3)
+
+if (ENABLE_PKG_CONFIGURE)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${core_pkg_cfg_file_2d} ${CMAKE_CURRENT_BINARY_DIR}/${core_pkg_cfg_file_3d}
+        DESTINATION ${LIB_DIR}/pkgconfig
+    )
+endif()
+
+
+
+
+
+
diff --git a/build/tizen/dali-physics/dali2-physics-2d.pc.in b/build/tizen/dali-physics/dali2-physics-2d.pc.in
new file mode 100644 (file)
index 0000000..75f9216
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+apiversion=@DALI_PHYSICS_2D_VERSION@
+libdir=@LIB_DIR@
+includedir=@DEV_INCLUDE_PATH@
+
+Name: DALi Engine Physics Library
+Description: Dali Physics 2D library
+Version: ${apiversion}
+Requires: chipmunk2d
+Libs: -L${libdir}
+Cflags: -I${includedir}
diff --git a/build/tizen/dali-physics/dali2-physics-3d.pc.in b/build/tizen/dali-physics/dali2-physics-3d.pc.in
new file mode 100644 (file)
index 0000000..739026b
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+apiversion=@DALI_PHYSICS_3D_VERSION@
+libdir=@LIB_DIR@
+includedir=@DEV_INCLUDE_PATH@
+
+Name: DALi Engine Physics Library
+Description: Dali Physics 3D library
+Version: ${apiversion}
+Requires: bullet3
+Libs: -L${libdir}
+Cflags: -I${includedir}
diff --git a/dali-physics-2d.manifest b/dali-physics-2d.manifest
new file mode 100644 (file)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
diff --git a/dali-physics-2d.manifest-smack b/dali-physics-2d.manifest-smack
new file mode 100644 (file)
index 0000000..08561d6
--- /dev/null
@@ -0,0 +1,8 @@
+<manifest>
+       <assign>
+               <filesystem path="/usr/lib/*" label="_" />
+       </assign>
+       <request>
+               <domain name="dali"/>
+       </request>
+</manifest>
diff --git a/dali-physics-3d.manifest b/dali-physics-3d.manifest
new file mode 100644 (file)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
diff --git a/dali-physics-3d.manifest-smack b/dali-physics-3d.manifest-smack
new file mode 100644 (file)
index 0000000..08561d6
--- /dev/null
@@ -0,0 +1,8 @@
+<manifest>
+       <assign>
+               <filesystem path="/usr/lib/*" label="_" />
+       </assign>
+       <request>
+               <domain name="dali"/>
+       </request>
+</manifest>
diff --git a/dali-physics/third-party/.clang-format b/dali-physics/third-party/.clang-format
new file mode 100644 (file)
index 0000000..297ddc2
--- /dev/null
@@ -0,0 +1,5 @@
+---
+Language:        Cpp
+DisableFormat: true
+SortIncludes: false
+...
diff --git a/dali-physics/third-party/bullet3/.ci/docker/env.list b/dali-physics/third-party/bullet3/.ci/docker/env.list
new file mode 100644 (file)
index 0000000..77dcd5b
--- /dev/null
@@ -0,0 +1,7 @@
+TRAVIS_OS_NAME
+TRAVIS_PULL_REQUEST
+
+BUILD_NAME
+CC
+CXX
+SUDO
diff --git a/dali-physics/third-party/bullet3/.ci/docker/ubuntu-bionic b/dali-physics/third-party/bullet3/.ci/docker/ubuntu-bionic
new file mode 100644 (file)
index 0000000..9b389a4
--- /dev/null
@@ -0,0 +1,19 @@
+FROM ubuntu:bionic
+
+RUN apt-get update -qq
+RUN apt-get install -y \
+    build-essential  \
+    clang \
+    cmake \
+    curl \
+    git \
+    libgl-dev \
+    libglu-dev \
+    libpython3-dev \
+    lsb-release \
+    pkg-config \
+    python3 \
+    python3-dev \
+    python3-distutils \
+    software-properties-common \
+    sudo
diff --git a/dali-physics/third-party/bullet3/.ci/docker/ubuntu-xenial b/dali-physics/third-party/bullet3/.ci/docker/ubuntu-xenial
new file mode 100644 (file)
index 0000000..bce1f2b
--- /dev/null
@@ -0,0 +1,18 @@
+FROM ubuntu:xenial
+
+RUN apt-get update -qq
+RUN apt-get install -y \
+    build-essential  \
+    clang \
+    cmake \
+    curl \
+    git \
+    libgl-dev \
+    libglu-dev \
+    libpython3-dev \
+    lsb-release \
+    pkg-config \
+    python3 \
+    python3-dev \
+    software-properties-common \
+    sudo
diff --git a/dali-physics/third-party/bullet3/.ci/script.sh b/dali-physics/third-party/bullet3/.ci/script.sh
new file mode 100755 (executable)
index 0000000..66b814e
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+set -ex
+
+echo "CXX="$CXX
+echo "CC="$CC
+if [[ "$TRAVIS_OS_NAME" == "linux" && "$CXX" = "g++" ]]; then
+  $SUDO apt-get update
+  $SUDO apt-get install -y python3
+  $SUDO apt-get install -y python3-pip
+  $SUDO apt-get install python3-dev
+  $SUDO pip3 install -U wheel
+  $SUDO pip3 install -U setuptools
+  python3 setup.py install --user
+  python3 examples/pybullet/unittests/unittests.py --verbose
+  python3 examples/pybullet/unittests/userDataTest.py --verbose
+  python3 examples/pybullet/unittests/saveRestoreStateTest.py --verbose
+fi
+cmake . -DBUILD_PYBULLET=ON -G"Unix Makefiles" #-DCMAKE_CXX_FLAGS=-Werror
+make -j8
+ctest -j8 --output-on-failure
+
+# Build again with double precision
+cmake . -G "Unix Makefiles" -DUSE_DOUBLE_PRECISION=ON #-DCMAKE_CXX_FLAGS=-Werror
+make -j8
+ctest -j8 --output-on-failure
+
+# Build again with shared libraries
+cmake . -G "Unix Makefiles" -DBUILD_SHARED_LIBS=ON
+make -j8
+ctest -j8 --output-on-failure
+$SUDO make install
diff --git a/dali-physics/third-party/bullet3/.github/workflows/cmake.yml b/dali-physics/third-party/bullet3/.github/workflows/cmake.yml
new file mode 100644 (file)
index 0000000..e282e38
--- /dev/null
@@ -0,0 +1,38 @@
+name: CMake
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+
+env:
+  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
+  BUILD_TYPE: Release
+
+jobs:
+  build:
+    # The CMake configure and build commands are platform agnostic and should work equally
+    # well on Windows or Mac.  You can convert this to a matrix build if you need
+    # cross-platform coverage.
+    # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+
+    - name: Configure CMake
+      # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
+      # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
+      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
+
+    - name: Build
+      # Build your program with the given configuration
+      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
+
+    - name: Test
+      working-directory: ${{github.workspace}}/build
+      # Execute tests defined by the CMake configuration.  
+      # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
+      run: ctest -C ${{env.BUILD_TYPE}}
+      
diff --git a/dali-physics/third-party/bullet3/.gitignore b/dali-physics/third-party/bullet3/.gitignore
new file mode 100644 (file)
index 0000000..baee182
--- /dev/null
@@ -0,0 +1,42 @@
+/bin
+/build3/gmake
+/build3/vs2010
+/build_cmake/
+
+*.pyc
+
+# Python
+__pycache__/
+*.py[cod]
+
+# Pip
+pip-selfcheck.json
+*.whl
+*.egg
+*.egg-info
+
+# Setuptools
+/build
+/dist
+*.eggs
+
+# CMake
+CMakeFiles/
+CMakeCache.txt
+cmake_install.cmake
+CTestTestFile.cmake
+
+# Visual Studio build files
+*.vcxproj
+*.vcxproj.filters
+*.sln
+
+# Apple Finder metadata
+*.DS_Store
+
+# vim temp files
+*.swp
+
+.vscode/
+.idea/
+cmake-build-debug/
diff --git a/dali-physics/third-party/bullet3/.style.yapf b/dali-physics/third-party/bullet3/.style.yapf
new file mode 100644 (file)
index 0000000..5e7043e
--- /dev/null
@@ -0,0 +1,5 @@
+[style]
+based_on_style = google
+column_limit = 99
+indent_width = 2
+
diff --git a/dali-physics/third-party/bullet3/AUTHORS.txt b/dali-physics/third-party/bullet3/AUTHORS.txt
new file mode 100644 (file)
index 0000000..1bff632
--- /dev/null
@@ -0,0 +1,45 @@
+Bullet Physics is created by Erwin Coumans with contributions from the following authors / copyright holders:
+
+AMD
+Apple
+Yunfei Bai
+Steve Baker
+Gino van den Bergen
+Jeff Bingham
+Nicola Candussi
+Erin Catto
+Lawrence Chai
+Erwin Coumans
+Disney Animation
+Benjamin Ellenberger
+Christer Ericson
+Google
+Dirk Gregorius
+Marcus Hennix
+Jasmine Hsu
+MBSim Development Team
+Takahiro Harada
+Simon Hobbs
+John Hsu
+Ole Kniemeyer
+Jay Lee
+Francisco Leon
+lunkhound
+Vsevolod Klementjev
+Phil Knight
+John McCutchan
+Steven Peters
+Roman Ponomarev
+Nathanael Presson
+Gabor PUHR
+Arthur Shek
+Russel Smith
+Sony
+Jakub Stephien
+Marten Svanfeldt
+Jie Tan
+Pierre Terdiman
+Steven Thompson
+Tamas Umenhoffer
+
+If your name is missing, please send an email to erwin.coumans@gmail.com or file an issue at http://github.com/bulletphysics/bullet3
diff --git a/dali-physics/third-party/bullet3/BulletConfig.cmake.in b/dali-physics/third-party/bullet3/BulletConfig.cmake.in
new file mode 100644 (file)
index 0000000..f5dc7bd
--- /dev/null
@@ -0,0 +1,25 @@
+#                                               -*- cmake -*-
+#
+#  BulletConfig.cmake(.in)
+#
+
+# Use the following variables to compile and link against Bullet:
+#  BULLET_FOUND              - True if Bullet was found on your system
+#  BULLET_USE_FILE           - The file making Bullet usable
+#  BULLET_DEFINITIONS        - Definitions needed to build with Bullet
+#  BULLET_INCLUDE_DIR        - Directory where Bullet-C-Api.h can be found
+#  BULLET_INCLUDE_DIRS       - List of directories of Bullet and it's dependencies
+#  BULLET_LIBRARIES          - List of libraries to link against Bullet library
+#  BULLET_LIBRARY_DIRS       - List of directories containing Bullet' libraries
+#  BULLET_ROOT_DIR           - The base directory of Bullet
+#  BULLET_VERSION_STRING     - A human-readable string containing the version
+
+set ( BULLET_FOUND 1 )
+set ( BULLET_USE_FILE     "@BULLET_USE_FILE@" )
+set ( BULLET_DEFINITIONS  "@BULLET_DEFINITIONS@" )
+set ( BULLET_INCLUDE_DIR  "@INCLUDE_INSTALL_DIR@" )
+set ( BULLET_INCLUDE_DIRS "@INCLUDE_INSTALL_DIR@" )
+set ( BULLET_LIBRARIES    "@BULLET_LIBRARIES@" )
+set ( BULLET_LIBRARY_DIRS "@LIB_DESTINATION@" )
+set ( BULLET_ROOT_DIR     "@CMAKE_INSTALL_PREFIX@" )
+set ( BULLET_VERSION_STRING "@BULLET_VERSION@" )
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/CMakeLists.txt b/dali-physics/third-party/bullet3/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1f331c9
--- /dev/null
@@ -0,0 +1,142 @@
+cmake_minimum_required(VERSION 3.10.2)
+
+unset(PROJECT_IS_TOPLEVEL)
+
+project(bullet3
+    VERSION 3.2.5
+    DESCRIPTION "C++ library portion of bullet"
+    LANGUAGES CXX
+)
+
+FILE (STRINGS "VERSION" BULLET_VERSION)
+
+# PROJECT_IS_TOPLEVEL for older CMake versions
+if(NOT DEFINED PROJECT_IS_TOPLEVEL)
+    set(PROJECT_IS_TOPLEVEL OFF)
+    if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
+        set(PROJECT_IS_TOPLEVEL ON)
+    endif()
+endif()
+
+# Build options
+option(BULLET3_BUILD_SHARED "Build bullet3 as a shared library" ON)
+
+set(prefix ${CMAKE_INSTALL_PREFIX})
+option(ENABLE_PKG_CONFIGURE "Use pkgconfig" ON)
+
+ADD_DEFINITIONS(-DB3_USE_CLEW)
+
+if (WIN32)
+    ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
+    ADD_DEFINITIONS( -D_CRT_SECURE_NO_DEPRECATE )
+    ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
+endif(WIN32)
+
+# Bullet is broken into sub-"libraries"; we'll automate handling of these
+set(BULLET_SUBMODULES
+    clew
+    Bullet3Collision
+    Bullet3Common
+    Bullet3Dynamics
+    Bullet3Geometry
+    Bullet3OpenCL
+    Bullet3Serialize
+    BulletCollision
+    BulletDynamics
+    BulletInverseDynamics
+    BulletSoftBody
+    LinearMath
+)
+
+set(repo_root_dir "${CMAKE_CURRENT_LIST_DIR}/../../../")
+set(bullet_SOURCE_DIR "${repo_root_dir}/dali-physics/third-party/bullet3")
+
+set(BULLET3_SOURCES
+    "${bullet_SOURCE_DIR}/src/btBulletCollisionCommon.h"
+    "${bullet_SOURCE_DIR}/src/btBulletDynamicsCommon.h"
+)
+
+foreach(SUB ${BULLET_SUBMODULES})
+    file(GLOB_RECURSE SUBMODULE_SOURCES
+        "${bullet_SOURCE_DIR}/src/${SUB}/*.h"
+        "${bullet_SOURCE_DIR}/src/${SUB}/*.cpp"
+        "${bullet_SOURCE_DIR}/src/${SUB}/*.c"
+    )
+    list(APPEND BULLET3_SOURCES ${SUBMODULE_SOURCES})
+endforeach()
+
+# CPack support
+set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
+set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
+include(CPack)
+
+# Build the main bullet3 library
+set(BULLET3_LIBRARY_TYPE "STATIC")
+if(BULLET3_BUILD_SHARED)
+    set(BULLET3_LIBRARY_TYPE "SHARED")
+endif()
+add_library(bullet3 ${BULLET3_LIBRARY_TYPE} ${BULLET3_SOURCES})
+set_target_properties(bullet3 PROPERTIES
+    WINDOWS_EXPORT_ALL_SYMBOLS 1
+    VERSION ${PROJECT_VERSION}
+    SOVERSION ${PROJECT_VERSION}
+)
+target_include_directories(bullet3
+    SYSTEM INTERFACE
+        $<BUILD_INTERFACE:${bullet_SOURCE_DIR}/src>
+        $<INSTALL_INTERFACE:include/bullet>
+    PRIVATE
+        ${bullet_SOURCE_DIR}/src
+)
+
+# Suppress the warnings in the libbullet source code
+if(MSVC)
+    target_compile_options(bullet3 PRIVATE /w)
+else()
+    target_compile_options(bullet3 PRIVATE -w)
+endif()
+
+target_link_libraries(bullet3 ${COVERAGE})
+
+if(ENABLE_PKG_CONFIGURE)
+    find_package(PkgConfig REQUIRED)
+
+    set( LIB_DIR $ENV{libdir} )
+    if( NOT LIB_DIR )
+        set( LIB_DIR ${CMAKE_INSTALL_LIBDIR} )
+    endif()
+    if( NOT LIB_DIR )
+        set( LIB_DIR ${prefix}/lib )
+    endif()
+
+    set(bullet_pkg_cfg_file bullet3.pc)
+    configure_file(${CMAKE_CURRENT_LIST_DIR}/${bullet_pkg_cfg_file}.cmake ${bullet_pkg_cfg_file} @ONLY)
+
+    # Installation
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${bullet_pkg_cfg_file}
+        DESTINATION ${LIB_DIR}/pkgconfig
+    )
+endif(ENABLE_PKG_CONFIGURE)
+
+install(
+    TARGETS bullet3
+    DESTINATION ${LIB_DIR}
+    EXPORT Bullet3Targets
+)
+
+if(BULLET3_BUILD_SHARED AND MSVC)
+    install(FILES $<TARGET_PDB_FILE:bullet3> DESTINATION lib)
+endif()
+
+install(FILES
+    "${bullet_SOURCE_DIR}/src/btBulletCollisionCommon.h"
+    "${bullet_SOURCE_DIR}/src/btBulletDynamicsCommon.h"
+    DESTINATION "include/bullet"
+)
+foreach(SUB ${BULLET_SUBMODULES})
+    install(
+        DIRECTORY "${bullet_SOURCE_DIR}/src/${SUB}"
+        DESTINATION "include/bullet"
+        FILES_MATCHING PATTERN "*.h"
+    )
+endforeach()
diff --git a/dali-physics/third-party/bullet3/Config.cmake.in b/dali-physics/third-party/bullet3/Config.cmake.in
new file mode 100644 (file)
index 0000000..f6f434d
--- /dev/null
@@ -0,0 +1,3 @@
+@PACKAGE_INIT@
+
+include("${CMAKE_CURRENT_LIST_DIR}/Bullet3Targets.cmake")
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/LICENSE.txt b/dali-physics/third-party/bullet3/LICENSE.txt
new file mode 100644 (file)
index 0000000..319c84e
--- /dev/null
@@ -0,0 +1,15 @@
+
+The files in this repository are licensed under the zlib license, except for the files under 'Extras' and examples/ThirdPartyLibs.
+
+Bullet Continuous Collision Detection and Physics Library
+http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
diff --git a/dali-physics/third-party/bullet3/MANIFEST.in b/dali-physics/third-party/bullet3/MANIFEST.in
new file mode 100644 (file)
index 0000000..a938c6f
--- /dev/null
@@ -0,0 +1,16 @@
+include MANIFEST.in *.txt
+recursive-include examples *.h
+recursive-include examples *.hpp
+recursive-include Extras *.h
+recursive-include Extras *.hpp
+recursive-include Extras *.inl
+recursive-include src *.h
+recursive-include src *.hpp
+recursive-include src *.cpp
+recursive-include examples/pybullet/gym *.*
+include examples/ThirdPartyLibs/enet/unix.c
+include examples/OpenGLWindow/*.*
+recursive-include examples/SharedMemory/plugins *.*
+recursive-include examples/ThirdPartyLibs/glad *.*
+include examples/ThirdPartyLibs/enet/win32.c
+recursive-include examples/ThirdPartyLibs/Eigen *
diff --git a/dali-physics/third-party/bullet3/README.md b/dali-physics/third-party/bullet3/README.md
new file mode 100644 (file)
index 0000000..7a8308d
--- /dev/null
@@ -0,0 +1,8 @@
+# Bullet Physics SDK
+
+This is the Bullet Physics SDK Version 3.25.
+
+The commit used is: [2c204c4](https://github.com/bulletphysics/bullet3/commit/2c204c49e56ed15ec5fcfa71d199ab6d6570b3f5).
+
+Please refer to [Bullet Physics SDK Github](https://github.com/bulletphysics/bullet3/tree/3.25) for further information.
+
diff --git a/dali-physics/third-party/bullet3/UseBullet.cmake b/dali-physics/third-party/bullet3/UseBullet.cmake
new file mode 100644 (file)
index 0000000..5ed9487
--- /dev/null
@@ -0,0 +1,10 @@
+#                                               -*- cmake -*-
+#
+#  UseBullet.cmake
+#
+
+
+add_definitions     ( ${BULLET_DEFINITIONS} )
+include_directories ( ${BULLET_INCLUDE_DIRS} )
+link_directories    ( ${BULLET_LIBRARY_DIRS} )
+
diff --git a/dali-physics/third-party/bullet3/VERSION b/dali-physics/third-party/bullet3/VERSION
new file mode 100644 (file)
index 0000000..ed5e66e
--- /dev/null
@@ -0,0 +1 @@
+3.25
diff --git a/dali-physics/third-party/bullet3/_clang-format b/dali-physics/third-party/bullet3/_clang-format
new file mode 100644 (file)
index 0000000..43a8b1d
--- /dev/null
@@ -0,0 +1,91 @@
+---
+Language:        Cpp
+# BasedOnStyle:  Google
+AccessModifierOffset: -1
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: true
+AlignOperands:   true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: true
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:   
+  AfterClass:      false
+  AfterControlStatement: false
+  AfterEnum:       false
+  AfterFunction:   false
+  AfterNamespace:  false
+  AfterObjCDeclaration: false
+  AfterStruct:     false
+  AfterUnion:      false
+  BeforeCatch:     false
+  BeforeElse:      false
+  IndentBraces:    false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Allman
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+ColumnLimit:     0
+CommentPragmas:  '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: true
+DisableFormat:   false
+ExperimentalAutoDetectBinPacking: false
+ForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeCategories: 
+  - Regex:           '^<.*\.h>'
+    Priority:        1
+  - Regex:           '^<.*'
+    Priority:        2
+  - Regex:           '.*'
+    Priority:        3
+IndentCaseLabels: true
+IndentWidth:     4
+IndentWrappedFunctionNames: false
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd:   ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakBeforeFirstCallParameter: 1
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+ReflowComments:  false
+SortIncludes:    false
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 2
+SpacesInAngles:  false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+AccessModifierOffset: -4
+Standard:        Auto
+TabWidth:        4
+UseTab:          ForContinuationAndIndentation
+...
+
diff --git a/dali-physics/third-party/bullet3/appveyor.yml b/dali-physics/third-party/bullet3/appveyor.yml
new file mode 100644 (file)
index 0000000..42a1c32
--- /dev/null
@@ -0,0 +1,19 @@
+build:
+  project: build3/vs2010/0_Bullet3Solution.sln
+
+build_script:
+  - mkdir cm
+  - cd cm
+  - cmake .. -G"Visual Studio 14 2015 Win64"
+  - cmake --build . --target ALL_BUILD --config Release -- /maxcpucount:4 /verbosity:quiet
+
+test_script:
+  - ctest --parallel 4 --build-config Release --output-on-failure
+
+before_build:
+  - echo %CD%
+  - ps: cd build3
+  - echo %CD%
+  - premake4  vs2010
+  - ps: cd ..
+
diff --git a/dali-physics/third-party/bullet3/bullet3.pc.cmake b/dali-physics/third-party/bullet3/bullet3.pc.cmake
new file mode 100644 (file)
index 0000000..9e7a760
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+apiversion=@BULLET_VERSION@
+libdir=@LIB_DIR@
+includedir=@DEV_INCLUDE_PATH@
+
+Name: bullet
+Description: Bullet Continuous Collision Detection and Physics Library
+Version: ${apiversion}
+Requires:
+Libs: -L${libdir} -lbullet3
+Cflags: -I${includedir}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/clang-format-all.sh b/dali-physics/third-party/bullet3/clang-format-all.sh
new file mode 100755 (executable)
index 0000000..51a84cb
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# clang-format-all: a tool to run clang-format on an entire project
+# Copyright (C) 2016 Evan Klitzke <evan@eklitzke.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+function usage {
+    echo "Usage: $0 DIR..."
+    exit 1
+}
+
+if [ $# -eq 0 ]; then
+    usage
+fi
+
+# Variable that will hold the name of the clang-format command
+FMT=""
+
+# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent
+# that the version number be part of the command. We prefer clang-format if
+# that's present, otherwise we work backwards from highest version to lowest
+# version.
+for clangfmt in clang-format{,-{4,3}.{9,8,7,6,5,4,3,2,1,0}}; do
+    if which "$clangfmt" &>/dev/null; then
+        FMT="$clangfmt"
+        break
+    fi
+done
+
+# Check if we found a working clang-format
+if [ -z "$FMT" ]; then
+    echo "failed to find clang-format"
+    exit 1
+fi
+
+# Check all of the arguments first to make sure they're all directories
+for dir in "$@"; do
+    if [ ! -d "${dir}" ]; then
+        echo "${dir} is not a directory"
+        usage
+    fi
+done
+
+# Find a dominating file, starting from a given directory and going up.
+find-dominating-file() {
+    if [ -r "$1"/"$2" ]; then
+        return 0
+    fi
+    if [ "$1" = "/" ]; then
+        return 1
+    fi
+    find-dominating-file "$(realpath "$1"/..)" "$2"
+    return $?
+}
+
+# Run clang-format -i on all of the things
+for dir in "$@"; do
+    pushd "${dir}" &>/dev/null
+    if ! find-dominating-file . _clang-format; then
+        echo "Failed to find dominating .clang-format starting at $PWD"
+        continue
+    fi
+    find . \
+         \( -name '*.c' \
+         -o -name '*.cc' \
+         -o -name '*.cpp' \
+         -o -name '*.h' \
+         -o -name '*.hh' \
+         -o -name '*.hpp' \) \
+         -exec "${FMT}" -i -verbose '{}' \;
+    popd &>/dev/null
+done
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/setup.py b/dali-physics/third-party/bullet3/setup.py
new file mode 100644 (file)
index 0000000..2ef922a
--- /dev/null
@@ -0,0 +1,537 @@
+from setuptools import find_packages
+from sys import platform as _platform
+import sys
+import glob
+import os
+
+from distutils.core import setup
+from distutils.extension import Extension
+from distutils.util import get_platform
+from glob import glob
+
+# monkey-patch for parallel compilation
+import multiprocessing
+import multiprocessing.pool
+
+
+def parallelCCompile(self,
+                     sources,
+                     output_dir=None,
+                     macros=None,
+                     include_dirs=None,
+                     debug=0,
+                     extra_preargs=None,
+                     extra_postargs=None,
+                     depends=None):
+  # those lines are copied from distutils.ccompiler.CCompiler directly
+  macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
+      output_dir, macros, include_dirs, sources, depends, extra_postargs)
+  cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)
+  # parallel code
+  N = 2 * multiprocessing.cpu_count()  # number of parallel compilations
+  try:
+    # On Unix-like platforms attempt to obtain the total memory in the
+    # machine and limit the number of parallel jobs to the number of Gbs
+    # of RAM (to avoid killing smaller platforms like the Pi)
+    mem = os.sysconf('SC_PHYS_PAGES') * os.sysconf('SC_PAGE_SIZE')  # bytes
+  except (AttributeError, ValueError):
+    # Couldn't query RAM; don't limit parallelism (it's probably a well
+    # equipped Windows / Mac OS X box)
+    pass
+  else:
+    mem = max(1, int(round(mem / 1024**3)))  # convert to Gb
+    N = min(mem, N)
+
+  def _single_compile(obj):
+    try:
+      src, ext = build[obj]
+    except KeyError:
+      return
+    newcc_args = cc_args
+    if _platform == "darwin":
+      if src.endswith('.cpp'):
+        newcc_args = cc_args + ["-mmacosx-version-min=10.7", "-stdlib=libc++"]
+    self._compile(obj, src, ext, newcc_args, extra_postargs, pp_opts)
+
+  # convert to list, imap is evaluated on-demand
+  pool = multiprocessing.pool.ThreadPool(N)
+  list(pool.imap(_single_compile, objects))
+  return objects
+
+
+import distutils.ccompiler
+distutils.ccompiler.CCompiler.compile = parallelCCompile
+
+#see http://stackoverflow.com/a/8719066/295157
+import os
+
+platform = get_platform()
+print(platform)
+
+CXX_FLAGS = ''
+CXX_FLAGS += '-DGWEN_COMPILE_STATIC '
+CXX_FLAGS += '-DBT_USE_DOUBLE_PRECISION '
+CXX_FLAGS += '-DBT_ENABLE_ENET '
+CXX_FLAGS += '-DBT_ENABLE_CLSOCKET '
+CXX_FLAGS += '-DB3_DUMP_PYTHON_VERSION '
+CXX_FLAGS += '-DEGL_ADD_PYTHON_INIT '
+CXX_FLAGS += '-DB3_ENABLE_FILEIO_PLUGIN '
+CXX_FLAGS += '-DB3_USE_ZIPFILE_FILEIO '
+CXX_FLAGS += '-DBT_THREADSAFE=1 '
+CXX_FLAGS += '-DSTATIC_LINK_SPD_PLUGIN '
+CXX_FLAGS += '-DBT_ENABLE_VHACD '
+
+EGL_CXX_FLAGS = ''
+
+# libraries += [current_python]
+
+libraries = []
+include_dirs = []
+
+try:
+  import numpy
+  NP_DIRS = [numpy.get_include()]
+except:
+  print("numpy is disabled. getCameraImage maybe slower.")
+else:
+  print("numpy is enabled.")
+  CXX_FLAGS += '-DPYBULLET_USE_NUMPY '
+  for d in NP_DIRS:
+    print("numpy_include_dirs = %s" % d)
+  include_dirs += NP_DIRS
+
+sources = ["examples/pybullet/pybullet.c"]\
++["examples/ThirdPartyLibs/tinyxml2/tinyxml2.cpp"]\
++["examples/SharedMemory/plugins/stablePDPlugin/BulletConversion.cpp"]\
++["examples/SharedMemory/plugins/stablePDPlugin/KinTree.cpp"]\
++["examples/SharedMemory/plugins/stablePDPlugin/MathUtil.cpp"]\
++["examples/SharedMemory/plugins/stablePDPlugin/RBDModel.cpp"]\
++["examples/SharedMemory/plugins/stablePDPlugin/RBDUtil.cpp"]\
++["examples/SharedMemory/plugins/stablePDPlugin/Shape.cpp"]\
++["examples/SharedMemory/plugins/stablePDPlugin/SpAlg.cpp"]\
++["src/btLinearMathAll.cpp"]\
++["src/btBulletCollisionAll.cpp"]\
++["src/btBulletDynamicsAll.cpp"]\
++["examples/ExampleBrowser/InProcessExampleBrowser.cpp"]\
++["examples/TinyRenderer/geometry.cpp"]\
++["examples/TinyRenderer/model.cpp"]\
++["examples/TinyRenderer/tgaimage.cpp"]\
++["examples/TinyRenderer/our_gl.cpp"]\
++["examples/TinyRenderer/TinyRenderer.cpp"]\
++["examples/SharedMemory/plugins/pdControlPlugin/pdControlPlugin.cpp"]\
++["examples/SharedMemory/plugins/collisionFilterPlugin/collisionFilterPlugin.cpp"]\
++["examples/SharedMemory/plugins/fileIOPlugin/fileIOPlugin.cpp"]\
++["examples/SharedMemory/b3RobotSimulatorClientAPI_NoDirect.cpp"]\
++["examples/SharedMemory/IKTrajectoryHelper.cpp"]\
++["examples/SharedMemory/InProcessMemory.cpp"]\
++["examples/SharedMemory/PhysicsClient.cpp"]\
++["examples/SharedMemory/PhysicsServer.cpp"]\
++["examples/SharedMemory/GraphicsClientExample.cpp"]\
++["examples/SharedMemory/GraphicsServerExample.cpp"]\
++["examples/SharedMemory/RemoteGUIHelper.cpp"]\
++["examples/SharedMemory/RemoteGUIHelperTCP.cpp"]\
++["examples/SharedMemory/PhysicsServerExample.cpp"]\
++["examples/SharedMemory/PhysicsServerExampleBullet2.cpp"]\
++["examples/SharedMemory/SharedMemoryInProcessPhysicsC_API.cpp"]\
++["examples/SharedMemory/PhysicsServerSharedMemory.cpp"]\
++["examples/SharedMemory/PhysicsDirect.cpp"]\
++["examples/SharedMemory/PhysicsDirectC_API.cpp"]\
++["examples/SharedMemory/PhysicsServerCommandProcessor.cpp"]\
++["examples/SharedMemory/PhysicsClientSharedMemory.cpp"]\
++["examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp"]\
++["examples/SharedMemory/PhysicsClientC_API.cpp"]\
++["examples/SharedMemory/Win32SharedMemory.cpp"]\
++["examples/SharedMemory/PosixSharedMemory.cpp"]\
++["examples/SharedMemory/plugins/tinyRendererPlugin/TinyRendererVisualShapeConverter.cpp"]\
++["examples/SharedMemory/plugins/tinyRendererPlugin/tinyRendererPlugin.cpp"]\
++["examples/SharedMemory/PhysicsClientUDP.cpp"]\
++["examples/SharedMemory/PhysicsClientUDP_C_API.cpp"]\
++["examples/SharedMemory/PhysicsClientTCP.cpp"]\
++["examples/SharedMemory/PhysicsClientTCP_C_API.cpp"]\
++["examples/SharedMemory/b3PluginManager.cpp"]\
++["examples/Utils/b3ResourcePath.cpp"]\
++["examples/Utils/RobotLoggingUtil.cpp"]\
++["examples/Utils/ChromeTraceUtil.cpp"]\
++["examples/Utils/b3Clock.cpp"]\
++["examples/Utils/b3Quickprof.cpp"]\
++["examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp"]\
++["examples/ThirdPartyLibs/stb_image/stb_image.cpp"]\
++["examples/ThirdPartyLibs/stb_image/stb_image_write.cpp"]\
++["examples/ThirdPartyLibs/minizip/ioapi.c"]\
++["examples/ThirdPartyLibs/minizip/unzip.c"]\
++["examples/ThirdPartyLibs/minizip/zip.c"]\
++["examples/ThirdPartyLibs/zlib/adler32.c"]\
++["examples/ThirdPartyLibs/zlib/compress.c"]\
++["examples/ThirdPartyLibs/zlib/crc32.c"]\
++["examples/ThirdPartyLibs/zlib/deflate.c"]\
++["examples/ThirdPartyLibs/zlib/gzclose.c"]\
++["examples/ThirdPartyLibs/zlib/gzlib.c"]\
++["examples/ThirdPartyLibs/zlib/gzread.c"]\
++["examples/ThirdPartyLibs/zlib/gzwrite.c"]\
++["examples/ThirdPartyLibs/zlib/infback.c"]\
++["examples/ThirdPartyLibs/zlib/inffast.c"]\
++["examples/ThirdPartyLibs/zlib/inflate.c"]\
++["examples/ThirdPartyLibs/zlib/inftrees.c"]\
++["examples/ThirdPartyLibs/zlib/trees.c"]\
++["examples/ThirdPartyLibs/zlib/uncompr.c"]\
++["examples/ThirdPartyLibs/zlib/zutil.c"]\
++["examples/Importers/ImportColladaDemo/LoadMeshFromCollada.cpp"]\
++["examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp"]\
++["examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp"]\
++["examples/Importers/ImportMJCFDemo/BulletMJCFImporter.cpp"]\
++["examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp"]\
++["examples/Importers/ImportURDFDemo/MyMultiBodyCreator.cpp"]\
++["examples/Importers/ImportURDFDemo/URDF2Bullet.cpp"]\
++["examples/Importers/ImportURDFDemo/UrdfParser.cpp"]\
++["examples/Importers/ImportURDFDemo/urdfStringSplit.cpp"]\
++["examples/Importers/ImportMeshUtility/b3ImportMeshUtility.cpp"]\
++["examples/MultiThreading/b3PosixThreadSupport.cpp"]\
++["examples/MultiThreading/b3Win32ThreadSupport.cpp"]\
++["examples/MultiThreading/b3ThreadSupportInterface.cpp"]\
++["examples/ThirdPartyLibs/enet/callbacks.c"]\
++["examples/ThirdPartyLibs/enet/compress.c"]\
++["examples/ThirdPartyLibs/enet/host.c"]\
++["examples/ThirdPartyLibs/enet/list.c"]\
++["examples/ThirdPartyLibs/enet/packet.c"]\
++["examples/ThirdPartyLibs/enet/peer.c"]\
++["examples/ThirdPartyLibs/enet/protocol.c"]\
++["examples/ExampleBrowser/OpenGLGuiHelper.cpp"]\
++["examples/ExampleBrowser/OpenGLExampleBrowser.cpp"]\
++["examples/ExampleBrowser/CollisionShape2TriangleMesh.cpp"]\
++["examples/ExampleBrowser/GL_ShapeDrawer.cpp"]\
++["examples/OpenGLWindow/SimpleOpenGL2Renderer.cpp"]\
++["examples/OpenGLWindow/GLInstancingRenderer.cpp"]\
++["examples/OpenGLWindow/SimpleOpenGL3App.cpp"]\
++["examples/OpenGLWindow/GLPrimitiveRenderer.cpp"]\
++["examples/OpenGLWindow/TwFonts.cpp"]\
++["examples/OpenGLWindow/GLRenderToTexture.cpp"]\
++["examples/OpenGLWindow/LoadShader.cpp"]\
++["examples/OpenGLWindow/OpenSans.cpp"]\
++["examples/OpenGLWindow/SimpleCamera.cpp"]\
++["examples/OpenGLWindow/fontstash.cpp"]\
++["examples/OpenGLWindow/SimpleOpenGL2App.cpp"]\
++["examples/OpenGLWindow/opengl_fontstashcallbacks.cpp"]\
++["examples/ExampleBrowser/GwenGUISupport/GraphingTexture.cpp"]\
++["examples/ExampleBrowser/GwenGUISupport/GwenProfileWindow.cpp"]\
++["examples/ExampleBrowser/GwenGUISupport/gwenUserInterface.cpp"]\
++["examples/ExampleBrowser/GwenGUISupport/GwenParameterInterface.cpp"]\
++["examples/ExampleBrowser/GwenGUISupport/GwenTextureWindow.cpp"]\
++["src/Bullet3Common/b3AlignedAllocator.cpp"]\
++["src/Bullet3Common/b3Logging.cpp"]\
++["src/Bullet3Common/b3Vector3.cpp"]\
++["examples/ThirdPartyLibs/clsocket/src/ActiveSocket.cpp"]\
++["examples/ThirdPartyLibs/clsocket/src/PassiveSocket.cpp"]\
++["examples/ThirdPartyLibs/clsocket/src/SimpleSocket.cpp"]\
++["Extras/Serialize/BulletFileLoader/bChunk.cpp"]\
++["Extras/Serialize/BulletFileLoader/bDNA.cpp"]\
++["Extras/Serialize/BulletFileLoader/bFile.cpp"]\
++["Extras/Serialize/BulletFileLoader/btBulletFile.cpp"]\
++["Extras/Serialize/BulletWorldImporter/btMultiBodyWorldImporter.cpp"]\
++["Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.cpp"]\
++["Extras/Serialize/BulletWorldImporter/btWorldImporter.cpp"]\
++["Extras/InverseDynamics/CloneTreeCreator.cpp"]\
++["Extras/InverseDynamics/IDRandomUtil.cpp"]\
++["Extras/InverseDynamics/MultiBodyTreeDebugGraph.cpp"]\
++["Extras/InverseDynamics/User2InternalIndex.cpp"]\
++["Extras/InverseDynamics/CoilCreator.cpp"]\
++["Extras/InverseDynamics/MultiBodyNameMap.cpp"]\
++["Extras/InverseDynamics/RandomTreeCreator.cpp"]\
++["Extras/InverseDynamics/btMultiBodyTreeCreator.cpp"]\
++["Extras/InverseDynamics/DillCreator.cpp"]\
++["Extras/InverseDynamics/MultiBodyTreeCreator.cpp"]\
++["Extras/InverseDynamics/SimpleTreeCreator.cpp"]\
++["Extras/InverseDynamics/invdyn_bullet_comparison.cpp"]\
++["src/BulletSoftBody/btDefaultSoftBodySolver.cpp"]\
++["src/BulletSoftBody/btSoftBodyHelpers.cpp"]\
++["src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp"]\
++["src/BulletSoftBody/btSoftBody.cpp"]\
++["src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp"]\
++["src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp"]\
++["src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp"]\
++["src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp"]\
++["src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp"]\
++["src/BulletSoftBody/btDeformableBackwardEulerObjective.cpp"]\
++["src/BulletSoftBody/btDeformableBodySolver.cpp"]\
++["src/BulletSoftBody/btDeformableContactProjection.cpp"]\
++["src/BulletSoftBody/btDeformableContactConstraint.cpp"]\
++["src/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp"]\
++["src/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp"]\
++["src/BulletSoftBody/poly34.cpp"]\
++["src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBody.cpp"]\
++["src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodyHelpers.cpp"]\
++["src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodySolver.cpp"]\
++["src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableContactConstraint.cpp"]\
++["src/BulletInverseDynamics/IDMath.cpp"]\
++["src/BulletInverseDynamics/MultiBodyTree.cpp"]\
++["src/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp"]\
++["src/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp"]\
++["examples/ThirdPartyLibs/BussIK/Jacobian.cpp"]\
++["examples/ThirdPartyLibs/BussIK/LinearR2.cpp"]\
++["examples/ThirdPartyLibs/BussIK/LinearR3.cpp"]\
++["examples/ThirdPartyLibs/BussIK/LinearR4.cpp"]\
++["examples/ThirdPartyLibs/BussIK/MatrixRmn.cpp"]\
++["examples/ThirdPartyLibs/BussIK/Misc.cpp"]\
++["examples/ThirdPartyLibs/BussIK/Node.cpp"]\
++["examples/ThirdPartyLibs/BussIK/Tree.cpp"]\
++["examples/ThirdPartyLibs/BussIK/VectorRn.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Anim.cpp"]\
++["examples/ThirdPartyLibs/Gwen/DragAndDrop.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Hook.cpp"]\
++["examples/ThirdPartyLibs/Gwen/ToolTip.cpp"]\
++["examples/ThirdPartyLibs/Gwen/events.cpp"]\
++["examples/ThirdPartyLibs/Gwen/BaseRender.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Gwen.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Skin.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Utility.cpp"]\
++["examples/ThirdPartyLibs/Gwen/inputhandler.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Base.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Button.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Canvas.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/CheckBox.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ColorControls.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ColorPicker.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ComboBox.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/CrossSplitter.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/DockBase.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/DockedTabControl.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Dragger.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/GroupBox.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/HSVColorPicker.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/HorizontalScrollBar.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ImagePanel.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/HorizontalSlider.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Label.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/LabelClickable.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ListBox.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/MenuItem.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Menu.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/MenuStrip.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/NumericUpDown.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/PanelListPanel.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ProgressBar.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Properties.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/RadioButton.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/RadioButtonController.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ResizableControl.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Resizer.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/RichLabel.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ScrollBar.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ScrollBarBar.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ScrollBarButton.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/ScrollControl.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Slider.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/SplitterBar.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/TabButton.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/TabControl.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/TabStrip.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Text.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/TextBox.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/TextBoxNumeric.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/TreeControl.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/TreeNode.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/VerticalScrollBar.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/VerticalSlider.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/WindowControl.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Dialog/FileOpen.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Dialog/FileSave.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Controls/Dialog/Query.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Platforms/Null.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Platforms/Windows.cpp"]\
++["examples/ThirdPartyLibs/Gwen/Renderers/OpenGL_DebugFont.cpp"]\
++["Extras/VHACD/test/src/main_vhacd.cpp"] \
++["Extras/VHACD/src/VHACD.cpp"] \
++["Extras/VHACD/src/vhacdICHull.cpp"] \
++["Extras/VHACD/src/vhacdManifoldMesh.cpp"] \
++["Extras/VHACD/src/vhacdMesh.cpp"] \
++["Extras/VHACD/src/vhacdVolume.cpp"]
+
+
+egl_renderer_sources = \
+["examples/SharedMemory/plugins/eglPlugin/eglRendererVisualShapeConverter.cpp"]\
++["examples/SharedMemory/plugins/eglPlugin/eglRendererPlugin.cpp"]\
++["examples/Importers/ImportColladaDemo/LoadMeshFromCollada.cpp"]\
++["examples/Importers/ImportObjDemo/LoadMeshFromObj.cpp"]\
++["examples/Importers/ImportMeshUtility/b3ImportMeshUtility.cpp"]\
++["examples/Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp"]\
++["examples/TinyRenderer/geometry.cpp"]\
++["examples/TinyRenderer/model.cpp"]\
++["examples/TinyRenderer/tgaimage.cpp"]\
++["examples/TinyRenderer/our_gl.cpp"]\
++["examples/TinyRenderer/TinyRenderer.cpp"]\
++["examples/ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp"]\
++["examples/ThirdPartyLibs/stb_image/stb_image.cpp"]\
++["examples/ThirdPartyLibs/stb_image/stb_image_write.cpp"]\
++["examples/ThirdPartyLibs/tinyxml2/tinyxml2.cpp"]\
++["examples/OpenGLWindow/SimpleCamera.cpp"]\
++["examples/Utils/b3Clock.cpp"]\
++["examples/Utils/b3ResourcePath.cpp"]\
++["src/BulletCollision/CollisionShapes/btShapeHull.cpp"]\
++["src/BulletCollision/CollisionShapes/btConvexHullShape.cpp"]\
++["src/BulletCollision/CollisionShapes/btBoxShape.cpp"]\
++["src/BulletCollision/CollisionShapes/btSphereShape.cpp"]\
++["src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp"]\
++["src/BulletCollision/CollisionShapes/btConvexShape.cpp"]\
++["src/BulletCollision/CollisionShapes/btCollisionShape.cpp"]\
++["src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp"]\
++["src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp"]\
++["src/Bullet3Common/b3Logging.cpp"]\
++["src/LinearMath/btAlignedAllocator.cpp"]\
++["src/LinearMath/btConvexHull.cpp"]\
++["src/LinearMath/btConvexHullComputer.cpp"] \
++["src/LinearMath/btGeometryUtil.cpp"]\
++["src/LinearMath/btQuickprof.cpp"] \
++["src/LinearMath/btThreads.cpp"] \
++["src/Bullet3Common/b3AlignedAllocator.cpp"] \
++["examples/ThirdPartyLibs/glad/gl.c"]\
++["examples/OpenGLWindow/GLInstancingRenderer.cpp"]\
++["examples/OpenGLWindow/GLRenderToTexture.cpp"] \
++["examples/OpenGLWindow/LoadShader.cpp"]
+
+if 'BT_USE_EGL' in CXX_FLAGS:
+  sources += ['examples/ThirdPartyLibs/glad/egl.c']
+  sources += ['examples/OpenGLWindow/EGLOpenGLWindow.cpp']
+
+if _platform == "linux" or _platform == "linux2":
+  libraries = ['dl', 'pthread']
+  CXX_FLAGS += '-D_LINUX '
+  CXX_FLAGS += '-DGLEW_STATIC '
+  CXX_FLAGS += '-DGLEW_INIT_OPENGL11_FUNCTIONS=1 '
+  CXX_FLAGS += '-DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1 '
+  CXX_FLAGS += '-DDYNAMIC_LOAD_X11_FUNCTIONS '
+  CXX_FLAGS += '-DHAS_SOCKLEN_T '
+  CXX_FLAGS += '-fno-inline-functions-called-once '
+  CXX_FLAGS += '-fvisibility=hidden '
+  CXX_FLAGS += '-fvisibility-inlines-hidden '
+  EGL_CXX_FLAGS += '-DBT_USE_EGL '
+  EGL_CXX_FLAGS += '-fPIC '  # for plugins
+
+  sources = sources + ["examples/ThirdPartyLibs/enet/unix.c"]\
+  +["examples/OpenGLWindow/X11OpenGLWindow.cpp"]\
+  +["examples/ThirdPartyLibs/glad/gl.c"]\
+  +["examples/ThirdPartyLibs/glad/glx.c"]
+  include_dirs += ["examples/ThirdPartyLibs/optionalX11"]
+
+  if 'BT_USE_EGL' in EGL_CXX_FLAGS:
+    egl_renderer_sources = egl_renderer_sources\
+    +["examples/OpenGLWindow/EGLOpenGLWindow.cpp"]\
+    +['examples/ThirdPartyLibs/glad/egl.c']
+  else:
+    egl_renderer_sources = egl_renderer_sources\
+    +["examples/OpenGLWindow/X11OpenGLWindow.cpp"]\
+    +["examples/ThirdPartyLibs/glad/glx.c"]
+
+elif _platform == "win32":
+  print("win32!")
+  libraries = ['Ws2_32', 'Winmm', 'User32', 'Opengl32', 'kernel32', 'glu32', 'Gdi32', 'Comdlg32']
+  CXX_FLAGS += '-DWIN32 '
+  CXX_FLAGS += '-DGLEW_STATIC '
+  sources = sources + ["examples/ThirdPartyLibs/enet/win32.c"]\
+  +["examples/OpenGLWindow/Win32Window.cpp"]\
+  +["examples/OpenGLWindow/Win32OpenGLWindow.cpp"]\
+  +["examples/ThirdPartyLibs/glad/gl.c"]
+elif _platform == "darwin":
+  print("darwin!")
+  os.environ['LDFLAGS'] = '-framework Cocoa -mmacosx-version-min=10.7 -stdlib=libc++ -framework OpenGL'
+  CXX_FLAGS += '-DB3_NO_PYTHON_FRAMEWORK '
+  CXX_FLAGS += '-DHAS_SOCKLEN_T '
+  CXX_FLAGS += '-D_DARWIN '
+  #    CXX_FLAGS += '-framework Cocoa '
+  sources = sources + ["examples/ThirdPartyLibs/enet/unix.c"]\
+  +["examples/OpenGLWindow/MacOpenGLWindow.cpp"]\
+  +["examples/ThirdPartyLibs/glad/gl.c"]\
+  +["examples/OpenGLWindow/MacOpenGLWindowObjC.m"]
+else:
+  print("bsd!")
+  libraries = ['GL', 'GLEW', 'pthread']
+  os.environ['LDFLAGS'] = '-L/usr/X11R6/lib'
+  CXX_FLAGS += '-D_BSD '
+  CXX_FLAGS += '-I/usr/X11R6/include '
+  CXX_FLAGS += '-DHAS_SOCKLEN_T '
+  CXX_FLAGS += '-fno-inline-functions-called-once'
+  sources = ["examples/ThirdPartyLibs/enet/unix.c"]\
+  +["examples/OpenGLWindow/X11OpenGLWindow.cpp"]\
+  +["examples/ThirdPartyLibs/glad/gl.c"]\
+  + sources
+
+setup_py_dir = os.path.dirname(os.path.realpath(__file__))
+
+need_files = []
+datadir = "examples/pybullet/gym/pybullet_data"
+
+hh = setup_py_dir + "/" + datadir
+
+for root, dirs, files in os.walk(hh):
+  for fn in files:
+    ext = os.path.splitext(fn)[1][1:]
+    if ext and ext in 'yaml index meta data-00000-of-00001 png gif jpg urdf sdf obj txt mtl dae off stl STL xml gin npy '.split(
+    ):
+      fn = root + "/" + fn
+      need_files.append(fn[1 + len(hh):])
+
+print("found resource files: %i" % len(need_files))
+for n in need_files:
+  print("-- %s" % n)
+print("packages")
+print(find_packages('examples/pybullet/gym'))
+print("-----")
+
+extensions = []
+
+pybullet_ext = Extension(
+    "pybullet",
+    sources=sources,
+    libraries=libraries,
+    extra_compile_args=CXX_FLAGS.split(),
+    include_dirs=include_dirs + [
+        "src", "examples/ThirdPartyLibs", "examples/ThirdPartyLibs/glad",
+        "examples/ThirdPartyLibs/enet/include", "examples/ThirdPartyLibs/clsocket/src",
+        "Extras/VHACD/inc", "Extras/VHACD/public",
+    ])
+extensions.append(pybullet_ext)
+
+if 'BT_USE_EGL' in EGL_CXX_FLAGS:
+
+  eglRender = Extension(
+      "eglRenderer",
+      sources=egl_renderer_sources,
+      libraries=libraries,
+      extra_compile_args=(CXX_FLAGS + EGL_CXX_FLAGS).split(),
+      include_dirs=include_dirs + [
+          "src", "examples", "examples/ThirdPartyLibs", "examples/ThirdPartyLibs/glad",
+          "examples/ThirdPartyLibs/enet/include", "examples/ThirdPartyLibs/clsocket/src"
+      ])
+
+  extensions.append(eglRender)
+
+setup(
+    name='pybullet',
+    version='3.2.5',
+    description=
+    'Official Python Interface for the Bullet Physics SDK specialized for Robotics Simulation and Reinforcement Learning',
+    long_description=
+    'pybullet is an easy to use Python module for physics simulation, robotics and deep reinforcement learning based on the Bullet Physics SDK. With pybullet you can load articulated bodies from URDF, SDF and other file formats. pybullet provides forward dynamics simulation, inverse dynamics computation, forward and inverse kinematics and collision detection and ray intersection queries. Aside from physics simulation, pybullet supports to rendering, with a CPU renderer and OpenGL visualization and support for virtual reality headsets.',
+    url='https://github.com/bulletphysics/bullet3',
+    author='Erwin Coumans, Yunfei Bai, Jasmine Hsu',
+    author_email='erwincoumans@google.com',
+    license='zlib',
+    platforms='any',
+    keywords=[
+        'game development', 'virtual reality', 'physics simulation', 'robotics',
+        'collision detection', 'opengl'
+    ],
+    ext_modules=extensions,
+    classifiers=[
+        'Development Status :: 5 - Production/Stable',
+        'License :: OSI Approved :: zlib/libpng License',
+        'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX :: Linux',
+        'Operating System :: MacOS', 'Intended Audience :: Science/Research',
+        "Programming Language :: Python", 'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5',
+        'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7',
+        'Programming Language :: Python :: 3.8', 'Topic :: Games/Entertainment :: Simulation',
+        'Topic :: Scientific/Engineering :: Artificial Intelligence',
+        'Framework :: Robot Framework'
+    ],
+    package_dir={'': 'examples/pybullet/gym'},
+    packages=[x for x in find_packages('examples/pybullet/gym')],
+    package_data={'pybullet_data': need_files})
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h
new file mode 100644 (file)
index 0000000..bec0800
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_BROADPHASE_CALLBACK_H
+#define B3_BROADPHASE_CALLBACK_H
+
+#include "Bullet3Common/b3Vector3.h"
+struct b3BroadphaseProxy;
+
+struct b3BroadphaseAabbCallback
+{
+       virtual ~b3BroadphaseAabbCallback() {}
+       virtual bool process(const b3BroadphaseProxy* proxy) = 0;
+};
+
+struct b3BroadphaseRayCallback : public b3BroadphaseAabbCallback
+{
+       ///added some cached data to accelerate ray-AABB tests
+       b3Vector3 m_rayDirectionInverse;
+       unsigned int m_signs[3];
+       b3Scalar m_lambda_max;
+
+       virtual ~b3BroadphaseRayCallback() {}
+};
+
+#endif  //B3_BROADPHASE_CALLBACK_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp b/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp
new file mode 100644 (file)
index 0000000..a0dc1da
--- /dev/null
@@ -0,0 +1,1352 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///b3DynamicBvh implementation by Nathanael Presson
+
+#include "b3DynamicBvh.h"
+
+//
+typedef b3AlignedObjectArray<b3DbvtNode*> b3NodeArray;
+typedef b3AlignedObjectArray<const b3DbvtNode*> b3ConstNodeArray;
+
+//
+struct b3DbvtNodeEnumerator : b3DynamicBvh::ICollide
+{
+       b3ConstNodeArray nodes;
+       void Process(const b3DbvtNode* n) { nodes.push_back(n); }
+};
+
+//
+static B3_DBVT_INLINE int b3IndexOf(const b3DbvtNode* node)
+{
+       return (node->parent->childs[1] == node);
+}
+
+//
+static B3_DBVT_INLINE b3DbvtVolume b3Merge(const b3DbvtVolume& a,
+                                                                                  const b3DbvtVolume& b)
+{
+#if (B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE)
+       B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtAabbMm)]);
+       b3DbvtVolume& res = *(b3DbvtVolume*)locals;
+#else
+       b3DbvtVolume res;
+#endif
+       b3Merge(a, b, res);
+       return (res);
+}
+
+// volume+edge lengths
+static B3_DBVT_INLINE b3Scalar b3Size(const b3DbvtVolume& a)
+{
+       const b3Vector3 edges = a.Lengths();
+       return (edges.x * edges.y * edges.z +
+                       edges.x + edges.y + edges.z);
+}
+
+//
+static void b3GetMaxDepth(const b3DbvtNode* node, int depth, int& maxdepth)
+{
+       if (node->isinternal())
+       {
+               b3GetMaxDepth(node->childs[0], depth + 1, maxdepth);
+               b3GetMaxDepth(node->childs[1], depth + 1, maxdepth);
+       }
+       else
+               maxdepth = b3Max(maxdepth, depth);
+}
+
+//
+static B3_DBVT_INLINE void b3DeleteNode(b3DynamicBvh* pdbvt,
+                                                                               b3DbvtNode* node)
+{
+       b3AlignedFree(pdbvt->m_free);
+       pdbvt->m_free = node;
+}
+
+//
+static void b3RecurseDeleteNode(b3DynamicBvh* pdbvt,
+                                                               b3DbvtNode* node)
+{
+       if (!node->isleaf())
+       {
+               b3RecurseDeleteNode(pdbvt, node->childs[0]);
+               b3RecurseDeleteNode(pdbvt, node->childs[1]);
+       }
+       if (node == pdbvt->m_root) pdbvt->m_root = 0;
+       b3DeleteNode(pdbvt, node);
+}
+
+//
+static B3_DBVT_INLINE b3DbvtNode* b3CreateNode(b3DynamicBvh* pdbvt,
+                                                                                          b3DbvtNode* parent,
+                                                                                          void* data)
+{
+       b3DbvtNode* node;
+       if (pdbvt->m_free)
+       {
+               node = pdbvt->m_free;
+               pdbvt->m_free = 0;
+       }
+       else
+       {
+               node = new (b3AlignedAlloc(sizeof(b3DbvtNode), 16)) b3DbvtNode();
+       }
+       node->parent = parent;
+       node->data = data;
+       node->childs[1] = 0;
+       return (node);
+}
+
+//
+static B3_DBVT_INLINE b3DbvtNode* b3CreateNode(b3DynamicBvh* pdbvt,
+                                                                                          b3DbvtNode* parent,
+                                                                                          const b3DbvtVolume& volume,
+                                                                                          void* data)
+{
+       b3DbvtNode* node = b3CreateNode(pdbvt, parent, data);
+       node->volume = volume;
+       return (node);
+}
+
+//
+static B3_DBVT_INLINE b3DbvtNode* b3CreateNode(b3DynamicBvh* pdbvt,
+                                                                                          b3DbvtNode* parent,
+                                                                                          const b3DbvtVolume& volume0,
+                                                                                          const b3DbvtVolume& volume1,
+                                                                                          void* data)
+{
+       b3DbvtNode* node = b3CreateNode(pdbvt, parent, data);
+       b3Merge(volume0, volume1, node->volume);
+       return (node);
+}
+
+//
+static void b3InsertLeaf(b3DynamicBvh* pdbvt,
+                                                b3DbvtNode* root,
+                                                b3DbvtNode* leaf)
+{
+       if (!pdbvt->m_root)
+       {
+               pdbvt->m_root = leaf;
+               leaf->parent = 0;
+       }
+       else
+       {
+               if (!root->isleaf())
+               {
+                       do
+                       {
+                               root = root->childs[b3Select(leaf->volume,
+                                                                                        root->childs[0]->volume,
+                                                                                        root->childs[1]->volume)];
+                       } while (!root->isleaf());
+               }
+               b3DbvtNode* prev = root->parent;
+               b3DbvtNode* node = b3CreateNode(pdbvt, prev, leaf->volume, root->volume, 0);
+               if (prev)
+               {
+                       prev->childs[b3IndexOf(root)] = node;
+                       node->childs[0] = root;
+                       root->parent = node;
+                       node->childs[1] = leaf;
+                       leaf->parent = node;
+                       do
+                       {
+                               if (!prev->volume.Contain(node->volume))
+                                       b3Merge(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 b3DbvtNode* b3RemoveLeaf(b3DynamicBvh* pdbvt,
+                                                               b3DbvtNode* leaf)
+{
+       if (leaf == pdbvt->m_root)
+       {
+               pdbvt->m_root = 0;
+               return (0);
+       }
+       else
+       {
+               b3DbvtNode* parent = leaf->parent;
+               b3DbvtNode* prev = parent->parent;
+               b3DbvtNode* sibling = parent->childs[1 - b3IndexOf(leaf)];
+               if (prev)
+               {
+                       prev->childs[b3IndexOf(parent)] = sibling;
+                       sibling->parent = prev;
+                       b3DeleteNode(pdbvt, parent);
+                       while (prev)
+                       {
+                               const b3DbvtVolume pb = prev->volume;
+                               b3Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
+                               if (b3NotEqual(pb, prev->volume))
+                               {
+                                       prev = prev->parent;
+                               }
+                               else
+                                       break;
+                       }
+                       return (prev ? prev : pdbvt->m_root);
+               }
+               else
+               {
+                       pdbvt->m_root = sibling;
+                       sibling->parent = 0;
+                       b3DeleteNode(pdbvt, parent);
+                       return (pdbvt->m_root);
+               }
+       }
+}
+
+//
+static void b3FetchLeaves(b3DynamicBvh* pdbvt,
+                                                 b3DbvtNode* root,
+                                                 b3NodeArray& leaves,
+                                                 int depth = -1)
+{
+       if (root->isinternal() && depth)
+       {
+               b3FetchLeaves(pdbvt, root->childs[0], leaves, depth - 1);
+               b3FetchLeaves(pdbvt, root->childs[1], leaves, depth - 1);
+               b3DeleteNode(pdbvt, root);
+       }
+       else
+       {
+               leaves.push_back(root);
+       }
+}
+
+static bool b3LeftOfAxis(const b3DbvtNode* node,
+                                                const b3Vector3& org,
+                                                const b3Vector3& axis)
+{
+       return b3Dot(axis, node->volume.Center() - org) <= 0;
+}
+
+// Partitions leaves such that leaves[0, n) are on the
+// left of axis, and leaves[n, count) are on the right
+// of axis. returns N.
+static int b3Split(b3DbvtNode** leaves,
+                                  int count,
+                                  const b3Vector3& org,
+                                  const b3Vector3& axis)
+{
+       int begin = 0;
+       int end = count;
+       for (;;)
+       {
+               while (begin != end && b3LeftOfAxis(leaves[begin], org, axis))
+               {
+                       ++begin;
+               }
+
+               if (begin == end)
+               {
+                       break;
+               }
+
+               while (begin != end && !b3LeftOfAxis(leaves[end - 1], org, axis))
+               {
+                       --end;
+               }
+
+               if (begin == end)
+               {
+                       break;
+               }
+
+               // swap out of place nodes
+               --end;
+               b3DbvtNode* temp = leaves[begin];
+               leaves[begin] = leaves[end];
+               leaves[end] = temp;
+               ++begin;
+       }
+
+       return begin;
+}
+
+//
+static b3DbvtVolume b3Bounds(b3DbvtNode** leaves,
+                                                        int count)
+{
+#if B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE
+       B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtVolume)]);
+       b3DbvtVolume& volume = *(b3DbvtVolume*)locals;
+       volume = leaves[0]->volume;
+#else
+       b3DbvtVolume volume = leaves[0]->volume;
+#endif
+       for (int i = 1, ni = count; i < ni; ++i)
+       {
+               b3Merge(volume, leaves[i]->volume, volume);
+       }
+       return (volume);
+}
+
+//
+static void b3BottomUp(b3DynamicBvh* pdbvt,
+                                          b3DbvtNode** leaves,
+                                          int count)
+{
+       while (count > 1)
+       {
+               b3Scalar minsize = B3_INFINITY;
+               int minidx[2] = {-1, -1};
+               for (int i = 0; i < count; ++i)
+               {
+                       for (int j = i + 1; j < count; ++j)
+                       {
+                               const b3Scalar sz = b3Size(b3Merge(leaves[i]->volume, leaves[j]->volume));
+                               if (sz < minsize)
+                               {
+                                       minsize = sz;
+                                       minidx[0] = i;
+                                       minidx[1] = j;
+                               }
+                       }
+               }
+               b3DbvtNode* n[] = {leaves[minidx[0]], leaves[minidx[1]]};
+               b3DbvtNode* p = b3CreateNode(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[minidx[1]] = leaves[count - 1];
+               --count;
+       }
+}
+
+//
+static b3DbvtNode* b3TopDown(b3DynamicBvh* pdbvt,
+                                                        b3DbvtNode** leaves,
+                                                        int count,
+                                                        int bu_treshold)
+{
+       static const b3Vector3 axis[] = {b3MakeVector3(1, 0, 0),
+                                                                        b3MakeVector3(0, 1, 0),
+                                                                        b3MakeVector3(0, 0, 1)};
+       b3Assert(bu_treshold > 1);
+       if (count > 1)
+       {
+               if (count > bu_treshold)
+               {
+                       const b3DbvtVolume vol = b3Bounds(leaves, count);
+                       const b3Vector3 org = vol.Center();
+                       int partition;
+                       int bestaxis = -1;
+                       int bestmidp = count;
+                       int splitcount[3][2] = {{0, 0}, {0, 0}, {0, 0}};
+                       int i;
+                       for (i = 0; i < count; ++i)
+                       {
+                               const b3Vector3 x = leaves[i]->volume.Center() - org;
+                               for (int j = 0; j < 3; ++j)
+                               {
+                                       ++splitcount[j][b3Dot(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)b3Fabs(b3Scalar(splitcount[i][0] - splitcount[i][1]));
+                                       if (midp < bestmidp)
+                                       {
+                                               bestaxis = i;
+                                               bestmidp = midp;
+                                       }
+                               }
+                       }
+                       if (bestaxis >= 0)
+                       {
+                               partition = b3Split(leaves, count, org, axis[bestaxis]);
+                               b3Assert(partition != 0 && partition != count);
+                       }
+                       else
+                       {
+                               partition = count / 2 + 1;
+                       }
+                       b3DbvtNode* node = b3CreateNode(pdbvt, 0, vol, 0);
+                       node->childs[0] = b3TopDown(pdbvt, &leaves[0], partition, bu_treshold);
+                       node->childs[1] = b3TopDown(pdbvt, &leaves[partition], count - partition, bu_treshold);
+                       node->childs[0]->parent = node;
+                       node->childs[1]->parent = node;
+                       return (node);
+               }
+               else
+               {
+                       b3BottomUp(pdbvt, leaves, count);
+                       return (leaves[0]);
+               }
+       }
+       return (leaves[0]);
+}
+
+//
+static B3_DBVT_INLINE b3DbvtNode* b3Sort(b3DbvtNode* n, b3DbvtNode*& r)
+{
+       b3DbvtNode* p = n->parent;
+       b3Assert(n->isinternal());
+       if (p > n)
+       {
+               const int i = b3IndexOf(n);
+               const int j = 1 - i;
+               b3DbvtNode* s = p->childs[j];
+               b3DbvtNode* q = p->parent;
+               b3Assert(n == p->childs[i]);
+               if (q)
+                       q->childs[b3IndexOf(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;
+               b3Swap(p->volume, n->volume);
+               return (p);
+       }
+       return (n);
+}
+
+#if 0
+static B3_DBVT_INLINE b3DbvtNode*      walkup(b3DbvtNode* n,int count)
+{
+       while(n&&(count--)) n=n->parent;
+       return(n);
+}
+#endif
+
+//
+// Api
+//
+
+//
+b3DynamicBvh::b3DynamicBvh()
+{
+       m_root = 0;
+       m_free = 0;
+       m_lkhd = -1;
+       m_leaves = 0;
+       m_opath = 0;
+}
+
+//
+b3DynamicBvh::~b3DynamicBvh()
+{
+       clear();
+}
+
+//
+void b3DynamicBvh::clear()
+{
+       if (m_root)
+               b3RecurseDeleteNode(this, m_root);
+       b3AlignedFree(m_free);
+       m_free = 0;
+       m_lkhd = -1;
+       m_stkStack.clear();
+       m_opath = 0;
+}
+
+//
+void b3DynamicBvh::optimizeBottomUp()
+{
+       if (m_root)
+       {
+               b3NodeArray leaves;
+               leaves.reserve(m_leaves);
+               b3FetchLeaves(this, m_root, leaves);
+               b3BottomUp(this, &leaves[0], leaves.size());
+               m_root = leaves[0];
+       }
+}
+
+//
+void b3DynamicBvh::optimizeTopDown(int bu_treshold)
+{
+       if (m_root)
+       {
+               b3NodeArray leaves;
+               leaves.reserve(m_leaves);
+               b3FetchLeaves(this, m_root, leaves);
+               m_root = b3TopDown(this, &leaves[0], leaves.size(), bu_treshold);
+       }
+}
+
+//
+void b3DynamicBvh::optimizeIncremental(int passes)
+{
+       if (passes < 0) passes = m_leaves;
+       if (m_root && (passes > 0))
+       {
+               do
+               {
+                       b3DbvtNode* node = m_root;
+                       unsigned bit = 0;
+                       while (node->isinternal())
+                       {
+                               node = b3Sort(node, m_root)->childs[(m_opath >> bit) & 1];
+                               bit = (bit + 1) & (sizeof(unsigned) * 8 - 1);
+                       }
+                       update(node);
+                       ++m_opath;
+               } while (--passes);
+       }
+}
+
+//
+b3DbvtNode* b3DynamicBvh::insert(const b3DbvtVolume& volume, void* data)
+{
+       b3DbvtNode* leaf = b3CreateNode(this, 0, volume, data);
+       b3InsertLeaf(this, m_root, leaf);
+       ++m_leaves;
+       return (leaf);
+}
+
+//
+void b3DynamicBvh::update(b3DbvtNode* leaf, int lookahead)
+{
+       b3DbvtNode* root = b3RemoveLeaf(this, leaf);
+       if (root)
+       {
+               if (lookahead >= 0)
+               {
+                       for (int i = 0; (i < lookahead) && root->parent; ++i)
+                       {
+                               root = root->parent;
+                       }
+               }
+               else
+                       root = m_root;
+       }
+       b3InsertLeaf(this, root, leaf);
+}
+
+//
+void b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume)
+{
+       b3DbvtNode* root = b3RemoveLeaf(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;
+       b3InsertLeaf(this, root, leaf);
+}
+
+//
+bool b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity, b3Scalar margin)
+{
+       if (leaf->volume.Contain(volume)) return (false);
+       volume.Expand(b3MakeVector3(margin, margin, margin));
+       volume.SignedExpand(velocity);
+       update(leaf, volume);
+       return (true);
+}
+
+//
+bool b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity)
+{
+       if (leaf->volume.Contain(volume)) return (false);
+       volume.SignedExpand(velocity);
+       update(leaf, volume);
+       return (true);
+}
+
+//
+bool b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume, b3Scalar margin)
+{
+       if (leaf->volume.Contain(volume)) return (false);
+       volume.Expand(b3MakeVector3(margin, margin, margin));
+       update(leaf, volume);
+       return (true);
+}
+
+//
+void b3DynamicBvh::remove(b3DbvtNode* leaf)
+{
+       b3RemoveLeaf(this, leaf);
+       b3DeleteNode(this, leaf);
+       --m_leaves;
+}
+
+//
+void b3DynamicBvh::write(IWriter* iwriter) const
+{
+       b3DbvtNodeEnumerator 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 b3DbvtNode* 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 b3DynamicBvh::clone(b3DynamicBvh& dest, IClone* iclone) const
+{
+       dest.clear();
+       if (m_root != 0)
+       {
+               b3AlignedObjectArray<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];
+                       b3DbvtNode* n = b3CreateNode(&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 b3DynamicBvh::maxdepth(const b3DbvtNode* node)
+{
+       int depth = 0;
+       if (node) b3GetMaxDepth(node, 1, depth);
+       return (depth);
+}
+
+//
+int b3DynamicBvh::countLeaves(const b3DbvtNode* node)
+{
+       if (node->isinternal())
+               return (countLeaves(node->childs[0]) + countLeaves(node->childs[1]));
+       else
+               return (1);
+}
+
+//
+void b3DynamicBvh::extractLeaves(const b3DbvtNode* node, b3AlignedObjectArray<const b3DbvtNode*>& leaves)
+{
+       if (node->isinternal())
+       {
+               extractLeaves(node->childs[0], leaves);
+               extractLeaves(node->childs[1], leaves);
+       }
+       else
+       {
+               leaves.push_back(node);
+       }
+}
+
+//
+#if B3_DBVT_ENABLE_BENCHMARK
+
+#include <stdio.h>
+#include <stdlib.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(b3DbvtVolume): 32 bytes
+sizeof(b3DbvtNode):   44 bytes
+[1] b3DbvtVolume intersections: 3499 ms (-1%)
+[2] b3DbvtVolume merges: 1934 ms (0%)
+[3] b3DynamicBvh::collideTT: 5485 ms (-21%)
+[4] b3DynamicBvh::collideTT self: 2814 ms (-20%)
+[5] b3DynamicBvh::collideTT xform: 7379 ms (-1%)
+[6] b3DynamicBvh::collideTT xform,self: 7270 ms (-2%)
+[7] b3DynamicBvh::rayTest: 6314 ms (0%),(332143 r/s)
+[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
+[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
+[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
+[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
+[12] b3DbvtVolume notequal: 3659 ms (0%)
+[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
+[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
+[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
+[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
+[17] b3DbvtVolume select: 3419 ms (0%)
+*/
+
+struct b3DbvtBenchmark
+{
+       struct NilPolicy : b3DynamicBvh::ICollide
+       {
+               NilPolicy() : m_pcount(0), m_depth(-B3_INFINITY), m_checksort(true) {}
+               void Process(const b3DbvtNode*, const b3DbvtNode*) { ++m_pcount; }
+               void Process(const b3DbvtNode*) { ++m_pcount; }
+               void Process(const b3DbvtNode*, b3Scalar 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;
+               b3Scalar m_depth;
+               bool m_checksort;
+       };
+       struct P14 : b3DynamicBvh::ICollide
+       {
+               struct Node
+               {
+                       const b3DbvtNode* leaf;
+                       b3Scalar depth;
+               };
+               void Process(const b3DbvtNode* leaf, b3Scalar 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);
+               }
+               b3AlignedObjectArray<Node> m_nodes;
+       };
+       struct P15 : b3DynamicBvh::ICollide
+       {
+               struct Node
+               {
+                       const b3DbvtNode* leaf;
+                       b3Scalar depth;
+               };
+               void Process(const b3DbvtNode* 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);
+               }
+               b3AlignedObjectArray<Node> m_nodes;
+               b3Vector3 m_axis;
+       };
+       static b3Scalar RandUnit()
+       {
+               return (rand() / (b3Scalar)RAND_MAX);
+       }
+       static b3Vector3 RandVector3()
+       {
+               return (b3Vector3(RandUnit(), RandUnit(), RandUnit()));
+       }
+       static b3Vector3 RandVector3(b3Scalar cs)
+       {
+               return (RandVector3() * cs - b3Vector3(cs, cs, cs) / 2);
+       }
+       static b3DbvtVolume RandVolume(b3Scalar cs, b3Scalar eb, b3Scalar es)
+       {
+               return (b3DbvtVolume::FromCE(RandVector3(cs), b3Vector3(eb, eb, eb) + RandVector3() * es));
+       }
+       static b3Transform RandTransform(b3Scalar cs)
+       {
+               b3Transform t;
+               t.setOrigin(RandVector3(cs));
+               t.setRotation(b3Quaternion(RandUnit() * B3_PI * 2, RandUnit() * B3_PI * 2, RandUnit() * B3_PI * 2).normalized());
+               return (t);
+       }
+       static void RandTree(b3Scalar cs, b3Scalar eb, b3Scalar es, int leaves, b3DynamicBvh& dbvt)
+       {
+               dbvt.clear();
+               for (int i = 0; i < leaves; ++i)
+               {
+                       dbvt.insert(RandVolume(cs, eb, es), 0);
+               }
+       }
+};
+
+void b3DynamicBvh::benchmark()
+{
+       static const b3Scalar cfgVolumeCenterScale = 100;
+       static const b3Scalar cfgVolumeExentsBase = 1;
+       static const b3Scalar cfgVolumeExentsScale = 4;
+       static const int cfgLeaves = 8192;
+       static const bool cfgEnable = true;
+
+       //[1] b3DbvtVolume intersections
+       bool cfgBenchmark1_Enable = cfgEnable;
+       static const int cfgBenchmark1_Iterations = 8;
+       static const int cfgBenchmark1_Reference = 3499;
+       //[2] b3DbvtVolume merges
+       bool cfgBenchmark2_Enable = cfgEnable;
+       static const int cfgBenchmark2_Iterations = 4;
+       static const int cfgBenchmark2_Reference = 1945;
+       //[3] b3DynamicBvh::collideTT
+       bool cfgBenchmark3_Enable = cfgEnable;
+       static const int cfgBenchmark3_Iterations = 512;
+       static const int cfgBenchmark3_Reference = 5485;
+       //[4] b3DynamicBvh::collideTT self
+       bool cfgBenchmark4_Enable = cfgEnable;
+       static const int cfgBenchmark4_Iterations = 512;
+       static const int cfgBenchmark4_Reference = 2814;
+       //[5] b3DynamicBvh::collideTT xform
+       bool cfgBenchmark5_Enable = cfgEnable;
+       static const int cfgBenchmark5_Iterations = 512;
+       static const b3Scalar cfgBenchmark5_OffsetScale = 2;
+       static const int cfgBenchmark5_Reference = 7379;
+       //[6] b3DynamicBvh::collideTT xform,self
+       bool cfgBenchmark6_Enable = cfgEnable;
+       static const int cfgBenchmark6_Iterations = 512;
+       static const b3Scalar cfgBenchmark6_OffsetScale = 2;
+       static const int cfgBenchmark6_Reference = 7270;
+       //[7] b3DynamicBvh::rayTest
+       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 = 1879;
+       //[10] updates (jitter)
+       bool cfgBenchmark10_Enable = cfgEnable;
+       static const b3Scalar cfgBenchmark10_Scale = cfgVolumeCenterScale / 10000;
+       static const int cfgBenchmark10_Passes = 32;
+       static const int cfgBenchmark10_Iterations = 65536;
+       static const int cfgBenchmark10_Reference = 1244;
+       //[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] b3DbvtVolume 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] select
+       bool cfgBenchmark17_Enable = cfgEnable;
+       static const int cfgBenchmark17_Iterations = 4;
+       static const int cfgBenchmark17_Reference = 3390;
+
+       b3Clock 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(b3DbvtVolume): %u bytes\r\n", sizeof(b3DbvtVolume));
+       printf("\tsizeof(b3DbvtNode):   %u bytes\r\n", sizeof(b3DbvtNode));
+       if (cfgBenchmark1_Enable)
+       {  // Benchmark 1
+               srand(380843);
+               b3AlignedObjectArray<b3DbvtVolume> volumes;
+               b3AlignedObjectArray<bool> results;
+               volumes.resize(cfgLeaves);
+               results.resize(cfgLeaves);
+               for (int i = 0; i < cfgLeaves; ++i)
+               {
+                       volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
+               }
+               printf("[1] b3DbvtVolume 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);
+               b3AlignedObjectArray<b3DbvtVolume> volumes;
+               b3AlignedObjectArray<b3DbvtVolume> results;
+               volumes.resize(cfgLeaves);
+               results.resize(cfgLeaves);
+               for (int i = 0; i < cfgLeaves; ++i)
+               {
+                       volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
+               }
+               printf("[2] b3DbvtVolume 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);
+               b3DynamicBvh dbvt[2];
+               b3DbvtBenchmark::NilPolicy policy;
+               b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
+               b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
+               dbvt[0].optimizeTopDown();
+               dbvt[1].optimizeTopDown();
+               printf("[3] b3DynamicBvh::collideTT: ");
+               wallclock.reset();
+               for (int i = 0; i < cfgBenchmark3_Iterations; ++i)
+               {
+                       b3DynamicBvh::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);
+               b3DynamicBvh dbvt;
+               b3DbvtBenchmark::NilPolicy policy;
+               b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
+               dbvt.optimizeTopDown();
+               printf("[4] b3DynamicBvh::collideTT self: ");
+               wallclock.reset();
+               for (int i = 0; i < cfgBenchmark4_Iterations; ++i)
+               {
+                       b3DynamicBvh::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);
+               b3DynamicBvh dbvt[2];
+               b3AlignedObjectArray<b3Transform> transforms;
+               b3DbvtBenchmark::NilPolicy policy;
+               transforms.resize(cfgBenchmark5_Iterations);
+               for (int i = 0; i < transforms.size(); ++i)
+               {
+                       transforms[i] = b3DbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark5_OffsetScale);
+               }
+               b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
+               b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
+               dbvt[0].optimizeTopDown();
+               dbvt[1].optimizeTopDown();
+               printf("[5] b3DynamicBvh::collideTT xform: ");
+               wallclock.reset();
+               for (int i = 0; i < cfgBenchmark5_Iterations; ++i)
+               {
+                       b3DynamicBvh::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);
+               b3DynamicBvh dbvt;
+               b3AlignedObjectArray<b3Transform> transforms;
+               b3DbvtBenchmark::NilPolicy policy;
+               transforms.resize(cfgBenchmark6_Iterations);
+               for (int i = 0; i < transforms.size(); ++i)
+               {
+                       transforms[i] = b3DbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark6_OffsetScale);
+               }
+               b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
+               dbvt.optimizeTopDown();
+               printf("[6] b3DynamicBvh::collideTT xform,self: ");
+               wallclock.reset();
+               for (int i = 0; i < cfgBenchmark6_Iterations; ++i)
+               {
+                       b3DynamicBvh::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);
+               b3DynamicBvh dbvt;
+               b3AlignedObjectArray<b3Vector3> rayorg;
+               b3AlignedObjectArray<b3Vector3> raydir;
+               b3DbvtBenchmark::NilPolicy policy;
+               rayorg.resize(cfgBenchmark7_Iterations);
+               raydir.resize(cfgBenchmark7_Iterations);
+               for (int i = 0; i < rayorg.size(); ++i)
+               {
+                       rayorg[i] = b3DbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
+                       raydir[i] = b3DbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
+               }
+               b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
+               dbvt.optimizeTopDown();
+               printf("[7] b3DynamicBvh::rayTest: ");
+               wallclock.reset();
+               for (int i = 0; i < cfgBenchmark7_Passes; ++i)
+               {
+                       for (int j = 0; j < cfgBenchmark7_Iterations; ++j)
+                       {
+                               b3DynamicBvh::rayTest(dbvt.m_root, rayorg[j], 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);
+               b3DynamicBvh dbvt;
+               b3DbvtBenchmark::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(b3DbvtBenchmark::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);
+               b3DynamicBvh dbvt;
+               b3AlignedObjectArray<const b3DbvtNode*> leaves;
+               b3DbvtBenchmark::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<b3DbvtNode*>(leaves[rand() % cfgLeaves]),
+                                                       b3DbvtBenchmark::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);
+               b3DynamicBvh dbvt;
+               b3AlignedObjectArray<const b3DbvtNode*> leaves;
+               b3AlignedObjectArray<b3Vector3> vectors;
+               vectors.resize(cfgBenchmark10_Iterations);
+               for (int i = 0; i < vectors.size(); ++i)
+               {
+                       vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)) * cfgBenchmark10_Scale;
+               }
+               b3DbvtBenchmark::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 b3Vector3& d = vectors[j];
+                               b3DbvtNode* l = const_cast<b3DbvtNode*>(leaves[rand() % cfgLeaves]);
+                               b3DbvtVolume v = b3DbvtVolume::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);
+               b3DynamicBvh dbvt;
+               b3DbvtBenchmark::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);
+               b3AlignedObjectArray<b3DbvtVolume> volumes;
+               b3AlignedObjectArray<bool> results;
+               volumes.resize(cfgLeaves);
+               results.resize(cfgLeaves);
+               for (int i = 0; i < cfgLeaves; ++i)
+               {
+                       volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
+               }
+               printf("[12] b3DbvtVolume 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);
+               b3DynamicBvh dbvt;
+               b3AlignedObjectArray<b3Vector3> vectors;
+               b3DbvtBenchmark::NilPolicy policy;
+               vectors.resize(cfgBenchmark13_Iterations);
+               for (int i = 0; i < vectors.size(); ++i)
+               {
+                       vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)).normalized();
+               }
+               b3DbvtBenchmark::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 b3Scalar offset = 0;
+                       policy.m_depth = -B3_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);
+               b3DynamicBvh dbvt;
+               b3AlignedObjectArray<b3Vector3> vectors;
+               b3DbvtBenchmark::P14 policy;
+               vectors.resize(cfgBenchmark14_Iterations);
+               for (int i = 0; i < vectors.size(); ++i)
+               {
+                       vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)).normalized();
+               }
+               b3DbvtBenchmark::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 b3Scalar offset = 0;
+                       policy.m_nodes.resize(0);
+                       dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy, false);
+                       policy.m_nodes.quickSort(b3DbvtBenchmark::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);
+               b3DynamicBvh dbvt;
+               b3AlignedObjectArray<b3Vector3> vectors;
+               b3DbvtBenchmark::P15 policy;
+               vectors.resize(cfgBenchmark15_Iterations);
+               for (int i = 0; i < vectors.size(); ++i)
+               {
+                       vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)).normalized();
+               }
+               b3DbvtBenchmark::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 b3Scalar 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(b3DbvtBenchmark::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);
+               b3DynamicBvh dbvt;
+               b3AlignedObjectArray<b3DbvtNode*> batch;
+               b3DbvtBenchmark::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(b3DbvtBenchmark::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);
+               b3AlignedObjectArray<b3DbvtVolume> volumes;
+               b3AlignedObjectArray<int> results;
+               b3AlignedObjectArray<int> indices;
+               volumes.resize(cfgLeaves);
+               results.resize(cfgLeaves);
+               indices.resize(cfgLeaves);
+               for (int i = 0; i < cfgLeaves; ++i)
+               {
+                       indices[i] = i;
+                       volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
+               }
+               for (int i = 0; i < cfgLeaves; ++i)
+               {
+                       b3Swap(indices[i], indices[rand() % cfgLeaves]);
+               }
+               printf("[17] b3DbvtVolume select: ");
+               wallclock.reset();
+               for (int i = 0; i < cfgBenchmark17_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 - cfgBenchmark17_Reference) * 100 / time);
+       }
+       printf("\r\n\r\n");
+}
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h
new file mode 100644 (file)
index 0000000..f44e337
--- /dev/null
@@ -0,0 +1,1332 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///b3DynamicBvh implementation by Nathanael Presson
+
+#ifndef B3_DYNAMIC_BOUNDING_VOLUME_TREE_H
+#define B3_DYNAMIC_BOUNDING_VOLUME_TREE_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+//
+// Compile time configuration
+//
+
+// Implementation profiles
+#define B3_DBVT_IMPL_GENERIC 0  // Generic implementation
+#define B3_DBVT_IMPL_SSE 1      // SSE
+
+// Template implementation of ICollide
+#ifdef _WIN32
+#if (defined(_MSC_VER) && _MSC_VER >= 1400)
+#define B3_DBVT_USE_TEMPLATE 1
+#else
+#define B3_DBVT_USE_TEMPLATE 0
+#endif
+#else
+#define B3_DBVT_USE_TEMPLATE 0
+#endif
+
+// Use only intrinsics instead of inline asm
+#define B3_DBVT_USE_INTRINSIC_SSE 1
+
+// Using memmov for collideOCL
+#define B3_DBVT_USE_MEMMOVE 1
+
+// Enable benchmarking code
+#define B3_DBVT_ENABLE_BENCHMARK 0
+
+// Inlining
+#define B3_DBVT_INLINE B3_FORCE_INLINE
+
+// Specific methods implementation
+
+//SSE gives errors on a MSVC 7.1
+#if defined(B3_USE_SSE)  //&& defined (_WIN32)
+#define B3_DBVT_SELECT_IMPL B3_DBVT_IMPL_SSE
+#define B3_DBVT_MERGE_IMPL B3_DBVT_IMPL_SSE
+#define B3_DBVT_INT0_IMPL B3_DBVT_IMPL_SSE
+#else
+#define B3_DBVT_SELECT_IMPL B3_DBVT_IMPL_GENERIC
+#define B3_DBVT_MERGE_IMPL B3_DBVT_IMPL_GENERIC
+#define B3_DBVT_INT0_IMPL B3_DBVT_IMPL_GENERIC
+#endif
+
+#if (B3_DBVT_SELECT_IMPL == B3_DBVT_IMPL_SSE) || \
+       (B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE) ||  \
+       (B3_DBVT_INT0_IMPL == B3_DBVT_IMPL_SSE)
+#include <emmintrin.h>
+#endif
+
+//
+// Auto config and checks
+//
+
+#if B3_DBVT_USE_TEMPLATE
+#define B3_DBVT_VIRTUAL
+#define B3_DBVT_VIRTUAL_DTOR(a)
+#define B3_DBVT_PREFIX template <typename T>
+#define B3_DBVT_IPOLICY T& policy
+#define B3_DBVT_CHECKTYPE                        \
+       static const ICollide& typechecker = *(T*)1; \
+       (void)typechecker;
+#else
+#define B3_DBVT_VIRTUAL_DTOR(a) \
+       virtual ~a() {}
+#define B3_DBVT_VIRTUAL virtual
+#define B3_DBVT_PREFIX
+#define B3_DBVT_IPOLICY ICollide& policy
+#define B3_DBVT_CHECKTYPE
+#endif
+
+#if B3_DBVT_USE_MEMMOVE
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+#endif
+
+#ifndef B3_DBVT_USE_TEMPLATE
+#error "B3_DBVT_USE_TEMPLATE undefined"
+#endif
+
+#ifndef B3_DBVT_USE_MEMMOVE
+#error "B3_DBVT_USE_MEMMOVE undefined"
+#endif
+
+#ifndef B3_DBVT_ENABLE_BENCHMARK
+#error "B3_DBVT_ENABLE_BENCHMARK undefined"
+#endif
+
+#ifndef B3_DBVT_SELECT_IMPL
+#error "B3_DBVT_SELECT_IMPL undefined"
+#endif
+
+#ifndef B3_DBVT_MERGE_IMPL
+#error "B3_DBVT_MERGE_IMPL undefined"
+#endif
+
+#ifndef B3_DBVT_INT0_IMPL
+#error "B3_DBVT_INT0_IMPL undefined"
+#endif
+
+//
+// Defaults volumes
+//
+
+/* b3DbvtAabbMm                        */
+struct b3DbvtAabbMm
+{
+       B3_DBVT_INLINE b3Vector3 Center() const { return ((mi + mx) / 2); }
+       B3_DBVT_INLINE b3Vector3 Lengths() const { return (mx - mi); }
+       B3_DBVT_INLINE b3Vector3 Extents() const { return ((mx - mi) / 2); }
+       B3_DBVT_INLINE const b3Vector3& Mins() const { return (mi); }
+       B3_DBVT_INLINE const b3Vector3& Maxs() const { return (mx); }
+       static inline b3DbvtAabbMm FromCE(const b3Vector3& c, const b3Vector3& e);
+       static inline b3DbvtAabbMm FromCR(const b3Vector3& c, b3Scalar r);
+       static inline b3DbvtAabbMm FromMM(const b3Vector3& mi, const b3Vector3& mx);
+       static inline b3DbvtAabbMm FromPoints(const b3Vector3* pts, int n);
+       static inline b3DbvtAabbMm FromPoints(const b3Vector3** ppts, int n);
+       B3_DBVT_INLINE void Expand(const b3Vector3& e);
+       B3_DBVT_INLINE void SignedExpand(const b3Vector3& e);
+       B3_DBVT_INLINE bool Contain(const b3DbvtAabbMm& a) const;
+       B3_DBVT_INLINE int Classify(const b3Vector3& n, b3Scalar o, int s) const;
+       B3_DBVT_INLINE b3Scalar ProjectMinimum(const b3Vector3& v, unsigned signs) const;
+       B3_DBVT_INLINE friend bool b3Intersect(const b3DbvtAabbMm& a,
+                                                                                  const b3DbvtAabbMm& b);
+
+       B3_DBVT_INLINE friend bool b3Intersect(const b3DbvtAabbMm& a,
+                                                                                  const b3Vector3& b);
+
+       B3_DBVT_INLINE friend b3Scalar b3Proximity(const b3DbvtAabbMm& a,
+                                                                                          const b3DbvtAabbMm& b);
+       B3_DBVT_INLINE friend int b3Select(const b3DbvtAabbMm& o,
+                                                                          const b3DbvtAabbMm& a,
+                                                                          const b3DbvtAabbMm& b);
+       B3_DBVT_INLINE friend void b3Merge(const b3DbvtAabbMm& a,
+                                                                          const b3DbvtAabbMm& b,
+                                                                          b3DbvtAabbMm& r);
+       B3_DBVT_INLINE friend bool b3NotEqual(const b3DbvtAabbMm& a,
+                                                                                 const b3DbvtAabbMm& b);
+
+       B3_DBVT_INLINE b3Vector3& tMins() { return (mi); }
+       B3_DBVT_INLINE b3Vector3& tMaxs() { return (mx); }
+
+private:
+       B3_DBVT_INLINE void AddSpan(const b3Vector3& d, b3Scalar& smi, b3Scalar& smx) const;
+
+private:
+       b3Vector3 mi, mx;
+};
+
+// Types
+typedef b3DbvtAabbMm b3DbvtVolume;
+
+/* b3DbvtNode                          */
+struct b3DbvtNode
+{
+       b3DbvtVolume volume;
+       b3DbvtNode* parent;
+       B3_DBVT_INLINE bool isleaf() const { return (childs[1] == 0); }
+       B3_DBVT_INLINE bool isinternal() const { return (!isleaf()); }
+       union {
+               b3DbvtNode* childs[2];
+               void* data;
+               int dataAsInt;
+       };
+};
+
+///The b3DynamicBvh class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
+///This b3DynamicBvh is used for soft body collision detection and for the b3DynamicBvhBroadphase. It has a fast insert, remove and update of nodes.
+///Unlike the b3QuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
+struct b3DynamicBvh
+{
+       /* Stack element        */
+       struct sStkNN
+       {
+               const b3DbvtNode* a;
+               const b3DbvtNode* b;
+               sStkNN() {}
+               sStkNN(const b3DbvtNode* na, const b3DbvtNode* nb) : a(na), b(nb) {}
+       };
+       struct sStkNP
+       {
+               const b3DbvtNode* node;
+               int mask;
+               sStkNP(const b3DbvtNode* n, unsigned m) : node(n), mask(m) {}
+       };
+       struct sStkNPS
+       {
+               const b3DbvtNode* node;
+               int mask;
+               b3Scalar value;
+               sStkNPS() {}
+               sStkNPS(const b3DbvtNode* n, unsigned m, b3Scalar v) : node(n), mask(m), value(v) {}
+       };
+       struct sStkCLN
+       {
+               const b3DbvtNode* node;
+               b3DbvtNode* parent;
+               sStkCLN(const b3DbvtNode* n, b3DbvtNode* p) : node(n), parent(p) {}
+       };
+       // Policies/Interfaces
+
+       /* ICollide     */
+       struct ICollide
+       {
+               B3_DBVT_VIRTUAL_DTOR(ICollide)
+               B3_DBVT_VIRTUAL void Process(const b3DbvtNode*, const b3DbvtNode*) {}
+               B3_DBVT_VIRTUAL void Process(const b3DbvtNode*) {}
+               B3_DBVT_VIRTUAL void Process(const b3DbvtNode* n, b3Scalar) { Process(n); }
+               B3_DBVT_VIRTUAL bool Descent(const b3DbvtNode*) { return (true); }
+               B3_DBVT_VIRTUAL bool AllLeaves(const b3DbvtNode*) { return (true); }
+       };
+       /* IWriter      */
+       struct IWriter
+       {
+               virtual ~IWriter() {}
+               virtual void Prepare(const b3DbvtNode* root, int numnodes) = 0;
+               virtual void WriteNode(const b3DbvtNode*, int index, int parent, int child0, int child1) = 0;
+               virtual void WriteLeaf(const b3DbvtNode*, int index, int parent) = 0;
+       };
+       /* IClone       */
+       struct IClone
+       {
+               virtual ~IClone() {}
+               virtual void CloneLeaf(b3DbvtNode*) {}
+       };
+
+       // Constants
+       enum
+       {
+               B3_SIMPLE_STACKSIZE = 64,
+               B3_DOUBLE_STACKSIZE = B3_SIMPLE_STACKSIZE * 2
+       };
+
+       // Fields
+       b3DbvtNode* m_root;
+       b3DbvtNode* m_free;
+       int m_lkhd;
+       int m_leaves;
+       unsigned m_opath;
+
+       b3AlignedObjectArray<sStkNN> m_stkStack;
+       mutable b3AlignedObjectArray<const b3DbvtNode*> m_rayTestStack;
+
+       // Methods
+       b3DynamicBvh();
+       ~b3DynamicBvh();
+       void clear();
+       bool empty() const { return (0 == m_root); }
+       void optimizeBottomUp();
+       void optimizeTopDown(int bu_treshold = 128);
+       void optimizeIncremental(int passes);
+       b3DbvtNode* insert(const b3DbvtVolume& box, void* data);
+       void update(b3DbvtNode* leaf, int lookahead = -1);
+       void update(b3DbvtNode* leaf, b3DbvtVolume& volume);
+       bool update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity, b3Scalar margin);
+       bool update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity);
+       bool update(b3DbvtNode* leaf, b3DbvtVolume& volume, b3Scalar margin);
+       void remove(b3DbvtNode* leaf);
+       void write(IWriter* iwriter) const;
+       void clone(b3DynamicBvh& dest, IClone* iclone = 0) const;
+       static int maxdepth(const b3DbvtNode* node);
+       static int countLeaves(const b3DbvtNode* node);
+       static void extractLeaves(const b3DbvtNode* node, b3AlignedObjectArray<const b3DbvtNode*>& leaves);
+#if B3_DBVT_ENABLE_BENCHMARK
+       static void benchmark();
+#else
+       static void benchmark()
+       {
+       }
+#endif
+       // B3_DBVT_IPOLICY must support ICollide policy/interface
+       B3_DBVT_PREFIX
+       static void enumNodes(const b3DbvtNode* root,
+                                                 B3_DBVT_IPOLICY);
+       B3_DBVT_PREFIX
+       static void enumLeaves(const b3DbvtNode* root,
+                                                  B3_DBVT_IPOLICY);
+       B3_DBVT_PREFIX
+       void collideTT(const b3DbvtNode* root0,
+                                  const b3DbvtNode* root1,
+                                  B3_DBVT_IPOLICY);
+
+       B3_DBVT_PREFIX
+       void collideTTpersistentStack(const b3DbvtNode* root0,
+                                                                 const b3DbvtNode* root1,
+                                                                 B3_DBVT_IPOLICY);
+#if 0
+       B3_DBVT_PREFIX
+               void            collideTT(      const b3DbvtNode* root0,
+               const b3DbvtNode* root1,
+               const b3Transform& xform,
+               B3_DBVT_IPOLICY);
+       B3_DBVT_PREFIX
+               void            collideTT(      const b3DbvtNode* root0,
+               const b3Transform& xform0,
+               const b3DbvtNode* root1,
+               const b3Transform& xform1,
+               B3_DBVT_IPOLICY);
+#endif
+
+       B3_DBVT_PREFIX
+       void collideTV(const b3DbvtNode* root,
+                                  const b3DbvtVolume& volume,
+                                  B3_DBVT_IPOLICY) const;
+       ///rayTest is a re-entrant ray test, and can be called in parallel as long as the b3AlignedAlloc is thread-safe (uses locking etc)
+       ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
+       B3_DBVT_PREFIX
+       static void rayTest(const b3DbvtNode* root,
+                                               const b3Vector3& rayFrom,
+                                               const b3Vector3& rayTo,
+                                               B3_DBVT_IPOLICY);
+       ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
+       ///rayTestInternal is used by b3DynamicBvhBroadphase to accelerate world ray casts
+       B3_DBVT_PREFIX
+       void rayTestInternal(const b3DbvtNode* root,
+                                                const b3Vector3& rayFrom,
+                                                const b3Vector3& rayTo,
+                                                const b3Vector3& rayDirectionInverse,
+                                                unsigned int signs[3],
+                                                b3Scalar lambda_max,
+                                                const b3Vector3& aabbMin,
+                                                const b3Vector3& aabbMax,
+                                                B3_DBVT_IPOLICY) const;
+
+       B3_DBVT_PREFIX
+       static void collideKDOP(const b3DbvtNode* root,
+                                                       const b3Vector3* normals,
+                                                       const b3Scalar* offsets,
+                                                       int count,
+                                                       B3_DBVT_IPOLICY);
+       B3_DBVT_PREFIX
+       static void collideOCL(const b3DbvtNode* root,
+                                                  const b3Vector3* normals,
+                                                  const b3Scalar* offsets,
+                                                  const b3Vector3& sortaxis,
+                                                  int count,
+                                                  B3_DBVT_IPOLICY,
+                                                  bool fullsort = true);
+       B3_DBVT_PREFIX
+       static void collideTU(const b3DbvtNode* root,
+                                                 B3_DBVT_IPOLICY);
+       // Helpers
+       static B3_DBVT_INLINE int nearest(const int* i, const b3DynamicBvh::sStkNPS* a, b3Scalar 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 B3_DBVT_INLINE int allocate(b3AlignedObjectArray<int>& ifree,
+                                                                          b3AlignedObjectArray<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:
+       b3DynamicBvh(const b3DynamicBvh&) {}
+};
+
+//
+// Inline's
+//
+
+//
+inline b3DbvtAabbMm b3DbvtAabbMm::FromCE(const b3Vector3& c, const b3Vector3& e)
+{
+       b3DbvtAabbMm box;
+       box.mi = c - e;
+       box.mx = c + e;
+       return (box);
+}
+
+//
+inline b3DbvtAabbMm b3DbvtAabbMm::FromCR(const b3Vector3& c, b3Scalar r)
+{
+       return (FromCE(c, b3MakeVector3(r, r, r)));
+}
+
+//
+inline b3DbvtAabbMm b3DbvtAabbMm::FromMM(const b3Vector3& mi, const b3Vector3& mx)
+{
+       b3DbvtAabbMm box;
+       box.mi = mi;
+       box.mx = mx;
+       return (box);
+}
+
+//
+inline b3DbvtAabbMm b3DbvtAabbMm::FromPoints(const b3Vector3* pts, int n)
+{
+       b3DbvtAabbMm 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 b3DbvtAabbMm b3DbvtAabbMm::FromPoints(const b3Vector3** ppts, int n)
+{
+       b3DbvtAabbMm 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);
+}
+
+//
+B3_DBVT_INLINE void b3DbvtAabbMm::Expand(const b3Vector3& e)
+{
+       mi -= e;
+       mx += e;
+}
+
+//
+B3_DBVT_INLINE void b3DbvtAabbMm::SignedExpand(const b3Vector3& e)
+{
+       if (e.x > 0)
+               mx.setX(mx.x + e[0]);
+       else
+               mi.setX(mi.x + e[0]);
+       if (e.y > 0)
+               mx.setY(mx.y + e[1]);
+       else
+               mi.setY(mi.y + e[1]);
+       if (e.z > 0)
+               mx.setZ(mx.z + e[2]);
+       else
+               mi.setZ(mi.z + e[2]);
+}
+
+//
+B3_DBVT_INLINE bool b3DbvtAabbMm::Contain(const b3DbvtAabbMm& 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));
+}
+
+//
+B3_DBVT_INLINE int b3DbvtAabbMm::Classify(const b3Vector3& n, b3Scalar o, int s) const
+{
+       b3Vector3 pi, px;
+       switch (s)
+       {
+               case (0 + 0 + 0):
+                       px = b3MakeVector3(mi.x, mi.y, mi.z);
+                       pi = b3MakeVector3(mx.x, mx.y, mx.z);
+                       break;
+               case (1 + 0 + 0):
+                       px = b3MakeVector3(mx.x, mi.y, mi.z);
+                       pi = b3MakeVector3(mi.x, mx.y, mx.z);
+                       break;
+               case (0 + 2 + 0):
+                       px = b3MakeVector3(mi.x, mx.y, mi.z);
+                       pi = b3MakeVector3(mx.x, mi.y, mx.z);
+                       break;
+               case (1 + 2 + 0):
+                       px = b3MakeVector3(mx.x, mx.y, mi.z);
+                       pi = b3MakeVector3(mi.x, mi.y, mx.z);
+                       break;
+               case (0 + 0 + 4):
+                       px = b3MakeVector3(mi.x, mi.y, mx.z);
+                       pi = b3MakeVector3(mx.x, mx.y, mi.z);
+                       break;
+               case (1 + 0 + 4):
+                       px = b3MakeVector3(mx.x, mi.y, mx.z);
+                       pi = b3MakeVector3(mi.x, mx.y, mi.z);
+                       break;
+               case (0 + 2 + 4):
+                       px = b3MakeVector3(mi.x, mx.y, mx.z);
+                       pi = b3MakeVector3(mx.x, mi.y, mi.z);
+                       break;
+               case (1 + 2 + 4):
+                       px = b3MakeVector3(mx.x, mx.y, mx.z);
+                       pi = b3MakeVector3(mi.x, mi.y, mi.z);
+                       break;
+       }
+       if ((b3Dot(n, px) + o) < 0) return (-1);
+       if ((b3Dot(n, pi) + o) >= 0) return (+1);
+       return (0);
+}
+
+//
+B3_DBVT_INLINE b3Scalar b3DbvtAabbMm::ProjectMinimum(const b3Vector3& v, unsigned signs) const
+{
+       const b3Vector3* b[] = {&mx, &mi};
+       const b3Vector3 p = b3MakeVector3(b[(signs >> 0) & 1]->x,
+                                                                         b[(signs >> 1) & 1]->y,
+                                                                         b[(signs >> 2) & 1]->z);
+       return (b3Dot(p, v));
+}
+
+//
+B3_DBVT_INLINE void b3DbvtAabbMm::AddSpan(const b3Vector3& d, b3Scalar& smi, b3Scalar& 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];
+               }
+       }
+}
+
+//
+B3_DBVT_INLINE bool b3Intersect(const b3DbvtAabbMm& a,
+                                                               const b3DbvtAabbMm& b)
+{
+#if B3_DBVT_INT0_IMPL == B3_DBVT_IMPL_SSE
+       const __m128 rt(_mm_or_ps(_mm_cmplt_ps(_mm_load_ps(b.mx), _mm_load_ps(a.mi)),
+                                                         _mm_cmplt_ps(_mm_load_ps(a.mx), _mm_load_ps(b.mi))));
+#if defined(_WIN32)
+       const __int32* pu((const __int32*)&rt);
+#else
+       const int* pu((const int*)&rt);
+#endif
+       return ((pu[0] | pu[1] | pu[2]) == 0);
+#else
+       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));
+#endif
+}
+
+//
+B3_DBVT_INLINE bool b3Intersect(const b3DbvtAabbMm& a,
+                                                               const b3Vector3& 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));
+}
+
+//////////////////////////////////////
+
+//
+B3_DBVT_INLINE b3Scalar b3Proximity(const b3DbvtAabbMm& a,
+                                                                       const b3DbvtAabbMm& b)
+{
+       const b3Vector3 d = (a.mi + a.mx) - (b.mi + b.mx);
+       return (b3Fabs(d.x) + b3Fabs(d.y) + b3Fabs(d.z));
+}
+
+//
+B3_DBVT_INLINE int b3Select(const b3DbvtAabbMm& o,
+                                                       const b3DbvtAabbMm& a,
+                                                       const b3DbvtAabbMm& b)
+{
+#if B3_DBVT_SELECT_IMPL == B3_DBVT_IMPL_SSE
+
+#if defined(_WIN32)
+       static B3_ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
+#else
+       static B3_ATTRIBUTE_ALIGNED16(const unsigned int) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x00000000 /*0x7fffffff*/};
+#endif
+       ///@todo: the intrinsic version is 11% slower
+#if B3_DBVT_USE_INTRINSIC_SSE
+
+       union b3SSEUnion  ///NOTE: if we use more intrinsics, move b3SSEUnion into the LinearMath directory
+       {
+               __m128 ssereg;
+               float floats[4];
+               int ints[4];
+       };
+
+       __m128 omi(_mm_load_ps(o.mi));
+       omi = _mm_add_ps(omi, _mm_load_ps(o.mx));
+       __m128 ami(_mm_load_ps(a.mi));
+       ami = _mm_add_ps(ami, _mm_load_ps(a.mx));
+       ami = _mm_sub_ps(ami, omi);
+       ami = _mm_and_ps(ami, _mm_load_ps((const float*)mask));
+       __m128 bmi(_mm_load_ps(b.mi));
+       bmi = _mm_add_ps(bmi, _mm_load_ps(b.mx));
+       bmi = _mm_sub_ps(bmi, omi);
+       bmi = _mm_and_ps(bmi, _mm_load_ps((const float*)mask));
+       __m128 t0(_mm_movehl_ps(ami, ami));
+       ami = _mm_add_ps(ami, t0);
+       ami = _mm_add_ss(ami, _mm_shuffle_ps(ami, ami, 1));
+       __m128 t1(_mm_movehl_ps(bmi, bmi));
+       bmi = _mm_add_ps(bmi, t1);
+       bmi = _mm_add_ss(bmi, _mm_shuffle_ps(bmi, bmi, 1));
+
+       b3SSEUnion tmp;
+       tmp.ssereg = _mm_cmple_ss(bmi, ami);
+       return tmp.ints[0] & 1;
+
+#else
+       B3_ATTRIBUTE_ALIGNED16(__int32 r[1]);
+       __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);
+#endif
+#else
+       return (b3Proximity(o, a) < b3Proximity(o, b) ? 0 : 1);
+#endif
+}
+
+//
+B3_DBVT_INLINE void b3Merge(const b3DbvtAabbMm& a,
+                                                       const b3DbvtAabbMm& b,
+                                                       b3DbvtAabbMm& r)
+{
+#if B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE
+       __m128 ami(_mm_load_ps(a.mi));
+       __m128 amx(_mm_load_ps(a.mx));
+       __m128 bmi(_mm_load_ps(b.mi));
+       __m128 bmx(_mm_load_ps(b.mx));
+       ami = _mm_min_ps(ami, bmi);
+       amx = _mm_max_ps(amx, bmx);
+       _mm_store_ps(r.mi, ami);
+       _mm_store_ps(r.mx, amx);
+#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
+}
+
+//
+B3_DBVT_INLINE bool b3NotEqual(const b3DbvtAabbMm& a,
+                                                          const b3DbvtAabbMm& 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
+//
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::enumNodes(const b3DbvtNode* root,
+                                                                       B3_DBVT_IPOLICY)
+{
+       B3_DBVT_CHECKTYPE
+       policy.Process(root);
+       if (root->isinternal())
+       {
+               enumNodes(root->childs[0], policy);
+               enumNodes(root->childs[1], policy);
+       }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::enumLeaves(const b3DbvtNode* root,
+                                                                        B3_DBVT_IPOLICY)
+{
+       B3_DBVT_CHECKTYPE
+       if (root->isinternal())
+       {
+               enumLeaves(root->childs[0], policy);
+               enumLeaves(root->childs[1], policy);
+       }
+       else
+       {
+               policy.Process(root);
+       }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideTT(const b3DbvtNode* root0,
+                                                                       const b3DbvtNode* root1,
+                                                                       B3_DBVT_IPOLICY)
+{
+       B3_DBVT_CHECKTYPE
+       if (root0 && root1)
+       {
+               int depth = 1;
+               int treshold = B3_DOUBLE_STACKSIZE - 4;
+               b3AlignedObjectArray<sStkNN> stkStack;
+               stkStack.resize(B3_DOUBLE_STACKSIZE);
+               stkStack[0] = sStkNN(root0, root1);
+               do
+               {
+                       sStkNN p = stkStack[--depth];
+                       if (depth > treshold)
+                       {
+                               stkStack.resize(stkStack.size() * 2);
+                               treshold = stkStack.size() - 4;
+                       }
+                       if (p.a == p.b)
+                       {
+                               if (p.a->isinternal())
+                               {
+                                       stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+                                       stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+                                       stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
+                               }
+                       }
+                       else if (b3Intersect(p.a->volume, p.b->volume))
+                       {
+                               if (p.a->isinternal())
+                               {
+                                       if (p.b->isinternal())
+                                       {
+                                               stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+                                               stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+                                               stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+                                               stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                               stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+                                               stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
+                                       }
+                               }
+                               else
+                               {
+                                       if (p.b->isinternal())
+                                       {
+                                               stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+                                               stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                               policy.Process(p.a, p.b);
+                                       }
+                               }
+                       }
+               } while (depth);
+       }
+}
+
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideTTpersistentStack(const b3DbvtNode* root0,
+                                                                                                  const b3DbvtNode* root1,
+                                                                                                  B3_DBVT_IPOLICY)
+{
+       B3_DBVT_CHECKTYPE
+       if (root0 && root1)
+       {
+               int depth = 1;
+               int treshold = B3_DOUBLE_STACKSIZE - 4;
+
+               m_stkStack.resize(B3_DOUBLE_STACKSIZE);
+               m_stkStack[0] = sStkNN(root0, root1);
+               do
+               {
+                       sStkNN p = m_stkStack[--depth];
+                       if (depth > treshold)
+                       {
+                               m_stkStack.resize(m_stkStack.size() * 2);
+                               treshold = m_stkStack.size() - 4;
+                       }
+                       if (p.a == p.b)
+                       {
+                               if (p.a->isinternal())
+                               {
+                                       m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+                                       m_stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+                                       m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
+                               }
+                       }
+                       else if (b3Intersect(p.a->volume, p.b->volume))
+                       {
+                               if (p.a->isinternal())
+                               {
+                                       if (p.b->isinternal())
+                                       {
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
+                                       }
+                               }
+                               else
+                               {
+                                       if (p.b->isinternal())
+                                       {
+                                               m_stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+                                               m_stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                               policy.Process(p.a, p.b);
+                                       }
+                               }
+                       }
+               } while (depth);
+       }
+}
+
+#if 0
+//
+B3_DBVT_PREFIX
+inline void            b3DynamicBvh::collideTT(        const b3DbvtNode* root0,
+                                                                 const b3DbvtNode* root1,
+                                                                 const b3Transform& xform,
+                                                                 B3_DBVT_IPOLICY)
+{
+       B3_DBVT_CHECKTYPE
+               if(root0&&root1)
+               {
+                       int                                                             depth=1;
+                       int                                                             treshold=B3_DOUBLE_STACKSIZE-4;
+                       b3AlignedObjectArray<sStkNN>    stkStack;
+                       stkStack.resize(B3_DOUBLE_STACKSIZE);
+                       stkStack[0]=sStkNN(root0,root1);
+                       do      {
+                               sStkNN  p=stkStack[--depth];
+                               if(b3Intersect(p.a->volume,p.b->volume,xform))
+                               {
+                                       if(depth>treshold)
+                                       {
+                                               stkStack.resize(stkStack.size()*2);
+                                               treshold=stkStack.size()-4;
+                                       }
+                                       if(p.a->isinternal())
+                                       {
+                                               if(p.b->isinternal())
+                                               {                                       
+                                                       stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+                                                       stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+                                                       stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+                                                       stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+                                               }
+                                               else
+                                               {
+                                                       stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+                                                       stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if(p.b->isinternal())
+                                               {
+                                                       stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+                                                       stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+                                               }
+                                               else
+                                               {
+                                                       policy.Process(p.a,p.b);
+                                               }
+                                       }
+                               }
+                       } while(depth);
+               }
+}
+//
+B3_DBVT_PREFIX
+inline void            b3DynamicBvh::collideTT(        const b3DbvtNode* root0,
+                                                                 const b3Transform& xform0,
+                                                                 const b3DbvtNode* root1,
+                                                                 const b3Transform& xform1,
+                                                                 B3_DBVT_IPOLICY)
+{
+       const b3Transform       xform=xform0.inverse()*xform1;
+       collideTT(root0,root1,xform,policy);
+}
+#endif
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideTV(const b3DbvtNode* root,
+                                                                       const b3DbvtVolume& vol,
+                                                                       B3_DBVT_IPOLICY) const
+{
+       B3_DBVT_CHECKTYPE
+       if (root)
+       {
+               B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
+               volume(vol);
+               b3AlignedObjectArray<const b3DbvtNode*> stack;
+               stack.resize(0);
+               stack.reserve(B3_SIMPLE_STACKSIZE);
+               stack.push_back(root);
+               do
+               {
+                       const b3DbvtNode* n = stack[stack.size() - 1];
+                       stack.pop_back();
+                       if (b3Intersect(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);
+       }
+}
+
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::rayTestInternal(const b3DbvtNode* root,
+                                                                                 const b3Vector3& rayFrom,
+                                                                                 const b3Vector3& rayTo,
+                                                                                 const b3Vector3& rayDirectionInverse,
+                                                                                 unsigned int signs[3],
+                                                                                 b3Scalar lambda_max,
+                                                                                 const b3Vector3& aabbMin,
+                                                                                 const b3Vector3& aabbMax,
+                                                                                 B3_DBVT_IPOLICY) const
+{
+       (void)rayTo;
+       B3_DBVT_CHECKTYPE
+       if (root)
+       {
+               int depth = 1;
+               int treshold = B3_DOUBLE_STACKSIZE - 2;
+               b3AlignedObjectArray<const b3DbvtNode*>& stack = m_rayTestStack;
+               stack.resize(B3_DOUBLE_STACKSIZE);
+               stack[0] = root;
+               b3Vector3 bounds[2];
+               do
+               {
+                       const b3DbvtNode* node = stack[--depth];
+                       bounds[0] = node->volume.Mins() - aabbMax;
+                       bounds[1] = node->volume.Maxs() - aabbMin;
+                       b3Scalar tmin = 1.f, lambda_min = 0.f;
+                       unsigned int result1 = false;
+                       result1 = b3RayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
+                       if (result1)
+                       {
+                               if (node->isinternal())
+                               {
+                                       if (depth > treshold)
+                                       {
+                                               stack.resize(stack.size() * 2);
+                                               treshold = stack.size() - 2;
+                                       }
+                                       stack[depth++] = node->childs[0];
+                                       stack[depth++] = node->childs[1];
+                               }
+                               else
+                               {
+                                       policy.Process(node);
+                               }
+                       }
+               } while (depth);
+       }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::rayTest(const b3DbvtNode* root,
+                                                                 const b3Vector3& rayFrom,
+                                                                 const b3Vector3& rayTo,
+                                                                 B3_DBVT_IPOLICY)
+{
+       B3_DBVT_CHECKTYPE
+       if (root)
+       {
+               b3Vector3 rayDir = (rayTo - rayFrom);
+               rayDir.normalize();
+
+               ///what about division by zero? --> just set rayDirection[i] to INF/B3_LARGE_FLOAT
+               b3Vector3 rayDirectionInverse;
+               rayDirectionInverse[0] = rayDir[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[0];
+               rayDirectionInverse[1] = rayDir[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[1];
+               rayDirectionInverse[2] = rayDir[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[2];
+               unsigned int signs[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+
+               b3Scalar lambda_max = rayDir.dot(rayTo - rayFrom);
+#ifdef COMPARE_BTRAY_AABB2
+               b3Vector3 resultNormal;
+#endif  //COMPARE_BTRAY_AABB2
+
+               b3AlignedObjectArray<const b3DbvtNode*> stack;
+
+               int depth = 1;
+               int treshold = B3_DOUBLE_STACKSIZE - 2;
+
+               stack.resize(B3_DOUBLE_STACKSIZE);
+               stack[0] = root;
+               b3Vector3 bounds[2];
+               do
+               {
+                       const b3DbvtNode* node = stack[--depth];
+
+                       bounds[0] = node->volume.Mins();
+                       bounds[1] = node->volume.Maxs();
+
+                       b3Scalar tmin = 1.f, lambda_min = 0.f;
+                       unsigned int result1 = b3RayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
+
+#ifdef COMPARE_BTRAY_AABB2
+                       b3Scalar param = 1.f;
+                       bool result2 = b3RayAabb(rayFrom, rayTo, node->volume.Mins(), node->volume.Maxs(), param, resultNormal);
+                       b3Assert(result1 == result2);
+#endif  //TEST_BTRAY_AABB2
+
+                       if (result1)
+                       {
+                               if (node->isinternal())
+                               {
+                                       if (depth > treshold)
+                                       {
+                                               stack.resize(stack.size() * 2);
+                                               treshold = stack.size() - 2;
+                                       }
+                                       stack[depth++] = node->childs[0];
+                                       stack[depth++] = node->childs[1];
+                               }
+                               else
+                               {
+                                       policy.Process(node);
+                               }
+                       }
+               } while (depth);
+       }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideKDOP(const b3DbvtNode* root,
+                                                                         const b3Vector3* normals,
+                                                                         const b3Scalar* offsets,
+                                                                         int count,
+                                                                         B3_DBVT_IPOLICY)
+{
+       B3_DBVT_CHECKTYPE
+       if (root)
+       {
+               const int inside = (1 << count) - 1;
+               b3AlignedObjectArray<sStkNP> stack;
+               int signs[sizeof(unsigned) * 8];
+               b3Assert(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(B3_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());
+       }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideOCL(const b3DbvtNode* root,
+                                                                        const b3Vector3* normals,
+                                                                        const b3Scalar* offsets,
+                                                                        const b3Vector3& sortaxis,
+                                                                        int count,
+                                                                        B3_DBVT_IPOLICY,
+                                                                        bool fsort)
+{
+       B3_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;
+               b3AlignedObjectArray<sStkNPS> stock;
+               b3AlignedObjectArray<int> ifree;
+               b3AlignedObjectArray<int> stack;
+               int signs[sizeof(unsigned) * 8];
+               b3Assert(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(B3_SIMPLE_STACKSIZE);
+               stack.reserve(B3_SIMPLE_STACKSIZE);
+               ifree.reserve(B3_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 b3DbvtNode* 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 B3_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 B3_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());
+       }
+}
+
+//
+B3_DBVT_PREFIX
+inline void b3DynamicBvh::collideTU(const b3DbvtNode* root,
+                                                                       B3_DBVT_IPOLICY)
+{
+       B3_DBVT_CHECKTYPE
+       if (root)
+       {
+               b3AlignedObjectArray<const b3DbvtNode*> stack;
+               stack.reserve(B3_SIMPLE_STACKSIZE);
+               stack.push_back(root);
+               do
+               {
+                       const b3DbvtNode* 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 B3_DBVT_USE_MEMMOVE
+#undef B3_DBVT_USE_TEMPLATE
+#undef B3_DBVT_VIRTUAL_DTOR
+#undef B3_DBVT_VIRTUAL
+#undef B3_DBVT_PREFIX
+#undef B3_DBVT_IPOLICY
+#undef B3_DBVT_CHECKTYPE
+#undef B3_DBVT_IMPL_GENERIC
+#undef B3_DBVT_IMPL_SSE
+#undef B3_DBVT_USE_INTRINSIC_SSE
+#undef B3_DBVT_SELECT_IMPL
+#undef B3_DBVT_MERGE_IMPL
+#undef B3_DBVT_INT0_IMPL
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp b/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp
new file mode 100644 (file)
index 0000000..dea2ddb
--- /dev/null
@@ -0,0 +1,808 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///b3DynamicBvhBroadphase implementation by Nathanael Presson
+
+#include "b3DynamicBvhBroadphase.h"
+#include "b3OverlappingPair.h"
+
+//
+// Profiling
+//
+
+#if B3_DBVT_BP_PROFILE || B3_DBVT_BP_ENABLE_BENCHMARK
+#include <stdio.h>
+#endif
+
+#if B3_DBVT_BP_PROFILE
+struct b3ProfileScope
+{
+       __forceinline b3ProfileScope(b3Clock& clock, unsigned long& value) : m_clock(&clock), m_value(&value), m_base(clock.getTimeMicroseconds())
+       {
+       }
+       __forceinline ~b3ProfileScope()
+       {
+               (*m_value) += m_clock->getTimeMicroseconds() - m_base;
+       }
+       b3Clock* m_clock;
+       unsigned long* m_value;
+       unsigned long m_base;
+};
+#define b3SPC(_value_) b3ProfileScope spc_scope(m_clock, _value_)
+#else
+#define b3SPC(_value_)
+#endif
+
+//
+// Helpers
+//
+
+//
+template <typename T>
+static inline void b3ListAppend(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 b3ListRemove(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 b3ListCount(T* root)
+{
+       int n = 0;
+       while (root)
+       {
+               ++n;
+               root = root->links[1];
+       }
+       return (n);
+}
+
+//
+template <typename T>
+static inline void b3Clear(T& value)
+{
+       static const struct ZeroDummy : T
+       {
+       } zerodummy;
+       value = zerodummy;
+}
+
+//
+// Colliders
+//
+
+/* Tree collider       */
+struct b3DbvtTreeCollider : b3DynamicBvh::ICollide
+{
+       b3DynamicBvhBroadphase* pbp;
+       b3DbvtProxy* proxy;
+       b3DbvtTreeCollider(b3DynamicBvhBroadphase* p) : pbp(p) {}
+       void Process(const b3DbvtNode* na, const b3DbvtNode* nb)
+       {
+               if (na != nb)
+               {
+                       b3DbvtProxy* pa = (b3DbvtProxy*)na->data;
+                       b3DbvtProxy* pb = (b3DbvtProxy*)nb->data;
+#if B3_DBVT_BP_SORTPAIRS
+                       if (pa->m_uniqueId > pb->m_uniqueId)
+                               b3Swap(pa, pb);
+#endif
+                       pbp->m_paircache->addOverlappingPair(pa->getUid(), pb->getUid());
+                       ++pbp->m_newpairs;
+               }
+       }
+       void Process(const b3DbvtNode* n)
+       {
+               Process(n, proxy->leaf);
+       }
+};
+
+//
+// b3DynamicBvhBroadphase
+//
+
+//
+b3DynamicBvhBroadphase::b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache)
+{
+       m_deferedcollide = false;
+       m_needcleanup = true;
+       m_releasepaircache = (paircache != 0) ? false : true;
+       m_prediction = 0;
+       m_stageCurrent = 0;
+       m_fixedleft = 0;
+       m_fupdates = 1;
+       m_dupdates = 0;
+       m_cupdates = 10;
+       m_newpairs = 1;
+       m_updates_call = 0;
+       m_updates_done = 0;
+       m_updates_ratio = 0;
+       m_paircache = paircache ? paircache : new (b3AlignedAlloc(sizeof(b3HashedOverlappingPairCache), 16)) b3HashedOverlappingPairCache();
+
+       m_pid = 0;
+       m_cid = 0;
+       for (int i = 0; i <= STAGECOUNT; ++i)
+       {
+               m_stageRoots[i] = 0;
+       }
+#if B3_DBVT_BP_PROFILE
+       b3Clear(m_profiling);
+#endif
+       m_proxies.resize(proxyCapacity);
+}
+
+//
+b3DynamicBvhBroadphase::~b3DynamicBvhBroadphase()
+{
+       if (m_releasepaircache)
+       {
+               m_paircache->~b3OverlappingPairCache();
+               b3AlignedFree(m_paircache);
+       }
+}
+
+//
+b3BroadphaseProxy* b3DynamicBvhBroadphase::createProxy(const b3Vector3& aabbMin,
+                                                                                                          const b3Vector3& aabbMax,
+                                                                                                          int objectId,
+                                                                                                          void* userPtr,
+                                                                                                          int collisionFilterGroup,
+                                                                                                          int collisionFilterMask)
+{
+       b3DbvtProxy* mem = &m_proxies[objectId];
+       b3DbvtProxy* proxy = new (mem) b3DbvtProxy(aabbMin, aabbMax, userPtr,
+                                                                                          collisionFilterGroup,
+                                                                                          collisionFilterMask);
+
+       b3DbvtAabbMm aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
+
+       //bproxy->aabb                  =       b3DbvtVolume::FromMM(aabbMin,aabbMax);
+       proxy->stage = m_stageCurrent;
+       proxy->m_uniqueId = objectId;
+       proxy->leaf = m_sets[0].insert(aabb, proxy);
+       b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
+       if (!m_deferedcollide)
+       {
+               b3DbvtTreeCollider collider(this);
+               collider.proxy = proxy;
+               m_sets[0].collideTV(m_sets[0].m_root, aabb, collider);
+               m_sets[1].collideTV(m_sets[1].m_root, aabb, collider);
+       }
+       return (proxy);
+}
+
+//
+void b3DynamicBvhBroadphase::destroyProxy(b3BroadphaseProxy* absproxy,
+                                                                                 b3Dispatcher* dispatcher)
+{
+       b3DbvtProxy* proxy = (b3DbvtProxy*)absproxy;
+       if (proxy->stage == STAGECOUNT)
+               m_sets[1].remove(proxy->leaf);
+       else
+               m_sets[0].remove(proxy->leaf);
+       b3ListRemove(proxy, m_stageRoots[proxy->stage]);
+       m_paircache->removeOverlappingPairsContainingProxy(proxy->getUid(), dispatcher);
+
+       m_needcleanup = true;
+}
+
+void b3DynamicBvhBroadphase::getAabb(int objectId, b3Vector3& aabbMin, b3Vector3& aabbMax) const
+{
+       const b3DbvtProxy* proxy = &m_proxies[objectId];
+       aabbMin = proxy->m_aabbMin;
+       aabbMax = proxy->m_aabbMax;
+}
+/*
+void   b3DynamicBvhBroadphase::getAabb(b3BroadphaseProxy* absproxy,b3Vector3& aabbMin, b3Vector3& aabbMax ) const
+{
+       b3DbvtProxy*                                            proxy=(b3DbvtProxy*)absproxy;
+       aabbMin = proxy->m_aabbMin;
+       aabbMax = proxy->m_aabbMax;
+}
+*/
+
+struct BroadphaseRayTester : b3DynamicBvh::ICollide
+{
+       b3BroadphaseRayCallback& m_rayCallback;
+       BroadphaseRayTester(b3BroadphaseRayCallback& orgCallback)
+               : m_rayCallback(orgCallback)
+       {
+       }
+       void Process(const b3DbvtNode* leaf)
+       {
+               b3DbvtProxy* proxy = (b3DbvtProxy*)leaf->data;
+               m_rayCallback.process(proxy);
+       }
+};
+
+void b3DynamicBvhBroadphase::rayTest(const b3Vector3& rayFrom, const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
+{
+       BroadphaseRayTester callback(rayCallback);
+
+       m_sets[0].rayTestInternal(m_sets[0].m_root,
+                                                         rayFrom,
+                                                         rayTo,
+                                                         rayCallback.m_rayDirectionInverse,
+                                                         rayCallback.m_signs,
+                                                         rayCallback.m_lambda_max,
+                                                         aabbMin,
+                                                         aabbMax,
+                                                         callback);
+
+       m_sets[1].rayTestInternal(m_sets[1].m_root,
+                                                         rayFrom,
+                                                         rayTo,
+                                                         rayCallback.m_rayDirectionInverse,
+                                                         rayCallback.m_signs,
+                                                         rayCallback.m_lambda_max,
+                                                         aabbMin,
+                                                         aabbMax,
+                                                         callback);
+}
+
+struct BroadphaseAabbTester : b3DynamicBvh::ICollide
+{
+       b3BroadphaseAabbCallback& m_aabbCallback;
+       BroadphaseAabbTester(b3BroadphaseAabbCallback& orgCallback)
+               : m_aabbCallback(orgCallback)
+       {
+       }
+       void Process(const b3DbvtNode* leaf)
+       {
+               b3DbvtProxy* proxy = (b3DbvtProxy*)leaf->data;
+               m_aabbCallback.process(proxy);
+       }
+};
+
+void b3DynamicBvhBroadphase::aabbTest(const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3BroadphaseAabbCallback& aabbCallback)
+{
+       BroadphaseAabbTester callback(aabbCallback);
+
+       const B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) bounds = b3DbvtVolume::FromMM(aabbMin, aabbMax);
+       //process all children, that overlap with  the given AABB bounds
+       m_sets[0].collideTV(m_sets[0].m_root, bounds, callback);
+       m_sets[1].collideTV(m_sets[1].m_root, bounds, callback);
+}
+
+//
+void b3DynamicBvhBroadphase::setAabb(int objectId,
+                                                                        const b3Vector3& aabbMin,
+                                                                        const b3Vector3& aabbMax,
+                                                                        b3Dispatcher* /*dispatcher*/)
+{
+       b3DbvtProxy* proxy = &m_proxies[objectId];
+       //      b3DbvtProxy*                                            proxy=(b3DbvtProxy*)absproxy;
+       B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
+       aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
+#if B3_DBVT_BP_PREVENTFALSEUPDATE
+       if (b3NotEqual(aabb, proxy->leaf->volume))
+#endif
+       {
+               bool docollide = false;
+               if (proxy->stage == STAGECOUNT)
+               { /* fixed -> dynamic set       */
+                       m_sets[1].remove(proxy->leaf);
+                       proxy->leaf = m_sets[0].insert(aabb, proxy);
+                       docollide = true;
+               }
+               else
+               { /* dynamic set                                */
+                       ++m_updates_call;
+                       if (b3Intersect(proxy->leaf->volume, aabb))
+                       { /* Moving                             */
+
+                               const b3Vector3 delta = aabbMin - proxy->m_aabbMin;
+                               b3Vector3 velocity(((proxy->m_aabbMax - proxy->m_aabbMin) / 2) * m_prediction);
+                               if (delta[0] < 0) velocity[0] = -velocity[0];
+                               if (delta[1] < 0) velocity[1] = -velocity[1];
+                               if (delta[2] < 0) velocity[2] = -velocity[2];
+                               if (
+#ifdef B3_DBVT_BP_MARGIN
+                                       m_sets[0].update(proxy->leaf, aabb, velocity, B3_DBVT_BP_MARGIN)
+#else
+                                       m_sets[0].update(proxy->leaf, aabb, velocity)
+#endif
+                               )
+                               {
+                                       ++m_updates_done;
+                                       docollide = true;
+                               }
+                       }
+                       else
+                       { /* Teleporting                        */
+                               m_sets[0].update(proxy->leaf, aabb);
+                               ++m_updates_done;
+                               docollide = true;
+                       }
+               }
+               b3ListRemove(proxy, m_stageRoots[proxy->stage]);
+               proxy->m_aabbMin = aabbMin;
+               proxy->m_aabbMax = aabbMax;
+               proxy->stage = m_stageCurrent;
+               b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
+               if (docollide)
+               {
+                       m_needcleanup = true;
+                       if (!m_deferedcollide)
+                       {
+                               b3DbvtTreeCollider collider(this);
+                               m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
+                               m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
+                       }
+               }
+       }
+}
+
+//
+void b3DynamicBvhBroadphase::setAabbForceUpdate(b3BroadphaseProxy* absproxy,
+                                                                                               const b3Vector3& aabbMin,
+                                                                                               const b3Vector3& aabbMax,
+                                                                                               b3Dispatcher* /*dispatcher*/)
+{
+       b3DbvtProxy* proxy = (b3DbvtProxy*)absproxy;
+       B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
+       aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
+       bool docollide = false;
+       if (proxy->stage == STAGECOUNT)
+       { /* fixed -> dynamic set       */
+               m_sets[1].remove(proxy->leaf);
+               proxy->leaf = m_sets[0].insert(aabb, proxy);
+               docollide = true;
+       }
+       else
+       { /* dynamic set                                */
+               ++m_updates_call;
+               /* Teleporting                  */
+               m_sets[0].update(proxy->leaf, aabb);
+               ++m_updates_done;
+               docollide = true;
+       }
+       b3ListRemove(proxy, m_stageRoots[proxy->stage]);
+       proxy->m_aabbMin = aabbMin;
+       proxy->m_aabbMax = aabbMax;
+       proxy->stage = m_stageCurrent;
+       b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
+       if (docollide)
+       {
+               m_needcleanup = true;
+               if (!m_deferedcollide)
+               {
+                       b3DbvtTreeCollider collider(this);
+                       m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
+                       m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
+               }
+       }
+}
+
+//
+void b3DynamicBvhBroadphase::calculateOverlappingPairs(b3Dispatcher* dispatcher)
+{
+       collide(dispatcher);
+#if B3_DBVT_BP_PROFILE
+       if (0 == (m_pid % B3_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 / B3_DBVT_BP_PROFILING_RATE);
+               printf("fdcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_fdcollide * 100) / total, m_profiling.m_fdcollide / B3_DBVT_BP_PROFILING_RATE);
+               printf("cleanup:   %u%% (%uus)\r\n", (50 + m_profiling.m_cleanup * 100) / total, m_profiling.m_cleanup / B3_DBVT_BP_PROFILING_RATE);
+               printf("total:     %uus\r\n", total / B3_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) / B3_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) * B3_DBVT_BP_PROFILING_RATE));
+               b3Clear(m_profiling);
+               m_clock.reset();
+       }
+#endif
+
+       performDeferredRemoval(dispatcher);
+}
+
+void b3DynamicBvhBroadphase::performDeferredRemoval(b3Dispatcher* dispatcher)
+{
+       if (m_paircache->hasDeferredRemoval())
+       {
+               b3BroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
+
+               //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+               overlappingPairArray.quickSort(b3BroadphasePairSortPredicate());
+
+               int invalidPair = 0;
+
+               int i;
+
+               b3BroadphasePair previousPair = b3MakeBroadphasePair(-1, -1);
+
+               for (i = 0; i < overlappingPairArray.size(); i++)
+               {
+                       b3BroadphasePair& pair = overlappingPairArray[i];
+
+                       bool isDuplicate = (pair == previousPair);
+
+                       previousPair = pair;
+
+                       bool needsRemoval = false;
+
+                       if (!isDuplicate)
+                       {
+                               //important to perform AABB check that is consistent with the broadphase
+                               b3DbvtProxy* pa = &m_proxies[pair.x];
+                               b3DbvtProxy* pb = &m_proxies[pair.y];
+                               bool hasOverlap = b3Intersect(pa->leaf->volume, pb->leaf->volume);
+
+                               if (hasOverlap)
+                               {
+                                       needsRemoval = false;
+                               }
+                               else
+                               {
+                                       needsRemoval = true;
+                               }
+                       }
+                       else
+                       {
+                               //remove duplicate
+                               needsRemoval = true;
+                               //should have no algorithm
+                       }
+
+                       if (needsRemoval)
+                       {
+                               m_paircache->cleanOverlappingPair(pair, dispatcher);
+
+                               pair.x = -1;
+                               pair.y = -1;
+                               invalidPair++;
+                       }
+               }
+
+               //perform a sort, to sort 'invalid' pairs to the end
+               overlappingPairArray.quickSort(b3BroadphasePairSortPredicate());
+               overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
+       }
+}
+
+//
+void b3DynamicBvhBroadphase::collide(b3Dispatcher* dispatcher)
+{
+       /*printf("---------------------------------------------------------\n");
+       printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
+       printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
+       printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
+       {
+               int i;
+               for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
+               {
+                       printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
+                               getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
+               }
+               printf("\n");
+       }
+*/
+
+       b3SPC(m_profiling.m_total);
+       /* optimize                             */
+       m_sets[0].optimizeIncremental(1 + (m_sets[0].m_leaves * m_dupdates) / 100);
+       if (m_fixedleft)
+       {
+               const int count = 1 + (m_sets[1].m_leaves * m_fupdates) / 100;
+               m_sets[1].optimizeIncremental(1 + (m_sets[1].m_leaves * m_fupdates) / 100);
+               m_fixedleft = b3Max<int>(0, m_fixedleft - count);
+       }
+       /* dynamic -> fixed set */
+       m_stageCurrent = (m_stageCurrent + 1) % STAGECOUNT;
+       b3DbvtProxy* current = m_stageRoots[m_stageCurrent];
+       if (current)
+       {
+               b3DbvtTreeCollider collider(this);
+               do
+               {
+                       b3DbvtProxy* next = current->links[1];
+                       b3ListRemove(current, m_stageRoots[current->stage]);
+                       b3ListAppend(current, m_stageRoots[STAGECOUNT]);
+#if B3_DBVT_BP_ACCURATESLEEPING
+                       m_paircache->removeOverlappingPairsContainingProxy(current, dispatcher);
+                       collider.proxy = current;
+                       b3DynamicBvh::collideTV(m_sets[0].m_root, current->aabb, collider);
+                       b3DynamicBvh::collideTV(m_sets[1].m_root, current->aabb, collider);
+#endif
+                       m_sets[0].remove(current->leaf);
+                       B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
+                       curAabb = b3DbvtVolume::FromMM(current->m_aabbMin, current->m_aabbMax);
+                       current->leaf = m_sets[1].insert(curAabb, current);
+                       current->stage = STAGECOUNT;
+                       current = next;
+               } while (current);
+               m_fixedleft = m_sets[1].m_leaves;
+               m_needcleanup = true;
+       }
+       /* collide dynamics             */
+       {
+               b3DbvtTreeCollider collider(this);
+               if (m_deferedcollide)
+               {
+                       b3SPC(m_profiling.m_fdcollide);
+                       m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[1].m_root, collider);
+               }
+               if (m_deferedcollide)
+               {
+                       b3SPC(m_profiling.m_ddcollide);
+                       m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[0].m_root, collider);
+               }
+       }
+       /* clean up                             */
+       if (m_needcleanup)
+       {
+               b3SPC(m_profiling.m_cleanup);
+               b3BroadphasePairArray& pairs = m_paircache->getOverlappingPairArray();
+               if (pairs.size() > 0)
+               {
+                       int ni = b3Min(pairs.size(), b3Max<int>(m_newpairs, (pairs.size() * m_cupdates) / 100));
+                       for (int i = 0; i < ni; ++i)
+                       {
+                               b3BroadphasePair& p = pairs[(m_cid + i) % pairs.size()];
+                               b3DbvtProxy* pa = &m_proxies[p.x];
+                               b3DbvtProxy* pb = &m_proxies[p.y];
+                               if (!b3Intersect(pa->leaf->volume, pb->leaf->volume))
+                               {
+#if B3_DBVT_BP_SORTPAIRS
+                                       if (pa->m_uniqueId > pb->m_uniqueId)
+                                               b3Swap(pa, pb);
+#endif
+                                       m_paircache->removeOverlappingPair(pa->getUid(), pb->getUid(), dispatcher);
+                                       --ni;
+                                       --i;
+                               }
+                       }
+                       if (pairs.size() > 0)
+                               m_cid = (m_cid + ni) % pairs.size();
+                       else
+                               m_cid = 0;
+               }
+       }
+       ++m_pid;
+       m_newpairs = 1;
+       m_needcleanup = false;
+       if (m_updates_call > 0)
+       {
+               m_updates_ratio = m_updates_done / (b3Scalar)m_updates_call;
+       }
+       else
+       {
+               m_updates_ratio = 0;
+       }
+       m_updates_done /= 2;
+       m_updates_call /= 2;
+}
+
+//
+void b3DynamicBvhBroadphase::optimize()
+{
+       m_sets[0].optimizeTopDown();
+       m_sets[1].optimizeTopDown();
+}
+
+//
+b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache()
+{
+       return (m_paircache);
+}
+
+//
+const b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache() const
+{
+       return (m_paircache);
+}
+
+//
+void b3DynamicBvhBroadphase::getBroadphaseAabb(b3Vector3& aabbMin, b3Vector3& aabbMax) const
+{
+       B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
+       bounds;
+
+       if (!m_sets[0].empty())
+               if (!m_sets[1].empty())
+                       b3Merge(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 = b3DbvtVolume::FromCR(b3MakeVector3(0, 0, 0), 0);
+       aabbMin = bounds.Mins();
+       aabbMax = bounds.Maxs();
+}
+
+void b3DynamicBvhBroadphase::resetPool(b3Dispatcher* dispatcher)
+{
+       int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
+       if (!totalObjects)
+       {
+               //reset internal dynamic tree data structures
+               m_sets[0].clear();
+               m_sets[1].clear();
+
+               m_deferedcollide = false;
+               m_needcleanup = true;
+               m_stageCurrent = 0;
+               m_fixedleft = 0;
+               m_fupdates = 1;
+               m_dupdates = 0;
+               m_cupdates = 10;
+               m_newpairs = 1;
+               m_updates_call = 0;
+               m_updates_done = 0;
+               m_updates_ratio = 0;
+
+               m_pid = 0;
+               m_cid = 0;
+               for (int i = 0; i <= STAGECOUNT; ++i)
+               {
+                       m_stageRoots[i] = 0;
+               }
+       }
+}
+
+//
+void b3DynamicBvhBroadphase::printStats()
+{
+}
+
+//
+#if B3_DBVT_BP_ENABLE_BENCHMARK
+
+struct b3BroadphaseBenchmark
+{
+       struct Experiment
+       {
+               const char* name;
+               int object_count;
+               int update_count;
+               int spawn_count;
+               int iterations;
+               b3Scalar speed;
+               b3Scalar amplitude;
+       };
+       struct Object
+       {
+               b3Vector3 center;
+               b3Vector3 extents;
+               b3BroadphaseProxy* proxy;
+               b3Scalar time;
+               void update(b3Scalar speed, b3Scalar amplitude, b3BroadphaseInterface* pbi)
+               {
+                       time += speed;
+                       center[0] = b3Cos(time * (b3Scalar)2.17) * amplitude +
+                                               b3Sin(time) * amplitude / 2;
+                       center[1] = b3Cos(time * (b3Scalar)1.38) * amplitude +
+                                               b3Sin(time) * amplitude;
+                       center[2] = b3Sin(time * (b3Scalar)0.777) * amplitude;
+                       pbi->setAabb(proxy, center - extents, center + extents, 0);
+               }
+       };
+       static int UnsignedRand(int range = RAND_MAX - 1) { return (rand() % (range + 1)); }
+       static b3Scalar UnitRand() { return (UnsignedRand(16384) / (b3Scalar)16384); }
+       static void OutputTime(const char* name, b3Clock& c, unsigned count = 0)
+       {
+               const unsigned long us = c.getTimeMicroseconds();
+               const unsigned long ms = (us + 500) / 1000;
+               const b3Scalar sec = us / (b3Scalar)(1000 * 1000);
+               if (count > 0)
+                       printf("%s : %u us (%u ms), %.2f/s\r\n", name, us, ms, count / sec);
+               else
+                       printf("%s : %u us (%u ms)\r\n", name, us, ms);
+       }
+};
+
+void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface* pbi)
+{
+       static const b3BroadphaseBenchmark::Experiment experiments[] =
+               {
+                       {"1024o.10%", 1024, 10, 0, 8192, (b3Scalar)0.005, (b3Scalar)100},
+                       /*{"4096o.10%",4096,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},
+               {"8192o.10%",8192,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},*/
+               };
+       static const int nexperiments = sizeof(experiments) / sizeof(experiments[0]);
+       b3AlignedObjectArray<b3BroadphaseBenchmark::Object*> objects;
+       b3Clock wallclock;
+       /* Begin                        */
+       for (int iexp = 0; iexp < nexperiments; ++iexp)
+       {
+               const b3BroadphaseBenchmark::Experiment& experiment = experiments[iexp];
+               const int object_count = experiment.object_count;
+               const int update_count = (object_count * experiment.update_count) / 100;
+               const int spawn_count = (object_count * experiment.spawn_count) / 100;
+               const b3Scalar speed = experiment.speed;
+               const b3Scalar amplitude = experiment.amplitude;
+               printf("Experiment #%u '%s':\r\n", iexp, experiment.name);
+               printf("\tObjects: %u\r\n", object_count);
+               printf("\tUpdate: %u\r\n", update_count);
+               printf("\tSpawn: %u\r\n", spawn_count);
+               printf("\tSpeed: %f\r\n", speed);
+               printf("\tAmplitude: %f\r\n", amplitude);
+               srand(180673);
+               /* Create objects       */
+               wallclock.reset();
+               objects.reserve(object_count);
+               for (int i = 0; i < object_count; ++i)
+               {
+                       b3BroadphaseBenchmark::Object* po = new b3BroadphaseBenchmark::Object();
+                       po->center[0] = b3BroadphaseBenchmark::UnitRand() * 50;
+                       po->center[1] = b3BroadphaseBenchmark::UnitRand() * 50;
+                       po->center[2] = b3BroadphaseBenchmark::UnitRand() * 50;
+                       po->extents[0] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
+                       po->extents[1] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
+                       po->extents[2] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
+                       po->time = b3BroadphaseBenchmark::UnitRand() * 2000;
+                       po->proxy = pbi->createProxy(po->center - po->extents, po->center + po->extents, 0, po, 1, 1, 0, 0);
+                       objects.push_back(po);
+               }
+               b3BroadphaseBenchmark::OutputTime("\tInitialization", wallclock);
+               /* First update         */
+               wallclock.reset();
+               for (int i = 0; i < objects.size(); ++i)
+               {
+                       objects[i]->update(speed, amplitude, pbi);
+               }
+               b3BroadphaseBenchmark::OutputTime("\tFirst update", wallclock);
+               /* Updates                      */
+               wallclock.reset();
+               for (int i = 0; i < experiment.iterations; ++i)
+               {
+                       for (int j = 0; j < update_count; ++j)
+                       {
+                               objects[j]->update(speed, amplitude, pbi);
+                       }
+                       pbi->calculateOverlappingPairs(0);
+               }
+               b3BroadphaseBenchmark::OutputTime("\tUpdate", wallclock, experiment.iterations);
+               /* Clean up                     */
+               wallclock.reset();
+               for (int i = 0; i < objects.size(); ++i)
+               {
+                       pbi->destroyProxy(objects[i]->proxy, 0);
+                       delete objects[i];
+               }
+               objects.resize(0);
+               b3BroadphaseBenchmark::OutputTime("\tRelease", wallclock);
+       }
+}
+#else
+/*void                                                 b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface*)
+{}
+*/
+#endif
+
+#if B3_DBVT_BP_PROFILE
+#undef b3SPC
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h
new file mode 100644 (file)
index 0000000..c235e40
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///b3DynamicBvhBroadphase implementation by Nathanael Presson
+#ifndef B3_DBVT_BROADPHASE_H
+#define B3_DBVT_BROADPHASE_H
+
+#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h"
+#include "Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+#include "b3BroadphaseCallback.h"
+
+//
+// Compile time config
+//
+
+#define B3_DBVT_BP_PROFILE 0
+//#define B3_DBVT_BP_SORTPAIRS                         1
+#define B3_DBVT_BP_PREVENTFALSEUPDATE 0
+#define B3_DBVT_BP_ACCURATESLEEPING 0
+#define B3_DBVT_BP_ENABLE_BENCHMARK 0
+#define B3_DBVT_BP_MARGIN (b3Scalar)0.05
+
+#if B3_DBVT_BP_PROFILE
+#define B3_DBVT_BP_PROFILING_RATE 256
+
+#endif
+
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3BroadphaseProxy
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       ///optional filtering to cull potential collisions
+       enum CollisionFilterGroups
+       {
+               DefaultFilter = 1,
+               StaticFilter = 2,
+               KinematicFilter = 4,
+               DebrisFilter = 8,
+               SensorTrigger = 16,
+               CharacterFilter = 32,
+               AllFilter = -1  //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+       };
+
+       //Usually the client b3CollisionObject or Rigidbody class
+       void* m_clientObject;
+       int m_collisionFilterGroup;
+       int m_collisionFilterMask;
+       int m_uniqueId;  //m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+
+       b3Vector3 m_aabbMin;
+       b3Vector3 m_aabbMax;
+
+       B3_FORCE_INLINE int getUid() const
+       {
+               return m_uniqueId;
+       }
+
+       //used for memory pools
+       b3BroadphaseProxy() : m_clientObject(0)
+       {
+       }
+
+       b3BroadphaseProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
+               : m_clientObject(userPtr),
+                 m_collisionFilterGroup(collisionFilterGroup),
+                 m_collisionFilterMask(collisionFilterMask),
+                 m_aabbMin(aabbMin),
+                 m_aabbMax(aabbMax)
+       {
+       }
+};
+
+//
+// b3DbvtProxy
+//
+struct b3DbvtProxy : b3BroadphaseProxy
+{
+       /* Fields               */
+       //b3DbvtAabbMm  aabb;
+       b3DbvtNode* leaf;
+       b3DbvtProxy* links[2];
+       int stage;
+       /* ctor                 */
+
+       explicit b3DbvtProxy() {}
+       b3DbvtProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask) : b3BroadphaseProxy(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask)
+       {
+               links[0] = links[1] = 0;
+       }
+};
+
+typedef b3AlignedObjectArray<b3DbvtProxy*> b3DbvtProxyArray;
+
+///The b3DynamicBvhBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see b3DynamicBvh).
+///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 b3AxisSweep3 and b332BitAxisSweep3.
+struct b3DynamicBvhBroadphase
+{
+       /* Config               */
+       enum
+       {
+               DYNAMIC_SET = 0, /* Dynamic set index   */
+               FIXED_SET = 1,   /* Fixed set index             */
+               STAGECOUNT = 2   /* Number of stages            */
+       };
+       /* Fields               */
+       b3DynamicBvh m_sets[2];                     // Dbvt sets
+       b3DbvtProxy* m_stageRoots[STAGECOUNT + 1];  // Stages list
+
+       b3AlignedObjectArray<b3DbvtProxy> m_proxies;
+       b3OverlappingPairCache* m_paircache;  // Pair cache
+       b3Scalar m_prediction;                // Velocity prediction
+       int m_stageCurrent;                   // Current stage
+       int m_fupdates;                       // % of fixed updates per frame
+       int m_dupdates;                       // % of dynamic updates per frame
+       int m_cupdates;                       // % of cleanup updates per frame
+       int m_newpairs;                       // Number of pairs created
+       int m_fixedleft;                      // Fixed optimization left
+       unsigned m_updates_call;              // Number of updates call
+       unsigned m_updates_done;              // Number of updates done
+       b3Scalar m_updates_ratio;             // m_updates_done/m_updates_call
+       int m_pid;                            // Parse id
+       int m_cid;                            // Cleanup index
+       bool m_releasepaircache;              // Release pair cache on delete
+       bool m_deferedcollide;                // Defere dynamic/static collision to collide call
+       bool m_needcleanup;                   // Need to run cleanup?
+#if B3_DBVT_BP_PROFILE
+       b3Clock 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              */
+       b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache = 0);
+       virtual ~b3DynamicBvhBroadphase();
+       void collide(b3Dispatcher* dispatcher);
+       void optimize();
+
+       /* b3BroadphaseInterface Implementation */
+       b3BroadphaseProxy* createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int objectIndex, void* userPtr, int collisionFilterGroup, int collisionFilterMask);
+       virtual void destroyProxy(b3BroadphaseProxy* proxy, b3Dispatcher* dispatcher);
+       virtual void setAabb(int objectId, const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3Dispatcher* dispatcher);
+       virtual void rayTest(const b3Vector3& rayFrom, const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback, const b3Vector3& aabbMin = b3MakeVector3(0, 0, 0), const b3Vector3& aabbMax = b3MakeVector3(0, 0, 0));
+       virtual void aabbTest(const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3BroadphaseAabbCallback& callback);
+
+       //virtual void                                  getAabb(b3BroadphaseProxy* proxy,b3Vector3& aabbMin, b3Vector3& aabbMax ) const;
+       virtual void getAabb(int objectId, b3Vector3& aabbMin, b3Vector3& aabbMax) const;
+       virtual void calculateOverlappingPairs(b3Dispatcher* dispatcher = 0);
+       virtual b3OverlappingPairCache* getOverlappingPairCache();
+       virtual const b3OverlappingPairCache* getOverlappingPairCache() const;
+       virtual void getBroadphaseAabb(b3Vector3& aabbMin, b3Vector3& aabbMax) const;
+       virtual void printStats();
+
+       ///reset broadphase internal structures, to ensure determinism/reproducability
+       virtual void resetPool(b3Dispatcher* dispatcher);
+
+       void performDeferredRemoval(b3Dispatcher* dispatcher);
+
+       void setVelocityPrediction(b3Scalar prediction)
+       {
+               m_prediction = prediction;
+       }
+       b3Scalar getVelocityPrediction() const
+       {
+               return m_prediction;
+       }
+
+       ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
+       ///it is not part of the b3BroadphaseInterface but specific to b3DynamicBvhBroadphase.
+       ///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
+       ///http://code.google.com/p/bullet/issues/detail?id=223
+       void setAabbForceUpdate(b3BroadphaseProxy* absproxy, const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3Dispatcher* /*dispatcher*/);
+
+       //static void                                           benchmark(b3BroadphaseInterface*);
+};
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h
new file mode 100644 (file)
index 0000000..4ff9eba
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_OVERLAPPING_PAIR_H
+#define B3_OVERLAPPING_PAIR_H
+
+#include "Bullet3Common/shared/b3Int4.h"
+
+#define B3_NEW_PAIR_MARKER -1
+#define B3_REMOVED_PAIR_MARKER -2
+
+typedef b3Int4 b3BroadphasePair;
+
+inline b3Int4 b3MakeBroadphasePair(int xx, int yy)
+{
+       b3Int4 pair;
+
+       if (xx < yy)
+       {
+               pair.x = xx;
+               pair.y = yy;
+       }
+       else
+       {
+               pair.x = yy;
+               pair.y = xx;
+       }
+       pair.z = B3_NEW_PAIR_MARKER;
+       pair.w = B3_NEW_PAIR_MARKER;
+       return pair;
+}
+
+/*struct b3BroadphasePair : public b3Int4
+{
+       explicit b3BroadphasePair(){}
+       
+};
+*/
+
+class b3BroadphasePairSortPredicate
+{
+public:
+       bool operator()(const b3BroadphasePair& a, const b3BroadphasePair& b) const
+       {
+               const int uidA0 = a.x;
+               const int uidB0 = b.x;
+               const int uidA1 = a.y;
+               const int uidB1 = b.y;
+               return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
+       }
+};
+
+B3_FORCE_INLINE bool operator==(const b3BroadphasePair& a, const b3BroadphasePair& b)
+{
+       return (a.x == b.x) && (a.y == b.y);
+}
+
+#endif  //B3_OVERLAPPING_PAIR_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp b/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp
new file mode 100644 (file)
index 0000000..1977324
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3OverlappingPairCache.h"
+
+//#include "b3Dispatcher.h"
+//#include "b3CollisionAlgorithm.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+#include <stdio.h>
+
+int b3g_overlappingPairs = 0;
+int b3g_removePairs = 0;
+int b3g_addedPairs = 0;
+int b3g_findPairs = 0;
+
+b3HashedOverlappingPairCache::b3HashedOverlappingPairCache() : m_overlapFilterCallback(0)
+//,    m_blockedForChanges(false)
+{
+       int initialAllocatedSize = 2;
+       m_overlappingPairArray.reserve(initialAllocatedSize);
+       growTables();
+}
+
+b3HashedOverlappingPairCache::~b3HashedOverlappingPairCache()
+{
+}
+
+void b3HashedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher)
+{
+       /*      if (pair.m_algorithm)
+       {
+               {
+                       pair.m_algorithm->~b3CollisionAlgorithm();
+                       dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+                       pair.m_algorithm=0;
+               }
+       }
+       */
+}
+
+void b3HashedOverlappingPairCache::cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher)
+{
+       class CleanPairCallback : public b3OverlapCallback
+       {
+               int m_cleanProxy;
+               b3OverlappingPairCache* m_pairCache;
+               b3Dispatcher* m_dispatcher;
+
+       public:
+               CleanPairCallback(int cleanProxy, b3OverlappingPairCache* pairCache, b3Dispatcher* dispatcher)
+                       : m_cleanProxy(cleanProxy),
+                         m_pairCache(pairCache),
+                         m_dispatcher(dispatcher)
+               {
+               }
+               virtual bool processOverlap(b3BroadphasePair& pair)
+               {
+                       if ((pair.x == m_cleanProxy) ||
+                               (pair.y == m_cleanProxy))
+                       {
+                               m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
+                       }
+                       return false;
+               }
+       };
+
+       CleanPairCallback cleanPairs(proxy, this, dispatcher);
+
+       processAllOverlappingPairs(&cleanPairs, dispatcher);
+}
+
+void b3HashedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher)
+{
+       class RemovePairCallback : public b3OverlapCallback
+       {
+               int m_obsoleteProxy;
+
+       public:
+               RemovePairCallback(int obsoleteProxy)
+                       : m_obsoleteProxy(obsoleteProxy)
+               {
+               }
+               virtual bool processOverlap(b3BroadphasePair& pair)
+               {
+                       return ((pair.x == m_obsoleteProxy) ||
+                                       (pair.y == m_obsoleteProxy));
+               }
+       };
+
+       RemovePairCallback removeCallback(proxy);
+
+       processAllOverlappingPairs(&removeCallback, dispatcher);
+}
+
+b3BroadphasePair* b3HashedOverlappingPairCache::findPair(int proxy0, int proxy1)
+{
+       b3g_findPairs++;
+       if (proxy0 > proxy1)
+               b3Swap(proxy0, proxy1);
+       int proxyId1 = proxy0;
+       int proxyId2 = proxy1;
+
+       /*if (proxyId1 > proxyId2) 
+               b3Swap(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 != B3_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+       {
+               index = m_next[index];
+       }
+
+       if (index == B3_NULL_PAIR)
+       {
+               return NULL;
+       }
+
+       b3Assert(index < m_overlappingPairArray.size());
+
+       return &m_overlappingPairArray[index];
+}
+
+//#include <stdio.h>
+
+void b3HashedOverlappingPairCache::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] = B3_NULL_PAIR;
+               }
+               for (i = 0; i < newCapacity; ++i)
+               {
+                       m_next[i] = B3_NULL_PAIR;
+               }
+
+               for (i = 0; i < curHashtableSize; i++)
+               {
+                       const b3BroadphasePair& pair = m_overlappingPairArray[i];
+                       int proxyId1 = pair.x;
+                       int proxyId2 = pair.y;
+                       /*if (proxyId1 > proxyId2) 
+                               b3Swap(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;
+               }
+       }
+}
+
+b3BroadphasePair* b3HashedOverlappingPairCache::internalAddPair(int proxy0, int proxy1)
+{
+       if (proxy0 > proxy1)
+               b3Swap(proxy0, proxy1);
+       int proxyId1 = proxy0;
+       int proxyId2 = proxy1;
+
+       /*if (proxyId1 > proxyId2) 
+               b3Swap(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
+
+       b3BroadphasePair* 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();
+       pair = &m_overlappingPairArray.expandNonInitializing();
+
+       //this is where we add an actual pair, so also call the 'ghost'
+       //      if (m_ghostPairCallback)
+       //              m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
+
+       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 = b3MakeBroadphasePair(proxy0, proxy1);
+
+       //      pair->m_pProxy0 = proxy0;
+       //      pair->m_pProxy1 = proxy1;
+       //pair->m_algorithm = 0;
+       //pair->m_internalTmpValue = 0;
+
+       m_next[count] = m_hashTable[hash];
+       m_hashTable[hash] = count;
+
+       return pair;
+}
+
+void* b3HashedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher)
+{
+       b3g_removePairs++;
+       if (proxy0 > proxy1)
+               b3Swap(proxy0, proxy1);
+       int proxyId1 = proxy0;
+       int proxyId2 = proxy1;
+
+       /*if (proxyId1 > proxyId2) 
+               b3Swap(proxyId1, proxyId2);*/
+
+       int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
+
+       b3BroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+       if (pair == NULL)
+       {
+               return 0;
+       }
+
+       cleanOverlappingPair(*pair, dispatcher);
+
+       int pairIndex = int(pair - &m_overlappingPairArray[0]);
+       b3Assert(pairIndex < m_overlappingPairArray.size());
+
+       // Remove the pair from the hash table.
+       int index = m_hashTable[hash];
+       b3Assert(index != B3_NULL_PAIR);
+
+       int previous = B3_NULL_PAIR;
+       while (index != pairIndex)
+       {
+               previous = index;
+               index = m_next[index];
+       }
+
+       if (previous != B3_NULL_PAIR)
+       {
+               b3Assert(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 (m_ghostPairCallback)
+       //      m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+
+       // If the removed pair is the last pair, we are done.
+       if (lastPairIndex == pairIndex)
+       {
+               m_overlappingPairArray.pop_back();
+               return 0;
+       }
+
+       // Remove the last pair from the hash table.
+       const b3BroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
+       /* missing swap here too, Nat. */
+       int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->x), static_cast<unsigned int>(last->y)) & (m_overlappingPairArray.capacity() - 1));
+
+       index = m_hashTable[lastHash];
+       b3Assert(index != B3_NULL_PAIR);
+
+       previous = B3_NULL_PAIR;
+       while (index != lastPairIndex)
+       {
+               previous = index;
+               index = m_next[index];
+       }
+
+       if (previous != B3_NULL_PAIR)
+       {
+               b3Assert(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 0;
+}
+//#include <stdio.h>
+
+void b3HashedOverlappingPairCache::processAllOverlappingPairs(b3OverlapCallback* callback, b3Dispatcher* dispatcher)
+{
+       int i;
+
+       //      printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+       for (i = 0; i < m_overlappingPairArray.size();)
+       {
+               b3BroadphasePair* pair = &m_overlappingPairArray[i];
+               if (callback->processOverlap(*pair))
+               {
+                       removeOverlappingPair(pair->x, pair->y, dispatcher);
+
+                       b3g_overlappingPairs--;
+               }
+               else
+               {
+                       i++;
+               }
+       }
+}
+
+void b3HashedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher)
+{
+       ///need to keep hashmap in sync with pair address, so rebuild all
+       b3BroadphasePairArray tmpPairs;
+       int i;
+       for (i = 0; i < m_overlappingPairArray.size(); i++)
+       {
+               tmpPairs.push_back(m_overlappingPairArray[i]);
+       }
+
+       for (i = 0; i < tmpPairs.size(); i++)
+       {
+               removeOverlappingPair(tmpPairs[i].x, tmpPairs[i].y, dispatcher);
+       }
+
+       for (i = 0; i < m_next.size(); i++)
+       {
+               m_next[i] = B3_NULL_PAIR;
+       }
+
+       tmpPairs.quickSort(b3BroadphasePairSortPredicate());
+
+       for (i = 0; i < tmpPairs.size(); i++)
+       {
+               addOverlappingPair(tmpPairs[i].x, tmpPairs[i].y);
+       }
+}
+
+void* b3SortedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher)
+{
+       if (!hasDeferredRemoval())
+       {
+               b3BroadphasePair findPair = b3MakeBroadphasePair(proxy0, proxy1);
+
+               int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
+               if (findIndex < m_overlappingPairArray.size())
+               {
+                       b3g_overlappingPairs--;
+                       b3BroadphasePair& pair = m_overlappingPairArray[findIndex];
+
+                       cleanOverlappingPair(pair, dispatcher);
+                       //if (m_ghostPairCallback)
+                       //      m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+
+                       m_overlappingPairArray.swap(findIndex, m_overlappingPairArray.capacity() - 1);
+                       m_overlappingPairArray.pop_back();
+                       return 0;
+               }
+       }
+
+       return 0;
+}
+
+b3BroadphasePair* b3SortedOverlappingPairCache::addOverlappingPair(int proxy0, int proxy1)
+{
+       //don't add overlap with own
+       b3Assert(proxy0 != proxy1);
+
+       if (!needsBroadphaseCollision(proxy0, proxy1))
+               return 0;
+
+       b3BroadphasePair* pair = &m_overlappingPairArray.expandNonInitializing();
+       *pair = b3MakeBroadphasePair(proxy0, proxy1);
+
+       b3g_overlappingPairs++;
+       b3g_addedPairs++;
+
+       //      if (m_ghostPairCallback)
+       //              m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
+       return pair;
+}
+
+///this findPair becomes really slow. Either sort the list to speedup the query, or
+///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
+///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
+///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
+b3BroadphasePair* b3SortedOverlappingPairCache::findPair(int proxy0, int proxy1)
+{
+       if (!needsBroadphaseCollision(proxy0, proxy1))
+               return 0;
+
+       b3BroadphasePair tmpPair = b3MakeBroadphasePair(proxy0, proxy1);
+       int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
+
+       if (findIndex < m_overlappingPairArray.size())
+       {
+               //b3Assert(it != m_overlappingPairSet.end());
+               b3BroadphasePair* pair = &m_overlappingPairArray[findIndex];
+               return pair;
+       }
+       return 0;
+}
+
+//#include <stdio.h>
+
+void b3SortedOverlappingPairCache::processAllOverlappingPairs(b3OverlapCallback* callback, b3Dispatcher* dispatcher)
+{
+       int i;
+
+       for (i = 0; i < m_overlappingPairArray.size();)
+       {
+               b3BroadphasePair* pair = &m_overlappingPairArray[i];
+               if (callback->processOverlap(*pair))
+               {
+                       cleanOverlappingPair(*pair, dispatcher);
+                       pair->x = -1;
+                       pair->y = -1;
+                       m_overlappingPairArray.swap(i, m_overlappingPairArray.size() - 1);
+                       m_overlappingPairArray.pop_back();
+                       b3g_overlappingPairs--;
+               }
+               else
+               {
+                       i++;
+               }
+       }
+}
+
+b3SortedOverlappingPairCache::b3SortedOverlappingPairCache() : m_blockedForChanges(false),
+                                                                                                                          m_hasDeferredRemoval(true),
+                                                                                                                          m_overlapFilterCallback(0)
+
+{
+       int initialAllocatedSize = 2;
+       m_overlappingPairArray.reserve(initialAllocatedSize);
+}
+
+b3SortedOverlappingPairCache::~b3SortedOverlappingPairCache()
+{
+}
+
+void b3SortedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher)
+{
+       /*      if (pair.m_algorithm)
+       {
+               {
+                       pair.m_algorithm->~b3CollisionAlgorithm();
+                       dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+                       pair.m_algorithm=0;
+                       b3g_removePairs--;
+               }
+       }
+       */
+}
+
+void b3SortedOverlappingPairCache::cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher)
+{
+       class CleanPairCallback : public b3OverlapCallback
+       {
+               int m_cleanProxy;
+               b3OverlappingPairCache* m_pairCache;
+               b3Dispatcher* m_dispatcher;
+
+       public:
+               CleanPairCallback(int cleanProxy, b3OverlappingPairCache* pairCache, b3Dispatcher* dispatcher)
+                       : m_cleanProxy(cleanProxy),
+                         m_pairCache(pairCache),
+                         m_dispatcher(dispatcher)
+               {
+               }
+               virtual bool processOverlap(b3BroadphasePair& pair)
+               {
+                       if ((pair.x == m_cleanProxy) ||
+                               (pair.y == m_cleanProxy))
+                       {
+                               m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
+                       }
+                       return false;
+               }
+       };
+
+       CleanPairCallback cleanPairs(proxy, this, dispatcher);
+
+       processAllOverlappingPairs(&cleanPairs, dispatcher);
+}
+
+void b3SortedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher)
+{
+       class RemovePairCallback : public b3OverlapCallback
+       {
+               int m_obsoleteProxy;
+
+       public:
+               RemovePairCallback(int obsoleteProxy)
+                       : m_obsoleteProxy(obsoleteProxy)
+               {
+               }
+               virtual bool processOverlap(b3BroadphasePair& pair)
+               {
+                       return ((pair.x == m_obsoleteProxy) ||
+                                       (pair.y == m_obsoleteProxy));
+               }
+       };
+
+       RemovePairCallback removeCallback(proxy);
+
+       processAllOverlappingPairs(&removeCallback, dispatcher);
+}
+
+void b3SortedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher)
+{
+       //should already be sorted
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h
new file mode 100644 (file)
index 0000000..f1de1d9
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_OVERLAPPING_PAIR_CACHE_H
+#define B3_OVERLAPPING_PAIR_CACHE_H
+
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+class b3Dispatcher;
+#include "b3OverlappingPair.h"
+
+typedef b3AlignedObjectArray<b3BroadphasePair> b3BroadphasePairArray;
+
+struct b3OverlapCallback
+{
+       virtual ~b3OverlapCallback()
+       {
+       }
+       //return true for deletion of the pair
+       virtual bool processOverlap(b3BroadphasePair& pair) = 0;
+};
+
+struct b3OverlapFilterCallback
+{
+       virtual ~b3OverlapFilterCallback()
+       {
+       }
+       // return true when pairs need collision
+       virtual bool needBroadphaseCollision(int proxy0, int proxy1) const = 0;
+};
+
+extern int b3g_removePairs;
+extern int b3g_addedPairs;
+extern int b3g_findPairs;
+
+const int B3_NULL_PAIR = 0xffffffff;
+
+///The b3OverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the b3BroadphaseInterface broadphases.
+///The b3HashedOverlappingPairCache and b3SortedOverlappingPairCache classes are two implementations.
+class b3OverlappingPairCache
+{
+public:
+       virtual ~b3OverlappingPairCache() {}  // this is needed so we can get to the derived class destructor
+
+       virtual b3BroadphasePair* getOverlappingPairArrayPtr() = 0;
+
+       virtual const b3BroadphasePair* getOverlappingPairArrayPtr() const = 0;
+
+       virtual b3BroadphasePairArray& getOverlappingPairArray() = 0;
+
+       virtual void cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher) = 0;
+
+       virtual int getNumOverlappingPairs() const = 0;
+
+       virtual void cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher) = 0;
+
+       virtual void setOverlapFilterCallback(b3OverlapFilterCallback* callback) = 0;
+
+       virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* dispatcher) = 0;
+
+       virtual b3BroadphasePair* findPair(int proxy0, int proxy1) = 0;
+
+       virtual bool hasDeferredRemoval() = 0;
+
+       //virtual       void    setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)=0;
+
+       virtual b3BroadphasePair* addOverlappingPair(int proxy0, int proxy1) = 0;
+       virtual void* removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher) = 0;
+       virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/, b3Dispatcher* /*dispatcher*/) = 0;
+
+       virtual void sortOverlappingPairs(b3Dispatcher* dispatcher) = 0;
+};
+
+/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
+class b3HashedOverlappingPairCache : public b3OverlappingPairCache
+{
+       b3BroadphasePairArray m_overlappingPairArray;
+       b3OverlapFilterCallback* m_overlapFilterCallback;
+       //      bool            m_blockedForChanges;
+
+public:
+       b3HashedOverlappingPairCache();
+       virtual ~b3HashedOverlappingPairCache();
+
+       virtual void removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher);
+
+       virtual void* removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher);
+
+       B3_FORCE_INLINE bool needsBroadphaseCollision(int proxy0, int proxy1) const
+       {
+               if (m_overlapFilterCallback)
+                       return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
+
+               bool collides = true;  //(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 b3BroadphasePair* addOverlappingPair(int proxy0, int proxy1)
+       {
+               b3g_addedPairs++;
+
+               if (!needsBroadphaseCollision(proxy0, proxy1))
+                       return 0;
+
+               return internalAddPair(proxy0, proxy1);
+       }
+
+       void cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher);
+
+       virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* dispatcher);
+
+       virtual b3BroadphasePair* getOverlappingPairArrayPtr()
+       {
+               return &m_overlappingPairArray[0];
+       }
+
+       const b3BroadphasePair* getOverlappingPairArrayPtr() const
+       {
+               return &m_overlappingPairArray[0];
+       }
+
+       b3BroadphasePairArray& getOverlappingPairArray()
+       {
+               return m_overlappingPairArray;
+       }
+
+       const b3BroadphasePairArray& getOverlappingPairArray() const
+       {
+               return m_overlappingPairArray;
+       }
+
+       void cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher);
+
+       b3BroadphasePair* findPair(int proxy0, int proxy1);
+
+       int GetCount() const { return m_overlappingPairArray.size(); }
+       //      b3BroadphasePair* GetPairs() { return m_pairs; }
+
+       b3OverlapFilterCallback* getOverlapFilterCallback()
+       {
+               return m_overlapFilterCallback;
+       }
+
+       void setOverlapFilterCallback(b3OverlapFilterCallback* callback)
+       {
+               m_overlapFilterCallback = callback;
+       }
+
+       int getNumOverlappingPairs() const
+       {
+               return m_overlappingPairArray.size();
+       }
+
+private:
+       b3BroadphasePair* internalAddPair(int proxy0, int proxy1);
+
+       void growTables();
+
+       B3_FORCE_INLINE bool equalsPair(const b3BroadphasePair& pair, int proxyId1, int proxyId2)
+       {
+               return pair.x == proxyId1 && pair.y == proxyId2;
+       }
+
+       /*
+       // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
+       // This assumes proxyId1 and proxyId2 are 16-bit.
+       B3_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;
+       }
+       */
+
+       B3_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);
+       }
+
+       B3_FORCE_INLINE b3BroadphasePair* internalFindPair(int proxy0, int proxy1, int hash)
+       {
+               int proxyId1 = proxy0;
+               int proxyId2 = proxy1;
+#if 0  // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
+               if (proxyId1 > proxyId2) 
+                       b3Swap(proxyId1, proxyId2);
+#endif
+
+               int index = m_hashTable[hash];
+
+               while (index != B3_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+               {
+                       index = m_next[index];
+               }
+
+               if (index == B3_NULL_PAIR)
+               {
+                       return NULL;
+               }
+
+               b3Assert(index < m_overlappingPairArray.size());
+
+               return &m_overlappingPairArray[index];
+       }
+
+       virtual bool hasDeferredRemoval()
+       {
+               return false;
+       }
+
+       /*      virtual void    setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)
+       {
+               m_ghostPairCallback = ghostPairCallback;
+       }
+       */
+
+       virtual void sortOverlappingPairs(b3Dispatcher* dispatcher);
+
+protected:
+       b3AlignedObjectArray<int> m_hashTable;
+       b3AlignedObjectArray<int> m_next;
+       //      b3OverlappingPairCallback*      m_ghostPairCallback;
+};
+
+///b3SortedOverlappingPairCache maintains the objects with overlapping AABB
+///Typically managed by the Broadphase, Axis3Sweep or b3SimpleBroadphase
+class b3SortedOverlappingPairCache : public b3OverlappingPairCache
+{
+protected:
+       //avoid brute-force finding all the time
+       b3BroadphasePairArray 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
+       b3OverlapFilterCallback* m_overlapFilterCallback;
+
+       //              b3OverlappingPairCallback*      m_ghostPairCallback;
+
+public:
+       b3SortedOverlappingPairCache();
+       virtual ~b3SortedOverlappingPairCache();
+
+       virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* dispatcher);
+
+       void* removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher);
+
+       void cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher);
+
+       b3BroadphasePair* addOverlappingPair(int proxy0, int proxy1);
+
+       b3BroadphasePair* findPair(int proxy0, int proxy1);
+
+       void cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher);
+
+       virtual void removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher);
+
+       inline bool needsBroadphaseCollision(int proxy0, int proxy1) const
+       {
+               if (m_overlapFilterCallback)
+                       return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
+
+               bool collides = true;  //(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+               //collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+
+               return collides;
+       }
+
+       b3BroadphasePairArray& getOverlappingPairArray()
+       {
+               return m_overlappingPairArray;
+       }
+
+       const b3BroadphasePairArray& getOverlappingPairArray() const
+       {
+               return m_overlappingPairArray;
+       }
+
+       b3BroadphasePair* getOverlappingPairArrayPtr()
+       {
+               return &m_overlappingPairArray[0];
+       }
+
+       const b3BroadphasePair* getOverlappingPairArrayPtr() const
+       {
+               return &m_overlappingPairArray[0];
+       }
+
+       int getNumOverlappingPairs() const
+       {
+               return m_overlappingPairArray.size();
+       }
+
+       b3OverlapFilterCallback* getOverlapFilterCallback()
+       {
+               return m_overlapFilterCallback;
+       }
+
+       void setOverlapFilterCallback(b3OverlapFilterCallback* callback)
+       {
+               m_overlapFilterCallback = callback;
+       }
+
+       virtual bool hasDeferredRemoval()
+       {
+               return m_hasDeferredRemoval;
+       }
+
+       /*              virtual void    setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)
+               {
+                       m_ghostPairCallback = ghostPairCallback;
+               }
+               */
+       virtual void sortOverlappingPairs(b3Dispatcher* dispatcher);
+};
+
+///b3NullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
+class b3NullPairCache : public b3OverlappingPairCache
+{
+       b3BroadphasePairArray m_overlappingPairArray;
+
+public:
+       virtual b3BroadphasePair* getOverlappingPairArrayPtr()
+       {
+               return &m_overlappingPairArray[0];
+       }
+       const b3BroadphasePair* getOverlappingPairArrayPtr() const
+       {
+               return &m_overlappingPairArray[0];
+       }
+       b3BroadphasePairArray& getOverlappingPairArray()
+       {
+               return m_overlappingPairArray;
+       }
+
+       virtual void cleanOverlappingPair(b3BroadphasePair& /*pair*/, b3Dispatcher* /*dispatcher*/)
+       {
+       }
+
+       virtual int getNumOverlappingPairs() const
+       {
+               return 0;
+       }
+
+       virtual void cleanProxyFromPairs(int /*proxy*/, b3Dispatcher* /*dispatcher*/)
+       {
+       }
+
+       virtual void setOverlapFilterCallback(b3OverlapFilterCallback* /*callback*/)
+       {
+       }
+
+       virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* /*dispatcher*/)
+       {
+       }
+
+       virtual b3BroadphasePair* findPair(int /*proxy0*/, int /*proxy1*/)
+       {
+               return 0;
+       }
+
+       virtual bool hasDeferredRemoval()
+       {
+               return true;
+       }
+
+       //      virtual void    setInternalGhostPairCallback(b3OverlappingPairCallback* /* ghostPairCallback */)
+       //      {
+       //
+       //      }
+
+       virtual b3BroadphasePair* addOverlappingPair(int /*proxy0*/, int /*proxy1*/)
+       {
+               return 0;
+       }
+
+       virtual void* removeOverlappingPair(int /*proxy0*/, int /*proxy1*/, b3Dispatcher* /*dispatcher*/)
+       {
+               return 0;
+       }
+
+       virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/, b3Dispatcher* /*dispatcher*/)
+       {
+       }
+
+       virtual void sortOverlappingPairs(b3Dispatcher* dispatcher)
+       {
+               (void)dispatcher;
+       }
+};
+
+#endif  //B3_OVERLAPPING_PAIR_CACHE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h
new file mode 100644 (file)
index 0000000..343a2c0
--- /dev/null
@@ -0,0 +1,56 @@
+
+#ifndef B3_AABB_H
+#define B3_AABB_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Common/shared/b3Mat3x3.h"
+
+typedef struct b3Aabb b3Aabb_t;
+
+struct b3Aabb
+{
+       union {
+               float m_min[4];
+               b3Float4 m_minVec;
+               int m_minIndices[4];
+       };
+       union {
+               float m_max[4];
+               b3Float4 m_maxVec;
+               int m_signedMaxIndices[4];
+       };
+};
+
+inline void b3TransformAabb2(b3Float4ConstArg localAabbMin, b3Float4ConstArg localAabbMax, float margin,
+                                                        b3Float4ConstArg pos,
+                                                        b3QuatConstArg orn,
+                                                        b3Float4* aabbMinOut, b3Float4* aabbMaxOut)
+{
+       b3Float4 localHalfExtents = 0.5f * (localAabbMax - localAabbMin);
+       localHalfExtents += b3MakeFloat4(margin, margin, margin, 0.f);
+       b3Float4 localCenter = 0.5f * (localAabbMax + localAabbMin);
+       b3Mat3x3 m;
+       m = b3QuatGetRotationMatrix(orn);
+       b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);
+       b3Float4 center = b3TransformPoint(localCenter, pos, orn);
+
+       b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents, b3GetRow(abs_b, 0)),
+                                                                  b3Dot3F4(localHalfExtents, b3GetRow(abs_b, 1)),
+                                                                  b3Dot3F4(localHalfExtents, b3GetRow(abs_b, 2)),
+                                                                  0.f);
+       *aabbMinOut = center - extent;
+       *aabbMaxOut = center + extent;
+}
+
+/// conservative test for overlap between two aabbs
+inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1, b3Float4ConstArg aabbMax1,
+                                                                 b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)
+{
+       bool overlap = true;
+       overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;
+       overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;
+       overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;
+       return overlap;
+}
+
+#endif  //B3_AABB_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/CMakeLists.txt b/dali-physics/third-party/bullet3/src/Bullet3Collision/CMakeLists.txt
new file mode 100644 (file)
index 0000000..130095c
--- /dev/null
@@ -0,0 +1,93 @@
+
+INCLUDE_DIRECTORIES(
+       ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(Bullet3Collision_SRCS
+       BroadPhaseCollision/b3DynamicBvh.cpp
+       BroadPhaseCollision/b3DynamicBvhBroadphase.cpp
+       BroadPhaseCollision/b3OverlappingPairCache.cpp
+       NarrowPhaseCollision/b3ConvexUtility.cpp
+       NarrowPhaseCollision/b3CpuNarrowPhase.cpp
+)
+
+SET(Bullet3CollisionBroadPhase_HDRS
+       BroadPhaseCollision/b3BroadphaseCallback.h
+       BroadPhaseCollision/b3DynamicBvh.h
+       BroadPhaseCollision/b3DynamicBvhBroadphase.h
+       BroadPhaseCollision/b3OverlappingPair.h
+       BroadPhaseCollision/b3OverlappingPairCache.h
+)
+SET(Bullet3CollisionBroadPhaseShared_HDRS
+       BroadPhaseCollision/shared/b3Aabb.h
+)
+
+SET(Bullet3CollisionNarrowPhase_HDRS
+       NarrowPhaseCollision/b3Config.h
+       NarrowPhaseCollision/b3Contact4.h
+       NarrowPhaseCollision/b3ConvexUtility.h
+       NarrowPhaseCollision/b3CpuNarrowPhase.h
+       NarrowPhaseCollision/b3RaycastInfo.h
+       NarrowPhaseCollision/b3RigidBodyCL.h
+)
+SET(Bullet3CollisionNarrowPhaseShared_HDRS
+
+       NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h
+       NarrowPhaseCollision/shared/b3BvhTraversal.h
+       NarrowPhaseCollision/shared/b3ClipFaces.h
+       NarrowPhaseCollision/shared/b3Collidable.h
+       NarrowPhaseCollision/shared/b3Contact4Data.h
+       NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h
+       NarrowPhaseCollision/shared/b3ContactSphereSphere.h
+       NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h
+       NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h
+       NarrowPhaseCollision/shared/b3FindSeparatingAxis.h
+       NarrowPhaseCollision/shared/b3MprPenetration.h
+       NarrowPhaseCollision/shared/b3NewContactReduction.h
+       NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h
+       NarrowPhaseCollision/shared/b3ReduceContacts.h
+       NarrowPhaseCollision/shared/b3RigidBodyData.h
+       NarrowPhaseCollision/shared/b3UpdateAabbs.h
+)
+
+SET(Bullet3Collision_HDRS
+       ${Bullet3CollisionBroadPhase_HDRS}
+       ${Bullet3CollisionBroadPhaseShared_HDRS}
+       ${Bullet3CollisionNarrowPhaseShared_HDRS}
+       ${Bullet3CollisionNarrowPhase_HDRS}
+)
+
+ADD_LIBRARY(Bullet3Collision ${Bullet3Collision_SRCS} ${Bullet3Collision_HDRS})
+if (BUILD_SHARED_LIBS)
+  target_link_libraries(Bullet3Collision Bullet3Geometry)
+endif ()
+SET_TARGET_PROPERTIES(Bullet3Collision PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet3Collision PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               #FILES_MATCHING requires CMake 2.6
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet3Collision DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet3Collision
+                                       RUNTIME DESTINATION bin
+                                       LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                       ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h"  PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(Bullet3Collision PROPERTIES FRAMEWORK true)
+                       SET_TARGET_PROPERTIES(Bullet3Collision PROPERTIES PUBLIC_HEADER "${Bullet3Collision_HDRS}")
+                       # Have to list out sub-directories manually:
+                       #todo
+                       #SET_PROPERTY(SOURCE ${Bullet3CollisionBroadPhase_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/BroadPhaseCollision)
+
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3Config.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3Config.h
new file mode 100644 (file)
index 0000000..518da89
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef B3_CONFIG_H
+#define B3_CONFIG_H
+
+struct b3Config
+{
+       int m_maxConvexBodies;
+       int m_maxConvexShapes;
+       int m_maxBroadphasePairs;
+       int m_maxContactCapacity;
+       int m_compoundPairCapacity;
+
+       int m_maxVerticesPerFace;
+       int m_maxFacesPerShape;
+       int m_maxConvexVertices;
+       int m_maxConvexIndices;
+       int m_maxConvexUniqueEdges;
+
+       int m_maxCompoundChildShapes;
+
+       int m_maxTriConvexPairCapacity;
+
+       b3Config()
+               : m_maxConvexBodies(128 * 1024),
+                 m_maxVerticesPerFace(64),
+                 m_maxFacesPerShape(12),
+                 m_maxConvexVertices(8192),
+                 m_maxConvexIndices(81920),
+                 m_maxConvexUniqueEdges(8192),
+                 m_maxCompoundChildShapes(8192),
+                 m_maxTriConvexPairCapacity(256 * 1024)
+       {
+               m_maxConvexShapes = m_maxConvexBodies;
+               m_maxBroadphasePairs = 16 * m_maxConvexBodies;
+               m_maxContactCapacity = m_maxBroadphasePairs;
+               m_compoundPairCapacity = 1024 * 1024;
+       }
+};
+
+#endif  //B3_CONFIG_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h
new file mode 100644 (file)
index 0000000..c2cd3c7
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_CONTACT4_H
+#define B3_CONTACT4_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3Contact4 : public b3Contact4Data
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       int getBodyA() const { return abs(m_bodyAPtrAndSignBit); }
+       int getBodyB() const { return abs(m_bodyBPtrAndSignBit); }
+       bool isBodyAFixed() const { return m_bodyAPtrAndSignBit < 0; }
+       bool isBodyBFixed() const { return m_bodyBPtrAndSignBit < 0; }
+       //      todo. make it safer
+       int& getBatchIdx() { return m_batchIdx; }
+       const int& getBatchIdx() const { return m_batchIdx; }
+       float getRestituitionCoeff() const { return ((float)m_restituitionCoeffCmp / (float)0xffff); }
+       void setRestituitionCoeff(float c)
+       {
+               b3Assert(c >= 0.f && c <= 1.f);
+               m_restituitionCoeffCmp = (unsigned short)(c * 0xffff);
+       }
+       float getFrictionCoeff() const { return ((float)m_frictionCoeffCmp / (float)0xffff); }
+       void setFrictionCoeff(float c)
+       {
+               b3Assert(c >= 0.f && c <= 1.f);
+               m_frictionCoeffCmp = (unsigned short)(c * 0xffff);
+       }
+
+       //float& getNPoints() { return m_worldNormal[3]; }
+       int getNPoints() const { return (int)m_worldNormalOnB.w; }
+
+       float getPenetration(int idx) const { return m_worldPosB[idx].w; }
+
+       bool isInvalid() const { return (getBodyA() == 0 || getBodyB() == 0); }
+};
+
+#endif  //B3_CONTACT4_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp
new file mode 100644 (file)
index 0000000..a5dab74
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#include "b3ConvexUtility.h"
+#include "Bullet3Geometry/b3ConvexHullComputer.h"
+#include "Bullet3Geometry/b3GrahamScan2dConvexHull.h"
+#include "Bullet3Common/b3Quaternion.h"
+#include "Bullet3Common/b3HashMap.h"
+
+b3ConvexUtility::~b3ConvexUtility()
+{
+}
+
+bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices, int numPoints, bool mergeCoplanarTriangles)
+{
+       b3ConvexHullComputer conv;
+       conv.compute(&orgVertices[0].getX(), sizeof(b3Vector3), numPoints, 0.f, 0.f);
+
+       b3AlignedObjectArray<b3Vector3> faceNormals;
+       int numFaces = conv.faces.size();
+       faceNormals.resize(numFaces);
+       b3ConvexHullComputer* convexUtil = &conv;
+
+       b3AlignedObjectArray<b3MyFace> tmpFaces;
+       tmpFaces.resize(numFaces);
+
+       int numVertices = convexUtil->vertices.size();
+       m_vertices.resize(numVertices);
+       for (int p = 0; p < numVertices; p++)
+       {
+               m_vertices[p] = convexUtil->vertices[p];
+       }
+
+       for (int i = 0; i < numFaces; i++)
+       {
+               int face = convexUtil->faces[i];
+               //printf("face=%d\n",face);
+               const b3ConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face];
+               const b3ConvexHullComputer::Edge* edge = firstEdge;
+
+               b3Vector3 edges[3];
+               int numEdges = 0;
+               //compute face normals
+
+               do
+               {
+                       int src = edge->getSourceVertex();
+                       tmpFaces[i].m_indices.push_back(src);
+                       int targ = edge->getTargetVertex();
+                       b3Vector3 wa = convexUtil->vertices[src];
+
+                       b3Vector3 wb = convexUtil->vertices[targ];
+                       b3Vector3 newEdge = wb - wa;
+                       newEdge.normalize();
+                       if (numEdges < 2)
+                               edges[numEdges++] = newEdge;
+
+                       edge = edge->getNextEdgeOfFace();
+               } while (edge != firstEdge);
+
+               b3Scalar planeEq = 1e30f;
+
+               if (numEdges == 2)
+               {
+                       faceNormals[i] = edges[0].cross(edges[1]);
+                       faceNormals[i].normalize();
+                       tmpFaces[i].m_plane[0] = faceNormals[i].getX();
+                       tmpFaces[i].m_plane[1] = faceNormals[i].getY();
+                       tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
+                       tmpFaces[i].m_plane[3] = planeEq;
+               }
+               else
+               {
+                       b3Assert(0);  //degenerate?
+                       faceNormals[i].setZero();
+               }
+
+               for (int v = 0; v < tmpFaces[i].m_indices.size(); v++)
+               {
+                       b3Scalar eq = m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
+                       if (planeEq > eq)
+                       {
+                               planeEq = eq;
+                       }
+               }
+               tmpFaces[i].m_plane[3] = -planeEq;
+       }
+
+       //merge coplanar faces and copy them to m_polyhedron
+
+       b3Scalar faceWeldThreshold = 0.999f;
+       b3AlignedObjectArray<int> todoFaces;
+       for (int i = 0; i < tmpFaces.size(); i++)
+               todoFaces.push_back(i);
+
+       while (todoFaces.size())
+       {
+               b3AlignedObjectArray<int> coplanarFaceGroup;
+               int refFace = todoFaces[todoFaces.size() - 1];
+
+               coplanarFaceGroup.push_back(refFace);
+               b3MyFace& faceA = tmpFaces[refFace];
+               todoFaces.pop_back();
+
+               b3Vector3 faceNormalA = b3MakeVector3(faceA.m_plane[0], faceA.m_plane[1], faceA.m_plane[2]);
+               for (int j = todoFaces.size() - 1; j >= 0; j--)
+               {
+                       int i = todoFaces[j];
+                       b3MyFace& faceB = tmpFaces[i];
+                       b3Vector3 faceNormalB = b3MakeVector3(faceB.m_plane[0], faceB.m_plane[1], faceB.m_plane[2]);
+                       if (faceNormalA.dot(faceNormalB) > faceWeldThreshold)
+                       {
+                               coplanarFaceGroup.push_back(i);
+                               todoFaces.remove(i);
+                       }
+               }
+
+               bool did_merge = false;
+               if (coplanarFaceGroup.size() > 1)
+               {
+                       //do the merge: use Graham Scan 2d convex hull
+
+                       b3AlignedObjectArray<b3GrahamVector3> orgpoints;
+                       b3Vector3 averageFaceNormal = b3MakeVector3(0, 0, 0);
+
+                       for (int i = 0; i < coplanarFaceGroup.size(); i++)
+                       {
+                               //                              m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
+
+                               b3MyFace& face = tmpFaces[coplanarFaceGroup[i]];
+                               b3Vector3 faceNormal = b3MakeVector3(face.m_plane[0], face.m_plane[1], face.m_plane[2]);
+                               averageFaceNormal += faceNormal;
+                               for (int f = 0; f < face.m_indices.size(); f++)
+                               {
+                                       int orgIndex = face.m_indices[f];
+                                       b3Vector3 pt = m_vertices[orgIndex];
+
+                                       bool found = false;
+
+                                       for (int i = 0; i < orgpoints.size(); i++)
+                                       {
+                                               //if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
+                                               if (orgpoints[i].m_orgIndex == orgIndex)
+                                               {
+                                                       found = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found)
+                                               orgpoints.push_back(b3GrahamVector3(pt, orgIndex));
+                               }
+                       }
+
+                       b3MyFace combinedFace;
+                       for (int i = 0; i < 4; i++)
+                               combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];
+
+                       b3AlignedObjectArray<b3GrahamVector3> hull;
+
+                       averageFaceNormal.normalize();
+                       b3GrahamScanConvexHull2D(orgpoints, hull, averageFaceNormal);
+
+                       for (int i = 0; i < hull.size(); i++)
+                       {
+                               combinedFace.m_indices.push_back(hull[i].m_orgIndex);
+                               for (int k = 0; k < orgpoints.size(); k++)
+                               {
+                                       if (orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
+                                       {
+                                               orgpoints[k].m_orgIndex = -1;  // invalidate...
+                                               break;
+                                       }
+                               }
+                       }
+
+                       // are there rejected vertices?
+                       bool reject_merge = false;
+
+                       for (int i = 0; i < orgpoints.size(); i++)
+                       {
+                               if (orgpoints[i].m_orgIndex == -1)
+                                       continue;  // this is in the hull...
+                               // this vertex is rejected -- is anybody else using this vertex?
+                               for (int j = 0; j < tmpFaces.size(); j++)
+                               {
+                                       b3MyFace& face = tmpFaces[j];
+                                       // is this a face of the current coplanar group?
+                                       bool is_in_current_group = false;
+                                       for (int k = 0; k < coplanarFaceGroup.size(); k++)
+                                       {
+                                               if (coplanarFaceGroup[k] == j)
+                                               {
+                                                       is_in_current_group = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (is_in_current_group)  // ignore this face...
+                                               continue;
+                                       // does this face use this rejected vertex?
+                                       for (int v = 0; v < face.m_indices.size(); v++)
+                                       {
+                                               if (face.m_indices[v] == orgpoints[i].m_orgIndex)
+                                               {
+                                                       // this rejected vertex is used in another face -- reject merge
+                                                       reject_merge = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (reject_merge)
+                                               break;
+                               }
+                               if (reject_merge)
+                                       break;
+                       }
+
+                       if (!reject_merge)
+                       {
+                               // do this merge!
+                               did_merge = true;
+                               m_faces.push_back(combinedFace);
+                       }
+               }
+               if (!did_merge)
+               {
+                       for (int i = 0; i < coplanarFaceGroup.size(); i++)
+                       {
+                               b3MyFace face = tmpFaces[coplanarFaceGroup[i]];
+                               m_faces.push_back(face);
+                       }
+               }
+       }
+
+       initialize();
+
+       return true;
+}
+
+inline bool IsAlmostZero(const b3Vector3& v)
+{
+       if (fabsf(v.getX()) > 1e-6 || fabsf(v.getY()) > 1e-6 || fabsf(v.getZ()) > 1e-6) return false;
+       return true;
+}
+
+struct b3InternalVertexPair
+{
+       b3InternalVertexPair(short int v0, short int v1)
+               : m_v0(v0),
+                 m_v1(v1)
+       {
+               if (m_v1 > m_v0)
+                       b3Swap(m_v0, m_v1);
+       }
+       short int m_v0;
+       short int m_v1;
+       int getHash() const
+       {
+               return m_v0 + (m_v1 << 16);
+       }
+       bool equals(const b3InternalVertexPair& other) const
+       {
+               return m_v0 == other.m_v0 && m_v1 == other.m_v1;
+       }
+};
+
+struct b3InternalEdge
+{
+       b3InternalEdge()
+               : m_face0(-1),
+                 m_face1(-1)
+       {
+       }
+       short int m_face0;
+       short int m_face1;
+};
+
+//
+
+#ifdef TEST_INTERNAL_OBJECTS
+bool b3ConvexUtility::testContainment() const
+{
+       for (int p = 0; p < 8; p++)
+       {
+               b3Vector3 LocalPt;
+               if (p == 0)
+                       LocalPt = m_localCenter + b3Vector3(m_extents[0], m_extents[1], m_extents[2]);
+               else if (p == 1)
+                       LocalPt = m_localCenter + b3Vector3(m_extents[0], m_extents[1], -m_extents[2]);
+               else if (p == 2)
+                       LocalPt = m_localCenter + b3Vector3(m_extents[0], -m_extents[1], m_extents[2]);
+               else if (p == 3)
+                       LocalPt = m_localCenter + b3Vector3(m_extents[0], -m_extents[1], -m_extents[2]);
+               else if (p == 4)
+                       LocalPt = m_localCenter + b3Vector3(-m_extents[0], m_extents[1], m_extents[2]);
+               else if (p == 5)
+                       LocalPt = m_localCenter + b3Vector3(-m_extents[0], m_extents[1], -m_extents[2]);
+               else if (p == 6)
+                       LocalPt = m_localCenter + b3Vector3(-m_extents[0], -m_extents[1], m_extents[2]);
+               else if (p == 7)
+                       LocalPt = m_localCenter + b3Vector3(-m_extents[0], -m_extents[1], -m_extents[2]);
+
+               for (int i = 0; i < m_faces.size(); i++)
+               {
+                       const b3Vector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
+                       const b3Scalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3];
+                       if (d > 0.0f)
+                               return false;
+               }
+       }
+       return true;
+}
+#endif
+
+void b3ConvexUtility::initialize()
+{
+       b3HashMap<b3InternalVertexPair, b3InternalEdge> edges;
+
+       b3Scalar TotalArea = 0.0f;
+
+       m_localCenter.setValue(0, 0, 0);
+       for (int i = 0; i < m_faces.size(); i++)
+       {
+               int numVertices = m_faces[i].m_indices.size();
+               int NbTris = numVertices;
+               for (int j = 0; j < NbTris; j++)
+               {
+                       int k = (j + 1) % numVertices;
+                       b3InternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
+                       b3InternalEdge* edptr = edges.find(vp);
+                       b3Vector3 edge = m_vertices[vp.m_v1] - m_vertices[vp.m_v0];
+                       edge.normalize();
+
+                       bool found = false;
+                       b3Vector3 diff, diff2;
+
+                       for (int p = 0; p < m_uniqueEdges.size(); p++)
+                       {
+                               diff = m_uniqueEdges[p] - edge;
+                               diff2 = m_uniqueEdges[p] + edge;
+
+                               //      if ((diff.length2()==0.f) ||
+                               //      (diff2.length2()==0.f))
+
+                               if (IsAlmostZero(diff) ||
+                                       IsAlmostZero(diff2))
+                               {
+                                       found = true;
+                                       break;
+                               }
+                       }
+
+                       if (!found)
+                       {
+                               m_uniqueEdges.push_back(edge);
+                       }
+
+                       if (edptr)
+                       {
+                               //TBD: figure out why I added this assert
+                               //                              b3Assert(edptr->m_face0>=0);
+                               //                      b3Assert(edptr->m_face1<0);
+                               edptr->m_face1 = i;
+                       }
+                       else
+                       {
+                               b3InternalEdge ed;
+                               ed.m_face0 = i;
+                               edges.insert(vp, ed);
+                       }
+               }
+       }
+
+#ifdef USE_CONNECTED_FACES
+       for (int i = 0; i < m_faces.size(); i++)
+       {
+               int numVertices = m_faces[i].m_indices.size();
+               m_faces[i].m_connectedFaces.resize(numVertices);
+
+               for (int j = 0; j < numVertices; j++)
+               {
+                       int k = (j + 1) % numVertices;
+                       b3InternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
+                       b3InternalEdge* edptr = edges.find(vp);
+                       b3Assert(edptr);
+                       b3Assert(edptr->m_face0 >= 0);
+                       b3Assert(edptr->m_face1 >= 0);
+
+                       int connectedFace = (edptr->m_face0 == i) ? edptr->m_face1 : edptr->m_face0;
+                       m_faces[i].m_connectedFaces[j] = connectedFace;
+               }
+       }
+#endif  //USE_CONNECTED_FACES
+
+       for (int i = 0; i < m_faces.size(); i++)
+       {
+               int numVertices = m_faces[i].m_indices.size();
+               int NbTris = numVertices - 2;
+
+               const b3Vector3& p0 = m_vertices[m_faces[i].m_indices[0]];
+               for (int j = 1; j <= NbTris; j++)
+               {
+                       int k = (j + 1) % numVertices;
+                       const b3Vector3& p1 = m_vertices[m_faces[i].m_indices[j]];
+                       const b3Vector3& p2 = m_vertices[m_faces[i].m_indices[k]];
+                       b3Scalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
+                       b3Vector3 Center = (p0 + p1 + p2) / 3.0f;
+                       m_localCenter += Area * Center;
+                       TotalArea += Area;
+               }
+       }
+       m_localCenter /= TotalArea;
+
+#ifdef TEST_INTERNAL_OBJECTS
+       if (1)
+       {
+               m_radius = FLT_MAX;
+               for (int i = 0; i < m_faces.size(); i++)
+               {
+                       const b3Vector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
+                       const b3Scalar dist = b3Fabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]);
+                       if (dist < m_radius)
+                               m_radius = dist;
+               }
+
+               b3Scalar MinX = FLT_MAX;
+               b3Scalar MinY = FLT_MAX;
+               b3Scalar MinZ = FLT_MAX;
+               b3Scalar MaxX = -FLT_MAX;
+               b3Scalar MaxY = -FLT_MAX;
+               b3Scalar MaxZ = -FLT_MAX;
+               for (int i = 0; i < m_vertices.size(); i++)
+               {
+                       const b3Vector3& pt = m_vertices[i];
+                       if (pt.getX() < MinX) MinX = pt.getX();
+                       if (pt.getX() > MaxX) MaxX = pt.getX();
+                       if (pt.getY() < MinY) MinY = pt.getY();
+                       if (pt.getY() > MaxY) MaxY = pt.getY();
+                       if (pt.getZ() < MinZ) MinZ = pt.getZ();
+                       if (pt.getZ() > MaxZ) MaxZ = pt.getZ();
+               }
+               mC.setValue(MaxX + MinX, MaxY + MinY, MaxZ + MinZ);
+               mE.setValue(MaxX - MinX, MaxY - MinY, MaxZ - MinZ);
+
+               //              const b3Scalar r = m_radius / sqrtf(2.0f);
+               const b3Scalar r = m_radius / sqrtf(3.0f);
+               const int LargestExtent = mE.maxAxis();
+               const b3Scalar Step = (mE[LargestExtent] * 0.5f - r) / 1024.0f;
+               m_extents[0] = m_extents[1] = m_extents[2] = r;
+               m_extents[LargestExtent] = mE[LargestExtent] * 0.5f;
+               bool FoundBox = false;
+               for (int j = 0; j < 1024; j++)
+               {
+                       if (testContainment())
+                       {
+                               FoundBox = true;
+                               break;
+                       }
+
+                       m_extents[LargestExtent] -= Step;
+               }
+               if (!FoundBox)
+               {
+                       m_extents[0] = m_extents[1] = m_extents[2] = r;
+               }
+               else
+               {
+                       // Refine the box
+                       const b3Scalar Step = (m_radius - r) / 1024.0f;
+                       const int e0 = (1 << LargestExtent) & 3;
+                       const int e1 = (1 << e0) & 3;
+
+                       for (int j = 0; j < 1024; j++)
+                       {
+                               const b3Scalar Saved0 = m_extents[e0];
+                               const b3Scalar Saved1 = m_extents[e1];
+                               m_extents[e0] += Step;
+                               m_extents[e1] += Step;
+
+                               if (!testContainment())
+                               {
+                                       m_extents[e0] = Saved0;
+                                       m_extents[e1] = Saved1;
+                                       break;
+                               }
+                       }
+               }
+       }
+#endif
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h
new file mode 100644 (file)
index 0000000..4c8a88c
--- /dev/null
@@ -0,0 +1,55 @@
+
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef _BT_CONVEX_UTILITY_H
+#define _BT_CONVEX_UTILITY_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Transform.h"
+
+struct b3MyFace
+{
+       b3AlignedObjectArray<int> m_indices;
+       b3Scalar m_plane[4];
+};
+
+B3_ATTRIBUTE_ALIGNED16(class)
+b3ConvexUtility
+{
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       b3Vector3 m_localCenter;
+       b3Vector3 m_extents;
+       b3Vector3 mC;
+       b3Vector3 mE;
+       b3Scalar m_radius;
+
+       b3AlignedObjectArray<b3Vector3> m_vertices;
+       b3AlignedObjectArray<b3MyFace> m_faces;
+       b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
+
+       b3ConvexUtility()
+       {
+       }
+       virtual ~b3ConvexUtility();
+
+       bool initializePolyhedralFeatures(const b3Vector3* orgVertices, int numVertices, bool mergeCoplanarTriangles = true);
+
+       void initialize();
+       bool testContainment() const;
+};
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp
new file mode 100644 (file)
index 0000000..e0b2161
--- /dev/null
@@ -0,0 +1,297 @@
+#include "b3CpuNarrowPhase.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h"
+
+struct b3CpuNarrowPhaseInternalData
+{
+       b3AlignedObjectArray<b3Aabb> m_localShapeAABBCPU;
+       b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
+       b3AlignedObjectArray<b3ConvexUtility*> m_convexData;
+       b3Config m_config;
+
+       b3AlignedObjectArray<b3ConvexPolyhedronData> m_convexPolyhedra;
+       b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
+       b3AlignedObjectArray<b3Vector3> m_convexVertices;
+       b3AlignedObjectArray<int> m_convexIndices;
+       b3AlignedObjectArray<b3GpuFace> m_convexFaces;
+
+       b3AlignedObjectArray<b3Contact4Data> m_contacts;
+
+       int m_numAcceleratedShapes;
+};
+
+const b3AlignedObjectArray<b3Contact4Data>& b3CpuNarrowPhase::getContacts() const
+{
+       return m_data->m_contacts;
+}
+
+b3Collidable& b3CpuNarrowPhase::getCollidableCpu(int collidableIndex)
+{
+       return m_data->m_collidablesCPU[collidableIndex];
+}
+
+const b3Collidable& b3CpuNarrowPhase::getCollidableCpu(int collidableIndex) const
+{
+       return m_data->m_collidablesCPU[collidableIndex];
+}
+
+b3CpuNarrowPhase::b3CpuNarrowPhase(const struct b3Config& config)
+{
+       m_data = new b3CpuNarrowPhaseInternalData;
+       m_data->m_config = config;
+       m_data->m_numAcceleratedShapes = 0;
+}
+
+b3CpuNarrowPhase::~b3CpuNarrowPhase()
+{
+       delete m_data;
+}
+
+void b3CpuNarrowPhase::computeContacts(b3AlignedObjectArray<b3Int4>& pairs, b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace, b3AlignedObjectArray<b3RigidBodyData>& bodies)
+{
+       int nPairs = pairs.size();
+       int numContacts = 0;
+       int maxContactCapacity = m_data->m_config.m_maxContactCapacity;
+       m_data->m_contacts.resize(maxContactCapacity);
+
+       for (int i = 0; i < nPairs; i++)
+       {
+               int bodyIndexA = pairs[i].x;
+               int bodyIndexB = pairs[i].y;
+               int collidableIndexA = bodies[bodyIndexA].m_collidableIdx;
+               int collidableIndexB = bodies[bodyIndexB].m_collidableIdx;
+
+               if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+                       m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+               {
+                       //                      computeContactSphereConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
+                       //                              &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+               }
+
+               if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+                       m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+               {
+                       //                      computeContactSphereConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+                       //                              &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+                       //printf("convex-sphere\n");
+               }
+
+               if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+                       m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_PLANE)
+               {
+                       //                      computeContactPlaneConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+                       //                      &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+                       //                      printf("convex-plane\n");
+               }
+
+               if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+                       m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+               {
+                       //                      computeContactPlaneConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
+                       //                      &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+                       //                      printf("plane-convex\n");
+               }
+
+               if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+                       m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+               {
+                       //                      computeContactCompoundCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+                       //                      &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0], hostAabbsWorldSpace,hostAabbsLocalSpace,hostVertices,hostUniqueEdges,hostIndices,hostFaces,&hostContacts[0],
+                       //                      nContacts,maxContactCapacity,treeNodesCPU,subTreesCPU,bvhInfoCPU);
+                       //                      printf("convex-plane\n");
+               }
+
+               if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+                       m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_PLANE)
+               {
+                       //                      computeContactPlaneCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
+                       //                      &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0], &hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+                       //                      printf("convex-plane\n");
+               }
+
+               if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+                       m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+               {
+                       //                      computeContactPlaneCompound(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
+                       //                      &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
+                       //                      printf("plane-convex\n");
+               }
+
+               if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+                       m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+               {
+                       //printf("pairs[i].z=%d\n",pairs[i].z);
+                       //int contactIndex = computeContactConvexConvex2(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,bodies,
+                       //              m_data->m_collidablesCPU,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
+                       int contactIndex = b3ContactConvexConvexSAT(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, bodies,
+                                                                                                               m_data->m_collidablesCPU, m_data->m_convexPolyhedra, m_data->m_convexVertices, m_data->m_uniqueEdges, m_data->m_convexIndices, m_data->m_convexFaces, m_data->m_contacts, numContacts, maxContactCapacity);
+
+                       if (contactIndex >= 0)
+                       {
+                               pairs[i].z = contactIndex;
+                       }
+                       //                      printf("plane-convex\n");
+               }
+       }
+
+       m_data->m_contacts.resize(numContacts);
+}
+
+int b3CpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
+{
+       int collidableIndex = allocateCollidable();
+       if (collidableIndex < 0)
+               return collidableIndex;
+
+       b3Collidable& col = m_data->m_collidablesCPU[collidableIndex];
+       col.m_shapeType = SHAPE_CONVEX_HULL;
+       col.m_shapeIndex = -1;
+
+       {
+               b3Vector3 localCenter = b3MakeVector3(0, 0, 0);
+               for (int i = 0; i < utilPtr->m_vertices.size(); i++)
+                       localCenter += utilPtr->m_vertices[i];
+               localCenter *= (1.f / utilPtr->m_vertices.size());
+               utilPtr->m_localCenter = localCenter;
+
+               col.m_shapeIndex = registerConvexHullShapeInternal(utilPtr, col);
+       }
+
+       if (col.m_shapeIndex >= 0)
+       {
+               b3Aabb aabb;
+
+               b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
+               b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
+
+               for (int i = 0; i < utilPtr->m_vertices.size(); i++)
+               {
+                       myAabbMin.setMin(utilPtr->m_vertices[i]);
+                       myAabbMax.setMax(utilPtr->m_vertices[i]);
+               }
+               aabb.m_min[0] = myAabbMin[0];
+               aabb.m_min[1] = myAabbMin[1];
+               aabb.m_min[2] = myAabbMin[2];
+               aabb.m_minIndices[3] = 0;
+
+               aabb.m_max[0] = myAabbMax[0];
+               aabb.m_max[1] = myAabbMax[1];
+               aabb.m_max[2] = myAabbMax[2];
+               aabb.m_signedMaxIndices[3] = 0;
+
+               m_data->m_localShapeAABBCPU.push_back(aabb);
+       }
+
+       return collidableIndex;
+}
+
+int b3CpuNarrowPhase::allocateCollidable()
+{
+       int curSize = m_data->m_collidablesCPU.size();
+       if (curSize < m_data->m_config.m_maxConvexShapes)
+       {
+               m_data->m_collidablesCPU.expand();
+               return curSize;
+       }
+       else
+       {
+               b3Error("allocateCollidable out-of-range %d\n", m_data->m_config.m_maxConvexShapes);
+       }
+       return -1;
+}
+
+int b3CpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
+{
+       b3AlignedObjectArray<b3Vector3> verts;
+
+       unsigned char* vts = (unsigned char*)vertices;
+       for (int i = 0; i < numVertices; i++)
+       {
+               float* vertex = (float*)&vts[i * strideInBytes];
+               verts.push_back(b3MakeVector3(vertex[0] * scaling[0], vertex[1] * scaling[1], vertex[2] * scaling[2]));
+       }
+
+       b3ConvexUtility* utilPtr = new b3ConvexUtility();
+       bool merge = true;
+       if (numVertices)
+       {
+               utilPtr->initializePolyhedralFeatures(&verts[0], verts.size(), merge);
+       }
+
+       int collidableIndex = registerConvexHullShape(utilPtr);
+
+       delete utilPtr;
+       return collidableIndex;
+}
+
+int b3CpuNarrowPhase::registerConvexHullShapeInternal(b3ConvexUtility* convexPtr, b3Collidable& col)
+{
+       m_data->m_convexData.resize(m_data->m_numAcceleratedShapes + 1);
+       m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes + 1);
+
+       b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size() - 1);
+       convex.mC = convexPtr->mC;
+       convex.mE = convexPtr->mE;
+       convex.m_extents = convexPtr->m_extents;
+       convex.m_localCenter = convexPtr->m_localCenter;
+       convex.m_radius = convexPtr->m_radius;
+
+       convex.m_numUniqueEdges = convexPtr->m_uniqueEdges.size();
+       int edgeOffset = m_data->m_uniqueEdges.size();
+       convex.m_uniqueEdgesOffset = edgeOffset;
+
+       m_data->m_uniqueEdges.resize(edgeOffset + convex.m_numUniqueEdges);
+
+       //convex data here
+       int i;
+       for (i = 0; i < convexPtr->m_uniqueEdges.size(); i++)
+       {
+               m_data->m_uniqueEdges[edgeOffset + i] = convexPtr->m_uniqueEdges[i];
+       }
+
+       int faceOffset = m_data->m_convexFaces.size();
+       convex.m_faceOffset = faceOffset;
+       convex.m_numFaces = convexPtr->m_faces.size();
+
+       m_data->m_convexFaces.resize(faceOffset + convex.m_numFaces);
+
+       for (i = 0; i < convexPtr->m_faces.size(); i++)
+       {
+               m_data->m_convexFaces[convex.m_faceOffset + i].m_plane = b3MakeVector3(convexPtr->m_faces[i].m_plane[0],
+                                                                                                                                                          convexPtr->m_faces[i].m_plane[1],
+                                                                                                                                                          convexPtr->m_faces[i].m_plane[2],
+                                                                                                                                                          convexPtr->m_faces[i].m_plane[3]);
+
+               int indexOffset = m_data->m_convexIndices.size();
+               int numIndices = convexPtr->m_faces[i].m_indices.size();
+               m_data->m_convexFaces[convex.m_faceOffset + i].m_numIndices = numIndices;
+               m_data->m_convexFaces[convex.m_faceOffset + i].m_indexOffset = indexOffset;
+               m_data->m_convexIndices.resize(indexOffset + numIndices);
+               for (int p = 0; p < numIndices; p++)
+               {
+                       m_data->m_convexIndices[indexOffset + p] = convexPtr->m_faces[i].m_indices[p];
+               }
+       }
+
+       convex.m_numVertices = convexPtr->m_vertices.size();
+       int vertexOffset = m_data->m_convexVertices.size();
+       convex.m_vertexOffset = vertexOffset;
+
+       m_data->m_convexVertices.resize(vertexOffset + convex.m_numVertices);
+       for (int i = 0; i < convexPtr->m_vertices.size(); i++)
+       {
+               m_data->m_convexVertices[vertexOffset + i] = convexPtr->m_vertices[i];
+       }
+
+       (m_data->m_convexData)[m_data->m_numAcceleratedShapes] = convexPtr;
+
+       return m_data->m_numAcceleratedShapes++;
+}
+
+const b3Aabb& b3CpuNarrowPhase::getLocalSpaceAabb(int collidableIndex) const
+{
+       return m_data->m_localShapeAABBCPU[collidableIndex];
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h
new file mode 100644 (file)
index 0000000..f02353c
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef B3_CPU_NARROWPHASE_H
+#define B3_CPU_NARROWPHASE_H
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+class b3CpuNarrowPhase
+{
+protected:
+       struct b3CpuNarrowPhaseInternalData* m_data;
+       int m_acceleratedCompanionShapeIndex;
+       int m_planeBodyIndex;
+       int m_static0Index;
+
+       int registerConvexHullShapeInternal(class b3ConvexUtility* convexPtr, b3Collidable& col);
+       int registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling);
+
+public:
+       b3CpuNarrowPhase(const struct b3Config& config);
+
+       virtual ~b3CpuNarrowPhase(void);
+
+       int registerSphereShape(float radius);
+       int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
+
+       int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
+       int registerFace(const b3Vector3& faceNormal, float faceConstant);
+
+       int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
+
+       //do they need to be merged?
+
+       int registerConvexHullShape(b3ConvexUtility* utilPtr);
+       int registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
+
+       //int registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMin, const float* aabbMax,bool writeToGpu);
+       void setObjectTransform(const float* position, const float* orientation, int bodyIndex);
+
+       void writeAllBodiesToGpu();
+       void reset();
+       void readbackAllBodiesToCpu();
+       bool getObjectTransformFromCpu(float* position, float* orientation, int bodyIndex) const;
+
+       void setObjectTransformCpu(float* position, float* orientation, int bodyIndex);
+       void setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex);
+
+       //virtual void computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects);
+       virtual void computeContacts(b3AlignedObjectArray<b3Int4>& pairs, b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace, b3AlignedObjectArray<b3RigidBodyData>& bodies);
+
+       const struct b3RigidBodyData* getBodiesCpu() const;
+       //struct b3RigidBodyData* getBodiesCpu();
+
+       int getNumBodiesGpu() const;
+
+       int getNumBodyInertiasGpu() const;
+
+       const struct b3Collidable* getCollidablesCpu() const;
+       int getNumCollidablesGpu() const;
+
+       /*const struct b3Contact4* getContactsCPU() const;
+
+       
+       int     getNumContactsGpu() const;
+       */
+
+       const b3AlignedObjectArray<b3Contact4Data>& getContacts() const;
+
+       int getNumRigidBodies() const;
+
+       int allocateCollidable();
+
+       int getStatic0Index() const
+       {
+               return m_static0Index;
+       }
+       b3Collidable& getCollidableCpu(int collidableIndex);
+       const b3Collidable& getCollidableCpu(int collidableIndex) const;
+
+       const b3CpuNarrowPhaseInternalData* getInternalData() const
+       {
+               return m_data;
+       }
+
+       const struct b3Aabb& getLocalSpaceAabb(int collidableIndex) const;
+};
+
+#endif  //B3_CPU_NARROWPHASE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h
new file mode 100644 (file)
index 0000000..b50c0ec
--- /dev/null
@@ -0,0 +1,25 @@
+
+#ifndef B3_RAYCAST_INFO_H
+#define B3_RAYCAST_INFO_H
+
+#include "Bullet3Common/b3Vector3.h"
+
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3RayInfo
+{
+       b3Vector3 m_from;
+       b3Vector3 m_to;
+};
+
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3RayHit
+{
+       b3Scalar m_hitFraction;
+       int m_hitBody;
+       int m_hitResult1;
+       int m_hitResult2;
+       b3Vector3 m_hitPoint;
+       b3Vector3 m_hitNormal;
+};
+
+#endif  //B3_RAYCAST_INFO_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h
new file mode 100644 (file)
index 0000000..be1be57
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_RIGID_BODY_CL
+#define B3_RIGID_BODY_CL
+
+#include "Bullet3Common/b3Scalar.h"
+#include "Bullet3Common/b3Matrix3x3.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+inline float b3GetInvMass(const b3RigidBodyData& body)
+{
+       return body.m_invMass;
+}
+
+#endif  //B3_RIGID_BODY_CL
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h
new file mode 100644 (file)
index 0000000..d6beb66
--- /dev/null
@@ -0,0 +1,19 @@
+
+#ifndef B3_BVH_SUBTREE_INFO_DATA_H
+#define B3_BVH_SUBTREE_INFO_DATA_H
+
+typedef struct b3BvhSubtreeInfoData b3BvhSubtreeInfoData_t;
+
+struct b3BvhSubtreeInfoData
+{
+       //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];
+};
+
+#endif  //B3_BVH_SUBTREE_INFO_DATA_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h
new file mode 100644 (file)
index 0000000..7c2507c
--- /dev/null
@@ -0,0 +1,123 @@
+
+
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
+
+// work-in-progress
+void b3BvhTraversal(__global const b3Int4* pairs,
+                                       __global const b3RigidBodyData* rigidBodies,
+                                       __global const b3Collidable* collidables,
+                                       __global b3Aabb* aabbs,
+                                       __global b3Int4* concavePairsOut,
+                                       __global volatile int* numConcavePairsOut,
+                                       __global const b3BvhSubtreeInfo* subtreeHeadersRoot,
+                                       __global const b3QuantizedBvhNode* quantizedNodesRoot,
+                                       __global const b3BvhInfo* bvhInfos,
+                                       int numPairs,
+                                       int maxNumConcavePairsCapacity,
+                                       int id)
+{
+       int bodyIndexA = pairs[id].x;
+       int bodyIndexB = pairs[id].y;
+       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+       //once the broadphase avoids static-static pairs, we can remove this test
+       if ((rigidBodies[bodyIndexA].m_invMass == 0) && (rigidBodies[bodyIndexB].m_invMass == 0))
+       {
+               return;
+       }
+
+       if (collidables[collidableIndexA].m_shapeType != SHAPE_CONCAVE_TRIMESH)
+               return;
+
+       int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+
+       if (shapeTypeB != SHAPE_CONVEX_HULL &&
+               shapeTypeB != SHAPE_SPHERE &&
+               shapeTypeB != SHAPE_COMPOUND_OF_CONVEX_HULLS)
+               return;
+
+       b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];
+
+       b3Float4 bvhAabbMin = bvhInfo.m_aabbMin;
+       b3Float4 bvhAabbMax = bvhInfo.m_aabbMax;
+       b3Float4 bvhQuantization = bvhInfo.m_quantization;
+       int numSubtreeHeaders = bvhInfo.m_numSubTrees;
+       __global const b3BvhSubtreeInfoData* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];
+       __global const b3QuantizedBvhNodeData* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];
+
+       unsigned short int quantizedQueryAabbMin[3];
+       unsigned short int quantizedQueryAabbMax[3];
+       b3QuantizeWithClamp(quantizedQueryAabbMin, aabbs[bodyIndexB].m_minVec, false, bvhAabbMin, bvhAabbMax, bvhQuantization);
+       b3QuantizeWithClamp(quantizedQueryAabbMax, aabbs[bodyIndexB].m_maxVec, true, bvhAabbMin, bvhAabbMax, bvhQuantization);
+
+       for (int i = 0; i < numSubtreeHeaders; i++)
+       {
+               b3BvhSubtreeInfoData subtree = subtreeHeaders[i];
+
+               int overlap = b3TestQuantizedAabbAgainstQuantizedAabbSlow(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
+               if (overlap != 0)
+               {
+                       int startNodeIndex = subtree.m_rootNodeIndex;
+                       int endNodeIndex = subtree.m_rootNodeIndex + subtree.m_subtreeSize;
+                       int curIndex = startNodeIndex;
+                       int escapeIndex;
+                       int isLeafNode;
+                       int aabbOverlap;
+                       while (curIndex < endNodeIndex)
+                       {
+                               b3QuantizedBvhNodeData rootNode = quantizedNodes[curIndex];
+                               aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabbSlow(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode.m_quantizedAabbMin, rootNode.m_quantizedAabbMax);
+                               isLeafNode = b3IsLeaf(&rootNode);
+                               if (aabbOverlap)
+                               {
+                                       if (isLeafNode)
+                                       {
+                                               int triangleIndex = b3GetTriangleIndex(&rootNode);
+                                               if (shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                                               {
+                                                       int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+                                                       int pairIdx = b3AtomicAdd(numConcavePairsOut, numChildrenB);
+                                                       for (int b = 0; b < numChildrenB; b++)
+                                                       {
+                                                               if ((pairIdx + b) < maxNumConcavePairsCapacity)
+                                                               {
+                                                                       int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + b;
+                                                                       b3Int4 newPair = b3MakeInt4(bodyIndexA, bodyIndexB, triangleIndex, childShapeIndexB);
+                                                                       concavePairsOut[pairIdx + b] = newPair;
+                                                               }
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       int pairIdx = b3AtomicInc(numConcavePairsOut);
+                                                       if (pairIdx < maxNumConcavePairsCapacity)
+                                                       {
+                                                               b3Int4 newPair = b3MakeInt4(bodyIndexA, bodyIndexB, triangleIndex, 0);
+                                                               concavePairsOut[pairIdx] = newPair;
+                                                       }
+                                               }
+                                       }
+                                       curIndex++;
+                               }
+                               else
+                               {
+                                       if (isLeafNode)
+                                       {
+                                               curIndex++;
+                                       }
+                                       else
+                                       {
+                                               escapeIndex = b3GetEscapeIndex(&rootNode);
+                                               curIndex += escapeIndex;
+                                       }
+                               }
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h
new file mode 100644 (file)
index 0000000..0d9b13f
--- /dev/null
@@ -0,0 +1,171 @@
+#ifndef B3_CLIP_FACES_H
+#define B3_CLIP_FACES_H
+
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+
+inline b3Float4 b3Lerp3(b3Float4ConstArg a, b3Float4ConstArg b, float t)
+{
+       return b3MakeFloat4(a.x + (b.x - a.x) * t,
+                                               a.y + (b.y - a.y) * t,
+                                               a.z + (b.z - a.z) * t,
+                                               0.f);
+}
+
+// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
+int clipFaceGlobal(__global const b3Float4* pVtxIn, int numVertsIn, b3Float4ConstArg planeNormalWS, float planeEqWS, __global b3Float4* ppVtxOut)
+{
+       int ve;
+       float ds, de;
+       int numVertsOut = 0;
+       //double-check next test
+       //      if (numVertsIn < 2)
+       //              return 0;
+
+       b3Float4 firstVertex = pVtxIn[numVertsIn - 1];
+       b3Float4 endVertex = pVtxIn[0];
+
+       ds = b3Dot(planeNormalWS, firstVertex) + planeEqWS;
+
+       for (ve = 0; ve < numVertsIn; ve++)
+       {
+               endVertex = pVtxIn[ve];
+               de = b3Dot(planeNormalWS, endVertex) + planeEqWS;
+               if (ds < 0)
+               {
+                       if (de < 0)
+                       {
+                               // Start < 0, end < 0, so output endVertex
+                               ppVtxOut[numVertsOut++] = endVertex;
+                       }
+                       else
+                       {
+                               // Start < 0, end >= 0, so output intersection
+                               ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
+                       }
+               }
+               else
+               {
+                       if (de < 0)
+                       {
+                               // Start >= 0, end < 0 so output intersection and end
+                               ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
+                               ppVtxOut[numVertsOut++] = endVertex;
+                       }
+               }
+               firstVertex = endVertex;
+               ds = de;
+       }
+       return numVertsOut;
+}
+
+__kernel void clipFacesAndFindContactsKernel(__global const b3Float4* separatingNormals,
+                                                                                        __global const int* hasSeparatingAxis,
+                                                                                        __global b3Int4* clippingFacesOut,
+                                                                                        __global b3Float4* worldVertsA1,
+                                                                                        __global b3Float4* worldNormalsA1,
+                                                                                        __global b3Float4* worldVertsB1,
+                                                                                        __global b3Float4* worldVertsB2,
+                                                                                        int vertexFaceCapacity,
+                                                                                        int pairIndex)
+{
+       //    int i = get_global_id(0);
+       //int pairIndex = i;
+       int i = pairIndex;
+
+       float minDist = -1e30f;
+       float maxDist = 0.02f;
+
+       //      if (i<numPairs)
+       {
+               if (hasSeparatingAxis[i])
+               {
+                       //                      int bodyIndexA = pairs[i].x;
+                       //              int bodyIndexB = pairs[i].y;
+
+                       int numLocalContactsOut = 0;
+
+                       int capacityWorldVertsB2 = vertexFaceCapacity;
+
+                       __global b3Float4* pVtxIn = &worldVertsB1[pairIndex * capacityWorldVertsB2];
+                       __global b3Float4* pVtxOut = &worldVertsB2[pairIndex * capacityWorldVertsB2];
+
+                       {
+                               __global b3Int4* clippingFaces = clippingFacesOut;
+
+                               int closestFaceA = clippingFaces[pairIndex].x;
+                               // int closestFaceB = clippingFaces[pairIndex].y;
+                               int numVertsInA = clippingFaces[pairIndex].z;
+                               int numVertsInB = clippingFaces[pairIndex].w;
+
+                               int numVertsOut = 0;
+
+                               if (closestFaceA >= 0)
+                               {
+                                       // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+
+                                       for (int e0 = 0; e0 < numVertsInA; e0++)
+                                       {
+                                               const b3Float4 aw = worldVertsA1[pairIndex * capacityWorldVertsB2 + e0];
+                                               const b3Float4 bw = worldVertsA1[pairIndex * capacityWorldVertsB2 + ((e0 + 1) % numVertsInA)];
+                                               const b3Float4 WorldEdge0 = aw - bw;
+                                               b3Float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
+                                               b3Float4 planeNormalWS1 = -b3Cross(WorldEdge0, worldPlaneAnormal1);
+                                               b3Float4 worldA1 = aw;
+                                               float planeEqWS1 = -b3Dot(worldA1, planeNormalWS1);
+                                               b3Float4 planeNormalWS = planeNormalWS1;
+                                               float planeEqWS = planeEqWS1;
+                                               numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS, planeEqWS, pVtxOut);
+                                               __global b3Float4* tmp = pVtxOut;
+                                               pVtxOut = pVtxIn;
+                                               pVtxIn = tmp;
+                                               numVertsInB = numVertsOut;
+                                               numVertsOut = 0;
+                                       }
+
+                                       b3Float4 planeNormalWS = worldNormalsA1[pairIndex];
+                                       float planeEqWS = -b3Dot(planeNormalWS, worldVertsA1[pairIndex * capacityWorldVertsB2]);
+
+                                       for (int i = 0; i < numVertsInB; i++)
+                                       {
+                                               float depth = b3Dot(planeNormalWS, pVtxIn[i]) + planeEqWS;
+                                               if (depth <= minDist)
+                                               {
+                                                       depth = minDist;
+                                               }
+                                               /*
+                                               static float maxDepth = 0.f;
+                                               if (depth < maxDepth)
+                                               {
+                                                       maxDepth = depth;
+                                                       if (maxDepth < -10)
+                                                       {
+                                                               printf("error at framecount %d?\n",myframecount);
+                                                       }
+                                                       printf("maxDepth = %f\n", maxDepth);
+
+                                               }
+*/
+                                               if (depth <= maxDist)
+                                               {
+                                                       b3Float4 pointInWorld = pVtxIn[i];
+                                                       pVtxOut[numLocalContactsOut++] = b3MakeFloat4(pointInWorld.x, pointInWorld.y, pointInWorld.z, depth);
+                                               }
+                                       }
+                               }
+                               clippingFaces[pairIndex].w = numLocalContactsOut;
+                       }
+
+                       for (int i = 0; i < numLocalContactsOut; i++)
+                               pVtxIn[i] = pVtxOut[i];
+
+               }  //           if (hasSeparatingAxis[i])
+       }      //       if (i<numPairs)
+}
+
+#endif  //B3_CLIP_FACES_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h
new file mode 100644 (file)
index 0000000..9a8c668
--- /dev/null
@@ -0,0 +1,69 @@
+
+#ifndef B3_COLLIDABLE_H
+#define B3_COLLIDABLE_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Common/shared/b3Quat.h"
+
+enum b3ShapeTypes
+{
+       SHAPE_HEIGHT_FIELD = 1,
+
+       SHAPE_CONVEX_HULL = 3,
+       SHAPE_PLANE = 4,
+       SHAPE_CONCAVE_TRIMESH = 5,
+       SHAPE_COMPOUND_OF_CONVEX_HULLS = 6,
+       SHAPE_SPHERE = 7,
+       MAX_NUM_SHAPE_TYPES,
+};
+
+typedef struct b3Collidable b3Collidable_t;
+
+struct b3Collidable
+{
+       union {
+               int m_numChildShapes;
+               int m_bvhIndex;
+       };
+       union {
+               float m_radius;
+               int m_compoundBvhIndex;
+       };
+
+       int m_shapeType;
+       union {
+               int m_shapeIndex;
+               float m_height;
+       };
+};
+
+typedef struct b3GpuChildShape b3GpuChildShape_t;
+struct b3GpuChildShape
+{
+       b3Float4 m_childPosition;
+       b3Quat m_childOrientation;
+       union {
+               int m_shapeIndex;  //used for SHAPE_COMPOUND_OF_CONVEX_HULLS
+               int m_capsuleAxis;
+       };
+       union {
+               float m_radius;        //used for childshape of SHAPE_COMPOUND_OF_SPHERES or SHAPE_COMPOUND_OF_CAPSULES
+               int m_numChildShapes;  //used for compound shape
+       };
+       union {
+               float m_height;  //used for childshape of SHAPE_COMPOUND_OF_CAPSULES
+               int m_collidableShapeIndex;
+       };
+       int m_shapeType;
+};
+
+struct b3CompoundOverlappingPair
+{
+       int m_bodyIndexA;
+       int m_bodyIndexB;
+       //      int     m_pairType;
+       int m_childShapeIndexA;
+       int m_childShapeIndexB;
+};
+
+#endif  //B3_COLLIDABLE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h
new file mode 100644 (file)
index 0000000..d5f6daa
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef B3_CONTACT4DATA_H
+#define B3_CONTACT4DATA_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+
+typedef struct b3Contact4Data b3Contact4Data_t;
+
+struct b3Contact4Data
+{
+       b3Float4 m_worldPosB[4];
+       //      b3Float4        m_localPosA[4];
+       //      b3Float4        m_localPosB[4];
+       b3Float4 m_worldNormalOnB;  //  w: m_nPoints
+       unsigned short m_restituitionCoeffCmp;
+       unsigned short m_frictionCoeffCmp;
+       int m_batchIdx;
+       int m_bodyAPtrAndSignBit;  //x:m_bodyAPtr, y:m_bodyBPtr
+       int m_bodyBPtrAndSignBit;
+
+       int m_childIndexA;
+       int m_childIndexB;
+       int m_unused1;
+       int m_unused2;
+};
+
+inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)
+{
+       return (int)contact->m_worldNormalOnB.w;
+};
+
+inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)
+{
+       contact->m_worldNormalOnB.w = (float)numPoints;
+};
+
+#endif  //B3_CONTACT4DATA_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h
new file mode 100644 (file)
index 0000000..ca68f4b
--- /dev/null
@@ -0,0 +1,486 @@
+
+#ifndef B3_CONTACT_CONVEX_CONVEX_SAT_H
+#define B3_CONTACT_CONVEX_CONVEX_SAT_H
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h"
+
+#define B3_MAX_VERTS 1024
+
+inline b3Float4 b3Lerp3(const b3Float4& a, const b3Float4& b, float t)
+{
+       return b3MakeVector3(a.x + (b.x - a.x) * t,
+                                                a.y + (b.y - a.y) * t,
+                                                a.z + (b.z - a.z) * t,
+                                                0.f);
+}
+
+// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
+inline int b3ClipFace(const b3Float4* pVtxIn, int numVertsIn, b3Float4& planeNormalWS, float planeEqWS, b3Float4* ppVtxOut)
+{
+       int ve;
+       float ds, de;
+       int numVertsOut = 0;
+       if (numVertsIn < 2)
+               return 0;
+
+       b3Float4 firstVertex = pVtxIn[numVertsIn - 1];
+       b3Float4 endVertex = pVtxIn[0];
+
+       ds = b3Dot3F4(planeNormalWS, firstVertex) + planeEqWS;
+
+       for (ve = 0; ve < numVertsIn; ve++)
+       {
+               endVertex = pVtxIn[ve];
+
+               de = b3Dot3F4(planeNormalWS, endVertex) + planeEqWS;
+
+               if (ds < 0)
+               {
+                       if (de < 0)
+                       {
+                               // Start < 0, end < 0, so output endVertex
+                               ppVtxOut[numVertsOut++] = endVertex;
+                       }
+                       else
+                       {
+                               // Start < 0, end >= 0, so output intersection
+                               ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
+                       }
+               }
+               else
+               {
+                       if (de < 0)
+                       {
+                               // Start >= 0, end < 0 so output intersection and end
+                               ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
+                               ppVtxOut[numVertsOut++] = endVertex;
+                       }
+               }
+               firstVertex = endVertex;
+               ds = de;
+       }
+       return numVertsOut;
+}
+
+inline int b3ClipFaceAgainstHull(const b3Float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
+                                                                const b3Float4& posA, const b3Quaternion& ornA, b3Float4* worldVertsB1, int numWorldVertsB1,
+                                                                b3Float4* worldVertsB2, int capacityWorldVertsB2,
+                                                                const float minDist, float maxDist,
+                                                                const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+                                                                //const b3Float4* verticesB,   const b3GpuFace* facesB,        const int* indicesB,
+                                                                b3Float4* contactsOut,
+                                                                int contactCapacity)
+{
+       int numContactsOut = 0;
+
+       b3Float4* pVtxIn = worldVertsB1;
+       b3Float4* pVtxOut = worldVertsB2;
+
+       int numVertsIn = numWorldVertsB1;
+       int numVertsOut = 0;
+
+       int closestFaceA = -1;
+       {
+               float dmin = FLT_MAX;
+               for (int face = 0; face < hullA->m_numFaces; face++)
+               {
+                       const b3Float4 Normal = b3MakeVector3(
+                               facesA[hullA->m_faceOffset + face].m_plane.x,
+                               facesA[hullA->m_faceOffset + face].m_plane.y,
+                               facesA[hullA->m_faceOffset + face].m_plane.z, 0.f);
+                       const b3Float4 faceANormalWS = b3QuatRotate(ornA, Normal);
+
+                       float d = b3Dot3F4(faceANormalWS, separatingNormal);
+                       if (d < dmin)
+                       {
+                               dmin = d;
+                               closestFaceA = face;
+                       }
+               }
+       }
+       if (closestFaceA < 0)
+               return numContactsOut;
+
+       b3GpuFace polyA = facesA[hullA->m_faceOffset + closestFaceA];
+
+       // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+       //int numContacts = numWorldVertsB1;
+       int numVerticesA = polyA.m_numIndices;
+       for (int e0 = 0; e0 < numVerticesA; e0++)
+       {
+               const b3Float4 a = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + e0]];
+               const b3Float4 b = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + ((e0 + 1) % numVerticesA)]];
+               const b3Float4 edge0 = a - b;
+               const b3Float4 WorldEdge0 = b3QuatRotate(ornA, edge0);
+               b3Float4 planeNormalA = b3MakeFloat4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
+               b3Float4 worldPlaneAnormal1 = b3QuatRotate(ornA, planeNormalA);
+
+               b3Float4 planeNormalWS1 = -b3Cross3(WorldEdge0, worldPlaneAnormal1);
+               b3Float4 worldA1 = b3TransformPoint(a, posA, ornA);
+               float planeEqWS1 = -b3Dot3F4(worldA1, planeNormalWS1);
+
+               b3Float4 planeNormalWS = planeNormalWS1;
+               float planeEqWS = planeEqWS1;
+
+               //clip face
+               //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
+               numVertsOut = b3ClipFace(pVtxIn, numVertsIn, planeNormalWS, planeEqWS, pVtxOut);
+
+               //btSwap(pVtxIn,pVtxOut);
+               b3Float4* tmp = pVtxOut;
+               pVtxOut = pVtxIn;
+               pVtxIn = tmp;
+               numVertsIn = numVertsOut;
+               numVertsOut = 0;
+       }
+
+       // only keep points that are behind the witness face
+       {
+               b3Float4 localPlaneNormal = b3MakeFloat4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
+               float localPlaneEq = polyA.m_plane.w;
+               b3Float4 planeNormalWS = b3QuatRotate(ornA, localPlaneNormal);
+               float planeEqWS = localPlaneEq - b3Dot3F4(planeNormalWS, posA);
+               for (int i = 0; i < numVertsIn; i++)
+               {
+                       float depth = b3Dot3F4(planeNormalWS, pVtxIn[i]) + planeEqWS;
+                       if (depth <= minDist)
+                       {
+                               depth = minDist;
+                       }
+                       if (numContactsOut < contactCapacity)
+                       {
+                               if (depth <= maxDist)
+                               {
+                                       b3Float4 pointInWorld = pVtxIn[i];
+                                       //resultOut.addContactPoint(separatingNormal,point,depth);
+                                       contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x, pointInWorld.y, pointInWorld.z, depth);
+                                       //printf("depth=%f\n",depth);
+                               }
+                       }
+                       else
+                       {
+                               b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut, contactCapacity);
+                       }
+               }
+       }
+
+       return numContactsOut;
+}
+
+inline int b3ClipHullAgainstHull(const b3Float4& separatingNormal,
+                                                                const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+                                                                const b3Float4& posA, const b3Quaternion& ornA, const b3Float4& posB, const b3Quaternion& ornB,
+                                                                b3Float4* worldVertsB1, b3Float4* worldVertsB2, int capacityWorldVerts,
+                                                                const float minDist, float maxDist,
+                                                                const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+                                                                const b3AlignedObjectArray<b3Float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
+
+                                                                b3Float4* contactsOut,
+                                                                int contactCapacity)
+{
+       int numContactsOut = 0;
+       int numWorldVertsB1 = 0;
+
+       B3_PROFILE("clipHullAgainstHull");
+
+       //float curMaxDist=maxDist;
+       int closestFaceB = -1;
+       float dmax = -FLT_MAX;
+
+       {
+               //B3_PROFILE("closestFaceB");
+               if (hullB.m_numFaces != 1)
+               {
+                       //printf("wtf\n");
+               }
+               static bool once = true;
+               //printf("separatingNormal=%f,%f,%f\n",separatingNormal.x,separatingNormal.y,separatingNormal.z);
+
+               for (int face = 0; face < hullB.m_numFaces; face++)
+               {
+#ifdef BT_DEBUG_SAT_FACE
+                       if (once)
+                               printf("face %d\n", face);
+                       const b3GpuFace* faceB = &facesB[hullB.m_faceOffset + face];
+                       if (once)
+                       {
+                               for (int i = 0; i < faceB->m_numIndices; i++)
+                               {
+                                       b3Float4 vert = verticesB[hullB.m_vertexOffset + indicesB[faceB->m_indexOffset + i]];
+                                       printf("vert[%d] = %f,%f,%f\n", i, vert.x, vert.y, vert.z);
+                               }
+                       }
+#endif  //BT_DEBUG_SAT_FACE \
+       //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
+                       {
+                               const b3Float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset + face].m_plane.x,
+                                                                                                         facesB[hullB.m_faceOffset + face].m_plane.y, facesB[hullB.m_faceOffset + face].m_plane.z, 0.f);
+                               const b3Float4 WorldNormal = b3QuatRotate(ornB, Normal);
+#ifdef BT_DEBUG_SAT_FACE
+                               if (once)
+                                       printf("faceNormal = %f,%f,%f\n", Normal.x, Normal.y, Normal.z);
+#endif
+                               float d = b3Dot3F4(WorldNormal, separatingNormal);
+                               if (d > dmax)
+                               {
+                                       dmax = d;
+                                       closestFaceB = face;
+                               }
+                       }
+               }
+               once = false;
+       }
+
+       b3Assert(closestFaceB >= 0);
+       {
+               //B3_PROFILE("worldVertsB1");
+               const b3GpuFace& polyB = facesB[hullB.m_faceOffset + closestFaceB];
+               const int numVertices = polyB.m_numIndices;
+               for (int e0 = 0; e0 < numVertices; e0++)
+               {
+                       const b3Float4& b = verticesB[hullB.m_vertexOffset + indicesB[polyB.m_indexOffset + e0]];
+                       worldVertsB1[numWorldVertsB1++] = b3TransformPoint(b, posB, ornB);
+               }
+       }
+
+       if (closestFaceB >= 0)
+       {
+               //B3_PROFILE("clipFaceAgainstHull");
+               numContactsOut = b3ClipFaceAgainstHull((b3Float4&)separatingNormal, &hullA,
+                                                                                          posA, ornA,
+                                                                                          worldVertsB1, numWorldVertsB1, worldVertsB2, capacityWorldVerts, minDist, maxDist,
+                                                                                          verticesA, facesA, indicesA,
+                                                                                          contactsOut, contactCapacity);
+       }
+
+       return numContactsOut;
+}
+
+inline int b3ClipHullHullSingle(
+       int bodyIndexA, int bodyIndexB,
+       const b3Float4& posA,
+       const b3Quaternion& ornA,
+       const b3Float4& posB,
+       const b3Quaternion& ornB,
+
+       int collidableIndexA, int collidableIndexB,
+
+       const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
+       b3AlignedObjectArray<b3Contact4Data>* globalContactOut,
+       int& nContacts,
+
+       const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
+       const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
+
+       const b3AlignedObjectArray<b3Vector3>& verticesA,
+       const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+       const b3AlignedObjectArray<b3GpuFace>& facesA,
+       const b3AlignedObjectArray<int>& indicesA,
+
+       const b3AlignedObjectArray<b3Vector3>& verticesB,
+       const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+       const b3AlignedObjectArray<b3GpuFace>& facesB,
+       const b3AlignedObjectArray<int>& indicesB,
+
+       const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
+       const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
+       const b3Vector3& sepNormalWorldSpace,
+       int maxContactCapacity)
+{
+       int contactIndex = -1;
+       b3ConvexPolyhedronData hullA, hullB;
+
+       b3Collidable colA = hostCollidablesA[collidableIndexA];
+       hullA = hostConvexDataA[colA.m_shapeIndex];
+       //printf("numvertsA = %d\n",hullA.m_numVertices);
+
+       b3Collidable colB = hostCollidablesB[collidableIndexB];
+       hullB = hostConvexDataB[colB.m_shapeIndex];
+       //printf("numvertsB = %d\n",hullB.m_numVertices);
+
+       b3Float4 contactsOut[B3_MAX_VERTS];
+       int localContactCapacity = B3_MAX_VERTS;
+
+#ifdef _WIN32
+       b3Assert(_finite(bodyBuf->at(bodyIndexA).m_pos.x));
+       b3Assert(_finite(bodyBuf->at(bodyIndexB).m_pos.x));
+#endif
+
+       {
+               b3Float4 worldVertsB1[B3_MAX_VERTS];
+               b3Float4 worldVertsB2[B3_MAX_VERTS];
+               int capacityWorldVerts = B3_MAX_VERTS;
+
+               b3Float4 hostNormal = b3MakeFloat4(sepNormalWorldSpace.x, sepNormalWorldSpace.y, sepNormalWorldSpace.z, 0.f);
+               int shapeA = hostCollidablesA[collidableIndexA].m_shapeIndex;
+               int shapeB = hostCollidablesB[collidableIndexB].m_shapeIndex;
+
+               b3Scalar minDist = -1;
+               b3Scalar maxDist = 0.;
+
+               b3Transform trA, trB;
+               {
+                       //B3_PROFILE("b3TransformPoint computation");
+                       //trA.setIdentity();
+                       trA.setOrigin(b3MakeVector3(posA.x, posA.y, posA.z));
+                       trA.setRotation(b3Quaternion(ornA.x, ornA.y, ornA.z, ornA.w));
+
+                       //trB.setIdentity();
+                       trB.setOrigin(b3MakeVector3(posB.x, posB.y, posB.z));
+                       trB.setRotation(b3Quaternion(ornB.x, ornB.y, ornB.z, ornB.w));
+               }
+
+               b3Quaternion trAorn = trA.getRotation();
+               b3Quaternion trBorn = trB.getRotation();
+
+               int numContactsOut = b3ClipHullAgainstHull(hostNormal,
+                                                                                                  hostConvexDataA.at(shapeA),
+                                                                                                  hostConvexDataB.at(shapeB),
+                                                                                                  (b3Float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
+                                                                                                  (b3Float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
+                                                                                                  worldVertsB1, worldVertsB2, capacityWorldVerts,
+                                                                                                  minDist, maxDist,
+                                                                                                  verticesA, facesA, indicesA,
+                                                                                                  verticesB, facesB, indicesB,
+
+                                                                                                  contactsOut, localContactCapacity);
+
+               if (numContactsOut > 0)
+               {
+                       B3_PROFILE("overlap");
+
+                       b3Float4 normalOnSurfaceB = (b3Float4&)hostNormal;
+                       //                      b3Float4 centerOut;
+
+                       b3Int4 contactIdx;
+                       contactIdx.x = 0;
+                       contactIdx.y = 1;
+                       contactIdx.z = 2;
+                       contactIdx.w = 3;
+
+                       int numPoints = 0;
+
+                       {
+                               B3_PROFILE("extractManifold");
+                               numPoints = b3ReduceContacts(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
+                       }
+
+                       b3Assert(numPoints);
+
+                       if (nContacts < maxContactCapacity)
+                       {
+                               contactIndex = nContacts;
+                               globalContactOut->expand();
+                               b3Contact4Data& contact = globalContactOut->at(nContacts);
+                               contact.m_batchIdx = 0;  //i;
+                               contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass == 0) ? -bodyIndexA : bodyIndexA;
+                               contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass == 0) ? -bodyIndexB : bodyIndexB;
+
+                               contact.m_frictionCoeffCmp = 45874;
+                               contact.m_restituitionCoeffCmp = 0;
+
+                               //      float distance = 0.f;
+                               for (int p = 0; p < numPoints; p++)
+                               {
+                                       contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]];  //check if it is actually on B
+                                       contact.m_worldNormalOnB = normalOnSurfaceB;
+                               }
+                               //printf("bodyIndexA %d,bodyIndexB %d,normal=%f,%f,%f numPoints %d\n",bodyIndexA,bodyIndexB,normalOnSurfaceB.x,normalOnSurfaceB.y,normalOnSurfaceB.z,numPoints);
+                               contact.m_worldNormalOnB.w = (b3Scalar)numPoints;
+                               nContacts++;
+                       }
+                       else
+                       {
+                               b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts, maxContactCapacity);
+                       }
+               }
+       }
+       return contactIndex;
+}
+
+inline int b3ContactConvexConvexSAT(
+       int pairIndex,
+       int bodyIndexA, int bodyIndexB,
+       int collidableIndexA, int collidableIndexB,
+       const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
+       const b3AlignedObjectArray<b3Collidable>& collidables,
+       const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
+       const b3AlignedObjectArray<b3Float4>& convexVertices,
+       const b3AlignedObjectArray<b3Float4>& uniqueEdges,
+       const b3AlignedObjectArray<int>& convexIndices,
+       const b3AlignedObjectArray<b3GpuFace>& faces,
+       b3AlignedObjectArray<b3Contact4Data>& globalContactsOut,
+       int& nGlobalContactsOut,
+       int maxContactCapacity)
+{
+       int contactIndex = -1;
+
+       b3Float4 posA = rigidBodies[bodyIndexA].m_pos;
+       b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
+       b3Float4 posB = rigidBodies[bodyIndexB].m_pos;
+       b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
+
+       b3ConvexPolyhedronData hullA, hullB;
+
+       b3Float4 sepNormalWorldSpace;
+
+       b3Collidable colA = collidables[collidableIndexA];
+       hullA = convexShapes[colA.m_shapeIndex];
+       //printf("numvertsA = %d\n",hullA.m_numVertices);
+
+       b3Collidable colB = collidables[collidableIndexB];
+       hullB = convexShapes[colB.m_shapeIndex];
+       //printf("numvertsB = %d\n",hullB.m_numVertices);
+
+#ifdef _WIN32
+       b3Assert(_finite(rigidBodies[bodyIndexA].m_pos.x));
+       b3Assert(_finite(rigidBodies[bodyIndexB].m_pos.x));
+#endif
+
+       bool foundSepAxis = b3FindSeparatingAxis(hullA, hullB,
+                                                                                        posA,
+                                                                                        ornA,
+                                                                                        posB,
+                                                                                        ornB,
+
+                                                                                        convexVertices, uniqueEdges, faces, convexIndices,
+                                                                                        convexVertices, uniqueEdges, faces, convexIndices,
+
+                                                                                        sepNormalWorldSpace);
+
+       if (foundSepAxis)
+       {
+               contactIndex = b3ClipHullHullSingle(
+                       bodyIndexA, bodyIndexB,
+                       posA, ornA,
+                       posB, ornB,
+                       collidableIndexA, collidableIndexB,
+                       &rigidBodies,
+                       &globalContactsOut,
+                       nGlobalContactsOut,
+
+                       convexShapes,
+                       convexShapes,
+
+                       convexVertices,
+                       uniqueEdges,
+                       faces,
+                       convexIndices,
+
+                       convexVertices,
+                       uniqueEdges,
+                       faces,
+                       convexIndices,
+
+                       collidables,
+                       collidables,
+                       sepNormalWorldSpace,
+                       maxContactCapacity);
+       }
+
+       return contactIndex;
+}
+
+#endif  //B3_CONTACT_CONVEX_CONVEX_SAT_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h
new file mode 100644 (file)
index 0000000..acf7c1b
--- /dev/null
@@ -0,0 +1,153 @@
+
+#ifndef B3_CONTACT_SPHERE_SPHERE_H
+#define B3_CONTACT_SPHERE_SPHERE_H
+
+void computeContactSphereConvex(int pairIndex,
+                                                               int bodyIndexA, int bodyIndexB,
+                                                               int collidableIndexA, int collidableIndexB,
+                                                               const b3RigidBodyData* rigidBodies,
+                                                               const b3Collidable* collidables,
+                                                               const b3ConvexPolyhedronData* convexShapes,
+                                                               const b3Vector3* convexVertices,
+                                                               const int* convexIndices,
+                                                               const b3GpuFace* faces,
+                                                               b3Contact4* globalContactsOut,
+                                                               int& nGlobalContactsOut,
+                                                               int maxContactCapacity)
+{
+       float radius = collidables[collidableIndexA].m_radius;
+       float4 spherePos1 = rigidBodies[bodyIndexA].m_pos;
+       b3Quaternion sphereOrn = rigidBodies[bodyIndexA].m_quat;
+
+       float4 pos = rigidBodies[bodyIndexB].m_pos;
+
+       b3Quaternion quat = rigidBodies[bodyIndexB].m_quat;
+
+       b3Transform tr;
+       tr.setIdentity();
+       tr.setOrigin(pos);
+       tr.setRotation(quat);
+       b3Transform trInv = tr.inverse();
+
+       float4 spherePos = trInv(spherePos1);
+
+       int collidableIndex = rigidBodies[bodyIndexB].m_collidableIdx;
+       int shapeIndex = collidables[collidableIndex].m_shapeIndex;
+       int numFaces = convexShapes[shapeIndex].m_numFaces;
+       float4 closestPnt = b3MakeVector3(0, 0, 0, 0);
+       float4 hitNormalWorld = b3MakeVector3(0, 0, 0, 0);
+       float minDist = -1000000.f;  // TODO: What is the largest/smallest float?
+       bool bCollide = true;
+       int region = -1;
+       float4 localHitNormal;
+       for (int f = 0; f < numFaces; f++)
+       {
+               b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset + f];
+               float4 planeEqn;
+               float4 localPlaneNormal = b3MakeVector3(face.m_plane.x, face.m_plane.y, face.m_plane.z, 0.f);
+               float4 n1 = localPlaneNormal;  //quatRotate(quat,localPlaneNormal);
+               planeEqn = n1;
+               planeEqn[3] = face.m_plane.w;
+
+               float4 pntReturn;
+               float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
+
+               if (dist > radius)
+               {
+                       bCollide = false;
+                       break;
+               }
+
+               if (dist > 0)
+               {
+                       //might hit an edge or vertex
+                       b3Vector3 out;
+
+                       bool isInPoly = IsPointInPolygon(spherePos,
+                                                                                        &face,
+                                                                                        &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
+                                                                                        convexIndices,
+                                                                                        &out);
+                       if (isInPoly)
+                       {
+                               if (dist > minDist)
+                               {
+                                       minDist = dist;
+                                       closestPnt = pntReturn;
+                                       localHitNormal = planeEqn;
+                                       region = 1;
+                               }
+                       }
+                       else
+                       {
+                               b3Vector3 tmp = spherePos - out;
+                               b3Scalar l2 = tmp.length2();
+                               if (l2 < radius * radius)
+                               {
+                                       dist = b3Sqrt(l2);
+                                       if (dist > minDist)
+                                       {
+                                               minDist = dist;
+                                               closestPnt = out;
+                                               localHitNormal = tmp / dist;
+                                               region = 2;
+                                       }
+                               }
+                               else
+                               {
+                                       bCollide = false;
+                                       break;
+                               }
+                       }
+               }
+               else
+               {
+                       if (dist > minDist)
+                       {
+                               minDist = dist;
+                               closestPnt = pntReturn;
+                               localHitNormal = planeEqn;
+                               region = 3;
+                       }
+               }
+       }
+       static int numChecks = 0;
+       numChecks++;
+
+       if (bCollide && minDist > -10000)
+       {
+               float4 normalOnSurfaceB1 = tr.getBasis() * localHitNormal;  //-hitNormalWorld;
+               float4 pOnB1 = tr(closestPnt);
+               //printf("dist ,%f,",minDist);
+               float actualDepth = minDist - radius;
+               if (actualDepth < 0)
+               {
+                       //printf("actualDepth = ,%f,", actualDepth);
+                       //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z);
+                       //printf("region=,%d,\n", region);
+                       pOnB1[3] = actualDepth;
+
+                       int dstIdx;
+                       //    dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+                       if (nGlobalContactsOut < maxContactCapacity)
+                       {
+                               dstIdx = nGlobalContactsOut;
+                               nGlobalContactsOut++;
+
+                               b3Contact4* c = &globalContactsOut[dstIdx];
+                               c->m_worldNormalOnB = normalOnSurfaceB1;
+                               c->setFrictionCoeff(0.7);
+                               c->setRestituitionCoeff(0.f);
+
+                               c->m_batchIdx = pairIndex;
+                               c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
+                               c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
+                               c->m_worldPosB[0] = pOnB1;
+                               int numPoints = 1;
+                               c->m_worldNormalOnB.w = (b3Scalar)numPoints;
+                       }  //if (dstIdx < numPairs)
+               }
+       }  //if (hasCollision)
+}
+#endif  //B3_CONTACT_SPHERE_SPHERE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h
new file mode 100644 (file)
index 0000000..d5a73bd
--- /dev/null
@@ -0,0 +1,38 @@
+
+#ifndef B3_CONVEX_POLYHEDRON_DATA_H
+#define B3_CONVEX_POLYHEDRON_DATA_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Common/shared/b3Quat.h"
+
+typedef struct b3GpuFace b3GpuFace_t;
+struct b3GpuFace
+{
+       b3Float4 m_plane;
+       int m_indexOffset;
+       int m_numIndices;
+       int m_unusedPadding1;
+       int m_unusedPadding2;
+};
+
+typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;
+
+struct b3ConvexPolyhedronData
+{
+       b3Float4 m_localCenter;
+       b3Float4 m_extents;
+       b3Float4 mC;
+       b3Float4 mE;
+
+       float m_radius;
+       int m_faceOffset;
+       int m_numFaces;
+       int m_numVertices;
+
+       int m_vertexOffset;
+       int m_uniqueEdgesOffset;
+       int m_numUniqueEdges;
+       int m_unused;
+};
+
+#endif  //B3_CONVEX_POLYHEDRON_DATA_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h
new file mode 100644 (file)
index 0000000..983554e
--- /dev/null
@@ -0,0 +1,797 @@
+#ifndef B3_FIND_CONCAVE_SEPARATING_AXIS_H
+#define B3_FIND_CONCAVE_SEPARATING_AXIS_H
+
+#define B3_TRIANGLE_NUM_CONVEX_FACES 5
+
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+
+inline void b3Project(__global const b3ConvexPolyhedronData* hull, b3Float4ConstArg pos, b3QuatConstArg orn,
+                                         const b3Float4* dir, __global const b3Float4* vertices, float* min, float* max)
+{
+       min[0] = FLT_MAX;
+       max[0] = -FLT_MAX;
+       int numVerts = hull->m_numVertices;
+
+       const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn), *dir);
+       float offset = b3Dot(pos, *dir);
+       for (int i = 0; i < numVerts; i++)
+       {
+               float dp = b3Dot(vertices[hull->m_vertexOffset + i], localDir);
+               if (dp < min[0])
+                       min[0] = dp;
+               if (dp > max[0])
+                       max[0] = dp;
+       }
+       if (min[0] > max[0])
+       {
+               float tmp = min[0];
+               min[0] = max[0];
+               max[0] = tmp;
+       }
+       min[0] += offset;
+       max[0] += offset;
+}
+
+inline bool b3TestSepAxis(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+                                                 b3Float4ConstArg posA, b3QuatConstArg ornA,
+                                                 b3Float4ConstArg posB, b3QuatConstArg ornB,
+                                                 b3Float4* sep_axis, const b3Float4* verticesA, __global const b3Float4* verticesB, float* depth)
+{
+       float Min0, Max0;
+       float Min1, Max1;
+       b3Project(hullA, posA, ornA, sep_axis, verticesA, &Min0, &Max0);
+       b3Project(hullB, posB, ornB, sep_axis, verticesB, &Min1, &Max1);
+
+       if (Max0 < Min1 || Max1 < Min0)
+               return false;
+
+       float d0 = Max0 - Min1;
+       float d1 = Max1 - Min0;
+       *depth = d0 < d1 ? d0 : d1;
+       return true;
+}
+
+bool b3FindSeparatingAxis(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+                                                 b3Float4ConstArg posA1,
+                                                 b3QuatConstArg ornA,
+                                                 b3Float4ConstArg posB1,
+                                                 b3QuatConstArg ornB,
+                                                 b3Float4ConstArg DeltaC2,
+
+                                                 const b3Float4* verticesA,
+                                                 const b3Float4* uniqueEdgesA,
+                                                 const b3GpuFace* facesA,
+                                                 const int* indicesA,
+
+                                                 __global const b3Float4* verticesB,
+                                                 __global const b3Float4* uniqueEdgesB,
+                                                 __global const b3GpuFace* facesB,
+                                                 __global const int* indicesB,
+                                                 b3Float4* sep,
+                                                 float* dmin)
+{
+       b3Float4 posA = posA1;
+       posA.w = 0.f;
+       b3Float4 posB = posB1;
+       posB.w = 0.f;
+       /*
+       static int maxFaceVertex = 0;
+
+       int curFaceVertexAB = hullA->m_numFaces*hullB->m_numVertices;
+       curFaceVertexAB+= hullB->m_numFaces*hullA->m_numVertices;
+
+       if (curFaceVertexAB>maxFaceVertex)
+       {
+               maxFaceVertex = curFaceVertexAB;
+               printf("curFaceVertexAB = %d\n",curFaceVertexAB);
+               printf("hullA->m_numFaces = %d\n",hullA->m_numFaces);
+               printf("hullA->m_numVertices = %d\n",hullA->m_numVertices);
+               printf("hullB->m_numVertices = %d\n",hullB->m_numVertices);
+       }
+*/
+
+       int curPlaneTests = 0;
+       {
+               int numFacesA = hullA->m_numFaces;
+               // Test normals from hullA
+               for (int i = 0; i < numFacesA; i++)
+               {
+                       const b3Float4 normal = facesA[hullA->m_faceOffset + i].m_plane;
+                       b3Float4 faceANormalWS = b3QuatRotate(ornA, normal);
+                       if (b3Dot(DeltaC2, faceANormalWS) < 0)
+                               faceANormalWS *= -1.f;
+                       curPlaneTests++;
+                       float d;
+                       if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, &faceANormalWS, verticesA, verticesB, &d))
+                               return false;
+                       if (d < *dmin)
+                       {
+                               *dmin = d;
+                               *sep = faceANormalWS;
+                       }
+               }
+       }
+       if ((b3Dot(-DeltaC2, *sep)) > 0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+b3Vector3 unitSphere162[] =
+       {
+               b3MakeVector3(0.000000, -1.000000, 0.000000),
+               b3MakeVector3(0.203181, -0.967950, 0.147618),
+               b3MakeVector3(-0.077607, -0.967950, 0.238853),
+               b3MakeVector3(0.723607, -0.447220, 0.525725),
+               b3MakeVector3(0.609547, -0.657519, 0.442856),
+               b3MakeVector3(0.812729, -0.502301, 0.295238),
+               b3MakeVector3(-0.251147, -0.967949, 0.000000),
+               b3MakeVector3(-0.077607, -0.967950, -0.238853),
+               b3MakeVector3(0.203181, -0.967950, -0.147618),
+               b3MakeVector3(0.860698, -0.251151, 0.442858),
+               b3MakeVector3(-0.276388, -0.447220, 0.850649),
+               b3MakeVector3(-0.029639, -0.502302, 0.864184),
+               b3MakeVector3(-0.155215, -0.251152, 0.955422),
+               b3MakeVector3(-0.894426, -0.447216, 0.000000),
+               b3MakeVector3(-0.831051, -0.502299, 0.238853),
+               b3MakeVector3(-0.956626, -0.251149, 0.147618),
+               b3MakeVector3(-0.276388, -0.447220, -0.850649),
+               b3MakeVector3(-0.483971, -0.502302, -0.716565),
+               b3MakeVector3(-0.436007, -0.251152, -0.864188),
+               b3MakeVector3(0.723607, -0.447220, -0.525725),
+               b3MakeVector3(0.531941, -0.502302, -0.681712),
+               b3MakeVector3(0.687159, -0.251152, -0.681715),
+               b3MakeVector3(0.687159, -0.251152, 0.681715),
+               b3MakeVector3(-0.436007, -0.251152, 0.864188),
+               b3MakeVector3(-0.956626, -0.251149, -0.147618),
+               b3MakeVector3(-0.155215, -0.251152, -0.955422),
+               b3MakeVector3(0.860698, -0.251151, -0.442858),
+               b3MakeVector3(0.276388, 0.447220, 0.850649),
+               b3MakeVector3(0.483971, 0.502302, 0.716565),
+               b3MakeVector3(0.232822, 0.657519, 0.716563),
+               b3MakeVector3(-0.723607, 0.447220, 0.525725),
+               b3MakeVector3(-0.531941, 0.502302, 0.681712),
+               b3MakeVector3(-0.609547, 0.657519, 0.442856),
+               b3MakeVector3(-0.723607, 0.447220, -0.525725),
+               b3MakeVector3(-0.812729, 0.502301, -0.295238),
+               b3MakeVector3(-0.609547, 0.657519, -0.442856),
+               b3MakeVector3(0.276388, 0.447220, -0.850649),
+               b3MakeVector3(0.029639, 0.502302, -0.864184),
+               b3MakeVector3(0.232822, 0.657519, -0.716563),
+               b3MakeVector3(0.894426, 0.447216, 0.000000),
+               b3MakeVector3(0.831051, 0.502299, -0.238853),
+               b3MakeVector3(0.753442, 0.657515, 0.000000),
+               b3MakeVector3(-0.232822, -0.657519, 0.716563),
+               b3MakeVector3(-0.162456, -0.850654, 0.499995),
+               b3MakeVector3(0.052790, -0.723612, 0.688185),
+               b3MakeVector3(0.138199, -0.894429, 0.425321),
+               b3MakeVector3(0.262869, -0.525738, 0.809012),
+               b3MakeVector3(0.361805, -0.723611, 0.587779),
+               b3MakeVector3(0.531941, -0.502302, 0.681712),
+               b3MakeVector3(0.425323, -0.850654, 0.309011),
+               b3MakeVector3(0.812729, -0.502301, -0.295238),
+               b3MakeVector3(0.609547, -0.657519, -0.442856),
+               b3MakeVector3(0.850648, -0.525736, 0.000000),
+               b3MakeVector3(0.670817, -0.723611, -0.162457),
+               b3MakeVector3(0.670817, -0.723610, 0.162458),
+               b3MakeVector3(0.425323, -0.850654, -0.309011),
+               b3MakeVector3(0.447211, -0.894428, 0.000001),
+               b3MakeVector3(-0.753442, -0.657515, 0.000000),
+               b3MakeVector3(-0.525730, -0.850652, 0.000000),
+               b3MakeVector3(-0.638195, -0.723609, 0.262864),
+               b3MakeVector3(-0.361801, -0.894428, 0.262864),
+               b3MakeVector3(-0.688189, -0.525736, 0.499997),
+               b3MakeVector3(-0.447211, -0.723610, 0.525729),
+               b3MakeVector3(-0.483971, -0.502302, 0.716565),
+               b3MakeVector3(-0.232822, -0.657519, -0.716563),
+               b3MakeVector3(-0.162456, -0.850654, -0.499995),
+               b3MakeVector3(-0.447211, -0.723611, -0.525727),
+               b3MakeVector3(-0.361801, -0.894429, -0.262863),
+               b3MakeVector3(-0.688189, -0.525736, -0.499997),
+               b3MakeVector3(-0.638195, -0.723609, -0.262863),
+               b3MakeVector3(-0.831051, -0.502299, -0.238853),
+               b3MakeVector3(0.361804, -0.723612, -0.587779),
+               b3MakeVector3(0.138197, -0.894429, -0.425321),
+               b3MakeVector3(0.262869, -0.525738, -0.809012),
+               b3MakeVector3(0.052789, -0.723611, -0.688186),
+               b3MakeVector3(-0.029639, -0.502302, -0.864184),
+               b3MakeVector3(0.956626, 0.251149, 0.147618),
+               b3MakeVector3(0.956626, 0.251149, -0.147618),
+               b3MakeVector3(0.951058, -0.000000, 0.309013),
+               b3MakeVector3(1.000000, 0.000000, 0.000000),
+               b3MakeVector3(0.947213, -0.276396, 0.162458),
+               b3MakeVector3(0.951058, 0.000000, -0.309013),
+               b3MakeVector3(0.947213, -0.276396, -0.162458),
+               b3MakeVector3(0.155215, 0.251152, 0.955422),
+               b3MakeVector3(0.436007, 0.251152, 0.864188),
+               b3MakeVector3(-0.000000, -0.000000, 1.000000),
+               b3MakeVector3(0.309017, 0.000000, 0.951056),
+               b3MakeVector3(0.138199, -0.276398, 0.951055),
+               b3MakeVector3(0.587786, 0.000000, 0.809017),
+               b3MakeVector3(0.447216, -0.276398, 0.850648),
+               b3MakeVector3(-0.860698, 0.251151, 0.442858),
+               b3MakeVector3(-0.687159, 0.251152, 0.681715),
+               b3MakeVector3(-0.951058, -0.000000, 0.309013),
+               b3MakeVector3(-0.809018, 0.000000, 0.587783),
+               b3MakeVector3(-0.861803, -0.276396, 0.425324),
+               b3MakeVector3(-0.587786, 0.000000, 0.809017),
+               b3MakeVector3(-0.670819, -0.276397, 0.688191),
+               b3MakeVector3(-0.687159, 0.251152, -0.681715),
+               b3MakeVector3(-0.860698, 0.251151, -0.442858),
+               b3MakeVector3(-0.587786, -0.000000, -0.809017),
+               b3MakeVector3(-0.809018, -0.000000, -0.587783),
+               b3MakeVector3(-0.670819, -0.276397, -0.688191),
+               b3MakeVector3(-0.951058, 0.000000, -0.309013),
+               b3MakeVector3(-0.861803, -0.276396, -0.425324),
+               b3MakeVector3(0.436007, 0.251152, -0.864188),
+               b3MakeVector3(0.155215, 0.251152, -0.955422),
+               b3MakeVector3(0.587786, -0.000000, -0.809017),
+               b3MakeVector3(0.309017, -0.000000, -0.951056),
+               b3MakeVector3(0.447216, -0.276398, -0.850648),
+               b3MakeVector3(0.000000, 0.000000, -1.000000),
+               b3MakeVector3(0.138199, -0.276398, -0.951055),
+               b3MakeVector3(0.670820, 0.276396, 0.688190),
+               b3MakeVector3(0.809019, -0.000002, 0.587783),
+               b3MakeVector3(0.688189, 0.525736, 0.499997),
+               b3MakeVector3(0.861804, 0.276394, 0.425323),
+               b3MakeVector3(0.831051, 0.502299, 0.238853),
+               b3MakeVector3(-0.447216, 0.276397, 0.850649),
+               b3MakeVector3(-0.309017, -0.000001, 0.951056),
+               b3MakeVector3(-0.262869, 0.525738, 0.809012),
+               b3MakeVector3(-0.138199, 0.276397, 0.951055),
+               b3MakeVector3(0.029639, 0.502302, 0.864184),
+               b3MakeVector3(-0.947213, 0.276396, -0.162458),
+               b3MakeVector3(-1.000000, 0.000001, 0.000000),
+               b3MakeVector3(-0.850648, 0.525736, -0.000000),
+               b3MakeVector3(-0.947213, 0.276397, 0.162458),
+               b3MakeVector3(-0.812729, 0.502301, 0.295238),
+               b3MakeVector3(-0.138199, 0.276397, -0.951055),
+               b3MakeVector3(-0.309016, -0.000000, -0.951057),
+               b3MakeVector3(-0.262869, 0.525738, -0.809012),
+               b3MakeVector3(-0.447215, 0.276397, -0.850649),
+               b3MakeVector3(-0.531941, 0.502302, -0.681712),
+               b3MakeVector3(0.861804, 0.276396, -0.425322),
+               b3MakeVector3(0.809019, 0.000000, -0.587782),
+               b3MakeVector3(0.688189, 0.525736, -0.499997),
+               b3MakeVector3(0.670821, 0.276397, -0.688189),
+               b3MakeVector3(0.483971, 0.502302, -0.716565),
+               b3MakeVector3(0.077607, 0.967950, 0.238853),
+               b3MakeVector3(0.251147, 0.967949, 0.000000),
+               b3MakeVector3(0.000000, 1.000000, 0.000000),
+               b3MakeVector3(0.162456, 0.850654, 0.499995),
+               b3MakeVector3(0.361800, 0.894429, 0.262863),
+               b3MakeVector3(0.447209, 0.723612, 0.525728),
+               b3MakeVector3(0.525730, 0.850652, 0.000000),
+               b3MakeVector3(0.638194, 0.723610, 0.262864),
+               b3MakeVector3(-0.203181, 0.967950, 0.147618),
+               b3MakeVector3(-0.425323, 0.850654, 0.309011),
+               b3MakeVector3(-0.138197, 0.894430, 0.425320),
+               b3MakeVector3(-0.361804, 0.723612, 0.587778),
+               b3MakeVector3(-0.052790, 0.723612, 0.688185),
+               b3MakeVector3(-0.203181, 0.967950, -0.147618),
+               b3MakeVector3(-0.425323, 0.850654, -0.309011),
+               b3MakeVector3(-0.447210, 0.894429, 0.000000),
+               b3MakeVector3(-0.670817, 0.723611, -0.162457),
+               b3MakeVector3(-0.670817, 0.723611, 0.162457),
+               b3MakeVector3(0.077607, 0.967950, -0.238853),
+               b3MakeVector3(0.162456, 0.850654, -0.499995),
+               b3MakeVector3(-0.138197, 0.894430, -0.425320),
+               b3MakeVector3(-0.052790, 0.723612, -0.688185),
+               b3MakeVector3(-0.361804, 0.723612, -0.587778),
+               b3MakeVector3(0.361800, 0.894429, -0.262863),
+               b3MakeVector3(0.638194, 0.723610, -0.262864),
+               b3MakeVector3(0.447209, 0.723612, -0.525728)};
+
+bool b3FindSeparatingAxisEdgeEdge(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+                                                                 b3Float4ConstArg posA1,
+                                                                 b3QuatConstArg ornA,
+                                                                 b3Float4ConstArg posB1,
+                                                                 b3QuatConstArg ornB,
+                                                                 b3Float4ConstArg DeltaC2,
+                                                                 const b3Float4* verticesA,
+                                                                 const b3Float4* uniqueEdgesA,
+                                                                 const b3GpuFace* facesA,
+                                                                 const int* indicesA,
+                                                                 __global const b3Float4* verticesB,
+                                                                 __global const b3Float4* uniqueEdgesB,
+                                                                 __global const b3GpuFace* facesB,
+                                                                 __global const int* indicesB,
+                                                                 b3Float4* sep,
+                                                                 float* dmin,
+                                                                 bool searchAllEdgeEdge)
+{
+       b3Float4 posA = posA1;
+       posA.w = 0.f;
+       b3Float4 posB = posB1;
+       posB.w = 0.f;
+
+       //      int curPlaneTests=0;
+
+       int curEdgeEdge = 0;
+       // Test edges
+       static int maxEdgeTests = 0;
+       int curEdgeTests = hullA->m_numUniqueEdges * hullB->m_numUniqueEdges;
+       if (curEdgeTests > maxEdgeTests)
+       {
+               maxEdgeTests = curEdgeTests;
+               printf("maxEdgeTests = %d\n", maxEdgeTests);
+               printf("hullA->m_numUniqueEdges = %d\n", hullA->m_numUniqueEdges);
+               printf("hullB->m_numUniqueEdges = %d\n", hullB->m_numUniqueEdges);
+       }
+
+       if (searchAllEdgeEdge)
+       {
+               for (int e0 = 0; e0 < hullA->m_numUniqueEdges; e0++)
+               {
+                       const b3Float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset + e0];
+                       b3Float4 edge0World = b3QuatRotate(ornA, edge0);
+
+                       for (int e1 = 0; e1 < hullB->m_numUniqueEdges; e1++)
+                       {
+                               const b3Float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset + e1];
+                               b3Float4 edge1World = b3QuatRotate(ornB, edge1);
+
+                               b3Float4 crossje = b3Cross(edge0World, edge1World);
+
+                               curEdgeEdge++;
+                               if (!b3IsAlmostZero(crossje))
+                               {
+                                       crossje = b3Normalized(crossje);
+                                       if (b3Dot(DeltaC2, crossje) < 0)
+                                               crossje *= -1.f;
+
+                                       float dist;
+                                       bool result = true;
+                                       {
+                                               float Min0, Max0;
+                                               float Min1, Max1;
+                                               b3Project(hullA, posA, ornA, &crossje, verticesA, &Min0, &Max0);
+                                               b3Project(hullB, posB, ornB, &crossje, verticesB, &Min1, &Max1);
+
+                                               if (Max0 < Min1 || Max1 < Min0)
+                                                       return false;
+
+                                               float d0 = Max0 - Min1;
+                                               float d1 = Max1 - Min0;
+                                               dist = d0 < d1 ? d0 : d1;
+                                               result = true;
+                                       }
+
+                                       if (dist < *dmin)
+                                       {
+                                               *dmin = dist;
+                                               *sep = crossje;
+                                       }
+                               }
+                       }
+               }
+       }
+       else
+       {
+               int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
+               //printf("numDirections =%d\n",numDirections );
+
+               for (int i = 0; i < numDirections; i++)
+               {
+                       b3Float4 crossje = unitSphere162[i];
+                       {
+                               //if (b3Dot(DeltaC2,crossje)>0)
+                               {
+                                       float dist;
+                                       bool result = true;
+                                       {
+                                               float Min0, Max0;
+                                               float Min1, Max1;
+                                               b3Project(hullA, posA, ornA, &crossje, verticesA, &Min0, &Max0);
+                                               b3Project(hullB, posB, ornB, &crossje, verticesB, &Min1, &Max1);
+
+                                               if (Max0 < Min1 || Max1 < Min0)
+                                                       return false;
+
+                                               float d0 = Max0 - Min1;
+                                               float d1 = Max1 - Min0;
+                                               dist = d0 < d1 ? d0 : d1;
+                                               result = true;
+                                       }
+
+                                       if (dist < *dmin)
+                                       {
+                                               *dmin = dist;
+                                               *sep = crossje;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if ((b3Dot(-DeltaC2, *sep)) > 0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+inline int b3FindClippingFaces(b3Float4ConstArg separatingNormal,
+                                                          __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
+                                                          b3Float4ConstArg posA, b3QuatConstArg ornA, b3Float4ConstArg posB, b3QuatConstArg ornB,
+                                                          __global b3Float4* worldVertsA1,
+                                                          __global b3Float4* worldNormalsA1,
+                                                          __global b3Float4* worldVertsB1,
+                                                          int capacityWorldVerts,
+                                                          const float minDist, float maxDist,
+                                                          __global const b3Float4* verticesA,
+                                                          __global const b3GpuFace_t* facesA,
+                                                          __global const int* indicesA,
+                                                          __global const b3Float4* verticesB,
+                                                          __global const b3GpuFace_t* facesB,
+                                                          __global const int* indicesB,
+
+                                                          __global b3Int4* clippingFaces, int pairIndex)
+{
+       int numContactsOut = 0;
+       int numWorldVertsB1 = 0;
+
+       int closestFaceB = -1;
+       float dmax = -FLT_MAX;
+
+       {
+               for (int face = 0; face < hullB->m_numFaces; face++)
+               {
+                       const b3Float4 Normal = b3MakeFloat4(facesB[hullB->m_faceOffset + face].m_plane.x,
+                                                                                                facesB[hullB->m_faceOffset + face].m_plane.y, facesB[hullB->m_faceOffset + face].m_plane.z, 0.f);
+                       const b3Float4 WorldNormal = b3QuatRotate(ornB, Normal);
+                       float d = b3Dot(WorldNormal, separatingNormal);
+                       if (d > dmax)
+                       {
+                               dmax = d;
+                               closestFaceB = face;
+                       }
+               }
+       }
+
+       {
+               const b3GpuFace_t polyB = facesB[hullB->m_faceOffset + closestFaceB];
+               const int numVertices = polyB.m_numIndices;
+               for (int e0 = 0; e0 < numVertices; e0++)
+               {
+                       const b3Float4 b = verticesB[hullB->m_vertexOffset + indicesB[polyB.m_indexOffset + e0]];
+                       worldVertsB1[pairIndex * capacityWorldVerts + numWorldVertsB1++] = b3TransformPoint(b, posB, ornB);
+               }
+       }
+
+       int closestFaceA = -1;
+       {
+               float dmin = FLT_MAX;
+               for (int face = 0; face < hullA->m_numFaces; face++)
+               {
+                       const b3Float4 Normal = b3MakeFloat4(
+                               facesA[hullA->m_faceOffset + face].m_plane.x,
+                               facesA[hullA->m_faceOffset + face].m_plane.y,
+                               facesA[hullA->m_faceOffset + face].m_plane.z,
+                               0.f);
+                       const b3Float4 faceANormalWS = b3QuatRotate(ornA, Normal);
+
+                       float d = b3Dot(faceANormalWS, separatingNormal);
+                       if (d < dmin)
+                       {
+                               dmin = d;
+                               closestFaceA = face;
+                               worldNormalsA1[pairIndex] = faceANormalWS;
+                       }
+               }
+       }
+
+       int numVerticesA = facesA[hullA->m_faceOffset + closestFaceA].m_numIndices;
+       for (int e0 = 0; e0 < numVerticesA; e0++)
+       {
+               const b3Float4 a = verticesA[hullA->m_vertexOffset + indicesA[facesA[hullA->m_faceOffset + closestFaceA].m_indexOffset + e0]];
+               worldVertsA1[pairIndex * capacityWorldVerts + e0] = b3TransformPoint(a, posA, ornA);
+       }
+
+       clippingFaces[pairIndex].x = closestFaceA;
+       clippingFaces[pairIndex].y = closestFaceB;
+       clippingFaces[pairIndex].z = numVerticesA;
+       clippingFaces[pairIndex].w = numWorldVertsB1;
+
+       return numContactsOut;
+}
+
+__kernel void b3FindConcaveSeparatingAxisKernel(__global b3Int4* concavePairs,
+                                                                                               __global const b3RigidBodyData* rigidBodies,
+                                                                                               __global const b3Collidable* collidables,
+                                                                                               __global const b3ConvexPolyhedronData* convexShapes,
+                                                                                               __global const b3Float4* vertices,
+                                                                                               __global const b3Float4* uniqueEdges,
+                                                                                               __global const b3GpuFace* faces,
+                                                                                               __global const int* indices,
+                                                                                               __global const b3GpuChildShape* gpuChildShapes,
+                                                                                               __global b3Aabb* aabbs,
+                                                                                               __global b3Float4* concaveSeparatingNormalsOut,
+                                                                                               __global b3Int4* clippingFacesOut,
+                                                                                               __global b3Vector3* worldVertsA1Out,
+                                                                                               __global b3Vector3* worldNormalsA1Out,
+                                                                                               __global b3Vector3* worldVertsB1Out,
+                                                                                               __global int* hasSeparatingNormals,
+                                                                                               int vertexFaceCapacity,
+                                                                                               int numConcavePairs,
+                                                                                               int pairIdx)
+{
+       int i = pairIdx;
+       /*      int i = get_global_id(0);
+       if (i>=numConcavePairs)
+               return;
+       int pairIdx = i;
+       */
+
+       int bodyIndexA = concavePairs[i].x;
+       int bodyIndexB = concavePairs[i].y;
+
+       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+       if (collidables[collidableIndexB].m_shapeType != SHAPE_CONVEX_HULL &&
+               collidables[collidableIndexB].m_shapeType != SHAPE_COMPOUND_OF_CONVEX_HULLS)
+       {
+               concavePairs[pairIdx].w = -1;
+               return;
+       }
+
+       hasSeparatingNormals[i] = 0;
+
+       //      int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+       int numActualConcaveConvexTests = 0;
+
+       int f = concavePairs[i].z;
+
+       bool overlap = false;
+
+       b3ConvexPolyhedronData convexPolyhedronA;
+
+       //add 3 vertices of the triangle
+       convexPolyhedronA.m_numVertices = 3;
+       convexPolyhedronA.m_vertexOffset = 0;
+       b3Float4 localCenter = b3MakeFloat4(0.f, 0.f, 0.f, 0.f);
+
+       b3GpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset + f];
+       b3Aabb triAabb;
+       triAabb.m_minVec = b3MakeFloat4(1e30f, 1e30f, 1e30f, 0.f);
+       triAabb.m_maxVec = b3MakeFloat4(-1e30f, -1e30f, -1e30f, 0.f);
+
+       b3Float4 verticesA[3];
+       for (int i = 0; i < 3; i++)
+       {
+               int index = indices[face.m_indexOffset + i];
+               b3Float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset + index];
+               verticesA[i] = vert;
+               localCenter += vert;
+
+               triAabb.m_minVec = b3MinFloat4(triAabb.m_minVec, vert);
+               triAabb.m_maxVec = b3MaxFloat4(triAabb.m_maxVec, vert);
+       }
+
+       overlap = true;
+       overlap = (triAabb.m_minVec.x > aabbs[bodyIndexB].m_maxVec.x || triAabb.m_maxVec.x < aabbs[bodyIndexB].m_minVec.x) ? false : overlap;
+       overlap = (triAabb.m_minVec.z > aabbs[bodyIndexB].m_maxVec.z || triAabb.m_maxVec.z < aabbs[bodyIndexB].m_minVec.z) ? false : overlap;
+       overlap = (triAabb.m_minVec.y > aabbs[bodyIndexB].m_maxVec.y || triAabb.m_maxVec.y < aabbs[bodyIndexB].m_minVec.y) ? false : overlap;
+
+       if (overlap)
+       {
+               float dmin = FLT_MAX;
+               int hasSeparatingAxis = 5;
+               b3Float4 sepAxis = b3MakeFloat4(1, 2, 3, 4);
+
+               //      int localCC=0;
+               numActualConcaveConvexTests++;
+
+               //a triangle has 3 unique edges
+               convexPolyhedronA.m_numUniqueEdges = 3;
+               convexPolyhedronA.m_uniqueEdgesOffset = 0;
+               b3Float4 uniqueEdgesA[3];
+
+               uniqueEdgesA[0] = (verticesA[1] - verticesA[0]);
+               uniqueEdgesA[1] = (verticesA[2] - verticesA[1]);
+               uniqueEdgesA[2] = (verticesA[0] - verticesA[2]);
+
+               convexPolyhedronA.m_faceOffset = 0;
+
+               b3Float4 normal = b3MakeFloat4(face.m_plane.x, face.m_plane.y, face.m_plane.z, 0.f);
+
+               b3GpuFace facesA[B3_TRIANGLE_NUM_CONVEX_FACES];
+               int indicesA[3 + 3 + 2 + 2 + 2];
+               int curUsedIndices = 0;
+               int fidx = 0;
+
+               //front size of triangle
+               {
+                       facesA[fidx].m_indexOffset = curUsedIndices;
+                       indicesA[0] = 0;
+                       indicesA[1] = 1;
+                       indicesA[2] = 2;
+                       curUsedIndices += 3;
+                       float c = face.m_plane.w;
+                       facesA[fidx].m_plane.x = normal.x;
+                       facesA[fidx].m_plane.y = normal.y;
+                       facesA[fidx].m_plane.z = normal.z;
+                       facesA[fidx].m_plane.w = c;
+                       facesA[fidx].m_numIndices = 3;
+               }
+               fidx++;
+               //back size of triangle
+               {
+                       facesA[fidx].m_indexOffset = curUsedIndices;
+                       indicesA[3] = 2;
+                       indicesA[4] = 1;
+                       indicesA[5] = 0;
+                       curUsedIndices += 3;
+                       float c = b3Dot(normal, verticesA[0]);
+                       //      float c1 = -face.m_plane.w;
+                       facesA[fidx].m_plane.x = -normal.x;
+                       facesA[fidx].m_plane.y = -normal.y;
+                       facesA[fidx].m_plane.z = -normal.z;
+                       facesA[fidx].m_plane.w = c;
+                       facesA[fidx].m_numIndices = 3;
+               }
+               fidx++;
+
+               bool addEdgePlanes = true;
+               if (addEdgePlanes)
+               {
+                       int numVertices = 3;
+                       int prevVertex = numVertices - 1;
+                       for (int i = 0; i < numVertices; i++)
+                       {
+                               b3Float4 v0 = verticesA[i];
+                               b3Float4 v1 = verticesA[prevVertex];
+
+                               b3Float4 edgeNormal = b3Normalized(b3Cross(normal, v1 - v0));
+                               float c = -b3Dot(edgeNormal, v0);
+
+                               facesA[fidx].m_numIndices = 2;
+                               facesA[fidx].m_indexOffset = curUsedIndices;
+                               indicesA[curUsedIndices++] = i;
+                               indicesA[curUsedIndices++] = prevVertex;
+
+                               facesA[fidx].m_plane.x = edgeNormal.x;
+                               facesA[fidx].m_plane.y = edgeNormal.y;
+                               facesA[fidx].m_plane.z = edgeNormal.z;
+                               facesA[fidx].m_plane.w = c;
+                               fidx++;
+                               prevVertex = i;
+                       }
+               }
+               convexPolyhedronA.m_numFaces = B3_TRIANGLE_NUM_CONVEX_FACES;
+               convexPolyhedronA.m_localCenter = localCenter * (1.f / 3.f);
+
+               b3Float4 posA = rigidBodies[bodyIndexA].m_pos;
+               posA.w = 0.f;
+               b3Float4 posB = rigidBodies[bodyIndexB].m_pos;
+               posB.w = 0.f;
+
+               b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
+               b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
+
+               ///////////////////
+               ///compound shape support
+
+               if (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+               {
+                       int compoundChild = concavePairs[pairIdx].w;
+                       int childShapeIndexB = compoundChild;  //collidables[collidableIndexB].m_shapeIndex+compoundChild;
+                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                       b3Float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                       b3Quaternion childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                       b3Float4 newPosB = b3TransformPoint(childPosB, posB, ornB);
+                       b3Quaternion newOrnB = b3QuatMul(ornB, childOrnB);
+                       posB = newPosB;
+                       ornB = newOrnB;
+                       shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+               }
+               //////////////////
+
+               b3Float4 c0local = convexPolyhedronA.m_localCenter;
+               b3Float4 c0 = b3TransformPoint(c0local, posA, ornA);
+               b3Float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+               b3Float4 c1 = b3TransformPoint(c1local, posB, ornB);
+               const b3Float4 DeltaC2 = c0 - c1;
+
+               bool sepA = b3FindSeparatingAxis(&convexPolyhedronA, &convexShapes[shapeIndexB],
+                                                                                posA, ornA,
+                                                                                posB, ornB,
+                                                                                DeltaC2,
+                                                                                verticesA, uniqueEdgesA, facesA, indicesA,
+                                                                                vertices, uniqueEdges, faces, indices,
+                                                                                &sepAxis, &dmin);
+               hasSeparatingAxis = 4;
+               if (!sepA)
+               {
+                       hasSeparatingAxis = 0;
+               }
+               else
+               {
+                       bool sepB = b3FindSeparatingAxis(&convexShapes[shapeIndexB], &convexPolyhedronA,
+                                                                                        posB, ornB,
+                                                                                        posA, ornA,
+                                                                                        DeltaC2,
+                                                                                        vertices, uniqueEdges, faces, indices,
+                                                                                        verticesA, uniqueEdgesA, facesA, indicesA,
+                                                                                        &sepAxis, &dmin);
+
+                       if (!sepB)
+                       {
+                               hasSeparatingAxis = 0;
+                       }
+                       else
+                       {
+                               bool sepEE = b3FindSeparatingAxisEdgeEdge(&convexPolyhedronA, &convexShapes[shapeIndexB],
+                                                                                                                 posA, ornA,
+                                                                                                                 posB, ornB,
+                                                                                                                 DeltaC2,
+                                                                                                                 verticesA, uniqueEdgesA, facesA, indicesA,
+                                                                                                                 vertices, uniqueEdges, faces, indices,
+                                                                                                                 &sepAxis, &dmin, true);
+
+                               if (!sepEE)
+                               {
+                                       hasSeparatingAxis = 0;
+                               }
+                               else
+                               {
+                                       hasSeparatingAxis = 1;
+                               }
+                       }
+               }
+
+               if (hasSeparatingAxis)
+               {
+                       hasSeparatingNormals[i] = 1;
+                       sepAxis.w = dmin;
+                       concaveSeparatingNormalsOut[pairIdx] = sepAxis;
+
+                       //now compute clipping faces A and B, and world-space clipping vertices A and B...
+
+                       float minDist = -1e30f;
+                       float maxDist = 0.02f;
+
+                       b3FindClippingFaces(sepAxis,
+                                                               &convexPolyhedronA,
+                                                               &convexShapes[shapeIndexB],
+                                                               posA, ornA,
+                                                               posB, ornB,
+                                                               worldVertsA1Out,
+                                                               worldNormalsA1Out,
+                                                               worldVertsB1Out,
+                                                               vertexFaceCapacity,
+                                                               minDist, maxDist,
+                                                               verticesA,
+                                                               facesA,
+                                                               indicesA,
+
+                                                               vertices,
+                                                               faces,
+                                                               indices,
+                                                               clippingFacesOut, pairIdx);
+               }
+               else
+               {
+                       //mark this pair as in-active
+                       concavePairs[pairIdx].w = -1;
+               }
+       }
+       else
+       {
+               //mark this pair as in-active
+               concavePairs[pairIdx].w = -1;
+       }
+}
+
+#endif  //B3_FIND_CONCAVE_SEPARATING_AXIS_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h
new file mode 100644 (file)
index 0000000..b4981ae
--- /dev/null
@@ -0,0 +1,197 @@
+#ifndef B3_FIND_SEPARATING_AXIS_H
+#define B3_FIND_SEPARATING_AXIS_H
+
+inline void b3ProjectAxis(const b3ConvexPolyhedronData& hull, const b3Float4& pos, const b3Quaternion& orn, const b3Float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
+{
+       min = FLT_MAX;
+       max = -FLT_MAX;
+       int numVerts = hull.m_numVertices;
+
+       const b3Float4 localDir = b3QuatRotate(orn.inverse(), dir);
+
+       b3Scalar offset = b3Dot3F4(pos, dir);
+
+       for (int i = 0; i < numVerts; i++)
+       {
+               //b3Vector3 pt = trans * vertices[m_vertexOffset+i];
+               //b3Scalar dp = pt.dot(dir);
+               //b3Vector3 vertex = vertices[hull.m_vertexOffset+i];
+               b3Scalar dp = b3Dot3F4((b3Float4&)vertices[hull.m_vertexOffset + i], localDir);
+               //b3Assert(dp==dpL);
+               if (dp < min) min = dp;
+               if (dp > max) max = dp;
+       }
+       if (min > max)
+       {
+               b3Scalar tmp = min;
+               min = max;
+               max = tmp;
+       }
+       min += offset;
+       max += offset;
+}
+
+inline bool b3TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+                                                 const b3Float4& posA, const b3Quaternion& ornA,
+                                                 const b3Float4& posB, const b3Quaternion& ornB,
+                                                 const b3Float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB, b3Scalar& depth)
+{
+       b3Scalar Min0, Max0;
+       b3Scalar Min1, Max1;
+       b3ProjectAxis(hullA, posA, ornA, sep_axis, verticesA, Min0, Max0);
+       b3ProjectAxis(hullB, posB, ornB, sep_axis, verticesB, Min1, Max1);
+
+       if (Max0 < Min1 || Max1 < Min0)
+               return false;
+
+       b3Scalar d0 = Max0 - Min1;
+       b3Assert(d0 >= 0.0f);
+       b3Scalar d1 = Max1 - Min0;
+       b3Assert(d1 >= 0.0f);
+       depth = d0 < d1 ? d0 : d1;
+       return true;
+}
+
+inline bool b3FindSeparatingAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+                                                                const b3Float4& posA1,
+                                                                const b3Quaternion& ornA,
+                                                                const b3Float4& posB1,
+                                                                const b3Quaternion& ornB,
+                                                                const b3AlignedObjectArray<b3Vector3>& verticesA,
+                                                                const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+                                                                const b3AlignedObjectArray<b3GpuFace>& facesA,
+                                                                const b3AlignedObjectArray<int>& indicesA,
+                                                                const b3AlignedObjectArray<b3Vector3>& verticesB,
+                                                                const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+                                                                const b3AlignedObjectArray<b3GpuFace>& facesB,
+                                                                const b3AlignedObjectArray<int>& indicesB,
+
+                                                                b3Vector3& sep)
+{
+       B3_PROFILE("findSeparatingAxis");
+
+       b3Float4 posA = posA1;
+       posA.w = 0.f;
+       b3Float4 posB = posB1;
+       posB.w = 0.f;
+       //#ifdef TEST_INTERNAL_OBJECTS
+       b3Float4 c0local = (b3Float4&)hullA.m_localCenter;
+
+       b3Float4 c0 = b3TransformPoint(c0local, posA, ornA);
+       b3Float4 c1local = (b3Float4&)hullB.m_localCenter;
+       b3Float4 c1 = b3TransformPoint(c1local, posB, ornB);
+       const b3Float4 deltaC2 = c0 - c1;
+       //#endif
+
+       b3Scalar dmin = FLT_MAX;
+       int curPlaneTests = 0;
+
+       int numFacesA = hullA.m_numFaces;
+       // Test normals from hullA
+       for (int i = 0; i < numFacesA; i++)
+       {
+               const b3Float4& normal = (b3Float4&)facesA[hullA.m_faceOffset + i].m_plane;
+               b3Float4 faceANormalWS = b3QuatRotate(ornA, normal);
+
+               if (b3Dot3F4(deltaC2, faceANormalWS) < 0)
+                       faceANormalWS *= -1.f;
+
+               curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+               gExpectedNbTests++;
+               if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
+                       continue;
+               gActualNbTests++;
+#endif
+
+               b3Scalar d;
+               if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, faceANormalWS, verticesA, verticesB, d))
+                       return false;
+
+               if (d < dmin)
+               {
+                       dmin = d;
+                       sep = (b3Vector3&)faceANormalWS;
+               }
+       }
+
+       int numFacesB = hullB.m_numFaces;
+       // Test normals from hullB
+       for (int i = 0; i < numFacesB; i++)
+       {
+               b3Float4 normal = (b3Float4&)facesB[hullB.m_faceOffset + i].m_plane;
+               b3Float4 WorldNormal = b3QuatRotate(ornB, normal);
+
+               if (b3Dot3F4(deltaC2, WorldNormal) < 0)
+               {
+                       WorldNormal *= -1.f;
+               }
+               curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+               gExpectedNbTests++;
+               if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
+                       continue;
+               gActualNbTests++;
+#endif
+
+               b3Scalar d;
+               if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, WorldNormal, verticesA, verticesB, d))
+                       return false;
+
+               if (d < dmin)
+               {
+                       dmin = d;
+                       sep = (b3Vector3&)WorldNormal;
+               }
+       }
+
+       //      b3Vector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
+
+       int curEdgeEdge = 0;
+       // Test edges
+       for (int e0 = 0; e0 < hullA.m_numUniqueEdges; e0++)
+       {
+               const b3Float4& edge0 = (b3Float4&)uniqueEdgesA[hullA.m_uniqueEdgesOffset + e0];
+               b3Float4 edge0World = b3QuatRotate(ornA, (b3Float4&)edge0);
+
+               for (int e1 = 0; e1 < hullB.m_numUniqueEdges; e1++)
+               {
+                       const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset + e1];
+                       b3Float4 edge1World = b3QuatRotate(ornB, (b3Float4&)edge1);
+
+                       b3Float4 crossje = b3Cross3(edge0World, edge1World);
+
+                       curEdgeEdge++;
+                       if (!b3IsAlmostZero((b3Vector3&)crossje))
+                       {
+                               crossje = b3FastNormalized3(crossje);
+                               if (b3Dot3F4(deltaC2, crossje) < 0)
+                                       crossje *= -1.f;
+
+#ifdef TEST_INTERNAL_OBJECTS
+                               gExpectedNbTests++;
+                               if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
+                                       continue;
+                               gActualNbTests++;
+#endif
+
+                               b3Scalar dist;
+                               if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, crossje, verticesA, verticesB, dist))
+                                       return false;
+
+                               if (dist < dmin)
+                               {
+                                       dmin = dist;
+                                       sep = (b3Vector3&)crossje;
+                               }
+                       }
+               }
+       }
+
+       if ((b3Dot3F4(-deltaC2, (b3Float4&)sep)) > 0.0f)
+               sep = -sep;
+
+       return true;
+}
+
+#endif  //B3_FIND_SEPARATING_AXIS_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h
new file mode 100644 (file)
index 0000000..a3bfbf2
--- /dev/null
@@ -0,0 +1,888 @@
+
+/***
+ * ---------------------------------
+ * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>
+ *
+ *  This file was ported from mpr.c file, part of libccd.
+ *  The Minkoski Portal Refinement implementation was ported 
+ *  to OpenCL by Erwin Coumans for the Bullet 3 Physics library.
+ *  at http://github.com/erwincoumans/bullet3
+ *
+ *  Distributed under the OSI-approved BSD License (the "License");
+ *  see <http://www.opensource.org/licenses/bsd-license.php>.
+ *  This software is distributed WITHOUT ANY WARRANTY; without even the
+ *  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *  See the License for more information.
+ */
+
+#ifndef B3_MPR_PENETRATION_H
+#define B3_MPR_PENETRATION_H
+
+#include "Bullet3Common/shared/b3PlatformDefinitions.h"
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+
+#ifdef __cplusplus
+#define B3_MPR_SQRT sqrtf
+#else
+#define B3_MPR_SQRT sqrt
+#endif
+#define B3_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))
+#define B3_MPR_FABS fabs
+
+#define B3_MPR_TOLERANCE 1E-6f
+#define B3_MPR_MAX_ITERATIONS 1000
+
+struct _b3MprSupport_t
+{
+       b3Float4 v;   //!< Support point in minkowski sum
+       b3Float4 v1;  //!< Support point in obj1
+       b3Float4 v2;  //!< Support point in obj2
+};
+typedef struct _b3MprSupport_t b3MprSupport_t;
+
+struct _b3MprSimplex_t
+{
+       b3MprSupport_t ps[4];
+       int last;  //!< index of last added point
+};
+typedef struct _b3MprSimplex_t b3MprSimplex_t;
+
+inline b3MprSupport_t *b3MprSimplexPointW(b3MprSimplex_t *s, int idx)
+{
+       return &s->ps[idx];
+}
+
+inline void b3MprSimplexSetSize(b3MprSimplex_t *s, int size)
+{
+       s->last = size - 1;
+}
+
+inline int b3MprSimplexSize(const b3MprSimplex_t *s)
+{
+       return s->last + 1;
+}
+
+inline const b3MprSupport_t *b3MprSimplexPoint(const b3MprSimplex_t *s, int idx)
+{
+       // here is no check on boundaries
+       return &s->ps[idx];
+}
+
+inline void b3MprSupportCopy(b3MprSupport_t *d, const b3MprSupport_t *s)
+{
+       *d = *s;
+}
+
+inline void b3MprSimplexSet(b3MprSimplex_t *s, size_t pos, const b3MprSupport_t *a)
+{
+       b3MprSupportCopy(s->ps + pos, a);
+}
+
+inline void b3MprSimplexSwap(b3MprSimplex_t *s, size_t pos1, size_t pos2)
+{
+       b3MprSupport_t supp;
+
+       b3MprSupportCopy(&supp, &s->ps[pos1]);
+       b3MprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
+       b3MprSupportCopy(&s->ps[pos2], &supp);
+}
+
+inline int b3MprIsZero(float val)
+{
+       return B3_MPR_FABS(val) < FLT_EPSILON;
+}
+
+inline int b3MprEq(float _a, float _b)
+{
+       float ab;
+       float a, b;
+
+       ab = B3_MPR_FABS(_a - _b);
+       if (B3_MPR_FABS(ab) < FLT_EPSILON)
+               return 1;
+
+       a = B3_MPR_FABS(_a);
+       b = B3_MPR_FABS(_b);
+       if (b > a)
+       {
+               return ab < FLT_EPSILON * b;
+       }
+       else
+       {
+               return ab < FLT_EPSILON * a;
+       }
+}
+
+inline int b3MprVec3Eq(const b3Float4 *a, const b3Float4 *b)
+{
+       return b3MprEq((*a).x, (*b).x) && b3MprEq((*a).y, (*b).y) && b3MprEq((*a).z, (*b).z);
+}
+
+inline b3Float4 b3LocalGetSupportVertex(b3Float4ConstArg supportVec, __global const b3ConvexPolyhedronData_t *hull, b3ConstArray(b3Float4) verticesA)
+{
+       b3Float4 supVec = b3MakeFloat4(0, 0, 0, 0);
+       float maxDot = -B3_LARGE_FLOAT;
+
+       if (0 < hull->m_numVertices)
+       {
+               const b3Float4 scaled = supportVec;
+               int index = b3MaxDot(scaled, &verticesA[hull->m_vertexOffset], hull->m_numVertices, &maxDot);
+               return verticesA[hull->m_vertexOffset + index];
+       }
+
+       return supVec;
+}
+
+B3_STATIC void b3MprConvexSupport(int pairIndex, int bodyIndex, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+                                                                 b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+                                                                 b3ConstArray(b3Collidable_t) cpuCollidables,
+                                                                 b3ConstArray(b3Float4) cpuVertices,
+                                                                 __global b3Float4 *sepAxis,
+                                                                 const b3Float4 *_dir, b3Float4 *outp, int logme)
+{
+       //dir is in worldspace, move to local space
+
+       b3Float4 pos = cpuBodyBuf[bodyIndex].m_pos;
+       b3Quat orn = cpuBodyBuf[bodyIndex].m_quat;
+
+       b3Float4 dir = b3MakeFloat4((*_dir).x, (*_dir).y, (*_dir).z, 0.f);
+
+       const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn), dir);
+
+       //find local support vertex
+       int colIndex = cpuBodyBuf[bodyIndex].m_collidableIdx;
+
+       b3Assert(cpuCollidables[colIndex].m_shapeType == SHAPE_CONVEX_HULL);
+       __global const b3ConvexPolyhedronData_t *hull = &cpuConvexData[cpuCollidables[colIndex].m_shapeIndex];
+
+       b3Float4 pInA;
+       if (logme)
+       {
+               //      b3Float4 supVec = b3MakeFloat4(0,0,0,0);
+               float maxDot = -B3_LARGE_FLOAT;
+
+               if (0 < hull->m_numVertices)
+               {
+                       const b3Float4 scaled = localDir;
+                       int index = b3MaxDot(scaled, &cpuVertices[hull->m_vertexOffset], hull->m_numVertices, &maxDot);
+                       pInA = cpuVertices[hull->m_vertexOffset + index];
+               }
+       }
+       else
+       {
+               pInA = b3LocalGetSupportVertex(localDir, hull, cpuVertices);
+       }
+
+       //move vertex to world space
+       *outp = b3TransformPoint(pInA, pos, orn);
+}
+
+inline void b3MprSupport(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+                                                b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+                                                b3ConstArray(b3Collidable_t) cpuCollidables,
+                                                b3ConstArray(b3Float4) cpuVertices,
+                                                __global b3Float4 *sepAxis,
+                                                const b3Float4 *_dir, b3MprSupport_t *supp)
+{
+       b3Float4 dir;
+       dir = *_dir;
+       b3MprConvexSupport(pairIndex, bodyIndexA, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &supp->v1, 0);
+       dir = *_dir * -1.f;
+       b3MprConvexSupport(pairIndex, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &supp->v2, 0);
+       supp->v = supp->v1 - supp->v2;
+}
+
+inline void b3FindOrigin(int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, b3MprSupport_t *center)
+{
+       center->v1 = cpuBodyBuf[bodyIndexA].m_pos;
+       center->v2 = cpuBodyBuf[bodyIndexB].m_pos;
+       center->v = center->v1 - center->v2;
+}
+
+inline void b3MprVec3Set(b3Float4 *v, float x, float y, float z)
+{
+       (*v).x = x;
+       (*v).y = y;
+       (*v).z = z;
+       (*v).w = 0.f;
+}
+
+inline void b3MprVec3Add(b3Float4 *v, const b3Float4 *w)
+{
+       (*v).x += (*w).x;
+       (*v).y += (*w).y;
+       (*v).z += (*w).z;
+}
+
+inline void b3MprVec3Copy(b3Float4 *v, const b3Float4 *w)
+{
+       *v = *w;
+}
+
+inline void b3MprVec3Scale(b3Float4 *d, float k)
+{
+       *d *= k;
+}
+
+inline float b3MprVec3Dot(const b3Float4 *a, const b3Float4 *b)
+{
+       float dot;
+
+       dot = b3Dot3F4(*a, *b);
+       return dot;
+}
+
+inline float b3MprVec3Len2(const b3Float4 *v)
+{
+       return b3MprVec3Dot(v, v);
+}
+
+inline void b3MprVec3Normalize(b3Float4 *d)
+{
+       float k = 1.f / B3_MPR_SQRT(b3MprVec3Len2(d));
+       b3MprVec3Scale(d, k);
+}
+
+inline void b3MprVec3Cross(b3Float4 *d, const b3Float4 *a, const b3Float4 *b)
+{
+       *d = b3Cross3(*a, *b);
+}
+
+inline void b3MprVec3Sub2(b3Float4 *d, const b3Float4 *v, const b3Float4 *w)
+{
+       *d = *v - *w;
+}
+
+inline void b3PortalDir(const b3MprSimplex_t *portal, b3Float4 *dir)
+{
+       b3Float4 v2v1, v3v1;
+
+       b3MprVec3Sub2(&v2v1, &b3MprSimplexPoint(portal, 2)->v,
+                                 &b3MprSimplexPoint(portal, 1)->v);
+       b3MprVec3Sub2(&v3v1, &b3MprSimplexPoint(portal, 3)->v,
+                                 &b3MprSimplexPoint(portal, 1)->v);
+       b3MprVec3Cross(dir, &v2v1, &v3v1);
+       b3MprVec3Normalize(dir);
+}
+
+inline int portalEncapsulesOrigin(const b3MprSimplex_t *portal,
+                                                                 const b3Float4 *dir)
+{
+       float dot;
+       dot = b3MprVec3Dot(dir, &b3MprSimplexPoint(portal, 1)->v);
+       return b3MprIsZero(dot) || dot > 0.f;
+}
+
+inline int portalReachTolerance(const b3MprSimplex_t *portal,
+                                                               const b3MprSupport_t *v4,
+                                                               const b3Float4 *dir)
+{
+       float dv1, dv2, dv3, dv4;
+       float dot1, dot2, dot3;
+
+       // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
+
+       dv1 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, dir);
+       dv2 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, dir);
+       dv3 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, dir);
+       dv4 = b3MprVec3Dot(&v4->v, dir);
+
+       dot1 = dv4 - dv1;
+       dot2 = dv4 - dv2;
+       dot3 = dv4 - dv3;
+
+       dot1 = B3_MPR_FMIN(dot1, dot2);
+       dot1 = B3_MPR_FMIN(dot1, dot3);
+
+       return b3MprEq(dot1, B3_MPR_TOLERANCE) || dot1 < B3_MPR_TOLERANCE;
+}
+
+inline int portalCanEncapsuleOrigin(const b3MprSimplex_t *portal,
+                                                                       const b3MprSupport_t *v4,
+                                                                       const b3Float4 *dir)
+{
+       float dot;
+       dot = b3MprVec3Dot(&v4->v, dir);
+       return b3MprIsZero(dot) || dot > 0.f;
+}
+
+inline void b3ExpandPortal(b3MprSimplex_t *portal,
+                                                  const b3MprSupport_t *v4)
+{
+       float dot;
+       b3Float4 v4v0;
+
+       b3MprVec3Cross(&v4v0, &v4->v, &b3MprSimplexPoint(portal, 0)->v);
+       dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &v4v0);
+       if (dot > 0.f)
+       {
+               dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &v4v0);
+               if (dot > 0.f)
+               {
+                       b3MprSimplexSet(portal, 1, v4);
+               }
+               else
+               {
+                       b3MprSimplexSet(portal, 3, v4);
+               }
+       }
+       else
+       {
+               dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &v4v0);
+               if (dot > 0.f)
+               {
+                       b3MprSimplexSet(portal, 2, v4);
+               }
+               else
+               {
+                       b3MprSimplexSet(portal, 1, v4);
+               }
+       }
+}
+
+B3_STATIC int b3DiscoverPortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+                                                          b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+                                                          b3ConstArray(b3Collidable_t) cpuCollidables,
+                                                          b3ConstArray(b3Float4) cpuVertices,
+                                                          __global b3Float4 *sepAxis,
+                                                          __global int *hasSepAxis,
+                                                          b3MprSimplex_t *portal)
+{
+       b3Float4 dir, va, vb;
+       float dot;
+       int cont;
+
+       // vertex 0 is center of portal
+       b3FindOrigin(bodyIndexA, bodyIndexB, cpuBodyBuf, b3MprSimplexPointW(portal, 0));
+       // vertex 0 is center of portal
+       b3MprSimplexSetSize(portal, 1);
+
+       b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
+       b3Float4 *b3mpr_vec3_origin = &zero;
+
+       if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 0)->v, b3mpr_vec3_origin))
+       {
+               // Portal's center lies on origin (0,0,0) => we know that objects
+               // intersect but we would need to know penetration info.
+               // So move center little bit...
+               b3MprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
+               b3MprVec3Add(&b3MprSimplexPointW(portal, 0)->v, &va);
+       }
+
+       // vertex 1 = support in direction of origin
+       b3MprVec3Copy(&dir, &b3MprSimplexPoint(portal, 0)->v);
+       b3MprVec3Scale(&dir, -1.f);
+       b3MprVec3Normalize(&dir);
+
+       b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, b3MprSimplexPointW(portal, 1));
+
+       b3MprSimplexSetSize(portal, 2);
+
+       // test if origin isn't outside of v1
+       dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &dir);
+
+       if (b3MprIsZero(dot) || dot < 0.f)
+               return -1;
+
+       // vertex 2
+       b3MprVec3Cross(&dir, &b3MprSimplexPoint(portal, 0)->v,
+                                  &b3MprSimplexPoint(portal, 1)->v);
+       if (b3MprIsZero(b3MprVec3Len2(&dir)))
+       {
+               if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 1)->v, b3mpr_vec3_origin))
+               {
+                       // origin lies on v1
+                       return 1;
+               }
+               else
+               {
+                       // origin lies on v0-v1 segment
+                       return 2;
+               }
+       }
+
+       b3MprVec3Normalize(&dir);
+       b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, b3MprSimplexPointW(portal, 2));
+
+       dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &dir);
+       if (b3MprIsZero(dot) || dot < 0.f)
+               return -1;
+
+       b3MprSimplexSetSize(portal, 3);
+
+       // vertex 3 direction
+       b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,
+                                 &b3MprSimplexPoint(portal, 0)->v);
+       b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,
+                                 &b3MprSimplexPoint(portal, 0)->v);
+       b3MprVec3Cross(&dir, &va, &vb);
+       b3MprVec3Normalize(&dir);
+
+       // it is better to form portal faces to be oriented "outside" origin
+       dot = b3MprVec3Dot(&dir, &b3MprSimplexPoint(portal, 0)->v);
+       if (dot > 0.f)
+       {
+               b3MprSimplexSwap(portal, 1, 2);
+               b3MprVec3Scale(&dir, -1.f);
+       }
+
+       while (b3MprSimplexSize(portal) < 4)
+       {
+               b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, b3MprSimplexPointW(portal, 3));
+
+               dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &dir);
+               if (b3MprIsZero(dot) || dot < 0.f)
+                       return -1;
+
+               cont = 0;
+
+               // test if origin is outside (v1, v0, v3) - set v2 as v3 and
+               // continue
+               b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 1)->v,
+                                          &b3MprSimplexPoint(portal, 3)->v);
+               dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);
+               if (dot < 0.f && !b3MprIsZero(dot))
+               {
+                       b3MprSimplexSet(portal, 2, b3MprSimplexPoint(portal, 3));
+                       cont = 1;
+               }
+
+               if (!cont)
+               {
+                       // test if origin is outside (v3, v0, v2) - set v1 as v3 and
+                       // continue
+                       b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 3)->v,
+                                                  &b3MprSimplexPoint(portal, 2)->v);
+                       dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);
+                       if (dot < 0.f && !b3MprIsZero(dot))
+                       {
+                               b3MprSimplexSet(portal, 1, b3MprSimplexPoint(portal, 3));
+                               cont = 1;
+                       }
+               }
+
+               if (cont)
+               {
+                       b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,
+                                                 &b3MprSimplexPoint(portal, 0)->v);
+                       b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,
+                                                 &b3MprSimplexPoint(portal, 0)->v);
+                       b3MprVec3Cross(&dir, &va, &vb);
+                       b3MprVec3Normalize(&dir);
+               }
+               else
+               {
+                       b3MprSimplexSetSize(portal, 4);
+               }
+       }
+
+       return 0;
+}
+
+B3_STATIC int b3RefinePortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+                                                        b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+                                                        b3ConstArray(b3Collidable_t) cpuCollidables,
+                                                        b3ConstArray(b3Float4) cpuVertices,
+                                                        __global b3Float4 *sepAxis,
+                                                        b3MprSimplex_t *portal)
+{
+       b3Float4 dir;
+       b3MprSupport_t v4;
+
+       for (int i = 0; i < B3_MPR_MAX_ITERATIONS; i++)
+       //while (1)
+       {
+               // compute direction outside the portal (from v0 throught v1,v2,v3
+               // face)
+               b3PortalDir(portal, &dir);
+
+               // test if origin is inside the portal
+               if (portalEncapsulesOrigin(portal, &dir))
+                       return 0;
+
+               // get next support point
+
+               b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &v4);
+
+               // test if v4 can expand portal to contain origin and if portal
+               // expanding doesn't reach given tolerance
+               if (!portalCanEncapsuleOrigin(portal, &v4, &dir) || portalReachTolerance(portal, &v4, &dir))
+               {
+                       return -1;
+               }
+
+               // v1-v2-v3 triangle must be rearranged to face outside Minkowski
+               // difference (direction from v0).
+               b3ExpandPortal(portal, &v4);
+       }
+
+       return -1;
+}
+
+B3_STATIC void b3FindPos(const b3MprSimplex_t *portal, b3Float4 *pos)
+{
+       b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
+       b3Float4 *b3mpr_vec3_origin = &zero;
+
+       b3Float4 dir;
+       size_t i;
+       float b[4], sum, inv;
+       b3Float4 vec, p1, p2;
+
+       b3PortalDir(portal, &dir);
+
+       // use barycentric coordinates of tetrahedron to find origin
+       b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,
+                                  &b3MprSimplexPoint(portal, 2)->v);
+       b[0] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);
+
+       b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,
+                                  &b3MprSimplexPoint(portal, 2)->v);
+       b[1] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);
+
+       b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 0)->v,
+                                  &b3MprSimplexPoint(portal, 1)->v);
+       b[2] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);
+
+       b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,
+                                  &b3MprSimplexPoint(portal, 1)->v);
+       b[3] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);
+
+       sum = b[0] + b[1] + b[2] + b[3];
+
+       if (b3MprIsZero(sum) || sum < 0.f)
+       {
+               b[0] = 0.f;
+
+               b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,
+                                          &b3MprSimplexPoint(portal, 3)->v);
+               b[1] = b3MprVec3Dot(&vec, &dir);
+               b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,
+                                          &b3MprSimplexPoint(portal, 1)->v);
+               b[2] = b3MprVec3Dot(&vec, &dir);
+               b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,
+                                          &b3MprSimplexPoint(portal, 2)->v);
+               b[3] = b3MprVec3Dot(&vec, &dir);
+
+               sum = b[1] + b[2] + b[3];
+       }
+
+       inv = 1.f / sum;
+
+       b3MprVec3Copy(&p1, b3mpr_vec3_origin);
+       b3MprVec3Copy(&p2, b3mpr_vec3_origin);
+       for (i = 0; i < 4; i++)
+       {
+               b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v1);
+               b3MprVec3Scale(&vec, b[i]);
+               b3MprVec3Add(&p1, &vec);
+
+               b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v2);
+               b3MprVec3Scale(&vec, b[i]);
+               b3MprVec3Add(&p2, &vec);
+       }
+       b3MprVec3Scale(&p1, inv);
+       b3MprVec3Scale(&p2, inv);
+
+       b3MprVec3Copy(pos, &p1);
+       b3MprVec3Add(pos, &p2);
+       b3MprVec3Scale(pos, 0.5);
+}
+
+inline float b3MprVec3Dist2(const b3Float4 *a, const b3Float4 *b)
+{
+       b3Float4 ab;
+       b3MprVec3Sub2(&ab, a, b);
+       return b3MprVec3Len2(&ab);
+}
+
+inline float _b3MprVec3PointSegmentDist2(const b3Float4 *P,
+                                                                                const b3Float4 *x0,
+                                                                                const b3Float4 *b,
+                                                                                b3Float4 *witness)
+{
+       // The computation comes from solving equation of segment:
+       //      S(t) = x0 + t.d
+       //          where - x0 is initial point of segment
+       //                - d is direction of segment from x0 (|d| > 0)
+       //                - t belongs to <0, 1> interval
+       //
+       // Than, distance from a segment to some point P can be expressed:
+       //      D(t) = |x0 + t.d - P|^2
+       //          which is distance from any point on segment. Minimization
+       //          of this function brings distance from P to segment.
+       // Minimization of D(t) leads to simple quadratic equation that's
+       // solving is straightforward.
+       //
+       // Bonus of this method is witness point for free.
+
+       float dist, t;
+       b3Float4 d, a;
+
+       // direction of segment
+       b3MprVec3Sub2(&d, b, x0);
+
+       // precompute vector from P to x0
+       b3MprVec3Sub2(&a, x0, P);
+
+       t = -1.f * b3MprVec3Dot(&a, &d);
+       t /= b3MprVec3Len2(&d);
+
+       if (t < 0.f || b3MprIsZero(t))
+       {
+               dist = b3MprVec3Dist2(x0, P);
+               if (witness)
+                       b3MprVec3Copy(witness, x0);
+       }
+       else if (t > 1.f || b3MprEq(t, 1.f))
+       {
+               dist = b3MprVec3Dist2(b, P);
+               if (witness)
+                       b3MprVec3Copy(witness, b);
+       }
+       else
+       {
+               if (witness)
+               {
+                       b3MprVec3Copy(witness, &d);
+                       b3MprVec3Scale(witness, t);
+                       b3MprVec3Add(witness, x0);
+                       dist = b3MprVec3Dist2(witness, P);
+               }
+               else
+               {
+                       // recycling variables
+                       b3MprVec3Scale(&d, t);
+                       b3MprVec3Add(&d, &a);
+                       dist = b3MprVec3Len2(&d);
+               }
+       }
+
+       return dist;
+}
+
+inline float b3MprVec3PointTriDist2(const b3Float4 *P,
+                                                                       const b3Float4 *x0, const b3Float4 *B,
+                                                                       const b3Float4 *C,
+                                                                       b3Float4 *witness)
+{
+       // Computation comes from analytic expression for triangle (x0, B, C)
+       //      T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and
+       // Then equation for distance is:
+       //      D(s, t) = | T(s, t) - P |^2
+       // This leads to minimization of quadratic function of two variables.
+       // The solution from is taken only if s is between 0 and 1, t is
+       // between 0 and 1 and t + s < 1, otherwise distance from segment is
+       // computed.
+
+       b3Float4 d1, d2, a;
+       float u, v, w, p, q, r;
+       float s, t, dist, dist2;
+       b3Float4 witness2;
+
+       b3MprVec3Sub2(&d1, B, x0);
+       b3MprVec3Sub2(&d2, C, x0);
+       b3MprVec3Sub2(&a, x0, P);
+
+       u = b3MprVec3Dot(&a, &a);
+       v = b3MprVec3Dot(&d1, &d1);
+       w = b3MprVec3Dot(&d2, &d2);
+       p = b3MprVec3Dot(&a, &d1);
+       q = b3MprVec3Dot(&a, &d2);
+       r = b3MprVec3Dot(&d1, &d2);
+
+       s = (q * r - w * p) / (w * v - r * r);
+       t = (-s * r - q) / w;
+
+       if ((b3MprIsZero(s) || s > 0.f) && (b3MprEq(s, 1.f) || s < 1.f) && (b3MprIsZero(t) || t > 0.f) && (b3MprEq(t, 1.f) || t < 1.f) && (b3MprEq(t + s, 1.f) || t + s < 1.f))
+       {
+               if (witness)
+               {
+                       b3MprVec3Scale(&d1, s);
+                       b3MprVec3Scale(&d2, t);
+                       b3MprVec3Copy(witness, x0);
+                       b3MprVec3Add(witness, &d1);
+                       b3MprVec3Add(witness, &d2);
+
+                       dist = b3MprVec3Dist2(witness, P);
+               }
+               else
+               {
+                       dist = s * s * v;
+                       dist += t * t * w;
+                       dist += 2.f * s * t * r;
+                       dist += 2.f * s * p;
+                       dist += 2.f * t * q;
+                       dist += u;
+               }
+       }
+       else
+       {
+               dist = _b3MprVec3PointSegmentDist2(P, x0, B, witness);
+
+               dist2 = _b3MprVec3PointSegmentDist2(P, x0, C, &witness2);
+               if (dist2 < dist)
+               {
+                       dist = dist2;
+                       if (witness)
+                               b3MprVec3Copy(witness, &witness2);
+               }
+
+               dist2 = _b3MprVec3PointSegmentDist2(P, B, C, &witness2);
+               if (dist2 < dist)
+               {
+                       dist = dist2;
+                       if (witness)
+                               b3MprVec3Copy(witness, &witness2);
+               }
+       }
+
+       return dist;
+}
+
+B3_STATIC void b3FindPenetr(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+                                                       b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+                                                       b3ConstArray(b3Collidable_t) cpuCollidables,
+                                                       b3ConstArray(b3Float4) cpuVertices,
+                                                       __global b3Float4 *sepAxis,
+                                                       b3MprSimplex_t *portal,
+                                                       float *depth, b3Float4 *pdir, b3Float4 *pos)
+{
+       b3Float4 dir;
+       b3MprSupport_t v4;
+       unsigned long iterations;
+
+       b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
+       b3Float4 *b3mpr_vec3_origin = &zero;
+
+       iterations = 1UL;
+       for (int i = 0; i < B3_MPR_MAX_ITERATIONS; i++)
+       //while (1)
+       {
+               // compute portal direction and obtain next support point
+               b3PortalDir(portal, &dir);
+
+               b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &v4);
+
+               // reached tolerance -> find penetration info
+               if (portalReachTolerance(portal, &v4, &dir) || iterations == B3_MPR_MAX_ITERATIONS)
+               {
+                       *depth = b3MprVec3PointTriDist2(b3mpr_vec3_origin, &b3MprSimplexPoint(portal, 1)->v, &b3MprSimplexPoint(portal, 2)->v, &b3MprSimplexPoint(portal, 3)->v, pdir);
+                       *depth = B3_MPR_SQRT(*depth);
+
+                       if (b3MprIsZero((*pdir).x) && b3MprIsZero((*pdir).y) && b3MprIsZero((*pdir).z))
+                       {
+                               *pdir = dir;
+                       }
+                       b3MprVec3Normalize(pdir);
+
+                       // barycentric coordinates:
+                       b3FindPos(portal, pos);
+
+                       return;
+               }
+
+               b3ExpandPortal(portal, &v4);
+
+               iterations++;
+       }
+}
+
+B3_STATIC void b3FindPenetrTouch(b3MprSimplex_t *portal, float *depth, b3Float4 *dir, b3Float4 *pos)
+{
+       // Touching contact on portal's v1 - so depth is zero and direction
+       // is unimportant and pos can be guessed
+       *depth = 0.f;
+       b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
+       b3Float4 *b3mpr_vec3_origin = &zero;
+
+       b3MprVec3Copy(dir, b3mpr_vec3_origin);
+
+       b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);
+       b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);
+       b3MprVec3Scale(pos, 0.5);
+}
+
+B3_STATIC void b3FindPenetrSegment(b3MprSimplex_t *portal,
+                                                                  float *depth, b3Float4 *dir, b3Float4 *pos)
+{
+       // Origin lies on v0-v1 segment.
+       // Depth is distance to v1, direction also and position must be
+       // computed
+
+       b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);
+       b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);
+       b3MprVec3Scale(pos, 0.5f);
+
+       b3MprVec3Copy(dir, &b3MprSimplexPoint(portal, 1)->v);
+       *depth = B3_MPR_SQRT(b3MprVec3Len2(dir));
+       b3MprVec3Normalize(dir);
+}
+
+inline int b3MprPenetration(int pairIndex, int bodyIndexA, int bodyIndexB,
+                                                       b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
+                                                       b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
+                                                       b3ConstArray(b3Collidable_t) cpuCollidables,
+                                                       b3ConstArray(b3Float4) cpuVertices,
+                                                       __global b3Float4 *sepAxis,
+                                                       __global int *hasSepAxis,
+                                                       float *depthOut, b3Float4 *dirOut, b3Float4 *posOut)
+{
+       b3MprSimplex_t portal;
+
+       //      if (!hasSepAxis[pairIndex])
+       //      return -1;
+
+       hasSepAxis[pairIndex] = 0;
+       int res;
+
+       // Phase 1: Portal discovery
+       res = b3DiscoverPortal(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, hasSepAxis, &portal);
+
+       //sepAxis[pairIndex] = *pdir;//or -dir?
+
+       switch (res)
+       {
+               case 0:
+               {
+                       // Phase 2: Portal refinement
+
+                       res = b3RefinePortal(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &portal);
+                       if (res < 0)
+                               return -1;
+
+                       // Phase 3. Penetration info
+                       b3FindPenetr(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &portal, depthOut, dirOut, posOut);
+                       hasSepAxis[pairIndex] = 1;
+                       sepAxis[pairIndex] = -*dirOut;
+                       break;
+               }
+               case 1:
+               {
+                       // Touching contact on portal's v1.
+                       b3FindPenetrTouch(&portal, depthOut, dirOut, posOut);
+                       break;
+               }
+               case 2:
+               {
+                       b3FindPenetrSegment(&portal, depthOut, dirOut, posOut);
+                       break;
+               }
+               default:
+               {
+                       hasSepAxis[pairIndex] = 0;
+                       //if (res < 0)
+                       //{
+                       // Origin isn't inside portal - no collision.
+                       return -1;
+                       //}
+               }
+       };
+
+       return 0;
+};
+
+#endif  //B3_MPR_PENETRATION_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h
new file mode 100644 (file)
index 0000000..6e991e1
--- /dev/null
@@ -0,0 +1,175 @@
+
+#ifndef B3_NEW_CONTACT_REDUCTION_H
+#define B3_NEW_CONTACT_REDUCTION_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
+
+int b3ExtractManifoldSequentialGlobal(__global const b3Float4* p, int nPoints, b3Float4ConstArg nearNormal, b3Int4* contactIdx)
+{
+       if (nPoints == 0)
+               return 0;
+
+       if (nPoints <= 4)
+               return nPoints;
+
+       if (nPoints > 64)
+               nPoints = 64;
+
+       b3Float4 center = b3MakeFloat4(0, 0, 0, 0);
+       {
+               for (int i = 0; i < nPoints; i++)
+                       center += p[i];
+               center /= (float)nPoints;
+       }
+
+       //      sample 4 directions
+
+       b3Float4 aVector = p[0] - center;
+       b3Float4 u = b3Cross(nearNormal, aVector);
+       b3Float4 v = b3Cross(nearNormal, u);
+       u = b3Normalized(u);
+       v = b3Normalized(v);
+
+       //keep point with deepest penetration
+       float minW = FLT_MAX;
+
+       int minIndex = -1;
+
+       b3Float4 maxDots;
+       maxDots.x = FLT_MIN;
+       maxDots.y = FLT_MIN;
+       maxDots.z = FLT_MIN;
+       maxDots.w = FLT_MIN;
+
+       //      idx, distance
+       for (int ie = 0; ie < nPoints; ie++)
+       {
+               if (p[ie].w < minW)
+               {
+                       minW = p[ie].w;
+                       minIndex = ie;
+               }
+               float f;
+               b3Float4 r = p[ie] - center;
+               f = b3Dot(u, r);
+               if (f < maxDots.x)
+               {
+                       maxDots.x = f;
+                       contactIdx[0].x = ie;
+               }
+
+               f = b3Dot(-u, r);
+               if (f < maxDots.y)
+               {
+                       maxDots.y = f;
+                       contactIdx[0].y = ie;
+               }
+
+               f = b3Dot(v, r);
+               if (f < maxDots.z)
+               {
+                       maxDots.z = f;
+                       contactIdx[0].z = ie;
+               }
+
+               f = b3Dot(-v, r);
+               if (f < maxDots.w)
+               {
+                       maxDots.w = f;
+                       contactIdx[0].w = ie;
+               }
+       }
+
+       if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+       {
+               //replace the first contact with minimum (todo: replace contact with least penetration)
+               contactIdx[0].x = minIndex;
+       }
+
+       return 4;
+}
+
+__kernel void b3NewContactReductionKernel(__global b3Int4* pairs,
+                                                                                 __global const b3RigidBodyData_t* rigidBodies,
+                                                                                 __global const b3Float4* separatingNormals,
+                                                                                 __global const int* hasSeparatingAxis,
+                                                                                 __global struct b3Contact4Data* globalContactsOut,
+                                                                                 __global b3Int4* clippingFaces,
+                                                                                 __global b3Float4* worldVertsB2,
+                                                                                 volatile __global int* nGlobalContactsOut,
+                                                                                 int vertexFaceCapacity,
+                                                                                 int contactCapacity,
+                                                                                 int numPairs,
+                                                                                 int pairIndex)
+{
+       //    int i = get_global_id(0);
+       //int pairIndex = i;
+       int i = pairIndex;
+
+       b3Int4 contactIdx;
+       contactIdx = b3MakeInt4(0, 1, 2, 3);
+
+       if (i < numPairs)
+       {
+               if (hasSeparatingAxis[i])
+               {
+                       int nPoints = clippingFaces[pairIndex].w;
+
+                       if (nPoints > 0)
+                       {
+                               __global b3Float4* pointsIn = &worldVertsB2[pairIndex * vertexFaceCapacity];
+                               b3Float4 normal = -separatingNormals[i];
+
+                               int nReducedContacts = b3ExtractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
+
+                               int dstIdx;
+                               dstIdx = b3AtomicInc(nGlobalContactsOut);
+
+                               //#if 0
+                               b3Assert(dstIdx < contactCapacity);
+                               if (dstIdx < contactCapacity)
+                               {
+                                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+                                       c->m_worldNormalOnB = -normal;
+                                       c->m_restituitionCoeffCmp = (0.f * 0xffff);
+                                       c->m_frictionCoeffCmp = (0.7f * 0xffff);
+                                       c->m_batchIdx = pairIndex;
+                                       int bodyA = pairs[pairIndex].x;
+                                       int bodyB = pairs[pairIndex].y;
+
+                                       pairs[pairIndex].w = dstIdx;
+
+                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass == 0 ? -bodyA : bodyA;
+                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass == 0 ? -bodyB : bodyB;
+                                       c->m_childIndexA = -1;
+                                       c->m_childIndexB = -1;
+
+                                       switch (nReducedContacts)
+                                       {
+                                               case 4:
+                                                       c->m_worldPosB[3] = pointsIn[contactIdx.w];
+                                               case 3:
+                                                       c->m_worldPosB[2] = pointsIn[contactIdx.z];
+                                               case 2:
+                                                       c->m_worldPosB[1] = pointsIn[contactIdx.y];
+                                               case 1:
+                                                       c->m_worldPosB[0] = pointsIn[contactIdx.x];
+                                               default:
+                                               {
+                                               }
+                                       };
+
+                                       GET_NPOINTS(*c) = nReducedContacts;
+                               }
+
+                               //#endif
+
+                       }  //           if (numContactsOut>0)
+               }      //               if (hasSeparatingAxis[i])
+       }          //   if (i<numPairs)
+}
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h
new file mode 100644 (file)
index 0000000..ba796ea
--- /dev/null
@@ -0,0 +1,88 @@
+
+
+#ifndef B3_QUANTIZED_BVH_NODE_H
+#define B3_QUANTIZED_BVH_NODE_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+
+#define B3_MAX_NUM_PARTS_IN_BITS 10
+
+///b3QuantizedBvhNodeData 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).
+typedef struct b3QuantizedBvhNodeData b3QuantizedBvhNodeData_t;
+
+struct b3QuantizedBvhNodeData
+{
+       //12 bytes
+       unsigned short int m_quantizedAabbMin[3];
+       unsigned short int m_quantizedAabbMax[3];
+       //4 bytes
+       int m_escapeIndexOrTriangleIndex;
+};
+
+inline int b3GetTriangleIndex(const b3QuantizedBvhNodeData* rootNode)
+{
+       unsigned int x = 0;
+       unsigned int y = (~(x & 0)) << (31 - B3_MAX_NUM_PARTS_IN_BITS);
+       // Get only the lower bits where the triangle index is stored
+       return (rootNode->m_escapeIndexOrTriangleIndex & ~(y));
+}
+
+inline int b3IsLeaf(const b3QuantizedBvhNodeData* rootNode)
+{
+       //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+       return (rootNode->m_escapeIndexOrTriangleIndex >= 0) ? 1 : 0;
+}
+
+inline int b3GetEscapeIndex(const b3QuantizedBvhNodeData* rootNode)
+{
+       return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+inline void b3QuantizeWithClamp(unsigned short* out, b3Float4ConstArg point2, int isMax, b3Float4ConstArg bvhAabbMin, b3Float4ConstArg bvhAabbMax, b3Float4ConstArg bvhQuantization)
+{
+       b3Float4 clampedPoint = b3MaxFloat4(point2, bvhAabbMin);
+       clampedPoint = b3MinFloat4(clampedPoint, bvhAabbMax);
+
+       b3Float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;
+       if (isMax)
+       {
+               out[0] = (unsigned short)(((unsigned short)(v.x + 1.f) | 1));
+               out[1] = (unsigned short)(((unsigned short)(v.y + 1.f) | 1));
+               out[2] = (unsigned short)(((unsigned short)(v.z + 1.f) | 1));
+       }
+       else
+       {
+               out[0] = (unsigned short)(((unsigned short)(v.x) & 0xfffe));
+               out[1] = (unsigned short)(((unsigned short)(v.y) & 0xfffe));
+               out[2] = (unsigned short)(((unsigned short)(v.z) & 0xfffe));
+       }
+}
+
+inline int b3TestQuantizedAabbAgainstQuantizedAabbSlow(
+       const unsigned short int* aabbMin1,
+       const unsigned short int* aabbMax1,
+       const unsigned short int* aabbMin2,
+       const unsigned short int* aabbMax2)
+{
+       //int overlap = 1;
+       if (aabbMin1[0] > aabbMax2[0])
+               return 0;
+       if (aabbMax1[0] < aabbMin2[0])
+               return 0;
+       if (aabbMin1[1] > aabbMax2[1])
+               return 0;
+       if (aabbMax1[1] < aabbMin2[1])
+               return 0;
+       if (aabbMin1[2] > aabbMax2[2])
+               return 0;
+       if (aabbMax1[2] < aabbMin2[2])
+               return 0;
+       return 1;
+       //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;
+       //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;
+       //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;
+       //return overlap;
+}
+
+#endif  //B3_QUANTIZED_BVH_NODE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h
new file mode 100644 (file)
index 0000000..c108255
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef B3_REDUCE_CONTACTS_H
+#define B3_REDUCE_CONTACTS_H
+
+inline int b3ReduceContacts(const b3Float4* p, int nPoints, const b3Float4& nearNormal, b3Int4* contactIdx)
+{
+       if (nPoints == 0)
+               return 0;
+
+       if (nPoints <= 4)
+               return nPoints;
+
+       if (nPoints > 64)
+               nPoints = 64;
+
+       b3Float4 center = b3MakeFloat4(0, 0, 0, 0);
+       {
+               for (int i = 0; i < nPoints; i++)
+                       center += p[i];
+               center /= (float)nPoints;
+       }
+
+       //      sample 4 directions
+
+       b3Float4 aVector = p[0] - center;
+       b3Float4 u = b3Cross3(nearNormal, aVector);
+       b3Float4 v = b3Cross3(nearNormal, u);
+       u = b3FastNormalized3(u);
+       v = b3FastNormalized3(v);
+
+       //keep point with deepest penetration
+       float minW = FLT_MAX;
+
+       int minIndex = -1;
+
+       b3Float4 maxDots;
+       maxDots.x = FLT_MIN;
+       maxDots.y = FLT_MIN;
+       maxDots.z = FLT_MIN;
+       maxDots.w = FLT_MIN;
+
+       //      idx, distance
+       for (int ie = 0; ie < nPoints; ie++)
+       {
+               if (p[ie].w < minW)
+               {
+                       minW = p[ie].w;
+                       minIndex = ie;
+               }
+               float f;
+               b3Float4 r = p[ie] - center;
+               f = b3Dot3F4(u, r);
+               if (f < maxDots.x)
+               {
+                       maxDots.x = f;
+                       contactIdx[0].x = ie;
+               }
+
+               f = b3Dot3F4(-u, r);
+               if (f < maxDots.y)
+               {
+                       maxDots.y = f;
+                       contactIdx[0].y = ie;
+               }
+
+               f = b3Dot3F4(v, r);
+               if (f < maxDots.z)
+               {
+                       maxDots.z = f;
+                       contactIdx[0].z = ie;
+               }
+
+               f = b3Dot3F4(-v, r);
+               if (f < maxDots.w)
+               {
+                       maxDots.w = f;
+                       contactIdx[0].w = ie;
+               }
+       }
+
+       if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+       {
+               //replace the first contact with minimum (todo: replace contact with least penetration)
+               contactIdx[0].x = minIndex;
+       }
+
+       return 4;
+}
+
+#endif  //B3_REDUCE_CONTACTS_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h
new file mode 100644 (file)
index 0000000..663e946
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef B3_RIGIDBODY_DATA_H
+#define B3_RIGIDBODY_DATA_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+#include "Bullet3Common/shared/b3Quat.h"
+#include "Bullet3Common/shared/b3Mat3x3.h"
+
+typedef struct b3RigidBodyData b3RigidBodyData_t;
+
+struct b3RigidBodyData
+{
+       b3Float4 m_pos;
+       b3Quat m_quat;
+       b3Float4 m_linVel;
+       b3Float4 m_angVel;
+
+       int m_collidableIdx;
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+};
+
+typedef struct b3InertiaData b3InertiaData_t;
+
+struct b3InertiaData
+{
+       b3Mat3x3 m_invInertiaWorld;
+       b3Mat3x3 m_initInvInertia;
+};
+
+#endif  //B3_RIGIDBODY_DATA_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h b/dali-physics/third-party/bullet3/src/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h
new file mode 100644 (file)
index 0000000..e0c3a5c
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef B3_UPDATE_AABBS_H
+#define B3_UPDATE_AABBS_H
+
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+void b3ComputeWorldAabb(int bodyId, __global const b3RigidBodyData_t* bodies, __global const b3Collidable_t* collidables, __global const b3Aabb_t* localShapeAABB, __global b3Aabb_t* worldAabbs)
+{
+       __global const b3RigidBodyData_t* body = &bodies[bodyId];
+
+       b3Float4 position = body->m_pos;
+       b3Quat orientation = body->m_quat;
+
+       int collidableIndex = body->m_collidableIdx;
+       int shapeIndex = collidables[collidableIndex].m_shapeIndex;
+
+       if (shapeIndex >= 0)
+       {
+               b3Aabb_t localAabb = localShapeAABB[collidableIndex];
+               b3Aabb_t worldAabb;
+
+               b3Float4 aabbAMinOut, aabbAMaxOut;
+               float margin = 0.f;
+               b3TransformAabb2(localAabb.m_minVec, localAabb.m_maxVec, margin, position, orientation, &aabbAMinOut, &aabbAMaxOut);
+
+               worldAabb.m_minVec = aabbAMinOut;
+               worldAabb.m_minIndices[3] = bodyId;
+               worldAabb.m_maxVec = aabbAMaxOut;
+               worldAabb.m_signedMaxIndices[3] = body[bodyId].m_invMass == 0.f ? 0 : 1;
+               worldAabbs[bodyId] = worldAabb;
+       }
+}
+
+#endif  //B3_UPDATE_AABBS_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Collision/premake4.lua b/dali-physics/third-party/bullet3/src/Bullet3Collision/premake4.lua
new file mode 100644 (file)
index 0000000..bd0da54
--- /dev/null
@@ -0,0 +1,16 @@
+       project "Bullet3Collision"
+
+       language "C++"
+                               
+       kind "StaticLib"
+               
+       includedirs {".."}
+
+    if os.is("Linux") then
+        buildoptions{"-fPIC"}
+    end
+
+       files {
+               "**.cpp",
+               "**.h"
+       }
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/CMakeLists.txt b/dali-physics/third-party/bullet3/src/Bullet3Common/CMakeLists.txt
new file mode 100644 (file)
index 0000000..03a3b40
--- /dev/null
@@ -0,0 +1,63 @@
+
+INCLUDE_DIRECTORIES(
+       ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(Bullet3Common_SRCS
+       b3AlignedAllocator.cpp
+       b3Vector3.cpp
+       b3Logging.cpp
+)
+
+SET(Bullet3Common_HDRS
+       b3AlignedAllocator.h
+       b3AlignedObjectArray.h
+       b3CommandLineArgs.h
+       b3HashMap.h
+       b3Logging.h
+       b3Matrix3x3.h
+       b3MinMax.h
+       b3PoolAllocator.h
+       b3QuadWord.h
+       b3Quaternion.h
+       b3Random.h
+       b3Scalar.h
+       b3StackAlloc.h
+       b3Transform.h
+       b3TransformUtil.h
+       b3Vector3.h
+       shared/b3Float4.h
+       shared/b3Int2.h
+       shared/b3Int4.h
+       shared/b3Mat3x3.h
+       shared/b3PlatformDefinitions.h
+       shared/b3Quat.h
+)
+
+ADD_LIBRARY(Bullet3Common ${Bullet3Common_SRCS} ${Bullet3Common_HDRS})
+SET_TARGET_PROPERTIES(Bullet3Common PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet3Common PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               #FILES_MATCHING requires CMake 2.6
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet3Common DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet3Common
+                                       RUNTIME DESTINATION bin
+                                       LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                       ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h"  PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(Bullet3Common PROPERTIES FRAMEWORK true)
+                       SET_TARGET_PROPERTIES(Bullet3Common PROPERTIES PUBLIC_HEADER "${Bullet3Common_HDRS}")
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3AlignedAllocator.cpp b/dali-physics/third-party/bullet3/src/Bullet3Common/b3AlignedAllocator.cpp
new file mode 100644 (file)
index 0000000..d546d5e
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3AlignedAllocator.h"
+
+#ifdef B3_ALLOCATOR_STATISTICS
+int b3g_numAlignedAllocs = 0;
+int b3g_numAlignedFree = 0;
+int b3g_totalBytesAlignedAllocs = 0;  //detect memory leaks
+#endif
+
+static void *b3AllocDefault(size_t size)
+{
+       return malloc(size);
+}
+
+static void b3FreeDefault(void *ptr)
+{
+       free(ptr);
+}
+
+static b3AllocFunc *b3s_allocFunc = b3AllocDefault;
+static b3FreeFunc *b3s_freeFunc = b3FreeDefault;
+
+#if defined(B3_HAS_ALIGNED_ALLOCATOR)
+#include <malloc.h>
+static void *b3AlignedAllocDefault(size_t size, int alignment)
+{
+       return _aligned_malloc(size, (size_t)alignment);
+}
+
+static void b3AlignedFreeDefault(void *ptr)
+{
+       _aligned_free(ptr);
+}
+#elif defined(__CELLOS_LV2__)
+#include <stdlib.h>
+
+static inline void *b3AlignedAllocDefault(size_t size, int alignment)
+{
+       return memalign(alignment, size);
+}
+
+static inline void b3AlignedFreeDefault(void *ptr)
+{
+       free(ptr);
+}
+#else
+
+static inline void *b3AlignedAllocDefault(size_t size, int alignment)
+{
+       void *ret;
+       char *real;
+       real = (char *)b3s_allocFunc(size + sizeof(void *) + (alignment - 1));
+       if (real)
+       {
+               ret = b3AlignPointer(real + sizeof(void *), alignment);
+               *((void **)(ret)-1) = (void *)(real);
+       }
+       else
+       {
+               ret = (void *)(real);
+       }
+       return (ret);
+}
+
+static inline void b3AlignedFreeDefault(void *ptr)
+{
+       void *real;
+
+       if (ptr)
+       {
+               real = *((void **)(ptr)-1);
+               b3s_freeFunc(real);
+       }
+}
+#endif
+
+static b3AlignedAllocFunc *b3s_alignedAllocFunc = b3AlignedAllocDefault;
+static b3AlignedFreeFunc *b3s_alignedFreeFunc = b3AlignedFreeDefault;
+
+void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc *allocFunc, b3AlignedFreeFunc *freeFunc)
+{
+       b3s_alignedAllocFunc = allocFunc ? allocFunc : b3AlignedAllocDefault;
+       b3s_alignedFreeFunc = freeFunc ? freeFunc : b3AlignedFreeDefault;
+}
+
+void b3AlignedAllocSetCustom(b3AllocFunc *allocFunc, b3FreeFunc *freeFunc)
+{
+       b3s_allocFunc = allocFunc ? allocFunc : b3AllocDefault;
+       b3s_freeFunc = freeFunc ? freeFunc : b3FreeDefault;
+}
+
+#ifdef B3_DEBUG_MEMORY_ALLOCATIONS
+//this generic allocator provides the total allocated number of bytes
+#include <stdio.h>
+
+void *b3AlignedAllocInternal(size_t size, int alignment, int line, char *filename)
+{
+       void *ret;
+       char *real;
+#ifdef B3_ALLOCATOR_STATISTICS
+       b3g_totalBytesAlignedAllocs += size;
+       b3g_numAlignedAllocs++;
+#endif
+       real = (char *)b3s_allocFunc(size + 2 * sizeof(void *) + (alignment - 1));
+       if (real)
+       {
+               ret = (void *)b3AlignPointer(real + 2 * sizeof(void *), alignment);
+               *((void **)(ret)-1) = (void *)(real);
+               *((int *)(ret)-2) = size;
+       }
+       else
+       {
+               ret = (void *)(real);  //??
+       }
+
+       b3Printf("allocation#%d at address %x, from %s,line %d, size %d\n", b3g_numAlignedAllocs, real, filename, line, size);
+
+       int *ptr = (int *)ret;
+       *ptr = 12;
+       return (ret);
+}
+
+void b3AlignedFreeInternal(void *ptr, int line, char *filename)
+{
+       void *real;
+#ifdef B3_ALLOCATOR_STATISTICS
+       b3g_numAlignedFree++;
+#endif
+       if (ptr)
+       {
+               real = *((void **)(ptr)-1);
+               int size = *((int *)(ptr)-2);
+#ifdef B3_ALLOCATOR_STATISTICS
+               b3g_totalBytesAlignedAllocs -= size;
+#endif
+               b3Printf("free #%d at address %x, from %s,line %d, size %d\n", b3g_numAlignedFree, real, filename, line, size);
+
+               b3s_freeFunc(real);
+       }
+       else
+       {
+               b3Printf("NULL ptr\n");
+       }
+}
+
+#else  //B3_DEBUG_MEMORY_ALLOCATIONS
+
+void *b3AlignedAllocInternal(size_t size, int alignment)
+{
+#ifdef B3_ALLOCATOR_STATISTICS
+       b3g_numAlignedAllocs++;
+#endif
+       void *ptr;
+       ptr = b3s_alignedAllocFunc(size, alignment);
+       //      b3Printf("b3AlignedAllocInternal %d, %x\n",size,ptr);
+       return ptr;
+}
+
+void b3AlignedFreeInternal(void *ptr)
+{
+       if (!ptr)
+       {
+               return;
+       }
+#ifdef B3_ALLOCATOR_STATISTICS
+       b3g_numAlignedFree++;
+#endif
+       //      b3Printf("b3AlignedFreeInternal %x\n",ptr);
+       b3s_alignedFreeFunc(ptr);
+}
+
+#endif  //B3_DEBUG_MEMORY_ALLOCATIONS
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3AlignedAllocator.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3AlignedAllocator.h
new file mode 100644 (file)
index 0000000..bcff9f1
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_ALIGNED_ALLOCATOR
+#define B3_ALIGNED_ALLOCATOR
+
+///we probably replace this with our own aligned memory allocator
+///so we replace _aligned_malloc and _aligned_free with our own
+///that is better portable and more predictable
+
+#include "b3Scalar.h"
+//#define B3_DEBUG_MEMORY_ALLOCATIONS 1
+#ifdef B3_DEBUG_MEMORY_ALLOCATIONS
+
+#define b3AlignedAlloc(a, b) \
+       b3AlignedAllocInternal(a, b, __LINE__, __FILE__)
+
+#define b3AlignedFree(ptr) \
+       b3AlignedFreeInternal(ptr, __LINE__, __FILE__)
+
+void* b3AlignedAllocInternal(size_t size, int alignment, int line, char* filename);
+
+void b3AlignedFreeInternal(void* ptr, int line, char* filename);
+
+#else
+void* b3AlignedAllocInternal(size_t size, int alignment);
+void b3AlignedFreeInternal(void* ptr);
+
+#define b3AlignedAlloc(size, alignment) b3AlignedAllocInternal(size, alignment)
+#define b3AlignedFree(ptr) b3AlignedFreeInternal(ptr)
+
+#endif
+typedef int btSizeType;
+
+typedef void*(b3AlignedAllocFunc)(size_t size, int alignment);
+typedef void(b3AlignedFreeFunc)(void* memblock);
+typedef void*(b3AllocFunc)(size_t size);
+typedef void(b3FreeFunc)(void* memblock);
+
+///The developer can let all Bullet memory allocations go through a custom memory allocator, using b3AlignedAllocSetCustom
+void b3AlignedAllocSetCustom(b3AllocFunc* allocFunc, b3FreeFunc* freeFunc);
+///If the developer has already an custom aligned allocator, then b3AlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
+void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc* allocFunc, b3AlignedFreeFunc* freeFunc);
+
+///The b3AlignedAllocator is a portable class for aligned memory allocations.
+///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using b3AlignedAllocSetCustom and b3AlignedAllocSetCustomAligned.
+template <typename T, unsigned Alignment>
+class b3AlignedAllocator
+{
+       typedef b3AlignedAllocator<T, Alignment> self_type;
+
+public:
+       //just going down a list:
+       b3AlignedAllocator() {}
+       /*
+       b3AlignedAllocator( const self_type & ) {}
+       */
+
+       template <typename Other>
+       b3AlignedAllocator(const b3AlignedAllocator<Other, Alignment>&)
+       {
+       }
+
+       typedef const T* const_pointer;
+       typedef const T& const_reference;
+       typedef T* pointer;
+       typedef T& reference;
+       typedef T value_type;
+
+       pointer address(reference ref) const { return &ref; }
+       const_pointer address(const_reference ref) const { return &ref; }
+       pointer allocate(btSizeType n, const_pointer* hint = 0)
+       {
+               (void)hint;
+               return reinterpret_cast<pointer>(b3AlignedAlloc(sizeof(value_type) * n, Alignment));
+       }
+       void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); }
+       void deallocate(pointer ptr)
+       {
+               b3AlignedFree(reinterpret_cast<void*>(ptr));
+       }
+       void destroy(pointer ptr) { ptr->~value_type(); }
+
+       template <typename O>
+       struct rebind
+       {
+               typedef b3AlignedAllocator<O, Alignment> other;
+       };
+       template <typename O>
+       self_type& operator=(const b3AlignedAllocator<O, Alignment>&)
+       {
+               return *this;
+       }
+
+       friend bool operator==(const self_type&, const self_type&) { return true; }
+};
+
+#endif  //B3_ALIGNED_ALLOCATOR
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3AlignedObjectArray.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3AlignedObjectArray.h
new file mode 100644 (file)
index 0000000..8ef3331
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_OBJECT_ARRAY__
+#define B3_OBJECT_ARRAY__
+
+#include "b3Scalar.h"  // has definitions like B3_FORCE_INLINE
+#include "b3AlignedAllocator.h"
+
+///If the platform doesn't support placement new, you can disable B3_USE_PLACEMENT_NEW
+///then the b3AlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
+///You can enable B3_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
+///see discussion here: https://bulletphysics.orgphpBB2/viewtopic.php?t=1231 and
+///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
+
+#define B3_USE_PLACEMENT_NEW 1
+//#define B3_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
+#define B3_ALLOW_ARRAY_COPY_OPERATOR  // enabling this can accidently perform deep copies of data if you are not careful
+
+#ifdef B3_USE_MEMCPY
+#include <memory.h>
+#include <string.h>
+#endif  //B3_USE_MEMCPY
+
+#ifdef B3_USE_PLACEMENT_NEW
+#include <new>  //for placement new
+#endif          //B3_USE_PLACEMENT_NEW
+
+///The b3AlignedObjectArray 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 b3AlignedObjectArray
+{
+       b3AlignedAllocator<T, 16> m_allocator;
+
+       int m_size;
+       int m_capacity;
+       T* m_data;
+       //PCK: added this line
+       bool m_ownsMemory;
+
+#ifdef B3_ALLOW_ARRAY_COPY_OPERATOR
+public:
+       B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T>& other)
+       {
+               copyFromArray(other);
+               return *this;
+       }
+#else   //B3_ALLOW_ARRAY_COPY_OPERATOR
+private:
+       B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T>& other);
+#endif  //B3_ALLOW_ARRAY_COPY_OPERATOR
+
+protected:
+       B3_FORCE_INLINE int allocSize(int size)
+       {
+               return (size ? size * 2 : 1);
+       }
+       B3_FORCE_INLINE void copy(int start, int end, T* dest) const
+       {
+               int i;
+               for (i = start; i < end; ++i)
+#ifdef B3_USE_PLACEMENT_NEW
+                       new (&dest[i]) T(m_data[i]);
+#else
+                       dest[i] = m_data[i];
+#endif  //B3_USE_PLACEMENT_NEW
+       }
+
+       B3_FORCE_INLINE void init()
+       {
+               //PCK: added this line
+               m_ownsMemory = true;
+               m_data = 0;
+               m_size = 0;
+               m_capacity = 0;
+       }
+       B3_FORCE_INLINE void destroy(int first, int last)
+       {
+               int i;
+               for (i = first; i < last; i++)
+               {
+                       m_data[i].~T();
+               }
+       }
+
+       B3_FORCE_INLINE void* allocate(int size)
+       {
+               if (size)
+                       return m_allocator.allocate(size);
+               return 0;
+       }
+
+       B3_FORCE_INLINE void deallocate()
+       {
+               if (m_data)
+               {
+                       //PCK: enclosed the deallocation in this block
+                       if (m_ownsMemory)
+                       {
+                               m_allocator.deallocate(m_data);
+                       }
+                       m_data = 0;
+               }
+       }
+
+public:
+       b3AlignedObjectArray()
+       {
+               init();
+       }
+
+       ~b3AlignedObjectArray()
+       {
+               clear();
+       }
+
+       ///Generally it is best to avoid using the copy constructor of an b3AlignedObjectArray, and use a (const) reference to the array instead.
+       b3AlignedObjectArray(const b3AlignedObjectArray& otherArray)
+       {
+               init();
+
+               int otherSize = otherArray.size();
+               resize(otherSize);
+               //don't use otherArray.copy, it can leak memory
+               for (int i = 0; i < otherSize; i++)
+               {
+                       m_data[i] = otherArray[i];
+               }
+       }
+
+       /// return the number of elements in the array
+       B3_FORCE_INLINE int size() const
+       {
+               return m_size;
+       }
+
+       B3_FORCE_INLINE const T& at(int n) const
+       {
+               b3Assert(n >= 0);
+               b3Assert(n < size());
+               return m_data[n];
+       }
+
+       B3_FORCE_INLINE T& at(int n)
+       {
+               b3Assert(n >= 0);
+               b3Assert(n < size());
+               return m_data[n];
+       }
+
+       B3_FORCE_INLINE const T& operator[](int n) const
+       {
+               b3Assert(n >= 0);
+               b3Assert(n < size());
+               return m_data[n];
+       }
+
+       B3_FORCE_INLINE T& operator[](int n)
+       {
+               b3Assert(n >= 0);
+               b3Assert(n < size());
+               return m_data[n];
+       }
+
+       ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
+       B3_FORCE_INLINE void clear()
+       {
+               destroy(0, size());
+
+               deallocate();
+
+               init();
+       }
+
+       B3_FORCE_INLINE void pop_back()
+       {
+               b3Assert(m_size > 0);
+               m_size--;
+               m_data[m_size].~T();
+       }
+
+       ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
+       ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
+       B3_FORCE_INLINE void resizeNoInitialize(int newsize)
+       {
+               int curSize = size();
+
+               if (newsize < curSize)
+               {
+               }
+               else
+               {
+                       if (newsize > size())
+                       {
+                               reserve(newsize);
+                       }
+                       //leave this uninitialized
+               }
+               m_size = newsize;
+       }
+
+       B3_FORCE_INLINE void resize(int newsize, const T& fillData = T())
+       {
+               int curSize = size();
+
+               if (newsize < curSize)
+               {
+                       for (int i = newsize; i < curSize; i++)
+                       {
+                               m_data[i].~T();
+                       }
+               }
+               else
+               {
+                       if (newsize > size())
+                       {
+                               reserve(newsize);
+                       }
+#ifdef B3_USE_PLACEMENT_NEW
+                       for (int i = curSize; i < newsize; i++)
+                       {
+                               new (&m_data[i]) T(fillData);
+                       }
+#endif  //B3_USE_PLACEMENT_NEW
+               }
+
+               m_size = newsize;
+       }
+       B3_FORCE_INLINE T& expandNonInitializing()
+       {
+               int sz = size();
+               if (sz == capacity())
+               {
+                       reserve(allocSize(size()));
+               }
+               m_size++;
+
+               return m_data[sz];
+       }
+
+       B3_FORCE_INLINE T& expand(const T& fillValue = T())
+       {
+               int sz = size();
+               if (sz == capacity())
+               {
+                       reserve(allocSize(size()));
+               }
+               m_size++;
+#ifdef B3_USE_PLACEMENT_NEW
+               new (&m_data[sz]) T(fillValue);  //use the in-place new (not really allocating heap memory)
+#endif
+
+               return m_data[sz];
+       }
+
+       B3_FORCE_INLINE void push_back(const T& _Val)
+       {
+               int sz = size();
+               if (sz == capacity())
+               {
+                       reserve(allocSize(size()));
+               }
+
+#ifdef B3_USE_PLACEMENT_NEW
+               new (&m_data[m_size]) T(_Val);
+#else
+               m_data[size()] = _Val;
+#endif  //B3_USE_PLACEMENT_NEW
+
+               m_size++;
+       }
+
+       /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
+       B3_FORCE_INLINE int capacity() const
+       {
+               return m_capacity;
+       }
+
+       B3_FORCE_INLINE void reserve(int _Count)
+       {  // determine new minimum length of allocated storage
+               if (capacity() < _Count)
+               {  // not enough room, reallocate
+                       T* s = (T*)allocate(_Count);
+                       b3Assert(s);
+                       if (s == 0)
+                       {
+                               b3Error("b3AlignedObjectArray reserve out-of-memory\n");
+                               _Count = 0;
+                               m_size = 0;
+                       }
+                       copy(0, size(), s);
+
+                       destroy(0, size());
+
+                       deallocate();
+
+                       //PCK: added this line
+                       m_ownsMemory = true;
+
+                       m_data = s;
+
+                       m_capacity = _Count;
+               }
+       }
+
+       class less
+       {
+       public:
+               bool operator()(const T& a, const T& b)
+               {
+                       return (a < b);
+               }
+       };
+
+       template <typename L>
+       void quickSortInternal(const 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(const 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>
+       void downHeap(T* pArr, int k, int n, const L& CompareFunc)
+       {
+               /*  PRE: a[k+1..N] is a heap */
+               /* POST:  a[k..N]  is a heap */
+
+               T temp = pArr[k - 1];
+               /* k has child(s) */
+               while (k <= n / 2)
+               {
+                       int child = 2 * k;
+
+                       if ((child < n) && CompareFunc(pArr[child - 1], pArr[child]))
+                       {
+                               child++;
+                       }
+                       /* pick larger child */
+                       if (CompareFunc(temp, pArr[child - 1]))
+                       {
+                               /* move child up */
+                               pArr[k - 1] = pArr[child - 1];
+                               k = child;
+                       }
+                       else
+                       {
+                               break;
+                       }
+               }
+               pArr[k - 1] = temp;
+       } /*downHeap*/
+
+       void swap(int index0, int index1)
+       {
+#ifdef B3_USE_MEMCPY
+               char temp[sizeof(T)];
+               memcpy(temp, &m_data[index0], sizeof(T));
+               memcpy(&m_data[index0], &m_data[index1], sizeof(T));
+               memcpy(&m_data[index1], temp, sizeof(T));
+#else
+               T temp = m_data[index0];
+               m_data[index0] = m_data[index1];
+               m_data[index1] = temp;
+#endif  //B3_USE_PLACEMENT_NEW
+       }
+
+       template <typename L>
+       void heapSort(const L& CompareFunc)
+       {
+               /* sort a[0..N-1],  N.B. 0 to N-1 */
+               int k;
+               int n = m_size;
+               for (k = n / 2; k > 0; k--)
+               {
+                       downHeap(m_data, k, n, CompareFunc);
+               }
+
+               /* a[1..N] is now a heap */
+               while (n >= 1)
+               {
+                       swap(0, n - 1); /* largest of a[0..n-1] */
+
+                       n = n - 1;
+                       /* restore a[1..i-1] heap */
+                       downHeap(m_data, 1, n, CompareFunc);
+               }
+       }
+
+       ///non-recursive binary search, assumes sorted array
+       int findBinarySearch(const T& key) const
+       {
+               int first = 0;
+               int last = size() - 1;
+
+               //assume sorted array
+               while (first <= last)
+               {
+                       int mid = (first + last) / 2;  // compute mid point.
+                       if (key > m_data[mid])
+                               first = mid + 1;  // repeat search in top half.
+                       else if (key < m_data[mid])
+                               last = mid - 1;  // repeat search in bottom half.
+                       else
+                               return mid;  // found it. return position /////
+               }
+               return size();  // failed to find key
+       }
+
+       int findLinearSearch(const T& key) const
+       {
+               int index = size();
+               int i;
+
+               for (i = 0; i < size(); i++)
+               {
+                       if (m_data[i] == key)
+                       {
+                               index = i;
+                               break;
+                       }
+               }
+               return index;
+       }
+
+       int findLinearSearch2(const T& key) const
+       {
+               int index = -1;
+               int i;
+
+               for (i = 0; i < size(); i++)
+               {
+                       if (m_data[i] == key)
+                       {
+                               index = i;
+                               break;
+                       }
+               }
+               return index;
+       }
+
+       void remove(const T& key)
+       {
+               int findIndex = findLinearSearch(key);
+               if (findIndex < size())
+               {
+                       swap(findIndex, size() - 1);
+                       pop_back();
+               }
+       }
+
+       //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;
+       }
+
+       void copyFromArray(const b3AlignedObjectArray& otherArray)
+       {
+               int otherSize = otherArray.size();
+               resize(otherSize);
+               //don't use otherArray.copy, it can leak memory
+               for (int i = 0; i < otherSize; i++)
+               {
+                       m_data[i] = otherArray[i];
+               }
+       }
+
+       void removeAtIndex(int index)
+       {
+               if (index < size())
+               {
+                       swap(index, size() - 1);
+                       pop_back();
+               }
+       }
+};
+
+#endif  //B3_OBJECT_ARRAY__
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3CommandLineArgs.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3CommandLineArgs.h
new file mode 100644 (file)
index 0000000..5fe4f25
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef COMMAND_LINE_ARGS_H
+#define COMMAND_LINE_ARGS_H
+
+/******************************************************************************
+ * Command-line parsing
+ ******************************************************************************/
+#include <map>
+#include <algorithm>
+#include <string>
+#include <cstring>
+#include <sstream>
+class b3CommandLineArgs
+{
+protected:
+       std::map<std::string, std::string> pairs;
+
+public:
+       // Constructor
+       b3CommandLineArgs(int argc, char **argv)
+       {
+               addArgs(argc, argv);
+       }
+
+       void addArgs(int argc, char **argv)
+       {
+               for (int i = 1; i < argc; i++)
+               {
+                       std::string arg = argv[i];
+
+                       if ((arg.length() < 2) || (arg[0] != '-') || (arg[1] != '-'))
+                       {
+                               continue;
+                       }
+
+                       std::string::size_type pos;
+                       std::string key, val;
+                       if ((pos = arg.find('=')) == std::string::npos)
+                       {
+                               key = std::string(arg, 2, arg.length() - 2);
+                               val = "";
+                       }
+                       else
+                       {
+                               key = std::string(arg, 2, pos - 2);
+                               val = std::string(arg, pos + 1, arg.length() - 1);
+                       }
+
+                       //only add new keys, don't replace existing
+                       if (pairs.find(key) == pairs.end())
+                       {
+                               pairs[key] = val;
+                       }
+               }
+       }
+
+       bool CheckCmdLineFlag(const char *arg_name)
+       {
+               std::map<std::string, std::string>::iterator itr;
+               if ((itr = pairs.find(arg_name)) != pairs.end())
+               {
+                       return true;
+               }
+               return false;
+       }
+
+       template <typename T>
+       bool GetCmdLineArgument(const char *arg_name, T &val);
+
+       int ParsedArgc()
+       {
+               return pairs.size();
+       }
+};
+
+template <typename T>
+inline bool b3CommandLineArgs::GetCmdLineArgument(const char *arg_name, T &val)
+{
+       std::map<std::string, std::string>::iterator itr;
+       if ((itr = pairs.find(arg_name)) != pairs.end())
+       {
+               std::istringstream strstream(itr->second);
+               strstream >> val;
+               return true;
+       }
+       return false;
+}
+
+template <>
+inline bool b3CommandLineArgs::GetCmdLineArgument<char *>(const char *arg_name, char *&val)
+{
+       std::map<std::string, std::string>::iterator itr;
+       if ((itr = pairs.find(arg_name)) != pairs.end())
+       {
+               std::string s = itr->second;
+               val = (char *)malloc(sizeof(char) * (s.length() + 1));
+               std::strcpy(val, s.c_str());
+               return true;
+       }
+       else
+       {
+               val = NULL;
+       }
+       return false;
+}
+
+#endif  //COMMAND_LINE_ARGS_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3FileUtils.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3FileUtils.h
new file mode 100644 (file)
index 0000000..9ded17e
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef B3_FILE_UTILS_H
+#define B3_FILE_UTILS_H
+
+#include <stdio.h>
+#include "b3Scalar.h"
+#include <stddef.h>  //ptrdiff_h
+#include <string.h>
+
+struct b3FileUtils
+{
+       b3FileUtils()
+       {
+       }
+       virtual ~b3FileUtils()
+       {
+       }
+
+       static bool findFile(const char* orgFileName, char* relativeFileName, int maxRelativeFileNameMaxLen)
+       {
+               FILE* f = 0;
+               f = fopen(orgFileName, "rb");
+               if (f)
+               {
+                       //printf("original file found: [%s]\n", orgFileName);
+                       sprintf(relativeFileName, "%s", orgFileName);
+                       fclose(f);
+                       return true;
+               }
+
+               //printf("Trying various directories, relative to current working directory\n");
+               const char* prefix[] = {"./", "./data/", "../data/", "../../data/", "../../../data/", "../../../../data/"};
+               int numPrefixes = sizeof(prefix) / sizeof(const char*);
+
+               f = 0;
+               bool fileFound = false;
+
+               for (int i = 0; !f && i < numPrefixes; i++)
+               {
+#ifdef _MSC_VER
+                       sprintf_s(relativeFileName, maxRelativeFileNameMaxLen, "%s%s", prefix[i], orgFileName);
+#else
+                       sprintf(relativeFileName, "%s%s", prefix[i], orgFileName);
+#endif
+                       f = fopen(relativeFileName, "rb");
+                       if (f)
+                       {
+                               fileFound = true;
+                               break;
+                       }
+               }
+               if (f)
+               {
+                       fclose(f);
+               }
+
+               return fileFound;
+       }
+
+       static const char* strip2(const char* name, const char* pattern)
+       {
+               size_t const patlen = strlen(pattern);
+               size_t patcnt = 0;
+               const char* oriptr;
+               const char* patloc;
+               // find how many times the pattern occurs in the original string
+               for (oriptr = name; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
+               {
+                       patcnt++;
+               }
+               return oriptr;
+       }
+
+       static int extractPath(const char* fileName, char* path, int maxPathLength)
+       {
+               const char* stripped = strip2(fileName, "/");
+               stripped = strip2(stripped, "\\");
+
+               ptrdiff_t len = stripped - fileName;
+               b3Assert((len + 1) < maxPathLength);
+
+               if (len && ((len + 1) < maxPathLength))
+               {
+                       for (int i = 0; i < len; i++)
+                       {
+                               path[i] = fileName[i];
+                       }
+                       path[len] = 0;
+               }
+               else
+               {
+                       len = 0;
+                       b3Assert(maxPathLength > 0);
+                       if (maxPathLength > 0)
+                       {
+                               path[len] = 0;
+                       }
+               }
+               return len;
+       }
+
+       static char toLowerChar(const char t)
+       {
+               if (t >= (char)'A' && t <= (char)'Z')
+                       return t + ((char)'a' - (char)'A');
+               else
+                       return t;
+       }
+
+       static void toLower(char* str)
+       {
+               int len = strlen(str);
+               for (int i = 0; i < len; i++)
+               {
+                       str[i] = toLowerChar(str[i]);
+               }
+       }
+
+       /*static const char* strip2(const char* name, const char* pattern)
+       {
+               size_t const patlen = strlen(pattern);
+               size_t patcnt = 0;
+               const char * oriptr;
+               const char * patloc;
+               // find how many times the pattern occurs in the original string
+               for (oriptr = name; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen)
+               {
+                       patcnt++;
+               }
+               return oriptr;
+       }
+       */
+};
+#endif  //B3_FILE_UTILS_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3HashMap.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3HashMap.h
new file mode 100644 (file)
index 0000000..3009e2c
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_HASH_MAP_H
+#define B3_HASH_MAP_H
+
+#include "b3AlignedObjectArray.h"
+
+#include <string>
+
+///very basic hashable string implementation, compatible with b3HashMap
+struct b3HashString
+{
+       std::string m_string;
+       unsigned int m_hash;
+
+       B3_FORCE_INLINE unsigned int getHash() const
+       {
+               return m_hash;
+       }
+
+       b3HashString(const char* name)
+               : m_string(name)
+       {
+               /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
+               static const unsigned int InitialFNV = 2166136261u;
+               static const unsigned int FNVMultiple = 16777619u;
+
+               /* Fowler / Noll / Vo (FNV) Hash */
+               unsigned int hash = InitialFNV;
+               int len = m_string.length();
+               for (int i = 0; i < len; i++)
+               {
+                       hash = hash ^ (m_string[i]); /* xor  the low 8 bits */
+                       hash = hash * FNVMultiple;   /* multiply by the magic number */
+               }
+               m_hash = hash;
+       }
+
+       int portableStringCompare(const char* src, const char* dst) const
+       {
+               int ret = 0;
+
+               while (!(ret = *(unsigned char*)src - *(unsigned char*)dst) && *dst)
+                       ++src, ++dst;
+
+               if (ret < 0)
+                       ret = -1;
+               else if (ret > 0)
+                       ret = 1;
+
+               return (ret);
+       }
+
+       bool equals(const b3HashString& other) const
+       {
+               return (m_string == other.m_string);
+       }
+};
+
+const int B3_HASH_NULL = 0xffffffff;
+
+class b3HashInt
+{
+       int m_uid;
+
+public:
+       b3HashInt(int uid) : m_uid(uid)
+       {
+       }
+
+       int getUid1() const
+       {
+               return m_uid;
+       }
+
+       void setUid1(int uid)
+       {
+               m_uid = uid;
+       }
+
+       bool equals(const b3HashInt& other) const
+       {
+               return getUid1() == other.getUid1();
+       }
+       //to our success
+       B3_FORCE_INLINE unsigned int getHash() const
+       {
+               int key = m_uid;
+               // Thomas Wang's hash
+               key += ~(key << 15);
+               key ^= (key >> 10);
+               key += (key << 3);
+               key ^= (key >> 6);
+               key += ~(key << 11);
+               key ^= (key >> 16);
+               return key;
+       }
+};
+
+class b3HashPtr
+{
+       union {
+               const void* m_pointer;
+               int m_hashValues[2];
+       };
+
+public:
+       b3HashPtr(const void* ptr)
+               : m_pointer(ptr)
+       {
+       }
+
+       const void* getPointer() const
+       {
+               return m_pointer;
+       }
+
+       bool equals(const b3HashPtr& other) const
+       {
+               return getPointer() == other.getPointer();
+       }
+
+       //to our success
+       B3_FORCE_INLINE unsigned int getHash() const
+       {
+               const bool VOID_IS_8 = ((sizeof(void*) == 8));
+
+               int key = VOID_IS_8 ? m_hashValues[0] + m_hashValues[1] : m_hashValues[0];
+
+               // Thomas Wang's hash
+               key += ~(key << 15);
+               key ^= (key >> 10);
+               key += (key << 3);
+               key ^= (key >> 6);
+               key += ~(key << 11);
+               key ^= (key >> 16);
+               return key;
+       }
+};
+
+template <class Value>
+class b3HashKeyPtr
+{
+       int m_uid;
+
+public:
+       b3HashKeyPtr(int uid) : m_uid(uid)
+       {
+       }
+
+       int getUid1() const
+       {
+               return m_uid;
+       }
+
+       bool equals(const b3HashKeyPtr<Value>& other) const
+       {
+               return getUid1() == other.getUid1();
+       }
+
+       //to our success
+       B3_FORCE_INLINE unsigned int getHash() const
+       {
+               int key = m_uid;
+               // Thomas Wang's hash
+               key += ~(key << 15);
+               key ^= (key >> 10);
+               key += (key << 3);
+               key ^= (key >> 6);
+               key += ~(key << 11);
+               key ^= (key >> 16);
+               return key;
+       }
+};
+
+template <class Value>
+class b3HashKey
+{
+       int m_uid;
+
+public:
+       b3HashKey(int uid) : m_uid(uid)
+       {
+       }
+
+       int getUid1() const
+       {
+               return m_uid;
+       }
+
+       bool equals(const b3HashKey<Value>& other) const
+       {
+               return getUid1() == other.getUid1();
+       }
+       //to our success
+       B3_FORCE_INLINE unsigned int getHash() const
+       {
+               int key = m_uid;
+               // Thomas Wang's hash
+               key += ~(key << 15);
+               key ^= (key >> 10);
+               key += (key << 3);
+               key ^= (key >> 6);
+               key += ~(key << 11);
+               key ^= (key >> 16);
+               return key;
+       }
+};
+
+///The b3HashMap template class implements a generic and lightweight hashmap.
+///A basic sample of how to use b3HashMap is located in Demos\BasicDemo\main.cpp
+template <class Key, class Value>
+class b3HashMap
+{
+protected:
+       b3AlignedObjectArray<int> m_hashTable;
+       b3AlignedObjectArray<int> m_next;
+
+       b3AlignedObjectArray<Value> m_valueArray;
+       b3AlignedObjectArray<Key> m_keyArray;
+
+       void growTables(const Key& /*key*/)
+       {
+               int newCapacity = m_valueArray.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] = B3_HASH_NULL;
+                       }
+                       for (i = 0; i < newCapacity; ++i)
+                       {
+                               m_next[i] = B3_HASH_NULL;
+                       }
+
+                       for (i = 0; i < curHashtableSize; i++)
+                       {
+                               //const Value& value = m_valueArray[i];
+                               //const Key& key = m_keyArray[i];
+
+                               int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity() - 1);  // New hash value with new mask
+                               m_next[i] = m_hashTable[hashValue];
+                               m_hashTable[hashValue] = i;
+                       }
+               }
+       }
+
+public:
+       void insert(const Key& key, const Value& value)
+       {
+               int hash = key.getHash() & (m_valueArray.capacity() - 1);
+
+               //replace value if the key is already there
+               int index = findIndex(key);
+               if (index != B3_HASH_NULL)
+               {
+                       m_valueArray[index] = value;
+                       return;
+               }
+
+               int count = m_valueArray.size();
+               int oldCapacity = m_valueArray.capacity();
+               m_valueArray.push_back(value);
+               m_keyArray.push_back(key);
+
+               int newCapacity = m_valueArray.capacity();
+               if (oldCapacity < newCapacity)
+               {
+                       growTables(key);
+                       //hash with new capacity
+                       hash = key.getHash() & (m_valueArray.capacity() - 1);
+               }
+               m_next[count] = m_hashTable[hash];
+               m_hashTable[hash] = count;
+       }
+
+       void remove(const Key& key)
+       {
+               int hash = key.getHash() & (m_valueArray.capacity() - 1);
+
+               int pairIndex = findIndex(key);
+
+               if (pairIndex == B3_HASH_NULL)
+               {
+                       return;
+               }
+
+               // Remove the pair from the hash table.
+               int index = m_hashTable[hash];
+               b3Assert(index != B3_HASH_NULL);
+
+               int previous = B3_HASH_NULL;
+               while (index != pairIndex)
+               {
+                       previous = index;
+                       index = m_next[index];
+               }
+
+               if (previous != B3_HASH_NULL)
+               {
+                       b3Assert(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_valueArray.size() - 1;
+
+               // If the removed pair is the last pair, we are done.
+               if (lastPairIndex == pairIndex)
+               {
+                       m_valueArray.pop_back();
+                       m_keyArray.pop_back();
+                       return;
+               }
+
+               // Remove the last pair from the hash table.
+               int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity() - 1);
+
+               index = m_hashTable[lastHash];
+               b3Assert(index != B3_HASH_NULL);
+
+               previous = B3_HASH_NULL;
+               while (index != lastPairIndex)
+               {
+                       previous = index;
+                       index = m_next[index];
+               }
+
+               if (previous != B3_HASH_NULL)
+               {
+                       b3Assert(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_valueArray[pairIndex] = m_valueArray[lastPairIndex];
+               m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
+
+               // Insert the last pair into the hash table
+               m_next[pairIndex] = m_hashTable[lastHash];
+               m_hashTable[lastHash] = pairIndex;
+
+               m_valueArray.pop_back();
+               m_keyArray.pop_back();
+       }
+
+       int size() const
+       {
+               return m_valueArray.size();
+       }
+
+       const Value* getAtIndex(int index) const
+       {
+               b3Assert(index < m_valueArray.size());
+
+               return &m_valueArray[index];
+       }
+
+       Value* getAtIndex(int index)
+       {
+               b3Assert(index < m_valueArray.size());
+
+               return &m_valueArray[index];
+       }
+
+       Key getKeyAtIndex(int index)
+       {
+               b3Assert(index < m_keyArray.size());
+               return m_keyArray[index];
+       }
+
+       const Key getKeyAtIndex(int index) const
+       {
+               b3Assert(index < m_keyArray.size());
+               return m_keyArray[index];
+       }
+
+       Value* operator[](const Key& key)
+       {
+               return find(key);
+       }
+
+       const Value* find(const Key& key) const
+       {
+               int index = findIndex(key);
+               if (index == B3_HASH_NULL)
+               {
+                       return NULL;
+               }
+               return &m_valueArray[index];
+       }
+
+       Value* find(const Key& key)
+       {
+               int index = findIndex(key);
+               if (index == B3_HASH_NULL)
+               {
+                       return NULL;
+               }
+               return &m_valueArray[index];
+       }
+
+       int findIndex(const Key& key) const
+       {
+               unsigned int hash = key.getHash() & (m_valueArray.capacity() - 1);
+
+               if (hash >= (unsigned int)m_hashTable.size())
+               {
+                       return B3_HASH_NULL;
+               }
+
+               int index = m_hashTable[hash];
+               while ((index != B3_HASH_NULL) && key.equals(m_keyArray[index]) == false)
+               {
+                       index = m_next[index];
+               }
+               return index;
+       }
+
+       void clear()
+       {
+               m_hashTable.clear();
+               m_next.clear();
+               m_valueArray.clear();
+               m_keyArray.clear();
+       }
+};
+
+#endif  //B3_HASH_MAP_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3Logging.cpp b/dali-physics/third-party/bullet3/src/Bullet3Common/b3Logging.cpp
new file mode 100644 (file)
index 0000000..9c9f7c0
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#include "b3Logging.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif  //_WIN32
+
+void b3PrintfFuncDefault(const char* msg)
+{
+#ifdef _WIN32
+       OutputDebugStringA(msg);
+#endif
+       printf("%s", msg);
+       //is this portable?
+       fflush(stdout);
+}
+
+void b3WarningMessageFuncDefault(const char* msg)
+{
+#ifdef _WIN32
+       OutputDebugStringA(msg);
+#endif
+       printf("%s", msg);
+       //is this portable?
+       fflush(stdout);
+}
+
+void b3ErrorMessageFuncDefault(const char* msg)
+{
+#ifdef _WIN32
+       OutputDebugStringA(msg);
+#endif
+       printf("%s", msg);
+
+       //is this portable?
+       fflush(stdout);
+}
+
+static b3PrintfFunc* b3s_printfFunc = b3PrintfFuncDefault;
+static b3WarningMessageFunc* b3s_warningMessageFunc = b3WarningMessageFuncDefault;
+static b3ErrorMessageFunc* b3s_errorMessageFunc = b3ErrorMessageFuncDefault;
+
+///The developer can route b3Printf output using their own implementation
+void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc)
+{
+       b3s_printfFunc = printfFunc;
+}
+void b3SetCustomWarningMessageFunc(b3PrintfFunc* warningMessageFunc)
+{
+       b3s_warningMessageFunc = warningMessageFunc;
+}
+void b3SetCustomErrorMessageFunc(b3PrintfFunc* errorMessageFunc)
+{
+       b3s_errorMessageFunc = errorMessageFunc;
+}
+
+//#define B3_MAX_DEBUG_STRING_LENGTH 2048
+#define B3_MAX_DEBUG_STRING_LENGTH 32768
+
+void b3OutputPrintfVarArgsInternal(const char* str, ...)
+{
+       char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0};
+       va_list argList;
+       va_start(argList, str);
+#ifdef _MSC_VER
+       vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
+#else
+       vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
+#endif
+       (b3s_printfFunc)(strDebug);
+       va_end(argList);
+}
+void b3OutputWarningMessageVarArgsInternal(const char* str, ...)
+{
+       char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0};
+       va_list argList;
+       va_start(argList, str);
+#ifdef _MSC_VER
+       vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
+#else
+       vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
+#endif
+       (b3s_warningMessageFunc)(strDebug);
+       va_end(argList);
+}
+void b3OutputErrorMessageVarArgsInternal(const char* str, ...)
+{
+       char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0};
+       va_list argList;
+       va_start(argList, str);
+#ifdef _MSC_VER
+       vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
+#else
+       vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
+#endif
+       (b3s_errorMessageFunc)(strDebug);
+       va_end(argList);
+}
+
+void b3EnterProfileZoneDefault(const char* name)
+{
+}
+void b3LeaveProfileZoneDefault()
+{
+}
+static b3EnterProfileZoneFunc* b3s_enterFunc = b3EnterProfileZoneDefault;
+static b3LeaveProfileZoneFunc* b3s_leaveFunc = b3LeaveProfileZoneDefault;
+void b3EnterProfileZone(const char* name)
+{
+       (b3s_enterFunc)(name);
+}
+void b3LeaveProfileZone()
+{
+       (b3s_leaveFunc)();
+}
+
+void b3SetCustomEnterProfileZoneFunc(b3EnterProfileZoneFunc* enterFunc)
+{
+       b3s_enterFunc = enterFunc;
+}
+void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc)
+{
+       b3s_leaveFunc = leaveFunc;
+}
+
+#ifndef _MSC_VER
+#undef vsprintf_s
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3Logging.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3Logging.h
new file mode 100644 (file)
index 0000000..f61149d
--- /dev/null
@@ -0,0 +1,74 @@
+
+#ifndef B3_LOGGING_H
+#define B3_LOGGING_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+///We add the do/while so that the statement "if (condition) b3Printf("test"); else {...}" would fail
+///You can also customize the message by uncommenting out a different line below
+#define b3Printf(...) b3OutputPrintfVarArgsInternal(__VA_ARGS__)
+       //#define b3Printf(...) do {b3OutputPrintfVarArgsInternal("b3Printf[%s,%d]:",__FILE__,__LINE__);b3OutputPrintfVarArgsInternal(__VA_ARGS__); } while(0)
+       //#define b3Printf b3OutputPrintfVarArgsInternal
+       //#define b3Printf(...) printf(__VA_ARGS__)
+       //#define b3Printf(...)
+#define b3Warning(...) do{     b3OutputWarningMessageVarArgsInternal("b3Warning[%s,%d]:\n", __FILE__, __LINE__);b3OutputWarningMessageVarArgsInternal(__VA_ARGS__);} while (0)
+#define b3Error(...)do {b3OutputErrorMessageVarArgsInternal("b3Error[%s,%d]:\n", __FILE__, __LINE__);b3OutputErrorMessageVarArgsInternal(__VA_ARGS__);} while (0)
+#ifndef B3_NO_PROFILE
+
+       void b3EnterProfileZone(const char* name);
+       void b3LeaveProfileZone();
+#ifdef __cplusplus
+
+       class b3ProfileZone
+       {
+       public:
+               b3ProfileZone(const char* name)
+               {
+                       b3EnterProfileZone(name);
+               }
+
+               ~b3ProfileZone()
+               {
+                       b3LeaveProfileZone();
+               }
+       };
+
+#define B3_PROFILE(name) b3ProfileZone __profile(name)
+#endif
+
+#else  //B3_NO_PROFILE
+
+#define B3_PROFILE(name)
+#define b3StartProfile(a)
+#define b3StopProfile
+
+#endif  //#ifndef B3_NO_PROFILE
+
+       typedef void(b3PrintfFunc)(const char* msg);
+       typedef void(b3WarningMessageFunc)(const char* msg);
+       typedef void(b3ErrorMessageFunc)(const char* msg);
+       typedef void(b3EnterProfileZoneFunc)(const char* msg);
+       typedef void(b3LeaveProfileZoneFunc)();
+
+       ///The developer can route b3Printf output using their own implementation
+       void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc);
+       void b3SetCustomWarningMessageFunc(b3WarningMessageFunc* warningMsgFunc);
+       void b3SetCustomErrorMessageFunc(b3ErrorMessageFunc* errorMsgFunc);
+
+       ///Set custom profile zone functions (zones can be nested)
+       void b3SetCustomEnterProfileZoneFunc(b3EnterProfileZoneFunc* enterFunc);
+       void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc);
+
+       ///Don't use those internal functions directly, use the b3Printf or b3SetCustomPrintfFunc instead (or warning/error version)
+       void b3OutputPrintfVarArgsInternal(const char* str, ...);
+       void b3OutputWarningMessageVarArgsInternal(const char* str, ...);
+       void b3OutputErrorMessageVarArgsInternal(const char* str, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  //B3_LOGGING_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3Matrix3x3.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3Matrix3x3.h
new file mode 100644 (file)
index 0000000..6c46536
--- /dev/null
@@ -0,0 +1,1354 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_MATRIX3x3_H
+#define B3_MATRIX3x3_H
+
+#include "b3Vector3.h"
+#include "b3Quaternion.h"
+#include <stdio.h>
+
+#ifdef B3_USE_SSE
+//const __m128 B3_ATTRIBUTE_ALIGNED16(b3v2220) = {2.0f, 2.0f, 2.0f, 0.0f};
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3vMPPP) = {-0.0f, +0.0f, +0.0f, +0.0f};
+#endif
+
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
+const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
+const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
+#endif
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define b3Matrix3x3Data b3Matrix3x3DoubleData
+#else
+#define b3Matrix3x3Data b3Matrix3x3FloatData
+#endif  //B3_USE_DOUBLE_PRECISION
+
+/**@brief The b3Matrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with b3Quaternion, b3Transform and b3Vector3.
+* Make sure to only include a pure orthogonal matrix without scaling. */
+B3_ATTRIBUTE_ALIGNED16(class)
+b3Matrix3x3
+{
+       ///Data storage for the matrix, each vector is a row of the matrix
+       b3Vector3 m_el[3];
+
+public:
+       /** @brief No initializaion constructor */
+       b3Matrix3x3() {}
+
+       //              explicit b3Matrix3x3(const b3Scalar *m) { setFromOpenGLSubMatrix(m); }
+
+       /**@brief Constructor from Quaternion */
+       explicit b3Matrix3x3(const b3Quaternion& q) { setRotation(q); }
+       /*
+       template <typename b3Scalar>
+       Matrix3x3(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
+       { 
+       setEulerYPR(yaw, pitch, roll);
+       }
+       */
+       /** @brief Constructor with row major formatting */
+       b3Matrix3x3(const b3Scalar& xx, const b3Scalar& xy, const b3Scalar& xz,
+                               const b3Scalar& yx, const b3Scalar& yy, const b3Scalar& yz,
+                               const b3Scalar& zx, const b3Scalar& zy, const b3Scalar& zz)
+       {
+               setValue(xx, xy, xz,
+                                yx, yy, yz,
+                                zx, zy, zz);
+       }
+
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+       B3_FORCE_INLINE b3Matrix3x3(const b3SimdFloat4 v0, const b3SimdFloat4 v1, const b3SimdFloat4 v2)
+       {
+               m_el[0].mVec128 = v0;
+               m_el[1].mVec128 = v1;
+               m_el[2].mVec128 = v2;
+       }
+
+       B3_FORCE_INLINE b3Matrix3x3(const b3Vector3& v0, const b3Vector3& v1, const b3Vector3& v2)
+       {
+               m_el[0] = v0;
+               m_el[1] = v1;
+               m_el[2] = v2;
+       }
+
+       // Copy constructor
+       B3_FORCE_INLINE b3Matrix3x3(const b3Matrix3x3& rhs)
+       {
+               m_el[0].mVec128 = rhs.m_el[0].mVec128;
+               m_el[1].mVec128 = rhs.m_el[1].mVec128;
+               m_el[2].mVec128 = rhs.m_el[2].mVec128;
+       }
+
+       // Assignment Operator
+       B3_FORCE_INLINE b3Matrix3x3& operator=(const b3Matrix3x3& m)
+       {
+               m_el[0].mVec128 = m.m_el[0].mVec128;
+               m_el[1].mVec128 = m.m_el[1].mVec128;
+               m_el[2].mVec128 = m.m_el[2].mVec128;
+
+               return *this;
+       }
+
+#else
+
+       /** @brief Copy constructor */
+       B3_FORCE_INLINE b3Matrix3x3(const b3Matrix3x3& other)
+       {
+               m_el[0] = other.m_el[0];
+               m_el[1] = other.m_el[1];
+               m_el[2] = other.m_el[2];
+       }
+
+       /** @brief Assignment Operator */
+       B3_FORCE_INLINE b3Matrix3x3& operator=(const b3Matrix3x3& other)
+       {
+               m_el[0] = other.m_el[0];
+               m_el[1] = other.m_el[1];
+               m_el[2] = other.m_el[2];
+               return *this;
+       }
+
+#endif
+
+       /** @brief Get a column of the matrix as a vector 
+       *  @param i Column number 0 indexed */
+       B3_FORCE_INLINE b3Vector3 getColumn(int i) const
+       {
+               return b3MakeVector3(m_el[0][i], m_el[1][i], m_el[2][i]);
+       }
+
+       /** @brief Get a row of the matrix as a vector 
+       *  @param i Row number 0 indexed */
+       B3_FORCE_INLINE const b3Vector3& getRow(int i) const
+       {
+               b3FullAssert(0 <= i && i < 3);
+               return m_el[i];
+       }
+
+       /** @brief Get a mutable reference to a row of the matrix as a vector 
+       *  @param i Row number 0 indexed */
+       B3_FORCE_INLINE b3Vector3& operator[](int i)
+       {
+               b3FullAssert(0 <= i && i < 3);
+               return m_el[i];
+       }
+
+       /** @brief Get a const reference to a row of the matrix as a vector 
+       *  @param i Row number 0 indexed */
+       B3_FORCE_INLINE const b3Vector3& operator[](int i) const
+       {
+               b3FullAssert(0 <= i && i < 3);
+               return m_el[i];
+       }
+
+       /** @brief Multiply by the target matrix on the right
+       *  @param m Rotation matrix to be applied 
+       * Equivilant to this = this * m */
+       b3Matrix3x3& operator*=(const b3Matrix3x3& m);
+
+       /** @brief Adds by the target matrix on the right
+       *  @param m matrix to be applied 
+       * Equivilant to this = this + m */
+       b3Matrix3x3& operator+=(const b3Matrix3x3& m);
+
+       /** @brief Substractss by the target matrix on the right
+       *  @param m matrix to be applied 
+       * Equivilant to this = this - m */
+       b3Matrix3x3& operator-=(const b3Matrix3x3& m);
+
+       /** @brief Set from the rotational part of a 4x4 OpenGL matrix
+       *  @param m A pointer to the beginning of the array of scalars*/
+       void setFromOpenGLSubMatrix(const b3Scalar* m)
+       {
+               m_el[0].setValue(m[0], m[4], m[8]);
+               m_el[1].setValue(m[1], m[5], m[9]);
+               m_el[2].setValue(m[2], m[6], m[10]);
+       }
+       /** @brief Set the values of the matrix explicitly (row major)
+       *  @param xx Top left
+       *  @param xy Top Middle
+       *  @param xz Top Right
+       *  @param yx Middle Left
+       *  @param yy Middle Middle
+       *  @param yz Middle Right
+       *  @param zx Bottom Left
+       *  @param zy Bottom Middle
+       *  @param zz Bottom Right*/
+       void setValue(const b3Scalar& xx, const b3Scalar& xy, const b3Scalar& xz,
+                                 const b3Scalar& yx, const b3Scalar& yy, const b3Scalar& yz,
+                                 const b3Scalar& zx, const b3Scalar& zy, const b3Scalar& zz)
+       {
+               m_el[0].setValue(xx, xy, xz);
+               m_el[1].setValue(yx, yy, yz);
+               m_el[2].setValue(zx, zy, zz);
+       }
+
+       /** @brief Set the matrix from a quaternion
+       *  @param q The Quaternion to match */
+       void setRotation(const b3Quaternion& q)
+       {
+               b3Scalar d = q.length2();
+               b3FullAssert(d != b3Scalar(0.0));
+               b3Scalar s = b3Scalar(2.0) / d;
+
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 vs, Q = q.get128();
+               __m128i Qi = b3CastfTo128i(Q);
+               __m128 Y, Z;
+               __m128 V1, V2, V3;
+               __m128 V11, V21, V31;
+               __m128 NQ = _mm_xor_ps(Q, b3vMzeroMask);
+               __m128i NQi = b3CastfTo128i(NQ);
+
+               V1 = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(1, 0, 2, 3)));  // Y X Z W
+               V2 = _mm_shuffle_ps(NQ, Q, B3_SHUFFLE(0, 0, 1, 3));                 // -X -X  Y  W
+               V3 = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(2, 1, 0, 3)));  // Z Y X W
+               V1 = _mm_xor_ps(V1, b3vMPPP);                                       //  change the sign of the first element
+
+               V11 = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(1, 1, 0, 3)));  // Y Y X W
+               V21 = _mm_unpackhi_ps(Q, Q);                                         //  Z  Z  W  W
+               V31 = _mm_shuffle_ps(Q, NQ, B3_SHUFFLE(0, 2, 0, 3));                 //  X  Z -X -W
+
+               V2 = V2 * V1;   //
+               V1 = V1 * V11;  //
+               V3 = V3 * V31;  //
+
+               V11 = _mm_shuffle_ps(NQ, Q, B3_SHUFFLE(2, 3, 1, 3));                //  -Z -W  Y  W
+               V11 = V11 * V21;                                                    //
+               V21 = _mm_xor_ps(V21, b3vMPPP);                                     //  change the sign of the first element
+               V31 = _mm_shuffle_ps(Q, NQ, B3_SHUFFLE(3, 3, 1, 3));                //   W  W -Y -W
+               V31 = _mm_xor_ps(V31, b3vMPPP);                                     //  change the sign of the first element
+               Y = b3CastiTo128f(_mm_shuffle_epi32(NQi, B3_SHUFFLE(3, 2, 0, 3)));  // -W -Z -X -W
+               Z = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(1, 0, 1, 3)));   //  Y  X  Y  W
+
+               vs = _mm_load_ss(&s);
+               V21 = V21 * Y;
+               V31 = V31 * Z;
+
+               V1 = V1 + V11;
+               V2 = V2 + V21;
+               V3 = V3 + V31;
+
+               vs = b3_splat3_ps(vs, 0);
+               //      s ready
+               V1 = V1 * vs;
+               V2 = V2 * vs;
+               V3 = V3 * vs;
+
+               V1 = V1 + b3v1000;
+               V2 = V2 + b3v0100;
+               V3 = V3 + b3v0010;
+
+               m_el[0] = b3MakeVector3(V1);
+               m_el[1] = b3MakeVector3(V2);
+               m_el[2] = b3MakeVector3(V3);
+#else
+               b3Scalar xs = q.getX() * s, ys = q.getY() * s, zs = q.getZ() * s;
+               b3Scalar wx = q.getW() * xs, wy = q.getW() * ys, wz = q.getW() * zs;
+               b3Scalar xx = q.getX() * xs, xy = q.getX() * ys, xz = q.getX() * zs;
+               b3Scalar yy = q.getY() * ys, yz = q.getY() * zs, zz = q.getZ() * zs;
+               setValue(
+                       b3Scalar(1.0) - (yy + zz), xy - wz, xz + wy,
+                       xy + wz, b3Scalar(1.0) - (xx + zz), yz - wx,
+                       xz - wy, yz + wx, b3Scalar(1.0) - (xx + yy));
+#endif
+       }
+
+       /** @brief Set the matrix from euler angles using YPR around YXZ respectively
+       *  @param yaw Yaw about Y axis
+       *  @param pitch Pitch about X axis
+       *  @param roll Roll about Z axis 
+       */
+       void setEulerYPR(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
+       {
+               setEulerZYX(roll, pitch, yaw);
+       }
+
+       /** @brief Set the matrix from euler angles YPR around ZYX axes
+       * @param eulerX Roll about X axis
+       * @param eulerY Pitch around Y axis
+       * @param eulerZ Yaw aboud Z axis
+       * 
+       * These angles are used to produce a rotation matrix. The euler
+       * angles are applied in ZYX order. I.e a vector is first rotated 
+       * about X then Y and then Z
+       **/
+       void setEulerZYX(b3Scalar eulerX, b3Scalar eulerY, b3Scalar eulerZ)
+       {
+               ///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
+               b3Scalar ci(b3Cos(eulerX));
+               b3Scalar cj(b3Cos(eulerY));
+               b3Scalar ch(b3Cos(eulerZ));
+               b3Scalar si(b3Sin(eulerX));
+               b3Scalar sj(b3Sin(eulerY));
+               b3Scalar sh(b3Sin(eulerZ));
+               b3Scalar cc = ci * ch;
+               b3Scalar cs = ci * sh;
+               b3Scalar sc = si * ch;
+               b3Scalar ss = si * sh;
+
+               setValue(cj * ch, sj * sc - cs, sj * cc + ss,
+                                cj * sh, sj * ss + cc, sj * cs - sc,
+                                -sj, cj * si, cj * ci);
+       }
+
+       /**@brief Set the matrix to the identity */
+       void setIdentity()
+       {
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+               m_el[0] = b3MakeVector3(b3v1000);
+               m_el[1] = b3MakeVector3(b3v0100);
+               m_el[2] = b3MakeVector3(b3v0010);
+#else
+               setValue(b3Scalar(1.0), b3Scalar(0.0), b3Scalar(0.0),
+                                b3Scalar(0.0), b3Scalar(1.0), b3Scalar(0.0),
+                                b3Scalar(0.0), b3Scalar(0.0), b3Scalar(1.0));
+#endif
+       }
+
+       static const b3Matrix3x3& getIdentity()
+       {
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+               static const b3Matrix3x3
+                       identityMatrix(b3v1000, b3v0100, b3v0010);
+#else
+               static const b3Matrix3x3
+                       identityMatrix(
+                               b3Scalar(1.0), b3Scalar(0.0), b3Scalar(0.0),
+                               b3Scalar(0.0), b3Scalar(1.0), b3Scalar(0.0),
+                               b3Scalar(0.0), b3Scalar(0.0), b3Scalar(1.0));
+#endif
+               return identityMatrix;
+       }
+
+       /**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective
+       * @param m The array to be filled */
+       void getOpenGLSubMatrix(b3Scalar * m) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 v0 = m_el[0].mVec128;
+               __m128 v1 = m_el[1].mVec128;
+               __m128 v2 = m_el[2].mVec128;  //  x2 y2 z2 w2
+               __m128* vm = (__m128*)m;
+               __m128 vT;
+
+               v2 = _mm_and_ps(v2, b3vFFF0fMask);  //  x2 y2 z2 0
+
+               vT = _mm_unpackhi_ps(v0, v1);  //       z0 z1 * *
+               v0 = _mm_unpacklo_ps(v0, v1);  //       x0 x1 y0 y1
+
+               v1 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(2, 3, 1, 3));                    // y0 y1 y2 0
+               v0 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(0, 1, 0, 3));                    // x0 x1 x2 0
+               v2 = b3CastdTo128f(_mm_move_sd(b3CastfTo128d(v2), b3CastfTo128d(vT)));  // z0 z1 z2 0
+
+               vm[0] = v0;
+               vm[1] = v1;
+               vm[2] = v2;
+#elif defined(B3_USE_NEON)
+               // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+               static const uint32x2_t zMask = (const uint32x2_t){-1, 0};
+               float32x4_t* vm = (float32x4_t*)m;
+               float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128);               // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+               float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f));  // {x2  0 }, {y2 0}
+               float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
+               float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
+               float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
+               float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q);  // z0 z1 z2  0
+
+               vm[0] = v0;
+               vm[1] = v1;
+               vm[2] = v2;
+#else
+               m[0] = b3Scalar(m_el[0].getX());
+               m[1] = b3Scalar(m_el[1].getX());
+               m[2] = b3Scalar(m_el[2].getX());
+               m[3] = b3Scalar(0.0);
+               m[4] = b3Scalar(m_el[0].getY());
+               m[5] = b3Scalar(m_el[1].getY());
+               m[6] = b3Scalar(m_el[2].getY());
+               m[7] = b3Scalar(0.0);
+               m[8] = b3Scalar(m_el[0].getZ());
+               m[9] = b3Scalar(m_el[1].getZ());
+               m[10] = b3Scalar(m_el[2].getZ());
+               m[11] = b3Scalar(0.0);
+#endif
+       }
+
+       /**@brief Get the matrix represented as a quaternion 
+       * @param q The quaternion which will be set */
+       void getRotation(b3Quaternion & q) const
+       {
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+               b3Scalar trace = m_el[0].getX() + m_el[1].getY() + m_el[2].getZ();
+               b3Scalar s, x;
+
+               union {
+                       b3SimdFloat4 vec;
+                       b3Scalar f[4];
+               } temp;
+
+               if (trace > b3Scalar(0.0))
+               {
+                       x = trace + b3Scalar(1.0);
+
+                       temp.f[0] = m_el[2].getY() - m_el[1].getZ();
+                       temp.f[1] = m_el[0].getZ() - m_el[2].getX();
+                       temp.f[2] = m_el[1].getX() - m_el[0].getY();
+                       temp.f[3] = x;
+                       //temp.f[3]= s * b3Scalar(0.5);
+               }
+               else
+               {
+                       int i, j, k;
+                       if (m_el[0].getX() < m_el[1].getY())
+                       {
+                               if (m_el[1].getY() < m_el[2].getZ())
+                               {
+                                       i = 2;
+                                       j = 0;
+                                       k = 1;
+                               }
+                               else
+                               {
+                                       i = 1;
+                                       j = 2;
+                                       k = 0;
+                               }
+                       }
+                       else
+                       {
+                               if (m_el[0].getX() < m_el[2].getZ())
+                               {
+                                       i = 2;
+                                       j = 0;
+                                       k = 1;
+                               }
+                               else
+                               {
+                                       i = 0;
+                                       j = 1;
+                                       k = 2;
+                               }
+                       }
+
+                       x = m_el[i][i] - m_el[j][j] - m_el[k][k] + b3Scalar(1.0);
+
+                       temp.f[3] = (m_el[k][j] - m_el[j][k]);
+                       temp.f[j] = (m_el[j][i] + m_el[i][j]);
+                       temp.f[k] = (m_el[k][i] + m_el[i][k]);
+                       temp.f[i] = x;
+                       //temp.f[i] = s * b3Scalar(0.5);
+               }
+
+               s = b3Sqrt(x);
+               q.set128(temp.vec);
+               s = b3Scalar(0.5) / s;
+
+               q *= s;
+#else
+               b3Scalar trace = m_el[0].getX() + m_el[1].getY() + m_el[2].getZ();
+
+               b3Scalar temp[4];
+
+               if (trace > b3Scalar(0.0))
+               {
+                       b3Scalar s = b3Sqrt(trace + b3Scalar(1.0));
+                       temp[3] = (s * b3Scalar(0.5));
+                       s = b3Scalar(0.5) / s;
+
+                       temp[0] = ((m_el[2].getY() - m_el[1].getZ()) * s);
+                       temp[1] = ((m_el[0].getZ() - m_el[2].getX()) * s);
+                       temp[2] = ((m_el[1].getX() - m_el[0].getY()) * s);
+               }
+               else
+               {
+                       int i = m_el[0].getX() < m_el[1].getY() ? (m_el[1].getY() < m_el[2].getZ() ? 2 : 1) : (m_el[0].getX() < m_el[2].getZ() ? 2 : 0);
+                       int j = (i + 1) % 3;
+                       int k = (i + 2) % 3;
+
+                       b3Scalar s = b3Sqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + b3Scalar(1.0));
+                       temp[i] = s * b3Scalar(0.5);
+                       s = b3Scalar(0.5) / s;
+
+                       temp[3] = (m_el[k][j] - m_el[j][k]) * s;
+                       temp[j] = (m_el[j][i] + m_el[i][j]) * s;
+                       temp[k] = (m_el[k][i] + m_el[i][k]) * s;
+               }
+               q.setValue(temp[0], temp[1], temp[2], temp[3]);
+#endif
+       }
+
+       /**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
+       * @param yaw Yaw around Y axis
+       * @param pitch Pitch around X axis
+       * @param roll around Z axis */
+       void getEulerYPR(b3Scalar & yaw, b3Scalar & pitch, b3Scalar & roll) const
+       {
+               // first use the normal calculus
+               yaw = b3Scalar(b3Atan2(m_el[1].getX(), m_el[0].getX()));
+               pitch = b3Scalar(b3Asin(-m_el[2].getX()));
+               roll = b3Scalar(b3Atan2(m_el[2].getY(), m_el[2].getZ()));
+
+               // on pitch = +/-HalfPI
+               if (b3Fabs(pitch) == B3_HALF_PI)
+               {
+                       if (yaw > 0)
+                               yaw -= B3_PI;
+                       else
+                               yaw += B3_PI;
+
+                       if (roll > 0)
+                               roll -= B3_PI;
+                       else
+                               roll += B3_PI;
+               }
+       };
+
+       /**@brief Get the matrix represented as euler angles around ZYX
+       * @param yaw Yaw around X axis
+       * @param pitch Pitch around Y axis
+       * @param roll around X axis 
+       * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
+       void getEulerZYX(b3Scalar & yaw, b3Scalar & pitch, b3Scalar & roll, unsigned int solution_number = 1) const
+       {
+               struct Euler
+               {
+                       b3Scalar yaw;
+                       b3Scalar pitch;
+                       b3Scalar roll;
+               };
+
+               Euler euler_out;
+               Euler euler_out2;  //second solution
+               //get the pointer to the raw data
+
+               // Check that pitch is not at a singularity
+               if (b3Fabs(m_el[2].getX()) >= 1)
+               {
+                       euler_out.yaw = 0;
+                       euler_out2.yaw = 0;
+
+                       // From difference of angles formula
+                       b3Scalar delta = b3Atan2(m_el[0].getX(), m_el[0].getZ());
+                       if (m_el[2].getX() > 0)  //gimbal locked up
+                       {
+                               euler_out.pitch = B3_PI / b3Scalar(2.0);
+                               euler_out2.pitch = B3_PI / b3Scalar(2.0);
+                               euler_out.roll = euler_out.pitch + delta;
+                               euler_out2.roll = euler_out.pitch + delta;
+                       }
+                       else  // gimbal locked down
+                       {
+                               euler_out.pitch = -B3_PI / b3Scalar(2.0);
+                               euler_out2.pitch = -B3_PI / b3Scalar(2.0);
+                               euler_out.roll = -euler_out.pitch + delta;
+                               euler_out2.roll = -euler_out.pitch + delta;
+                       }
+               }
+               else
+               {
+                       euler_out.pitch = -b3Asin(m_el[2].getX());
+                       euler_out2.pitch = B3_PI - euler_out.pitch;
+
+                       euler_out.roll = b3Atan2(m_el[2].getY() / b3Cos(euler_out.pitch),
+                                                                        m_el[2].getZ() / b3Cos(euler_out.pitch));
+                       euler_out2.roll = b3Atan2(m_el[2].getY() / b3Cos(euler_out2.pitch),
+                                                                         m_el[2].getZ() / b3Cos(euler_out2.pitch));
+
+                       euler_out.yaw = b3Atan2(m_el[1].getX() / b3Cos(euler_out.pitch),
+                                                                       m_el[0].getX() / b3Cos(euler_out.pitch));
+                       euler_out2.yaw = b3Atan2(m_el[1].getX() / b3Cos(euler_out2.pitch),
+                                                                        m_el[0].getX() / b3Cos(euler_out2.pitch));
+               }
+
+               if (solution_number == 1)
+               {
+                       yaw = euler_out.yaw;
+                       pitch = euler_out.pitch;
+                       roll = euler_out.roll;
+               }
+               else
+               {
+                       yaw = euler_out2.yaw;
+                       pitch = euler_out2.pitch;
+                       roll = euler_out2.roll;
+               }
+       }
+
+       /**@brief Create a scaled copy of the matrix 
+       * @param s Scaling vector The elements of the vector will scale each column */
+
+       b3Matrix3x3 scaled(const b3Vector3& s) const
+       {
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+               return b3Matrix3x3(m_el[0] * s, m_el[1] * s, m_el[2] * s);
+#else
+               return b3Matrix3x3(
+                       m_el[0].getX() * s.getX(), m_el[0].getY() * s.getY(), m_el[0].getZ() * s.getZ(),
+                       m_el[1].getX() * s.getX(), m_el[1].getY() * s.getY(), m_el[1].getZ() * s.getZ(),
+                       m_el[2].getX() * s.getX(), m_el[2].getY() * s.getY(), m_el[2].getZ() * s.getZ());
+#endif
+       }
+
+       /**@brief Return the determinant of the matrix */
+       b3Scalar determinant() const;
+       /**@brief Return the adjoint of the matrix */
+       b3Matrix3x3 adjoint() const;
+       /**@brief Return the matrix with all values non negative */
+       b3Matrix3x3 absolute() const;
+       /**@brief Return the transpose of the matrix */
+       b3Matrix3x3 transpose() const;
+       /**@brief Return the inverse of the matrix */
+       b3Matrix3x3 inverse() const;
+
+       b3Matrix3x3 transposeTimes(const b3Matrix3x3& m) const;
+       b3Matrix3x3 timesTranspose(const b3Matrix3x3& m) const;
+
+       B3_FORCE_INLINE b3Scalar tdotx(const b3Vector3& v) const
+       {
+               return m_el[0].getX() * v.getX() + m_el[1].getX() * v.getY() + m_el[2].getX() * v.getZ();
+       }
+       B3_FORCE_INLINE b3Scalar tdoty(const b3Vector3& v) const
+       {
+               return m_el[0].getY() * v.getX() + m_el[1].getY() * v.getY() + m_el[2].getY() * v.getZ();
+       }
+       B3_FORCE_INLINE b3Scalar tdotz(const b3Vector3& v) const
+       {
+               return m_el[0].getZ() * v.getX() + m_el[1].getZ() * v.getY() + m_el[2].getZ() * v.getZ();
+       }
+
+       /**@brief diagonalizes this matrix by the Jacobi method.
+       * @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
+       * coordinate system, i.e., old_this = rot * new_this * rot^T. 
+       * @param threshold See iteration
+       * @param iteration The iteration stops when all off-diagonal elements are less than the threshold multiplied 
+       * by the sum of the absolute values of the diagonal, or when maxSteps have been executed. 
+       * 
+       * Note that this matrix is assumed to be symmetric. 
+       */
+       void diagonalize(b3Matrix3x3 & rot, b3Scalar threshold, int maxSteps)
+       {
+               rot.setIdentity();
+               for (int step = maxSteps; step > 0; step--)
+               {
+                       // find off-diagonal element [p][q] with largest magnitude
+                       int p = 0;
+                       int q = 1;
+                       int r = 2;
+                       b3Scalar max = b3Fabs(m_el[0][1]);
+                       b3Scalar v = b3Fabs(m_el[0][2]);
+                       if (v > max)
+                       {
+                               q = 2;
+                               r = 1;
+                               max = v;
+                       }
+                       v = b3Fabs(m_el[1][2]);
+                       if (v > max)
+                       {
+                               p = 1;
+                               q = 2;
+                               r = 0;
+                               max = v;
+                       }
+
+                       b3Scalar t = threshold * (b3Fabs(m_el[0][0]) + b3Fabs(m_el[1][1]) + b3Fabs(m_el[2][2]));
+                       if (max <= t)
+                       {
+                               if (max <= B3_EPSILON * t)
+                               {
+                                       return;
+                               }
+                               step = 1;
+                       }
+
+                       // compute Jacobi rotation J which leads to a zero for element [p][q]
+                       b3Scalar mpq = m_el[p][q];
+                       b3Scalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
+                       b3Scalar theta2 = theta * theta;
+                       b3Scalar cos;
+                       b3Scalar sin;
+                       if (theta2 * theta2 < b3Scalar(10 / B3_EPSILON))
+                       {
+                               t = (theta >= 0) ? 1 / (theta + b3Sqrt(1 + theta2))
+                                                                : 1 / (theta - b3Sqrt(1 + theta2));
+                               cos = 1 / b3Sqrt(1 + t * t);
+                               sin = cos * t;
+                       }
+                       else
+                       {
+                               // approximation for large theta-value, i.e., a nearly diagonal matrix
+                               t = 1 / (theta * (2 + b3Scalar(0.5) / theta2));
+                               cos = 1 - b3Scalar(0.5) * t * t;
+                               sin = cos * t;
+                       }
+
+                       // apply rotation to matrix (this = J^T * this * J)
+                       m_el[p][q] = m_el[q][p] = 0;
+                       m_el[p][p] -= t * mpq;
+                       m_el[q][q] += t * mpq;
+                       b3Scalar mrp = m_el[r][p];
+                       b3Scalar mrq = m_el[r][q];
+                       m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq;
+                       m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp;
+
+                       // apply rotation to rot (rot = rot * J)
+                       for (int i = 0; i < 3; i++)
+                       {
+                               b3Vector3& row = rot[i];
+                               mrp = row[p];
+                               mrq = row[q];
+                               row[p] = cos * mrp - sin * mrq;
+                               row[q] = cos * mrq + sin * mrp;
+                       }
+               }
+       }
+
+       /**@brief Calculate the matrix cofactor 
+       * @param r1 The first row to use for calculating the cofactor
+       * @param c1 The first column to use for calculating the cofactor
+       * @param r1 The second row to use for calculating the cofactor
+       * @param c1 The second column to use for calculating the cofactor
+       * See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
+       */
+       b3Scalar cofac(int r1, int c1, int r2, int c2) const
+       {
+               return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
+       }
+
+       void serialize(struct b3Matrix3x3Data & dataOut) const;
+
+       void serializeFloat(struct b3Matrix3x3FloatData & dataOut) const;
+
+       void deSerialize(const struct b3Matrix3x3Data& dataIn);
+
+       void deSerializeFloat(const struct b3Matrix3x3FloatData& dataIn);
+
+       void deSerializeDouble(const struct b3Matrix3x3DoubleData& dataIn);
+};
+
+B3_FORCE_INLINE b3Matrix3x3&
+b3Matrix3x3::operator*=(const b3Matrix3x3& m)
+{
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+       __m128 rv00, rv01, rv02;
+       __m128 rv10, rv11, rv12;
+       __m128 rv20, rv21, rv22;
+       __m128 mv0, mv1, mv2;
+
+       rv02 = m_el[0].mVec128;
+       rv12 = m_el[1].mVec128;
+       rv22 = m_el[2].mVec128;
+
+       mv0 = _mm_and_ps(m[0].mVec128, b3vFFF0fMask);
+       mv1 = _mm_and_ps(m[1].mVec128, b3vFFF0fMask);
+       mv2 = _mm_and_ps(m[2].mVec128, b3vFFF0fMask);
+
+       // rv0
+       rv00 = b3_splat_ps(rv02, 0);
+       rv01 = b3_splat_ps(rv02, 1);
+       rv02 = b3_splat_ps(rv02, 2);
+
+       rv00 = _mm_mul_ps(rv00, mv0);
+       rv01 = _mm_mul_ps(rv01, mv1);
+       rv02 = _mm_mul_ps(rv02, mv2);
+
+       // rv1
+       rv10 = b3_splat_ps(rv12, 0);
+       rv11 = b3_splat_ps(rv12, 1);
+       rv12 = b3_splat_ps(rv12, 2);
+
+       rv10 = _mm_mul_ps(rv10, mv0);
+       rv11 = _mm_mul_ps(rv11, mv1);
+       rv12 = _mm_mul_ps(rv12, mv2);
+
+       // rv2
+       rv20 = b3_splat_ps(rv22, 0);
+       rv21 = b3_splat_ps(rv22, 1);
+       rv22 = b3_splat_ps(rv22, 2);
+
+       rv20 = _mm_mul_ps(rv20, mv0);
+       rv21 = _mm_mul_ps(rv21, mv1);
+       rv22 = _mm_mul_ps(rv22, mv2);
+
+       rv00 = _mm_add_ps(rv00, rv01);
+       rv10 = _mm_add_ps(rv10, rv11);
+       rv20 = _mm_add_ps(rv20, rv21);
+
+       m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
+       m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
+       m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
+
+#elif defined(B3_USE_NEON)
+
+       float32x4_t rv0, rv1, rv2;
+       float32x4_t v0, v1, v2;
+       float32x4_t mv0, mv1, mv2;
+
+       v0 = m_el[0].mVec128;
+       v1 = m_el[1].mVec128;
+       v2 = m_el[2].mVec128;
+
+       mv0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, b3vFFF0Mask);
+       mv1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, b3vFFF0Mask);
+       mv2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, b3vFFF0Mask);
+
+       rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+       rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+       rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+       rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+       rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+       rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+       rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+       rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+       rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+       m_el[0].mVec128 = rv0;
+       m_el[1].mVec128 = rv1;
+       m_el[2].mVec128 = rv2;
+#else
+       setValue(
+               m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
+               m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
+               m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
+#endif
+       return *this;
+}
+
+B3_FORCE_INLINE b3Matrix3x3&
+b3Matrix3x3::operator+=(const b3Matrix3x3& m)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+       m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
+       m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
+       m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
+#else
+       setValue(
+               m_el[0][0] + m.m_el[0][0],
+               m_el[0][1] + m.m_el[0][1],
+               m_el[0][2] + m.m_el[0][2],
+               m_el[1][0] + m.m_el[1][0],
+               m_el[1][1] + m.m_el[1][1],
+               m_el[1][2] + m.m_el[1][2],
+               m_el[2][0] + m.m_el[2][0],
+               m_el[2][1] + m.m_el[2][1],
+               m_el[2][2] + m.m_el[2][2]);
+#endif
+       return *this;
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+operator*(const b3Matrix3x3& m, const b3Scalar& k)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+       __m128 vk = b3_splat_ps(_mm_load_ss((float*)&k), 0x80);
+       return b3Matrix3x3(
+               _mm_mul_ps(m[0].mVec128, vk),
+               _mm_mul_ps(m[1].mVec128, vk),
+               _mm_mul_ps(m[2].mVec128, vk));
+#elif defined(B3_USE_NEON)
+       return b3Matrix3x3(
+               vmulq_n_f32(m[0].mVec128, k),
+               vmulq_n_f32(m[1].mVec128, k),
+               vmulq_n_f32(m[2].mVec128, k));
+#else
+       return b3Matrix3x3(
+               m[0].getX() * k, m[0].getY() * k, m[0].getZ() * k,
+               m[1].getX() * k, m[1].getY() * k, m[1].getZ() * k,
+               m[2].getX() * k, m[2].getY() * k, m[2].getZ() * k);
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+operator+(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+       return b3Matrix3x3(
+               m1[0].mVec128 + m2[0].mVec128,
+               m1[1].mVec128 + m2[1].mVec128,
+               m1[2].mVec128 + m2[2].mVec128);
+#else
+       return b3Matrix3x3(
+               m1[0][0] + m2[0][0],
+               m1[0][1] + m2[0][1],
+               m1[0][2] + m2[0][2],
+
+               m1[1][0] + m2[1][0],
+               m1[1][1] + m2[1][1],
+               m1[1][2] + m2[1][2],
+
+               m1[2][0] + m2[2][0],
+               m1[2][1] + m2[2][1],
+               m1[2][2] + m2[2][2]);
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+operator-(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+       return b3Matrix3x3(
+               m1[0].mVec128 - m2[0].mVec128,
+               m1[1].mVec128 - m2[1].mVec128,
+               m1[2].mVec128 - m2[2].mVec128);
+#else
+       return b3Matrix3x3(
+               m1[0][0] - m2[0][0],
+               m1[0][1] - m2[0][1],
+               m1[0][2] - m2[0][2],
+
+               m1[1][0] - m2[1][0],
+               m1[1][1] - m2[1][1],
+               m1[1][2] - m2[1][2],
+
+               m1[2][0] - m2[2][0],
+               m1[2][1] - m2[2][1],
+               m1[2][2] - m2[2][2]);
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3&
+b3Matrix3x3::operator-=(const b3Matrix3x3& m)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+       m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
+       m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
+       m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
+#else
+       setValue(
+               m_el[0][0] - m.m_el[0][0],
+               m_el[0][1] - m.m_el[0][1],
+               m_el[0][2] - m.m_el[0][2],
+               m_el[1][0] - m.m_el[1][0],
+               m_el[1][1] - m.m_el[1][1],
+               m_el[1][2] - m.m_el[1][2],
+               m_el[2][0] - m.m_el[2][0],
+               m_el[2][1] - m.m_el[2][1],
+               m_el[2][2] - m.m_el[2][2]);
+#endif
+       return *this;
+}
+
+B3_FORCE_INLINE b3Scalar
+b3Matrix3x3::determinant() const
+{
+       return b3Triple((*this)[0], (*this)[1], (*this)[2]);
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::absolute() const
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+       return b3Matrix3x3(
+               _mm_and_ps(m_el[0].mVec128, b3vAbsfMask),
+               _mm_and_ps(m_el[1].mVec128, b3vAbsfMask),
+               _mm_and_ps(m_el[2].mVec128, b3vAbsfMask));
+#elif defined(B3_USE_NEON)
+       return b3Matrix3x3(
+               (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, b3v3AbsMask),
+               (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, b3v3AbsMask),
+               (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, b3v3AbsMask));
+#else
+       return b3Matrix3x3(
+               b3Fabs(m_el[0].getX()), b3Fabs(m_el[0].getY()), b3Fabs(m_el[0].getZ()),
+               b3Fabs(m_el[1].getX()), b3Fabs(m_el[1].getY()), b3Fabs(m_el[1].getZ()),
+               b3Fabs(m_el[2].getX()), b3Fabs(m_el[2].getY()), b3Fabs(m_el[2].getZ()));
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::transpose() const
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+       __m128 v0 = m_el[0].mVec128;
+       __m128 v1 = m_el[1].mVec128;
+       __m128 v2 = m_el[2].mVec128;  //  x2 y2 z2 w2
+       __m128 vT;
+
+       v2 = _mm_and_ps(v2, b3vFFF0fMask);  //  x2 y2 z2 0
+
+       vT = _mm_unpackhi_ps(v0, v1);  //       z0 z1 * *
+       v0 = _mm_unpacklo_ps(v0, v1);  //       x0 x1 y0 y1
+
+       v1 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(2, 3, 1, 3));                    // y0 y1 y2 0
+       v0 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(0, 1, 0, 3));                    // x0 x1 x2 0
+       v2 = b3CastdTo128f(_mm_move_sd(b3CastfTo128d(v2), b3CastfTo128d(vT)));  // z0 z1 z2 0
+
+       return b3Matrix3x3(v0, v1, v2);
+#elif defined(B3_USE_NEON)
+       // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+       static const uint32x2_t zMask = (const uint32x2_t){-1, 0};
+       float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128);               // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+       float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f));  // {x2  0 }, {y2 0}
+       float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
+       float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
+       float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
+       float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q);  // z0 z1 z2  0
+       return b3Matrix3x3(v0, v1, v2);
+#else
+       return b3Matrix3x3(m_el[0].getX(), m_el[1].getX(), m_el[2].getX(),
+                                          m_el[0].getY(), m_el[1].getY(), m_el[2].getY(),
+                                          m_el[0].getZ(), m_el[1].getZ(), m_el[2].getZ());
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::adjoint() const
+{
+       return b3Matrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
+                                          cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
+                                          cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::inverse() const
+{
+       b3Vector3 co = b3MakeVector3(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
+       b3Scalar det = (*this)[0].dot(co);
+       b3FullAssert(det != b3Scalar(0.0));
+       b3Scalar s = b3Scalar(1.0) / det;
+       return b3Matrix3x3(co.getX() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
+                                          co.getY() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+                                          co.getZ() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::transposeTimes(const b3Matrix3x3& m) const
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+       // zeros w
+       //    static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
+       __m128 row = m_el[0].mVec128;
+       __m128 m0 = _mm_and_ps(m.getRow(0).mVec128, b3vFFF0fMask);
+       __m128 m1 = _mm_and_ps(m.getRow(1).mVec128, b3vFFF0fMask);
+       __m128 m2 = _mm_and_ps(m.getRow(2).mVec128, b3vFFF0fMask);
+       __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
+       __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
+       __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
+       row = m_el[1].mVec128;
+       r0 = _mm_add_ps(r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
+       r1 = _mm_add_ps(r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
+       r2 = _mm_add_ps(r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
+       row = m_el[2].mVec128;
+       r0 = _mm_add_ps(r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
+       r1 = _mm_add_ps(r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
+       r2 = _mm_add_ps(r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
+       return b3Matrix3x3(r0, r1, r2);
+
+#elif defined B3_USE_NEON
+       // zeros w
+       static const uint32x4_t xyzMask = (const uint32x4_t){-1, -1, -1, 0};
+       float32x4_t m0 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(0).mVec128, xyzMask);
+       float32x4_t m1 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(1).mVec128, xyzMask);
+       float32x4_t m2 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(2).mVec128, xyzMask);
+       float32x4_t row = m_el[0].mVec128;
+       float32x4_t r0 = vmulq_lane_f32(m0, vget_low_f32(row), 0);
+       float32x4_t r1 = vmulq_lane_f32(m0, vget_low_f32(row), 1);
+       float32x4_t r2 = vmulq_lane_f32(m0, vget_high_f32(row), 0);
+       row = m_el[1].mVec128;
+       r0 = vmlaq_lane_f32(r0, m1, vget_low_f32(row), 0);
+       r1 = vmlaq_lane_f32(r1, m1, vget_low_f32(row), 1);
+       r2 = vmlaq_lane_f32(r2, m1, vget_high_f32(row), 0);
+       row = m_el[2].mVec128;
+       r0 = vmlaq_lane_f32(r0, m2, vget_low_f32(row), 0);
+       r1 = vmlaq_lane_f32(r1, m2, vget_low_f32(row), 1);
+       r2 = vmlaq_lane_f32(r2, m2, vget_high_f32(row), 0);
+       return b3Matrix3x3(r0, r1, r2);
+#else
+       return b3Matrix3x3(
+               m_el[0].getX() * m[0].getX() + m_el[1].getX() * m[1].getX() + m_el[2].getX() * m[2].getX(),
+               m_el[0].getX() * m[0].getY() + m_el[1].getX() * m[1].getY() + m_el[2].getX() * m[2].getY(),
+               m_el[0].getX() * m[0].getZ() + m_el[1].getX() * m[1].getZ() + m_el[2].getX() * m[2].getZ(),
+               m_el[0].getY() * m[0].getX() + m_el[1].getY() * m[1].getX() + m_el[2].getY() * m[2].getX(),
+               m_el[0].getY() * m[0].getY() + m_el[1].getY() * m[1].getY() + m_el[2].getY() * m[2].getY(),
+               m_el[0].getY() * m[0].getZ() + m_el[1].getY() * m[1].getZ() + m_el[2].getY() * m[2].getZ(),
+               m_el[0].getZ() * m[0].getX() + m_el[1].getZ() * m[1].getX() + m_el[2].getZ() * m[2].getX(),
+               m_el[0].getZ() * m[0].getY() + m_el[1].getZ() * m[1].getY() + m_el[2].getZ() * m[2].getY(),
+               m_el[0].getZ() * m[0].getZ() + m_el[1].getZ() * m[1].getZ() + m_el[2].getZ() * m[2].getZ());
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+b3Matrix3x3::timesTranspose(const b3Matrix3x3& m) const
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+       __m128 a0 = m_el[0].mVec128;
+       __m128 a1 = m_el[1].mVec128;
+       __m128 a2 = m_el[2].mVec128;
+
+       b3Matrix3x3 mT = m.transpose();  // we rely on transpose() zeroing w channel so that we don't have to do it here
+       __m128 mx = mT[0].mVec128;
+       __m128 my = mT[1].mVec128;
+       __m128 mz = mT[2].mVec128;
+
+       __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
+       __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
+       __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
+       r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
+       r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
+       r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
+       r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
+       r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
+       r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
+       return b3Matrix3x3(r0, r1, r2);
+
+#elif defined B3_USE_NEON
+       float32x4_t a0 = m_el[0].mVec128;
+       float32x4_t a1 = m_el[1].mVec128;
+       float32x4_t a2 = m_el[2].mVec128;
+
+       b3Matrix3x3 mT = m.transpose();  // we rely on transpose() zeroing w channel so that we don't have to do it here
+       float32x4_t mx = mT[0].mVec128;
+       float32x4_t my = mT[1].mVec128;
+       float32x4_t mz = mT[2].mVec128;
+
+       float32x4_t r0 = vmulq_lane_f32(mx, vget_low_f32(a0), 0);
+       float32x4_t r1 = vmulq_lane_f32(mx, vget_low_f32(a1), 0);
+       float32x4_t r2 = vmulq_lane_f32(mx, vget_low_f32(a2), 0);
+       r0 = vmlaq_lane_f32(r0, my, vget_low_f32(a0), 1);
+       r1 = vmlaq_lane_f32(r1, my, vget_low_f32(a1), 1);
+       r2 = vmlaq_lane_f32(r2, my, vget_low_f32(a2), 1);
+       r0 = vmlaq_lane_f32(r0, mz, vget_high_f32(a0), 0);
+       r1 = vmlaq_lane_f32(r1, mz, vget_high_f32(a1), 0);
+       r2 = vmlaq_lane_f32(r2, mz, vget_high_f32(a2), 0);
+       return b3Matrix3x3(r0, r1, r2);
+
+#else
+       return b3Matrix3x3(
+               m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
+               m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
+               m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
+#endif
+}
+
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Matrix3x3& m, const b3Vector3& v)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+       return v.dot3(m[0], m[1], m[2]);
+#else
+       return b3MakeVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
+#endif
+}
+
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Vector3& v, const b3Matrix3x3& m)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+
+       const __m128 vv = v.mVec128;
+
+       __m128 c0 = b3_splat_ps(vv, 0);
+       __m128 c1 = b3_splat_ps(vv, 1);
+       __m128 c2 = b3_splat_ps(vv, 2);
+
+       c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, b3vFFF0fMask));
+       c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, b3vFFF0fMask));
+       c0 = _mm_add_ps(c0, c1);
+       c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, b3vFFF0fMask));
+
+       return b3MakeVector3(_mm_add_ps(c0, c2));
+#elif defined(B3_USE_NEON)
+       const float32x4_t vv = v.mVec128;
+       const float32x2_t vlo = vget_low_f32(vv);
+       const float32x2_t vhi = vget_high_f32(vv);
+
+       float32x4_t c0, c1, c2;
+
+       c0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, b3vFFF0Mask);
+       c1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, b3vFFF0Mask);
+       c2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, b3vFFF0Mask);
+
+       c0 = vmulq_lane_f32(c0, vlo, 0);
+       c1 = vmulq_lane_f32(c1, vlo, 1);
+       c2 = vmulq_lane_f32(c2, vhi, 0);
+       c0 = vaddq_f32(c0, c1);
+       c0 = vaddq_f32(c0, c2);
+
+       return b3MakeVector3(c0);
+#else
+       return b3MakeVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
+#endif
+}
+
+B3_FORCE_INLINE b3Matrix3x3
+operator*(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+
+       __m128 m10 = m1[0].mVec128;
+       __m128 m11 = m1[1].mVec128;
+       __m128 m12 = m1[2].mVec128;
+
+       __m128 m2v = _mm_and_ps(m2[0].mVec128, b3vFFF0fMask);
+
+       __m128 c0 = b3_splat_ps(m10, 0);
+       __m128 c1 = b3_splat_ps(m11, 0);
+       __m128 c2 = b3_splat_ps(m12, 0);
+
+       c0 = _mm_mul_ps(c0, m2v);
+       c1 = _mm_mul_ps(c1, m2v);
+       c2 = _mm_mul_ps(c2, m2v);
+
+       m2v = _mm_and_ps(m2[1].mVec128, b3vFFF0fMask);
+
+       __m128 c0_1 = b3_splat_ps(m10, 1);
+       __m128 c1_1 = b3_splat_ps(m11, 1);
+       __m128 c2_1 = b3_splat_ps(m12, 1);
+
+       c0_1 = _mm_mul_ps(c0_1, m2v);
+       c1_1 = _mm_mul_ps(c1_1, m2v);
+       c2_1 = _mm_mul_ps(c2_1, m2v);
+
+       m2v = _mm_and_ps(m2[2].mVec128, b3vFFF0fMask);
+
+       c0 = _mm_add_ps(c0, c0_1);
+       c1 = _mm_add_ps(c1, c1_1);
+       c2 = _mm_add_ps(c2, c2_1);
+
+       m10 = b3_splat_ps(m10, 2);
+       m11 = b3_splat_ps(m11, 2);
+       m12 = b3_splat_ps(m12, 2);
+
+       m10 = _mm_mul_ps(m10, m2v);
+       m11 = _mm_mul_ps(m11, m2v);
+       m12 = _mm_mul_ps(m12, m2v);
+
+       c0 = _mm_add_ps(c0, m10);
+       c1 = _mm_add_ps(c1, m11);
+       c2 = _mm_add_ps(c2, m12);
+
+       return b3Matrix3x3(c0, c1, c2);
+
+#elif defined(B3_USE_NEON)
+
+       float32x4_t rv0, rv1, rv2;
+       float32x4_t v0, v1, v2;
+       float32x4_t mv0, mv1, mv2;
+
+       v0 = m1[0].mVec128;
+       v1 = m1[1].mVec128;
+       v2 = m1[2].mVec128;
+
+       mv0 = (float32x4_t)vandq_s32((int32x4_t)m2[0].mVec128, b3vFFF0Mask);
+       mv1 = (float32x4_t)vandq_s32((int32x4_t)m2[1].mVec128, b3vFFF0Mask);
+       mv2 = (float32x4_t)vandq_s32((int32x4_t)m2[2].mVec128, b3vFFF0Mask);
+
+       rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+       rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+       rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+       rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+       rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+       rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+       rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+       rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+       rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+       return b3Matrix3x3(rv0, rv1, rv2);
+
+#else
+       return b3Matrix3x3(
+               m2.tdotx(m1[0]), m2.tdoty(m1[0]), m2.tdotz(m1[0]),
+               m2.tdotx(m1[1]), m2.tdoty(m1[1]), m2.tdotz(m1[1]),
+               m2.tdotx(m1[2]), m2.tdoty(m1[2]), m2.tdotz(m1[2]));
+#endif
+}
+
+/*
+B3_FORCE_INLINE b3Matrix3x3 b3MultTransposeLeft(const b3Matrix3x3& m1, const b3Matrix3x3& m2) {
+return b3Matrix3x3(
+m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
+m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
+m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
+m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
+m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
+m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
+m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
+m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
+m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
+}
+*/
+
+/**@brief Equality operator between two matrices
+* It will test all elements are equal.  */
+B3_FORCE_INLINE bool operator==(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+
+       __m128 c0, c1, c2;
+
+       c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
+       c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
+       c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
+
+       c0 = _mm_and_ps(c0, c1);
+       c0 = _mm_and_ps(c0, c2);
+
+       return (0x7 == _mm_movemask_ps((__m128)c0));
+#else
+       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
+}
+
+///for serialization
+struct b3Matrix3x3FloatData
+{
+       b3Vector3FloatData m_el[3];
+};
+
+///for serialization
+struct b3Matrix3x3DoubleData
+{
+       b3Vector3DoubleData m_el[3];
+};
+
+B3_FORCE_INLINE void b3Matrix3x3::serialize(struct b3Matrix3x3Data& dataOut) const
+{
+       for (int i = 0; i < 3; i++)
+               m_el[i].serialize(dataOut.m_el[i]);
+}
+
+B3_FORCE_INLINE void b3Matrix3x3::serializeFloat(struct b3Matrix3x3FloatData& dataOut) const
+{
+       for (int i = 0; i < 3; i++)
+               m_el[i].serializeFloat(dataOut.m_el[i]);
+}
+
+B3_FORCE_INLINE void b3Matrix3x3::deSerialize(const struct b3Matrix3x3Data& dataIn)
+{
+       for (int i = 0; i < 3; i++)
+               m_el[i].deSerialize(dataIn.m_el[i]);
+}
+
+B3_FORCE_INLINE void b3Matrix3x3::deSerializeFloat(const struct b3Matrix3x3FloatData& dataIn)
+{
+       for (int i = 0; i < 3; i++)
+               m_el[i].deSerializeFloat(dataIn.m_el[i]);
+}
+
+B3_FORCE_INLINE void b3Matrix3x3::deSerializeDouble(const struct b3Matrix3x3DoubleData& dataIn)
+{
+       for (int i = 0; i < 3; i++)
+               m_el[i].deSerializeDouble(dataIn.m_el[i]);
+}
+
+#endif  //B3_MATRIX3x3_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3MinMax.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3MinMax.h
new file mode 100644 (file)
index 0000000..c09c3db
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_GEN_MINMAX_H
+#define B3_GEN_MINMAX_H
+
+#include "b3Scalar.h"
+
+template <class T>
+B3_FORCE_INLINE const T& b3Min(const T& a, const T& b)
+{
+       return a < b ? a : b;
+}
+
+template <class T>
+B3_FORCE_INLINE const T& b3Max(const T& a, const T& b)
+{
+       return a > b ? a : b;
+}
+
+template <class T>
+B3_FORCE_INLINE const T& b3Clamped(const T& a, const T& lb, const T& ub)
+{
+       return a < lb ? lb : (ub < a ? ub : a);
+}
+
+template <class T>
+B3_FORCE_INLINE void b3SetMin(T& a, const T& b)
+{
+       if (b < a)
+       {
+               a = b;
+       }
+}
+
+template <class T>
+B3_FORCE_INLINE void b3SetMax(T& a, const T& b)
+{
+       if (a < b)
+       {
+               a = b;
+       }
+}
+
+template <class T>
+B3_FORCE_INLINE void b3Clamp(T& a, const T& lb, const T& ub)
+{
+       if (a < lb)
+       {
+               a = lb;
+       }
+       else if (ub < a)
+       {
+               a = ub;
+       }
+}
+
+#endif  //B3_GEN_MINMAX_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3PoolAllocator.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3PoolAllocator.h
new file mode 100644 (file)
index 0000000..ed56bc6
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _BT_POOL_ALLOCATOR_H
+#define _BT_POOL_ALLOCATOR_H
+
+#include "b3Scalar.h"
+#include "b3AlignedAllocator.h"
+
+///The b3PoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
+class b3PoolAllocator
+{
+       int m_elemSize;
+       int m_maxElements;
+       int m_freeCount;
+       void* m_firstFree;
+       unsigned char* m_pool;
+
+public:
+       b3PoolAllocator(int elemSize, int maxElements)
+               : m_elemSize(elemSize),
+                 m_maxElements(maxElements)
+       {
+               m_pool = (unsigned char*)b3AlignedAlloc(static_cast<unsigned int>(m_elemSize * m_maxElements), 16);
+
+               unsigned char* p = m_pool;
+               m_firstFree = p;
+               m_freeCount = m_maxElements;
+               int count = m_maxElements;
+               while (--count)
+               {
+                       *(void**)p = (p + m_elemSize);
+                       p += m_elemSize;
+               }
+               *(void**)p = 0;
+       }
+
+       ~b3PoolAllocator()
+       {
+               b3AlignedFree(m_pool);
+       }
+
+       int getFreeCount() const
+       {
+               return m_freeCount;
+       }
+
+       int getUsedCount() const
+       {
+               return m_maxElements - m_freeCount;
+       }
+
+       int getMaxCount() const
+       {
+               return m_maxElements;
+       }
+
+       void* allocate(int size)
+       {
+               // release mode fix
+               (void)size;
+               b3Assert(!size || size <= m_elemSize);
+               b3Assert(m_freeCount > 0);
+               void* result = m_firstFree;
+               m_firstFree = *(void**)m_firstFree;
+               --m_freeCount;
+               return result;
+       }
+
+       bool validPtr(void* ptr)
+       {
+               if (ptr)
+               {
+                       if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
+                       {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       void freeMemory(void* ptr)
+       {
+               if (ptr)
+               {
+                       b3Assert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
+
+                       *(void**)ptr = m_firstFree;
+                       m_firstFree = ptr;
+                       ++m_freeCount;
+               }
+       }
+
+       int getElementSize() const
+       {
+               return m_elemSize;
+       }
+
+       unsigned char* getPoolAddress()
+       {
+               return m_pool;
+       }
+
+       const unsigned char* getPoolAddress() const
+       {
+               return m_pool;
+       }
+};
+
+#endif  //_BT_POOL_ALLOCATOR_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3QuadWord.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3QuadWord.h
new file mode 100644 (file)
index 0000000..0def305
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_SIMD_QUADWORD_H
+#define B3_SIMD_QUADWORD_H
+
+#include "b3Scalar.h"
+#include "b3MinMax.h"
+
+#if defined(__CELLOS_LV2) && defined(__SPU__)
+#include <altivec.h>
+#endif
+
+/**@brief The b3QuadWord class is base class for b3Vector3 and b3Quaternion. 
+ * Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
+ */
+#ifndef USE_LIBSPE2
+B3_ATTRIBUTE_ALIGNED16(class)
+b3QuadWord
+#else
+class b3QuadWord
+#endif
+{
+protected:
+#if defined(__SPU__) && defined(__CELLOS_LV2__)
+       union {
+               vec_float4 mVec128;
+               b3Scalar m_floats[4];
+       };
+
+public:
+       vec_float4 get128() const
+       {
+               return mVec128;
+       }
+
+#else  //__CELLOS_LV2__ __SPU__
+
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+public:
+       union {
+               b3SimdFloat4 mVec128;
+               b3Scalar m_floats[4];
+               struct
+               {
+                       b3Scalar x, y, z, w;
+               };
+       };
+
+public:
+       B3_FORCE_INLINE b3SimdFloat4 get128() const
+       {
+               return mVec128;
+       }
+       B3_FORCE_INLINE void set128(b3SimdFloat4 v128)
+       {
+               mVec128 = v128;
+       }
+#else
+public:
+       union {
+               b3Scalar m_floats[4];
+               struct
+               {
+                       b3Scalar x, y, z, w;
+               };
+       };
+#endif  // B3_USE_SSE
+
+#endif  //__CELLOS_LV2__ __SPU__
+
+public:
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+
+       // Set Vector
+       B3_FORCE_INLINE b3QuadWord(const b3SimdFloat4 vec)
+       {
+               mVec128 = vec;
+       }
+
+       // Copy constructor
+       B3_FORCE_INLINE b3QuadWord(const b3QuadWord& rhs)
+       {
+               mVec128 = rhs.mVec128;
+       }
+
+       // Assignment Operator
+       B3_FORCE_INLINE b3QuadWord&
+       operator=(const b3QuadWord& v)
+       {
+               mVec128 = v.mVec128;
+
+               return *this;
+       }
+
+#endif
+
+       /**@brief Return the x value */
+       B3_FORCE_INLINE const b3Scalar& getX() const { return m_floats[0]; }
+       /**@brief Return the y value */
+       B3_FORCE_INLINE const b3Scalar& getY() const { return m_floats[1]; }
+       /**@brief Return the z value */
+       B3_FORCE_INLINE const b3Scalar& getZ() const { return m_floats[2]; }
+       /**@brief Set the x value */
+       B3_FORCE_INLINE void setX(b3Scalar _x) { m_floats[0] = _x; };
+       /**@brief Set the y value */
+       B3_FORCE_INLINE void setY(b3Scalar _y) { m_floats[1] = _y; };
+       /**@brief Set the z value */
+       B3_FORCE_INLINE void setZ(b3Scalar _z) { m_floats[2] = _z; };
+       /**@brief Set the w value */
+       B3_FORCE_INLINE void setW(b3Scalar _w) { m_floats[3] = _w; };
+       /**@brief Return the x value */
+
+       //B3_FORCE_INLINE b3Scalar&       operator[](int i)       { return (&m_floats[0])[i];   }
+       //B3_FORCE_INLINE const b3Scalar& operator[](int i) const { return (&m_floats[0])[i]; }
+       ///operator b3Scalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+       B3_FORCE_INLINE operator b3Scalar*() { return &m_floats[0]; }
+       B3_FORCE_INLINE operator const b3Scalar*() const { return &m_floats[0]; }
+
+       B3_FORCE_INLINE bool operator==(const b3QuadWord& other) const
+       {
+#ifdef B3_USE_SSE
+               return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+               return ((m_floats[3] == other.m_floats[3]) &&
+                               (m_floats[2] == other.m_floats[2]) &&
+                               (m_floats[1] == other.m_floats[1]) &&
+                               (m_floats[0] == other.m_floats[0]));
+#endif
+       }
+
+       B3_FORCE_INLINE bool operator!=(const b3QuadWord& other) const
+       {
+               return !(*this == other);
+       }
+
+       /**@brief Set x,y,z and zero w 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+       B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
+       {
+               m_floats[0] = _x;
+               m_floats[1] = _y;
+               m_floats[2] = _z;
+               m_floats[3] = 0.f;
+       }
+
+       /*              void getValue(b3Scalar *m) const 
+               {
+                       m[0] = m_floats[0];
+                       m[1] = m_floats[1];
+                       m[2] = m_floats[2];
+               }
+*/
+       /**@brief Set the values 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+       B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
+       {
+               m_floats[0] = _x;
+               m_floats[1] = _y;
+               m_floats[2] = _z;
+               m_floats[3] = _w;
+       }
+       /**@brief No initialization constructor */
+       B3_FORCE_INLINE b3QuadWord()
+       //      :m_floats[0](b3Scalar(0.)),m_floats[1](b3Scalar(0.)),m_floats[2](b3Scalar(0.)),m_floats[3](b3Scalar(0.))
+       {
+       }
+
+       /**@brief Three argument constructor (zeros w)
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+       B3_FORCE_INLINE b3QuadWord(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
+       {
+               m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
+       }
+
+       /**@brief Initializing constructor
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+       B3_FORCE_INLINE b3QuadWord(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
+       {
+               m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
+       }
+
+       /**@brief Set each element to the max of the current values and the values of another b3QuadWord
+   * @param other The other b3QuadWord to compare with 
+   */
+       B3_FORCE_INLINE void setMax(const b3QuadWord& other)
+       {
+#ifdef B3_USE_SSE
+               mVec128 = _mm_max_ps(mVec128, other.mVec128);
+#elif defined(B3_USE_NEON)
+               mVec128 = vmaxq_f32(mVec128, other.mVec128);
+#else
+               b3SetMax(m_floats[0], other.m_floats[0]);
+               b3SetMax(m_floats[1], other.m_floats[1]);
+               b3SetMax(m_floats[2], other.m_floats[2]);
+               b3SetMax(m_floats[3], other.m_floats[3]);
+#endif
+       }
+       /**@brief Set each element to the min of the current values and the values of another b3QuadWord
+   * @param other The other b3QuadWord to compare with 
+   */
+       B3_FORCE_INLINE void setMin(const b3QuadWord& other)
+       {
+#ifdef B3_USE_SSE
+               mVec128 = _mm_min_ps(mVec128, other.mVec128);
+#elif defined(B3_USE_NEON)
+               mVec128 = vminq_f32(mVec128, other.mVec128);
+#else
+               b3SetMin(m_floats[0], other.m_floats[0]);
+               b3SetMin(m_floats[1], other.m_floats[1]);
+               b3SetMin(m_floats[2], other.m_floats[2]);
+               b3SetMin(m_floats[3], other.m_floats[3]);
+#endif
+       }
+};
+
+#endif  //B3_SIMD_QUADWORD_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3Quaternion.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3Quaternion.h
new file mode 100644 (file)
index 0000000..4fdd72d
--- /dev/null
@@ -0,0 +1,908 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_SIMD__QUATERNION_H_
+#define B3_SIMD__QUATERNION_H_
+
+#include "b3Vector3.h"
+#include "b3QuadWord.h"
+
+#ifdef B3_USE_SSE
+
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3vOnes) = {1.0f, 1.0f, 1.0f, 1.0f};
+
+#endif
+
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+
+const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3vQInv) = {-0.0f, -0.0f, -0.0f, +0.0f};
+const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3vPPPM) = {+0.0f, +0.0f, +0.0f, -0.0f};
+
+#endif
+
+/**@brief The b3Quaternion implements quaternion to perform linear algebra rotations in combination with b3Matrix3x3, b3Vector3 and b3Transform. */
+class b3Quaternion : public b3QuadWord
+{
+public:
+       /**@brief No initialization constructor */
+       b3Quaternion() {}
+
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
+       // Set Vector
+       B3_FORCE_INLINE b3Quaternion(const b3SimdFloat4 vec)
+       {
+               mVec128 = vec;
+       }
+
+       // Copy constructor
+       B3_FORCE_INLINE b3Quaternion(const b3Quaternion& rhs)
+       {
+               mVec128 = rhs.mVec128;
+       }
+
+       // Assignment Operator
+       B3_FORCE_INLINE b3Quaternion&
+       operator=(const b3Quaternion& v)
+       {
+               mVec128 = v.mVec128;
+
+               return *this;
+       }
+
+#endif
+
+       //              template <typename b3Scalar>
+       //              explicit Quaternion(const b3Scalar *v) : Tuple4<b3Scalar>(v) {}
+       /**@brief Constructor from scalars */
+       b3Quaternion(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
+               : b3QuadWord(_x, _y, _z, _w)
+       {
+               //b3Assert(!((_x==1.f) && (_y==0.f) && (_z==0.f) && (_w==0.f)));
+       }
+       /**@brief Axis angle Constructor
+   * @param axis The axis which the rotation is around
+   * @param angle The magnitude of the rotation around the angle (Radians) */
+       b3Quaternion(const b3Vector3& _axis, const b3Scalar& _angle)
+       {
+               setRotation(_axis, _angle);
+       }
+       /**@brief Constructor from Euler angles
+   * @param yaw Angle around Y unless B3_EULER_DEFAULT_ZYX defined then Z
+   * @param pitch Angle around X unless B3_EULER_DEFAULT_ZYX defined then Y
+   * @param roll Angle around Z unless B3_EULER_DEFAULT_ZYX defined then X */
+       b3Quaternion(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
+       {
+#ifndef B3_EULER_DEFAULT_ZYX
+               setEuler(yaw, pitch, roll);
+#else
+               setEulerZYX(yaw, pitch, roll);
+#endif
+       }
+       /**@brief Set the rotation using axis angle notation 
+   * @param axis The axis around which to rotate
+   * @param angle The magnitude of the rotation in Radians */
+       void setRotation(const b3Vector3& axis1, const b3Scalar& _angle)
+       {
+               b3Vector3 axis = axis1;
+               axis.safeNormalize();
+               
+               b3Scalar d = axis.length();
+               b3Assert(d != b3Scalar(0.0));
+               if (d < B3_EPSILON)
+               {
+                       setValue(0, 0, 0, 1);
+               }
+               else
+               {
+                       b3Scalar s = b3Sin(_angle * b3Scalar(0.5)) / d;
+                       setValue(axis.getX() * s, axis.getY() * s, axis.getZ() * s,
+                               b3Cos(_angle * b3Scalar(0.5)));
+               }
+       }
+       /**@brief Set the quaternion using Euler angles
+   * @param yaw Angle around Y
+   * @param pitch Angle around X
+   * @param roll Angle around Z */
+       void setEuler(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
+       {
+               b3Scalar halfYaw = b3Scalar(yaw) * b3Scalar(0.5);
+               b3Scalar halfPitch = b3Scalar(pitch) * b3Scalar(0.5);
+               b3Scalar halfRoll = b3Scalar(roll) * b3Scalar(0.5);
+               b3Scalar cosYaw = b3Cos(halfYaw);
+               b3Scalar sinYaw = b3Sin(halfYaw);
+               b3Scalar cosPitch = b3Cos(halfPitch);
+               b3Scalar sinPitch = b3Sin(halfPitch);
+               b3Scalar cosRoll = b3Cos(halfRoll);
+               b3Scalar sinRoll = b3Sin(halfRoll);
+               setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
+                                cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
+                                sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
+                                cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
+       }
+
+       /**@brief Set the quaternion using euler angles 
+   * @param yaw Angle around Z
+   * @param pitch Angle around Y
+   * @param roll Angle around X */
+       void setEulerZYX(const b3Scalar& yawZ, const b3Scalar& pitchY, const b3Scalar& rollX)
+       {
+               b3Scalar halfYaw = b3Scalar(yawZ) * b3Scalar(0.5);
+               b3Scalar halfPitch = b3Scalar(pitchY) * b3Scalar(0.5);
+               b3Scalar halfRoll = b3Scalar(rollX) * b3Scalar(0.5);
+               b3Scalar cosYaw = b3Cos(halfYaw);
+               b3Scalar sinYaw = b3Sin(halfYaw);
+               b3Scalar cosPitch = b3Cos(halfPitch);
+               b3Scalar sinPitch = b3Sin(halfPitch);
+               b3Scalar cosRoll = b3Cos(halfRoll);
+               b3Scalar sinRoll = b3Sin(halfRoll);
+               setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,   //x
+                                cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,   //y
+                                cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,   //z
+                                cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);  //formerly yzx
+               normalize();
+       }
+
+       /**@brief Get the euler angles from this quaternion
+          * @param yaw Angle around Z
+          * @param pitch Angle around Y
+          * @param roll Angle around X */
+       void getEulerZYX(b3Scalar& yawZ, b3Scalar& pitchY, b3Scalar& rollX) const
+       {
+               b3Scalar squ;
+               b3Scalar sqx;
+               b3Scalar sqy;
+               b3Scalar sqz;
+               b3Scalar sarg;
+               sqx = m_floats[0] * m_floats[0];
+               sqy = m_floats[1] * m_floats[1];
+               sqz = m_floats[2] * m_floats[2];
+               squ = m_floats[3] * m_floats[3];
+               rollX = b3Atan2(2 * (m_floats[1] * m_floats[2] + m_floats[3] * m_floats[0]), squ - sqx - sqy + sqz);
+               sarg = b3Scalar(-2.) * (m_floats[0] * m_floats[2] - m_floats[3] * m_floats[1]);
+               pitchY = sarg <= b3Scalar(-1.0) ? b3Scalar(-0.5) * B3_PI : (sarg >= b3Scalar(1.0) ? b3Scalar(0.5) * B3_PI : b3Asin(sarg));
+               yawZ = b3Atan2(2 * (m_floats[0] * m_floats[1] + m_floats[3] * m_floats[2]), squ + sqx - sqy - sqz);
+       }
+
+       /**@brief Add two quaternions
+   * @param q The quaternion to add to this one */
+       B3_FORCE_INLINE b3Quaternion& operator+=(const b3Quaternion& q)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               mVec128 = _mm_add_ps(mVec128, q.mVec128);
+#elif defined(B3_USE_NEON)
+               mVec128 = vaddq_f32(mVec128, q.mVec128);
+#else
+               m_floats[0] += q.getX();
+               m_floats[1] += q.getY();
+               m_floats[2] += q.getZ();
+               m_floats[3] += q.m_floats[3];
+#endif
+               return *this;
+       }
+
+       /**@brief Subtract out a quaternion
+   * @param q The quaternion to subtract from this one */
+       b3Quaternion& operator-=(const b3Quaternion& q)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               mVec128 = _mm_sub_ps(mVec128, q.mVec128);
+#elif defined(B3_USE_NEON)
+               mVec128 = vsubq_f32(mVec128, q.mVec128);
+#else
+               m_floats[0] -= q.getX();
+               m_floats[1] -= q.getY();
+               m_floats[2] -= q.getZ();
+               m_floats[3] -= q.m_floats[3];
+#endif
+               return *this;
+       }
+
+       /**@brief Scale this quaternion
+   * @param s The scalar to scale by */
+       b3Quaternion& operator*=(const b3Scalar& s)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 vs = _mm_load_ss(&s);  //        (S 0 0 0)
+               vs = b3_pshufd_ps(vs, 0);     //        (S S S S)
+               mVec128 = _mm_mul_ps(mVec128, vs);
+#elif defined(B3_USE_NEON)
+               mVec128 = vmulq_n_f32(mVec128, s);
+#else
+               m_floats[0] *= s;
+               m_floats[1] *= s;
+               m_floats[2] *= s;
+               m_floats[3] *= s;
+#endif
+               return *this;
+       }
+
+       /**@brief Multiply this quaternion by q on the right
+   * @param q The other quaternion 
+   * Equivilant to this = this * q */
+       b3Quaternion& operator*=(const b3Quaternion& q)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 vQ2 = q.get128();
+
+               __m128 A1 = b3_pshufd_ps(mVec128, B3_SHUFFLE(0, 1, 2, 0));
+               __m128 B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3, 3, 3, 0));
+
+               A1 = A1 * B1;
+
+               __m128 A2 = b3_pshufd_ps(mVec128, B3_SHUFFLE(1, 2, 0, 1));
+               __m128 B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1));
+
+               A2 = A2 * B2;
+
+               B1 = b3_pshufd_ps(mVec128, B3_SHUFFLE(2, 0, 1, 2));
+               B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2));
+
+               B1 = B1 * B2;  //       A3 *= B3
+
+               mVec128 = b3_splat_ps(mVec128, 3);  //  A0
+               mVec128 = mVec128 * vQ2;            //  A0 * B0
+
+               A1 = A1 + A2;                  //       AB12
+               mVec128 = mVec128 - B1;        //       AB03 = AB0 - AB3
+               A1 = _mm_xor_ps(A1, b3vPPPM);  //       change sign of the last element
+               mVec128 = mVec128 + A1;        //       AB03 + AB12
+
+#elif defined(B3_USE_NEON)
+
+               float32x4_t vQ1 = mVec128;
+               float32x4_t vQ2 = q.get128();
+               float32x4_t A0, A1, B1, A2, B2, A3, B3;
+               float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+               {
+                       float32x2x2_t tmp;
+                       tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1));  // {z x}, {w y}
+                       vQ1zx = tmp.val[0];
+
+                       tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2));  // {z x}, {w y}
+                       vQ2zx = tmp.val[0];
+               }
+               vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+               vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+               vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+               vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+               A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx);                     // X Y  z x
+               B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx);  // W W  W X
+
+               A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+               B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+               A3 = vcombine_f32(vQ1zx, vQ1yz);  // Z X Y Z
+               B3 = vcombine_f32(vQ2yz, vQ2xz);  // Y Z x z
+
+               A1 = vmulq_f32(A1, B1);
+               A2 = vmulq_f32(A2, B2);
+               A3 = vmulq_f32(A3, B3);                           //    A3 *= B3
+               A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1);  //    A0 * B0
+
+               A1 = vaddq_f32(A1, A2);  //     AB12 = AB1 + AB2
+               A0 = vsubq_f32(A0, A3);  //     AB03 = AB0 - AB3
+
+               //      change the sign of the last element
+               A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+               A0 = vaddq_f32(A0, A1);  //     AB03 + AB12
+
+               mVec128 = A0;
+#else
+               setValue(
+                       m_floats[3] * q.getX() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.getZ() - m_floats[2] * q.getY(),
+                       m_floats[3] * q.getY() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.getX() - m_floats[0] * q.getZ(),
+                       m_floats[3] * q.getZ() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.getY() - m_floats[1] * q.getX(),
+                       m_floats[3] * q.m_floats[3] - m_floats[0] * q.getX() - m_floats[1] * q.getY() - m_floats[2] * q.getZ());
+#endif
+               return *this;
+       }
+       /**@brief Return the dot product between this quaternion and another
+   * @param q The other quaternion */
+       b3Scalar dot(const b3Quaternion& q) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 vd;
+
+               vd = _mm_mul_ps(mVec128, q.mVec128);
+
+               __m128 t = _mm_movehl_ps(vd, vd);
+               vd = _mm_add_ps(vd, t);
+               t = _mm_shuffle_ps(vd, vd, 0x55);
+               vd = _mm_add_ss(vd, t);
+
+               return _mm_cvtss_f32(vd);
+#elif defined(B3_USE_NEON)
+               float32x4_t vd = vmulq_f32(mVec128, q.mVec128);
+               float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
+               x = vpadd_f32(x, x);
+               return vget_lane_f32(x, 0);
+#else
+               return m_floats[0] * q.getX() +
+                          m_floats[1] * q.getY() +
+                          m_floats[2] * q.getZ() +
+                          m_floats[3] * q.m_floats[3];
+#endif
+       }
+
+       /**@brief Return the length squared of the quaternion */
+       b3Scalar length2() const
+       {
+               return dot(*this);
+       }
+
+       /**@brief Return the length of the quaternion */
+       b3Scalar length() const
+       {
+               return b3Sqrt(length2());
+       }
+
+       /**@brief Normalize the quaternion 
+   * Such that x^2 + y^2 + z^2 +w^2 = 1 */
+       b3Quaternion& normalize()
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 vd;
+
+               vd = _mm_mul_ps(mVec128, mVec128);
+
+               __m128 t = _mm_movehl_ps(vd, vd);
+               vd = _mm_add_ps(vd, t);
+               t = _mm_shuffle_ps(vd, vd, 0x55);
+               vd = _mm_add_ss(vd, t);
+
+               vd = _mm_sqrt_ss(vd);
+               vd = _mm_div_ss(b3vOnes, vd);
+               vd = b3_pshufd_ps(vd, 0);  // splat
+               mVec128 = _mm_mul_ps(mVec128, vd);
+
+               return *this;
+#else
+               return *this /= length();
+#endif
+       }
+
+       /**@brief Return a scaled version of this quaternion
+   * @param s The scale factor */
+       B3_FORCE_INLINE b3Quaternion
+       operator*(const b3Scalar& s) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 vs = _mm_load_ss(&s);  //        (S 0 0 0)
+               vs = b3_pshufd_ps(vs, 0x00);  //        (S S S S)
+
+               return b3Quaternion(_mm_mul_ps(mVec128, vs));
+#elif defined(B3_USE_NEON)
+               return b3Quaternion(vmulq_n_f32(mVec128, s));
+#else
+               return b3Quaternion(getX() * s, getY() * s, getZ() * s, m_floats[3] * s);
+#endif
+       }
+
+       /**@brief Return an inversely scaled versionof this quaternion
+   * @param s The inverse scale factor */
+       b3Quaternion operator/(const b3Scalar& s) const
+       {
+               b3Assert(s != b3Scalar(0.0));
+               return *this * (b3Scalar(1.0) / s);
+       }
+
+       /**@brief Inversely scale this quaternion
+   * @param s The scale factor */
+       b3Quaternion& operator/=(const b3Scalar& s)
+       {
+               b3Assert(s != b3Scalar(0.0));
+               return *this *= b3Scalar(1.0) / s;
+       }
+
+       /**@brief Return a normalized version of this quaternion */
+       b3Quaternion normalized() const
+       {
+               return *this / length();
+       }
+       /**@brief Return the angle between this quaternion and the other 
+   * @param q The other quaternion */
+       b3Scalar angle(const b3Quaternion& q) const
+       {
+               b3Scalar s = b3Sqrt(length2() * q.length2());
+               b3Assert(s != b3Scalar(0.0));
+               return b3Acos(dot(q) / s);
+       }
+       /**@brief Return the angle of rotation represented by this quaternion */
+       b3Scalar getAngle() const
+       {
+               b3Scalar s = b3Scalar(2.) * b3Acos(m_floats[3]);
+               return s;
+       }
+
+       /**@brief Return the axis of the rotation represented by this quaternion */
+       b3Vector3 getAxis() const
+       {
+               b3Scalar s_squared = 1.f - m_floats[3] * m_floats[3];
+
+               if (s_squared < b3Scalar(10.) * B3_EPSILON)  //Check for divide by zero
+                       return b3MakeVector3(1.0, 0.0, 0.0);     // Arbitrary
+               b3Scalar s = 1.f / b3Sqrt(s_squared);
+               return b3MakeVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s);
+       }
+
+       /**@brief Return the inverse of this quaternion */
+       b3Quaternion inverse() const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               return b3Quaternion(_mm_xor_ps(mVec128, b3vQInv));
+#elif defined(B3_USE_NEON)
+               return b3Quaternion((b3SimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)b3vQInv));
+#else
+               return b3Quaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
+#endif
+       }
+
+       /**@brief Return the sum of this quaternion and the other 
+   * @param q2 The other quaternion */
+       B3_FORCE_INLINE b3Quaternion
+       operator+(const b3Quaternion& q2) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               return b3Quaternion(_mm_add_ps(mVec128, q2.mVec128));
+#elif defined(B3_USE_NEON)
+               return b3Quaternion(vaddq_f32(mVec128, q2.mVec128));
+#else
+               const b3Quaternion& q1 = *this;
+               return b3Quaternion(q1.getX() + q2.getX(), q1.getY() + q2.getY(), q1.getZ() + q2.getZ(), q1.m_floats[3] + q2.m_floats[3]);
+#endif
+       }
+
+       /**@brief Return the difference between this quaternion and the other 
+   * @param q2 The other quaternion */
+       B3_FORCE_INLINE b3Quaternion
+       operator-(const b3Quaternion& q2) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               return b3Quaternion(_mm_sub_ps(mVec128, q2.mVec128));
+#elif defined(B3_USE_NEON)
+               return b3Quaternion(vsubq_f32(mVec128, q2.mVec128));
+#else
+               const b3Quaternion& q1 = *this;
+               return b3Quaternion(q1.getX() - q2.getX(), q1.getY() - q2.getY(), q1.getZ() - q2.getZ(), q1.m_floats[3] - q2.m_floats[3]);
+#endif
+       }
+
+       /**@brief Return the negative of this quaternion 
+   * This simply negates each element */
+       B3_FORCE_INLINE b3Quaternion operator-() const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               return b3Quaternion(_mm_xor_ps(mVec128, b3vMzeroMask));
+#elif defined(B3_USE_NEON)
+               return b3Quaternion((b3SimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)b3vMzeroMask));
+#else
+               const b3Quaternion& q2 = *this;
+               return b3Quaternion(-q2.getX(), -q2.getY(), -q2.getZ(), -q2.m_floats[3]);
+#endif
+       }
+       /**@todo document this and it's use */
+       B3_FORCE_INLINE b3Quaternion farthest(const b3Quaternion& qd) const
+       {
+               b3Quaternion diff, sum;
+               diff = *this - qd;
+               sum = *this + qd;
+               if (diff.dot(diff) > sum.dot(sum))
+                       return qd;
+               return (-qd);
+       }
+
+       /**@todo document this and it's use */
+       B3_FORCE_INLINE b3Quaternion nearest(const b3Quaternion& qd) const
+       {
+               b3Quaternion diff, sum;
+               diff = *this - qd;
+               sum = *this + qd;
+               if (diff.dot(diff) < sum.dot(sum))
+                       return qd;
+               return (-qd);
+       }
+
+       /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
+   * @param q The other quaternion to interpolate with 
+   * @param t The ratio between this and q to interpolate.  If t = 0 the result is this, if t=1 the result is q.
+   * Slerp interpolates assuming constant velocity.  */
+       b3Quaternion slerp(const b3Quaternion& q, const b3Scalar& t) const
+       {
+               b3Scalar magnitude = b3Sqrt(length2() * q.length2());
+               b3Assert(magnitude > b3Scalar(0));
+
+               b3Scalar product = dot(q) / magnitude;
+               if (b3Fabs(product) < b3Scalar(1))
+               {
+                       // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
+                       const b3Scalar sign = (product < 0) ? b3Scalar(-1) : b3Scalar(1);
+
+                       const b3Scalar theta = b3Acos(sign * product);
+                       const b3Scalar s1 = b3Sin(sign * t * theta);
+                       const b3Scalar d = b3Scalar(1.0) / b3Sin(theta);
+                       const b3Scalar s0 = b3Sin((b3Scalar(1.0) - t) * theta);
+
+                       return b3Quaternion(
+                               (m_floats[0] * s0 + q.getX() * s1) * d,
+                               (m_floats[1] * s0 + q.getY() * s1) * d,
+                               (m_floats[2] * s0 + q.getZ() * s1) * d,
+                               (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
+               }
+               else
+               {
+                       return *this;
+               }
+       }
+
+       static const b3Quaternion& getIdentity()
+       {
+               static const b3Quaternion identityQuat(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.), b3Scalar(1.));
+               return identityQuat;
+       }
+
+       B3_FORCE_INLINE const b3Scalar& getW() const { return m_floats[3]; }
+};
+
+/**@brief Return the product of two quaternions */
+B3_FORCE_INLINE b3Quaternion
+operator*(const b3Quaternion& q1, const b3Quaternion& q2)
+{
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+       __m128 vQ1 = q1.get128();
+       __m128 vQ2 = q2.get128();
+       __m128 A0, A1, B1, A2, B2;
+
+       A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(0, 1, 2, 0));  // X Y  z x     //      vtrn
+       B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3, 3, 3, 0));  // W W  W X     // vdup vext
+
+       A1 = A1 * B1;
+
+       A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1, 2, 0, 1));  // Y Z  X Y     // vext
+       B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1));  // z x  Y Y     // vtrn vdup
+
+       A2 = A2 * B2;
+
+       B1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2, 0, 1, 2));  // z x Y Z      // vtrn vext
+       B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2));  // Y Z x z      // vext vtrn
+
+       B1 = B1 * B2;  //       A3 *= B3
+
+       A0 = b3_splat_ps(vQ1, 3);  //   A0
+       A0 = A0 * vQ2;             //   A0 * B0
+
+       A1 = A1 + A2;  //       AB12
+       A0 = A0 - B1;  //       AB03 = AB0 - AB3
+
+       A1 = _mm_xor_ps(A1, b3vPPPM);  //       change sign of the last element
+       A0 = A0 + A1;                  //       AB03 + AB12
+
+       return b3Quaternion(A0);
+
+#elif defined(B3_USE_NEON)
+
+       float32x4_t vQ1 = q1.get128();
+       float32x4_t vQ2 = q2.get128();
+       float32x4_t A0, A1, B1, A2, B2, A3, B3;
+       float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+       {
+               float32x2x2_t tmp;
+               tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1));  // {z x}, {w y}
+               vQ1zx = tmp.val[0];
+
+               tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2));  // {z x}, {w y}
+               vQ2zx = tmp.val[0];
+       }
+       vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+       vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+       vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+       vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+       A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx);                     // X Y  z x
+       B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx);  // W W  W X
+
+       A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+       B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+       A3 = vcombine_f32(vQ1zx, vQ1yz);  // Z X Y Z
+       B3 = vcombine_f32(vQ2yz, vQ2xz);  // Y Z x z
+
+       A1 = vmulq_f32(A1, B1);
+       A2 = vmulq_f32(A2, B2);
+       A3 = vmulq_f32(A3, B3);                           //    A3 *= B3
+       A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1);  //    A0 * B0
+
+       A1 = vaddq_f32(A1, A2);  //     AB12 = AB1 + AB2
+       A0 = vsubq_f32(A0, A3);  //     AB03 = AB0 - AB3
+
+       //      change the sign of the last element
+       A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+       A0 = vaddq_f32(A0, A1);  //     AB03 + AB12
+
+       return b3Quaternion(A0);
+
+#else
+       return b3Quaternion(
+               q1.getW() * q2.getX() + q1.getX() * q2.getW() + q1.getY() * q2.getZ() - q1.getZ() * q2.getY(),
+               q1.getW() * q2.getY() + q1.getY() * q2.getW() + q1.getZ() * q2.getX() - q1.getX() * q2.getZ(),
+               q1.getW() * q2.getZ() + q1.getZ() * q2.getW() + q1.getX() * q2.getY() - q1.getY() * q2.getX(),
+               q1.getW() * q2.getW() - q1.getX() * q2.getX() - q1.getY() * q2.getY() - q1.getZ() * q2.getZ());
+#endif
+}
+
+B3_FORCE_INLINE b3Quaternion
+operator*(const b3Quaternion& q, const b3Vector3& w)
+{
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+       __m128 vQ1 = q.get128();
+       __m128 vQ2 = w.get128();
+       __m128 A1, B1, A2, B2, A3, B3;
+
+       A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(3, 3, 3, 0));
+       B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(0, 1, 2, 0));
+
+       A1 = A1 * B1;
+
+       A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1, 2, 0, 1));
+       B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1));
+
+       A2 = A2 * B2;
+
+       A3 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2, 0, 1, 2));
+       B3 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2));
+
+       A3 = A3 * B3;  //       A3 *= B3
+
+       A1 = A1 + A2;                  //       AB12
+       A1 = _mm_xor_ps(A1, b3vPPPM);  //       change sign of the last element
+       A1 = A1 - A3;                  //       AB123 = AB12 - AB3
+
+       return b3Quaternion(A1);
+
+#elif defined(B3_USE_NEON)
+
+       float32x4_t vQ1 = q.get128();
+       float32x4_t vQ2 = w.get128();
+       float32x4_t A1, B1, A2, B2, A3, B3;
+       float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
+
+       vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
+       {
+               float32x2x2_t tmp;
+
+               tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2));  // {z x}, {w y}
+               vQ2zx = tmp.val[0];
+
+               tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1));  // {z x}, {w y}
+               vQ1zx = tmp.val[0];
+       }
+
+       vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+       vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+       vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+       A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx);  // W W  W X
+       B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx);                     // X Y  z x
+
+       A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+       B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+       A3 = vcombine_f32(vQ1zx, vQ1yz);  // Z X Y Z
+       B3 = vcombine_f32(vQ2yz, vQ2xz);  // Y Z x z
+
+       A1 = vmulq_f32(A1, B1);
+       A2 = vmulq_f32(A2, B2);
+       A3 = vmulq_f32(A3, B3);  //     A3 *= B3
+
+       A1 = vaddq_f32(A1, A2);  //     AB12 = AB1 + AB2
+
+       //      change the sign of the last element
+       A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+
+       A1 = vsubq_f32(A1, A3);  //     AB123 = AB12 - AB3
+
+       return b3Quaternion(A1);
+
+#else
+       return b3Quaternion(
+               q.getW() * w.getX() + q.getY() * w.getZ() - q.getZ() * w.getY(),
+               q.getW() * w.getY() + q.getZ() * w.getX() - q.getX() * w.getZ(),
+               q.getW() * w.getZ() + q.getX() * w.getY() - q.getY() * w.getX(),
+               -q.getX() * w.getX() - q.getY() * w.getY() - q.getZ() * w.getZ());
+#endif
+}
+
+B3_FORCE_INLINE b3Quaternion
+operator*(const b3Vector3& w, const b3Quaternion& q)
+{
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+       __m128 vQ1 = w.get128();
+       __m128 vQ2 = q.get128();
+       __m128 A1, B1, A2, B2, A3, B3;
+
+       A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(0, 1, 2, 0));  // X Y  z x
+       B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3, 3, 3, 0));  // W W  W X
+
+       A1 = A1 * B1;
+
+       A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1, 2, 0, 1));
+       B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1));
+
+       A2 = A2 * B2;
+
+       A3 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2, 0, 1, 2));
+       B3 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2));
+
+       A3 = A3 * B3;  //       A3 *= B3
+
+       A1 = A1 + A2;                  //       AB12
+       A1 = _mm_xor_ps(A1, b3vPPPM);  //       change sign of the last element
+       A1 = A1 - A3;                  //       AB123 = AB12 - AB3
+
+       return b3Quaternion(A1);
+
+#elif defined(B3_USE_NEON)
+
+       float32x4_t vQ1 = w.get128();
+       float32x4_t vQ2 = q.get128();
+       float32x4_t A1, B1, A2, B2, A3, B3;
+       float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+       {
+               float32x2x2_t tmp;
+
+               tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1));  // {z x}, {w y}
+               vQ1zx = tmp.val[0];
+
+               tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2));  // {z x}, {w y}
+               vQ2zx = tmp.val[0];
+       }
+       vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+       vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+       vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+       vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+       A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx);                     // X Y  z x
+       B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx);  // W W  W X
+
+       A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+       B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+       A3 = vcombine_f32(vQ1zx, vQ1yz);  // Z X Y Z
+       B3 = vcombine_f32(vQ2yz, vQ2xz);  // Y Z x z
+
+       A1 = vmulq_f32(A1, B1);
+       A2 = vmulq_f32(A2, B2);
+       A3 = vmulq_f32(A3, B3);  //     A3 *= B3
+
+       A1 = vaddq_f32(A1, A2);  //     AB12 = AB1 + AB2
+
+       //      change the sign of the last element
+       A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
+
+       A1 = vsubq_f32(A1, A3);  //     AB123 = AB12 - AB3
+
+       return b3Quaternion(A1);
+
+#else
+       return b3Quaternion(
+               +w.getX() * q.getW() + w.getY() * q.getZ() - w.getZ() * q.getY(),
+               +w.getY() * q.getW() + w.getZ() * q.getX() - w.getX() * q.getZ(),
+               +w.getZ() * q.getW() + w.getX() * q.getY() - w.getY() * q.getX(),
+               -w.getX() * q.getX() - w.getY() * q.getY() - w.getZ() * q.getZ());
+#endif
+}
+
+/**@brief Calculate the dot product between two quaternions */
+B3_FORCE_INLINE b3Scalar
+b3Dot(const b3Quaternion& q1, const b3Quaternion& q2)
+{
+       return q1.dot(q2);
+}
+
+/**@brief Return the length of a quaternion */
+B3_FORCE_INLINE b3Scalar
+b3Length(const b3Quaternion& q)
+{
+       return q.length();
+}
+
+/**@brief Return the angle between two quaternions*/
+B3_FORCE_INLINE b3Scalar
+b3Angle(const b3Quaternion& q1, const b3Quaternion& q2)
+{
+       return q1.angle(q2);
+}
+
+/**@brief Return the inverse of a quaternion*/
+B3_FORCE_INLINE b3Quaternion
+b3Inverse(const b3Quaternion& q)
+{
+       return q.inverse();
+}
+
+/**@brief Return the result of spherical linear interpolation betwen two quaternions 
+ * @param q1 The first quaternion
+ * @param q2 The second quaternion 
+ * @param t The ration between q1 and q2.  t = 0 return q1, t=1 returns q2 
+ * Slerp assumes constant velocity between positions. */
+B3_FORCE_INLINE b3Quaternion
+b3Slerp(const b3Quaternion& q1, const b3Quaternion& q2, const b3Scalar& t)
+{
+       return q1.slerp(q2, t);
+}
+
+B3_FORCE_INLINE b3Quaternion
+b3QuatMul(const b3Quaternion& rot0, const b3Quaternion& rot1)
+{
+       return rot0 * rot1;
+}
+
+B3_FORCE_INLINE b3Quaternion
+b3QuatNormalized(const b3Quaternion& orn)
+{
+       return orn.normalized();
+}
+
+B3_FORCE_INLINE b3Vector3
+b3QuatRotate(const b3Quaternion& rotation, const b3Vector3& v)
+{
+       b3Quaternion q = rotation * v;
+       q *= rotation.inverse();
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+       return b3MakeVector3(_mm_and_ps(q.get128(), b3vFFF0fMask));
+#elif defined(B3_USE_NEON)
+       return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), b3vFFF0Mask));
+#else
+       return b3MakeVector3(q.getX(), q.getY(), q.getZ());
+#endif
+}
+
+B3_FORCE_INLINE b3Quaternion
+b3ShortestArcQuat(const b3Vector3& v0, const b3Vector3& v1)  // Game Programming Gems 2.10. make sure v0,v1 are normalized
+{
+       b3Vector3 c = v0.cross(v1);
+       b3Scalar d = v0.dot(v1);
+
+       if (d < -1.0 + B3_EPSILON)
+       {
+               b3Vector3 n, unused;
+               b3PlaneSpace1(v0, n, unused);
+               return b3Quaternion(n.getX(), n.getY(), n.getZ(), 0.0f);  // just pick any vector that is orthogonal to v0
+       }
+
+       b3Scalar s = b3Sqrt((1.0f + d) * 2.0f);
+       b3Scalar rs = 1.0f / s;
+
+       return b3Quaternion(c.getX() * rs, c.getY() * rs, c.getZ() * rs, s * 0.5f);
+}
+
+B3_FORCE_INLINE b3Quaternion
+b3ShortestArcQuatNormalize2(b3Vector3& v0, b3Vector3& v1)
+{
+       v0.normalize();
+       v1.normalize();
+       return b3ShortestArcQuat(v0, v1);
+}
+
+#endif  //B3_SIMD__QUATERNION_H_
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3Random.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3Random.h
new file mode 100644 (file)
index 0000000..c2e2149
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_GEN_RANDOM_H
+#define B3_GEN_RANDOM_H
+
+#include "b3Scalar.h"
+
+#ifdef MT19937
+
+#include <limits.h>
+#include <mt19937.h>
+
+#define B3_RAND_MAX UINT_MAX
+
+B3_FORCE_INLINE void b3Srand(unsigned int seed) { init_genrand(seed); }
+B3_FORCE_INLINE unsigned int b3rand() { return genrand_int32(); }
+
+#else
+
+#include <stdlib.h>
+
+#define B3_RAND_MAX RAND_MAX
+
+B3_FORCE_INLINE void b3Srand(unsigned int seed) { srand(seed); }
+B3_FORCE_INLINE unsigned int b3rand() { return rand(); }
+
+#endif
+
+inline b3Scalar b3RandRange(b3Scalar minRange, b3Scalar maxRange)
+{
+       return (b3rand() / (b3Scalar(B3_RAND_MAX) + b3Scalar(1.0))) * (maxRange - minRange) + minRange;
+}
+
+#endif  //B3_GEN_RANDOM_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3ResizablePool.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3ResizablePool.h
new file mode 100644 (file)
index 0000000..cafe3ff
--- /dev/null
@@ -0,0 +1,171 @@
+
+#ifndef B3_RESIZABLE_POOL_H
+#define B3_RESIZABLE_POOL_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+enum
+{
+       B3_POOL_HANDLE_TERMINAL_FREE = -1,
+       B3_POOL_HANDLE_TERMINAL_USED = -2
+};
+
+template <typename U>
+struct b3PoolBodyHandle : public U
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       int m_nextFreeHandle;
+       void setNextFree(int next)
+       {
+               m_nextFreeHandle = next;
+       }
+       int getNextFree() const
+       {
+               return m_nextFreeHandle;
+       }
+};
+
+template <typename T>
+class b3ResizablePool
+{
+protected:
+       b3AlignedObjectArray<T> m_bodyHandles;
+       int m_numUsedHandles;   // number of active handles
+       int m_firstFreeHandle;  // free handles list
+
+       T* getHandleInternal(int handle)
+       {
+               return &m_bodyHandles[handle];
+       }
+       const T* getHandleInternal(int handle) const
+       {
+               return &m_bodyHandles[handle];
+       }
+
+public:
+       b3ResizablePool()
+       {
+               initHandles();
+       }
+
+       virtual ~b3ResizablePool()
+       {
+               exitHandles();
+       }
+       ///handle management
+
+       int getNumHandles() const
+       {
+               return m_bodyHandles.size();
+       }
+
+       void getUsedHandles(b3AlignedObjectArray<int>& usedHandles) const
+       {
+               for (int i = 0; i < m_bodyHandles.size(); i++)
+               {
+                       if (m_bodyHandles[i].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
+                       {
+                               usedHandles.push_back(i);
+                       }
+               }
+       }
+
+       T* getHandle(int handle)
+       {
+               b3Assert(handle >= 0);
+               b3Assert(handle < m_bodyHandles.size());
+               if ((handle < 0) || (handle >= m_bodyHandles.size()))
+               {
+                       return 0;
+               }
+
+               if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
+               {
+                       return &m_bodyHandles[handle];
+               }
+               return 0;
+       }
+       const T* getHandle(int handle) const
+       {
+               b3Assert(handle >= 0);
+               b3Assert(handle < m_bodyHandles.size());
+               if ((handle < 0) || (handle >= m_bodyHandles.size()))
+               {
+                       return 0;
+               }
+
+               if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
+               {
+                       return &m_bodyHandles[handle];
+               }
+               return 0;
+       }
+
+       void increaseHandleCapacity(int extraCapacity)
+       {
+               int curCapacity = m_bodyHandles.size();
+               //b3Assert(curCapacity == m_numUsedHandles);
+               int newCapacity = curCapacity + extraCapacity;
+               m_bodyHandles.resize(newCapacity);
+
+               {
+                       for (int i = curCapacity; i < newCapacity; i++)
+                               m_bodyHandles[i].setNextFree(i + 1);
+
+                       m_bodyHandles[newCapacity - 1].setNextFree(-1);
+               }
+               m_firstFreeHandle = curCapacity;
+       }
+       void initHandles()
+       {
+               m_numUsedHandles = 0;
+               m_firstFreeHandle = -1;
+
+               increaseHandleCapacity(1);
+       }
+
+       void exitHandles()
+       {
+               m_bodyHandles.resize(0);
+               m_firstFreeHandle = -1;
+               m_numUsedHandles = 0;
+       }
+
+       int allocHandle()
+       {
+               b3Assert(m_firstFreeHandle >= 0);
+
+               int handle = m_firstFreeHandle;
+               m_firstFreeHandle = getHandleInternal(handle)->getNextFree();
+               m_numUsedHandles++;
+
+               if (m_firstFreeHandle < 0)
+               {
+                       //int curCapacity = m_bodyHandles.size();
+                       int additionalCapacity = m_bodyHandles.size();
+                       increaseHandleCapacity(additionalCapacity);
+
+                       getHandleInternal(handle)->setNextFree(m_firstFreeHandle);
+               }
+               getHandleInternal(handle)->setNextFree(B3_POOL_HANDLE_TERMINAL_USED);
+               getHandleInternal(handle)->clear();
+               return handle;
+       }
+
+       void freeHandle(int handle)
+       {
+               b3Assert(handle >= 0);
+
+               if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
+               {
+                       getHandleInternal(handle)->clear();
+                       getHandleInternal(handle)->setNextFree(m_firstFreeHandle);
+                       m_firstFreeHandle = handle;
+                       m_numUsedHandles--;
+               }
+       }
+};
+///end handle management
+
+#endif  //B3_RESIZABLE_POOL_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3Scalar.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3Scalar.h
new file mode 100644 (file)
index 0000000..eeb70ed
--- /dev/null
@@ -0,0 +1,689 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_SCALAR_H
+#define B3_SCALAR_H
+
+#ifdef B3_MANAGED_CODE
+//Aligned data types not supported in managed code
+#pragma unmanaged
+#endif
+
+#include <math.h>
+#include <stdlib.h>  //size_t for MSVC 6.0
+#include <float.h>
+
+//Original repository is at http://github.com/erwincoumans/bullet3
+#define B3_BULLET_VERSION 300
+
+inline int b3GetVersion()
+{
+       return B3_BULLET_VERSION;
+}
+
+#if defined(DEBUG) || defined(_DEBUG)
+#define B3_DEBUG
+#endif
+
+#include "b3Logging.h"  //for b3Error
+
+#ifdef _WIN32
+
+#if  defined(__GNUC__) // it should handle both MINGW and CYGWIN
+#define B3_FORCE_INLINE             __inline__ __attribute__((always_inline))
+#define B3_ATTRIBUTE_ALIGNED16(a)   a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a)   a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a)  a __attribute__((aligned(128)))
+#elif ( defined(_MSC_VER) && _MSC_VER < 1300 )
+#define B3_FORCE_INLINE inline
+#define B3_ATTRIBUTE_ALIGNED16(a) a
+#define B3_ATTRIBUTE_ALIGNED64(a) a
+#define B3_ATTRIBUTE_ALIGNED128(a) a
+#else
+//#define B3_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 B3_FORCE_INLINE __forceinline
+#define B3_ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
+#define B3_ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
+#define B3_ATTRIBUTE_ALIGNED128(a) __declspec(align(128)) a
+#ifdef _XBOX
+#define B3_USE_VMX128
+
+#include <ppcintrinsics.h>
+#define B3_HAVE_NATIVE_FSEL
+#define b3Fsel(a, b, c) __fsel((a), (b), (c))
+#else
+
+#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(B3_USE_DOUBLE_PRECISION))
+#if (defined(_M_IX86) || defined(_M_X64))
+
+
+#ifdef __clang__
+//#define B3_NO_SIMD_OPERATOR_OVERLOADS
+#define B3_DISABLE_SSE
+#endif //__clang__
+
+#ifndef B3_DISABLE_SSE
+#define B3_USE_SSE
+#endif //B3_DISABLE_SSE
+
+#ifdef B3_USE_SSE
+//B3_USE_SSE_IN_API is disabled under Windows by default, because
+//it makes it harder to integrate Bullet into your application under Windows
+//(structured embedding Bullet structs/classes need to be 16-byte aligned)
+//with relatively little performance gain
+//If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries
+//you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage)
+//#define B3_USE_SSE_IN_API
+#endif  //B3_USE_SSE
+#include <emmintrin.h>
+#endif
+#endif
+
+#endif  //_XBOX
+
+#endif  //__MINGW32__
+
+#ifdef B3_DEBUG
+#ifdef _MSC_VER
+#include <stdio.h>
+#define b3Assert(x) { if(!(x)){b3Error("Assert " __FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak();  }}
+#else  //_MSC_VER
+#include <assert.h>
+#define b3Assert assert
+#endif  //_MSC_VER
+#else
+#define b3Assert(x)
+#endif
+//b3FullAssert is optional, slows down a lot
+#define b3FullAssert(x)
+
+#define b3Likely(_c) _c
+#define b3Unlikely(_c) _c
+
+#else
+
+#if defined(__CELLOS_LV2__)
+#define B3_FORCE_INLINE inline __attribute__((always_inline))
+#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#ifndef assert
+#include <assert.h>
+#endif
+#ifdef B3_DEBUG
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+#define b3Assert(x)               \
+       {                             \
+               if (!(x))                 \
+               {                         \
+                       b3Error(              \
+                               "Assert "__FILE__ \
+                               ":%u (" #x ")\n", \
+                               __LINE__);        \
+                       spu_hcmpeq(0, 0);     \
+               }                         \
+       }
+#else
+#define b3Assert assert
+#endif
+
+#else
+#define b3Assert(x)
+#endif
+//b3FullAssert is optional, slows down a lot
+#define b3FullAssert(x)
+
+#define b3Likely(_c) _c
+#define b3Unlikely(_c) _c
+
+#else
+
+#ifdef USE_LIBSPE2
+
+#define B3_FORCE_INLINE __inline
+#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#ifndef assert
+#include <assert.h>
+#endif
+#ifdef B3_DEBUG
+#define b3Assert assert
+#else
+#define b3Assert(x)
+#endif
+//b3FullAssert is optional, slows down a lot
+#define b3FullAssert(x)
+
+#define b3Likely(_c) __builtin_expect((_c), 1)
+#define b3Unlikely(_c) __builtin_expect((_c), 0)
+
+#else
+//non-windows systems
+
+#if (defined(__APPLE__) && (!defined(B3_USE_DOUBLE_PRECISION)))
+#if defined(__i386__) || defined(__x86_64__)
+#define B3_USE_SSE
+//B3_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries
+//if apps run into issues, we will disable the next line
+#define B3_USE_SSE_IN_API
+#ifdef B3_USE_SSE
+// include appropriate SSE level
+#if defined(__SSE4_1__)
+#include <smmintrin.h>
+#elif defined(__SSSE3__)
+#include <tmmintrin.h>
+#elif defined(__SSE3__)
+#include <pmmintrin.h>
+#else
+#include <emmintrin.h>
+#endif
+#endif  //B3_USE_SSE
+#elif defined(__armv7__)
+#ifdef __clang__
+#define B3_USE_NEON 1
+
+#if defined B3_USE_NEON && defined(__clang__)
+#include <arm_neon.h>
+#endif  //B3_USE_NEON
+#endif  //__clang__
+#endif  //__arm__
+
+#define B3_FORCE_INLINE inline __attribute__((always_inline))
+///@todo: check out alignment methods for other platforms/compilers
+#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+#ifndef assert
+#include <assert.h>
+#endif
+
+#if defined(DEBUG) || defined(_DEBUG)
+#if defined(__i386__) || defined(__x86_64__)
+#include <stdio.h>
+#define b3Assert(x)                                                             \
+       {                                                                           \
+               if (!(x))                                                               \
+               {                                                                       \
+                       b3Error("Assert %s in line %d, file %s\n", #x, __LINE__, __FILE__); \
+                       asm volatile("int3");                                               \
+               }                                                                       \
+       }
+#else  //defined (__i386__) || defined (__x86_64__)
+#define b3Assert assert
+#endif  //defined (__i386__) || defined (__x86_64__)
+#else   //defined(DEBUG) || defined (_DEBUG)
+#define b3Assert(x)
+#endif  //defined(DEBUG) || defined (_DEBUG)
+
+//b3FullAssert is optional, slows down a lot
+#define b3FullAssert(x)
+#define b3Likely(_c) _c
+#define b3Unlikely(_c) _c
+
+#else
+
+#define B3_FORCE_INLINE inline
+///@todo: check out alignment methods for other platforms/compilers
+#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
+#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
+#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
+///#define B3_ATTRIBUTE_ALIGNED16(a) a
+///#define B3_ATTRIBUTE_ALIGNED64(a) a
+///#define B3_ATTRIBUTE_ALIGNED128(a) a
+#ifndef assert
+#include <assert.h>
+#endif
+
+#if defined(DEBUG) || defined(_DEBUG)
+#define b3Assert assert
+#else
+#define b3Assert(x)
+#endif
+
+//b3FullAssert is optional, slows down a lot
+#define b3FullAssert(x)
+#define b3Likely(_c) _c
+#define b3Unlikely(_c) _c
+#endif  //__APPLE__
+
+#endif  // LIBSPE2
+
+#endif  //__CELLOS_LV2__
+#endif
+
+///The b3Scalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
+#if defined(B3_USE_DOUBLE_PRECISION)
+typedef double b3Scalar;
+//this number could be bigger in double precision
+#define B3_LARGE_FLOAT 1e30
+#else
+typedef float b3Scalar;
+//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX
+#define B3_LARGE_FLOAT 1e18f
+#endif
+
+#ifdef B3_USE_SSE
+typedef __m128 b3SimdFloat4;
+#endif  //B3_USE_SSE
+
+#if defined B3_USE_SSE_IN_API && defined(B3_USE_SSE)
+#ifdef _WIN32
+
+#ifndef B3_NAN
+static int b3NanMask = 0x7F800001;
+#define B3_NAN (*(float *)&b3NanMask)
+#endif
+
+#ifndef B3_INFINITY_MASK
+static int b3InfinityMask = 0x7F800000;
+#define B3_INFINITY_MASK (*(float *)&b3InfinityMask)
+#endif
+#ifndef B3_NO_SIMD_OPERATOR_OVERLOADS
+inline __m128 operator+(const __m128 A, const __m128 B)
+{
+       return _mm_add_ps(A, B);
+}
+
+inline __m128 operator-(const __m128 A, const __m128 B)
+{
+       return _mm_sub_ps(A, B);
+}
+
+inline __m128 operator*(const __m128 A, const __m128 B)
+{
+       return _mm_mul_ps(A, B);
+}
+#endif //B3_NO_SIMD_OPERATOR_OVERLOADS
+#define b3CastfTo128i(a) (_mm_castps_si128(a))
+#define b3CastfTo128d(a) (_mm_castps_pd(a))
+#define b3CastiTo128f(a) (_mm_castsi128_ps(a))
+#define b3CastdTo128f(a) (_mm_castpd_ps(a))
+#define b3CastdTo128i(a) (_mm_castpd_si128(a))
+#define b3Assign128(r0, r1, r2, r3) _mm_setr_ps(r0, r1, r2, r3)
+
+#else  //_WIN32
+
+#define b3CastfTo128i(a) ((__m128i)(a))
+#define b3CastfTo128d(a) ((__m128d)(a))
+#define b3CastiTo128f(a) ((__m128)(a))
+#define b3CastdTo128f(a) ((__m128)(a))
+#define b3CastdTo128i(a) ((__m128i)(a))
+#define b3Assign128(r0, r1, r2, r3) \
+       (__m128) { r0, r1, r2, r3 }
+#endif  //_WIN32
+#endif  //B3_USE_SSE_IN_API
+
+#ifdef B3_USE_NEON
+#include <arm_neon.h>
+
+typedef float32x4_t b3SimdFloat4;
+#define B3_INFINITY INFINITY
+#define B3_NAN NAN
+#define b3Assign128(r0, r1, r2, r3) \
+       (float32x4_t) { r0, r1, r2, r3 }
+#endif
+
+#define B3_DECLARE_ALIGNED_ALLOCATOR()                                                                   \
+       B3_FORCE_INLINE void *operator new(size_t sizeInBytes) { return b3AlignedAlloc(sizeInBytes, 16); }   \
+       B3_FORCE_INLINE void operator delete(void *ptr) { b3AlignedFree(ptr); }                              \
+       B3_FORCE_INLINE void *operator new(size_t, void *ptr) { return ptr; }                                \
+       B3_FORCE_INLINE void operator delete(void *, void *) {}                                              \
+       B3_FORCE_INLINE void *operator new[](size_t sizeInBytes) { return b3AlignedAlloc(sizeInBytes, 16); } \
+       B3_FORCE_INLINE void operator delete[](void *ptr) { b3AlignedFree(ptr); }                            \
+       B3_FORCE_INLINE void *operator new[](size_t, void *ptr) { return ptr; }                              \
+       B3_FORCE_INLINE void operator delete[](void *, void *) {}
+
+#if defined(B3_USE_DOUBLE_PRECISION) || defined(B3_FORCE_DOUBLE_FUNCTIONS)
+
+B3_FORCE_INLINE b3Scalar b3Sqrt(b3Scalar x)
+{
+       return sqrt(x);
+}
+B3_FORCE_INLINE b3Scalar b3Fabs(b3Scalar x) { return fabs(x); }
+B3_FORCE_INLINE b3Scalar b3Cos(b3Scalar x) { return cos(x); }
+B3_FORCE_INLINE b3Scalar b3Sin(b3Scalar x) { return sin(x); }
+B3_FORCE_INLINE b3Scalar b3Tan(b3Scalar x) { return tan(x); }
+B3_FORCE_INLINE b3Scalar b3Acos(b3Scalar x)
+{
+       if (x < b3Scalar(-1)) x = b3Scalar(-1);
+       if (x > b3Scalar(1)) x = b3Scalar(1);
+       return acos(x);
+}
+B3_FORCE_INLINE b3Scalar b3Asin(b3Scalar x)
+{
+       if (x < b3Scalar(-1)) x = b3Scalar(-1);
+       if (x > b3Scalar(1)) x = b3Scalar(1);
+       return asin(x);
+}
+B3_FORCE_INLINE b3Scalar b3Atan(b3Scalar x) { return atan(x); }
+B3_FORCE_INLINE b3Scalar b3Atan2(b3Scalar x, b3Scalar y) { return atan2(x, y); }
+B3_FORCE_INLINE b3Scalar b3Exp(b3Scalar x) { return exp(x); }
+B3_FORCE_INLINE b3Scalar b3Log(b3Scalar x) { return log(x); }
+B3_FORCE_INLINE b3Scalar b3Pow(b3Scalar x, b3Scalar y) { return pow(x, y); }
+B3_FORCE_INLINE b3Scalar b3Fmod(b3Scalar x, b3Scalar y) { return fmod(x, y); }
+
+#else
+
+B3_FORCE_INLINE b3Scalar b3Sqrt(b3Scalar 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 * b3Scalar(0.5);
+       x = (b3Scalar(1.5) * x) - (x * x) * (x * z); /* iteration formula     */
+       x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
+       x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
+       x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
+       x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
+       return x * y;
+#else
+       return sqrtf(y);
+#endif
+}
+B3_FORCE_INLINE b3Scalar b3Fabs(b3Scalar x) { return fabsf(x); }
+B3_FORCE_INLINE b3Scalar b3Cos(b3Scalar x) { return cosf(x); }
+B3_FORCE_INLINE b3Scalar b3Sin(b3Scalar x) { return sinf(x); }
+B3_FORCE_INLINE b3Scalar b3Tan(b3Scalar x) { return tanf(x); }
+B3_FORCE_INLINE b3Scalar b3Acos(b3Scalar x)
+{
+       if (x < b3Scalar(-1))
+               x = b3Scalar(-1);
+       if (x > b3Scalar(1))
+               x = b3Scalar(1);
+       return acosf(x);
+}
+B3_FORCE_INLINE b3Scalar b3Asin(b3Scalar x)
+{
+       if (x < b3Scalar(-1))
+               x = b3Scalar(-1);
+       if (x > b3Scalar(1))
+               x = b3Scalar(1);
+       return asinf(x);
+}
+B3_FORCE_INLINE b3Scalar b3Atan(b3Scalar x) { return atanf(x); }
+B3_FORCE_INLINE b3Scalar b3Atan2(b3Scalar x, b3Scalar y) { return atan2f(x, y); }
+B3_FORCE_INLINE b3Scalar b3Exp(b3Scalar x) { return expf(x); }
+B3_FORCE_INLINE b3Scalar b3Log(b3Scalar x) { return logf(x); }
+B3_FORCE_INLINE b3Scalar b3Pow(b3Scalar x, b3Scalar y) { return powf(x, y); }
+B3_FORCE_INLINE b3Scalar b3Fmod(b3Scalar x, b3Scalar y) { return fmodf(x, y); }
+
+#endif
+
+#define B3_2_PI b3Scalar(6.283185307179586232)
+#define B3_PI (B3_2_PI * b3Scalar(0.5))
+#define B3_HALF_PI (B3_2_PI * b3Scalar(0.25))
+#define B3_RADS_PER_DEG (B3_2_PI / b3Scalar(360.0))
+#define B3_DEGS_PER_RAD (b3Scalar(360.0) / B3_2_PI)
+#define B3_SQRT12 b3Scalar(0.7071067811865475244008443621048490)
+
+#define b3RecipSqrt(x) ((b3Scalar)(b3Scalar(1.0) / b3Sqrt(b3Scalar(x)))) /* reciprocal square root */
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define B3_EPSILON DBL_EPSILON
+#define B3_INFINITY DBL_MAX
+#else
+#define B3_EPSILON FLT_EPSILON
+#define B3_INFINITY FLT_MAX
+#endif
+
+B3_FORCE_INLINE b3Scalar b3Atan2Fast(b3Scalar y, b3Scalar x)
+{
+       b3Scalar coeff_1 = B3_PI / 4.0f;
+       b3Scalar coeff_2 = 3.0f * coeff_1;
+       b3Scalar abs_y = b3Fabs(y);
+       b3Scalar angle;
+       if (x >= 0.0f)
+       {
+               b3Scalar r = (x - abs_y) / (x + abs_y);
+               angle = coeff_1 - coeff_1 * r;
+       }
+       else
+       {
+               b3Scalar r = (x + abs_y) / (abs_y - x);
+               angle = coeff_2 - coeff_1 * r;
+       }
+       return (y < 0.0f) ? -angle : angle;
+}
+
+B3_FORCE_INLINE bool b3FuzzyZero(b3Scalar x) { return b3Fabs(x) < B3_EPSILON; }
+
+B3_FORCE_INLINE bool b3Equal(b3Scalar a, b3Scalar eps)
+{
+       return (((a) <= eps) && !((a) < -eps));
+}
+B3_FORCE_INLINE bool b3GreaterEqual(b3Scalar a, b3Scalar eps)
+{
+       return (!((a) <= eps));
+}
+
+B3_FORCE_INLINE int b3IsNegative(b3Scalar x)
+{
+       return x < b3Scalar(0.0) ? 1 : 0;
+}
+
+B3_FORCE_INLINE b3Scalar b3Radians(b3Scalar x) { return x * B3_RADS_PER_DEG; }
+B3_FORCE_INLINE b3Scalar b3Degrees(b3Scalar x) { return x * B3_DEGS_PER_RAD; }
+
+#define B3_DECLARE_HANDLE(name) \
+       typedef struct name##__     \
+       {                           \
+               int unused;             \
+       } * name
+
+#ifndef b3Fsel
+B3_FORCE_INLINE b3Scalar b3Fsel(b3Scalar a, b3Scalar b, b3Scalar c)
+{
+       return a >= 0 ? b : c;
+}
+#endif
+#define b3Fsels(a, b, c) (b3Scalar) b3Fsel(a, b, c)
+
+B3_FORCE_INLINE bool b3MachineIsLittleEndian()
+{
+       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;
+}
+
+///b3Select 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
+B3_FORCE_INLINE unsigned b3Select(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));
+}
+B3_FORCE_INLINE int b3Select(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));
+}
+B3_FORCE_INLINE float b3Select(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
+{
+#ifdef B3_HAVE_NATIVE_FSEL
+       return (float)b3Fsel((b3Scalar)condition - b3Scalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
+#else
+       return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
+#endif
+}
+
+template <typename T>
+B3_FORCE_INLINE void b3Swap(T &a, T &b)
+{
+       T tmp = a;
+       a = b;
+       b = tmp;
+}
+
+//PCK: endian swapping functions
+B3_FORCE_INLINE unsigned b3SwapEndian(unsigned val)
+{
+       return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
+}
+
+B3_FORCE_INLINE unsigned short b3SwapEndian(unsigned short val)
+{
+       return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
+}
+
+B3_FORCE_INLINE unsigned b3SwapEndian(int val)
+{
+       return b3SwapEndian((unsigned)val);
+}
+
+B3_FORCE_INLINE unsigned short b3SwapEndian(short val)
+{
+       return b3SwapEndian((unsigned short)val);
+}
+
+///b3SwapFloat uses using char pointers to swap the endianness
+////b3SwapFloat/b3SwapDouble 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
+B3_FORCE_INLINE unsigned int b3SwapEndianFloat(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
+B3_FORCE_INLINE float b3UnswapEndianFloat(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
+B3_FORCE_INLINE void b3SwapEndianDouble(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
+B3_FORCE_INLINE double b3UnswapEndianDouble(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;
+}
+
+// returns normalized value in range [-B3_PI, B3_PI]
+B3_FORCE_INLINE b3Scalar b3NormalizeAngle(b3Scalar angleInRadians)
+{
+       angleInRadians = b3Fmod(angleInRadians, B3_2_PI);
+       if (angleInRadians < -B3_PI)
+       {
+               return angleInRadians + B3_2_PI;
+       }
+       else if (angleInRadians > B3_PI)
+       {
+               return angleInRadians - B3_2_PI;
+       }
+       else
+       {
+               return angleInRadians;
+       }
+}
+
+///rudimentary class to provide type info
+struct b3TypedObject
+{
+       b3TypedObject(int objectType)
+               : m_objectType(objectType)
+       {
+       }
+       int m_objectType;
+       inline int getObjectType() const
+       {
+               return m_objectType;
+       }
+};
+
+///align a pointer to the provided alignment, upwards
+template <typename T>
+T *b3AlignPointer(T *unalignedPtr, size_t alignment)
+{
+       struct b3ConvertPointerSizeT
+       {
+               union {
+                       T *ptr;
+                       size_t integer;
+               };
+       };
+       b3ConvertPointerSizeT converter;
+
+       const size_t bit_mask = ~(alignment - 1);
+       converter.ptr = unalignedPtr;
+       converter.integer += alignment - 1;
+       converter.integer &= bit_mask;
+       return converter.ptr;
+}
+
+#endif  //B3_SCALAR_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3StackAlloc.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3StackAlloc.h
new file mode 100644 (file)
index 0000000..4972236
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson
+Nov.2006
+*/
+
+#ifndef B3_STACK_ALLOC
+#define B3_STACK_ALLOC
+
+#include "b3Scalar.h"  //for b3Assert
+#include "b3AlignedAllocator.h"
+
+///The b3Block class is an internal structure for the b3StackAlloc memory allocator.
+struct b3Block
+{
+       b3Block* previous;
+       unsigned char* address;
+};
+
+///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
+class b3StackAlloc
+{
+public:
+       b3StackAlloc(unsigned int size)
+       {
+               ctor();
+               create(size);
+       }
+       ~b3StackAlloc() { destroy(); }
+
+       inline void create(unsigned int size)
+       {
+               destroy();
+               data = (unsigned char*)b3AlignedAlloc(size, 16);
+               totalsize = size;
+       }
+       inline void destroy()
+       {
+               b3Assert(usedsize == 0);
+               //Raise(L"StackAlloc is still in use");
+
+               if (usedsize == 0)
+               {
+                       if (!ischild && data)
+                               b3AlignedFree(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);
+               if (nus < totalsize)
+               {
+                       usedsize = nus;
+                       return (data + (usedsize - size));
+               }
+               b3Assert(0);
+               //&& (L"Not enough memory"));
+
+               return (0);
+       }
+       B3_FORCE_INLINE b3Block* beginBlock()
+       {
+               b3Block* pb = (b3Block*)allocate(sizeof(b3Block));
+               pb->previous = current;
+               pb->address = data + usedsize;
+               current = pb;
+               return (pb);
+       }
+       B3_FORCE_INLINE void endBlock(b3Block* block)
+       {
+               b3Assert(block == current);
+               //Raise(L"Unmatched blocks");
+               if (block == current)
+               {
+                       current = block->previous;
+                       usedsize = (unsigned int)((block->address - data) - sizeof(b3Block));
+               }
+       }
+
+private:
+       void ctor()
+       {
+               data = 0;
+               totalsize = 0;
+               usedsize = 0;
+               current = 0;
+               ischild = false;
+       }
+       unsigned char* data;
+       unsigned int totalsize;
+       unsigned int usedsize;
+       b3Block* current;
+       bool ischild;
+};
+
+#endif  //B3_STACK_ALLOC
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3Transform.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3Transform.h
new file mode 100644 (file)
index 0000000..149da9d
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_TRANSFORM_H
+#define B3_TRANSFORM_H
+
+#include "b3Matrix3x3.h"
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define b3TransformData b3TransformDoubleData
+#else
+#define b3TransformData b3TransformFloatData
+#endif
+
+/**@brief The b3Transform class supports rigid transforms with only translation and rotation and no scaling/shear.
+ *It can be used in combination with b3Vector3, b3Quaternion and b3Matrix3x3 linear algebra classes. */
+B3_ATTRIBUTE_ALIGNED16(class)
+b3Transform
+{
+       ///Storage for the rotation
+       b3Matrix3x3 m_basis;
+       ///Storage for the translation
+       b3Vector3 m_origin;
+
+public:
+       /**@brief No initialization constructor */
+       b3Transform() {}
+       /**@brief Constructor from b3Quaternion (optional b3Vector3 )
+   * @param q Rotation from quaternion 
+   * @param c Translation from Vector (default 0,0,0) */
+       explicit B3_FORCE_INLINE b3Transform(const b3Quaternion& q,
+                                                                                const b3Vector3& c = b3MakeVector3(b3Scalar(0), b3Scalar(0), b3Scalar(0)))
+               : m_basis(q),
+                 m_origin(c)
+       {
+       }
+
+       /**@brief Constructor from b3Matrix3x3 (optional b3Vector3)
+   * @param b Rotation from Matrix 
+   * @param c Translation from Vector default (0,0,0)*/
+       explicit B3_FORCE_INLINE b3Transform(const b3Matrix3x3& b,
+                                                                                const b3Vector3& c = b3MakeVector3(b3Scalar(0), b3Scalar(0), b3Scalar(0)))
+               : m_basis(b),
+                 m_origin(c)
+       {
+       }
+       /**@brief Copy constructor */
+       B3_FORCE_INLINE b3Transform(const b3Transform& other)
+               : m_basis(other.m_basis),
+                 m_origin(other.m_origin)
+       {
+       }
+       /**@brief Assignment Operator */
+       B3_FORCE_INLINE b3Transform& operator=(const b3Transform& other)
+       {
+               m_basis = other.m_basis;
+               m_origin = other.m_origin;
+               return *this;
+       }
+
+       /**@brief Set the current transform as the value of the product of two transforms
+   * @param t1 Transform 1
+   * @param t2 Transform 2
+   * This = Transform1 * Transform2 */
+       B3_FORCE_INLINE void mult(const b3Transform& t1, const b3Transform& t2)
+       {
+               m_basis = t1.m_basis * t2.m_basis;
+               m_origin = t1(t2.m_origin);
+       }
+
+       /*              void multInverseLeft(const b3Transform& t1, const b3Transform& t2) {
+                       b3Vector3 v = t2.m_origin - t1.m_origin;
+                       m_basis = b3MultTransposeLeft(t1.m_basis, t2.m_basis);
+                       m_origin = v * t1.m_basis;
+               }
+               */
+
+       /**@brief Return the transform of the vector */
+       B3_FORCE_INLINE b3Vector3 operator()(const b3Vector3& x) const
+       {
+               return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
+       }
+
+       /**@brief Return the transform of the vector */
+       B3_FORCE_INLINE b3Vector3 operator*(const b3Vector3& x) const
+       {
+               return (*this)(x);
+       }
+
+       /**@brief Return the transform of the b3Quaternion */
+       B3_FORCE_INLINE b3Quaternion operator*(const b3Quaternion& q) const
+       {
+               return getRotation() * q;
+       }
+
+       /**@brief Return the basis matrix for the rotation */
+       B3_FORCE_INLINE b3Matrix3x3& getBasis() { return m_basis; }
+       /**@brief Return the basis matrix for the rotation */
+       B3_FORCE_INLINE const b3Matrix3x3& getBasis() const { return m_basis; }
+
+       /**@brief Return the origin vector translation */
+       B3_FORCE_INLINE b3Vector3& getOrigin() { return m_origin; }
+       /**@brief Return the origin vector translation */
+       B3_FORCE_INLINE const b3Vector3& getOrigin() const { return m_origin; }
+
+       /**@brief Return a quaternion representing the rotation */
+       b3Quaternion getRotation() const
+       {
+               b3Quaternion q;
+               m_basis.getRotation(q);
+               return q;
+       }
+
+       /**@brief Set from an array 
+   * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+       void setFromOpenGLMatrix(const b3Scalar* m)
+       {
+               m_basis.setFromOpenGLSubMatrix(m);
+               m_origin.setValue(m[12], m[13], m[14]);
+       }
+
+       /**@brief Fill an array representation
+   * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+       void getOpenGLMatrix(b3Scalar * m) const
+       {
+               m_basis.getOpenGLSubMatrix(m);
+               m[12] = m_origin.getX();
+               m[13] = m_origin.getY();
+               m[14] = m_origin.getZ();
+               m[15] = b3Scalar(1.0);
+       }
+
+       /**@brief Set the translational element
+   * @param origin The vector to set the translation to */
+       B3_FORCE_INLINE void setOrigin(const b3Vector3& origin)
+       {
+               m_origin = origin;
+       }
+
+       B3_FORCE_INLINE b3Vector3 invXform(const b3Vector3& inVec) const;
+
+       /**@brief Set the rotational element by b3Matrix3x3 */
+       B3_FORCE_INLINE void setBasis(const b3Matrix3x3& basis)
+       {
+               m_basis = basis;
+       }
+
+       /**@brief Set the rotational element by b3Quaternion */
+       B3_FORCE_INLINE void setRotation(const b3Quaternion& q)
+       {
+               m_basis.setRotation(q);
+       }
+
+       /**@brief Set this transformation to the identity */
+       void setIdentity()
+       {
+               m_basis.setIdentity();
+               m_origin.setValue(b3Scalar(0.0), b3Scalar(0.0), b3Scalar(0.0));
+       }
+
+       /**@brief Multiply this Transform by another(this = this * another) 
+   * @param t The other transform */
+       b3Transform& operator*=(const b3Transform& t)
+       {
+               m_origin += m_basis * t.m_origin;
+               m_basis *= t.m_basis;
+               return *this;
+       }
+
+       /**@brief Return the inverse of this transform */
+       b3Transform inverse() const
+       {
+               b3Matrix3x3 inv = m_basis.transpose();
+               return b3Transform(inv, inv * -m_origin);
+       }
+
+       /**@brief Return the inverse of this transform times the other transform
+   * @param t The other transform 
+   * return this.inverse() * the other */
+       b3Transform inverseTimes(const b3Transform& t) const;
+
+       /**@brief Return the product of this transform and the other */
+       b3Transform operator*(const b3Transform& t) const;
+
+       /**@brief Return an identity transform */
+       static const b3Transform& getIdentity()
+       {
+               static const b3Transform identityTransform(b3Matrix3x3::getIdentity());
+               return identityTransform;
+       }
+
+       void serialize(struct b3TransformData & dataOut) const;
+
+       void serializeFloat(struct b3TransformFloatData & dataOut) const;
+
+       void deSerialize(const struct b3TransformData& dataIn);
+
+       void deSerializeDouble(const struct b3TransformDoubleData& dataIn);
+
+       void deSerializeFloat(const struct b3TransformFloatData& dataIn);
+};
+
+B3_FORCE_INLINE b3Vector3
+b3Transform::invXform(const b3Vector3& inVec) const
+{
+       b3Vector3 v = inVec - m_origin;
+       return (m_basis.transpose() * v);
+}
+
+B3_FORCE_INLINE b3Transform
+b3Transform::inverseTimes(const b3Transform& t) const
+{
+       b3Vector3 v = t.getOrigin() - m_origin;
+       return b3Transform(m_basis.transposeTimes(t.m_basis),
+                                          v * m_basis);
+}
+
+B3_FORCE_INLINE b3Transform
+       b3Transform::operator*(const b3Transform& t) const
+{
+       return b3Transform(m_basis * t.m_basis,
+                                          (*this)(t.m_origin));
+}
+
+/**@brief Test if two transforms have all elements equal */
+B3_FORCE_INLINE bool operator==(const b3Transform& t1, const b3Transform& t2)
+{
+       return (t1.getBasis() == t2.getBasis() &&
+                       t1.getOrigin() == t2.getOrigin());
+}
+
+///for serialization
+struct b3TransformFloatData
+{
+       b3Matrix3x3FloatData m_basis;
+       b3Vector3FloatData m_origin;
+};
+
+struct b3TransformDoubleData
+{
+       b3Matrix3x3DoubleData m_basis;
+       b3Vector3DoubleData m_origin;
+};
+
+B3_FORCE_INLINE void b3Transform::serialize(b3TransformData& dataOut) const
+{
+       m_basis.serialize(dataOut.m_basis);
+       m_origin.serialize(dataOut.m_origin);
+}
+
+B3_FORCE_INLINE void b3Transform::serializeFloat(b3TransformFloatData& dataOut) const
+{
+       m_basis.serializeFloat(dataOut.m_basis);
+       m_origin.serializeFloat(dataOut.m_origin);
+}
+
+B3_FORCE_INLINE void b3Transform::deSerialize(const b3TransformData& dataIn)
+{
+       m_basis.deSerialize(dataIn.m_basis);
+       m_origin.deSerialize(dataIn.m_origin);
+}
+
+B3_FORCE_INLINE void b3Transform::deSerializeFloat(const b3TransformFloatData& dataIn)
+{
+       m_basis.deSerializeFloat(dataIn.m_basis);
+       m_origin.deSerializeFloat(dataIn.m_origin);
+}
+
+B3_FORCE_INLINE void b3Transform::deSerializeDouble(const b3TransformDoubleData& dataIn)
+{
+       m_basis.deSerializeDouble(dataIn.m_basis);
+       m_origin.deSerializeDouble(dataIn.m_origin);
+}
+
+#endif  //B3_TRANSFORM_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3TransformUtil.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3TransformUtil.h
new file mode 100644 (file)
index 0000000..1850a9b
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_TRANSFORM_UTIL_H
+#define B3_TRANSFORM_UTIL_H
+
+#include "b3Transform.h"
+#define B3_ANGULAR_MOTION_THRESHOLD b3Scalar(0.5) * B3_HALF_PI
+
+B3_FORCE_INLINE b3Vector3 b3AabbSupport(const b3Vector3& halfExtents, const b3Vector3& supportDir)
+{
+       return b3MakeVector3(supportDir.getX() < b3Scalar(0.0) ? -halfExtents.getX() : halfExtents.getX(),
+                                                supportDir.getY() < b3Scalar(0.0) ? -halfExtents.getY() : halfExtents.getY(),
+                                                supportDir.getZ() < b3Scalar(0.0) ? -halfExtents.getZ() : halfExtents.getZ());
+}
+
+/// Utils related to temporal transforms
+class b3TransformUtil
+{
+public:
+       static void integrateTransform(const b3Transform& curTrans, const b3Vector3& linvel, const b3Vector3& angvel, b3Scalar timeStep, b3Transform& predictedTransform)
+       {
+               predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
+               //      #define QUATERNION_DERIVATIVE
+#ifdef QUATERNION_DERIVATIVE
+               b3Quaternion predictedOrn = curTrans.getRotation();
+               predictedOrn += (angvel * predictedOrn) * (timeStep * b3Scalar(0.5));
+               predictedOrn.normalize();
+#else
+               //Exponential map
+               //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
+
+               b3Vector3 axis;
+               b3Scalar fAngle = angvel.length();
+               //limit the angular motion
+               if (fAngle * timeStep > B3_ANGULAR_MOTION_THRESHOLD)
+               {
+                       fAngle = B3_ANGULAR_MOTION_THRESHOLD / timeStep;
+               }
+
+               if (fAngle < b3Scalar(0.001))
+               {
+                       // use Taylor's expansions of sync function
+                       axis = angvel * (b3Scalar(0.5) * timeStep - (timeStep * timeStep * timeStep) * (b3Scalar(0.020833333333)) * fAngle * fAngle);
+               }
+               else
+               {
+                       // sync(fAngle) = sin(c*fAngle)/t
+                       axis = angvel * (b3Sin(b3Scalar(0.5) * fAngle * timeStep) / fAngle);
+               }
+               b3Quaternion dorn(axis.getX(), axis.getY(), axis.getZ(), b3Cos(fAngle * timeStep * b3Scalar(0.5)));
+               b3Quaternion orn0 = curTrans.getRotation();
+
+               b3Quaternion predictedOrn = dorn * orn0;
+               predictedOrn.normalize();
+#endif
+               predictedTransform.setRotation(predictedOrn);
+       }
+
+       static void calculateVelocityQuaternion(const b3Vector3& pos0, const b3Vector3& pos1, const b3Quaternion& orn0, const b3Quaternion& orn1, b3Scalar timeStep, b3Vector3& linVel, b3Vector3& angVel)
+       {
+               linVel = (pos1 - pos0) / timeStep;
+               b3Vector3 axis;
+               b3Scalar angle;
+               if (orn0 != orn1)
+               {
+                       calculateDiffAxisAngleQuaternion(orn0, orn1, axis, angle);
+                       angVel = axis * angle / timeStep;
+               }
+               else
+               {
+                       angVel.setValue(0, 0, 0);
+               }
+       }
+
+       static void calculateDiffAxisAngleQuaternion(const b3Quaternion& orn0, const b3Quaternion& orn1a, b3Vector3& axis, b3Scalar& angle)
+       {
+               b3Quaternion orn1 = orn0.nearest(orn1a);
+               b3Quaternion dorn = orn1 * orn0.inverse();
+               angle = dorn.getAngle();
+               axis = b3MakeVector3(dorn.getX(), dorn.getY(), dorn.getZ());
+               axis[3] = b3Scalar(0.);
+               //check for axis length
+               b3Scalar len = axis.length2();
+               if (len < B3_EPSILON * B3_EPSILON)
+                       axis = b3MakeVector3(b3Scalar(1.), b3Scalar(0.), b3Scalar(0.));
+               else
+                       axis /= b3Sqrt(len);
+       }
+
+       static void calculateVelocity(const b3Transform& transform0, const b3Transform& transform1, b3Scalar timeStep, b3Vector3& linVel, b3Vector3& angVel)
+       {
+               linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
+               b3Vector3 axis;
+               b3Scalar angle;
+               calculateDiffAxisAngle(transform0, transform1, axis, angle);
+               angVel = axis * angle / timeStep;
+       }
+
+       static void calculateDiffAxisAngle(const b3Transform& transform0, const b3Transform& transform1, b3Vector3& axis, b3Scalar& angle)
+       {
+               b3Matrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
+               b3Quaternion dorn;
+               dmat.getRotation(dorn);
+
+               ///floating point inaccuracy can lead to w component > 1..., which breaks
+               dorn.normalize();
+
+               angle = dorn.getAngle();
+               axis = b3MakeVector3(dorn.getX(), dorn.getY(), dorn.getZ());
+               axis[3] = b3Scalar(0.);
+               //check for axis length
+               b3Scalar len = axis.length2();
+               if (len < B3_EPSILON * B3_EPSILON)
+                       axis = b3MakeVector3(b3Scalar(1.), b3Scalar(0.), b3Scalar(0.));
+               else
+                       axis /= b3Sqrt(len);
+       }
+};
+
+///The b3ConvexSeparatingDistanceUtil can help speed up convex collision detection
+///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
+class b3ConvexSeparatingDistanceUtil
+{
+       b3Quaternion m_ornA;
+       b3Quaternion m_ornB;
+       b3Vector3 m_posA;
+       b3Vector3 m_posB;
+
+       b3Vector3 m_separatingNormal;
+
+       b3Scalar m_boundingRadiusA;
+       b3Scalar m_boundingRadiusB;
+       b3Scalar m_separatingDistance;
+
+public:
+       b3ConvexSeparatingDistanceUtil(b3Scalar boundingRadiusA, b3Scalar boundingRadiusB)
+               : m_boundingRadiusA(boundingRadiusA),
+                 m_boundingRadiusB(boundingRadiusB),
+                 m_separatingDistance(0.f)
+       {
+       }
+
+       b3Scalar getConservativeSeparatingDistance()
+       {
+               return m_separatingDistance;
+       }
+
+       void updateSeparatingDistance(const b3Transform& transA, const b3Transform& transB)
+       {
+               const b3Vector3& toPosA = transA.getOrigin();
+               const b3Vector3& toPosB = transB.getOrigin();
+               b3Quaternion toOrnA = transA.getRotation();
+               b3Quaternion toOrnB = transB.getRotation();
+
+               if (m_separatingDistance > 0.f)
+               {
+                       b3Vector3 linVelA, angVelA, linVelB, angVelB;
+                       b3TransformUtil::calculateVelocityQuaternion(m_posA, toPosA, m_ornA, toOrnA, b3Scalar(1.), linVelA, angVelA);
+                       b3TransformUtil::calculateVelocityQuaternion(m_posB, toPosB, m_ornB, toOrnB, b3Scalar(1.), linVelB, angVelB);
+                       b3Scalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
+                       b3Vector3 relLinVel = (linVelB - linVelA);
+                       b3Scalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
+                       if (relLinVelocLength < 0.f)
+                       {
+                               relLinVelocLength = 0.f;
+                       }
+
+                       b3Scalar projectedMotion = maxAngularProjectedVelocity + relLinVelocLength;
+                       m_separatingDistance -= projectedMotion;
+               }
+
+               m_posA = toPosA;
+               m_posB = toPosB;
+               m_ornA = toOrnA;
+               m_ornB = toOrnB;
+       }
+
+       void initSeparatingDistance(const b3Vector3& separatingVector, b3Scalar separatingDistance, const b3Transform& transA, const b3Transform& transB)
+       {
+               m_separatingDistance = separatingDistance;
+
+               if (m_separatingDistance > 0.f)
+               {
+                       m_separatingNormal = separatingVector;
+
+                       const b3Vector3& toPosA = transA.getOrigin();
+                       const b3Vector3& toPosB = transB.getOrigin();
+                       b3Quaternion toOrnA = transA.getRotation();
+                       b3Quaternion toOrnB = transB.getRotation();
+                       m_posA = toPosA;
+                       m_posB = toPosB;
+                       m_ornA = toOrnA;
+                       m_ornB = toOrnB;
+               }
+       }
+};
+
+#endif  //B3_TRANSFORM_UTIL_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3Vector3.cpp b/dali-physics/third-party/bullet3/src/Bullet3Common/b3Vector3.cpp
new file mode 100644 (file)
index 0000000..100fb77
--- /dev/null
@@ -0,0 +1,1637 @@
+/*
+ Copyright (c) 2011-213 Apple Inc. http://bulletphysics.org
+
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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 source version has been altered.
+ */
+
+#if defined(_WIN32) || defined(__i386__)
+#define B3_USE_SSE_IN_API
+#endif
+
+#include "b3Vector3.h"
+
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+
+#ifdef __APPLE__
+#include <stdint.h>
+typedef float float4 __attribute__((vector_size(16)));
+#else
+#define float4 __m128
+#endif
+//typedef  uint32_t uint4 __attribute__ ((vector_size(16)));
+
+#if defined B3_USE_SSE || defined _WIN32
+
+#define LOG2_ARRAY_SIZE 6
+#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
+
+#include <emmintrin.h>
+
+long b3_maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
+long b3_maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       const float4 *vertices = (const float4 *)vv;
+       static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
+       float4 dotMax = b3Assign128(-B3_INFINITY, -B3_INFINITY, -B3_INFINITY, -B3_INFINITY);
+       float4 vvec = _mm_loadu_ps(vec);
+       float4 vHi = b3CastiTo128f(_mm_shuffle_epi32(b3CastfTo128i(vvec), 0xaa));  /// zzzz
+       float4 vLo = _mm_movelh_ps(vvec, vvec);                                    /// xyxy
+
+       long maxIndex = -1L;
+
+       size_t segment = 0;
+       float4 stack_array[STACK_ARRAY_COUNT];
+
+#if DEBUG
+       // memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+#endif
+
+       size_t index;
+       float4 max;
+       // Faster loop without cleanup code for full tiles
+       for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
+       {
+               max = dotMax;
+
+               for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
+               {  // do four dot products at a time. Carefully avoid touching the w element.
+                       float4 v0 = vertices[0];
+                       float4 v1 = vertices[1];
+                       float4 v2 = vertices[2];
+                       float4 v3 = vertices[3];
+                       vertices += 4;
+
+                       float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 1] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 2] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 3] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       // It is too costly to keep the index of the max here. We will look for it again later.  We save a lot of work this way.
+               }
+
+               // If we found a new max
+               if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
+               {
+                       // copy the new max across all lanes of our max accumulator
+                       max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
+                       max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
+
+                       dotMax = max;
+
+                       // find first occurrence of that max
+                       size_t test;
+                       for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++)  // local_count must be a multiple of 4
+                       {
+                       }
+                       // record where it is.
+                       maxIndex = 4 * index + segment + indexTable[test];
+               }
+       }
+
+       // account for work we've already done
+       count -= segment;
+
+       // Deal with the last < STACK_ARRAY_COUNT vectors
+       max = dotMax;
+       index = 0;
+
+       if (b3Unlikely(count > 16))
+       {
+               for (; index + 4 <= count / 4; index += 4)
+               {  // do four dot products at a time. Carefully avoid touching the w element.
+                       float4 v0 = vertices[0];
+                       float4 v1 = vertices[1];
+                       float4 v2 = vertices[2];
+                       float4 v3 = vertices[3];
+                       vertices += 4;
+
+                       float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 1] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 2] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 3] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       // It is too costly to keep the index of the max here. We will look for it again later.  We save a lot of work this way.
+               }
+       }
+
+       size_t localCount = (count & -4L) - 4 * index;
+       if (localCount)
+       {
+#ifdef __APPLE__
+               float4 t0, t1, t2, t3, t4;
+               float4 *sap = &stack_array[index + localCount / 4];
+               vertices += localCount;  // counter the offset
+               size_t byteIndex = -(localCount) * sizeof(float);
+               //AT&T Code style assembly
+               asm volatile(
+                       ".align 4                                                                   \n\
+             0: movaps  %[max], %[t2]                            // move max out of the way to avoid propagating NaNs in max \n\
+          movaps  (%[vertices], %[byteIndex], 4),    %[t0]    // vertices[0]      \n\
+          movaps  16(%[vertices], %[byteIndex], 4),  %[t1]    // vertices[1]      \n\
+          movaps  %[t0], %[max]                               // vertices[0]      \n\
+          movlhps %[t1], %[max]                               // x0y0x1y1         \n\
+         movaps  32(%[vertices], %[byteIndex], 4),  %[t3]    // vertices[2]      \n\
+         movaps  48(%[vertices], %[byteIndex], 4),  %[t4]    // vertices[3]      \n\
+          mulps   %[vLo], %[max]                              // x0y0x1y1 * vLo   \n\
+         movhlps %[t0], %[t1]                                // z0w0z1w1         \n\
+         movaps  %[t3], %[t0]                                // vertices[2]      \n\
+         movlhps %[t4], %[t0]                                // x2y2x3y3         \n\
+         mulps   %[vLo], %[t0]                               // x2y2x3y3 * vLo   \n\
+          movhlps %[t3], %[t4]                                // z2w2z3w3         \n\
+          shufps  $0x88, %[t4], %[t1]                         // z0z1z2z3         \n\
+          mulps   %[vHi], %[t1]                               // z0z1z2z3 * vHi   \n\
+         movaps  %[max], %[t3]                               // x0y0x1y1 * vLo   \n\
+         shufps  $0x88, %[t0], %[max]                        // x0x1x2x3 * vLo.x \n\
+         shufps  $0xdd, %[t0], %[t3]                         // y0y1y2y3 * vLo.y \n\
+         addps   %[t3], %[max]                               // x + y            \n\
+         addps   %[t1], %[max]                               // x + y + z        \n\
+         movaps  %[max], (%[sap], %[byteIndex])              // record result for later scrutiny \n\
+         maxps   %[t2], %[max]                               // record max, restore max   \n\
+         add     $16, %[byteIndex]                           // advance loop counter\n\
+         jnz     0b                                          \n\
+     "
+                       : [max] "+x"(max), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
+                       : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
+                       : "memory", "cc");
+               index += localCount / 4;
+#else
+               {
+                       for (unsigned int i = 0; i < localCount / 4; i++, index++)
+                       {  // do four dot products at a time. Carefully avoid touching the w element.
+                               float4 v0 = vertices[0];
+                               float4 v1 = vertices[1];
+                               float4 v2 = vertices[2];
+                               float4 v3 = vertices[3];
+                               vertices += 4;
+
+                               float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                               float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                               float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                               float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                               lo0 = lo0 * vLo;
+                               lo1 = lo1 * vLo;
+                               float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                               float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                               float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                               z = z * vHi;
+                               x = x + y;
+                               x = x + z;
+                               stack_array[index] = x;
+                               max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+                       }
+               }
+#endif  //__APPLE__
+       }
+
+       // process the last few points
+       if (count & 3)
+       {
+               float4 v0, v1, v2, x, y, z;
+               switch (count & 3)
+               {
+                       case 3:
+                       {
+                               v0 = vertices[0];
+                               v1 = vertices[1];
+                               v2 = vertices[2];
+
+                               // Calculate 3 dot products, transpose, duplicate v2
+                               float4 lo0 = _mm_movelh_ps(v0, v1);  // xyxy.lo
+                               float4 hi0 = _mm_movehl_ps(v1, v0);  // z?z?.lo
+                               lo0 = lo0 * vLo;
+                               z = _mm_shuffle_ps(hi0, v2, 0xa8);  // z0z1z2z2
+                               z = z * vHi;
+                               float4 lo1 = _mm_movelh_ps(v2, v2);  // xyxy
+                               lo1 = lo1 * vLo;
+                               x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                               y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       }
+                       break;
+                       case 2:
+                       {
+                               v0 = vertices[0];
+                               v1 = vertices[1];
+                               float4 xy = _mm_movelh_ps(v0, v1);
+                               z = _mm_movehl_ps(v1, v0);
+                               xy = xy * vLo;
+                               z = _mm_shuffle_ps(z, z, 0xa8);
+                               x = _mm_shuffle_ps(xy, xy, 0xa8);
+                               y = _mm_shuffle_ps(xy, xy, 0xfd);
+                               z = z * vHi;
+                       }
+                       break;
+                       case 1:
+                       {
+                               float4 xy = vertices[0];
+                               z = _mm_shuffle_ps(xy, xy, 0xaa);
+                               xy = xy * vLo;
+                               z = z * vHi;
+                               x = _mm_shuffle_ps(xy, xy, 0);
+                               y = _mm_shuffle_ps(xy, xy, 0x55);
+                       }
+                       break;
+               }
+               x = x + y;
+               x = x + z;
+               stack_array[index] = x;
+               max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+               index++;
+       }
+
+       // if we found a new max.
+       if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
+       {  // we found a new max. Search for it
+               // find max across the max vector, place in all elements of max -- big latency hit here
+               max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
+               max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
+
+               // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+               // this where it actually makes a difference is handled in the early out at the top of the function,
+               // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+               // complexity, and removed it.
+
+               dotMax = max;
+
+               // scan for the first occurence of max in the array
+               size_t test;
+               for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++)  // local_count must be a multiple of 4
+               {
+               }
+               maxIndex = 4 * index + segment + indexTable[test];
+       }
+
+       _mm_store_ss(dotResult, dotMax);
+       return maxIndex;
+}
+
+long b3_mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
+
+long b3_mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       const float4 *vertices = (const float4 *)vv;
+       static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
+
+       float4 dotmin = b3Assign128(B3_INFINITY, B3_INFINITY, B3_INFINITY, B3_INFINITY);
+       float4 vvec = _mm_loadu_ps(vec);
+       float4 vHi = b3CastiTo128f(_mm_shuffle_epi32(b3CastfTo128i(vvec), 0xaa));  /// zzzz
+       float4 vLo = _mm_movelh_ps(vvec, vvec);                                    /// xyxy
+
+       long minIndex = -1L;
+
+       size_t segment = 0;
+       float4 stack_array[STACK_ARRAY_COUNT];
+
+#if DEBUG
+       // memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+#endif
+
+       size_t index;
+       float4 min;
+       // Faster loop without cleanup code for full tiles
+       for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
+       {
+               min = dotmin;
+
+               for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
+               {  // do four dot products at a time. Carefully avoid touching the w element.
+                       float4 v0 = vertices[0];
+                       float4 v1 = vertices[1];
+                       float4 v2 = vertices[2];
+                       float4 v3 = vertices[3];
+                       vertices += 4;
+
+                       float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 1] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 2] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 3] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       // It is too costly to keep the index of the min here. We will look for it again later.  We save a lot of work this way.
+               }
+
+               // If we found a new min
+               if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
+               {
+                       // copy the new min across all lanes of our min accumulator
+                       min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
+                       min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
+
+                       dotmin = min;
+
+                       // find first occurrence of that min
+                       size_t test;
+                       for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++)  // local_count must be a multiple of 4
+                       {
+                       }
+                       // record where it is.
+                       minIndex = 4 * index + segment + indexTable[test];
+               }
+       }
+
+       // account for work we've already done
+       count -= segment;
+
+       // Deal with the last < STACK_ARRAY_COUNT vectors
+       min = dotmin;
+       index = 0;
+
+       if (b3Unlikely(count > 16))
+       {
+               for (; index + 4 <= count / 4; index += 4)
+               {  // do four dot products at a time. Carefully avoid touching the w element.
+                       float4 v0 = vertices[0];
+                       float4 v1 = vertices[1];
+                       float4 v2 = vertices[2];
+                       float4 v3 = vertices[3];
+                       vertices += 4;
+
+                       float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 1] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 2] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 3] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       // It is too costly to keep the index of the min here. We will look for it again later.  We save a lot of work this way.
+               }
+       }
+
+       size_t localCount = (count & -4L) - 4 * index;
+       if (localCount)
+       {
+#ifdef __APPLE__
+               vertices += localCount;  // counter the offset
+               float4 t0, t1, t2, t3, t4;
+               size_t byteIndex = -(localCount) * sizeof(float);
+               float4 *sap = &stack_array[index + localCount / 4];
+
+               asm volatile(
+                       ".align 4                                                                   \n\
+             0: movaps  %[min], %[t2]                            // move min out of the way to avoid propagating NaNs in min \n\
+             movaps  (%[vertices], %[byteIndex], 4),    %[t0]    // vertices[0]      \n\
+             movaps  16(%[vertices], %[byteIndex], 4),  %[t1]    // vertices[1]      \n\
+             movaps  %[t0], %[min]                               // vertices[0]      \n\
+             movlhps %[t1], %[min]                               // x0y0x1y1         \n\
+             movaps  32(%[vertices], %[byteIndex], 4),  %[t3]    // vertices[2]      \n\
+             movaps  48(%[vertices], %[byteIndex], 4),  %[t4]    // vertices[3]      \n\
+             mulps   %[vLo], %[min]                              // x0y0x1y1 * vLo   \n\
+             movhlps %[t0], %[t1]                                // z0w0z1w1         \n\
+             movaps  %[t3], %[t0]                                // vertices[2]      \n\
+             movlhps %[t4], %[t0]                                // x2y2x3y3         \n\
+             movhlps %[t3], %[t4]                                // z2w2z3w3         \n\
+             mulps   %[vLo], %[t0]                               // x2y2x3y3 * vLo   \n\
+             shufps  $0x88, %[t4], %[t1]                         // z0z1z2z3         \n\
+             mulps   %[vHi], %[t1]                               // z0z1z2z3 * vHi   \n\
+             movaps  %[min], %[t3]                               // x0y0x1y1 * vLo   \n\
+             shufps  $0x88, %[t0], %[min]                        // x0x1x2x3 * vLo.x \n\
+             shufps  $0xdd, %[t0], %[t3]                         // y0y1y2y3 * vLo.y \n\
+             addps   %[t3], %[min]                               // x + y            \n\
+             addps   %[t1], %[min]                               // x + y + z        \n\
+             movaps  %[min], (%[sap], %[byteIndex])              // record result for later scrutiny \n\
+             minps   %[t2], %[min]                               // record min, restore min   \n\
+             add     $16, %[byteIndex]                           // advance loop counter\n\
+             jnz     0b                                          \n\
+             "
+                       : [min] "+x"(min), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
+                       : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
+                       : "memory", "cc");
+               index += localCount / 4;
+#else
+               {
+                       for (unsigned int i = 0; i < localCount / 4; i++, index++)
+                       {  // do four dot products at a time. Carefully avoid touching the w element.
+                               float4 v0 = vertices[0];
+                               float4 v1 = vertices[1];
+                               float4 v2 = vertices[2];
+                               float4 v3 = vertices[3];
+                               vertices += 4;
+
+                               float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                               float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                               float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                               float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                               lo0 = lo0 * vLo;
+                               lo1 = lo1 * vLo;
+                               float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                               float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                               float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                               z = z * vHi;
+                               x = x + y;
+                               x = x + z;
+                               stack_array[index] = x;
+                               min = _mm_min_ps(x, min);  // control the order here so that max is never NaN even if x is nan
+                       }
+               }
+
+#endif
+       }
+
+       // process the last few points
+       if (count & 3)
+       {
+               float4 v0, v1, v2, x, y, z;
+               switch (count & 3)
+               {
+                       case 3:
+                       {
+                               v0 = vertices[0];
+                               v1 = vertices[1];
+                               v2 = vertices[2];
+
+                               // Calculate 3 dot products, transpose, duplicate v2
+                               float4 lo0 = _mm_movelh_ps(v0, v1);  // xyxy.lo
+                               float4 hi0 = _mm_movehl_ps(v1, v0);  // z?z?.lo
+                               lo0 = lo0 * vLo;
+                               z = _mm_shuffle_ps(hi0, v2, 0xa8);  // z0z1z2z2
+                               z = z * vHi;
+                               float4 lo1 = _mm_movelh_ps(v2, v2);  // xyxy
+                               lo1 = lo1 * vLo;
+                               x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                               y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       }
+                       break;
+                       case 2:
+                       {
+                               v0 = vertices[0];
+                               v1 = vertices[1];
+                               float4 xy = _mm_movelh_ps(v0, v1);
+                               z = _mm_movehl_ps(v1, v0);
+                               xy = xy * vLo;
+                               z = _mm_shuffle_ps(z, z, 0xa8);
+                               x = _mm_shuffle_ps(xy, xy, 0xa8);
+                               y = _mm_shuffle_ps(xy, xy, 0xfd);
+                               z = z * vHi;
+                       }
+                       break;
+                       case 1:
+                       {
+                               float4 xy = vertices[0];
+                               z = _mm_shuffle_ps(xy, xy, 0xaa);
+                               xy = xy * vLo;
+                               z = z * vHi;
+                               x = _mm_shuffle_ps(xy, xy, 0);
+                               y = _mm_shuffle_ps(xy, xy, 0x55);
+                       }
+                       break;
+               }
+               x = x + y;
+               x = x + z;
+               stack_array[index] = x;
+               min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+               index++;
+       }
+
+       // if we found a new min.
+       if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
+       {  // we found a new min. Search for it
+               // find min across the min vector, place in all elements of min -- big latency hit here
+               min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
+               min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
+
+               // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+               // this where it actually makes a difference is handled in the early out at the top of the function,
+               // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+               // complexity, and removed it.
+
+               dotmin = min;
+
+               // scan for the first occurence of min in the array
+               size_t test;
+               for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++)  // local_count must be a multiple of 4
+               {
+               }
+               minIndex = 4 * index + segment + indexTable[test];
+       }
+
+       _mm_store_ss(dotResult, dotmin);
+       return minIndex;
+}
+
+#elif defined B3_USE_NEON
+#define ARM_NEON_GCC_COMPATIBILITY 1
+#include <arm_neon.h>
+
+static long b3_maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long b3_maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long b3_maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long b3_mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long b3_mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long b3_mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
+
+long (*b3_maxdot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = b3_maxdot_large_sel;
+long (*b3_mindot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = b3_mindot_large_sel;
+
+extern "C"
+{
+       int _get_cpu_capabilities(void);
+}
+
+static long b3_maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       if (_get_cpu_capabilities() & 0x2000)
+               b3_maxdot_large = _maxdot_large_v1;
+       else
+               b3_maxdot_large = _maxdot_large_v0;
+
+       return b3_maxdot_large(vv, vec, count, dotResult);
+}
+
+static long b3_mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       if (_get_cpu_capabilities() & 0x2000)
+               b3_mindot_large = _mindot_large_v1;
+       else
+               b3_mindot_large = _mindot_large_v0;
+
+       return b3_mindot_large(vv, vec, count, dotResult);
+}
+
+#define vld1q_f32_aligned_postincrement(_ptr) ({ float32x4_t _r; asm( "vld1.f32  {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
+
+long b3_maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       unsigned long i = 0;
+       float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+       float32x2_t vLo = vget_low_f32(vvec);
+       float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+       float32x2_t dotMaxLo = (float32x2_t){-B3_INFINITY, -B3_INFINITY};
+       float32x2_t dotMaxHi = (float32x2_t){-B3_INFINITY, -B3_INFINITY};
+       uint32x2_t indexLo = (uint32x2_t){0, 1};
+       uint32x2_t indexHi = (uint32x2_t){2, 3};
+       uint32x2_t iLo = (uint32x2_t){-1, -1};
+       uint32x2_t iHi = (uint32x2_t){-1, -1};
+       const uint32x2_t four = (uint32x2_t){4, 4};
+
+       for (; i + 8 <= count; i += 8)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+               float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+               float32x2_t rLo = vpadd_f32(xy0, xy1);
+               float32x2_t rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+               uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+               dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+               dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+
+               v0 = vld1q_f32_aligned_postincrement(vv);
+               v1 = vld1q_f32_aligned_postincrement(vv);
+               v2 = vld1q_f32_aligned_postincrement(vv);
+               v3 = vld1q_f32_aligned_postincrement(vv);
+
+               xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               zLo = vmul_f32(z0.val[0], vHi);
+               zHi = vmul_f32(z1.val[0], vHi);
+
+               rLo = vpadd_f32(xy0, xy1);
+               rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               maskLo = vcgt_f32(rLo, dotMaxLo);
+               maskHi = vcgt_f32(rHi, dotMaxHi);
+               dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+               dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+       }
+
+       for (; i + 4 <= count; i += 4)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+               float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+               float32x2_t rLo = vpadd_f32(xy0, xy1);
+               float32x2_t rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+               uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+               dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+               dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+       }
+
+       switch (count & 3)
+       {
+               case 3:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+                       float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+
+                       float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+                       float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+                       float32x2_t rLo = vpadd_f32(xy0, xy1);
+                       float32x2_t rHi = vpadd_f32(xy2, xy2);
+                       rLo = vadd_f32(rLo, zLo);
+                       rHi = vadd_f32(rHi, zHi);
+
+                       uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+                       uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+                       dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+                       dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+                       iHi = vbsl_u32(maskHi, indexHi, iHi);
+               }
+               break;
+               case 2:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+
+                       float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+
+                       float32x2_t rLo = vpadd_f32(xy0, xy1);
+                       rLo = vadd_f32(rLo, zLo);
+
+                       uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+                       dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+               }
+               break;
+               case 1:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+                       float32x2_t zLo = vmul_f32(z0, vHi);
+                       float32x2_t rLo = vpadd_f32(xy0, xy0);
+                       rLo = vadd_f32(rLo, zLo);
+                       uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+                       dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+               }
+               break;
+
+               default:
+                       break;
+       }
+
+       // select best answer between hi and lo results
+       uint32x2_t mask = vcgt_f32(dotMaxHi, dotMaxLo);
+       dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+       iLo = vbsl_u32(mask, iHi, iLo);
+
+       // select best answer between even and odd results
+       dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
+       iHi = vdup_lane_u32(iLo, 1);
+       mask = vcgt_f32(dotMaxHi, dotMaxLo);
+       dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+       iLo = vbsl_u32(mask, iHi, iLo);
+
+       *dotResult = vget_lane_f32(dotMaxLo, 0);
+       return vget_lane_u32(iLo, 0);
+}
+
+long b3_maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+       float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+       float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+       const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
+       uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
+       uint32x4_t index = (uint32x4_t){-1, -1, -1, -1};
+       float32x4_t maxDot = (float32x4_t){-B3_INFINITY, -B3_INFINITY, -B3_INFINITY, -B3_INFINITY};
+
+       unsigned long i = 0;
+       for (; i + 8 <= count; i += 8)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               float32x4x2_t zb = vuzpq_f32(z0, z1);
+               float32x4_t z = vmulq_f32(zb.val[0], vHi);
+               float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+               float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               uint32x4_t mask = vcgtq_f32(x, maxDot);
+               maxDot = vbslq_f32(mask, x, maxDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+
+               v0 = vld1q_f32_aligned_postincrement(vv);
+               v1 = vld1q_f32_aligned_postincrement(vv);
+               v2 = vld1q_f32_aligned_postincrement(vv);
+               v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               zb = vuzpq_f32(z0, z1);
+               z = vmulq_f32(zb.val[0], vHi);
+               xy = vuzpq_f32(xy0, xy1);
+               x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               mask = vcgtq_f32(x, maxDot);
+               maxDot = vbslq_f32(mask, x, maxDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+       }
+
+       for (; i + 4 <= count; i += 4)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               float32x4x2_t zb = vuzpq_f32(z0, z1);
+               float32x4_t z = vmulq_f32(zb.val[0], vHi);
+               float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+               float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               uint32x4_t mask = vcgtq_f32(x, maxDot);
+               maxDot = vbslq_f32(mask, x, maxDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+       }
+
+       switch (count & 3)
+       {
+               case 3:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+                       float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
+
+                       xy0 = vmulq_f32(xy0, vLo);
+                       xy1 = vmulq_f32(xy1, vLo);
+
+                       float32x4x2_t zb = vuzpq_f32(z0, z1);
+                       float32x4_t z = vmulq_f32(zb.val[0], vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcgtq_f32(x, maxDot);
+                       maxDot = vbslq_f32(mask, x, maxDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               case 2:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+
+                       xy0 = vmulq_f32(xy0, vLo);
+
+                       float32x4x2_t zb = vuzpq_f32(z0, z0);
+                       float32x4_t z = vmulq_f32(zb.val[0], vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcgtq_f32(x, maxDot);
+                       maxDot = vbslq_f32(mask, x, maxDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               case 1:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+                       xy0 = vmulq_f32(xy0, vLo);
+
+                       z = vmulq_f32(z, vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcgtq_f32(x, maxDot);
+                       maxDot = vbslq_f32(mask, x, maxDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               default:
+                       break;
+       }
+
+       // select best answer between hi and lo results
+       uint32x2_t mask = vcgt_f32(vget_high_f32(maxDot), vget_low_f32(maxDot));
+       float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
+       uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+       // select best answer between even and odd results
+       float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
+       uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+       mask = vcgt_f32(maxDotO, maxDot2);
+       maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
+       index2 = vbsl_u32(mask, indexHi, index2);
+
+       *dotResult = vget_lane_f32(maxDot2, 0);
+       return vget_lane_u32(index2, 0);
+}
+
+long b3_mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       unsigned long i = 0;
+       float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+       float32x2_t vLo = vget_low_f32(vvec);
+       float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+       float32x2_t dotMinLo = (float32x2_t){B3_INFINITY, B3_INFINITY};
+       float32x2_t dotMinHi = (float32x2_t){B3_INFINITY, B3_INFINITY};
+       uint32x2_t indexLo = (uint32x2_t){0, 1};
+       uint32x2_t indexHi = (uint32x2_t){2, 3};
+       uint32x2_t iLo = (uint32x2_t){-1, -1};
+       uint32x2_t iHi = (uint32x2_t){-1, -1};
+       const uint32x2_t four = (uint32x2_t){4, 4};
+
+       for (; i + 8 <= count; i += 8)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+               float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+               float32x2_t rLo = vpadd_f32(xy0, xy1);
+               float32x2_t rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+               uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+               dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+               dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+
+               v0 = vld1q_f32_aligned_postincrement(vv);
+               v1 = vld1q_f32_aligned_postincrement(vv);
+               v2 = vld1q_f32_aligned_postincrement(vv);
+               v3 = vld1q_f32_aligned_postincrement(vv);
+
+               xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               zLo = vmul_f32(z0.val[0], vHi);
+               zHi = vmul_f32(z1.val[0], vHi);
+
+               rLo = vpadd_f32(xy0, xy1);
+               rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               maskLo = vclt_f32(rLo, dotMinLo);
+               maskHi = vclt_f32(rHi, dotMinHi);
+               dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+               dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+       }
+
+       for (; i + 4 <= count; i += 4)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+               float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+               float32x2_t rLo = vpadd_f32(xy0, xy1);
+               float32x2_t rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+               uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+               dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+               dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+       }
+       switch (count & 3)
+       {
+               case 3:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+                       float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+
+                       float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+                       float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+                       float32x2_t rLo = vpadd_f32(xy0, xy1);
+                       float32x2_t rHi = vpadd_f32(xy2, xy2);
+                       rLo = vadd_f32(rLo, zLo);
+                       rHi = vadd_f32(rHi, zHi);
+
+                       uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+                       uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+                       dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+                       dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+                       iHi = vbsl_u32(maskHi, indexHi, iHi);
+               }
+               break;
+               case 2:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+
+                       float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+
+                       float32x2_t rLo = vpadd_f32(xy0, xy1);
+                       rLo = vadd_f32(rLo, zLo);
+
+                       uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+                       dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+               }
+               break;
+               case 1:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+                       float32x2_t zLo = vmul_f32(z0, vHi);
+                       float32x2_t rLo = vpadd_f32(xy0, xy0);
+                       rLo = vadd_f32(rLo, zLo);
+                       uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+                       dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+               }
+               break;
+
+               default:
+                       break;
+       }
+
+       // select best answer between hi and lo results
+       uint32x2_t mask = vclt_f32(dotMinHi, dotMinLo);
+       dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+       iLo = vbsl_u32(mask, iHi, iLo);
+
+       // select best answer between even and odd results
+       dotMinHi = vdup_lane_f32(dotMinLo, 1);
+       iHi = vdup_lane_u32(iLo, 1);
+       mask = vclt_f32(dotMinHi, dotMinLo);
+       dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+       iLo = vbsl_u32(mask, iHi, iLo);
+
+       *dotResult = vget_lane_f32(dotMinLo, 0);
+       return vget_lane_u32(iLo, 0);
+}
+
+long b3_mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+       float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+       float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+       const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
+       uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
+       uint32x4_t index = (uint32x4_t){-1, -1, -1, -1};
+       float32x4_t minDot = (float32x4_t){B3_INFINITY, B3_INFINITY, B3_INFINITY, B3_INFINITY};
+
+       unsigned long i = 0;
+       for (; i + 8 <= count; i += 8)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               float32x4x2_t zb = vuzpq_f32(z0, z1);
+               float32x4_t z = vmulq_f32(zb.val[0], vHi);
+               float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+               float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               uint32x4_t mask = vcltq_f32(x, minDot);
+               minDot = vbslq_f32(mask, x, minDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+
+               v0 = vld1q_f32_aligned_postincrement(vv);
+               v1 = vld1q_f32_aligned_postincrement(vv);
+               v2 = vld1q_f32_aligned_postincrement(vv);
+               v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               zb = vuzpq_f32(z0, z1);
+               z = vmulq_f32(zb.val[0], vHi);
+               xy = vuzpq_f32(xy0, xy1);
+               x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               mask = vcltq_f32(x, minDot);
+               minDot = vbslq_f32(mask, x, minDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+       }
+
+       for (; i + 4 <= count; i += 4)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               float32x4x2_t zb = vuzpq_f32(z0, z1);
+               float32x4_t z = vmulq_f32(zb.val[0], vHi);
+               float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+               float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               uint32x4_t mask = vcltq_f32(x, minDot);
+               minDot = vbslq_f32(mask, x, minDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+       }
+
+       switch (count & 3)
+       {
+               case 3:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+                       float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
+
+                       xy0 = vmulq_f32(xy0, vLo);
+                       xy1 = vmulq_f32(xy1, vLo);
+
+                       float32x4x2_t zb = vuzpq_f32(z0, z1);
+                       float32x4_t z = vmulq_f32(zb.val[0], vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcltq_f32(x, minDot);
+                       minDot = vbslq_f32(mask, x, minDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               case 2:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+
+                       xy0 = vmulq_f32(xy0, vLo);
+
+                       float32x4x2_t zb = vuzpq_f32(z0, z0);
+                       float32x4_t z = vmulq_f32(zb.val[0], vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcltq_f32(x, minDot);
+                       minDot = vbslq_f32(mask, x, minDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               case 1:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+                       xy0 = vmulq_f32(xy0, vLo);
+
+                       z = vmulq_f32(z, vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcltq_f32(x, minDot);
+                       minDot = vbslq_f32(mask, x, minDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               default:
+                       break;
+       }
+
+       // select best answer between hi and lo results
+       uint32x2_t mask = vclt_f32(vget_high_f32(minDot), vget_low_f32(minDot));
+       float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
+       uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+       // select best answer between even and odd results
+       float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
+       uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+       mask = vclt_f32(minDotO, minDot2);
+       minDot2 = vbsl_f32(mask, minDotO, minDot2);
+       index2 = vbsl_u32(mask, indexHi, index2);
+
+       *dotResult = vget_lane_f32(minDot2, 0);
+       return vget_lane_u32(index2, 0);
+}
+
+#else
+#error Unhandled __APPLE__ arch
+#endif
+
+#endif /* __APPLE__ */
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/b3Vector3.h b/dali-physics/third-party/bullet3/src/Bullet3Common/b3Vector3.h
new file mode 100644 (file)
index 0000000..a70d68d
--- /dev/null
@@ -0,0 +1,1303 @@
+/*
+Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_VECTOR3_H
+#define B3_VECTOR3_H
+
+//#include <stdint.h>
+#include "b3Scalar.h"
+#include "b3MinMax.h"
+#include "b3AlignedAllocator.h"
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define b3Vector3Data b3Vector3DoubleData
+#define b3Vector3DataName "b3Vector3DoubleData"
+#else
+#define b3Vector3Data b3Vector3FloatData
+#define b3Vector3DataName "b3Vector3FloatData"
+#endif  //B3_USE_DOUBLE_PRECISION
+
+#if defined B3_USE_SSE
+
+//typedef  uint32_t __m128i __attribute__ ((vector_size(16)));
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4556)  // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
+#endif
+
+#define B3_SHUFFLE(x, y, z, w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
+//#define b3_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
+#define b3_pshufd_ps(_a, _mask) _mm_shuffle_ps((_a), (_a), (_mask))
+#define b3_splat3_ps(_a, _i) b3_pshufd_ps((_a), B3_SHUFFLE(_i, _i, _i, 3))
+#define b3_splat_ps(_a, _i) b3_pshufd_ps((_a), B3_SHUFFLE(_i, _i, _i, _i))
+
+#define b3v3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define b3vAbsMask (_mm_set_epi32(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define b3vFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF))
+#define b3v3AbsfMask b3CastiTo128f(b3v3AbsiMask)
+#define b3vFFF0fMask b3CastiTo128f(b3vFFF0Mask)
+#define b3vxyzMaskf b3vFFF0fMask
+#define b3vAbsfMask b3CastiTo128f(b3vAbsMask)
+
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3vMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f};
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3v1110) = {1.0f, 1.0f, 1.0f, 0.0f};
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3vHalf) = {0.5f, 0.5f, 0.5f, 0.5f};
+const __m128 B3_ATTRIBUTE_ALIGNED16(b3v1_5) = {1.5f, 1.5f, 1.5f, 1.5f};
+
+#endif
+
+#ifdef B3_USE_NEON
+
+const float32x4_t B3_ATTRIBUTE_ALIGNED16(b3vMzeroMask) = (float32x4_t){-0.0f, -0.0f, -0.0f, -0.0f};
+const int32x4_t B3_ATTRIBUTE_ALIGNED16(b3vFFF0Mask) = (int32x4_t){0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0};
+const int32x4_t B3_ATTRIBUTE_ALIGNED16(b3vAbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
+const int32x4_t B3_ATTRIBUTE_ALIGNED16(b3v3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0};
+
+#endif
+
+class b3Vector3;
+class b3Vector4;
+
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+//#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
+inline b3Vector3 b3MakeVector3(b3SimdFloat4 v);
+inline b3Vector4 b3MakeVector4(b3SimdFloat4 vec);
+#endif
+
+inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z);
+inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w);
+inline b3Vector4 b3MakeVector4(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w);
+
+/**@brief b3Vector3 can be used to represent 3D points and vectors.
+ * It has an un-used w component to suit 16-byte alignment when b3Vector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
+ * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
+ */
+B3_ATTRIBUTE_ALIGNED16(class)
+b3Vector3
+{
+public:
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)  // _WIN32 || ARM
+       union {
+               b3SimdFloat4 mVec128;
+               float m_floats[4];
+               struct
+               {
+                       float x, y, z, w;
+               };
+       };
+#else
+       union {
+               float m_floats[4];
+               struct
+               {
+                       float x, y, z, w;
+               };
+       };
+#endif
+
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)  // _WIN32 || ARM
+
+       /*B3_FORCE_INLINE               b3Vector3()
+       {
+       }
+       */
+
+       B3_FORCE_INLINE b3SimdFloat4 get128() const
+       {
+               return mVec128;
+       }
+       B3_FORCE_INLINE void set128(b3SimdFloat4 v128)
+       {
+               mVec128 = v128;
+       }
+#endif
+
+public:
+       /**@brief Add a vector to this one
+ * @param The vector to add to this one */
+       B3_FORCE_INLINE b3Vector3& operator+=(const b3Vector3& v)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               mVec128 = _mm_add_ps(mVec128, v.mVec128);
+#elif defined(B3_USE_NEON)
+               mVec128 = vaddq_f32(mVec128, v.mVec128);
+#else
+               m_floats[0] += v.m_floats[0];
+               m_floats[1] += v.m_floats[1];
+               m_floats[2] += v.m_floats[2];
+#endif
+               return *this;
+       }
+
+       /**@brief Subtract a vector from this one
+   * @param The vector to subtract */
+       B3_FORCE_INLINE b3Vector3& operator-=(const b3Vector3& v)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               mVec128 = _mm_sub_ps(mVec128, v.mVec128);
+#elif defined(B3_USE_NEON)
+               mVec128 = vsubq_f32(mVec128, v.mVec128);
+#else
+               m_floats[0] -= v.m_floats[0];
+               m_floats[1] -= v.m_floats[1];
+               m_floats[2] -= v.m_floats[2];
+#endif
+               return *this;
+       }
+
+       /**@brief Scale the vector
+   * @param s Scale factor */
+       B3_FORCE_INLINE b3Vector3& operator*=(const b3Scalar& s)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 vs = _mm_load_ss(&s);  //        (S 0 0 0)
+               vs = b3_pshufd_ps(vs, 0x80);  //        (S S S 0.0)
+               mVec128 = _mm_mul_ps(mVec128, vs);
+#elif defined(B3_USE_NEON)
+               mVec128 = vmulq_n_f32(mVec128, s);
+#else
+               m_floats[0] *= s;
+               m_floats[1] *= s;
+               m_floats[2] *= s;
+#endif
+               return *this;
+       }
+
+       /**@brief Inversely scale the vector
+   * @param s Scale factor to divide by */
+       B3_FORCE_INLINE b3Vector3& operator/=(const b3Scalar& s)
+       {
+               b3FullAssert(s != b3Scalar(0.0));
+
+#if 0  //defined(B3_USE_SSE_IN_API)
+// this code is not faster !
+               __m128 vs = _mm_load_ss(&s);
+               vs = _mm_div_ss(b3v1110, vs);
+               vs = b3_pshufd_ps(vs, 0x00);    //      (S S S S)
+
+               mVec128 = _mm_mul_ps(mVec128, vs);
+
+               return *this;
+#else
+               return *this *= b3Scalar(1.0) / s;
+#endif
+       }
+
+       /**@brief Return the dot product
+   * @param v The other vector in the dot product */
+       B3_FORCE_INLINE b3Scalar dot(const b3Vector3& v) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 vd = _mm_mul_ps(mVec128, v.mVec128);
+               __m128 z = _mm_movehl_ps(vd, vd);
+               __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
+               vd = _mm_add_ss(vd, y);
+               vd = _mm_add_ss(vd, z);
+               return _mm_cvtss_f32(vd);
+#elif defined(B3_USE_NEON)
+               float32x4_t vd = vmulq_f32(mVec128, v.mVec128);
+               float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd));
+               x = vadd_f32(x, vget_high_f32(vd));
+               return vget_lane_f32(x, 0);
+#else
+               return m_floats[0] * v.m_floats[0] +
+                          m_floats[1] * v.m_floats[1] +
+                          m_floats[2] * v.m_floats[2];
+#endif
+       }
+
+       /**@brief Return the length of the vector squared */
+       B3_FORCE_INLINE b3Scalar length2() const
+       {
+               return dot(*this);
+       }
+
+       /**@brief Return the length of the vector */
+       B3_FORCE_INLINE b3Scalar length() const
+       {
+               return b3Sqrt(length2());
+       }
+
+       /**@brief Return the distance squared between the ends of this and another vector
+   * This is symantically treating the vector like a point */
+       B3_FORCE_INLINE b3Scalar distance2(const b3Vector3& v) const;
+
+       /**@brief Return the distance between the ends of this and another vector
+   * This is symantically treating the vector like a point */
+       B3_FORCE_INLINE b3Scalar distance(const b3Vector3& v) const;
+
+       B3_FORCE_INLINE b3Vector3& safeNormalize()
+       {
+               b3Scalar l2 = length2();
+               //triNormal.normalize();
+               if (l2 >= B3_EPSILON * B3_EPSILON)
+               {
+                       (*this) /= b3Sqrt(l2);
+               }
+               else
+               {
+                       setValue(1, 0, 0);
+               }
+               return *this;
+       }
+
+       /**@brief Normalize this vector
+   * x^2 + y^2 + z^2 = 1 */
+       B3_FORCE_INLINE b3Vector3& normalize()
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               // dot product first
+               __m128 vd = _mm_mul_ps(mVec128, mVec128);
+               __m128 z = _mm_movehl_ps(vd, vd);
+               __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
+               vd = _mm_add_ss(vd, y);
+               vd = _mm_add_ss(vd, z);
+
+#if 0
+        vd = _mm_sqrt_ss(vd);
+               vd = _mm_div_ss(b3v1110, vd);
+               vd = b3_splat_ps(vd, 0x80);
+               mVec128 = _mm_mul_ps(mVec128, vd);
+#else
+
+               // NR step 1/sqrt(x) - vd is x, y is output
+               y = _mm_rsqrt_ss(vd);  // estimate
+
+               //  one step NR
+               z = b3v1_5;
+               vd = _mm_mul_ss(vd, b3vHalf);  // vd * 0.5
+               //x2 = vd;
+               vd = _mm_mul_ss(vd, y);  // vd * 0.5 * y0
+               vd = _mm_mul_ss(vd, y);  // vd * 0.5 * y0 * y0
+               z = _mm_sub_ss(z, vd);   // 1.5 - vd * 0.5 * y0 * y0
+
+               y = _mm_mul_ss(y, z);  // y0 * (1.5 - vd * 0.5 * y0 * y0)
+
+               y = b3_splat_ps(y, 0x80);
+               mVec128 = _mm_mul_ps(mVec128, y);
+
+#endif
+
+               return *this;
+#else
+               return *this /= length();
+#endif
+       }
+
+       /**@brief Return a normalized version of this vector */
+       B3_FORCE_INLINE b3Vector3 normalized() const;
+
+       /**@brief Return a rotated version of this vector
+   * @param wAxis The axis to rotate about
+   * @param angle The angle to rotate by */
+       B3_FORCE_INLINE b3Vector3 rotate(const b3Vector3& wAxis, const b3Scalar angle) const;
+
+       /**@brief Return the angle between this and another vector
+   * @param v The other vector */
+       B3_FORCE_INLINE b3Scalar angle(const b3Vector3& v) const
+       {
+               b3Scalar s = b3Sqrt(length2() * v.length2());
+               b3FullAssert(s != b3Scalar(0.0));
+               return b3Acos(dot(v) / s);
+       }
+
+       /**@brief Return a vector will the absolute values of each element */
+       B3_FORCE_INLINE b3Vector3 absolute() const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               return b3MakeVector3(_mm_and_ps(mVec128, b3v3AbsfMask));
+#elif defined(B3_USE_NEON)
+               return b3Vector3(vabsq_f32(mVec128));
+#else
+               return b3MakeVector3(
+                       b3Fabs(m_floats[0]),
+                       b3Fabs(m_floats[1]),
+                       b3Fabs(m_floats[2]));
+#endif
+       }
+
+       /**@brief Return the cross product between this and another vector
+   * @param v The other vector */
+       B3_FORCE_INLINE b3Vector3 cross(const b3Vector3& v) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 T, V;
+
+               T = b3_pshufd_ps(mVec128, B3_SHUFFLE(1, 2, 0, 3));    //        (Y Z X 0)
+               V = b3_pshufd_ps(v.mVec128, B3_SHUFFLE(1, 2, 0, 3));  //        (Y Z X 0)
+
+               V = _mm_mul_ps(V, mVec128);
+               T = _mm_mul_ps(T, v.mVec128);
+               V = _mm_sub_ps(V, T);
+
+               V = b3_pshufd_ps(V, B3_SHUFFLE(1, 2, 0, 3));
+               return b3MakeVector3(V);
+#elif defined(B3_USE_NEON)
+               float32x4_t T, V;
+               // form (Y, Z, X, _) of mVec128 and v.mVec128
+               float32x2_t Tlow = vget_low_f32(mVec128);
+               float32x2_t Vlow = vget_low_f32(v.mVec128);
+               T = vcombine_f32(vext_f32(Tlow, vget_high_f32(mVec128), 1), Tlow);
+               V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v.mVec128), 1), Vlow);
+
+               V = vmulq_f32(V, mVec128);
+               T = vmulq_f32(T, v.mVec128);
+               V = vsubq_f32(V, T);
+               Vlow = vget_low_f32(V);
+               // form (Y, Z, X, _);
+               V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
+               V = (float32x4_t)vandq_s32((int32x4_t)V, b3vFFF0Mask);
+
+               return b3Vector3(V);
+#else
+               return b3MakeVector3(
+                       m_floats[1] * v.m_floats[2] - m_floats[2] * v.m_floats[1],
+                       m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
+                       m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
+#endif
+       }
+
+       B3_FORCE_INLINE b3Scalar triple(const b3Vector3& v1, const b3Vector3& v2) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               // cross:
+               __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, B3_SHUFFLE(1, 2, 0, 3));  //  (Y Z X 0)
+               __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, B3_SHUFFLE(1, 2, 0, 3));  //  (Y Z X 0)
+
+               V = _mm_mul_ps(V, v1.mVec128);
+               T = _mm_mul_ps(T, v2.mVec128);
+               V = _mm_sub_ps(V, T);
+
+               V = _mm_shuffle_ps(V, V, B3_SHUFFLE(1, 2, 0, 3));
+
+               // dot:
+               V = _mm_mul_ps(V, mVec128);
+               __m128 z = _mm_movehl_ps(V, V);
+               __m128 y = _mm_shuffle_ps(V, V, 0x55);
+               V = _mm_add_ss(V, y);
+               V = _mm_add_ss(V, z);
+               return _mm_cvtss_f32(V);
+
+#elif defined(B3_USE_NEON)
+               // cross:
+               float32x4_t T, V;
+               // form (Y, Z, X, _) of mVec128 and v.mVec128
+               float32x2_t Tlow = vget_low_f32(v1.mVec128);
+               float32x2_t Vlow = vget_low_f32(v2.mVec128);
+               T = vcombine_f32(vext_f32(Tlow, vget_high_f32(v1.mVec128), 1), Tlow);
+               V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v2.mVec128), 1), Vlow);
+
+               V = vmulq_f32(V, v1.mVec128);
+               T = vmulq_f32(T, v2.mVec128);
+               V = vsubq_f32(V, T);
+               Vlow = vget_low_f32(V);
+               // form (Y, Z, X, _);
+               V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
+
+               // dot:
+               V = vmulq_f32(mVec128, V);
+               float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V));
+               x = vadd_f32(x, vget_high_f32(V));
+               return vget_lane_f32(x, 0);
+#else
+               return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
+                          m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
+                          m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
+#endif
+       }
+
+       /**@brief Return the axis with the smallest value
+   * Note return values are 0,1,2 for x, y, or z */
+       B3_FORCE_INLINE int minAxis() const
+       {
+               return m_floats[0] < m_floats[1] ? (m_floats[0] < m_floats[2] ? 0 : 2) : (m_floats[1] < m_floats[2] ? 1 : 2);
+       }
+
+       /**@brief Return the axis with the largest value
+   * Note return values are 0,1,2 for x, y, or z */
+       B3_FORCE_INLINE int maxAxis() const
+       {
+               return m_floats[0] < m_floats[1] ? (m_floats[1] < m_floats[2] ? 2 : 1) : (m_floats[0] < m_floats[2] ? 2 : 0);
+       }
+
+       B3_FORCE_INLINE int furthestAxis() const
+       {
+               return absolute().minAxis();
+       }
+
+       B3_FORCE_INLINE int closestAxis() const
+       {
+               return absolute().maxAxis();
+       }
+
+       B3_FORCE_INLINE void setInterpolate3(const b3Vector3& v0, const b3Vector3& v1, b3Scalar rt)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 vrt = _mm_load_ss(&rt);  //      (rt 0 0 0)
+               b3Scalar s = b3Scalar(1.0) - rt;
+               __m128 vs = _mm_load_ss(&s);  //        (S 0 0 0)
+               vs = b3_pshufd_ps(vs, 0x80);  //        (S S S 0.0)
+               __m128 r0 = _mm_mul_ps(v0.mVec128, vs);
+               vrt = b3_pshufd_ps(vrt, 0x80);  //      (rt rt rt 0.0)
+               __m128 r1 = _mm_mul_ps(v1.mVec128, vrt);
+               __m128 tmp3 = _mm_add_ps(r0, r1);
+               mVec128 = tmp3;
+#elif defined(B3_USE_NEON)
+               float32x4_t vl = vsubq_f32(v1.mVec128, v0.mVec128);
+               vl = vmulq_n_f32(vl, rt);
+               mVec128 = vaddq_f32(vl, v0.mVec128);
+#else
+               b3Scalar s = b3Scalar(1.0) - rt;
+               m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
+               m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
+               m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
+               //don't do the unused w component
+               //              m_co[3] = s * v0[3] + rt * v1[3];
+#endif
+       }
+
+       /**@brief Return the linear interpolation between this and another vector
+   * @param v The other vector
+   * @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
+       B3_FORCE_INLINE b3Vector3 lerp(const b3Vector3& v, const b3Scalar& t) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               __m128 vt = _mm_load_ss(&t);  //        (t 0 0 0)
+               vt = b3_pshufd_ps(vt, 0x80);  //        (rt rt rt 0.0)
+               __m128 vl = _mm_sub_ps(v.mVec128, mVec128);
+               vl = _mm_mul_ps(vl, vt);
+               vl = _mm_add_ps(vl, mVec128);
+
+               return b3MakeVector3(vl);
+#elif defined(B3_USE_NEON)
+               float32x4_t vl = vsubq_f32(v.mVec128, mVec128);
+               vl = vmulq_n_f32(vl, t);
+               vl = vaddq_f32(vl, mVec128);
+
+               return b3Vector3(vl);
+#else
+               return b3MakeVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
+                                                        m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
+                                                        m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
+#endif
+       }
+
+       /**@brief Elementwise multiply this vector by the other
+   * @param v The other vector */
+       B3_FORCE_INLINE b3Vector3& operator*=(const b3Vector3& v)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               mVec128 = _mm_mul_ps(mVec128, v.mVec128);
+#elif defined(B3_USE_NEON)
+               mVec128 = vmulq_f32(mVec128, v.mVec128);
+#else
+               m_floats[0] *= v.m_floats[0];
+               m_floats[1] *= v.m_floats[1];
+               m_floats[2] *= v.m_floats[2];
+#endif
+               return *this;
+       }
+
+       /**@brief Return the x value */
+       B3_FORCE_INLINE const b3Scalar& getX() const { return m_floats[0]; }
+       /**@brief Return the y value */
+       B3_FORCE_INLINE const b3Scalar& getY() const { return m_floats[1]; }
+       /**@brief Return the z value */
+       B3_FORCE_INLINE const b3Scalar& getZ() const { return m_floats[2]; }
+       /**@brief Return the w value */
+       B3_FORCE_INLINE const b3Scalar& getW() const { return m_floats[3]; }
+
+       /**@brief Set the x value */
+       B3_FORCE_INLINE void setX(b3Scalar _x) { m_floats[0] = _x; };
+       /**@brief Set the y value */
+       B3_FORCE_INLINE void setY(b3Scalar _y) { m_floats[1] = _y; };
+       /**@brief Set the z value */
+       B3_FORCE_INLINE void setZ(b3Scalar _z) { m_floats[2] = _z; };
+       /**@brief Set the w value */
+       B3_FORCE_INLINE void setW(b3Scalar _w) { m_floats[3] = _w; };
+
+       //B3_FORCE_INLINE b3Scalar&       operator[](int i)       { return (&m_floats[0])[i];   }
+       //B3_FORCE_INLINE const b3Scalar& operator[](int i) const { return (&m_floats[0])[i]; }
+       ///operator b3Scalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+       B3_FORCE_INLINE operator b3Scalar*() { return &m_floats[0]; }
+       B3_FORCE_INLINE operator const b3Scalar*() const { return &m_floats[0]; }
+
+       B3_FORCE_INLINE bool operator==(const b3Vector3& other) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+               return ((m_floats[3] == other.m_floats[3]) &&
+                               (m_floats[2] == other.m_floats[2]) &&
+                               (m_floats[1] == other.m_floats[1]) &&
+                               (m_floats[0] == other.m_floats[0]));
+#endif
+       }
+
+       B3_FORCE_INLINE bool operator!=(const b3Vector3& other) const
+       {
+               return !(*this == other);
+       }
+
+       /**@brief Set each element to the max of the current values and the values of another b3Vector3
+   * @param other The other b3Vector3 to compare with
+   */
+       B3_FORCE_INLINE void setMax(const b3Vector3& other)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               mVec128 = _mm_max_ps(mVec128, other.mVec128);
+#elif defined(B3_USE_NEON)
+               mVec128 = vmaxq_f32(mVec128, other.mVec128);
+#else
+               b3SetMax(m_floats[0], other.m_floats[0]);
+               b3SetMax(m_floats[1], other.m_floats[1]);
+               b3SetMax(m_floats[2], other.m_floats[2]);
+               b3SetMax(m_floats[3], other.m_floats[3]);
+#endif
+       }
+
+       /**@brief Set each element to the min of the current values and the values of another b3Vector3
+   * @param other The other b3Vector3 to compare with
+   */
+       B3_FORCE_INLINE void setMin(const b3Vector3& other)
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               mVec128 = _mm_min_ps(mVec128, other.mVec128);
+#elif defined(B3_USE_NEON)
+               mVec128 = vminq_f32(mVec128, other.mVec128);
+#else
+               b3SetMin(m_floats[0], other.m_floats[0]);
+               b3SetMin(m_floats[1], other.m_floats[1]);
+               b3SetMin(m_floats[2], other.m_floats[2]);
+               b3SetMin(m_floats[3], other.m_floats[3]);
+#endif
+       }
+
+       B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
+       {
+               m_floats[0] = _x;
+               m_floats[1] = _y;
+               m_floats[2] = _z;
+               m_floats[3] = b3Scalar(0.f);
+       }
+
+       void getSkewSymmetricMatrix(b3Vector3 * v0, b3Vector3 * v1, b3Vector3 * v2) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+
+               __m128 V = _mm_and_ps(mVec128, b3vFFF0fMask);
+               __m128 V0 = _mm_xor_ps(b3vMzeroMask, V);
+               __m128 V2 = _mm_movelh_ps(V0, V);
+
+               __m128 V1 = _mm_shuffle_ps(V, V0, 0xCE);
+
+               V0 = _mm_shuffle_ps(V0, V, 0xDB);
+               V2 = _mm_shuffle_ps(V2, V, 0xF9);
+
+               v0->mVec128 = V0;
+               v1->mVec128 = V1;
+               v2->mVec128 = V2;
+#else
+               v0->setValue(0., -getZ(), getY());
+               v1->setValue(getZ(), 0., -getX());
+               v2->setValue(-getY(), getX(), 0.);
+#endif
+       }
+
+       void setZero()
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128);
+#elif defined(B3_USE_NEON)
+               int32x4_t vi = vdupq_n_s32(0);
+               mVec128 = vreinterpretq_f32_s32(vi);
+#else
+               setValue(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+#endif
+       }
+
+       B3_FORCE_INLINE bool isZero() const
+       {
+               return m_floats[0] == b3Scalar(0) && m_floats[1] == b3Scalar(0) && m_floats[2] == b3Scalar(0);
+       }
+
+       B3_FORCE_INLINE bool fuzzyZero() const
+       {
+               return length2() < B3_EPSILON;
+       }
+
+       B3_FORCE_INLINE void serialize(struct b3Vector3Data & dataOut) const;
+
+       B3_FORCE_INLINE void deSerialize(const struct b3Vector3Data& dataIn);
+
+       B3_FORCE_INLINE void serializeFloat(struct b3Vector3FloatData & dataOut) const;
+
+       B3_FORCE_INLINE void deSerializeFloat(const struct b3Vector3FloatData& dataIn);
+
+       B3_FORCE_INLINE void serializeDouble(struct b3Vector3DoubleData & dataOut) const;
+
+       B3_FORCE_INLINE void deSerializeDouble(const struct b3Vector3DoubleData& dataIn);
+
+       /**@brief returns index of maximum dot product between this and vectors in array[]
+         * @param array The other vectors
+         * @param array_count The number of other vectors
+         * @param dotOut The maximum dot product */
+       B3_FORCE_INLINE long maxDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const;
+
+       /**@brief returns index of minimum dot product between this and vectors in array[]
+         * @param array The other vectors
+         * @param array_count The number of other vectors
+         * @param dotOut The minimum dot product */
+       B3_FORCE_INLINE long minDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const;
+
+       /* create a vector as  b3Vector3( this->dot( b3Vector3 v0 ), this->dot( b3Vector3 v1), this->dot( b3Vector3 v2 ))  */
+       B3_FORCE_INLINE b3Vector3 dot3(const b3Vector3& v0, const b3Vector3& v1, const b3Vector3& v2) const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+
+               __m128 a0 = _mm_mul_ps(v0.mVec128, this->mVec128);
+               __m128 a1 = _mm_mul_ps(v1.mVec128, this->mVec128);
+               __m128 a2 = _mm_mul_ps(v2.mVec128, this->mVec128);
+               __m128 b0 = _mm_unpacklo_ps(a0, a1);
+               __m128 b1 = _mm_unpackhi_ps(a0, a1);
+               __m128 b2 = _mm_unpacklo_ps(a2, _mm_setzero_ps());
+               __m128 r = _mm_movelh_ps(b0, b2);
+               r = _mm_add_ps(r, _mm_movehl_ps(b2, b0));
+               a2 = _mm_and_ps(a2, b3vxyzMaskf);
+               r = _mm_add_ps(r, b3CastdTo128f(_mm_move_sd(b3CastfTo128d(a2), b3CastfTo128d(b1))));
+               return b3MakeVector3(r);
+
+#elif defined(B3_USE_NEON)
+               static const uint32x4_t xyzMask = (const uint32x4_t){-1, -1, -1, 0};
+               float32x4_t a0 = vmulq_f32(v0.mVec128, this->mVec128);
+               float32x4_t a1 = vmulq_f32(v1.mVec128, this->mVec128);
+               float32x4_t a2 = vmulq_f32(v2.mVec128, this->mVec128);
+               float32x2x2_t zLo = vtrn_f32(vget_high_f32(a0), vget_high_f32(a1));
+               a2 = (float32x4_t)vandq_u32((uint32x4_t)a2, xyzMask);
+               float32x2_t b0 = vadd_f32(vpadd_f32(vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0]);
+               float32x2_t b1 = vpadd_f32(vpadd_f32(vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
+               return b3Vector3(vcombine_f32(b0, b1));
+#else
+               return b3MakeVector3(dot(v0), dot(v1), dot(v2));
+#endif
+       }
+};
+
+/**@brief Return the sum of two vectors (Point symantics)*/
+B3_FORCE_INLINE b3Vector3
+operator+(const b3Vector3& v1, const b3Vector3& v2)
+{
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+       return b3MakeVector3(_mm_add_ps(v1.mVec128, v2.mVec128));
+#elif defined(B3_USE_NEON)
+       return b3MakeVector3(vaddq_f32(v1.mVec128, v2.mVec128));
+#else
+       return b3MakeVector3(
+               v1.m_floats[0] + v2.m_floats[0],
+               v1.m_floats[1] + v2.m_floats[1],
+               v1.m_floats[2] + v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the elementwise product of two vectors */
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Vector3& v1, const b3Vector3& v2)
+{
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+       return b3MakeVector3(_mm_mul_ps(v1.mVec128, v2.mVec128));
+#elif defined(B3_USE_NEON)
+       return b3MakeVector3(vmulq_f32(v1.mVec128, v2.mVec128));
+#else
+       return b3MakeVector3(
+               v1.m_floats[0] * v2.m_floats[0],
+               v1.m_floats[1] * v2.m_floats[1],
+               v1.m_floats[2] * v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the difference between two vectors */
+B3_FORCE_INLINE b3Vector3
+operator-(const b3Vector3& v1, const b3Vector3& v2)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+
+       //      without _mm_and_ps this code causes slowdown in Concave moving
+       __m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128);
+       return b3MakeVector3(_mm_and_ps(r, b3vFFF0fMask));
+#elif defined(B3_USE_NEON)
+       float32x4_t r = vsubq_f32(v1.mVec128, v2.mVec128);
+       return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)r, b3vFFF0Mask));
+#else
+       return b3MakeVector3(
+               v1.m_floats[0] - v2.m_floats[0],
+               v1.m_floats[1] - v2.m_floats[1],
+               v1.m_floats[2] - v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the negative of the vector */
+B3_FORCE_INLINE b3Vector3
+operator-(const b3Vector3& v)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+       __m128 r = _mm_xor_ps(v.mVec128, b3vMzeroMask);
+       return b3MakeVector3(_mm_and_ps(r, b3vFFF0fMask));
+#elif defined(B3_USE_NEON)
+       return b3MakeVector3((b3SimdFloat4)veorq_s32((int32x4_t)v.mVec128, (int32x4_t)b3vMzeroMask));
+#else
+       return b3MakeVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
+#endif
+}
+
+/**@brief Return the vector scaled by s */
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Vector3& v, const b3Scalar& s)
+{
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+       __m128 vs = _mm_load_ss(&s);  //        (S 0 0 0)
+       vs = b3_pshufd_ps(vs, 0x80);  //        (S S S 0.0)
+       return b3MakeVector3(_mm_mul_ps(v.mVec128, vs));
+#elif defined(B3_USE_NEON)
+       float32x4_t r = vmulq_n_f32(v.mVec128, s);
+       return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)r, b3vFFF0Mask));
+#else
+       return b3MakeVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
+#endif
+}
+
+/**@brief Return the vector scaled by s */
+B3_FORCE_INLINE b3Vector3
+operator*(const b3Scalar& s, const b3Vector3& v)
+{
+       return v * s;
+}
+
+/**@brief Return the vector inversely scaled by s */
+B3_FORCE_INLINE b3Vector3
+operator/(const b3Vector3& v, const b3Scalar& s)
+{
+       b3FullAssert(s != b3Scalar(0.0));
+#if 0  //defined(B3_USE_SSE_IN_API)
+// this code is not faster !
+       __m128 vs = _mm_load_ss(&s);
+    vs = _mm_div_ss(b3v1110, vs);
+       vs = b3_pshufd_ps(vs, 0x00);    //      (S S S S)
+
+       return b3Vector3(_mm_mul_ps(v.mVec128, vs));
+#else
+       return v * (b3Scalar(1.0) / s);
+#endif
+}
+
+/**@brief Return the vector inversely scaled by s */
+B3_FORCE_INLINE b3Vector3
+operator/(const b3Vector3& v1, const b3Vector3& v2)
+{
+#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
+       __m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128);
+       vec = _mm_and_ps(vec, b3vFFF0fMask);
+       return b3MakeVector3(vec);
+#elif defined(B3_USE_NEON)
+       float32x4_t x, y, v, m;
+
+       x = v1.mVec128;
+       y = v2.mVec128;
+
+       v = vrecpeq_f32(y);     // v ~ 1/y
+       m = vrecpsq_f32(y, v);  // m = (2-v*y)
+       v = vmulq_f32(v, m);    // vv = v*m ~~ 1/y
+       m = vrecpsq_f32(y, v);  // mm = (2-vv*y)
+       v = vmulq_f32(v, x);    // x*vv
+       v = vmulq_f32(v, m);    // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
+
+       return b3Vector3(v);
+#else
+       return b3MakeVector3(
+               v1.m_floats[0] / v2.m_floats[0],
+               v1.m_floats[1] / v2.m_floats[1],
+               v1.m_floats[2] / v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the dot product between two vectors */
+B3_FORCE_INLINE b3Scalar
+b3Dot(const b3Vector3& v1, const b3Vector3& v2)
+{
+       return v1.dot(v2);
+}
+
+/**@brief Return the distance squared between two vectors */
+B3_FORCE_INLINE b3Scalar
+b3Distance2(const b3Vector3& v1, const b3Vector3& v2)
+{
+       return v1.distance2(v2);
+}
+
+/**@brief Return the distance between two vectors */
+B3_FORCE_INLINE b3Scalar
+b3Distance(const b3Vector3& v1, const b3Vector3& v2)
+{
+       return v1.distance(v2);
+}
+
+/**@brief Return the angle between two vectors */
+B3_FORCE_INLINE b3Scalar
+b3Angle(const b3Vector3& v1, const b3Vector3& v2)
+{
+       return v1.angle(v2);
+}
+
+/**@brief Return the cross product of two vectors */
+B3_FORCE_INLINE b3Vector3
+b3Cross(const b3Vector3& v1, const b3Vector3& v2)
+{
+       return v1.cross(v2);
+}
+
+B3_FORCE_INLINE b3Scalar
+b3Triple(const b3Vector3& v1, const b3Vector3& v2, const b3Vector3& v3)
+{
+       return v1.triple(v2, v3);
+}
+
+/**@brief Return the linear interpolation between two vectors
+ * @param v1 One vector
+ * @param v2 The other vector
+ * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
+B3_FORCE_INLINE b3Vector3
+b3Lerp(const b3Vector3& v1, const b3Vector3& v2, const b3Scalar& t)
+{
+       return v1.lerp(v2, t);
+}
+
+B3_FORCE_INLINE b3Scalar b3Vector3::distance2(const b3Vector3& v) const
+{
+       return (v - *this).length2();
+}
+
+B3_FORCE_INLINE b3Scalar b3Vector3::distance(const b3Vector3& v) const
+{
+       return (v - *this).length();
+}
+
+B3_FORCE_INLINE b3Vector3 b3Vector3::normalized() const
+{
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+       b3Vector3 norm = *this;
+
+       return norm.normalize();
+#else
+       return *this / length();
+#endif
+}
+
+B3_FORCE_INLINE b3Vector3 b3Vector3::rotate(const b3Vector3& wAxis, const b3Scalar _angle) const
+{
+       // wAxis must be a unit lenght vector
+
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+
+       __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
+       b3Scalar ssin = b3Sin(_angle);
+       __m128 C = wAxis.cross(b3MakeVector3(mVec128)).mVec128;
+       O = _mm_and_ps(O, b3vFFF0fMask);
+       b3Scalar scos = b3Cos(_angle);
+
+       __m128 vsin = _mm_load_ss(&ssin);  //   (S 0 0 0)
+       __m128 vcos = _mm_load_ss(&scos);  //   (S 0 0 0)
+
+       __m128 Y = b3_pshufd_ps(O, 0xC9);  //   (Y Z X 0)
+       __m128 Z = b3_pshufd_ps(O, 0xD2);  //   (Z X Y 0)
+       O = _mm_add_ps(O, Y);
+       vsin = b3_pshufd_ps(vsin, 0x80);  //    (S S S 0)
+       O = _mm_add_ps(O, Z);
+       vcos = b3_pshufd_ps(vcos, 0x80);  //    (S S S 0)
+
+       vsin = vsin * C;
+       O = O * wAxis.mVec128;
+       __m128 X = mVec128 - O;
+
+       O = O + vsin;
+       vcos = vcos * X;
+       O = O + vcos;
+
+       return b3MakeVector3(O);
+#else
+       b3Vector3 o = wAxis * wAxis.dot(*this);
+       b3Vector3 _x = *this - o;
+       b3Vector3 _y;
+
+       _y = wAxis.cross(*this);
+
+       return (o + _x * b3Cos(_angle) + _y * b3Sin(_angle));
+#endif
+}
+
+B3_FORCE_INLINE long b3Vector3::maxDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const
+{
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+#if defined _WIN32 || defined(B3_USE_SSE)
+       const long scalar_cutoff = 10;
+       long b3_maxdot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#elif defined B3_USE_NEON
+       const long scalar_cutoff = 4;
+       extern long (*_maxdot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#endif
+       if (array_count < scalar_cutoff)
+#else
+
+#endif  //B3_USE_SSE || B3_USE_NEON
+       {
+               b3Scalar maxDot = -B3_INFINITY;
+               int i = 0;
+               int ptIndex = -1;
+               for (i = 0; i < array_count; i++)
+               {
+                       b3Scalar dot = array[i].dot(*this);
+
+                       if (dot > maxDot)
+                       {
+                               maxDot = dot;
+                               ptIndex = i;
+                       }
+               }
+
+               b3Assert(ptIndex >= 0);
+               if (ptIndex < 0)
+               {
+                       ptIndex = 0;
+               }
+               dotOut = maxDot;
+               return ptIndex;
+       }
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+       return b3_maxdot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
+#endif
+}
+
+B3_FORCE_INLINE long b3Vector3::minDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const
+{
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+#if defined B3_USE_SSE
+       const long scalar_cutoff = 10;
+       long b3_mindot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#elif defined B3_USE_NEON
+       const long scalar_cutoff = 4;
+       extern long (*b3_mindot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#else
+#error unhandled arch!
+#endif
+
+       if (array_count < scalar_cutoff)
+#endif  //B3_USE_SSE || B3_USE_NEON
+       {
+               b3Scalar minDot = B3_INFINITY;
+               int i = 0;
+               int ptIndex = -1;
+
+               for (i = 0; i < array_count; i++)
+               {
+                       b3Scalar dot = array[i].dot(*this);
+
+                       if (dot < minDot)
+                       {
+                               minDot = dot;
+                               ptIndex = i;
+                       }
+               }
+
+               dotOut = minDot;
+
+               return ptIndex;
+       }
+#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
+       return b3_mindot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
+#endif
+}
+
+class b3Vector4 : public b3Vector3
+{
+public:
+       B3_FORCE_INLINE b3Vector4 absolute4() const
+       {
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+               return b3MakeVector4(_mm_and_ps(mVec128, b3vAbsfMask));
+#elif defined(B3_USE_NEON)
+               return b3Vector4(vabsq_f32(mVec128));
+#else
+               return b3MakeVector4(
+                       b3Fabs(m_floats[0]),
+                       b3Fabs(m_floats[1]),
+                       b3Fabs(m_floats[2]),
+                       b3Fabs(m_floats[3]));
+#endif
+       }
+
+       b3Scalar getW() const { return m_floats[3]; }
+
+       B3_FORCE_INLINE int maxAxis4() const
+       {
+               int maxIndex = -1;
+               b3Scalar maxVal = b3Scalar(-B3_LARGE_FLOAT);
+               if (m_floats[0] > maxVal)
+               {
+                       maxIndex = 0;
+                       maxVal = m_floats[0];
+               }
+               if (m_floats[1] > maxVal)
+               {
+                       maxIndex = 1;
+                       maxVal = m_floats[1];
+               }
+               if (m_floats[2] > maxVal)
+               {
+                       maxIndex = 2;
+                       maxVal = m_floats[2];
+               }
+               if (m_floats[3] > maxVal)
+               {
+                       maxIndex = 3;
+               }
+
+               return maxIndex;
+       }
+
+       B3_FORCE_INLINE int minAxis4() const
+       {
+               int minIndex = -1;
+               b3Scalar minVal = b3Scalar(B3_LARGE_FLOAT);
+               if (m_floats[0] < minVal)
+               {
+                       minIndex = 0;
+                       minVal = m_floats[0];
+               }
+               if (m_floats[1] < minVal)
+               {
+                       minIndex = 1;
+                       minVal = m_floats[1];
+               }
+               if (m_floats[2] < minVal)
+               {
+                       minIndex = 2;
+                       minVal = m_floats[2];
+               }
+               if (m_floats[3] < minVal)
+               {
+                       minIndex = 3;
+                       minVal = m_floats[3];
+               }
+
+               return minIndex;
+       }
+
+       B3_FORCE_INLINE int closestAxis4() const
+       {
+               return absolute4().maxAxis4();
+       }
+
+       /**@brief Set x,y,z and zero w
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+
+       /*              void getValue(b3Scalar *m) const
+               {
+                       m[0] = m_floats[0];
+                       m[1] = m_floats[1];
+                       m[2] =m_floats[2];
+               }
+*/
+       /**@brief Set the values
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+       B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
+       {
+               m_floats[0] = _x;
+               m_floats[1] = _y;
+               m_floats[2] = _z;
+               m_floats[3] = _w;
+       }
+};
+
+///b3SwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+B3_FORCE_INLINE void b3SwapScalarEndian(const b3Scalar& sourceVal, b3Scalar& destVal)
+{
+#ifdef B3_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  //B3_USE_DOUBLE_PRECISION
+}
+///b3SwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+B3_FORCE_INLINE void b3SwapVector3Endian(const b3Vector3& sourceVec, b3Vector3& destVec)
+{
+       for (int i = 0; i < 4; i++)
+       {
+               b3SwapScalarEndian(sourceVec[i], destVec[i]);
+       }
+}
+
+///b3UnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+B3_FORCE_INLINE void b3UnSwapVector3Endian(b3Vector3& vector)
+{
+       b3Vector3 swappedVec;
+       for (int i = 0; i < 4; i++)
+       {
+               b3SwapScalarEndian(vector[i], swappedVec[i]);
+       }
+       vector = swappedVec;
+}
+
+template <class T>
+B3_FORCE_INLINE void b3PlaneSpace1(const T& n, T& p, T& q)
+{
+       if (b3Fabs(n[2]) > B3_SQRT12)
+       {
+               // choose p in y-z plane
+               b3Scalar a = n[1] * n[1] + n[2] * n[2];
+               b3Scalar k = b3RecipSqrt(a);
+               p[0] = 0;
+               p[1] = -n[2] * k;
+               p[2] = n[1] * k;
+               // set q = n x p
+               q[0] = a * k;
+               q[1] = -n[0] * p[2];
+               q[2] = n[0] * p[1];
+       }
+       else
+       {
+               // choose p in x-y plane
+               b3Scalar a = n[0] * n[0] + n[1] * n[1];
+               b3Scalar k = b3RecipSqrt(a);
+               p[0] = -n[1] * k;
+               p[1] = n[0] * k;
+               p[2] = 0;
+               // set q = n x p
+               q[0] = -n[2] * p[1];
+               q[1] = n[2] * p[0];
+               q[2] = a * k;
+       }
+}
+
+struct b3Vector3FloatData
+{
+       float m_floats[4];
+};
+
+struct b3Vector3DoubleData
+{
+       double m_floats[4];
+};
+
+B3_FORCE_INLINE void b3Vector3::serializeFloat(struct b3Vector3FloatData& dataOut) const
+{
+       ///could also do a memcpy, check if it is worth it
+       for (int i = 0; i < 4; i++)
+               dataOut.m_floats[i] = float(m_floats[i]);
+}
+
+B3_FORCE_INLINE void b3Vector3::deSerializeFloat(const struct b3Vector3FloatData& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = b3Scalar(dataIn.m_floats[i]);
+}
+
+B3_FORCE_INLINE void b3Vector3::serializeDouble(struct b3Vector3DoubleData& dataOut) const
+{
+       ///could also do a memcpy, check if it is worth it
+       for (int i = 0; i < 4; i++)
+               dataOut.m_floats[i] = double(m_floats[i]);
+}
+
+B3_FORCE_INLINE void b3Vector3::deSerializeDouble(const struct b3Vector3DoubleData& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = b3Scalar(dataIn.m_floats[i]);
+}
+
+B3_FORCE_INLINE void b3Vector3::serialize(struct b3Vector3Data& dataOut) const
+{
+       ///could also do a memcpy, check if it is worth it
+       for (int i = 0; i < 4; i++)
+               dataOut.m_floats[i] = m_floats[i];
+}
+
+B3_FORCE_INLINE void b3Vector3::deSerialize(const struct b3Vector3Data& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = dataIn.m_floats[i];
+}
+
+inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z)
+{
+       b3Vector3 tmp;
+       tmp.setValue(x, y, z);
+       return tmp;
+}
+
+inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w)
+{
+       b3Vector3 tmp;
+       tmp.setValue(x, y, z);
+       tmp.w = w;
+       return tmp;
+}
+
+inline b3Vector4 b3MakeVector4(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w)
+{
+       b3Vector4 tmp;
+       tmp.setValue(x, y, z, w);
+       return tmp;
+}
+
+#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
+
+inline b3Vector3 b3MakeVector3(b3SimdFloat4 v)
+{
+       b3Vector3 tmp;
+       tmp.set128(v);
+       return tmp;
+}
+
+inline b3Vector4 b3MakeVector4(b3SimdFloat4 vec)
+{
+       b3Vector4 tmp;
+       tmp.set128(vec);
+       return tmp;
+}
+
+#endif
+
+#endif  //B3_VECTOR3_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/premake4.lua b/dali-physics/third-party/bullet3/src/Bullet3Common/premake4.lua
new file mode 100644 (file)
index 0000000..f03573e
--- /dev/null
@@ -0,0 +1,16 @@
+       project "Bullet3Common"
+
+       language "C++"
+                               
+       kind "StaticLib"
+               
+       if os.is("Linux") then
+           buildoptions{"-fPIC"}
+       end
+
+       includedirs {".."}
+
+       files {
+               "*.cpp",
+               "*.h"
+       }
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Float4.h b/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Float4.h
new file mode 100644 (file)
index 0000000..d8a9f47
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef B3_FLOAT4_H
+#define B3_FLOAT4_H
+
+#include "Bullet3Common/shared/b3PlatformDefinitions.h"
+
+#ifdef __cplusplus
+#include "Bullet3Common/b3Vector3.h"
+#define b3Float4 b3Vector3
+#define b3Float4ConstArg const b3Vector3&
+#define b3Dot3F4 b3Dot
+#define b3Cross3 b3Cross
+#define b3MakeFloat4 b3MakeVector3
+inline b3Vector3 b3Normalized(const b3Vector3& vec)
+{
+       return vec.normalized();
+}
+
+inline b3Float4 b3FastNormalized3(b3Float4ConstArg v)
+{
+       return v.normalized();
+}
+
+inline b3Float4 b3MaxFloat4(const b3Float4& a, const b3Float4& b)
+{
+       b3Float4 tmp = a;
+       tmp.setMax(b);
+       return tmp;
+}
+inline b3Float4 b3MinFloat4(const b3Float4& a, const b3Float4& b)
+{
+       b3Float4 tmp = a;
+       tmp.setMin(b);
+       return tmp;
+}
+
+#else
+typedef float4 b3Float4;
+#define b3Float4ConstArg const b3Float4
+#define b3MakeFloat4 (float4)
+float b3Dot3F4(b3Float4ConstArg v0, b3Float4ConstArg v1)
+{
+       float4 a1 = b3MakeFloat4(v0.xyz, 0.f);
+       float4 b1 = b3MakeFloat4(v1.xyz, 0.f);
+       return dot(a1, b1);
+}
+b3Float4 b3Cross3(b3Float4ConstArg v0, b3Float4ConstArg v1)
+{
+       float4 a1 = b3MakeFloat4(v0.xyz, 0.f);
+       float4 b1 = b3MakeFloat4(v1.xyz, 0.f);
+       return cross(a1, b1);
+}
+#define b3MinFloat4 min
+#define b3MaxFloat4 max
+
+#define b3Normalized(a) normalize(a)
+
+#endif
+
+inline bool b3IsAlmostZero(b3Float4ConstArg v)
+{
+       if (b3Fabs(v.x) > 1e-6 || b3Fabs(v.y) > 1e-6 || b3Fabs(v.z) > 1e-6)
+               return false;
+       return true;
+}
+
+inline int b3MaxDot(b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut)
+{
+       float maxDot = -B3_INFINITY;
+       int i = 0;
+       int ptIndex = -1;
+       for (i = 0; i < vecLen; i++)
+       {
+               float dot = b3Dot3F4(vecArray[i], vec);
+
+               if (dot > maxDot)
+               {
+                       maxDot = dot;
+                       ptIndex = i;
+               }
+       }
+       b3Assert(ptIndex >= 0);
+       if (ptIndex < 0)
+       {
+               ptIndex = 0;
+       }
+       *dotOut = maxDot;
+       return ptIndex;
+}
+
+#endif  //B3_FLOAT4_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Int2.h b/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Int2.h
new file mode 100644 (file)
index 0000000..7b84de4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_INT2_H
+#define B3_INT2_H
+
+#ifdef __cplusplus
+
+struct b3UnsignedInt2
+{
+       union {
+               struct
+               {
+                       unsigned int x, y;
+               };
+               struct
+               {
+                       unsigned int s[2];
+               };
+       };
+};
+
+struct b3Int2
+{
+       union {
+               struct
+               {
+                       int x, y;
+               };
+               struct
+               {
+                       int s[2];
+               };
+       };
+};
+
+inline b3Int2 b3MakeInt2(int x, int y)
+{
+       b3Int2 v;
+       v.s[0] = x;
+       v.s[1] = y;
+       return v;
+}
+#else
+
+#define b3UnsignedInt2 uint2
+#define b3Int2 int2
+#define b3MakeInt2 (int2)
+
+#endif  //__cplusplus
+#endif
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Int4.h b/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Int4.h
new file mode 100644 (file)
index 0000000..f6a1754
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef B3_INT4_H
+#define B3_INT4_H
+
+#ifdef __cplusplus
+
+#include "Bullet3Common/b3Scalar.h"
+
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3UnsignedInt4
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       union {
+               struct
+               {
+                       unsigned int x, y, z, w;
+               };
+               struct
+               {
+                       unsigned int s[4];
+               };
+       };
+};
+
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3Int4
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       union {
+               struct
+               {
+                       int x, y, z, w;
+               };
+               struct
+               {
+                       int s[4];
+               };
+       };
+};
+
+B3_FORCE_INLINE b3Int4 b3MakeInt4(int x, int y, int z, int w = 0)
+{
+       b3Int4 v;
+       v.s[0] = x;
+       v.s[1] = y;
+       v.s[2] = z;
+       v.s[3] = w;
+       return v;
+}
+
+B3_FORCE_INLINE b3UnsignedInt4 b3MakeUnsignedInt4(unsigned int x, unsigned int y, unsigned int z, unsigned int w = 0)
+{
+       b3UnsignedInt4 v;
+       v.s[0] = x;
+       v.s[1] = y;
+       v.s[2] = z;
+       v.s[3] = w;
+       return v;
+}
+
+#else
+
+#define b3UnsignedInt4 uint4
+#define b3Int4 int4
+#define b3MakeInt4 (int4)
+#define b3MakeUnsignedInt4 (uint4)
+
+#endif  //__cplusplus
+
+#endif  //B3_INT4_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Mat3x3.h b/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Mat3x3.h
new file mode 100644 (file)
index 0000000..ce6482b
--- /dev/null
@@ -0,0 +1,157 @@
+
+#ifndef B3_MAT3x3_H
+#define B3_MAT3x3_H
+
+#include "Bullet3Common/shared/b3Quat.h"
+
+#ifdef __cplusplus
+
+#include "Bullet3Common/b3Matrix3x3.h"
+
+#define b3Mat3x3 b3Matrix3x3
+#define b3Mat3x3ConstArg const b3Matrix3x3&
+
+inline b3Mat3x3 b3QuatGetRotationMatrix(b3QuatConstArg quat)
+{
+       return b3Mat3x3(quat);
+}
+
+inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg mat)
+{
+       return mat.absolute();
+}
+
+#define b3GetRow(m, row) m.getRow(row)
+
+__inline b3Float4 mtMul3(b3Float4ConstArg a, b3Mat3x3ConstArg b)
+{
+       return b * a;
+}
+
+#else
+
+typedef struct
+{
+       b3Float4 m_row[3];
+} b3Mat3x3;
+
+#define b3Mat3x3ConstArg const b3Mat3x3
+#define b3GetRow(m, row) (m.m_row[row])
+
+inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)
+{
+       b3Float4 quat2 = (b3Float4)(quat.x * quat.x, quat.y * quat.y, quat.z * quat.z, 0.f);
+       b3Mat3x3 out;
+
+       out.m_row[0].x = 1 - 2 * quat2.y - 2 * quat2.z;
+       out.m_row[0].y = 2 * quat.x * quat.y - 2 * quat.w * quat.z;
+       out.m_row[0].z = 2 * quat.x * quat.z + 2 * quat.w * quat.y;
+       out.m_row[0].w = 0.f;
+
+       out.m_row[1].x = 2 * quat.x * quat.y + 2 * quat.w * quat.z;
+       out.m_row[1].y = 1 - 2 * quat2.x - 2 * quat2.z;
+       out.m_row[1].z = 2 * quat.y * quat.z - 2 * quat.w * quat.x;
+       out.m_row[1].w = 0.f;
+
+       out.m_row[2].x = 2 * quat.x * quat.z - 2 * quat.w * quat.y;
+       out.m_row[2].y = 2 * quat.y * quat.z + 2 * quat.w * quat.x;
+       out.m_row[2].z = 1 - 2 * quat2.x - 2 * quat2.y;
+       out.m_row[2].w = 0.f;
+
+       return out;
+}
+
+inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)
+{
+       b3Mat3x3 out;
+       out.m_row[0] = fabs(matIn.m_row[0]);
+       out.m_row[1] = fabs(matIn.m_row[1]);
+       out.m_row[2] = fabs(matIn.m_row[2]);
+       return out;
+}
+
+__inline b3Mat3x3 mtZero();
+
+__inline b3Mat3x3 mtIdentity();
+
+__inline b3Mat3x3 mtTranspose(b3Mat3x3 m);
+
+__inline b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);
+
+__inline b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);
+
+__inline b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);
+
+__inline b3Mat3x3 mtZero()
+{
+       b3Mat3x3 m;
+       m.m_row[0] = (b3Float4)(0.f);
+       m.m_row[1] = (b3Float4)(0.f);
+       m.m_row[2] = (b3Float4)(0.f);
+       return m;
+}
+
+__inline b3Mat3x3 mtIdentity()
+{
+       b3Mat3x3 m;
+       m.m_row[0] = (b3Float4)(1, 0, 0, 0);
+       m.m_row[1] = (b3Float4)(0, 1, 0, 0);
+       m.m_row[2] = (b3Float4)(0, 0, 1, 0);
+       return m;
+}
+
+__inline b3Mat3x3 mtTranspose(b3Mat3x3 m)
+{
+       b3Mat3x3 out;
+       out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
+       out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
+       out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
+       return out;
+}
+
+__inline b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)
+{
+       b3Mat3x3 transB;
+       transB = mtTranspose(b);
+       b3Mat3x3 ans;
+       //      why this doesn't run when 0ing in the for{}
+       a.m_row[0].w = 0.f;
+       a.m_row[1].w = 0.f;
+       a.m_row[2].w = 0.f;
+       for (int i = 0; i < 3; i++)
+       {
+               //      a.m_row[i].w = 0.f;
+               ans.m_row[i].x = b3Dot3F4(a.m_row[i], transB.m_row[0]);
+               ans.m_row[i].y = b3Dot3F4(a.m_row[i], transB.m_row[1]);
+               ans.m_row[i].z = b3Dot3F4(a.m_row[i], transB.m_row[2]);
+               ans.m_row[i].w = 0.f;
+       }
+       return ans;
+}
+
+__inline b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)
+{
+       b3Float4 ans;
+       ans.x = b3Dot3F4(a.m_row[0], b);
+       ans.y = b3Dot3F4(a.m_row[1], b);
+       ans.z = b3Dot3F4(a.m_row[2], b);
+       ans.w = 0.f;
+       return ans;
+}
+
+__inline b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)
+{
+       b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+       b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+       b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+       b3Float4 ans;
+       ans.x = b3Dot3F4(a, colx);
+       ans.y = b3Dot3F4(a, coly);
+       ans.z = b3Dot3F4(a, colz);
+       return ans;
+}
+
+#endif
+
+#endif  //B3_MAT3x3_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3PlatformDefinitions.h b/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3PlatformDefinitions.h
new file mode 100644 (file)
index 0000000..b72bee9
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef B3_PLATFORM_DEFINITIONS_H
+#define B3_PLATFORM_DEFINITIONS_H
+
+struct MyTest
+{
+       int bla;
+};
+
+#ifdef __cplusplus
+//#define b3ConstArray(a) const b3AlignedObjectArray<a>&
+#define b3ConstArray(a) const a *
+#define b3AtomicInc(a) ((*a)++)
+
+inline int b3AtomicAdd(volatile int *p, int val)
+{
+       int oldValue = *p;
+       int newValue = oldValue + val;
+       *p = newValue;
+       return oldValue;
+}
+
+#define __global
+
+#define B3_STATIC static
+#else
+//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX
+#define B3_LARGE_FLOAT 1e18f
+#define B3_INFINITY 1e18f
+#define b3Assert(a)
+#define b3ConstArray(a) __global const a *
+#define b3AtomicInc atomic_inc
+#define b3AtomicAdd atomic_add
+#define b3Fabs fabs
+#define b3Sqrt native_sqrt
+#define b3Sin native_sin
+#define b3Cos native_cos
+
+#define B3_STATIC
+#endif
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Quat.h b/dali-physics/third-party/bullet3/src/Bullet3Common/shared/b3Quat.h
new file mode 100644 (file)
index 0000000..940610c
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef B3_QUAT_H
+#define B3_QUAT_H
+
+#include "Bullet3Common/shared/b3PlatformDefinitions.h"
+#include "Bullet3Common/shared/b3Float4.h"
+
+#ifdef __cplusplus
+#include "Bullet3Common/b3Quaternion.h"
+#include "Bullet3Common/b3Transform.h"
+
+#define b3Quat b3Quaternion
+#define b3QuatConstArg const b3Quaternion&
+inline b3Quat b3QuatInverse(b3QuatConstArg orn)
+{
+       return orn.inverse();
+}
+
+inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)
+{
+       b3Transform tr;
+       tr.setOrigin(translation);
+       tr.setRotation(orientation);
+       return tr(point);
+}
+
+#else
+typedef float4 b3Quat;
+#define b3QuatConstArg const b3Quat
+
+inline float4 b3FastNormalize4(float4 v)
+{
+       v = (float4)(v.xyz, 0.f);
+       return fast_normalize(v);
+}
+
+inline b3Quat b3QuatMul(b3Quat a, b3Quat b);
+inline b3Quat b3QuatNormalized(b3QuatConstArg in);
+inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);
+inline b3Quat b3QuatInvert(b3QuatConstArg q);
+inline b3Quat b3QuatInverse(b3QuatConstArg q);
+
+inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)
+{
+       b3Quat ans;
+       ans = b3Cross3(a, b);
+       ans += a.w * b + b.w * a;
+       //      ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+       ans.w = a.w * b.w - b3Dot3F4(a, b);
+       return ans;
+}
+
+inline b3Quat b3QuatNormalized(b3QuatConstArg in)
+{
+       b3Quat q;
+       q = in;
+       //return b3FastNormalize4(in);
+       float len = native_sqrt(dot(q, q));
+       if (len > 0.f)
+       {
+               q *= 1.f / len;
+       }
+       else
+       {
+               q.x = q.y = q.z = 0.f;
+               q.w = 1.f;
+       }
+       return q;
+}
+inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)
+{
+       b3Quat qInv = b3QuatInvert(q);
+       float4 vcpy = vec;
+       vcpy.w = 0.f;
+       float4 out = b3QuatMul(b3QuatMul(q, vcpy), qInv);
+       return out;
+}
+
+inline b3Quat b3QuatInverse(b3QuatConstArg q)
+{
+       return (b3Quat)(-q.xyz, q.w);
+}
+
+inline b3Quat b3QuatInvert(b3QuatConstArg q)
+{
+       return (b3Quat)(-q.xyz, q.w);
+}
+
+inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)
+{
+       return b3QuatRotate(b3QuatInvert(q), vec);
+}
+
+inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)
+{
+       return b3QuatRotate(orientation, point) + (translation);
+}
+
+#endif
+
+#endif  //B3_QUAT_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/CMakeLists.txt b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/CMakeLists.txt
new file mode 100644 (file)
index 0000000..94c120d
--- /dev/null
@@ -0,0 +1,61 @@
+
+INCLUDE_DIRECTORIES(
+       ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(Bullet3Dynamics_SRCS
+       b3CpuRigidBodyPipeline.cpp
+       ConstraintSolver/b3FixedConstraint.cpp
+       ConstraintSolver/b3Generic6DofConstraint.cpp
+       ConstraintSolver/b3PgsJacobiSolver.cpp
+       ConstraintSolver/b3Point2PointConstraint.cpp
+       ConstraintSolver/b3TypedConstraint.cpp
+)
+
+SET(Bullet3Dynamics_HDRS
+         b3CpuRigidBodyPipeline.h
+       ConstraintSolver/b3ContactSolverInfo.h
+       ConstraintSolver/b3FixedConstraint.h
+       ConstraintSolver/b3Generic6DofConstraint.h
+       ConstraintSolver/b3JacobianEntry.h
+       ConstraintSolver/b3PgsJacobiSolver.h
+       ConstraintSolver/b3Point2PointConstraint.h
+       ConstraintSolver/b3SolverBody.h
+       ConstraintSolver/b3SolverConstraint.h
+       ConstraintSolver/b3TypedConstraint.h
+       shared/b3ContactConstraint4.h
+       shared/b3ConvertConstraint4.h
+       shared/b3Inertia.h
+       shared/b3IntegrateTransforms.h
+)
+
+ADD_LIBRARY(Bullet3Dynamics ${Bullet3Dynamics_SRCS} ${Bullet3Dynamics_HDRS})
+if (BUILD_SHARED_LIBS)
+  target_link_libraries(Bullet3Dynamics Bullet3Collision)
+endif ()
+SET_TARGET_PROPERTIES(Bullet3Dynamics PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet3Dynamics PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               #FILES_MATCHING requires CMake 2.6
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet3Dynamics DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet3Dynamics
+                                       RUNTIME DESTINATION bin
+                                       LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                       ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h"  PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(Bullet3Dynamics PROPERTIES FRAMEWORK true)
+                       SET_TARGET_PROPERTIES(Bullet3Dynamics PROPERTIES PUBLIC_HEADER "${Bullet3Dynamics_HDRS}")
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h
new file mode 100644 (file)
index 0000000..e946c2a
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_CONTACT_SOLVER_INFO
+#define B3_CONTACT_SOLVER_INFO
+
+#include "Bullet3Common/b3Scalar.h"
+
+enum b3SolverMode
+{
+       B3_SOLVER_RANDMIZE_ORDER = 1,
+       B3_SOLVER_FRICTION_SEPARATE = 2,
+       B3_SOLVER_USE_WARMSTARTING = 4,
+       B3_SOLVER_USE_2_FRICTION_DIRECTIONS = 16,
+       B3_SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32,
+       B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64,
+       B3_SOLVER_CACHE_FRIENDLY = 128,
+       B3_SOLVER_SIMD = 256,
+       B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512,
+       B3_SOLVER_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024
+};
+
+struct b3ContactSolverInfoData
+{
+       b3Scalar m_tau;
+       b3Scalar m_damping;  //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+       b3Scalar m_friction;
+       b3Scalar m_timeStep;
+       b3Scalar m_restitution;
+       int m_numIterations;
+       b3Scalar m_maxErrorReduction;
+       b3Scalar m_sor;
+       b3Scalar m_erp;        //used as Baumgarte factor
+       b3Scalar m_erp2;       //used in Split Impulse
+       b3Scalar m_globalCfm;  //constraint force mixing
+       int m_splitImpulse;
+       b3Scalar m_splitImpulsePenetrationThreshold;
+       b3Scalar m_splitImpulseTurnErp;
+       b3Scalar m_linearSlop;
+       b3Scalar m_warmstartingFactor;
+
+       int m_solverMode;
+       int m_restingContactRestitutionThreshold;
+       int m_minimumSolverBatchSize;
+       b3Scalar m_maxGyroscopicForce;
+       b3Scalar m_singleAxisRollingFrictionThreshold;
+};
+
+struct b3ContactSolverInfo : public b3ContactSolverInfoData
+{
+       inline b3ContactSolverInfo()
+       {
+               m_tau = b3Scalar(0.6);
+               m_damping = b3Scalar(1.0);
+               m_friction = b3Scalar(0.3);
+               m_timeStep = b3Scalar(1.f / 60.f);
+               m_restitution = b3Scalar(0.);
+               m_maxErrorReduction = b3Scalar(20.);
+               m_numIterations = 10;
+               m_erp = b3Scalar(0.2);
+               m_erp2 = b3Scalar(0.8);
+               m_globalCfm = b3Scalar(0.);
+               m_sor = b3Scalar(1.);
+               m_splitImpulse = true;
+               m_splitImpulsePenetrationThreshold = -.04f;
+               m_splitImpulseTurnErp = 0.1f;
+               m_linearSlop = b3Scalar(0.0);
+               m_warmstartingFactor = b3Scalar(0.85);
+               //m_solverMode =  B3_SOLVER_USE_WARMSTARTING |  B3_SOLVER_SIMD | B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | B3_SOLVER_RANDMIZE_ORDER;
+               m_solverMode = B3_SOLVER_USE_WARMSTARTING | B3_SOLVER_SIMD;  // | B3_SOLVER_RANDMIZE_ORDER;
+               m_restingContactRestitutionThreshold = 2;                    //unused as of 2.81
+               m_minimumSolverBatchSize = 128;                              //try to combine islands until the amount of constraints reaches this limit
+               m_maxGyroscopicForce = 100.f;                                ///only used to clamp forces for bodies that have their B3_ENABLE_GYROPSCOPIC_FORCE flag set (using b3RigidBody::setFlag)
+               m_singleAxisRollingFrictionThreshold = 1e30f;                ///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
+       }
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3ContactSolverInfoDoubleData
+{
+       double m_tau;
+       double m_damping;  //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+       double m_friction;
+       double m_timeStep;
+       double m_restitution;
+       double m_maxErrorReduction;
+       double m_sor;
+       double m_erp;        //used as Baumgarte factor
+       double m_erp2;       //used in Split Impulse
+       double m_globalCfm;  //constraint force mixing
+       double m_splitImpulsePenetrationThreshold;
+       double m_splitImpulseTurnErp;
+       double m_linearSlop;
+       double m_warmstartingFactor;
+       double m_maxGyroscopicForce;
+       double m_singleAxisRollingFrictionThreshold;
+
+       int m_numIterations;
+       int m_solverMode;
+       int m_restingContactRestitutionThreshold;
+       int m_minimumSolverBatchSize;
+       int m_splitImpulse;
+       char m_padding[4];
+};
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3ContactSolverInfoFloatData
+{
+       float m_tau;
+       float m_damping;  //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+       float m_friction;
+       float m_timeStep;
+
+       float m_restitution;
+       float m_maxErrorReduction;
+       float m_sor;
+       float m_erp;  //used as Baumgarte factor
+
+       float m_erp2;       //used in Split Impulse
+       float m_globalCfm;  //constraint force mixing
+       float m_splitImpulsePenetrationThreshold;
+       float m_splitImpulseTurnErp;
+
+       float m_linearSlop;
+       float m_warmstartingFactor;
+       float m_maxGyroscopicForce;
+       float m_singleAxisRollingFrictionThreshold;
+
+       int m_numIterations;
+       int m_solverMode;
+       int m_restingContactRestitutionThreshold;
+       int m_minimumSolverBatchSize;
+
+       int m_splitImpulse;
+       char m_padding[4];
+};
+
+#endif  //B3_CONTACT_SOLVER_INFO
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp
new file mode 100644 (file)
index 0000000..ace4b18
--- /dev/null
@@ -0,0 +1,103 @@
+
+#include "b3FixedConstraint.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Common/b3TransformUtil.h"
+#include <new>
+
+b3FixedConstraint::b3FixedConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB)
+       : b3TypedConstraint(B3_FIXED_CONSTRAINT_TYPE, rbA, rbB)
+{
+       m_pivotInA = frameInA.getOrigin();
+       m_pivotInB = frameInB.getOrigin();
+       m_relTargetAB = frameInA.getRotation() * frameInB.getRotation().inverse();
+}
+
+b3FixedConstraint::~b3FixedConstraint()
+{
+}
+
+void b3FixedConstraint::getInfo1(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
+{
+       info->m_numConstraintRows = 6;
+       info->nub = 6;
+}
+
+void b3FixedConstraint::getInfo2(b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
+{
+       //fix the 3 linear degrees of freedom
+
+       const b3Vector3& worldPosA = bodies[m_rbA].m_pos;
+       const b3Quaternion& worldOrnA = bodies[m_rbA].m_quat;
+       const b3Vector3& worldPosB = bodies[m_rbB].m_pos;
+       const b3Quaternion& worldOrnB = bodies[m_rbB].m_quat;
+
+       info->m_J1linearAxis[0] = 1;
+       info->m_J1linearAxis[info->rowskip + 1] = 1;
+       info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
+
+       b3Vector3 a1 = b3QuatRotate(worldOrnA, m_pivotInA);
+       {
+               b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
+               b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis + info->rowskip);
+               b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis + 2 * info->rowskip);
+               b3Vector3 a1neg = -a1;
+               a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+
+       if (info->m_J2linearAxis)
+       {
+               info->m_J2linearAxis[0] = -1;
+               info->m_J2linearAxis[info->rowskip + 1] = -1;
+               info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
+       }
+
+       b3Vector3 a2 = b3QuatRotate(worldOrnB, m_pivotInB);
+
+       {
+               //      b3Vector3 a2n = -a2;
+               b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
+               b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis + info->rowskip);
+               b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis + 2 * info->rowskip);
+               a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+
+       // set right hand side for the linear dofs
+       b3Scalar k = info->fps * info->erp;
+       b3Vector3 linearError = k * (a2 + worldPosB - a1 - worldPosA);
+       int j;
+       for (j = 0; j < 3; j++)
+       {
+               info->m_constraintError[j * info->rowskip] = linearError[j];
+               //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
+       }
+
+       //fix the 3 angular degrees of freedom
+
+       int start_row = 3;
+       int s = info->rowskip;
+       int start_index = start_row * s;
+
+       // 3 rows to make body rotations equal
+       info->m_J1angularAxis[start_index] = 1;
+       info->m_J1angularAxis[start_index + s + 1] = 1;
+       info->m_J1angularAxis[start_index + s * 2 + 2] = 1;
+       if (info->m_J2angularAxis)
+       {
+               info->m_J2angularAxis[start_index] = -1;
+               info->m_J2angularAxis[start_index + s + 1] = -1;
+               info->m_J2angularAxis[start_index + s * 2 + 2] = -1;
+       }
+
+       // set right hand side for the angular dofs
+
+       b3Vector3 diff;
+       b3Scalar angle;
+       b3Quaternion qrelCur = worldOrnA * worldOrnB.inverse();
+
+       b3TransformUtil::calculateDiffAxisAngleQuaternion(m_relTargetAB, qrelCur, diff, angle);
+       diff *= -angle;
+       for (j = 0; j < 3; j++)
+       {
+               info->m_constraintError[(3 + j) * info->rowskip] = k * diff[j];
+       }
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h
new file mode 100644 (file)
index 0000000..6480966
--- /dev/null
@@ -0,0 +1,34 @@
+
+#ifndef B3_FIXED_CONSTRAINT_H
+#define B3_FIXED_CONSTRAINT_H
+
+#include "b3TypedConstraint.h"
+
+B3_ATTRIBUTE_ALIGNED16(class)
+b3FixedConstraint : public b3TypedConstraint
+{
+       b3Vector3 m_pivotInA;
+       b3Vector3 m_pivotInB;
+       b3Quaternion m_relTargetAB;
+
+public:
+       b3FixedConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB);
+
+       virtual ~b3FixedConstraint();
+
+       virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
+
+       virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies);
+
+       virtual void setParam(int num, b3Scalar value, int axis = -1)
+       {
+               b3Assert(0);
+       }
+       virtual b3Scalar getParam(int num, int axis = -1) const
+       {
+               b3Assert(0);
+               return 0.f;
+       }
+};
+
+#endif  //B3_FIXED_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp
new file mode 100644 (file)
index 0000000..fd3e518
--- /dev/null
@@ -0,0 +1,737 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3Generic6DofConstraint.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include "Bullet3Common/b3TransformUtil.h"
+#include "Bullet3Common/b3TransformUtil.h"
+#include <new>
+
+#define D6_USE_OBSOLETE_METHOD false
+#define D6_USE_FRAME_OFFSET true
+
+b3Generic6DofConstraint::b3Generic6DofConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB, bool useLinearReferenceFrameA, const b3RigidBodyData* bodies)
+       : b3TypedConstraint(B3_D6_CONSTRAINT_TYPE, rbA, rbB), m_frameInA(frameInA), m_frameInB(frameInB), m_useLinearReferenceFrameA(useLinearReferenceFrameA), m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), m_flags(0)
+{
+       calculateTransforms(bodies);
+}
+
+#define GENERIC_D6_DISABLE_WARMSTARTING 1
+
+b3Scalar btGetMatrixElem(const b3Matrix3x3& mat, int index);
+b3Scalar btGetMatrixElem(const b3Matrix3x3& mat, int index)
+{
+       int i = index % 3;
+       int j = index / 3;
+       return mat[i][j];
+}
+
+///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
+bool matrixToEulerXYZ(const b3Matrix3x3& mat, b3Vector3& xyz);
+bool matrixToEulerXYZ(const b3Matrix3x3& mat, b3Vector3& xyz)
+{
+       //      // rot =  cy*cz          -cy*sz           sy
+       //      //        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
+       //      //       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
+       //
+
+       b3Scalar fi = btGetMatrixElem(mat, 2);
+       if (fi < b3Scalar(1.0f))
+       {
+               if (fi > b3Scalar(-1.0f))
+               {
+                       xyz[0] = b3Atan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 8));
+                       xyz[1] = b3Asin(btGetMatrixElem(mat, 2));
+                       xyz[2] = b3Atan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
+                       return true;
+               }
+               else
+               {
+                       // WARNING.  Not unique.  XA - ZA = -atan2(r10,r11)
+                       xyz[0] = -b3Atan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
+                       xyz[1] = -B3_HALF_PI;
+                       xyz[2] = b3Scalar(0.0);
+                       return false;
+               }
+       }
+       else
+       {
+               // WARNING.  Not unique.  XAngle + ZAngle = atan2(r10,r11)
+               xyz[0] = b3Atan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
+               xyz[1] = B3_HALF_PI;
+               xyz[2] = 0.0;
+       }
+       return false;
+}
+
+//////////////////////////// b3RotationalLimitMotor ////////////////////////////////////
+
+int b3RotationalLimitMotor::testLimitValue(b3Scalar test_value)
+{
+       if (m_loLimit > m_hiLimit)
+       {
+               m_currentLimit = 0;  //Free from violation
+               return 0;
+       }
+       if (test_value < m_loLimit)
+       {
+               m_currentLimit = 1;  //low limit violation
+               m_currentLimitError = test_value - m_loLimit;
+               if (m_currentLimitError > B3_PI)
+                       m_currentLimitError -= B3_2_PI;
+               else if (m_currentLimitError < -B3_PI)
+                       m_currentLimitError += B3_2_PI;
+               return 1;
+       }
+       else if (test_value > m_hiLimit)
+       {
+               m_currentLimit = 2;  //High limit violation
+               m_currentLimitError = test_value - m_hiLimit;
+               if (m_currentLimitError > B3_PI)
+                       m_currentLimitError -= B3_2_PI;
+               else if (m_currentLimitError < -B3_PI)
+                       m_currentLimitError += B3_2_PI;
+               return 2;
+       };
+
+       m_currentLimit = 0;  //Free from violation
+       return 0;
+}
+
+//////////////////////////// End b3RotationalLimitMotor ////////////////////////////////////
+
+//////////////////////////// b3TranslationalLimitMotor ////////////////////////////////////
+
+int b3TranslationalLimitMotor::testLimitValue(int limitIndex, b3Scalar test_value)
+{
+       b3Scalar loLimit = m_lowerLimit[limitIndex];
+       b3Scalar hiLimit = m_upperLimit[limitIndex];
+       if (loLimit > hiLimit)
+       {
+               m_currentLimit[limitIndex] = 0;  //Free from violation
+               m_currentLimitError[limitIndex] = b3Scalar(0.f);
+               return 0;
+       }
+
+       if (test_value < loLimit)
+       {
+               m_currentLimit[limitIndex] = 2;  //low limit violation
+               m_currentLimitError[limitIndex] = test_value - loLimit;
+               return 2;
+       }
+       else if (test_value > hiLimit)
+       {
+               m_currentLimit[limitIndex] = 1;  //High limit violation
+               m_currentLimitError[limitIndex] = test_value - hiLimit;
+               return 1;
+       };
+
+       m_currentLimit[limitIndex] = 0;  //Free from violation
+       m_currentLimitError[limitIndex] = b3Scalar(0.f);
+       return 0;
+}
+
+//////////////////////////// b3TranslationalLimitMotor ////////////////////////////////////
+
+void b3Generic6DofConstraint::calculateAngleInfo()
+{
+       b3Matrix3x3 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.
+       b3Vector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
+       b3Vector3 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]);
+
+       m_calculatedAxis[0].normalize();
+       m_calculatedAxis[1].normalize();
+       m_calculatedAxis[2].normalize();
+}
+
+static b3Transform getCenterOfMassTransform(const b3RigidBodyData& body)
+{
+       b3Transform tr(body.m_quat, body.m_pos);
+       return tr;
+}
+
+void b3Generic6DofConstraint::calculateTransforms(const b3RigidBodyData* bodies)
+{
+       b3Transform transA;
+       b3Transform transB;
+       transA = getCenterOfMassTransform(bodies[m_rbA]);
+       transB = getCenterOfMassTransform(bodies[m_rbB]);
+       calculateTransforms(transA, transB, bodies);
+}
+
+void b3Generic6DofConstraint::calculateTransforms(const b3Transform& transA, const b3Transform& transB, const b3RigidBodyData* bodies)
+{
+       m_calculatedTransformA = transA * m_frameInA;
+       m_calculatedTransformB = transB * m_frameInB;
+       calculateLinearInfo();
+       calculateAngleInfo();
+       if (m_useOffsetForConstraintFrame)
+       {  //  get weight factors depending on masses
+               b3Scalar miA = bodies[m_rbA].m_invMass;
+               b3Scalar miB = bodies[m_rbB].m_invMass;
+               m_hasStaticBody = (miA < B3_EPSILON) || (miB < B3_EPSILON);
+               b3Scalar miS = miA + miB;
+               if (miS > b3Scalar(0.f))
+               {
+                       m_factA = miB / miS;
+               }
+               else
+               {
+                       m_factA = b3Scalar(0.5f);
+               }
+               m_factB = b3Scalar(1.0f) - m_factA;
+       }
+}
+
+bool b3Generic6DofConstraint::testAngularLimitMotor(int axis_index)
+{
+       b3Scalar angle = m_calculatedAxisAngleDiff[axis_index];
+       angle = b3AdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
+       m_angularLimits[axis_index].m_currentPosition = angle;
+       //test limits
+       m_angularLimits[axis_index].testLimitValue(angle);
+       return m_angularLimits[axis_index].needApplyTorques();
+}
+
+void b3Generic6DofConstraint::getInfo1(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
+{
+       //prepare constraint
+       calculateTransforms(getCenterOfMassTransform(bodies[m_rbA]), getCenterOfMassTransform(bodies[m_rbB]), bodies);
+       info->m_numConstraintRows = 0;
+       info->nub = 6;
+       int i;
+       //test linear limits
+       for (i = 0; i < 3; i++)
+       {
+               if (m_linearLimits.needApplyForce(i))
+               {
+                       info->m_numConstraintRows++;
+                       info->nub--;
+               }
+       }
+       //test angular limits
+       for (i = 0; i < 3; i++)
+       {
+               if (testAngularLimitMotor(i))
+               {
+                       info->m_numConstraintRows++;
+                       info->nub--;
+               }
+       }
+       //      printf("info->m_numConstraintRows=%d\n",info->m_numConstraintRows);
+}
+
+void b3Generic6DofConstraint::getInfo1NonVirtual(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
+{
+       //pre-allocate all 6
+       info->m_numConstraintRows = 6;
+       info->nub = 0;
+}
+
+void b3Generic6DofConstraint::getInfo2(b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
+{
+       b3Transform transA = getCenterOfMassTransform(bodies[m_rbA]);
+       b3Transform transB = getCenterOfMassTransform(bodies[m_rbB]);
+       const b3Vector3& linVelA = bodies[m_rbA].m_linVel;
+       const b3Vector3& linVelB = bodies[m_rbB].m_linVel;
+       const b3Vector3& angVelA = bodies[m_rbA].m_angVel;
+       const b3Vector3& angVelB = bodies[m_rbB].m_angVel;
+
+       if (m_useOffsetForConstraintFrame)
+       {  // for stability better to solve angular limits first
+               int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+               setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
+       }
+       else
+       {  // leave old version for compatibility
+               int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+               setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
+       }
+}
+
+void b3Generic6DofConstraint::getInfo2NonVirtual(b3ConstraintInfo2* info, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB, const b3RigidBodyData* bodies)
+{
+       //prepare constraint
+       calculateTransforms(transA, transB, bodies);
+
+       int i;
+       for (i = 0; i < 3; i++)
+       {
+               testAngularLimitMotor(i);
+       }
+
+       if (m_useOffsetForConstraintFrame)
+       {  // for stability better to solve angular limits first
+               int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+               setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
+       }
+       else
+       {  // leave old version for compatibility
+               int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+               setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
+       }
+}
+
+int b3Generic6DofConstraint::setLinearLimits(b3ConstraintInfo2* info, int row, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB)
+{
+       //      int row = 0;
+       //solve linear limits
+       b3RotationalLimitMotor limot;
+       for (int i = 0; i < 3; i++)
+       {
+               if (m_linearLimits.needApplyForce(i))
+               {  // re-use rotational motor code
+                       limot.m_bounce = b3Scalar(0.f);
+                       limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
+                       limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
+                       limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
+                       limot.m_damping = m_linearLimits.m_damping;
+                       limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
+                       limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
+                       limot.m_limitSoftness = m_linearLimits.m_limitSoftness;
+                       limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
+                       limot.m_maxLimitForce = b3Scalar(0.f);
+                       limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
+                       limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
+                       b3Vector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
+                       int flags = m_flags >> (i * B3_6DOF_FLAGS_AXIS_SHIFT);
+                       limot.m_normalCFM = (flags & B3_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
+                       limot.m_stopCFM = (flags & B3_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
+                       limot.m_stopERP = (flags & B3_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
+                       if (m_useOffsetForConstraintFrame)
+                       {
+                               int indx1 = (i + 1) % 3;
+                               int indx2 = (i + 2) % 3;
+                               int rotAllowed = 1;  // rotations around orthos to current axis
+                               if (m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
+                               {
+                                       rotAllowed = 0;
+                               }
+                               row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed);
+                       }
+                       else
+                       {
+                               row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0);
+                       }
+               }
+       }
+       return row;
+}
+
+int b3Generic6DofConstraint::setAngularLimits(b3ConstraintInfo2* info, int row_offset, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB)
+{
+       b3Generic6DofConstraint* d6constraint = this;
+       int row = row_offset;
+       //solve angular limits
+       for (int i = 0; i < 3; i++)
+       {
+               if (d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
+               {
+                       b3Vector3 axis = d6constraint->getAxis(i);
+                       int flags = m_flags >> ((i + 3) * B3_6DOF_FLAGS_AXIS_SHIFT);
+                       if (!(flags & B3_6DOF_FLAGS_CFM_NORM))
+                       {
+                               m_angularLimits[i].m_normalCFM = info->cfm[0];
+                       }
+                       if (!(flags & B3_6DOF_FLAGS_CFM_STOP))
+                       {
+                               m_angularLimits[i].m_stopCFM = info->cfm[0];
+                       }
+                       if (!(flags & B3_6DOF_FLAGS_ERP_STOP))
+                       {
+                               m_angularLimits[i].m_stopERP = info->erp;
+                       }
+                       row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i),
+                                                                                transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1);
+               }
+       }
+
+       return row;
+}
+
+void b3Generic6DofConstraint::updateRHS(b3Scalar timeStep)
+{
+       (void)timeStep;
+}
+
+void b3Generic6DofConstraint::setFrames(const b3Transform& frameA, const b3Transform& frameB, const b3RigidBodyData* bodies)
+{
+       m_frameInA = frameA;
+       m_frameInB = frameB;
+
+       calculateTransforms(bodies);
+}
+
+b3Vector3 b3Generic6DofConstraint::getAxis(int axis_index) const
+{
+       return m_calculatedAxis[axis_index];
+}
+
+b3Scalar b3Generic6DofConstraint::getRelativePivotPosition(int axisIndex) const
+{
+       return m_calculatedLinearDiff[axisIndex];
+}
+
+b3Scalar b3Generic6DofConstraint::getAngle(int axisIndex) const
+{
+       return m_calculatedAxisAngleDiff[axisIndex];
+}
+
+void b3Generic6DofConstraint::calcAnchorPos(const b3RigidBodyData* bodies)
+{
+       b3Scalar imA = bodies[m_rbA].m_invMass;
+       b3Scalar imB = bodies[m_rbB].m_invMass;
+       b3Scalar weight;
+       if (imB == b3Scalar(0.0))
+       {
+               weight = b3Scalar(1.0);
+       }
+       else
+       {
+               weight = imA / (imA + imB);
+       }
+       const b3Vector3& pA = m_calculatedTransformA.getOrigin();
+       const b3Vector3& pB = m_calculatedTransformB.getOrigin();
+       m_AnchorPos = pA * weight + pB * (b3Scalar(1.0) - weight);
+       return;
+}
+
+void b3Generic6DofConstraint::calculateLinearInfo()
+{
+       m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
+       m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
+       for (int i = 0; i < 3; i++)
+       {
+               m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
+               m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
+       }
+}
+
+int b3Generic6DofConstraint::get_limit_motor_info2(
+       b3RotationalLimitMotor* limot,
+       const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB,
+       b3ConstraintInfo2* info, int row, b3Vector3& ax1, int rotational, int rotAllowed)
+{
+       int srow = row * info->rowskip;
+       bool powered = limot->m_enableMotor;
+       int limit = limot->m_currentLimit;
+       if (powered || limit)
+       {  // if the joint is powered, or has joint limits, add in the extra row
+               b3Scalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
+               b3Scalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
+               if (J1)
+               {
+                       J1[srow + 0] = ax1[0];
+                       J1[srow + 1] = ax1[1];
+                       J1[srow + 2] = ax1[2];
+               }
+               if (J2)
+               {
+                       J2[srow + 0] = -ax1[0];
+                       J2[srow + 1] = -ax1[1];
+                       J2[srow + 2] = -ax1[2];
+               }
+               if ((!rotational))
+               {
+                       if (m_useOffsetForConstraintFrame)
+                       {
+                               b3Vector3 tmpA, tmpB, relA, relB;
+                               // get vector from bodyB to frameB in WCS
+                               relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+                               // get its projection to constraint axis
+                               b3Vector3 projB = ax1 * relB.dot(ax1);
+                               // get vector directed from bodyB to constraint axis (and orthogonal to it)
+                               b3Vector3 orthoB = relB - projB;
+                               // same for bodyA
+                               relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
+                               b3Vector3 projA = ax1 * relA.dot(ax1);
+                               b3Vector3 orthoA = relA - projA;
+                               // get desired offset between frames A and B along constraint axis
+                               b3Scalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError;
+                               // desired vector from projection of center of bodyA to projection of center of bodyB to constraint axis
+                               b3Vector3 totalDist = projA + ax1 * desiredOffs - projB;
+                               // get offset vectors relA and relB
+                               relA = orthoA + totalDist * m_factA;
+                               relB = orthoB - totalDist * m_factB;
+                               tmpA = relA.cross(ax1);
+                               tmpB = relB.cross(ax1);
+                               if (m_hasStaticBody && (!rotAllowed))
+                               {
+                                       tmpA *= m_factA;
+                                       tmpB *= m_factB;
+                               }
+                               int i;
+                               for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i];
+                               for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i];
+                       }
+                       else
+                       {
+                               b3Vector3 ltd;  // Linear Torque Decoupling vector
+                               b3Vector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin();
+                               ltd = c.cross(ax1);
+                               info->m_J1angularAxis[srow + 0] = ltd[0];
+                               info->m_J1angularAxis[srow + 1] = ltd[1];
+                               info->m_J1angularAxis[srow + 2] = ltd[2];
+
+                               c = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+                               ltd = -c.cross(ax1);
+                               info->m_J2angularAxis[srow + 0] = ltd[0];
+                               info->m_J2angularAxis[srow + 1] = ltd[1];
+                               info->m_J2angularAxis[srow + 2] = ltd[2];
+                       }
+               }
+               // if we're limited low and high simultaneously, the joint motor is
+               // ineffective
+               if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
+               info->m_constraintError[srow] = b3Scalar(0.f);
+               if (powered)
+               {
+                       info->cfm[srow] = limot->m_normalCFM;
+                       if (!limit)
+                       {
+                               b3Scalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
+
+                               b3Scalar mot_fact = getMotorFactor(limot->m_currentPosition,
+                                                                                                  limot->m_loLimit,
+                                                                                                  limot->m_hiLimit,
+                                                                                                  tag_vel,
+                                                                                                  info->fps * limot->m_stopERP);
+                               info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
+                               info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
+                               info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
+                       }
+               }
+               if (limit)
+               {
+                       b3Scalar k = info->fps * limot->m_stopERP;
+                       if (!rotational)
+                       {
+                               info->m_constraintError[srow] += k * limot->m_currentLimitError;
+                       }
+                       else
+                       {
+                               info->m_constraintError[srow] += -k * limot->m_currentLimitError;
+                       }
+                       info->cfm[srow] = limot->m_stopCFM;
+                       if (limot->m_loLimit == limot->m_hiLimit)
+                       {  // limited low and high simultaneously
+                               info->m_lowerLimit[srow] = -B3_INFINITY;
+                               info->m_upperLimit[srow] = B3_INFINITY;
+                       }
+                       else
+                       {
+                               if (limit == 1)
+                               {
+                                       info->m_lowerLimit[srow] = 0;
+                                       info->m_upperLimit[srow] = B3_INFINITY;
+                               }
+                               else
+                               {
+                                       info->m_lowerLimit[srow] = -B3_INFINITY;
+                                       info->m_upperLimit[srow] = 0;
+                               }
+                               // deal with bounce
+                               if (limot->m_bounce > 0)
+                               {
+                                       // calculate joint velocity
+                                       b3Scalar vel;
+                                       if (rotational)
+                                       {
+                                               vel = angVelA.dot(ax1);
+                                               //make sure that if no body -> angVelB == zero vec
+                                               //                        if (body1)
+                                               vel -= angVelB.dot(ax1);
+                                       }
+                                       else
+                                       {
+                                               vel = linVelA.dot(ax1);
+                                               //make sure that if no body -> angVelB == zero vec
+                                               //                        if (body1)
+                                               vel -= linVelB.dot(ax1);
+                                       }
+                                       // only apply bounce if the velocity is incoming, and if the
+                                       // resulting c[] exceeds what we already have.
+                                       if (limit == 1)
+                                       {
+                                               if (vel < 0)
+                                               {
+                                                       b3Scalar newc = -limot->m_bounce * vel;
+                                                       if (newc > info->m_constraintError[srow])
+                                                               info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (vel > 0)
+                                               {
+                                                       b3Scalar newc = -limot->m_bounce * vel;
+                                                       if (newc < info->m_constraintError[srow])
+                                                               info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               return 1;
+       }
+       else
+               return 0;
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void b3Generic6DofConstraint::setParam(int num, b3Scalar value, int axis)
+{
+       if ((axis >= 0) && (axis < 3))
+       {
+               switch (num)
+               {
+                       case B3_CONSTRAINT_STOP_ERP:
+                               m_linearLimits.m_stopERP[axis] = value;
+                               m_flags |= B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       case B3_CONSTRAINT_STOP_CFM:
+                               m_linearLimits.m_stopCFM[axis] = value;
+                               m_flags |= B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       case B3_CONSTRAINT_CFM:
+                               m_linearLimits.m_normalCFM[axis] = value;
+                               m_flags |= B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       default:
+                               b3AssertConstrParams(0);
+               }
+       }
+       else if ((axis >= 3) && (axis < 6))
+       {
+               switch (num)
+               {
+                       case B3_CONSTRAINT_STOP_ERP:
+                               m_angularLimits[axis - 3].m_stopERP = value;
+                               m_flags |= B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       case B3_CONSTRAINT_STOP_CFM:
+                               m_angularLimits[axis - 3].m_stopCFM = value;
+                               m_flags |= B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       case B3_CONSTRAINT_CFM:
+                               m_angularLimits[axis - 3].m_normalCFM = value;
+                               m_flags |= B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       default:
+                               b3AssertConstrParams(0);
+               }
+       }
+       else
+       {
+               b3AssertConstrParams(0);
+       }
+}
+
+///return the local value of parameter
+b3Scalar b3Generic6DofConstraint::getParam(int num, int axis) const
+{
+       b3Scalar retVal = 0;
+       if ((axis >= 0) && (axis < 3))
+       {
+               switch (num)
+               {
+                       case B3_CONSTRAINT_STOP_ERP:
+                               b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_linearLimits.m_stopERP[axis];
+                               break;
+                       case B3_CONSTRAINT_STOP_CFM:
+                               b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_linearLimits.m_stopCFM[axis];
+                               break;
+                       case B3_CONSTRAINT_CFM:
+                               b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_linearLimits.m_normalCFM[axis];
+                               break;
+                       default:
+                               b3AssertConstrParams(0);
+               }
+       }
+       else if ((axis >= 3) && (axis < 6))
+       {
+               switch (num)
+               {
+                       case B3_CONSTRAINT_STOP_ERP:
+                               b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_angularLimits[axis - 3].m_stopERP;
+                               break;
+                       case B3_CONSTRAINT_STOP_CFM:
+                               b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_angularLimits[axis - 3].m_stopCFM;
+                               break;
+                       case B3_CONSTRAINT_CFM:
+                               b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_angularLimits[axis - 3].m_normalCFM;
+                               break;
+                       default:
+                               b3AssertConstrParams(0);
+               }
+       }
+       else
+       {
+               b3AssertConstrParams(0);
+       }
+       return retVal;
+}
+
+void b3Generic6DofConstraint::setAxis(const b3Vector3& axis1, const b3Vector3& axis2, const b3RigidBodyData* bodies)
+{
+       b3Vector3 zAxis = axis1.normalized();
+       b3Vector3 yAxis = axis2.normalized();
+       b3Vector3 xAxis = yAxis.cross(zAxis);  // we want right coordinate system
+
+       b3Transform frameInW;
+       frameInW.setIdentity();
+       frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+                                                                xAxis[1], yAxis[1], zAxis[1],
+                                                                xAxis[2], yAxis[2], zAxis[2]);
+
+       // now get constraint frame in local coordinate systems
+       m_frameInA = getCenterOfMassTransform(bodies[m_rbA]).inverse() * frameInW;
+       m_frameInB = getCenterOfMassTransform(bodies[m_rbB]).inverse() * frameInW;
+
+       calculateTransforms(bodies);
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h
new file mode 100644 (file)
index 0000000..d162d58
--- /dev/null
@@ -0,0 +1,517 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// 2009 March: b3Generic6DofConstraint refactored by Roman Ponomarev
+/// Added support for generic constraint solver through getInfo1/getInfo2 methods
+
+/*
+2007-09-09
+b3Generic6DofConstraint Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+#ifndef B3_GENERIC_6DOF_CONSTRAINT_H
+#define B3_GENERIC_6DOF_CONSTRAINT_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "b3JacobianEntry.h"
+#include "b3TypedConstraint.h"
+
+struct b3RigidBodyData;
+
+//! Rotation Limit structure for generic joints
+class b3RotationalLimitMotor
+{
+public:
+       //! limit_parameters
+       //!@{
+       b3Scalar m_loLimit;         //!< joint limit
+       b3Scalar m_hiLimit;         //!< joint limit
+       b3Scalar m_targetVelocity;  //!< target motor velocity
+       b3Scalar m_maxMotorForce;   //!< max force on motor
+       b3Scalar m_maxLimitForce;   //!< max force on limit
+       b3Scalar m_damping;         //!< Damping.
+       b3Scalar m_limitSoftness;   //! Relaxation factor
+       b3Scalar m_normalCFM;       //!< Constraint force mixing factor
+       b3Scalar m_stopERP;         //!< Error tolerance factor when joint is at limit
+       b3Scalar m_stopCFM;         //!< Constraint force mixing factor when joint is at limit
+       b3Scalar m_bounce;          //!< restitution factor
+       bool m_enableMotor;
+
+       //!@}
+
+       //! temp_variables
+       //!@{
+       b3Scalar m_currentLimitError;  //!  How much is violated this limit
+       b3Scalar m_currentPosition;    //!  current value of angle
+       int m_currentLimit;            //!< 0=free, 1=at lo limit, 2=at hi limit
+       b3Scalar m_accumulatedImpulse;
+       //!@}
+
+       b3RotationalLimitMotor()
+       {
+               m_accumulatedImpulse = 0.f;
+               m_targetVelocity = 0;
+               m_maxMotorForce = 6.0f;
+               m_maxLimitForce = 300.0f;
+               m_loLimit = 1.0f;
+               m_hiLimit = -1.0f;
+               m_normalCFM = 0.f;
+               m_stopERP = 0.2f;
+               m_stopCFM = 0.f;
+               m_bounce = 0.0f;
+               m_damping = 1.0f;
+               m_limitSoftness = 0.5f;
+               m_currentLimit = 0;
+               m_currentLimitError = 0;
+               m_enableMotor = false;
+       }
+
+       b3RotationalLimitMotor(const b3RotationalLimitMotor& 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_normalCFM = limot.m_normalCFM;
+               m_stopERP = limot.m_stopERP;
+               m_stopCFM = limot.m_stopCFM;
+               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(b3Scalar test_value);
+
+       //! apply the correction impulses for two bodies
+       b3Scalar solveAngularLimits(b3Scalar timeStep, b3Vector3& axis, b3Scalar jacDiagABInv, b3RigidBodyData* body0, b3RigidBodyData* body1);
+};
+
+class b3TranslationalLimitMotor
+{
+public:
+       b3Vector3 m_lowerLimit;  //!< the constraint lower limits
+       b3Vector3 m_upperLimit;  //!< the constraint upper limits
+       b3Vector3 m_accumulatedImpulse;
+       //! Linear_Limit_parameters
+       //!@{
+       b3Vector3 m_normalCFM;          //!< Constraint force mixing factor
+       b3Vector3 m_stopERP;            //!< Error tolerance factor when joint is at limit
+       b3Vector3 m_stopCFM;            //!< Constraint force mixing factor when joint is at limit
+       b3Vector3 m_targetVelocity;     //!< target motor velocity
+       b3Vector3 m_maxMotorForce;      //!< max force on motor
+       b3Vector3 m_currentLimitError;  //!  How much is violated this limit
+       b3Vector3 m_currentLinearDiff;  //!  Current relative offset of constraint frames
+       b3Scalar m_limitSoftness;       //!< Softness for linear limit
+       b3Scalar m_damping;             //!< Damping for linear limit
+       b3Scalar m_restitution;         //! Bounce parameter for linear limit
+       //!@}
+       bool m_enableMotor[3];
+       int m_currentLimit[3];  //!< 0=free, 1=at lower limit, 2=at upper limit
+
+       b3TranslationalLimitMotor()
+       {
+               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_normalCFM.setValue(0.f, 0.f, 0.f);
+               m_stopERP.setValue(0.2f, 0.2f, 0.2f);
+               m_stopCFM.setValue(0.f, 0.f, 0.f);
+
+               m_limitSoftness = 0.7f;
+               m_damping = b3Scalar(1.0f);
+               m_restitution = b3Scalar(0.5f);
+               for (int i = 0; i < 3; i++)
+               {
+                       m_enableMotor[i] = false;
+                       m_targetVelocity[i] = b3Scalar(0.f);
+                       m_maxMotorForce[i] = b3Scalar(0.f);
+               }
+       }
+
+       b3TranslationalLimitMotor(const b3TranslationalLimitMotor& 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;
+               m_normalCFM = other.m_normalCFM;
+               m_stopERP = other.m_stopERP;
+               m_stopCFM = other.m_stopCFM;
+
+               for (int i = 0; i < 3; i++)
+               {
+                       m_enableMotor[i] = other.m_enableMotor[i];
+                       m_targetVelocity[i] = other.m_targetVelocity[i];
+                       m_maxMotorForce[i] = other.m_maxMotorForce[i];
+               }
+       }
+
+       //! 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]);
+       }
+       inline bool needApplyForce(int limitIndex)
+       {
+               if (m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
+               return true;
+       }
+       int testLimitValue(int limitIndex, b3Scalar test_value);
+
+       b3Scalar solveLinearAxis(
+               b3Scalar timeStep,
+               b3Scalar jacDiagABInv,
+               b3RigidBodyData& body1, const b3Vector3& pointInA,
+               b3RigidBodyData& body2, const b3Vector3& pointInB,
+               int limit_index,
+               const b3Vector3& axis_normal_on_a,
+               const b3Vector3& anchorPos);
+};
+
+enum b36DofFlags
+{
+       B3_6DOF_FLAGS_CFM_NORM = 1,
+       B3_6DOF_FLAGS_CFM_STOP = 2,
+       B3_6DOF_FLAGS_ERP_STOP = 4
+};
+#define B3_6DOF_FLAGS_AXIS_SHIFT 3  // bits per axis
+
+/// b3Generic6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
+/*!
+b3Generic6DofConstraint 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 b3Generic6DofConstraint.setLinearUpperLimit, b3Generic6DofConstraint.setLinearLowerLimit. You can set the parameters with the b3TranslationalLimitMotor structure accsesible through the b3Generic6DofConstraint.getTranslationalLimitMotor method.
+At this moment translational motors are not supported. May be in the future. </li>
+
+<li> For Angular limits, use the b3RotationalLimitMotor structure for configuring the limit.
+This is accessible through b3Generic6DofConstraint.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>
+</tr><tr>
+       <td>X</td>
+       <td>-PI</td>
+       <td>PI</td>
+</tr><tr>
+       <td>Y</td>
+       <td>-PI/2</td>
+       <td>PI/2</td>
+</tr><tr>
+       <td>Z</td>
+       <td>-PI</td>
+       <td>PI</td>
+</tr>
+</table>
+</li>
+</ul>
+
+*/
+B3_ATTRIBUTE_ALIGNED16(class)
+b3Generic6DofConstraint : public b3TypedConstraint
+{
+protected:
+       //! relative_frames
+       //!@{
+       b3Transform m_frameInA;  //!< the constraint space w.r.t body A
+       b3Transform m_frameInB;  //!< the constraint space w.r.t body B
+       //!@}
+
+       //! Jacobians
+       //!@{
+       //    b3JacobianEntry   m_jacLinear[3];//!< 3 orthogonal linear constraints
+       //    b3JacobianEntry   m_jacAng[3];//!< 3 orthogonal angular constraints
+       //!@}
+
+       //! Linear_Limit_parameters
+       //!@{
+       b3TranslationalLimitMotor m_linearLimits;
+       //!@}
+
+       //! hinge_parameters
+       //!@{
+       b3RotationalLimitMotor m_angularLimits[3];
+       //!@}
+
+protected:
+       //! temporal variables
+       //!@{
+       b3Transform m_calculatedTransformA;
+       b3Transform m_calculatedTransformB;
+       b3Vector3 m_calculatedAxisAngleDiff;
+       b3Vector3 m_calculatedAxis[3];
+       b3Vector3 m_calculatedLinearDiff;
+       b3Scalar m_timeStep;
+       b3Scalar m_factA;
+       b3Scalar m_factB;
+       bool m_hasStaticBody;
+
+       b3Vector3 m_AnchorPos;  // point betwen pivots of bodies A and B to solve linear axes
+
+       bool m_useLinearReferenceFrameA;
+       bool m_useOffsetForConstraintFrame;
+
+       int m_flags;
+
+       //!@}
+
+       b3Generic6DofConstraint& operator=(b3Generic6DofConstraint& other)
+       {
+               b3Assert(0);
+               (void)other;
+               return *this;
+       }
+
+       int setAngularLimits(b3ConstraintInfo2 * info, int row_offset, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB);
+
+       int setLinearLimits(b3ConstraintInfo2 * info, int row, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB);
+
+       // tests linear limits
+       void calculateLinearInfo();
+
+       //! calcs the euler angles between the two bodies.
+       void calculateAngleInfo();
+
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       b3Generic6DofConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB, bool useLinearReferenceFrameA, const b3RigidBodyData* bodies);
+
+       //! 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 b3Generic6DofConstraint.getCalculatedTransformA , b3Generic6DofConstraint.getCalculatedTransformB, b3Generic6DofConstraint.calculateAngleInfo
+       */
+       void calculateTransforms(const b3Transform& transA, const b3Transform& transB, const b3RigidBodyData* bodies);
+
+       void calculateTransforms(const b3RigidBodyData* bodies);
+
+       //! Gets the global transform of the offset for body A
+       /*!
+    \sa b3Generic6DofConstraint.getFrameOffsetA, b3Generic6DofConstraint.getFrameOffsetB, b3Generic6DofConstraint.calculateAngleInfo.
+    */
+       const b3Transform& getCalculatedTransformA() const
+       {
+               return m_calculatedTransformA;
+       }
+
+       //! Gets the global transform of the offset for body B
+       /*!
+    \sa b3Generic6DofConstraint.getFrameOffsetA, b3Generic6DofConstraint.getFrameOffsetB, b3Generic6DofConstraint.calculateAngleInfo.
+    */
+       const b3Transform& getCalculatedTransformB() const
+       {
+               return m_calculatedTransformB;
+       }
+
+       const b3Transform& getFrameOffsetA() const
+       {
+               return m_frameInA;
+       }
+
+       const b3Transform& getFrameOffsetB() const
+       {
+               return m_frameInB;
+       }
+
+       b3Transform& getFrameOffsetA()
+       {
+               return m_frameInA;
+       }
+
+       b3Transform& getFrameOffsetB()
+       {
+               return m_frameInB;
+       }
+
+       virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
+
+       void getInfo1NonVirtual(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
+
+       virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies);
+
+       void getInfo2NonVirtual(b3ConstraintInfo2 * info, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB, const b3RigidBodyData* bodies);
+
+       void updateRHS(b3Scalar timeStep);
+
+       //! Get the rotation axis in global coordinates
+       b3Vector3 getAxis(int axis_index) const;
+
+       //! Get the relative Euler angle
+       /*!
+       \pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
+       */
+       b3Scalar getAngle(int axis_index) const;
+
+       //! Get the relative position of the constraint pivot
+       /*!
+       \pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
+       */
+       b3Scalar getRelativePivotPosition(int axis_index) const;
+
+       void setFrames(const b3Transform& frameA, const b3Transform& frameB, const b3RigidBodyData* bodies);
+
+       //! Test angular limit.
+       /*!
+       Calculates angular correction and returns true if limit needs to be corrected.
+       \pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
+       */
+       bool testAngularLimitMotor(int axis_index);
+
+       void setLinearLowerLimit(const b3Vector3& linearLower)
+       {
+               m_linearLimits.m_lowerLimit = linearLower;
+       }
+
+       void getLinearLowerLimit(b3Vector3 & linearLower)
+       {
+               linearLower = m_linearLimits.m_lowerLimit;
+       }
+
+       void setLinearUpperLimit(const b3Vector3& linearUpper)
+       {
+               m_linearLimits.m_upperLimit = linearUpper;
+       }
+
+       void getLinearUpperLimit(b3Vector3 & linearUpper)
+       {
+               linearUpper = m_linearLimits.m_upperLimit;
+       }
+
+       void setAngularLowerLimit(const b3Vector3& angularLower)
+       {
+               for (int i = 0; i < 3; i++)
+                       m_angularLimits[i].m_loLimit = b3NormalizeAngle(angularLower[i]);
+       }
+
+       void getAngularLowerLimit(b3Vector3 & angularLower)
+       {
+               for (int i = 0; i < 3; i++)
+                       angularLower[i] = m_angularLimits[i].m_loLimit;
+       }
+
+       void setAngularUpperLimit(const b3Vector3& angularUpper)
+       {
+               for (int i = 0; i < 3; i++)
+                       m_angularLimits[i].m_hiLimit = b3NormalizeAngle(angularUpper[i]);
+       }
+
+       void getAngularUpperLimit(b3Vector3 & angularUpper)
+       {
+               for (int i = 0; i < 3; i++)
+                       angularUpper[i] = m_angularLimits[i].m_hiLimit;
+       }
+
+       //! Retrieves the angular limit informacion
+       b3RotationalLimitMotor* getRotationalLimitMotor(int index)
+       {
+               return &m_angularLimits[index];
+       }
+
+       //! Retrieves the  limit informacion
+       b3TranslationalLimitMotor* getTranslationalLimitMotor()
+       {
+               return &m_linearLimits;
+       }
+
+       //first 3 are linear, next 3 are angular
+       void setLimit(int axis, b3Scalar lo, b3Scalar hi)
+       {
+               if (axis < 3)
+               {
+                       m_linearLimits.m_lowerLimit[axis] = lo;
+                       m_linearLimits.m_upperLimit[axis] = hi;
+               }
+               else
+               {
+                       lo = b3NormalizeAngle(lo);
+                       hi = b3NormalizeAngle(hi);
+                       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();
+       }
+
+       virtual void calcAnchorPos(const b3RigidBodyData* bodies);  // overridable
+
+       int get_limit_motor_info2(b3RotationalLimitMotor * limot,
+                                                         const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB,
+                                                         b3ConstraintInfo2* info, int row, b3Vector3& ax1, int rotational, int rotAllowed = false);
+
+       // access for UseFrameOffset
+       bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
+       void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+
+       ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+       ///If no axis is provided, it uses the default axis for this constraint.
+       virtual void setParam(int num, b3Scalar value, int axis = -1);
+       ///return the local value of parameter
+       virtual b3Scalar getParam(int num, int axis = -1) const;
+
+       void setAxis(const b3Vector3& axis1, const b3Vector3& axis2, const b3RigidBodyData* bodies);
+};
+
+#endif  //B3_GENERIC_6DOF_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h
new file mode 100644 (file)
index 0000000..3cc4f60
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_JACOBIAN_ENTRY_H
+#define B3_JACOBIAN_ENTRY_H
+
+#include "Bullet3Common/b3Matrix3x3.h"
+
+//notes:
+// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components
+// which makes the b3JacobianEntry memory layout 16 bytes
+// if you only are interested in angular part, just feed massInvA and massInvB zero
+
+/// Jacobian entry is an abstraction that allows to describe constraints
+/// it can be used in combination with a constraint solver
+/// Can be used to relate the effect of an impulse to the constraint error
+B3_ATTRIBUTE_ALIGNED16(class)
+b3JacobianEntry
+{
+public:
+       b3JacobianEntry(){};
+       //constraint between two different rigidbodies
+       b3JacobianEntry(
+               const b3Matrix3x3& world2A,
+               const b3Matrix3x3& world2B,
+               const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
+               const b3Vector3& jointAxis,
+               const b3Vector3& inertiaInvA,
+               const b3Scalar massInvA,
+               const b3Vector3& inertiaInvB,
+               const b3Scalar massInvB)
+               : m_linearJointAxis(jointAxis)
+       {
+               m_aJ = world2A * (rel_pos1.cross(m_linearJointAxis));
+               m_bJ = world2B * (rel_pos2.cross(-m_linearJointAxis));
+               m_0MinvJt = inertiaInvA * m_aJ;
+               m_1MinvJt = inertiaInvB * m_bJ;
+               m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
+
+               b3Assert(m_Adiag > b3Scalar(0.0));
+       }
+
+       //angular constraint between two different rigidbodies
+       b3JacobianEntry(const b3Vector3& jointAxis,
+                                       const b3Matrix3x3& world2A,
+                                       const b3Matrix3x3& world2B,
+                                       const b3Vector3& inertiaInvA,
+                                       const b3Vector3& inertiaInvB)
+               : m_linearJointAxis(b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.)))
+       {
+               m_aJ = world2A * jointAxis;
+               m_bJ = world2B * -jointAxis;
+               m_0MinvJt = inertiaInvA * m_aJ;
+               m_1MinvJt = inertiaInvB * m_bJ;
+               m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+
+               b3Assert(m_Adiag > b3Scalar(0.0));
+       }
+
+       //angular constraint between two different rigidbodies
+       b3JacobianEntry(const b3Vector3& axisInA,
+                                       const b3Vector3& axisInB,
+                                       const b3Vector3& inertiaInvA,
+                                       const b3Vector3& inertiaInvB)
+               : m_linearJointAxis(b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.))), m_aJ(axisInA), m_bJ(-axisInB)
+       {
+               m_0MinvJt = inertiaInvA * m_aJ;
+               m_1MinvJt = inertiaInvB * m_bJ;
+               m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+
+               b3Assert(m_Adiag > b3Scalar(0.0));
+       }
+
+       //constraint on one rigidbody
+       b3JacobianEntry(
+               const b3Matrix3x3& world2A,
+               const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
+               const b3Vector3& jointAxis,
+               const b3Vector3& inertiaInvA,
+               const b3Scalar massInvA)
+               : m_linearJointAxis(jointAxis)
+       {
+               m_aJ = world2A * (rel_pos1.cross(jointAxis));
+               m_bJ = world2A * (rel_pos2.cross(-jointAxis));
+               m_0MinvJt = inertiaInvA * m_aJ;
+               m_1MinvJt = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+               m_Adiag = massInvA + m_0MinvJt.dot(m_aJ);
+
+               b3Assert(m_Adiag > b3Scalar(0.0));
+       }
+
+       b3Scalar getDiagonal() const { return m_Adiag; }
+
+       // for two constraints on the same rigidbody (for example vehicle friction)
+       b3Scalar getNonDiagonal(const b3JacobianEntry& jacB, const b3Scalar massInvA) const
+       {
+               const b3JacobianEntry& jacA = *this;
+               b3Scalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis);
+               b3Scalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ);
+               return lin + ang;
+       }
+
+       // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
+       b3Scalar getNonDiagonal(const b3JacobianEntry& jacB, const b3Scalar massInvA, const b3Scalar massInvB) const
+       {
+               const b3JacobianEntry& jacA = *this;
+               b3Vector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
+               b3Vector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
+               b3Vector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
+               b3Vector3 lin0 = massInvA * lin;
+               b3Vector3 lin1 = massInvB * lin;
+               b3Vector3 sum = ang0 + ang1 + lin0 + lin1;
+               return sum[0] + sum[1] + sum[2];
+       }
+
+       b3Scalar getRelativeVelocity(const b3Vector3& linvelA, const b3Vector3& angvelA, const b3Vector3& linvelB, const b3Vector3& angvelB)
+       {
+               b3Vector3 linrel = linvelA - linvelB;
+               b3Vector3 angvela = angvelA * m_aJ;
+               b3Vector3 angvelb = angvelB * m_bJ;
+               linrel *= m_linearJointAxis;
+               angvela += angvelb;
+               angvela += linrel;
+               b3Scalar rel_vel2 = angvela[0] + angvela[1] + angvela[2];
+               return rel_vel2 + B3_EPSILON;
+       }
+       //private:
+
+       b3Vector3 m_linearJointAxis;
+       b3Vector3 m_aJ;
+       b3Vector3 m_bJ;
+       b3Vector3 m_0MinvJt;
+       b3Vector3 m_1MinvJt;
+       //Optimization: can be stored in the w/last component of one of the vectors
+       b3Scalar m_Adiag;
+};
+
+#endif  //B3_JACOBIAN_ENTRY_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp
new file mode 100644 (file)
index 0000000..b7050b1
--- /dev/null
@@ -0,0 +1,1696 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2012 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//enable B3_SOLVER_DEBUG if you experience solver crashes
+//#define B3_SOLVER_DEBUG
+//#define COMPUTE_IMPULSE_DENOM 1
+//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
+
+//#define DISABLE_JOINTS
+
+#include "b3PgsJacobiSolver.h"
+#include "Bullet3Common/b3MinMax.h"
+#include "b3TypedConstraint.h"
+#include <new>
+#include "Bullet3Common/b3StackAlloc.h"
+
+//#include "b3SolverBody.h"
+//#include "b3SolverConstraint.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include <string.h>  //for memset
+//#include "../../dynamics/basic_demo/Stubs/AdlContact4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+static b3Transform getWorldTransform(b3RigidBodyData* rb)
+{
+       b3Transform newTrans;
+       newTrans.setOrigin(rb->m_pos);
+       newTrans.setRotation(rb->m_quat);
+       return newTrans;
+}
+
+static const b3Matrix3x3& getInvInertiaTensorWorld(b3InertiaData* inertia)
+{
+       return inertia->m_invInertiaWorld;
+}
+
+static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
+{
+       return rb->m_linVel;
+}
+
+static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
+{
+       return rb->m_angVel;
+}
+
+static b3Vector3 getVelocityInLocalPoint(b3RigidBodyData* rb, const b3Vector3& rel_pos)
+{
+       //we also calculate lin/ang velocity for kinematic objects
+       return getLinearVelocity(rb) + getAngularVelocity(rb).cross(rel_pos);
+}
+
+struct b3ContactPoint
+{
+       b3Vector3 m_positionWorldOnA;
+       b3Vector3 m_positionWorldOnB;
+       b3Vector3 m_normalWorldOnB;
+       b3Scalar m_appliedImpulse;
+       b3Scalar m_distance;
+       b3Scalar m_combinedRestitution;
+
+       ///information related to friction
+       b3Scalar m_combinedFriction;
+       b3Vector3 m_lateralFrictionDir1;
+       b3Vector3 m_lateralFrictionDir2;
+       b3Scalar m_appliedImpulseLateral1;
+       b3Scalar m_appliedImpulseLateral2;
+       b3Scalar m_combinedRollingFriction;
+       b3Scalar m_contactMotion1;
+       b3Scalar m_contactMotion2;
+       b3Scalar m_contactCFM1;
+       b3Scalar m_contactCFM2;
+
+       bool m_lateralFrictionInitialized;
+
+       b3Vector3 getPositionWorldOnA()
+       {
+               return m_positionWorldOnA;
+       }
+       b3Vector3 getPositionWorldOnB()
+       {
+               return m_positionWorldOnB;
+       }
+       b3Scalar getDistance()
+       {
+               return m_distance;
+       }
+};
+
+void getContactPoint(b3Contact4* contact, int contactIndex, b3ContactPoint& pointOut)
+{
+       pointOut.m_appliedImpulse = 0.f;
+       pointOut.m_appliedImpulseLateral1 = 0.f;
+       pointOut.m_appliedImpulseLateral2 = 0.f;
+       pointOut.m_combinedFriction = contact->getFrictionCoeff();
+       pointOut.m_combinedRestitution = contact->getRestituitionCoeff();
+       pointOut.m_combinedRollingFriction = 0.f;
+       pointOut.m_contactCFM1 = 0.f;
+       pointOut.m_contactCFM2 = 0.f;
+       pointOut.m_contactMotion1 = 0.f;
+       pointOut.m_contactMotion2 = 0.f;
+       pointOut.m_distance = contact->getPenetration(contactIndex);  //??0.01f
+       b3Vector3 normalOnB = contact->m_worldNormalOnB;
+       normalOnB.normalize();  //is this needed?
+
+       b3Vector3 l1, l2;
+       b3PlaneSpace1(normalOnB, l1, l2);
+
+       pointOut.m_normalWorldOnB = normalOnB;
+       //printf("normalOnB = %f,%f,%f\n",normalOnB.getX(),normalOnB.getY(),normalOnB.getZ());
+       pointOut.m_lateralFrictionDir1 = l1;
+       pointOut.m_lateralFrictionDir2 = l2;
+       pointOut.m_lateralFrictionInitialized = true;
+
+       b3Vector3 worldPosB = contact->m_worldPosB[contactIndex];
+       pointOut.m_positionWorldOnB = worldPosB;
+       pointOut.m_positionWorldOnA = worldPosB + normalOnB * pointOut.m_distance;
+}
+
+int getNumContacts(b3Contact4* contact)
+{
+       return contact->getNPoints();
+}
+
+b3PgsJacobiSolver::b3PgsJacobiSolver(bool usePgs)
+       : m_usePgs(usePgs),
+         m_numSplitImpulseRecoveries(0),
+         m_btSeed2(0)
+{
+}
+
+b3PgsJacobiSolver::~b3PgsJacobiSolver()
+{
+}
+
+void b3PgsJacobiSolver::solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints)
+{
+       b3ContactSolverInfo infoGlobal;
+       infoGlobal.m_splitImpulse = false;
+       infoGlobal.m_timeStep = 1.f / 60.f;
+       infoGlobal.m_numIterations = 4;  //4;
+                                                                        //     infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
+       //infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS;
+       infoGlobal.m_solverMode |= B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
+
+       //if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+       //if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+
+       solveGroup(bodies, inertias, numBodies, contacts, numContacts, constraints, numConstraints, infoGlobal);
+
+       if (!numContacts)
+               return;
+}
+
+/// b3PgsJacobiSolver Sequentially applies impulses
+b3Scalar b3PgsJacobiSolver::solveGroup(b3RigidBodyData* bodies,
+                                                                          b3InertiaData* inertias,
+                                                                          int numBodies,
+                                                                          b3Contact4* manifoldPtr,
+                                                                          int numManifolds,
+                                                                          b3TypedConstraint** constraints,
+                                                                          int numConstraints,
+                                                                          const b3ContactSolverInfo& infoGlobal)
+{
+       B3_PROFILE("solveGroup");
+       //you need to provide at least some bodies
+
+       solveGroupCacheFriendlySetup(bodies, inertias, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal);
+
+       solveGroupCacheFriendlyIterations(constraints, numConstraints, infoGlobal);
+
+       solveGroupCacheFriendlyFinish(bodies, inertias, numBodies, infoGlobal);
+
+       return 0.f;
+}
+
+#ifdef USE_SIMD
+#include <emmintrin.h>
+#define b3VecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e, e, e, e))
+static inline __m128 b3SimdDot3(__m128 vec0, __m128 vec1)
+{
+       __m128 result = _mm_mul_ps(vec0, vec1);
+       return _mm_add_ps(b3VecSplat(result, 0), _mm_add_ps(b3VecSplat(result, 1), b3VecSplat(result, 2)));
+}
+#endif  //USE_SIMD
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+void b3PgsJacobiSolver::resolveSingleConstraintRowGenericSIMD(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
+{
+#ifdef USE_SIMD
+       __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
+       __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+       __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+       __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
+       __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
+       __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128), b3SimdDot3((c.m_contactNormal).mVec128, body2.internalGetDeltaLinearVelocity().mVec128));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       b3SimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+       b3SimdScalar resultLowerLess, resultUpperLess;
+       resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+       resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+       __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+       deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+       c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+       __m128 upperMinApplied = _mm_sub_ps(upperLimit1, cpAppliedImp);
+       deltaImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied));
+       c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1));
+       __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128, body1.internalGetInvMass().mVec128);
+       __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128, body2.internalGetInvMass().mVec128);
+       __m128 impulseMagnitude = deltaImpulse;
+       body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+       body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+       body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+       body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
+#else
+       resolveSingleConstraintRowGeneric(body1, body2, c);
+#endif
+}
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+void b3PgsJacobiSolver::resolveSingleConstraintRowGeneric(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
+{
+       b3Scalar deltaImpulse = c.m_rhs - b3Scalar(c.m_appliedImpulse) * c.m_cfm;
+       const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+       const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+
+       //      const b3Scalar delta_rel_vel    =       deltaVel1Dotn-deltaVel2Dotn;
+       deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+       deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
+
+       const b3Scalar sum = b3Scalar(c.m_appliedImpulse) + deltaImpulse;
+       if (sum < c.m_lowerLimit)
+       {
+               deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
+               c.m_appliedImpulse = c.m_lowerLimit;
+       }
+       else if (sum > c.m_upperLimit)
+       {
+               deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
+               c.m_appliedImpulse = c.m_upperLimit;
+       }
+       else
+       {
+               c.m_appliedImpulse = sum;
+       }
+
+       body1.internalApplyImpulse(c.m_contactNormal * body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+       body2.internalApplyImpulse(-c.m_contactNormal * body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+}
+
+void b3PgsJacobiSolver::resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
+{
+#ifdef USE_SIMD
+       __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
+       __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+       __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+       __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
+       __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
+       __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128), b3SimdDot3((c.m_contactNormal).mVec128, body2.internalGetDeltaLinearVelocity().mVec128));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       b3SimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+       b3SimdScalar resultLowerLess, resultUpperLess;
+       resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+       resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+       __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+       deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+       c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+       __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128, body1.internalGetInvMass().mVec128);
+       __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128, body2.internalGetInvMass().mVec128);
+       __m128 impulseMagnitude = deltaImpulse;
+       body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+       body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+       body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+       body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
+#else
+       resolveSingleConstraintRowLowerLimit(body1, body2, c);
+#endif
+}
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+void b3PgsJacobiSolver::resolveSingleConstraintRowLowerLimit(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
+{
+       b3Scalar deltaImpulse = c.m_rhs - b3Scalar(c.m_appliedImpulse) * c.m_cfm;
+       const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+       const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+
+       deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+       deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
+       const b3Scalar sum = b3Scalar(c.m_appliedImpulse) + deltaImpulse;
+       if (sum < c.m_lowerLimit)
+       {
+               deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
+               c.m_appliedImpulse = c.m_lowerLimit;
+       }
+       else
+       {
+               c.m_appliedImpulse = sum;
+       }
+       body1.internalApplyImpulse(c.m_contactNormal * body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+       body2.internalApplyImpulse(-c.m_contactNormal * body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+}
+
+void b3PgsJacobiSolver::resolveSplitPenetrationImpulseCacheFriendly(
+       b3SolverBody& body1,
+       b3SolverBody& body2,
+       const b3SolverConstraint& c)
+{
+       if (c.m_rhsPenetration)
+       {
+               m_numSplitImpulseRecoveries++;
+               b3Scalar deltaImpulse = c.m_rhsPenetration - b3Scalar(c.m_appliedPushImpulse) * c.m_cfm;
+               const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
+               const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
+
+               deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+               deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
+               const b3Scalar sum = b3Scalar(c.m_appliedPushImpulse) + deltaImpulse;
+               if (sum < c.m_lowerLimit)
+               {
+                       deltaImpulse = c.m_lowerLimit - c.m_appliedPushImpulse;
+                       c.m_appliedPushImpulse = c.m_lowerLimit;
+               }
+               else
+               {
+                       c.m_appliedPushImpulse = sum;
+               }
+               body1.internalApplyPushImpulse(c.m_contactNormal * body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+               body2.internalApplyPushImpulse(-c.m_contactNormal * body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+       }
+}
+
+void b3PgsJacobiSolver::resolveSplitPenetrationSIMD(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
+{
+#ifdef USE_SIMD
+       if (!c.m_rhsPenetration)
+               return;
+
+       m_numSplitImpulseRecoveries++;
+
+       __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
+       __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+       __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+       __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse), _mm_set1_ps(c.m_cfm)));
+       __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128, body1.internalGetPushVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetTurnVelocity().mVec128));
+       __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetTurnVelocity().mVec128), b3SimdDot3((c.m_contactNormal).mVec128, body2.internalGetPushVelocity().mVec128));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       b3SimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+       b3SimdScalar resultLowerLess, resultUpperLess;
+       resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+       resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+       __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+       deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+       c.m_appliedPushImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+       __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128, body1.internalGetInvMass().mVec128);
+       __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128, body2.internalGetInvMass().mVec128);
+       __m128 impulseMagnitude = deltaImpulse;
+       body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+       body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+       body2.internalGetPushVelocity().mVec128 = _mm_sub_ps(body2.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+       body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
+#else
+       resolveSplitPenetrationImpulseCacheFriendly(body1, body2, c);
+#endif
+}
+
+unsigned long b3PgsJacobiSolver::b3Rand2()
+{
+       m_btSeed2 = (1664525L * m_btSeed2 + 1013904223L) & 0xffffffff;
+       return m_btSeed2;
+}
+
+//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
+int b3PgsJacobiSolver::b3RandInt2(int n)
+{
+       // seems good; xor-fold and modulus
+       const unsigned long un = static_cast<unsigned long>(n);
+       unsigned long r = b3Rand2();
+
+       // note: probably more aggressive than it needs to be -- might be
+       //       able to get away without one or two of the innermost branches.
+       if (un <= 0x00010000UL)
+       {
+               r ^= (r >> 16);
+               if (un <= 0x00000100UL)
+               {
+                       r ^= (r >> 8);
+                       if (un <= 0x00000010UL)
+                       {
+                               r ^= (r >> 4);
+                               if (un <= 0x00000004UL)
+                               {
+                                       r ^= (r >> 2);
+                                       if (un <= 0x00000002UL)
+                                       {
+                                               r ^= (r >> 1);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return (int)(r % un);
+}
+
+void b3PgsJacobiSolver::initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* rb)
+{
+       solverBody->m_deltaLinearVelocity.setValue(0.f, 0.f, 0.f);
+       solverBody->m_deltaAngularVelocity.setValue(0.f, 0.f, 0.f);
+       solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+       solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+
+       if (rb)
+       {
+               solverBody->m_worldTransform = getWorldTransform(rb);
+               solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass, rb->m_invMass, rb->m_invMass));
+               solverBody->m_originalBodyIndex = bodyIndex;
+               solverBody->m_angularFactor = b3MakeVector3(1, 1, 1);
+               solverBody->m_linearFactor = b3MakeVector3(1, 1, 1);
+               solverBody->m_linearVelocity = getLinearVelocity(rb);
+               solverBody->m_angularVelocity = getAngularVelocity(rb);
+       }
+       else
+       {
+               solverBody->m_worldTransform.setIdentity();
+               solverBody->internalSetInvMass(b3MakeVector3(0, 0, 0));
+               solverBody->m_originalBodyIndex = bodyIndex;
+               solverBody->m_angularFactor.setValue(1, 1, 1);
+               solverBody->m_linearFactor.setValue(1, 1, 1);
+               solverBody->m_linearVelocity.setValue(0, 0, 0);
+               solverBody->m_angularVelocity.setValue(0, 0, 0);
+       }
+}
+
+b3Scalar b3PgsJacobiSolver::restitutionCurve(b3Scalar rel_vel, b3Scalar restitution)
+{
+       b3Scalar rest = restitution * -rel_vel;
+       return rest;
+}
+
+void b3PgsJacobiSolver::setupFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
+{
+       solverConstraint.m_contactNormal = normalAxis;
+       b3SolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+       b3SolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+
+       b3RigidBodyData* body0 = &bodies[solverBodyA.m_originalBodyIndex];
+       b3RigidBodyData* body1 = &bodies[solverBodyB.m_originalBodyIndex];
+
+       solverConstraint.m_solverBodyIdA = solverBodyIdA;
+       solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+       solverConstraint.m_friction = cp.m_combinedFriction;
+       solverConstraint.m_originalContactPoint = 0;
+
+       solverConstraint.m_appliedImpulse = 0.f;
+       solverConstraint.m_appliedPushImpulse = 0.f;
+
+       {
+               b3Vector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal);
+               solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+               solverConstraint.m_angularComponentA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
+       }
+       {
+               b3Vector3 ftorqueAxis1 = rel_pos2.cross(-solverConstraint.m_contactNormal);
+               solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+               solverConstraint.m_angularComponentB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
+       }
+
+       b3Scalar scaledDenom;
+
+       {
+               b3Vector3 vec;
+               b3Scalar denom0 = 0.f;
+               b3Scalar denom1 = 0.f;
+               if (body0)
+               {
+                       vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
+                       denom0 = body0->m_invMass + normalAxis.dot(vec);
+               }
+               if (body1)
+               {
+                       vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
+                       denom1 = body1->m_invMass + normalAxis.dot(vec);
+               }
+
+               b3Scalar denom;
+               if (m_usePgs)
+               {
+                       scaledDenom = denom = relaxation / (denom0 + denom1);
+               }
+               else
+               {
+                       denom = relaxation / (denom0 + denom1);
+                       b3Scalar countA = body0->m_invMass ? b3Scalar(m_bodyCount[solverBodyA.m_originalBodyIndex]) : 1.f;
+                       b3Scalar countB = body1->m_invMass ? b3Scalar(m_bodyCount[solverBodyB.m_originalBodyIndex]) : 1.f;
+
+                       scaledDenom = relaxation / (denom0 * countA + denom1 * countB);
+               }
+
+               solverConstraint.m_jacDiagABInv = denom;
+       }
+
+       {
+               b3Scalar rel_vel;
+               b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0 ? solverBodyA.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : b3MakeVector3(0, 0, 0));
+               b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1 ? solverBodyB.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(body1 ? solverBodyB.m_angularVelocity : b3MakeVector3(0, 0, 0));
+
+               rel_vel = vel1Dotn + vel2Dotn;
+
+               //              b3Scalar positionalError = 0.f;
+
+               b3SimdScalar velocityError = desiredVelocity - rel_vel;
+               b3SimdScalar velocityImpulse = velocityError * b3SimdScalar(scaledDenom);  //solverConstraint.m_jacDiagABInv);
+               solverConstraint.m_rhs = velocityImpulse;
+               solverConstraint.m_cfm = cfmSlip;
+               solverConstraint.m_lowerLimit = 0;
+               solverConstraint.m_upperLimit = 1e10f;
+       }
+}
+
+b3SolverConstraint& b3PgsJacobiSolver::addFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
+{
+       b3SolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
+       solverConstraint.m_frictionIndex = frictionIndex;
+       setupFrictionConstraint(bodies, inertias, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
+                                                       colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+       return solverConstraint;
+}
+
+void b3PgsJacobiSolver::setupRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
+                                                                                                          b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
+                                                                                                          b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation,
+                                                                                                          b3Scalar desiredVelocity, b3Scalar cfmSlip)
+
+{
+       b3Vector3 normalAxis = b3MakeVector3(0, 0, 0);
+
+       solverConstraint.m_contactNormal = normalAxis;
+       b3SolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+       b3SolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+
+       b3RigidBodyData* body0 = &bodies[m_tmpSolverBodyPool[solverBodyIdA].m_originalBodyIndex];
+       b3RigidBodyData* body1 = &bodies[m_tmpSolverBodyPool[solverBodyIdB].m_originalBodyIndex];
+
+       solverConstraint.m_solverBodyIdA = solverBodyIdA;
+       solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+       solverConstraint.m_friction = cp.m_combinedRollingFriction;
+       solverConstraint.m_originalContactPoint = 0;
+
+       solverConstraint.m_appliedImpulse = 0.f;
+       solverConstraint.m_appliedPushImpulse = 0.f;
+
+       {
+               b3Vector3 ftorqueAxis1 = -normalAxis1;
+               solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+               solverConstraint.m_angularComponentA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
+       }
+       {
+               b3Vector3 ftorqueAxis1 = normalAxis1;
+               solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+               solverConstraint.m_angularComponentB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
+       }
+
+       {
+               b3Vector3 iMJaA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex]) * solverConstraint.m_relpos1CrossNormal : b3MakeVector3(0, 0, 0);
+               b3Vector3 iMJaB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex]) * solverConstraint.m_relpos2CrossNormal : b3MakeVector3(0, 0, 0);
+               b3Scalar sum = 0;
+               sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+               sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+               solverConstraint.m_jacDiagABInv = b3Scalar(1.) / sum;
+       }
+
+       {
+               b3Scalar rel_vel;
+               b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0 ? solverBodyA.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : b3MakeVector3(0, 0, 0));
+               b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1 ? solverBodyB.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(body1 ? solverBodyB.m_angularVelocity : b3MakeVector3(0, 0, 0));
+
+               rel_vel = vel1Dotn + vel2Dotn;
+
+               //              b3Scalar positionalError = 0.f;
+
+               b3SimdScalar velocityError = desiredVelocity - rel_vel;
+               b3SimdScalar velocityImpulse = velocityError * b3SimdScalar(solverConstraint.m_jacDiagABInv);
+               solverConstraint.m_rhs = velocityImpulse;
+               solverConstraint.m_cfm = cfmSlip;
+               solverConstraint.m_lowerLimit = 0;
+               solverConstraint.m_upperLimit = 1e10f;
+       }
+}
+
+b3SolverConstraint& b3PgsJacobiSolver::addRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
+{
+       b3SolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
+       solverConstraint.m_frictionIndex = frictionIndex;
+       setupRollingFrictionConstraint(bodies, inertias, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
+                                                                  colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+       return solverConstraint;
+}
+
+int b3PgsJacobiSolver::getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies, b3InertiaData* inertias)
+{
+       //b3Assert(bodyIndex< m_tmpSolverBodyPool.size());
+
+       b3RigidBodyData& body = bodies[bodyIndex];
+       int curIndex = -1;
+       if (m_usePgs || body.m_invMass == 0.f)
+       {
+               if (m_bodyCount[bodyIndex] < 0)
+               {
+                       curIndex = m_tmpSolverBodyPool.size();
+                       b3SolverBody& solverBody = m_tmpSolverBodyPool.expand();
+                       initSolverBody(bodyIndex, &solverBody, &body);
+                       solverBody.m_originalBodyIndex = bodyIndex;
+                       m_bodyCount[bodyIndex] = curIndex;
+               }
+               else
+               {
+                       curIndex = m_bodyCount[bodyIndex];
+               }
+       }
+       else
+       {
+               b3Assert(m_bodyCount[bodyIndex] > 0);
+               m_bodyCountCheck[bodyIndex]++;
+               curIndex = m_tmpSolverBodyPool.size();
+               b3SolverBody& solverBody = m_tmpSolverBodyPool.expand();
+               initSolverBody(bodyIndex, &solverBody, &body);
+               solverBody.m_originalBodyIndex = bodyIndex;
+       }
+
+       b3Assert(curIndex >= 0);
+       return curIndex;
+}
+#include <stdio.h>
+
+void b3PgsJacobiSolver::setupContactConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint,
+                                                                                          int solverBodyIdA, int solverBodyIdB,
+                                                                                          b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal,
+                                                                                          b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation,
+                                                                                          b3Vector3& rel_pos1, b3Vector3& rel_pos2)
+{
+       const b3Vector3& pos1 = cp.getPositionWorldOnA();
+       const b3Vector3& pos2 = cp.getPositionWorldOnB();
+
+       b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+       b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+       b3RigidBodyData* rb0 = &bodies[bodyA->m_originalBodyIndex];
+       b3RigidBodyData* rb1 = &bodies[bodyB->m_originalBodyIndex];
+
+       //                      b3Vector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
+       //                      b3Vector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+       rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+       rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+
+       relaxation = 1.f;
+
+       b3Vector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
+       solverConstraint.m_angularComponentA = rb0 ? getInvInertiaTensorWorld(&inertias[bodyA->m_originalBodyIndex]) * torqueAxis0 : b3MakeVector3(0, 0, 0);
+       b3Vector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
+       solverConstraint.m_angularComponentB = rb1 ? getInvInertiaTensorWorld(&inertias[bodyB->m_originalBodyIndex]) * -torqueAxis1 : b3MakeVector3(0, 0, 0);
+
+       b3Scalar scaledDenom;
+       {
+#ifdef COMPUTE_IMPULSE_DENOM
+               b3Scalar denom0 = rb0->computeImpulseDenominator(pos1, cp.m_normalWorldOnB);
+               b3Scalar denom1 = rb1->computeImpulseDenominator(pos2, cp.m_normalWorldOnB);
+#else
+               b3Vector3 vec;
+               b3Scalar denom0 = 0.f;
+               b3Scalar denom1 = 0.f;
+               if (rb0)
+               {
+                       vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
+                       denom0 = rb0->m_invMass + cp.m_normalWorldOnB.dot(vec);
+               }
+               if (rb1)
+               {
+                       vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
+                       denom1 = rb1->m_invMass + cp.m_normalWorldOnB.dot(vec);
+               }
+#endif  //COMPUTE_IMPULSE_DENOM
+
+               b3Scalar denom;
+               if (m_usePgs)
+               {
+                       scaledDenom = denom = relaxation / (denom0 + denom1);
+               }
+               else
+               {
+                       denom = relaxation / (denom0 + denom1);
+
+                       b3Scalar countA = rb0->m_invMass ? b3Scalar(m_bodyCount[bodyA->m_originalBodyIndex]) : 1.f;
+                       b3Scalar countB = rb1->m_invMass ? b3Scalar(m_bodyCount[bodyB->m_originalBodyIndex]) : 1.f;
+                       scaledDenom = relaxation / (denom0 * countA + denom1 * countB);
+               }
+               solverConstraint.m_jacDiagABInv = denom;
+       }
+
+       solverConstraint.m_contactNormal = cp.m_normalWorldOnB;
+       solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+       solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+
+       b3Scalar restitution = 0.f;
+       b3Scalar penetration = cp.getDistance() + infoGlobal.m_linearSlop;
+
+       {
+               b3Vector3 vel1, vel2;
+
+               vel1 = rb0 ? getVelocityInLocalPoint(rb0, rel_pos1) : b3MakeVector3(0, 0, 0);
+               vel2 = rb1 ? getVelocityInLocalPoint(rb1, rel_pos2) : b3MakeVector3(0, 0, 0);
+
+               //                      b3Vector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : b3Vector3(0,0,0);
+               vel = vel1 - vel2;
+               rel_vel = cp.m_normalWorldOnB.dot(vel);
+
+               solverConstraint.m_friction = cp.m_combinedFriction;
+
+               restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution);
+               if (restitution <= b3Scalar(0.))
+               {
+                       restitution = 0.f;
+               };
+       }
+
+       ///warm starting (or zero if disabled)
+       if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
+       {
+               solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
+               if (rb0)
+                       bodyA->internalApplyImpulse(solverConstraint.m_contactNormal * bodyA->internalGetInvMass(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
+               if (rb1)
+                       bodyB->internalApplyImpulse(solverConstraint.m_contactNormal * bodyB->internalGetInvMass(), -solverConstraint.m_angularComponentB, -(b3Scalar)solverConstraint.m_appliedImpulse);
+       }
+       else
+       {
+               solverConstraint.m_appliedImpulse = 0.f;
+       }
+
+       solverConstraint.m_appliedPushImpulse = 0.f;
+
+       {
+               b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0 ? bodyA->m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(rb0 ? bodyA->m_angularVelocity : b3MakeVector3(0, 0, 0));
+               b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1 ? bodyB->m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(rb1 ? bodyB->m_angularVelocity : b3MakeVector3(0, 0, 0));
+               b3Scalar rel_vel = vel1Dotn + vel2Dotn;
+
+               b3Scalar positionalError = 0.f;
+               b3Scalar velocityError = restitution - rel_vel;  // * damping;
+
+               b3Scalar erp = infoGlobal.m_erp2;
+               if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+               {
+                       erp = infoGlobal.m_erp;
+               }
+
+               if (penetration > 0)
+               {
+                       positionalError = 0;
+
+                       velocityError -= penetration / infoGlobal.m_timeStep;
+               }
+               else
+               {
+                       positionalError = -penetration * erp / infoGlobal.m_timeStep;
+               }
+
+               b3Scalar penetrationImpulse = positionalError * scaledDenom;  //solverConstraint.m_jacDiagABInv;
+               b3Scalar velocityImpulse = velocityError * scaledDenom;       //solverConstraint.m_jacDiagABInv;
+
+               if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+               {
+                       //combine position and velocity into rhs
+                       solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+                       solverConstraint.m_rhsPenetration = 0.f;
+               }
+               else
+               {
+                       //split position and velocity into rhs and m_rhsPenetration
+                       solverConstraint.m_rhs = velocityImpulse;
+                       solverConstraint.m_rhsPenetration = penetrationImpulse;
+               }
+               solverConstraint.m_cfm = 0.f;
+               solverConstraint.m_lowerLimit = 0;
+               solverConstraint.m_upperLimit = 1e10f;
+       }
+}
+
+void b3PgsJacobiSolver::setFrictionConstraintImpulse(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint,
+                                                                                                        int solverBodyIdA, int solverBodyIdB,
+                                                                                                        b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal)
+{
+       b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+       b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+       {
+               b3SolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
+               if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
+               {
+                       frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
+                       if (bodies[bodyA->m_originalBodyIndex].m_invMass)
+                               bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal * bodies[bodyA->m_originalBodyIndex].m_invMass, frictionConstraint1.m_angularComponentA, frictionConstraint1.m_appliedImpulse);
+                       if (bodies[bodyB->m_originalBodyIndex].m_invMass)
+                               bodyB->internalApplyImpulse(frictionConstraint1.m_contactNormal * bodies[bodyB->m_originalBodyIndex].m_invMass, -frictionConstraint1.m_angularComponentB, -(b3Scalar)frictionConstraint1.m_appliedImpulse);
+               }
+               else
+               {
+                       frictionConstraint1.m_appliedImpulse = 0.f;
+               }
+       }
+
+       if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+       {
+               b3SolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
+               if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
+               {
+                       frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
+                       if (bodies[bodyA->m_originalBodyIndex].m_invMass)
+                               bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal * bodies[bodyA->m_originalBodyIndex].m_invMass, frictionConstraint2.m_angularComponentA, frictionConstraint2.m_appliedImpulse);
+                       if (bodies[bodyB->m_originalBodyIndex].m_invMass)
+                               bodyB->internalApplyImpulse(frictionConstraint2.m_contactNormal * bodies[bodyB->m_originalBodyIndex].m_invMass, -frictionConstraint2.m_angularComponentB, -(b3Scalar)frictionConstraint2.m_appliedImpulse);
+               }
+               else
+               {
+                       frictionConstraint2.m_appliedImpulse = 0.f;
+               }
+       }
+}
+
+void b3PgsJacobiSolver::convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias, b3Contact4* manifold, const b3ContactSolverInfo& infoGlobal)
+{
+       b3RigidBodyData *colObj0 = 0, *colObj1 = 0;
+
+       int solverBodyIdA = getOrInitSolverBody(manifold->getBodyA(), bodies, inertias);
+       int solverBodyIdB = getOrInitSolverBody(manifold->getBodyB(), bodies, inertias);
+
+       //      b3RigidBody* bodyA = b3RigidBody::upcast(colObj0);
+       //      b3RigidBody* bodyB = b3RigidBody::upcast(colObj1);
+
+       b3SolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+       b3SolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+       ///avoid collision response between two static objects
+       if (solverBodyA->m_invMass.isZero() && solverBodyB->m_invMass.isZero())
+               return;
+
+       int rollingFriction = 1;
+       int numContacts = getNumContacts(manifold);
+       for (int j = 0; j < numContacts; j++)
+       {
+               b3ContactPoint cp;
+               getContactPoint(manifold, j, cp);
+
+               if (cp.getDistance() <= getContactProcessingThreshold(manifold))
+               {
+                       b3Vector3 rel_pos1;
+                       b3Vector3 rel_pos2;
+                       b3Scalar relaxation;
+                       b3Scalar rel_vel;
+                       b3Vector3 vel;
+
+                       int frictionIndex = m_tmpSolverContactConstraintPool.size();
+                       b3SolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
+                       //                      b3RigidBody* rb0 = b3RigidBody::upcast(colObj0);
+                       //                      b3RigidBody* rb1 = b3RigidBody::upcast(colObj1);
+                       solverConstraint.m_solverBodyIdA = solverBodyIdA;
+                       solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+                       solverConstraint.m_originalContactPoint = &cp;
+
+                       setupContactConstraint(bodies, inertias, solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, vel, rel_vel, relaxation, rel_pos1, rel_pos2);
+
+                       //                      const b3Vector3& pos1 = cp.getPositionWorldOnA();
+                       //                      const b3Vector3& pos2 = cp.getPositionWorldOnB();
+
+                       /////setup the friction constraints
+
+                       solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
+
+                       b3Vector3 angVelA, angVelB;
+                       solverBodyA->getAngularVelocity(angVelA);
+                       solverBodyB->getAngularVelocity(angVelB);
+                       b3Vector3 relAngVel = angVelB - angVelA;
+
+                       if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0))
+                       {
+                               //only a single rollingFriction per manifold
+                               rollingFriction--;
+                               if (relAngVel.length() > infoGlobal.m_singleAxisRollingFrictionThreshold)
+                               {
+                                       relAngVel.normalize();
+                                       if (relAngVel.length() > 0.001)
+                                               addRollingFrictionConstraint(bodies, inertias, relAngVel, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+                               }
+                               else
+                               {
+                                       addRollingFrictionConstraint(bodies, inertias, cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+                                       b3Vector3 axis0, axis1;
+                                       b3PlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
+                                       if (axis0.length() > 0.001)
+                                               addRollingFrictionConstraint(bodies, inertias, axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+                                       if (axis1.length() > 0.001)
+                                               addRollingFrictionConstraint(bodies, inertias, axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+                               }
+                       }
+
+                       ///Bullet has several options to set the friction directions
+                       ///By default, each contact has only a single friction direction that is recomputed automatically very frame
+                       ///based on the relative linear velocity.
+                       ///If the relative velocity it zero, it will automatically compute a friction direction.
+
+                       ///You can also enable two friction directions, using the B3_SOLVER_USE_2_FRICTION_DIRECTIONS.
+                       ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
+                       ///
+                       ///If you choose B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
+                       ///
+                       ///The user can manually override the friction directions for certain contacts using a contact callback,
+                       ///and set the cp.m_lateralFrictionInitialized to true
+                       ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
+                       ///this will give a conveyor belt effect
+                       ///
+                       if (!(infoGlobal.m_solverMode & B3_SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized)
+                       {
+                               cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
+                               b3Scalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
+                               if (!(infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > B3_EPSILON)
+                               {
+                                       cp.m_lateralFrictionDir1 *= 1.f / b3Sqrt(lat_rel_vel);
+                                       if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+                                       {
+                                               cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
+                                               cp.m_lateralFrictionDir2.normalize();  //??
+                                               addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+                                       }
+
+                                       addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+                               }
+                               else
+                               {
+                                       b3PlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
+
+                                       if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+                                       {
+                                               addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+                                       }
+
+                                       addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+
+                                       if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+                                       {
+                                               cp.m_lateralFrictionInitialized = true;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, cp.m_contactMotion1, cp.m_contactCFM1);
+
+                               if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+                                       addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2);
+
+                               setFrictionConstraintImpulse(bodies, inertias, solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
+                       }
+               }
+       }
+}
+
+b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
+{
+       B3_PROFILE("solveGroupCacheFriendlySetup");
+
+       m_maxOverrideNumSolverIterations = 0;
+
+       m_tmpSolverBodyPool.resize(0);
+
+       m_bodyCount.resize(0);
+       m_bodyCount.resize(numBodies, 0);
+       m_bodyCountCheck.resize(0);
+       m_bodyCountCheck.resize(numBodies, 0);
+
+       m_deltaLinearVelocities.resize(0);
+       m_deltaLinearVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
+       m_deltaAngularVelocities.resize(0);
+       m_deltaAngularVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
+
+       //int totalBodies = 0;
+
+       for (int i = 0; i < numConstraints; i++)
+       {
+               int bodyIndexA = constraints[i]->getRigidBodyA();
+               int bodyIndexB = constraints[i]->getRigidBodyB();
+               if (m_usePgs)
+               {
+                       m_bodyCount[bodyIndexA] = -1;
+                       m_bodyCount[bodyIndexB] = -1;
+               }
+               else
+               {
+                       //didn't implement joints with Jacobi version yet
+                       b3Assert(0);
+               }
+       }
+       for (int i = 0; i < numManifolds; i++)
+       {
+               int bodyIndexA = manifoldPtr[i].getBodyA();
+               int bodyIndexB = manifoldPtr[i].getBodyB();
+               if (m_usePgs)
+               {
+                       m_bodyCount[bodyIndexA] = -1;
+                       m_bodyCount[bodyIndexB] = -1;
+               }
+               else
+               {
+                       if (bodies[bodyIndexA].m_invMass)
+                       {
+                               //m_bodyCount[bodyIndexA]+=manifoldPtr[i].getNPoints();
+                               m_bodyCount[bodyIndexA]++;
+                       }
+                       else
+                               m_bodyCount[bodyIndexA] = -1;
+
+                       if (bodies[bodyIndexB].m_invMass)
+                               //      m_bodyCount[bodyIndexB]+=manifoldPtr[i].getNPoints();
+                               m_bodyCount[bodyIndexB]++;
+                       else
+                               m_bodyCount[bodyIndexB] = -1;
+               }
+       }
+
+       if (1)
+       {
+               int j;
+               for (j = 0; j < numConstraints; j++)
+               {
+                       b3TypedConstraint* constraint = constraints[j];
+
+                       constraint->internalSetAppliedImpulse(0.0f);
+               }
+       }
+
+       //b3RigidBody* rb0=0,*rb1=0;
+       //if (1)
+       {
+               {
+                       int totalNumRows = 0;
+                       int i;
+
+                       m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
+                       //calculate the total number of contraint rows
+                       for (i = 0; i < numConstraints; i++)
+                       {
+                               b3TypedConstraint::b3ConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+                               b3JointFeedback* fb = constraints[i]->getJointFeedback();
+                               if (fb)
+                               {
+                                       fb->m_appliedForceBodyA.setZero();
+                                       fb->m_appliedTorqueBodyA.setZero();
+                                       fb->m_appliedForceBodyB.setZero();
+                                       fb->m_appliedTorqueBodyB.setZero();
+                               }
+
+                               if (constraints[i]->isEnabled())
+                               {
+                               }
+                               if (constraints[i]->isEnabled())
+                               {
+                                       constraints[i]->getInfo1(&info1, bodies);
+                               }
+                               else
+                               {
+                                       info1.m_numConstraintRows = 0;
+                                       info1.nub = 0;
+                               }
+                               totalNumRows += info1.m_numConstraintRows;
+                       }
+                       m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
+
+#ifndef DISABLE_JOINTS
+                       ///setup the b3SolverConstraints
+                       int currentRow = 0;
+
+                       for (i = 0; i < numConstraints; i++)
+                       {
+                               const b3TypedConstraint::b3ConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+
+                               if (info1.m_numConstraintRows)
+                               {
+                                       b3Assert(currentRow < totalNumRows);
+
+                                       b3SolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
+                                       b3TypedConstraint* constraint = constraints[i];
+
+                                       b3RigidBodyData& rbA = bodies[constraint->getRigidBodyA()];
+                                       //b3RigidBody& rbA = constraint->getRigidBodyA();
+                                       //                              b3RigidBody& rbB = constraint->getRigidBodyB();
+                                       b3RigidBodyData& rbB = bodies[constraint->getRigidBodyB()];
+
+                                       int solverBodyIdA = getOrInitSolverBody(constraint->getRigidBodyA(), bodies, inertias);
+                                       int solverBodyIdB = getOrInitSolverBody(constraint->getRigidBodyB(), bodies, inertias);
+
+                                       b3SolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+                                       b3SolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
+
+                                       int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
+                                       if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
+                                               m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
+
+                                       int j;
+                                       for (j = 0; j < info1.m_numConstraintRows; j++)
+                                       {
+                                               memset(&currentConstraintRow[j], 0, sizeof(b3SolverConstraint));
+                                               currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
+                                               currentConstraintRow[j].m_upperLimit = B3_INFINITY;
+                                               currentConstraintRow[j].m_appliedImpulse = 0.f;
+                                               currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+                                               currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
+                                               currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
+                                               currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
+                                       }
+
+                                       bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+                                       bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+                                       bodyAPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+                                       bodyAPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+                                       bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+                                       bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+                                       bodyBPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+                                       bodyBPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+
+                                       b3TypedConstraint::b3ConstraintInfo2 info2;
+                                       info2.fps = 1.f / infoGlobal.m_timeStep;
+                                       info2.erp = infoGlobal.m_erp;
+                                       info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
+                                       info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
+                                       info2.m_J2linearAxis = 0;
+                                       info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
+                                       info2.rowskip = sizeof(b3SolverConstraint) / sizeof(b3Scalar);  //check this
+                                                                                                                                                                       ///the size of b3SolverConstraint needs be a multiple of b3Scalar
+                                       b3Assert(info2.rowskip * sizeof(b3Scalar) == sizeof(b3SolverConstraint));
+                                       info2.m_constraintError = &currentConstraintRow->m_rhs;
+                                       currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
+                                       info2.m_damping = infoGlobal.m_damping;
+                                       info2.cfm = &currentConstraintRow->m_cfm;
+                                       info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
+                                       info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
+                                       info2.m_numIterations = infoGlobal.m_numIterations;
+                                       constraints[i]->getInfo2(&info2, bodies);
+
+                                       ///finalize the constraint setup
+                                       for (j = 0; j < info1.m_numConstraintRows; j++)
+                                       {
+                                               b3SolverConstraint& solverConstraint = currentConstraintRow[j];
+
+                                               if (solverConstraint.m_upperLimit >= constraints[i]->getBreakingImpulseThreshold())
+                                               {
+                                                       solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold();
+                                               }
+
+                                               if (solverConstraint.m_lowerLimit <= -constraints[i]->getBreakingImpulseThreshold())
+                                               {
+                                                       solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold();
+                                               }
+
+                                               solverConstraint.m_originalContactPoint = constraint;
+
+                                               b3Matrix3x3& invInertiaWorldA = inertias[constraint->getRigidBodyA()].m_invInertiaWorld;
+                                               {
+                                                       //b3Vector3 angularFactorA(1,1,1);
+                                                       const b3Vector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
+                                                       solverConstraint.m_angularComponentA = invInertiaWorldA * ftorqueAxis1;  //*angularFactorA;
+                                               }
+
+                                               b3Matrix3x3& invInertiaWorldB = inertias[constraint->getRigidBodyB()].m_invInertiaWorld;
+                                               {
+                                                       const b3Vector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
+                                                       solverConstraint.m_angularComponentB = invInertiaWorldB * ftorqueAxis2;  //*constraint->getRigidBodyB().getAngularFactor();
+                                               }
+
+                                               {
+                                                       //it is ok to use solverConstraint.m_contactNormal instead of -solverConstraint.m_contactNormal
+                                                       //because it gets multiplied iMJlB
+                                                       b3Vector3 iMJlA = solverConstraint.m_contactNormal * rbA.m_invMass;
+                                                       b3Vector3 iMJaA = invInertiaWorldA * solverConstraint.m_relpos1CrossNormal;
+                                                       b3Vector3 iMJlB = solverConstraint.m_contactNormal * rbB.m_invMass;  //sign of normal?
+                                                       b3Vector3 iMJaB = invInertiaWorldB * solverConstraint.m_relpos2CrossNormal;
+
+                                                       b3Scalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
+                                                       sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+                                                       sum += iMJlB.dot(solverConstraint.m_contactNormal);
+                                                       sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+                                                       b3Scalar fsum = b3Fabs(sum);
+                                                       b3Assert(fsum > B3_EPSILON);
+                                                       solverConstraint.m_jacDiagABInv = fsum > B3_EPSILON ? b3Scalar(1.) / sum : 0.f;
+                                               }
+
+                                               ///fix rhs
+                                               ///todo: add force/torque accelerators
+                                               {
+                                                       b3Scalar rel_vel;
+                                                       b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.m_linVel) + solverConstraint.m_relpos1CrossNormal.dot(rbA.m_angVel);
+                                                       b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.m_linVel) + solverConstraint.m_relpos2CrossNormal.dot(rbB.m_angVel);
+
+                                                       rel_vel = vel1Dotn + vel2Dotn;
+
+                                                       b3Scalar restitution = 0.f;
+                                                       b3Scalar positionalError = solverConstraint.m_rhs;  //already filled in by getConstraintInfo2
+                                                       b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
+                                                       b3Scalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+                                                       b3Scalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+                                                       solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+                                                       solverConstraint.m_appliedImpulse = 0.f;
+                                               }
+                                       }
+                               }
+                               currentRow += m_tmpConstraintSizesPool[i].m_numConstraintRows;
+                       }
+#endif  //DISABLE_JOINTS
+               }
+
+               {
+                       int i;
+
+                       for (i = 0; i < numManifolds; i++)
+                       {
+                               b3Contact4& manifold = manifoldPtr[i];
+                               convertContact(bodies, inertias, &manifold, infoGlobal);
+                       }
+               }
+       }
+
+       //      b3ContactSolverInfo info = infoGlobal;
+
+       int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+       int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+       int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+       ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
+       m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
+       if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+               m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool * 2);
+       else
+               m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
+
+       m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
+       {
+               int i;
+               for (i = 0; i < numNonContactPool; i++)
+               {
+                       m_orderNonContactConstraintPool[i] = i;
+               }
+               for (i = 0; i < numConstraintPool; i++)
+               {
+                       m_orderTmpConstraintPool[i] = i;
+               }
+               for (i = 0; i < numFrictionPool; i++)
+               {
+                       m_orderFrictionConstraintPool[i] = i;
+               }
+       }
+
+       return 0.f;
+}
+
+b3Scalar b3PgsJacobiSolver::solveSingleIteration(int iteration, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
+{
+       int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+       int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+       int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+       if (infoGlobal.m_solverMode & B3_SOLVER_RANDMIZE_ORDER)
+       {
+               if (1)  // uncomment this for a bit less random ((iteration & 7) == 0)
+               {
+                       for (int j = 0; j < numNonContactPool; ++j)
+                       {
+                               int tmp = m_orderNonContactConstraintPool[j];
+                               int swapi = b3RandInt2(j + 1);
+                               m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
+                               m_orderNonContactConstraintPool[swapi] = tmp;
+                       }
+
+                       //contact/friction constraints are not solved more than
+                       if (iteration < infoGlobal.m_numIterations)
+                       {
+                               for (int j = 0; j < numConstraintPool; ++j)
+                               {
+                                       int tmp = m_orderTmpConstraintPool[j];
+                                       int swapi = b3RandInt2(j + 1);
+                                       m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
+                                       m_orderTmpConstraintPool[swapi] = tmp;
+                               }
+
+                               for (int j = 0; j < numFrictionPool; ++j)
+                               {
+                                       int tmp = m_orderFrictionConstraintPool[j];
+                                       int swapi = b3RandInt2(j + 1);
+                                       m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
+                                       m_orderFrictionConstraintPool[swapi] = tmp;
+                               }
+                       }
+               }
+       }
+
+       if (infoGlobal.m_solverMode & B3_SOLVER_SIMD)
+       {
+               ///solve all joint constraints, using SIMD, if available
+               for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
+               {
+                       b3SolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+                       if (iteration < constraint.m_overrideNumSolverIterations)
+                               resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
+               }
+
+               if (iteration < infoGlobal.m_numIterations)
+               {
+                       ///solve all contact constraints using SIMD, if available
+                       if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+                       {
+                               int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                               int multiplier = (infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
+
+                               for (int c = 0; c < numPoolConstraints; c++)
+                               {
+                                       b3Scalar totalImpulse = 0;
+
+                                       {
+                                               const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
+                                               resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                               totalImpulse = solveManifold.m_appliedImpulse;
+                                       }
+                                       bool applyFriction = true;
+                                       if (applyFriction)
+                                       {
+                                               {
+                                                       b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
+
+                                                       if (totalImpulse > b3Scalar(0))
+                                                       {
+                                                               solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                                                               solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+                                                               resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                                       }
+                                               }
+
+                                               if (infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS)
+                                               {
+                                                       b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
+
+                                                       if (totalImpulse > b3Scalar(0))
+                                                       {
+                                                               solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                                                               solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+                                                               resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       else  //B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+                       {
+                               //solve the friction constraints after all contact constraints, don't interleave them
+                               int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                               int j;
+
+                               for (j = 0; j < numPoolConstraints; j++)
+                               {
+                                       const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+                                       resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                               }
+
+                               if (!m_usePgs)
+                                       averageVelocities();
+
+                               ///solve all friction constraints, using SIMD, if available
+
+                               int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+                               for (j = 0; j < numFrictionPoolConstraints; j++)
+                               {
+                                       b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+                                       b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+
+                                       if (totalImpulse > b3Scalar(0))
+                                       {
+                                               solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                                               solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+                                               resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                       }
+                               }
+
+                               int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+                               for (j = 0; j < numRollingFrictionPoolConstraints; j++)
+                               {
+                                       b3SolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+                                       b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+                                       if (totalImpulse > b3Scalar(0))
+                                       {
+                                               b3Scalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+                                               if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+                                                       rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+                                               rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+                                               rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+                                               resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+                                       }
+                               }
+                       }
+               }
+       }
+       else
+       {
+               //non-SIMD version
+               ///solve all joint constraints
+               for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
+               {
+                       b3SolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+                       if (iteration < constraint.m_overrideNumSolverIterations)
+                               resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
+               }
+
+               if (iteration < infoGlobal.m_numIterations)
+               {
+                       ///solve all contact constraints
+                       int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                       for (int j = 0; j < numPoolConstraints; j++)
+                       {
+                               const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+                               resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                       }
+                       ///solve all friction constraints
+                       int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+                       for (int j = 0; j < numFrictionPoolConstraints; j++)
+                       {
+                               b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+                               b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+
+                               if (totalImpulse > b3Scalar(0))
+                               {
+                                       solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                                       solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+                                       resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                               }
+                       }
+
+                       int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+                       for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
+                       {
+                               b3SolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+                               b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+                               if (totalImpulse > b3Scalar(0))
+                               {
+                                       b3Scalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+                                       if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+                                               rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+                                       rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+                                       rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+                                       resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+                               }
+                       }
+               }
+       }
+       return 0.f;
+}
+
+void b3PgsJacobiSolver::solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
+{
+       int iteration;
+       if (infoGlobal.m_splitImpulse)
+       {
+               if (infoGlobal.m_solverMode & B3_SOLVER_SIMD)
+               {
+                       for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
+                       {
+                               {
+                                       int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                                       int j;
+                                       for (j = 0; j < numPoolConstraints; j++)
+                                       {
+                                               const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+
+                                               resolveSplitPenetrationSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                       }
+                               }
+                       }
+               }
+               else
+               {
+                       for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
+                       {
+                               {
+                                       int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                                       int j;
+                                       for (j = 0; j < numPoolConstraints; j++)
+                                       {
+                                               const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+
+                                               resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
+{
+       B3_PROFILE("solveGroupCacheFriendlyIterations");
+
+       {
+               ///this is a special step to resolve penetrations (just for contacts)
+               solveGroupCacheFriendlySplitImpulseIterations(constraints, numConstraints, infoGlobal);
+
+               int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
+
+               for (int iteration = 0; iteration < maxIterations; iteration++)
+               //for ( int iteration = maxIterations-1  ; iteration >= 0;iteration--)
+               {
+                       solveSingleIteration(iteration, constraints, numConstraints, infoGlobal);
+
+                       if (!m_usePgs)
+                       {
+                               averageVelocities();
+                       }
+               }
+       }
+       return 0.f;
+}
+
+void b3PgsJacobiSolver::averageVelocities()
+{
+       B3_PROFILE("averaging");
+       //average the velocities
+       int numBodies = m_bodyCount.size();
+
+       m_deltaLinearVelocities.resize(0);
+       m_deltaLinearVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
+       m_deltaAngularVelocities.resize(0);
+       m_deltaAngularVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
+
+       for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
+       {
+               if (!m_tmpSolverBodyPool[i].m_invMass.isZero())
+               {
+                       int orgBodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
+                       m_deltaLinearVelocities[orgBodyIndex] += m_tmpSolverBodyPool[i].getDeltaLinearVelocity();
+                       m_deltaAngularVelocities[orgBodyIndex] += m_tmpSolverBodyPool[i].getDeltaAngularVelocity();
+               }
+       }
+
+       for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
+       {
+               int orgBodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
+
+               if (!m_tmpSolverBodyPool[i].m_invMass.isZero())
+               {
+                       b3Assert(m_bodyCount[orgBodyIndex] == m_bodyCountCheck[orgBodyIndex]);
+
+                       b3Scalar factor = 1.f / b3Scalar(m_bodyCount[orgBodyIndex]);
+
+                       m_tmpSolverBodyPool[i].m_deltaLinearVelocity = m_deltaLinearVelocities[orgBodyIndex] * factor;
+                       m_tmpSolverBodyPool[i].m_deltaAngularVelocity = m_deltaAngularVelocities[orgBodyIndex] * factor;
+               }
+       }
+}
+
+b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, const b3ContactSolverInfo& infoGlobal)
+{
+       B3_PROFILE("solveGroupCacheFriendlyFinish");
+       int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+       int i, j;
+
+       if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
+       {
+               for (j = 0; j < numPoolConstraints; j++)
+               {
+                       const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
+                       b3ContactPoint* pt = (b3ContactPoint*)solveManifold.m_originalContactPoint;
+                       b3Assert(pt);
+                       pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
+                       //      float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+                       //      printf("pt->m_appliedImpulseLateral1 = %f\n", f);
+                       pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+                       //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
+                       if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
+                       {
+                               pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
+                       }
+                       //do a callback here?
+               }
+       }
+
+       numPoolConstraints = m_tmpSolverNonContactConstraintPool.size();
+       for (j = 0; j < numPoolConstraints; j++)
+       {
+               const b3SolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
+               b3TypedConstraint* constr = (b3TypedConstraint*)solverConstr.m_originalContactPoint;
+               b3JointFeedback* fb = constr->getJointFeedback();
+               if (fb)
+               {
+                       b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverConstr.m_solverBodyIdA];
+                       b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverConstr.m_solverBodyIdB];
+
+                       fb->m_appliedForceBodyA += solverConstr.m_contactNormal * solverConstr.m_appliedImpulse * bodyA->m_linearFactor / infoGlobal.m_timeStep;
+                       fb->m_appliedForceBodyB += -solverConstr.m_contactNormal * solverConstr.m_appliedImpulse * bodyB->m_linearFactor / infoGlobal.m_timeStep;
+                       fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal * bodyA->m_angularFactor * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep;
+                       fb->m_appliedTorqueBodyB += -solverConstr.m_relpos1CrossNormal * bodyB->m_angularFactor * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep;
+               }
+
+               constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
+               if (b3Fabs(solverConstr.m_appliedImpulse) >= constr->getBreakingImpulseThreshold())
+               {
+                       constr->setEnabled(false);
+               }
+       }
+
+       {
+               B3_PROFILE("write back velocities and transforms");
+               for (i = 0; i < m_tmpSolverBodyPool.size(); i++)
+               {
+                       int bodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
+                       //b3Assert(i==bodyIndex);
+
+                       b3RigidBodyData* body = &bodies[bodyIndex];
+                       if (body->m_invMass)
+                       {
+                               if (infoGlobal.m_splitImpulse)
+                                       m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
+                               else
+                                       m_tmpSolverBodyPool[i].writebackVelocity();
+
+                               if (m_usePgs)
+                               {
+                                       body->m_linVel = m_tmpSolverBodyPool[i].m_linearVelocity;
+                                       body->m_angVel = m_tmpSolverBodyPool[i].m_angularVelocity;
+                               }
+                               else
+                               {
+                                       b3Scalar factor = 1.f / b3Scalar(m_bodyCount[bodyIndex]);
+
+                                       b3Vector3 deltaLinVel = m_deltaLinearVelocities[bodyIndex] * factor;
+                                       b3Vector3 deltaAngVel = m_deltaAngularVelocities[bodyIndex] * factor;
+                                       //printf("body %d\n",bodyIndex);
+                                       //printf("deltaLinVel = %f,%f,%f\n",deltaLinVel.getX(),deltaLinVel.getY(),deltaLinVel.getZ());
+                                       //printf("deltaAngVel = %f,%f,%f\n",deltaAngVel.getX(),deltaAngVel.getY(),deltaAngVel.getZ());
+
+                                       body->m_linVel += deltaLinVel;
+                                       body->m_angVel += deltaAngVel;
+                               }
+
+                               if (infoGlobal.m_splitImpulse)
+                               {
+                                       body->m_pos = m_tmpSolverBodyPool[i].m_worldTransform.getOrigin();
+                                       b3Quaternion orn;
+                                       orn = m_tmpSolverBodyPool[i].m_worldTransform.getRotation();
+                                       body->m_quat = orn;
+                               }
+                       }
+               }
+       }
+
+       m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
+
+       m_tmpSolverBodyPool.resizeNoInitialize(0);
+       return 0.f;
+}
+
+void b3PgsJacobiSolver::reset()
+{
+       m_btSeed2 = 0;
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h
new file mode 100644 (file)
index 0000000..5b61654
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef B3_PGS_JACOBI_SOLVER
+#define B3_PGS_JACOBI_SOLVER
+
+struct b3Contact4;
+struct b3ContactPoint;
+
+class b3Dispatcher;
+
+#include "b3TypedConstraint.h"
+#include "b3ContactSolverInfo.h"
+#include "b3SolverBody.h"
+#include "b3SolverConstraint.h"
+
+struct b3RigidBodyData;
+struct b3InertiaData;
+
+class b3PgsJacobiSolver
+{
+protected:
+       b3AlignedObjectArray<b3SolverBody> m_tmpSolverBodyPool;
+       b3ConstraintArray m_tmpSolverContactConstraintPool;
+       b3ConstraintArray m_tmpSolverNonContactConstraintPool;
+       b3ConstraintArray m_tmpSolverContactFrictionConstraintPool;
+       b3ConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
+
+       b3AlignedObjectArray<int> m_orderTmpConstraintPool;
+       b3AlignedObjectArray<int> m_orderNonContactConstraintPool;
+       b3AlignedObjectArray<int> m_orderFrictionConstraintPool;
+       b3AlignedObjectArray<b3TypedConstraint::b3ConstraintInfo1> m_tmpConstraintSizesPool;
+
+       b3AlignedObjectArray<int> m_bodyCount;
+       b3AlignedObjectArray<int> m_bodyCountCheck;
+
+       b3AlignedObjectArray<b3Vector3> m_deltaLinearVelocities;
+       b3AlignedObjectArray<b3Vector3> m_deltaAngularVelocities;
+
+       bool m_usePgs;
+       void averageVelocities();
+
+       int m_maxOverrideNumSolverIterations;
+
+       int m_numSplitImpulseRecoveries;
+
+       b3Scalar getContactProcessingThreshold(b3Contact4* contact)
+       {
+               return 0.02f;
+       }
+       void setupFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
+                                                                b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
+                                                                b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation,
+                                                                b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.);
+
+       void setupRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
+                                                                               b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
+                                                                               b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation,
+                                                                               b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.);
+
+       b3SolverConstraint& addFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.);
+       b3SolverConstraint& addRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity = 0, b3Scalar cfmSlip = 0.f);
+
+       void setupContactConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias,
+                                                               b3SolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp,
+                                                               const b3ContactSolverInfo& infoGlobal, b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation,
+                                                               b3Vector3& rel_pos1, b3Vector3& rel_pos2);
+
+       void setFrictionConstraintImpulse(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB,
+                                                                         b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal);
+
+       ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
+       unsigned long m_btSeed2;
+
+       b3Scalar restitutionCurve(b3Scalar rel_vel, b3Scalar restitution);
+
+       void convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias, b3Contact4* manifold, const b3ContactSolverInfo& infoGlobal);
+
+       void resolveSplitPenetrationSIMD(
+               b3SolverBody& bodyA, b3SolverBody& bodyB,
+               const b3SolverConstraint& contactConstraint);
+
+       void resolveSplitPenetrationImpulseCacheFriendly(
+               b3SolverBody& bodyA, b3SolverBody& bodyB,
+               const b3SolverConstraint& contactConstraint);
+
+       //internal method
+       int getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies, b3InertiaData* inertias);
+       void initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* collisionObject);
+
+       void resolveSingleConstraintRowGeneric(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
+
+       void resolveSingleConstraintRowGenericSIMD(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
+
+       void resolveSingleConstraintRowLowerLimit(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
+
+       void resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
+
+protected:
+       virtual b3Scalar solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+
+       virtual b3Scalar solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+       virtual void solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+       b3Scalar solveSingleIteration(int iteration, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+
+       virtual b3Scalar solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, const b3ContactSolverInfo& infoGlobal);
+
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       b3PgsJacobiSolver(bool usePgs);
+       virtual ~b3PgsJacobiSolver();
+
+       //      void    solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts);
+       void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints);
+
+       b3Scalar solveGroup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+
+       ///clear internal cached data and reset random seed
+       virtual void reset();
+
+       unsigned long b3Rand2();
+
+       int b3RandInt2(int n);
+
+       void setRandSeed(unsigned long seed)
+       {
+               m_btSeed2 = seed;
+       }
+       unsigned long getRandSeed() const
+       {
+               return m_btSeed2;
+       }
+};
+
+#endif  //B3_PGS_JACOBI_SOLVER
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp
new file mode 100644 (file)
index 0000000..f9b103e
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3Point2PointConstraint.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include <new>
+
+b3Point2PointConstraint::b3Point2PointConstraint(int rbA, int rbB, const b3Vector3& pivotInA, const b3Vector3& pivotInB)
+       : b3TypedConstraint(B3_POINT2POINT_CONSTRAINT_TYPE, rbA, rbB), m_pivotInA(pivotInA), m_pivotInB(pivotInB), m_flags(0)
+{
+}
+
+/*
+b3Point2PointConstraint::b3Point2PointConstraint(int  rbA,const b3Vector3& pivotInA)
+:b3TypedConstraint(B3_POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)),
+m_flags(0),
+m_useSolveConstraintObsolete(false)
+{
+       
+}
+*/
+
+void b3Point2PointConstraint::getInfo1(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
+{
+       getInfo1NonVirtual(info, bodies);
+}
+
+void b3Point2PointConstraint::getInfo1NonVirtual(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
+{
+       info->m_numConstraintRows = 3;
+       info->nub = 3;
+}
+
+void b3Point2PointConstraint::getInfo2(b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
+{
+       b3Transform trA;
+       trA.setIdentity();
+       trA.setOrigin(bodies[m_rbA].m_pos);
+       trA.setRotation(bodies[m_rbA].m_quat);
+
+       b3Transform trB;
+       trB.setIdentity();
+       trB.setOrigin(bodies[m_rbB].m_pos);
+       trB.setRotation(bodies[m_rbB].m_quat);
+
+       getInfo2NonVirtual(info, trA, trB);
+}
+
+void b3Point2PointConstraint::getInfo2NonVirtual(b3ConstraintInfo2* info, const b3Transform& body0_trans, const b3Transform& body1_trans)
+{
+       //retrieve matrices
+
+       // anchor points in global coordinates with respect to body PORs.
+
+       // set jacobian
+       info->m_J1linearAxis[0] = 1;
+       info->m_J1linearAxis[info->rowskip + 1] = 1;
+       info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
+
+       b3Vector3 a1 = body0_trans.getBasis() * getPivotInA();
+       //b3Vector3 a1a = b3QuatRotate(body0_trans.getRotation(),getPivotInA());
+
+       {
+               b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
+               b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis + info->rowskip);
+               b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis + 2 * info->rowskip);
+               b3Vector3 a1neg = -a1;
+               a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+
+       if (info->m_J2linearAxis)
+       {
+               info->m_J2linearAxis[0] = -1;
+               info->m_J2linearAxis[info->rowskip + 1] = -1;
+               info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
+       }
+
+       b3Vector3 a2 = body1_trans.getBasis() * getPivotInB();
+
+       {
+               //      b3Vector3 a2n = -a2;
+               b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
+               b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis + info->rowskip);
+               b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis + 2 * info->rowskip);
+               a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+
+       // set right hand side
+       b3Scalar currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
+       b3Scalar k = info->fps * currERP;
+       int j;
+       for (j = 0; j < 3; j++)
+       {
+               info->m_constraintError[j * info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
+               //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
+       }
+       if (m_flags & B3_P2P_FLAGS_CFM)
+       {
+               for (j = 0; j < 3; j++)
+               {
+                       info->cfm[j * info->rowskip] = m_cfm;
+               }
+       }
+
+       b3Scalar impulseClamp = m_setting.m_impulseClamp;  //
+       for (j = 0; j < 3; j++)
+       {
+               if (m_setting.m_impulseClamp > 0)
+               {
+                       info->m_lowerLimit[j * info->rowskip] = -impulseClamp;
+                       info->m_upperLimit[j * info->rowskip] = impulseClamp;
+               }
+       }
+       info->m_damping = m_setting.m_damping;
+}
+
+void b3Point2PointConstraint::updateRHS(b3Scalar timeStep)
+{
+       (void)timeStep;
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void b3Point2PointConstraint::setParam(int num, b3Scalar value, int axis)
+{
+       if (axis != -1)
+       {
+               b3AssertConstrParams(0);
+       }
+       else
+       {
+               switch (num)
+               {
+                       case B3_CONSTRAINT_ERP:
+                       case B3_CONSTRAINT_STOP_ERP:
+                               m_erp = value;
+                               m_flags |= B3_P2P_FLAGS_ERP;
+                               break;
+                       case B3_CONSTRAINT_CFM:
+                       case B3_CONSTRAINT_STOP_CFM:
+                               m_cfm = value;
+                               m_flags |= B3_P2P_FLAGS_CFM;
+                               break;
+                       default:
+                               b3AssertConstrParams(0);
+               }
+       }
+}
+
+///return the local value of parameter
+b3Scalar b3Point2PointConstraint::getParam(int num, int axis) const
+{
+       b3Scalar retVal(B3_INFINITY);
+       if (axis != -1)
+       {
+               b3AssertConstrParams(0);
+       }
+       else
+       {
+               switch (num)
+               {
+                       case B3_CONSTRAINT_ERP:
+                       case B3_CONSTRAINT_STOP_ERP:
+                               b3AssertConstrParams(m_flags & B3_P2P_FLAGS_ERP);
+                               retVal = m_erp;
+                               break;
+                       case B3_CONSTRAINT_CFM:
+                       case B3_CONSTRAINT_STOP_CFM:
+                               b3AssertConstrParams(m_flags & B3_P2P_FLAGS_CFM);
+                               retVal = m_cfm;
+                               break;
+                       default:
+                               b3AssertConstrParams(0);
+               }
+       }
+       return retVal;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h
new file mode 100644 (file)
index 0000000..a6c21d2
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_POINT2POINTCONSTRAINT_H
+#define B3_POINT2POINTCONSTRAINT_H
+
+#include "Bullet3Common/b3Vector3.h"
+//#include "b3JacobianEntry.h"
+#include "b3TypedConstraint.h"
+
+class b3RigidBody;
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define b3Point2PointConstraintData b3Point2PointConstraintDoubleData
+#define b3Point2PointConstraintDataName "b3Point2PointConstraintDoubleData"
+#else
+#define b3Point2PointConstraintData b3Point2PointConstraintFloatData
+#define b3Point2PointConstraintDataName "b3Point2PointConstraintFloatData"
+#endif  //B3_USE_DOUBLE_PRECISION
+
+struct b3ConstraintSetting
+{
+       b3ConstraintSetting() : m_tau(b3Scalar(0.3)),
+                                                       m_damping(b3Scalar(1.)),
+                                                       m_impulseClamp(b3Scalar(0.))
+       {
+       }
+       b3Scalar m_tau;
+       b3Scalar m_damping;
+       b3Scalar m_impulseClamp;
+};
+
+enum b3Point2PointFlags
+{
+       B3_P2P_FLAGS_ERP = 1,
+       B3_P2P_FLAGS_CFM = 2
+};
+
+/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
+B3_ATTRIBUTE_ALIGNED16(class)
+b3Point2PointConstraint : public b3TypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+
+       b3Vector3 m_pivotInA;
+       b3Vector3 m_pivotInB;
+
+       int m_flags;
+       b3Scalar m_erp;
+       b3Scalar m_cfm;
+
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       b3ConstraintSetting m_setting;
+
+       b3Point2PointConstraint(int rbA, int rbB, const b3Vector3& pivotInA, const b3Vector3& pivotInB);
+
+       //b3Point2PointConstraint(int  rbA,const b3Vector3& pivotInA);
+
+       virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
+
+       void getInfo1NonVirtual(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
+
+       virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies);
+
+       void getInfo2NonVirtual(b3ConstraintInfo2 * info, const b3Transform& body0_trans, const b3Transform& body1_trans);
+
+       void updateRHS(b3Scalar timeStep);
+
+       void setPivotA(const b3Vector3& pivotA)
+       {
+               m_pivotInA = pivotA;
+       }
+
+       void setPivotB(const b3Vector3& pivotB)
+       {
+               m_pivotInB = pivotB;
+       }
+
+       const b3Vector3& getPivotInA() const
+       {
+               return m_pivotInA;
+       }
+
+       const b3Vector3& getPivotInB() const
+       {
+               return m_pivotInB;
+       }
+
+       ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+       ///If no axis is provided, it uses the default axis for this constraint.
+       virtual void setParam(int num, b3Scalar value, int axis = -1);
+       ///return the local value of parameter
+       virtual b3Scalar getParam(int num, int axis = -1) const;
+
+       //      virtual int     calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       //      virtual const char*     serialize(void* dataBuffer, b3Serializer* serializer) const;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3Point2PointConstraintFloatData
+{
+       b3TypedConstraintData m_typeConstraintData;
+       b3Vector3FloatData m_pivotInA;
+       b3Vector3FloatData m_pivotInB;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3Point2PointConstraintDoubleData
+{
+       b3TypedConstraintData m_typeConstraintData;
+       b3Vector3DoubleData m_pivotInA;
+       b3Vector3DoubleData m_pivotInB;
+};
+
+/*
+B3_FORCE_INLINE        int     b3Point2PointConstraint::calculateSerializeBufferSize() const
+{
+       return sizeof(b3Point2PointConstraintData);
+
+}
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+B3_FORCE_INLINE        const char*     b3Point2PointConstraint::serialize(void* dataBuffer, b3Serializer* serializer) const
+{
+       b3Point2PointConstraintData* p2pData = (b3Point2PointConstraintData*)dataBuffer;
+
+       b3TypedConstraint::serialize(&p2pData->m_typeConstraintData,serializer);
+       m_pivotInA.serialize(p2pData->m_pivotInA);
+       m_pivotInB.serialize(p2pData->m_pivotInB);
+
+       return b3Point2PointConstraintDataName;
+}
+*/
+
+#endif  //B3_POINT2POINTCONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h
new file mode 100644 (file)
index 0000000..c9056ec
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_SOLVER_BODY_H
+#define B3_SOLVER_BODY_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Matrix3x3.h"
+
+#include "Bullet3Common/b3AlignedAllocator.h"
+#include "Bullet3Common/b3TransformUtil.h"
+
+///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
+#ifdef B3_USE_SSE
+#define USE_SIMD 1
+#endif  //
+
+#ifdef USE_SIMD
+
+struct b3SimdScalar
+{
+       B3_FORCE_INLINE b3SimdScalar()
+       {
+       }
+
+       B3_FORCE_INLINE b3SimdScalar(float fl)
+               : m_vec128(_mm_set1_ps(fl))
+       {
+       }
+
+       B3_FORCE_INLINE b3SimdScalar(__m128 v128)
+               : m_vec128(v128)
+       {
+       }
+       union {
+               __m128 m_vec128;
+               float m_floats[4];
+               float x, y, z, w;
+               int m_ints[4];
+               b3Scalar m_unusedPadding;
+       };
+       B3_FORCE_INLINE __m128 get128()
+       {
+               return m_vec128;
+       }
+
+       B3_FORCE_INLINE const __m128 get128() const
+       {
+               return m_vec128;
+       }
+
+       B3_FORCE_INLINE void set128(__m128 v128)
+       {
+               m_vec128 = v128;
+       }
+
+       B3_FORCE_INLINE operator __m128()
+       {
+               return m_vec128;
+       }
+       B3_FORCE_INLINE operator const __m128() const
+       {
+               return m_vec128;
+       }
+
+       B3_FORCE_INLINE operator float() const
+       {
+               return m_floats[0];
+       }
+};
+
+///@brief Return the elementwise product of two b3SimdScalar
+B3_FORCE_INLINE b3SimdScalar
+operator*(const b3SimdScalar& v1, const b3SimdScalar& v2)
+{
+       return b3SimdScalar(_mm_mul_ps(v1.get128(), v2.get128()));
+}
+
+///@brief Return the elementwise product of two b3SimdScalar
+B3_FORCE_INLINE b3SimdScalar
+operator+(const b3SimdScalar& v1, const b3SimdScalar& v2)
+{
+       return b3SimdScalar(_mm_add_ps(v1.get128(), v2.get128()));
+}
+
+#else
+#define b3SimdScalar b3Scalar
+#endif
+
+///The b3SolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3SolverBody
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+       b3Transform m_worldTransform;
+       b3Vector3 m_deltaLinearVelocity;
+       b3Vector3 m_deltaAngularVelocity;
+       b3Vector3 m_angularFactor;
+       b3Vector3 m_linearFactor;
+       b3Vector3 m_invMass;
+       b3Vector3 m_pushVelocity;
+       b3Vector3 m_turnVelocity;
+       b3Vector3 m_linearVelocity;
+       b3Vector3 m_angularVelocity;
+
+       union {
+               void* m_originalBody;
+               int m_originalBodyIndex;
+       };
+
+       int padding[3];
+
+       void setWorldTransform(const b3Transform& worldTransform)
+       {
+               m_worldTransform = worldTransform;
+       }
+
+       const b3Transform& getWorldTransform() const
+       {
+               return m_worldTransform;
+       }
+
+       B3_FORCE_INLINE void getVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
+       {
+               if (m_originalBody)
+                       velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
+               else
+                       velocity.setValue(0, 0, 0);
+       }
+
+       B3_FORCE_INLINE void getAngularVelocity(b3Vector3 & angVel) const
+       {
+               if (m_originalBody)
+                       angVel = m_angularVelocity + m_deltaAngularVelocity;
+               else
+                       angVel.setValue(0, 0, 0);
+       }
+
+       //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+       B3_FORCE_INLINE void applyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
+       {
+               if (m_originalBody)
+               {
+                       m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+                       m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
+               }
+       }
+
+       B3_FORCE_INLINE void internalApplyPushImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, b3Scalar impulseMagnitude)
+       {
+               if (m_originalBody)
+               {
+                       m_pushVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+                       m_turnVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
+               }
+       }
+
+       const b3Vector3& getDeltaLinearVelocity() const
+       {
+               return m_deltaLinearVelocity;
+       }
+
+       const b3Vector3& getDeltaAngularVelocity() const
+       {
+               return m_deltaAngularVelocity;
+       }
+
+       const b3Vector3& getPushVelocity() const
+       {
+               return m_pushVelocity;
+       }
+
+       const b3Vector3& getTurnVelocity() const
+       {
+               return m_turnVelocity;
+       }
+
+       ////////////////////////////////////////////////
+       ///some internal methods, don't use them
+
+       b3Vector3& internalGetDeltaLinearVelocity()
+       {
+               return m_deltaLinearVelocity;
+       }
+
+       b3Vector3& internalGetDeltaAngularVelocity()
+       {
+               return m_deltaAngularVelocity;
+       }
+
+       const b3Vector3& internalGetAngularFactor() const
+       {
+               return m_angularFactor;
+       }
+
+       const b3Vector3& internalGetInvMass() const
+       {
+               return m_invMass;
+       }
+
+       void internalSetInvMass(const b3Vector3& invMass)
+       {
+               m_invMass = invMass;
+       }
+
+       b3Vector3& internalGetPushVelocity()
+       {
+               return m_pushVelocity;
+       }
+
+       b3Vector3& internalGetTurnVelocity()
+       {
+               return m_turnVelocity;
+       }
+
+       B3_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
+       {
+               velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
+       }
+
+       B3_FORCE_INLINE void internalGetAngularVelocity(b3Vector3 & angVel) const
+       {
+               angVel = m_angularVelocity + m_deltaAngularVelocity;
+       }
+
+       //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+       B3_FORCE_INLINE void internalApplyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
+       {
+               //if (m_originalBody)
+               {
+                       m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+                       m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
+               }
+       }
+
+       void writebackVelocity()
+       {
+               //if (m_originalBody>=0)
+               {
+                       m_linearVelocity += m_deltaLinearVelocity;
+                       m_angularVelocity += m_deltaAngularVelocity;
+
+                       //m_originalBody->setCompanionId(-1);
+               }
+       }
+
+       void writebackVelocityAndTransform(b3Scalar timeStep, b3Scalar splitImpulseTurnErp)
+       {
+               (void)timeStep;
+               if (m_originalBody)
+               {
+                       m_linearVelocity += m_deltaLinearVelocity;
+                       m_angularVelocity += m_deltaAngularVelocity;
+
+                       //correct the position/orientation based on push/turn recovery
+                       b3Transform newTransform;
+                       if (m_pushVelocity[0] != 0.f || m_pushVelocity[1] != 0 || m_pushVelocity[2] != 0 || m_turnVelocity[0] != 0.f || m_turnVelocity[1] != 0 || m_turnVelocity[2] != 0)
+                       {
+                               //      b3Quaternion orn = m_worldTransform.getRotation();
+                               b3TransformUtil::integrateTransform(m_worldTransform, m_pushVelocity, m_turnVelocity * splitImpulseTurnErp, timeStep, newTransform);
+                               m_worldTransform = newTransform;
+                       }
+                       //m_worldTransform.setRotation(orn);
+                       //m_originalBody->setCompanionId(-1);
+               }
+       }
+};
+
+#endif  //B3_SOLVER_BODY_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h
new file mode 100644 (file)
index 0000000..1e9533f
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_SOLVER_CONSTRAINT_H
+#define B3_SOLVER_CONSTRAINT_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Matrix3x3.h"
+//#include "b3JacobianEntry.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+//#define NO_FRICTION_TANGENTIALS 1
+#include "b3SolverBody.h"
+
+///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3SolverConstraint
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       b3Vector3 m_relpos1CrossNormal;
+       b3Vector3 m_contactNormal;
+
+       b3Vector3 m_relpos2CrossNormal;
+       //b3Vector3             m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
+
+       b3Vector3 m_angularComponentA;
+       b3Vector3 m_angularComponentB;
+
+       mutable b3SimdScalar m_appliedPushImpulse;
+       mutable b3SimdScalar m_appliedImpulse;
+       int m_padding1;
+       int m_padding2;
+       b3Scalar m_friction;
+       b3Scalar m_jacDiagABInv;
+       b3Scalar m_rhs;
+       b3Scalar m_cfm;
+
+       b3Scalar m_lowerLimit;
+       b3Scalar m_upperLimit;
+       b3Scalar m_rhsPenetration;
+       union {
+               void* m_originalContactPoint;
+               b3Scalar m_unusedPadding4;
+       };
+
+       int m_overrideNumSolverIterations;
+       int m_frictionIndex;
+       int m_solverBodyIdA;
+       int m_solverBodyIdB;
+
+       enum b3SolverConstraintType
+       {
+               B3_SOLVER_CONTACT_1D = 0,
+               B3_SOLVER_FRICTION_1D
+       };
+};
+
+typedef b3AlignedObjectArray<b3SolverConstraint> b3ConstraintArray;
+
+#endif  //B3_SOLVER_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp
new file mode 100644 (file)
index 0000000..eab17b9
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3TypedConstraint.h"
+//#include "Bullet3Common/b3Serializer.h"
+
+#define B3_DEFAULT_DEBUGDRAW_SIZE b3Scalar(0.3f)
+
+b3TypedConstraint::b3TypedConstraint(b3TypedConstraintType type, int rbA, int rbB)
+       : b3TypedObject(type),
+         m_userConstraintType(-1),
+         m_userConstraintPtr((void*)-1),
+         m_breakingImpulseThreshold(B3_INFINITY),
+         m_isEnabled(true),
+         m_needsFeedback(false),
+         m_overrideNumSolverIterations(-1),
+         m_rbA(rbA),
+         m_rbB(rbB),
+         m_appliedImpulse(b3Scalar(0.)),
+         m_dbgDrawSize(B3_DEFAULT_DEBUGDRAW_SIZE),
+         m_jointFeedback(0)
+{
+}
+
+b3Scalar b3TypedConstraint::getMotorFactor(b3Scalar pos, b3Scalar lowLim, b3Scalar uppLim, b3Scalar vel, b3Scalar timeFact)
+{
+       if (lowLim > uppLim)
+       {
+               return b3Scalar(1.0f);
+       }
+       else if (lowLim == uppLim)
+       {
+               return b3Scalar(0.0f);
+       }
+       b3Scalar lim_fact = b3Scalar(1.0f);
+       b3Scalar delta_max = vel / timeFact;
+       if (delta_max < b3Scalar(0.0f))
+       {
+               if ((pos >= lowLim) && (pos < (lowLim - delta_max)))
+               {
+                       lim_fact = (lowLim - pos) / delta_max;
+               }
+               else if (pos < lowLim)
+               {
+                       lim_fact = b3Scalar(0.0f);
+               }
+               else
+               {
+                       lim_fact = b3Scalar(1.0f);
+               }
+       }
+       else if (delta_max > b3Scalar(0.0f))
+       {
+               if ((pos <= uppLim) && (pos > (uppLim - delta_max)))
+               {
+                       lim_fact = (uppLim - pos) / delta_max;
+               }
+               else if (pos > uppLim)
+               {
+                       lim_fact = b3Scalar(0.0f);
+               }
+               else
+               {
+                       lim_fact = b3Scalar(1.0f);
+               }
+       }
+       else
+       {
+               lim_fact = b3Scalar(0.0f);
+       }
+       return lim_fact;
+}
+
+void b3AngularLimit::set(b3Scalar low, b3Scalar high, b3Scalar _softness, b3Scalar _biasFactor, b3Scalar _relaxationFactor)
+{
+       m_halfRange = (high - low) / 2.0f;
+       m_center = b3NormalizeAngle(low + m_halfRange);
+       m_softness = _softness;
+       m_biasFactor = _biasFactor;
+       m_relaxationFactor = _relaxationFactor;
+}
+
+void b3AngularLimit::test(const b3Scalar angle)
+{
+       m_correction = 0.0f;
+       m_sign = 0.0f;
+       m_solveLimit = false;
+
+       if (m_halfRange >= 0.0f)
+       {
+               b3Scalar deviation = b3NormalizeAngle(angle - m_center);
+               if (deviation < -m_halfRange)
+               {
+                       m_solveLimit = true;
+                       m_correction = -(deviation + m_halfRange);
+                       m_sign = +1.0f;
+               }
+               else if (deviation > m_halfRange)
+               {
+                       m_solveLimit = true;
+                       m_correction = m_halfRange - deviation;
+                       m_sign = -1.0f;
+               }
+       }
+}
+
+b3Scalar b3AngularLimit::getError() const
+{
+       return m_correction * m_sign;
+}
+
+void b3AngularLimit::fit(b3Scalar& angle) const
+{
+       if (m_halfRange > 0.0f)
+       {
+               b3Scalar relativeAngle = b3NormalizeAngle(angle - m_center);
+               if (!b3Equal(relativeAngle, m_halfRange))
+               {
+                       if (relativeAngle > 0.0f)
+                       {
+                               angle = getHigh();
+                       }
+                       else
+                       {
+                               angle = getLow();
+                       }
+               }
+       }
+}
+
+b3Scalar b3AngularLimit::getLow() const
+{
+       return b3NormalizeAngle(m_center - m_halfRange);
+}
+
+b3Scalar b3AngularLimit::getHigh() const
+{
+       return b3NormalizeAngle(m_center + m_halfRange);
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h
new file mode 100644 (file)
index 0000000..82075db
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2010 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_TYPED_CONSTRAINT_H
+#define B3_TYPED_CONSTRAINT_H
+
+#include "Bullet3Common/b3Scalar.h"
+#include "b3SolverConstraint.h"
+
+class b3Serializer;
+
+//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
+enum b3TypedConstraintType
+{
+       B3_POINT2POINT_CONSTRAINT_TYPE = 3,
+       B3_HINGE_CONSTRAINT_TYPE,
+       B3_CONETWIST_CONSTRAINT_TYPE,
+       B3_D6_CONSTRAINT_TYPE,
+       B3_SLIDER_CONSTRAINT_TYPE,
+       B3_CONTACT_CONSTRAINT_TYPE,
+       B3_D6_SPRING_CONSTRAINT_TYPE,
+       B3_GEAR_CONSTRAINT_TYPE,
+       B3_FIXED_CONSTRAINT_TYPE,
+       B3_MAX_CONSTRAINT_TYPE
+};
+
+enum b3ConstraintParams
+{
+       B3_CONSTRAINT_ERP = 1,
+       B3_CONSTRAINT_STOP_ERP,
+       B3_CONSTRAINT_CFM,
+       B3_CONSTRAINT_STOP_CFM
+};
+
+#if 1
+#define b3AssertConstrParams(_par) b3Assert(_par)
+#else
+#define b3AssertConstrParams(_par)
+#endif
+
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3JointFeedback
+{
+       b3Vector3 m_appliedForceBodyA;
+       b3Vector3 m_appliedTorqueBodyA;
+       b3Vector3 m_appliedForceBodyB;
+       b3Vector3 m_appliedTorqueBodyB;
+};
+
+struct b3RigidBodyData;
+
+///TypedConstraint is the baseclass for Bullet constraints and vehicles
+B3_ATTRIBUTE_ALIGNED16(class)
+b3TypedConstraint : public b3TypedObject
+{
+       int m_userConstraintType;
+
+       union {
+               int m_userConstraintId;
+               void* m_userConstraintPtr;
+       };
+
+       b3Scalar m_breakingImpulseThreshold;
+       bool m_isEnabled;
+       bool m_needsFeedback;
+       int m_overrideNumSolverIterations;
+
+       b3TypedConstraint& operator=(b3TypedConstraint& other)
+       {
+               b3Assert(0);
+               (void)other;
+               return *this;
+       }
+
+protected:
+       int m_rbA;
+       int m_rbB;
+       b3Scalar m_appliedImpulse;
+       b3Scalar m_dbgDrawSize;
+       b3JointFeedback* m_jointFeedback;
+
+       ///internal method used by the constraint solver, don't use them directly
+       b3Scalar getMotorFactor(b3Scalar pos, b3Scalar lowLim, b3Scalar uppLim, b3Scalar vel, b3Scalar timeFact);
+
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       virtual ~b3TypedConstraint(){};
+       b3TypedConstraint(b3TypedConstraintType type, int bodyA, int bodyB);
+
+       struct b3ConstraintInfo1
+       {
+               int m_numConstraintRows, nub;
+       };
+
+       struct b3ConstraintInfo2
+       {
+               // integrator parameters: frames per second (1/stepsize), default error
+               // reduction parameter (0..1).
+               b3Scalar fps, erp;
+
+               // for the first and second body, pointers to two (linear and angular)
+               // n*3 jacobian sub matrices, stored by rows. these matrices will have
+               // been initialized to 0 on entry. if the second body is zero then the
+               // J2xx pointers may be 0.
+               b3Scalar *m_J1linearAxis, *m_J1angularAxis, *m_J2linearAxis, *m_J2angularAxis;
+
+               // elements to jump from one row to the next in J's
+               int rowskip;
+
+               // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+               // "constraint force mixing" vector. c is set to zero on entry, cfm is
+               // set to a constant value (typically very small or zero) value on entry.
+               b3Scalar *m_constraintError, *cfm;
+
+               // lo and hi limits for variables (set to -/+ infinity on entry).
+               b3Scalar *m_lowerLimit, *m_upperLimit;
+
+               // findex vector for variables. see the LCP solver interface for a
+               // description of what this does. this is set to -1 on entry.
+               // note that the returned indexes are relative to the first index of
+               // the constraint.
+               int* findex;
+               // number of solver iterations
+               int m_numIterations;
+
+               //damping of the velocity
+               b3Scalar m_damping;
+       };
+
+       int getOverrideNumSolverIterations() const
+       {
+               return m_overrideNumSolverIterations;
+       }
+
+       ///override the number of constraint solver iterations used to solve this constraint
+       ///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations
+       void setOverrideNumSolverIterations(int overideNumIterations)
+       {
+               m_overrideNumSolverIterations = overideNumIterations;
+       }
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void setupSolverConstraint(b3ConstraintArray & ca, int solverBodyA, int solverBodyB, b3Scalar timeStep)
+       {
+               (void)ca;
+               (void)solverBodyA;
+               (void)solverBodyB;
+               (void)timeStep;
+       }
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies) = 0;
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies) = 0;
+
+       ///internal method used by the constraint solver, don't use them directly
+       void internalSetAppliedImpulse(b3Scalar appliedImpulse)
+       {
+               m_appliedImpulse = appliedImpulse;
+       }
+       ///internal method used by the constraint solver, don't use them directly
+       b3Scalar internalGetAppliedImpulse()
+       {
+               return m_appliedImpulse;
+       }
+
+       b3Scalar getBreakingImpulseThreshold() const
+       {
+               return m_breakingImpulseThreshold;
+       }
+
+       void setBreakingImpulseThreshold(b3Scalar threshold)
+       {
+               m_breakingImpulseThreshold = threshold;
+       }
+
+       bool isEnabled() const
+       {
+               return m_isEnabled;
+       }
+
+       void setEnabled(bool enabled)
+       {
+               m_isEnabled = enabled;
+       }
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void solveConstraintObsolete(b3SolverBody& /*bodyA*/, b3SolverBody& /*bodyB*/, b3Scalar /*timeStep*/){};
+
+       int getRigidBodyA() const
+       {
+               return m_rbA;
+       }
+       int getRigidBodyB() const
+       {
+               return m_rbB;
+       }
+
+       int getRigidBodyA()
+       {
+               return m_rbA;
+       }
+       int getRigidBodyB()
+       {
+               return m_rbB;
+       }
+
+       int getUserConstraintType() const
+       {
+               return m_userConstraintType;
+       }
+
+       void setUserConstraintType(int userConstraintType)
+       {
+               m_userConstraintType = userConstraintType;
+       };
+
+       void setUserConstraintId(int uid)
+       {
+               m_userConstraintId = uid;
+       }
+
+       int getUserConstraintId() const
+       {
+               return m_userConstraintId;
+       }
+
+       void setUserConstraintPtr(void* ptr)
+       {
+               m_userConstraintPtr = ptr;
+       }
+
+       void* getUserConstraintPtr()
+       {
+               return m_userConstraintPtr;
+       }
+
+       void setJointFeedback(b3JointFeedback * jointFeedback)
+       {
+               m_jointFeedback = jointFeedback;
+       }
+
+       const b3JointFeedback* getJointFeedback() const
+       {
+               return m_jointFeedback;
+       }
+
+       b3JointFeedback* getJointFeedback()
+       {
+               return m_jointFeedback;
+       }
+
+       int getUid() const
+       {
+               return m_userConstraintId;
+       }
+
+       bool needsFeedback() const
+       {
+               return m_needsFeedback;
+       }
+
+       ///enableFeedback will allow to read the applied linear and angular impulse
+       ///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information
+       void enableFeedback(bool needsFeedback)
+       {
+               m_needsFeedback = needsFeedback;
+       }
+
+       ///getAppliedImpulse is an estimated total applied impulse.
+       ///This feedback could be used to determine breaking constraints or playing sounds.
+       b3Scalar getAppliedImpulse() const
+       {
+               b3Assert(m_needsFeedback);
+               return m_appliedImpulse;
+       }
+
+       b3TypedConstraintType getConstraintType() const
+       {
+               return b3TypedConstraintType(m_objectType);
+       }
+
+       void setDbgDrawSize(b3Scalar dbgDrawSize)
+       {
+               m_dbgDrawSize = dbgDrawSize;
+       }
+       b3Scalar getDbgDrawSize()
+       {
+               return m_dbgDrawSize;
+       }
+
+       ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+       ///If no axis is provided, it uses the default axis for this constraint.
+       virtual void setParam(int num, b3Scalar value, int axis = -1) = 0;
+
+       ///return the local value of parameter
+       virtual b3Scalar getParam(int num, int axis = -1) const = 0;
+
+       //      virtual int     calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       //virtual       const char*     serialize(void* dataBuffer, b3Serializer* serializer) const;
+};
+
+// returns angle in range [-B3_2_PI, B3_2_PI], closest to one of the limits
+// all arguments should be normalized angles (i.e. in range [-B3_PI, B3_PI])
+B3_FORCE_INLINE b3Scalar b3AdjustAngleToLimits(b3Scalar angleInRadians, b3Scalar angleLowerLimitInRadians, b3Scalar angleUpperLimitInRadians)
+{
+       if (angleLowerLimitInRadians >= angleUpperLimitInRadians)
+       {
+               return angleInRadians;
+       }
+       else if (angleInRadians < angleLowerLimitInRadians)
+       {
+               b3Scalar diffLo = b3Fabs(b3NormalizeAngle(angleLowerLimitInRadians - angleInRadians));
+               b3Scalar diffHi = b3Fabs(b3NormalizeAngle(angleUpperLimitInRadians - angleInRadians));
+               return (diffLo < diffHi) ? angleInRadians : (angleInRadians + B3_2_PI);
+       }
+       else if (angleInRadians > angleUpperLimitInRadians)
+       {
+               b3Scalar diffHi = b3Fabs(b3NormalizeAngle(angleInRadians - angleUpperLimitInRadians));
+               b3Scalar diffLo = b3Fabs(b3NormalizeAngle(angleInRadians - angleLowerLimitInRadians));
+               return (diffLo < diffHi) ? (angleInRadians - B3_2_PI) : angleInRadians;
+       }
+       else
+       {
+               return angleInRadians;
+       }
+}
+
+// clang-format off
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3TypedConstraintData
+{
+       int             m_bodyA;
+       int             m_bodyB;
+       char    *m_name;
+
+       int     m_objectType;
+       int     m_userConstraintType;
+       int     m_userConstraintId;
+       int     m_needsFeedback;
+
+       float   m_appliedImpulse;
+       float   m_dbgDrawSize;
+
+       int     m_disableCollisionsBetweenLinkedBodies;
+       int     m_overrideNumSolverIterations;
+
+       float   m_breakingImpulseThreshold;
+       int             m_isEnabled;
+       
+};
+
+// clang-format on
+
+/*B3_FORCE_INLINE      int     b3TypedConstraint::calculateSerializeBufferSize() const
+{
+       return sizeof(b3TypedConstraintData);
+}
+*/
+
+class b3AngularLimit
+{
+private:
+       b3Scalar
+               m_center,
+               m_halfRange,
+               m_softness,
+               m_biasFactor,
+               m_relaxationFactor,
+               m_correction,
+               m_sign;
+
+       bool
+               m_solveLimit;
+
+public:
+       /// Default constructor initializes limit as inactive, allowing free constraint movement
+       b3AngularLimit()
+               : m_center(0.0f),
+                 m_halfRange(-1.0f),
+                 m_softness(0.9f),
+                 m_biasFactor(0.3f),
+                 m_relaxationFactor(1.0f),
+                 m_correction(0.0f),
+                 m_sign(0.0f),
+                 m_solveLimit(false)
+       {
+       }
+
+       /// Sets all limit's parameters.
+       /// When low > high limit becomes inactive.
+       /// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit
+       void set(b3Scalar low, b3Scalar high, b3Scalar _softness = 0.9f, b3Scalar _biasFactor = 0.3f, b3Scalar _relaxationFactor = 1.0f);
+
+       /// Checks conastaint angle against limit. If limit is active and the angle violates the limit
+       /// correction is calculated.
+       void test(const b3Scalar angle);
+
+       /// Returns limit's softness
+       inline b3Scalar getSoftness() const
+       {
+               return m_softness;
+       }
+
+       /// Returns limit's bias factor
+       inline b3Scalar getBiasFactor() const
+       {
+               return m_biasFactor;
+       }
+
+       /// Returns limit's relaxation factor
+       inline b3Scalar getRelaxationFactor() const
+       {
+               return m_relaxationFactor;
+       }
+
+       /// Returns correction value evaluated when test() was invoked
+       inline b3Scalar getCorrection() const
+       {
+               return m_correction;
+       }
+
+       /// Returns sign value evaluated when test() was invoked
+       inline b3Scalar getSign() const
+       {
+               return m_sign;
+       }
+
+       /// Gives half of the distance between min and max limit angle
+       inline b3Scalar getHalfRange() const
+       {
+               return m_halfRange;
+       }
+
+       /// Returns true when the last test() invocation recognized limit violation
+       inline bool isLimit() const
+       {
+               return m_solveLimit;
+       }
+
+       /// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle
+       /// returned is modified so it equals to the limit closest to given angle.
+       void fit(b3Scalar& angle) const;
+
+       /// Returns correction value multiplied by sign value
+       b3Scalar getError() const;
+
+       b3Scalar getLow() const;
+
+       b3Scalar getHigh() const;
+};
+
+#endif  //B3_TYPED_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp
new file mode 100644 (file)
index 0000000..f1080d9
--- /dev/null
@@ -0,0 +1,447 @@
+#include "b3CpuRigidBodyPipeline.h"
+
+#include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
+#include "Bullet3Dynamics/shared/b3Inertia.h"
+
+struct b3CpuRigidBodyPipelineInternalData
+{
+       b3AlignedObjectArray<b3RigidBodyData> m_rigidBodies;
+       b3AlignedObjectArray<b3Inertia> m_inertias;
+       b3AlignedObjectArray<b3Aabb> m_aabbWorldSpace;
+
+       b3DynamicBvhBroadphase* m_bp;
+       b3CpuNarrowPhase* m_np;
+       b3Config m_config;
+};
+
+b3CpuRigidBodyPipeline::b3CpuRigidBodyPipeline(class b3CpuNarrowPhase* narrowphase, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
+{
+       m_data = new b3CpuRigidBodyPipelineInternalData;
+       m_data->m_np = narrowphase;
+       m_data->m_bp = broadphaseDbvt;
+       m_data->m_config = config;
+}
+
+b3CpuRigidBodyPipeline::~b3CpuRigidBodyPipeline()
+{
+       delete m_data;
+}
+
+void b3CpuRigidBodyPipeline::updateAabbWorldSpace()
+{
+       for (int i = 0; i < this->getNumBodies(); i++)
+       {
+               b3RigidBodyData* body = &m_data->m_rigidBodies[i];
+               b3Float4 position = body->m_pos;
+               b3Quat orientation = body->m_quat;
+
+               int collidableIndex = body->m_collidableIdx;
+               b3Collidable& collidable = m_data->m_np->getCollidableCpu(collidableIndex);
+               int shapeIndex = collidable.m_shapeIndex;
+
+               if (shapeIndex >= 0)
+               {
+                       b3Aabb localAabb = m_data->m_np->getLocalSpaceAabb(shapeIndex);
+                       b3Aabb& worldAabb = m_data->m_aabbWorldSpace[i];
+                       float margin = 0.f;
+                       b3TransformAabb2(localAabb.m_minVec, localAabb.m_maxVec, margin, position, orientation, &worldAabb.m_minVec, &worldAabb.m_maxVec);
+                       m_data->m_bp->setAabb(i, worldAabb.m_minVec, worldAabb.m_maxVec, 0);
+               }
+       }
+}
+
+void b3CpuRigidBodyPipeline::computeOverlappingPairs()
+{
+       int numPairs = m_data->m_bp->getOverlappingPairCache()->getNumOverlappingPairs();
+       m_data->m_bp->calculateOverlappingPairs();
+       numPairs = m_data->m_bp->getOverlappingPairCache()->getNumOverlappingPairs();
+       printf("numPairs=%d\n", numPairs);
+}
+
+void b3CpuRigidBodyPipeline::computeContactPoints()
+{
+       b3AlignedObjectArray<b3Int4>& pairs = m_data->m_bp->getOverlappingPairCache()->getOverlappingPairArray();
+
+       m_data->m_np->computeContacts(pairs, m_data->m_aabbWorldSpace, m_data->m_rigidBodies);
+}
+void b3CpuRigidBodyPipeline::stepSimulation(float deltaTime)
+{
+       //update world space aabb's
+       updateAabbWorldSpace();
+
+       //compute overlapping pairs
+       computeOverlappingPairs();
+
+       //compute contacts
+       computeContactPoints();
+
+       //solve contacts
+
+       //update transforms
+       integrate(deltaTime);
+}
+
+static inline float b3CalcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
+                                                                const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
+{
+       return b3Dot(l0, linVel0) + b3Dot(a0, angVel0) + b3Dot(l1, linVel1) + b3Dot(a1, angVel1);
+}
+
+static inline void b3SetLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
+                                                                                b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
+{
+       linear = -n;
+       angular0 = -b3Cross(r0, n);
+       angular1 = b3Cross(r1, n);
+}
+
+static inline void b3SolveContact(b3ContactConstraint4& cs,
+                                                                 const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+                                                                 const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+                                                                 float maxRambdaDt[4], float minRambdaDt[4])
+{
+       b3Vector3 dLinVelA;
+       dLinVelA.setZero();
+       b3Vector3 dAngVelA;
+       dAngVelA.setZero();
+       b3Vector3 dLinVelB;
+       dLinVelB.setZero();
+       b3Vector3 dAngVelB;
+       dAngVelB.setZero();
+
+       for (int ic = 0; ic < 4; ic++)
+       {
+               //      dont necessary because this makes change to 0
+               if (cs.m_jacCoeffInv[ic] == 0.f) continue;
+
+               {
+                       b3Vector3 angular0, angular1, linear;
+                       b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
+                       b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
+                       b3SetLinearAndAngular((const b3Vector3&)-cs.m_linear, (const b3Vector3&)r0, (const b3Vector3&)r1, linear, angular0, angular1);
+
+                       float rambdaDt = b3CalcRelVel((const b3Vector3&)cs.m_linear, (const b3Vector3&)-cs.m_linear, angular0, angular1,
+                                                                                 linVelA, angVelA, linVelB, angVelB) +
+                                                        cs.m_b[ic];
+                       rambdaDt *= cs.m_jacCoeffInv[ic];
+
+                       {
+                               float prevSum = cs.m_appliedRambdaDt[ic];
+                               float updated = prevSum;
+                               updated += rambdaDt;
+                               updated = b3Max(updated, minRambdaDt[ic]);
+                               updated = b3Min(updated, maxRambdaDt[ic]);
+                               rambdaDt = updated - prevSum;
+                               cs.m_appliedRambdaDt[ic] = updated;
+                       }
+
+                       b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+                       b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+                       b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+                       b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
+#ifdef _WIN32
+                       b3Assert(_finite(linImp0.getX()));
+                       b3Assert(_finite(linImp1.getX()));
+#endif
+                       {
+                               linVelA += linImp0;
+                               angVelA += angImp0;
+                               linVelB += linImp1;
+                               angVelB += angImp1;
+                       }
+               }
+       }
+}
+
+static inline void b3SolveFriction(b3ContactConstraint4& cs,
+                                                                  const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+                                                                  const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+                                                                  float maxRambdaDt[4], float minRambdaDt[4])
+{
+       if (cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0) return;
+       const b3Vector3& center = (const b3Vector3&)cs.m_center;
+
+       b3Vector3 n = -(const b3Vector3&)cs.m_linear;
+
+       b3Vector3 tangent[2];
+
+       b3PlaneSpace1(n, tangent[0], tangent[1]);
+
+       b3Vector3 angular0, angular1, linear;
+       b3Vector3 r0 = center - posA;
+       b3Vector3 r1 = center - posB;
+       for (int i = 0; i < 2; i++)
+       {
+               b3SetLinearAndAngular(tangent[i], r0, r1, linear, angular0, angular1);
+               float rambdaDt = b3CalcRelVel(linear, -linear, angular0, angular1,
+                                                                         linVelA, angVelA, linVelB, angVelB);
+               rambdaDt *= cs.m_fJacCoeffInv[i];
+
+               {
+                       float prevSum = cs.m_fAppliedRambdaDt[i];
+                       float updated = prevSum;
+                       updated += rambdaDt;
+                       updated = b3Max(updated, minRambdaDt[i]);
+                       updated = b3Min(updated, maxRambdaDt[i]);
+                       rambdaDt = updated - prevSum;
+                       cs.m_fAppliedRambdaDt[i] = updated;
+               }
+
+               b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+               b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+               b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+               b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
+#ifdef _WIN32
+               b3Assert(_finite(linImp0.getX()));
+               b3Assert(_finite(linImp1.getX()));
+#endif
+               linVelA += linImp0;
+               angVelA += angImp0;
+               linVelB += linImp1;
+               angVelB += angImp1;
+       }
+
+       {  //   angular damping for point constraint
+               b3Vector3 ab = (posB - posA).normalized();
+               b3Vector3 ac = (center - posA).normalized();
+               if (b3Dot(ab, ac) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+               {
+                       float angNA = b3Dot(n, angVelA);
+                       float angNB = b3Dot(n, angVelB);
+
+                       angVelA -= (angNA * 0.1f) * n;
+                       angVelB -= (angNB * 0.1f) * n;
+               }
+       }
+}
+
+struct b3SolveTask  // : public ThreadPool::Task
+{
+       b3SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies,
+                               b3AlignedObjectArray<b3Inertia>& shapes,
+                               b3AlignedObjectArray<b3ContactConstraint4>& constraints,
+                               int start, int nConstraints,
+                               int maxNumBatches,
+                               b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx)
+               : m_bodies(bodies), m_shapes(shapes), m_constraints(constraints), m_wgUsedBodies(wgUsedBodies), m_curWgidx(curWgidx), m_start(start), m_nConstraints(nConstraints), m_solveFriction(true), m_maxNumBatches(maxNumBatches)
+       {
+       }
+
+       unsigned short int getType() { return 0; }
+
+       void run(int tIdx)
+       {
+               b3AlignedObjectArray<int> usedBodies;
+               //printf("run..............\n");
+
+               for (int bb = 0; bb < m_maxNumBatches; bb++)
+               {
+                       usedBodies.resize(0);
+                       for (int ic = m_nConstraints - 1; ic >= 0; ic--)
+                       //for(int ic=0; ic<m_nConstraints; ic++)
+                       {
+                               int i = m_start + ic;
+                               if (m_constraints[i].m_batchIdx != bb)
+                                       continue;
+
+                               float frictionCoeff = b3GetFrictionCoeff(&m_constraints[i]);
+                               int aIdx = (int)m_constraints[i].m_bodyA;
+                               int bIdx = (int)m_constraints[i].m_bodyB;
+                               //int localBatch = m_constraints[i].m_batchIdx;
+                               b3RigidBodyData& bodyA = m_bodies[aIdx];
+                               b3RigidBodyData& bodyB = m_bodies[bIdx];
+
+#if 0
+                               if ((bodyA.m_invMass) && (bodyB.m_invMass))
+                               {
+                               //      printf("aIdx=%d, bIdx=%d\n", aIdx,bIdx);
+                               }
+                               if (bIdx==10)
+                               {
+                                       //printf("ic(b)=%d, localBatch=%d\n",ic,localBatch);
+                               }
+#endif
+                               if (aIdx == 10)
+                               {
+                                       //printf("ic(a)=%d, localBatch=%d\n",ic,localBatch);
+                               }
+                               if (usedBodies.size() < (aIdx + 1))
+                               {
+                                       usedBodies.resize(aIdx + 1, 0);
+                               }
+
+                               if (usedBodies.size() < (bIdx + 1))
+                               {
+                                       usedBodies.resize(bIdx + 1, 0);
+                               }
+
+                               if (bodyA.m_invMass)
+                               {
+                                       b3Assert(usedBodies[aIdx] == 0);
+                                       usedBodies[aIdx]++;
+                               }
+
+                               if (bodyB.m_invMass)
+                               {
+                                       b3Assert(usedBodies[bIdx] == 0);
+                                       usedBodies[bIdx]++;
+                               }
+
+                               if (!m_solveFriction)
+                               {
+                                       float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+                                       float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
+
+                                       b3SolveContact(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
+                                                                  (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
+                                                                  maxRambdaDt, minRambdaDt);
+                               }
+                               else
+                               {
+                                       float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+                                       float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
+
+                                       float sum = 0;
+                                       for (int j = 0; j < 4; j++)
+                                       {
+                                               sum += m_constraints[i].m_appliedRambdaDt[j];
+                                       }
+                                       frictionCoeff = 0.7f;
+                                       for (int j = 0; j < 4; j++)
+                                       {
+                                               maxRambdaDt[j] = frictionCoeff * sum;
+                                               minRambdaDt[j] = -maxRambdaDt[j];
+                                       }
+
+                                       b3SolveFriction(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
+                                                                       (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
+                                                                       maxRambdaDt, minRambdaDt);
+                               }
+                       }
+
+                       if (m_wgUsedBodies)
+                       {
+                               if (m_wgUsedBodies[m_curWgidx].size() < usedBodies.size())
+                               {
+                                       m_wgUsedBodies[m_curWgidx].resize(usedBodies.size());
+                               }
+                               for (int i = 0; i < usedBodies.size(); i++)
+                               {
+                                       if (usedBodies[i])
+                                       {
+                                               //printf("cell %d uses body %d\n", m_curWgidx,i);
+                                               m_wgUsedBodies[m_curWgidx][i] = 1;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
+       b3AlignedObjectArray<b3Inertia>& m_shapes;
+       b3AlignedObjectArray<b3ContactConstraint4>& m_constraints;
+       b3AlignedObjectArray<int>* m_wgUsedBodies;
+       int m_curWgidx;
+       int m_start;
+       int m_nConstraints;
+       bool m_solveFriction;
+       int m_maxNumBatches;
+};
+
+void b3CpuRigidBodyPipeline::solveContactConstraints()
+{
+       int m_nIterations = 4;
+
+       b3AlignedObjectArray<b3ContactConstraint4> contactConstraints;
+       //      const b3AlignedObjectArray<b3Contact4Data>& contacts = m_data->m_np->getContacts();
+       int n = contactConstraints.size();
+       //convert contacts...
+
+       int maxNumBatches = 250;
+
+       for (int iter = 0; iter < m_nIterations; iter++)
+       {
+               b3SolveTask task(m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n, maxNumBatches, 0, 0);
+               task.m_solveFriction = false;
+               task.run(0);
+       }
+
+       for (int iter = 0; iter < m_nIterations; iter++)
+       {
+               b3SolveTask task(m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n, maxNumBatches, 0, 0);
+               task.m_solveFriction = true;
+               task.run(0);
+       }
+}
+
+void b3CpuRigidBodyPipeline::integrate(float deltaTime)
+{
+       float angDamping = 0.f;
+       b3Vector3 gravityAcceleration = b3MakeVector3(0, -9, 0);
+
+       //integrate transforms (external forces/gravity should be moved into constraint solver)
+       for (int i = 0; i < m_data->m_rigidBodies.size(); i++)
+       {
+               b3IntegrateTransform(&m_data->m_rigidBodies[i], deltaTime, angDamping, gravityAcceleration);
+       }
+}
+
+int b3CpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userData)
+{
+       b3RigidBodyData body;
+       int bodyIndex = m_data->m_rigidBodies.size();
+       body.m_invMass = mass ? 1.f / mass : 0.f;
+       body.m_angVel.setValue(0, 0, 0);
+       body.m_collidableIdx = collidableIndex;
+       body.m_frictionCoeff = 0.3f;
+       body.m_linVel.setValue(0, 0, 0);
+       body.m_pos.setValue(position[0], position[1], position[2]);
+       body.m_quat.setValue(orientation[0], orientation[1], orientation[2], orientation[3]);
+       body.m_restituitionCoeff = 0.f;
+
+       m_data->m_rigidBodies.push_back(body);
+
+       if (collidableIndex >= 0)
+       {
+               b3Aabb& worldAabb = m_data->m_aabbWorldSpace.expand();
+
+               b3Aabb localAabb = m_data->m_np->getLocalSpaceAabb(collidableIndex);
+               b3Vector3 localAabbMin = b3MakeVector3(localAabb.m_min[0], localAabb.m_min[1], localAabb.m_min[2]);
+               b3Vector3 localAabbMax = b3MakeVector3(localAabb.m_max[0], localAabb.m_max[1], localAabb.m_max[2]);
+
+               b3Scalar margin = 0.01f;
+               b3Transform t;
+               t.setIdentity();
+               t.setOrigin(b3MakeVector3(position[0], position[1], position[2]));
+               t.setRotation(b3Quaternion(orientation[0], orientation[1], orientation[2], orientation[3]));
+               b3TransformAabb(localAabbMin, localAabbMax, margin, t, worldAabb.m_minVec, worldAabb.m_maxVec);
+
+               m_data->m_bp->createProxy(worldAabb.m_minVec, worldAabb.m_maxVec, bodyIndex, 0, 1, 1);
+               //              b3Vector3 aabbMin,aabbMax;
+               //      m_data->m_bp->getAabb(bodyIndex,aabbMin,aabbMax);
+       }
+       else
+       {
+               b3Error("registerPhysicsInstance using invalid collidableIndex\n");
+       }
+
+       return bodyIndex;
+}
+
+const struct b3RigidBodyData* b3CpuRigidBodyPipeline::getBodyBuffer() const
+{
+       return m_data->m_rigidBodies.size() ? &m_data->m_rigidBodies[0] : 0;
+}
+
+int b3CpuRigidBodyPipeline::getNumBodies() const
+{
+       return m_data->m_rigidBodies.size();
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/b3CpuRigidBodyPipeline.h
new file mode 100644 (file)
index 0000000..9c65419
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_CPU_RIGIDBODY_PIPELINE_H
+#define B3_CPU_RIGIDBODY_PIPELINE_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
+
+class b3CpuRigidBodyPipeline
+{
+protected:
+       struct b3CpuRigidBodyPipelineInternalData* m_data;
+
+       int allocateCollidable();
+
+public:
+       b3CpuRigidBodyPipeline(class b3CpuNarrowPhase* narrowphase, struct b3DynamicBvhBroadphase* broadphaseDbvt, const struct b3Config& config);
+       virtual ~b3CpuRigidBodyPipeline();
+
+       virtual void stepSimulation(float deltaTime);
+       virtual void integrate(float timeStep);
+       virtual void updateAabbWorldSpace();
+       virtual void computeOverlappingPairs();
+       virtual void computeContactPoints();
+       virtual void solveContactConstraints();
+
+       int registerConvexPolyhedron(class b3ConvexUtility* convex);
+
+       int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData);
+       void writeAllInstancesToGpu();
+       void copyConstraintsToHost();
+       void setGravity(const float* grav);
+       void reset();
+
+       int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, float breakingThreshold);
+       int createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold);
+       void removeConstraintByUid(int uid);
+
+       void addConstraint(class b3TypedConstraint* constraint);
+       void removeConstraint(b3TypedConstraint* constraint);
+
+       void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults);
+
+       const struct b3RigidBodyData* getBodyBuffer() const;
+
+       int getNumBodies() const;
+};
+
+#endif  //B3_CPU_RIGIDBODY_PIPELINE_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/premake4.lua b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/premake4.lua
new file mode 100644 (file)
index 0000000..e05b2cd
--- /dev/null
@@ -0,0 +1,18 @@
+       project "Bullet3Dynamics"
+
+       language "C++"
+                               
+       kind "StaticLib"
+
+       includedirs {
+               ".."
+       }               
+       
+    if os.is("Linux") then
+        buildoptions{"-fPIC"}
+    end
+
+       files {
+               "**.cpp",
+               "**.h"
+       }
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3ContactConstraint4.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3ContactConstraint4.h
new file mode 100644 (file)
index 0000000..cf2eed0
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef B3_CONTACT_CONSTRAINT5_H
+#define B3_CONTACT_CONSTRAINT5_H
+
+#include "Bullet3Common/shared/b3Float4.h"
+
+typedef struct b3ContactConstraint4 b3ContactConstraint4_t;
+
+struct b3ContactConstraint4
+{
+       b3Float4 m_linear;  //normal?
+       b3Float4 m_worldPos[4];
+       b3Float4 m_center;  //  friction
+       float m_jacCoeffInv[4];
+       float m_b[4];
+       float m_appliedRambdaDt[4];
+       float m_fJacCoeffInv[2];      //        friction
+       float m_fAppliedRambdaDt[2];  //        friction
+
+       unsigned int m_bodyA;
+       unsigned int m_bodyB;
+       int m_batchIdx;
+       unsigned int m_paddings;
+};
+
+//inline       void setFrictionCoeff(float value) { m_linear[3] = value; }
+inline float b3GetFrictionCoeff(b3ContactConstraint4_t* constraint)
+{
+       return constraint->m_linear.w;
+}
+
+#endif  //B3_CONTACT_CONSTRAINT5_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3ConvertConstraint4.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3ConvertConstraint4.h
new file mode 100644 (file)
index 0000000..3e72f1c
--- /dev/null
@@ -0,0 +1,148 @@
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+void b3PlaneSpace1(b3Float4ConstArg n, b3Float4* p, b3Float4* q);
+void b3PlaneSpace1(b3Float4ConstArg n, b3Float4* p, b3Float4* q)
+{
+       if (b3Fabs(n.z) > 0.70710678f)
+       {
+               // choose p in y-z plane
+               float a = n.y * n.y + n.z * n.z;
+               float k = 1.f / sqrt(a);
+               p[0].x = 0;
+               p[0].y = -n.z * k;
+               p[0].z = n.y * k;
+               // set q = n x p
+               q[0].x = a * k;
+               q[0].y = -n.x * p[0].z;
+               q[0].z = n.x * p[0].y;
+       }
+       else
+       {
+               // choose p in x-y plane
+               float a = n.x * n.x + n.y * n.y;
+               float k = 1.f / sqrt(a);
+               p[0].x = -n.y * k;
+               p[0].y = n.x * k;
+               p[0].z = 0;
+               // set q = n x p
+               q[0].x = -n.z * p[0].y;
+               q[0].y = n.z * p[0].x;
+               q[0].z = a * k;
+       }
+}
+
+void setLinearAndAngular(b3Float4ConstArg n, b3Float4ConstArg r0, b3Float4ConstArg r1, b3Float4* linear, b3Float4* angular0, b3Float4* angular1)
+{
+       *linear = b3MakeFloat4(n.x, n.y, n.z, 0.f);
+       *angular0 = b3Cross3(r0, n);
+       *angular1 = -b3Cross3(r1, n);
+}
+
+float calcRelVel(b3Float4ConstArg l0, b3Float4ConstArg l1, b3Float4ConstArg a0, b3Float4ConstArg a1, b3Float4ConstArg linVel0,
+                                b3Float4ConstArg angVel0, b3Float4ConstArg linVel1, b3Float4ConstArg angVel1)
+{
+       return b3Dot3F4(l0, linVel0) + b3Dot3F4(a0, angVel0) + b3Dot3F4(l1, linVel1) + b3Dot3F4(a1, angVel1);
+}
+
+float calcJacCoeff(b3Float4ConstArg linear0, b3Float4ConstArg linear1, b3Float4ConstArg angular0, b3Float4ConstArg angular1,
+                                  float invMass0, const b3Mat3x3* invInertia0, float invMass1, const b3Mat3x3* invInertia1)
+{
+       //      linear0,1 are normlized
+       float jmj0 = invMass0;  //b3Dot3F4(linear0, linear0)*invMass0;
+       float jmj1 = b3Dot3F4(mtMul3(angular0, *invInertia0), angular0);
+       float jmj2 = invMass1;  //b3Dot3F4(linear1, linear1)*invMass1;
+       float jmj3 = b3Dot3F4(mtMul3(angular1, *invInertia1), angular1);
+       return -1.f / (jmj0 + jmj1 + jmj2 + jmj3);
+}
+
+void setConstraint4(b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4ConstArg angVelA, float invMassA, b3Mat3x3ConstArg invInertiaA,
+                                       b3Float4ConstArg posB, b3Float4ConstArg linVelB, b3Float4ConstArg angVelB, float invMassB, b3Mat3x3ConstArg invInertiaB,
+                                       __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,
+                                       b3ContactConstraint4_t* dstC)
+{
+       dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
+       dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
+
+       float dtInv = 1.f / dt;
+       for (int ic = 0; ic < 4; ic++)
+       {
+               dstC->m_appliedRambdaDt[ic] = 0.f;
+       }
+       dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
+
+       dstC->m_linear = src->m_worldNormalOnB;
+       dstC->m_linear.w = 0.7f;  //src->getFrictionCoeff() );
+       for (int ic = 0; ic < 4; ic++)
+       {
+               b3Float4 r0 = src->m_worldPosB[ic] - posA;
+               b3Float4 r1 = src->m_worldPosB[ic] - posB;
+
+               if (ic >= src->m_worldNormalOnB.w)  //npoints
+               {
+                       dstC->m_jacCoeffInv[ic] = 0.f;
+                       continue;
+               }
+
+               float relVelN;
+               {
+                       b3Float4 linear, angular0, angular1;
+                       setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);
+
+                       dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
+                                                                                                  invMassA, &invInertiaA, invMassB, &invInertiaB);
+
+                       relVelN = calcRelVel(linear, -linear, angular0, angular1,
+                                                                linVelA, angVelA, linVelB, angVelB);
+
+                       float e = 0.f;  //src->getRestituitionCoeff();
+                       if (relVelN * relVelN < 0.004f) e = 0.f;
+
+                       dstC->m_b[ic] = e * relVelN;
+                       //float penetration = src->m_worldPosB[ic].w;
+                       dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift) * positionConstraintCoeff * dtInv;
+                       dstC->m_appliedRambdaDt[ic] = 0.f;
+               }
+       }
+
+       if (src->m_worldNormalOnB.w > 0)  //npoints
+       {                                 //    prepare friction
+               b3Float4 center = b3MakeFloat4(0.f, 0.f, 0.f, 0.f);
+               for (int i = 0; i < src->m_worldNormalOnB.w; i++)
+                       center += src->m_worldPosB[i];
+               center /= (float)src->m_worldNormalOnB.w;
+
+               b3Float4 tangent[2];
+               b3PlaneSpace1(src->m_worldNormalOnB, &tangent[0], &tangent[1]);
+
+               b3Float4 r[2];
+               r[0] = center - posA;
+               r[1] = center - posB;
+
+               for (int i = 0; i < 2; i++)
+               {
+                       b3Float4 linear, angular0, angular1;
+                       setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);
+
+                       dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
+                                                                                                  invMassA, &invInertiaA, invMassB, &invInertiaB);
+                       dstC->m_fAppliedRambdaDt[i] = 0.f;
+               }
+               dstC->m_center = center;
+       }
+
+       for (int i = 0; i < 4; i++)
+       {
+               if (i < src->m_worldNormalOnB.w)
+               {
+                       dstC->m_worldPos[i] = src->m_worldPosB[i];
+               }
+               else
+               {
+                       dstC->m_worldPos[i] = b3MakeFloat4(0.f, 0.f, 0.f, 0.f);
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3Inertia.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3Inertia.h
new file mode 100644 (file)
index 0000000..602a133
--- /dev/null
@@ -0,0 +1,14 @@
+
+
+#ifndef B3_INERTIA_H
+#define B3_INERTIA_H
+
+#include "Bullet3Common/shared/b3Mat3x3.h"
+
+struct b3Inertia
+{
+       b3Mat3x3 m_invInertiaWorld;
+       b3Mat3x3 m_initInvInertia;
+};
+
+#endif  //B3_INERTIA_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3IntegrateTransforms.h b/dali-physics/third-party/bullet3/src/Bullet3Dynamics/shared/b3IntegrateTransforms.h
new file mode 100644 (file)
index 0000000..56d9118
--- /dev/null
@@ -0,0 +1,106 @@
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+inline void integrateSingleTransform(__global b3RigidBodyData_t* bodies, int nodeID, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)
+{
+       if (bodies[nodeID].m_invMass != 0.f)
+       {
+               float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);
+
+               //angular velocity
+               {
+                       b3Float4 axis;
+                       //add some hardcoded angular damping
+                       bodies[nodeID].m_angVel.x *= angularDamping;
+                       bodies[nodeID].m_angVel.y *= angularDamping;
+                       bodies[nodeID].m_angVel.z *= angularDamping;
+
+                       b3Float4 angvel = bodies[nodeID].m_angVel;
+
+                       float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));
+
+                       //limit the angular motion
+                       if (fAngle * timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
+                       {
+                               fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;
+                       }
+                       if (fAngle < 0.001f)
+                       {
+                               // use Taylor's expansions of sync function
+                               axis = angvel * (0.5f * timeStep - (timeStep * timeStep * timeStep) * 0.020833333333f * fAngle * fAngle);
+                       }
+                       else
+                       {
+                               // sync(fAngle) = sin(c*fAngle)/t
+                               axis = angvel * (b3Sin(0.5f * fAngle * timeStep) / fAngle);
+                       }
+
+                       b3Quat dorn;
+                       dorn.x = axis.x;
+                       dorn.y = axis.y;
+                       dorn.z = axis.z;
+                       dorn.w = b3Cos(fAngle * timeStep * 0.5f);
+                       b3Quat orn0 = bodies[nodeID].m_quat;
+                       b3Quat predictedOrn = b3QuatMul(dorn, orn0);
+                       predictedOrn = b3QuatNormalized(predictedOrn);
+                       bodies[nodeID].m_quat = predictedOrn;
+               }
+               //linear velocity
+               bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;
+
+               //apply gravity
+               bodies[nodeID].m_linVel += gravityAcceleration * timeStep;
+       }
+}
+
+inline void b3IntegrateTransform(__global b3RigidBodyData_t* body, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)
+{
+       float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);
+
+       if ((body->m_invMass != 0.f))
+       {
+               //angular velocity
+               {
+                       b3Float4 axis;
+                       //add some hardcoded angular damping
+                       body->m_angVel.x *= angularDamping;
+                       body->m_angVel.y *= angularDamping;
+                       body->m_angVel.z *= angularDamping;
+
+                       b3Float4 angvel = body->m_angVel;
+                       float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));
+                       //limit the angular motion
+                       if (fAngle * timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
+                       {
+                               fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;
+                       }
+                       if (fAngle < 0.001f)
+                       {
+                               // use Taylor's expansions of sync function
+                               axis = angvel * (0.5f * timeStep - (timeStep * timeStep * timeStep) * 0.020833333333f * fAngle * fAngle);
+                       }
+                       else
+                       {
+                               // sync(fAngle) = sin(c*fAngle)/t
+                               axis = angvel * (b3Sin(0.5f * fAngle * timeStep) / fAngle);
+                       }
+                       b3Quat dorn;
+                       dorn.x = axis.x;
+                       dorn.y = axis.y;
+                       dorn.z = axis.z;
+                       dorn.w = b3Cos(fAngle * timeStep * 0.5f);
+                       b3Quat orn0 = body->m_quat;
+
+                       b3Quat predictedOrn = b3QuatMul(dorn, orn0);
+                       predictedOrn = b3QuatNormalized(predictedOrn);
+                       body->m_quat = predictedOrn;
+               }
+
+               //apply gravity
+               body->m_linVel += gravityAcceleration * timeStep;
+
+               //linear velocity
+               body->m_pos += body->m_linVel * timeStep;
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Geometry/CMakeLists.txt b/dali-physics/third-party/bullet3/src/Bullet3Geometry/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8206872
--- /dev/null
@@ -0,0 +1,47 @@
+
+INCLUDE_DIRECTORIES(
+       ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(Bullet3Geometry_SRCS
+       b3ConvexHullComputer.cpp
+       b3GeometryUtil.cpp
+)
+
+SET(Bullet3Geometry_HDRS
+       b3AabbUtil.h
+       b3ConvexHullComputer.h
+       b3GeometryUtil.h
+       b3GrahamScan2dConvexHull.h
+)
+
+ADD_LIBRARY(Bullet3Geometry ${Bullet3Geometry_SRCS} ${Bullet3Geometry_HDRS})
+if (BUILD_SHARED_LIBS)
+  target_link_libraries(Bullet3Geometry Bullet3Common)
+endif()
+SET_TARGET_PROPERTIES(Bullet3Geometry PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet3Geometry PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               #FILES_MATCHING requires CMake 2.6
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet3Geometry DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet3Geometry
+                                       RUNTIME DESTINATION bin
+                                       LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                       ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h"  PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(Bullet3Geometry PROPERTIES FRAMEWORK true)
+                       SET_TARGET_PROPERTIES(Bullet3Geometry PROPERTIES PUBLIC_HEADER "${Bullet3Geometry_HDRS}")
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3AabbUtil.h b/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3AabbUtil.h
new file mode 100644 (file)
index 0000000..04c52d8
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_AABB_UTIL2
+#define B3_AABB_UTIL2
+
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3MinMax.h"
+
+B3_FORCE_INLINE void b3AabbExpand(b3Vector3& aabbMin,
+                                                                 b3Vector3& aabbMax,
+                                                                 const b3Vector3& expansionMin,
+                                                                 const b3Vector3& expansionMax)
+{
+       aabbMin = aabbMin + expansionMin;
+       aabbMax = aabbMax + expansionMax;
+}
+
+/// conservative test for overlap between two aabbs
+B3_FORCE_INLINE bool b3TestPointAgainstAabb2(const b3Vector3& aabbMin1, const b3Vector3& aabbMax1,
+                                                                                        const b3Vector3& point)
+{
+       bool overlap = true;
+       overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
+       overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap;
+       overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap;
+       return overlap;
+}
+
+/// conservative test for overlap between two aabbs
+B3_FORCE_INLINE bool b3TestAabbAgainstAabb2(const b3Vector3& aabbMin1, const b3Vector3& aabbMax1,
+                                                                                       const b3Vector3& aabbMin2, const b3Vector3& aabbMax2)
+{
+       bool overlap = true;
+       overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
+       overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
+       overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
+       return overlap;
+}
+
+/// conservative test for overlap between triangle and aabb
+B3_FORCE_INLINE bool b3TestTriangleAgainstAabb2(const b3Vector3* vertices,
+                                                                                               const b3Vector3& aabbMin, const b3Vector3& aabbMax)
+{
+       const b3Vector3& p1 = vertices[0];
+       const b3Vector3& p2 = vertices[1];
+       const b3Vector3& p3 = vertices[2];
+
+       if (b3Min(b3Min(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
+       if (b3Max(b3Max(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
+
+       if (b3Min(b3Min(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
+       if (b3Max(b3Max(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
+
+       if (b3Min(b3Min(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
+       if (b3Max(b3Max(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
+       return true;
+}
+
+B3_FORCE_INLINE int b3Outcode(const b3Vector3& p, const b3Vector3& halfExtent)
+{
+       return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
+                  (p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
+                  (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
+                  (p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
+                  (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
+                  (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
+}
+
+B3_FORCE_INLINE bool b3RayAabb2(const b3Vector3& rayFrom,
+                                                               const b3Vector3& rayInvDirection,
+                                                               const unsigned int raySign[3],
+                                                               const b3Vector3 bounds[2],
+                                                               b3Scalar& tmin,
+                                                               b3Scalar lambda_min,
+                                                               b3Scalar lambda_max)
+{
+       b3Scalar tmax, tymin, tymax, tzmin, tzmax;
+       tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+       tmax = (bounds[1 - raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+       tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+       tymax = (bounds[1 - raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+
+       if ((tmin > tymax) || (tymin > tmax))
+               return false;
+
+       if (tymin > tmin)
+               tmin = tymin;
+
+       if (tymax < tmax)
+               tmax = tymax;
+
+       tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+       tzmax = (bounds[1 - raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+
+       if ((tmin > tzmax) || (tzmin > tmax))
+               return false;
+       if (tzmin > tmin)
+               tmin = tzmin;
+       if (tzmax < tmax)
+               tmax = tzmax;
+       return ((tmin < lambda_max) && (tmax > lambda_min));
+}
+
+B3_FORCE_INLINE bool b3RayAabb(const b3Vector3& rayFrom,
+                                                          const b3Vector3& rayTo,
+                                                          const b3Vector3& aabbMin,
+                                                          const b3Vector3& aabbMax,
+                                                          b3Scalar& param, b3Vector3& normal)
+{
+       b3Vector3 aabbHalfExtent = (aabbMax - aabbMin) * b3Scalar(0.5);
+       b3Vector3 aabbCenter = (aabbMax + aabbMin) * b3Scalar(0.5);
+       b3Vector3 source = rayFrom - aabbCenter;
+       b3Vector3 target = rayTo - aabbCenter;
+       int sourceOutcode = b3Outcode(source, aabbHalfExtent);
+       int targetOutcode = b3Outcode(target, aabbHalfExtent);
+       if ((sourceOutcode & targetOutcode) == 0x0)
+       {
+               b3Scalar lambda_enter = b3Scalar(0.0);
+               b3Scalar lambda_exit = param;
+               b3Vector3 r = target - source;
+               int i;
+               b3Scalar normSign = 1;
+               b3Vector3 hitNormal = b3MakeVector3(0, 0, 0);
+               int bit = 1;
+
+               for (int j = 0; j < 2; j++)
+               {
+                       for (i = 0; i != 3; ++i)
+                       {
+                               if (sourceOutcode & bit)
+                               {
+                                       b3Scalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
+                                       if (lambda_enter <= lambda)
+                                       {
+                                               lambda_enter = lambda;
+                                               hitNormal.setValue(0, 0, 0);
+                                               hitNormal[i] = normSign;
+                                       }
+                               }
+                               else if (targetOutcode & bit)
+                               {
+                                       b3Scalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
+                                       b3SetMin(lambda_exit, lambda);
+                               }
+                               bit <<= 1;
+                       }
+                       normSign = b3Scalar(-1.);
+               }
+               if (lambda_enter <= lambda_exit)
+               {
+                       param = lambda_enter;
+                       normal = hitNormal;
+                       return true;
+               }
+       }
+       return false;
+}
+
+B3_FORCE_INLINE void b3TransformAabb(const b3Vector3& halfExtents, b3Scalar margin, const b3Transform& t, b3Vector3& aabbMinOut, b3Vector3& aabbMaxOut)
+{
+       b3Vector3 halfExtentsWithMargin = halfExtents + b3MakeVector3(margin, margin, margin);
+       b3Matrix3x3 abs_b = t.getBasis().absolute();
+       b3Vector3 center = t.getOrigin();
+       b3Vector3 extent = halfExtentsWithMargin.dot3(abs_b[0], abs_b[1], abs_b[2]);
+       aabbMinOut = center - extent;
+       aabbMaxOut = center + extent;
+}
+
+B3_FORCE_INLINE void b3TransformAabb(const b3Vector3& localAabbMin, const b3Vector3& localAabbMax, b3Scalar margin, const b3Transform& trans, b3Vector3& aabbMinOut, b3Vector3& aabbMaxOut)
+{
+       //b3Assert(localAabbMin.getX() <= localAabbMax.getX());
+       //b3Assert(localAabbMin.getY() <= localAabbMax.getY());
+       //b3Assert(localAabbMin.getZ() <= localAabbMax.getZ());
+       b3Vector3 localHalfExtents = b3Scalar(0.5) * (localAabbMax - localAabbMin);
+       localHalfExtents += b3MakeVector3(margin, margin, margin);
+
+       b3Vector3 localCenter = b3Scalar(0.5) * (localAabbMax + localAabbMin);
+       b3Matrix3x3 abs_b = trans.getBasis().absolute();
+       b3Vector3 center = trans(localCenter);
+       b3Vector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+       aabbMinOut = center - extent;
+       aabbMaxOut = center + extent;
+}
+
+#define B3_USE_BANCHLESS 1
+#ifdef B3_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)
+B3_FORCE_INLINE unsigned b3TestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
+{
+       return static_cast<unsigned int>(b3Select((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
+B3_FORCE_INLINE bool b3TestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
+{
+       bool overlap = true;
+       overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
+       overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
+       overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
+       return overlap;
+}
+#endif  //B3_USE_BANCHLESS
+
+#endif  //B3_AABB_UTIL2
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3ConvexHullComputer.cpp b/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3ConvexHullComputer.cpp
new file mode 100644 (file)
index 0000000..b376524
--- /dev/null
@@ -0,0 +1,2745 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 <string.h>
+
+#include "b3ConvexHullComputer.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3MinMax.h"
+#include "Bullet3Common/b3Vector3.h"
+
+#ifdef __GNUC__
+#include <stdint.h>
+typedef int32_t btInt32_t;
+typedef int64_t btInt64_t;
+typedef uint32_t btUint32_t;
+typedef uint64_t btUint64_t;
+#elif defined(_MSC_VER)
+typedef __int32 btInt32_t;
+typedef __int64 btInt64_t;
+typedef unsigned __int32 btUint32_t;
+typedef unsigned __int64 btUint64_t;
+#else
+typedef int btInt32_t;
+typedef long long int btInt64_t;
+typedef unsigned int btUint32_t;
+typedef unsigned long long int btUint64_t;
+#endif
+
+//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
+//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL))  // || (defined(__ICL) && defined(_M_X64))   bug in Intel compiler, disable inline assembly
+//     #define USE_X86_64_ASM
+//#endif
+
+//#define DEBUG_CONVEX_HULL
+//#define SHOW_ITERATIONS
+
+#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
+#include <stdio.h>
+#endif
+
+// Convex hull implementation based on Preparata and Hong
+// Ole Kniemeyer, MAXON Computer GmbH
+class b3ConvexHullInternal
+{
+public:
+       class Point64
+       {
+       public:
+               btInt64_t x;
+               btInt64_t y;
+               btInt64_t z;
+
+               Point64(btInt64_t x, btInt64_t y, btInt64_t z) : x(x), y(y), z(z)
+               {
+               }
+
+               bool isZero()
+               {
+                       return (x == 0) && (y == 0) && (z == 0);
+               }
+
+               btInt64_t dot(const Point64& b) const
+               {
+                       return x * b.x + y * b.y + z * b.z;
+               }
+       };
+
+       class Point32
+       {
+       public:
+               btInt32_t x;
+               btInt32_t y;
+               btInt32_t z;
+               int index;
+
+               Point32()
+               {
+               }
+
+               Point32(btInt32_t x, btInt32_t y, btInt32_t z) : x(x), y(y), z(z), index(-1)
+               {
+               }
+
+               bool operator==(const Point32& b) const
+               {
+                       return (x == b.x) && (y == b.y) && (z == b.z);
+               }
+
+               bool operator!=(const Point32& b) const
+               {
+                       return (x != b.x) || (y != b.y) || (z != b.z);
+               }
+
+               bool isZero()
+               {
+                       return (x == 0) && (y == 0) && (z == 0);
+               }
+
+               Point64 cross(const Point32& b) const
+               {
+                       return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+               }
+
+               Point64 cross(const Point64& b) const
+               {
+                       return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+               }
+
+               btInt64_t dot(const Point32& b) const
+               {
+                       return x * b.x + y * b.y + z * b.z;
+               }
+
+               btInt64_t dot(const Point64& b) const
+               {
+                       return x * b.x + y * b.y + z * b.z;
+               }
+
+               Point32 operator+(const Point32& b) const
+               {
+                       return Point32(x + b.x, y + b.y, z + b.z);
+               }
+
+               Point32 operator-(const Point32& b) const
+               {
+                       return Point32(x - b.x, y - b.y, z - b.z);
+               }
+       };
+
+       class Int128
+       {
+       public:
+               btUint64_t low;
+               btUint64_t high;
+
+               Int128()
+               {
+               }
+
+               Int128(btUint64_t low, btUint64_t high) : low(low), high(high)
+               {
+               }
+
+               Int128(btUint64_t low) : low(low), high(0)
+               {
+               }
+
+               Int128(btInt64_t value) : low(value), high((value >= 0) ? 0 : (btUint64_t)-1LL)
+               {
+               }
+
+               static Int128 mul(btInt64_t a, btInt64_t b);
+
+               static Int128 mul(btUint64_t a, btUint64_t b);
+
+               Int128 operator-() const
+               {
+                       return Int128((btUint64_t) - (btInt64_t)low, ~high + (low == 0));
+               }
+
+               Int128 operator+(const Int128& b) const
+               {
+#ifdef USE_X86_64_ASM
+                       Int128 result;
+                       __asm__(
+                               "addq %[bl], %[rl]\n\t"
+                               "adcq %[bh], %[rh]\n\t"
+                               : [rl] "=r"(result.low), [rh] "=r"(result.high)
+                               : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+                               : "cc");
+                       return result;
+#else
+                       btUint64_t lo = low + b.low;
+                       return Int128(lo, high + b.high + (lo < low));
+#endif
+               }
+
+               Int128 operator-(const Int128& b) const
+               {
+#ifdef USE_X86_64_ASM
+                       Int128 result;
+                       __asm__(
+                               "subq %[bl], %[rl]\n\t"
+                               "sbbq %[bh], %[rh]\n\t"
+                               : [rl] "=r"(result.low), [rh] "=r"(result.high)
+                               : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+                               : "cc");
+                       return result;
+#else
+                       return *this + -b;
+#endif
+               }
+
+               Int128& operator+=(const Int128& b)
+               {
+#ifdef USE_X86_64_ASM
+                       __asm__(
+                               "addq %[bl], %[rl]\n\t"
+                               "adcq %[bh], %[rh]\n\t"
+                               : [rl] "=r"(low), [rh] "=r"(high)
+                               : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+                               : "cc");
+#else
+                       btUint64_t lo = low + b.low;
+                       if (lo < low)
+                       {
+                               ++high;
+                       }
+                       low = lo;
+                       high += b.high;
+#endif
+                       return *this;
+               }
+
+               Int128& operator++()
+               {
+                       if (++low == 0)
+                       {
+                               ++high;
+                       }
+                       return *this;
+               }
+
+               Int128 operator*(btInt64_t b) const;
+
+               b3Scalar toScalar() const
+               {
+                       return ((btInt64_t)high >= 0) ? b3Scalar(high) * (b3Scalar(0x100000000LL) * b3Scalar(0x100000000LL)) + b3Scalar(low)
+                                                                                 : -(-*this).toScalar();
+               }
+
+               int getSign() const
+               {
+                       return ((btInt64_t)high < 0) ? -1 : (high || low) ? 1 : 0;
+               }
+
+               bool operator<(const Int128& b) const
+               {
+                       return (high < b.high) || ((high == b.high) && (low < b.low));
+               }
+
+               int ucmp(const Int128& b) const
+               {
+                       if (high < b.high)
+                       {
+                               return -1;
+                       }
+                       if (high > b.high)
+                       {
+                               return 1;
+                       }
+                       if (low < b.low)
+                       {
+                               return -1;
+                       }
+                       if (low > b.low)
+                       {
+                               return 1;
+                       }
+                       return 0;
+               }
+       };
+
+       class Rational64
+       {
+       private:
+               btUint64_t m_numerator;
+               btUint64_t m_denominator;
+               int sign;
+
+       public:
+               Rational64(btInt64_t numerator, btInt64_t denominator)
+               {
+                       if (numerator > 0)
+                       {
+                               sign = 1;
+                               m_numerator = (btUint64_t)numerator;
+                       }
+                       else if (numerator < 0)
+                       {
+                               sign = -1;
+                               m_numerator = (btUint64_t)-numerator;
+                       }
+                       else
+                       {
+                               sign = 0;
+                               m_numerator = 0;
+                       }
+                       if (denominator > 0)
+                       {
+                               m_denominator = (btUint64_t)denominator;
+                       }
+                       else if (denominator < 0)
+                       {
+                               sign = -sign;
+                               m_denominator = (btUint64_t)-denominator;
+                       }
+                       else
+                       {
+                               m_denominator = 0;
+                       }
+               }
+
+               bool isNegativeInfinity() const
+               {
+                       return (sign < 0) && (m_denominator == 0);
+               }
+
+               bool isNaN() const
+               {
+                       return (sign == 0) && (m_denominator == 0);
+               }
+
+               int compare(const Rational64& b) const;
+
+               b3Scalar toScalar() const
+               {
+                       return sign * ((m_denominator == 0) ? B3_INFINITY : (b3Scalar)m_numerator / m_denominator);
+               }
+       };
+
+       class Rational128
+       {
+       private:
+               Int128 numerator;
+               Int128 denominator;
+               int sign;
+               bool isInt64;
+
+       public:
+               Rational128(btInt64_t value)
+               {
+                       if (value > 0)
+                       {
+                               sign = 1;
+                               this->numerator = value;
+                       }
+                       else if (value < 0)
+                       {
+                               sign = -1;
+                               this->numerator = -value;
+                       }
+                       else
+                       {
+                               sign = 0;
+                               this->numerator = (btUint64_t)0;
+                       }
+                       this->denominator = (btUint64_t)1;
+                       isInt64 = true;
+               }
+
+               Rational128(const Int128& numerator, const Int128& denominator)
+               {
+                       sign = numerator.getSign();
+                       if (sign >= 0)
+                       {
+                               this->numerator = numerator;
+                       }
+                       else
+                       {
+                               this->numerator = -numerator;
+                       }
+                       int dsign = denominator.getSign();
+                       if (dsign >= 0)
+                       {
+                               this->denominator = denominator;
+                       }
+                       else
+                       {
+                               sign = -sign;
+                               this->denominator = -denominator;
+                       }
+                       isInt64 = false;
+               }
+
+               int compare(const Rational128& b) const;
+
+               int compare(btInt64_t b) const;
+
+               b3Scalar toScalar() const
+               {
+                       return sign * ((denominator.getSign() == 0) ? B3_INFINITY : numerator.toScalar() / denominator.toScalar());
+               }
+       };
+
+       class PointR128
+       {
+       public:
+               Int128 x;
+               Int128 y;
+               Int128 z;
+               Int128 denominator;
+
+               PointR128()
+               {
+               }
+
+               PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator) : x(x), y(y), z(z), denominator(denominator)
+               {
+               }
+
+               b3Scalar xvalue() const
+               {
+                       return x.toScalar() / denominator.toScalar();
+               }
+
+               b3Scalar yvalue() const
+               {
+                       return y.toScalar() / denominator.toScalar();
+               }
+
+               b3Scalar zvalue() const
+               {
+                       return z.toScalar() / denominator.toScalar();
+               }
+       };
+
+       class Edge;
+       class Face;
+
+       class Vertex
+       {
+       public:
+               Vertex* next;
+               Vertex* prev;
+               Edge* edges;
+               Face* firstNearbyFace;
+               Face* lastNearbyFace;
+               PointR128 point128;
+               Point32 point;
+               int copy;
+
+               Vertex() : next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
+               {
+               }
+
+#ifdef DEBUG_CONVEX_HULL
+               void print()
+               {
+                       b3Printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
+               }
+
+               void printGraph();
+#endif
+
+               Point32 operator-(const Vertex& b) const
+               {
+                       return point - b.point;
+               }
+
+               Rational128 dot(const Point64& b) const
+               {
+                       return (point.index >= 0) ? Rational128(point.dot(b))
+                                                                         : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
+               }
+
+               b3Scalar xvalue() const
+               {
+                       return (point.index >= 0) ? b3Scalar(point.x) : point128.xvalue();
+               }
+
+               b3Scalar yvalue() const
+               {
+                       return (point.index >= 0) ? b3Scalar(point.y) : point128.yvalue();
+               }
+
+               b3Scalar zvalue() const
+               {
+                       return (point.index >= 0) ? b3Scalar(point.z) : point128.zvalue();
+               }
+
+               void receiveNearbyFaces(Vertex* src)
+               {
+                       if (lastNearbyFace)
+                       {
+                               lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
+                       }
+                       else
+                       {
+                               firstNearbyFace = src->firstNearbyFace;
+                       }
+                       if (src->lastNearbyFace)
+                       {
+                               lastNearbyFace = src->lastNearbyFace;
+                       }
+                       for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
+                       {
+                               b3Assert(f->nearbyVertex == src);
+                               f->nearbyVertex = this;
+                       }
+                       src->firstNearbyFace = NULL;
+                       src->lastNearbyFace = NULL;
+               }
+       };
+
+       class Edge
+       {
+       public:
+               Edge* next;
+               Edge* prev;
+               Edge* reverse;
+               Vertex* target;
+               Face* face;
+               int copy;
+
+               ~Edge()
+               {
+                       next = NULL;
+                       prev = NULL;
+                       reverse = NULL;
+                       target = NULL;
+                       face = NULL;
+               }
+
+               void link(Edge* n)
+               {
+                       b3Assert(reverse->target == n->reverse->target);
+                       next = n;
+                       n->prev = this;
+               }
+
+#ifdef DEBUG_CONVEX_HULL
+               void print()
+               {
+                       b3Printf("E%p : %d -> %d,  n=%p p=%p   (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
+                                        reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
+               }
+#endif
+       };
+
+       class Face
+       {
+       public:
+               Face* next;
+               Vertex* nearbyVertex;
+               Face* nextWithSameNearbyVertex;
+               Point32 origin;
+               Point32 dir0;
+               Point32 dir1;
+
+               Face() : next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
+               {
+               }
+
+               void init(Vertex* a, Vertex* b, Vertex* c)
+               {
+                       nearbyVertex = a;
+                       origin = a->point;
+                       dir0 = *b - *a;
+                       dir1 = *c - *a;
+                       if (a->lastNearbyFace)
+                       {
+                               a->lastNearbyFace->nextWithSameNearbyVertex = this;
+                       }
+                       else
+                       {
+                               a->firstNearbyFace = this;
+                       }
+                       a->lastNearbyFace = this;
+               }
+
+               Point64 getNormal()
+               {
+                       return dir0.cross(dir1);
+               }
+       };
+
+       template <typename UWord, typename UHWord>
+       class DMul
+       {
+       private:
+               static btUint32_t high(btUint64_t value)
+               {
+                       return (btUint32_t)(value >> 32);
+               }
+
+               static btUint32_t low(btUint64_t value)
+               {
+                       return (btUint32_t)value;
+               }
+
+               static btUint64_t mul(btUint32_t a, btUint32_t b)
+               {
+                       return (btUint64_t)a * (btUint64_t)b;
+               }
+
+               static void shlHalf(btUint64_t& value)
+               {
+                       value <<= 32;
+               }
+
+               static btUint64_t high(Int128 value)
+               {
+                       return value.high;
+               }
+
+               static btUint64_t low(Int128 value)
+               {
+                       return value.low;
+               }
+
+               static Int128 mul(btUint64_t a, btUint64_t b)
+               {
+                       return Int128::mul(a, b);
+               }
+
+               static void shlHalf(Int128& value)
+               {
+                       value.high = value.low;
+                       value.low = 0;
+               }
+
+       public:
+               static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
+               {
+                       UWord p00 = mul(low(a), low(b));
+                       UWord p01 = mul(low(a), high(b));
+                       UWord p10 = mul(high(a), low(b));
+                       UWord p11 = mul(high(a), high(b));
+                       UWord p0110 = UWord(low(p01)) + UWord(low(p10));
+                       p11 += high(p01);
+                       p11 += high(p10);
+                       p11 += high(p0110);
+                       shlHalf(p0110);
+                       p00 += p0110;
+                       if (p00 < p0110)
+                       {
+                               ++p11;
+                       }
+                       resLow = p00;
+                       resHigh = p11;
+               }
+       };
+
+private:
+       class IntermediateHull
+       {
+       public:
+               Vertex* minXy;
+               Vertex* maxXy;
+               Vertex* minYx;
+               Vertex* maxYx;
+
+               IntermediateHull() : minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
+               {
+               }
+
+               void print();
+       };
+
+       enum Orientation
+       {
+               NONE,
+               CLOCKWISE,
+               COUNTER_CLOCKWISE
+       };
+
+       template <typename T>
+       class PoolArray
+       {
+       private:
+               T* array;
+               int size;
+
+       public:
+               PoolArray<T>* next;
+
+               PoolArray(int size) : size(size), next(NULL)
+               {
+                       array = (T*)b3AlignedAlloc(sizeof(T) * size, 16);
+               }
+
+               ~PoolArray()
+               {
+                       b3AlignedFree(array);
+               }
+
+               T* init()
+               {
+                       T* o = array;
+                       for (int i = 0; i < size; i++, o++)
+                       {
+                               o->next = (i + 1 < size) ? o + 1 : NULL;
+                       }
+                       return array;
+               }
+       };
+
+       template <typename T>
+       class Pool
+       {
+       private:
+               PoolArray<T>* arrays;
+               PoolArray<T>* nextArray;
+               T* freeObjects;
+               int arraySize;
+
+       public:
+               Pool() : arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
+               {
+               }
+
+               ~Pool()
+               {
+                       while (arrays)
+                       {
+                               PoolArray<T>* p = arrays;
+                               arrays = p->next;
+                               p->~PoolArray<T>();
+                               b3AlignedFree(p);
+                       }
+               }
+
+               void reset()
+               {
+                       nextArray = arrays;
+                       freeObjects = NULL;
+               }
+
+               void setArraySize(int arraySize)
+               {
+                       this->arraySize = arraySize;
+               }
+
+               T* newObject()
+               {
+                       T* o = freeObjects;
+                       if (!o)
+                       {
+                               PoolArray<T>* p = nextArray;
+                               if (p)
+                               {
+                                       nextArray = p->next;
+                               }
+                               else
+                               {
+                                       p = new (b3AlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
+                                       p->next = arrays;
+                                       arrays = p;
+                               }
+                               o = p->init();
+                       }
+                       freeObjects = o->next;
+                       return new (o) T();
+               };
+
+               void freeObject(T* object)
+               {
+                       object->~T();
+                       object->next = freeObjects;
+                       freeObjects = object;
+               }
+       };
+
+       b3Vector3 scaling;
+       b3Vector3 center;
+       Pool<Vertex> vertexPool;
+       Pool<Edge> edgePool;
+       Pool<Face> facePool;
+       b3AlignedObjectArray<Vertex*> originalVertices;
+       int mergeStamp;
+       int minAxis;
+       int medAxis;
+       int maxAxis;
+       int usedEdgePairs;
+       int maxUsedEdgePairs;
+
+       static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
+       Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
+       void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
+
+       Edge* newEdgePair(Vertex* from, Vertex* to);
+
+       void removeEdgePair(Edge* edge)
+       {
+               Edge* n = edge->next;
+               Edge* r = edge->reverse;
+
+               b3Assert(edge->target && r->target);
+
+               if (n != edge)
+               {
+                       n->prev = edge->prev;
+                       edge->prev->next = n;
+                       r->target->edges = n;
+               }
+               else
+               {
+                       r->target->edges = NULL;
+               }
+
+               n = r->next;
+
+               if (n != r)
+               {
+                       n->prev = r->prev;
+                       r->prev->next = n;
+                       edge->target->edges = n;
+               }
+               else
+               {
+                       edge->target->edges = NULL;
+               }
+
+               edgePool.freeObject(edge);
+               edgePool.freeObject(r);
+               usedEdgePairs--;
+       }
+
+       void computeInternal(int start, int end, IntermediateHull& result);
+
+       bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
+
+       void merge(IntermediateHull& h0, IntermediateHull& h1);
+
+       b3Vector3 toBtVector(const Point32& v);
+
+       b3Vector3 getBtNormal(Face* face);
+
+       bool shiftFace(Face* face, b3Scalar amount, b3AlignedObjectArray<Vertex*> stack);
+
+public:
+       Vertex* vertexList;
+
+       void compute(const void* coords, bool doubleCoords, int stride, int count);
+
+       b3Vector3 getCoordinates(const Vertex* v);
+
+       b3Scalar shrink(b3Scalar amount, b3Scalar clampAmount);
+};
+
+b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::operator*(btInt64_t b) const
+{
+       bool negative = (btInt64_t)high < 0;
+       Int128 a = negative ? -*this : *this;
+       if (b < 0)
+       {
+               negative = !negative;
+               b = -b;
+       }
+       Int128 result = mul(a.low, (btUint64_t)b);
+       result.high += a.high * (btUint64_t)b;
+       return negative ? -result : result;
+}
+
+b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btInt64_t a, btInt64_t b)
+{
+       Int128 result;
+
+#ifdef USE_X86_64_ASM
+       __asm__("imulq %[b]"
+                       : "=a"(result.low), "=d"(result.high)
+                       : "0"(a), [b] "r"(b)
+                       : "cc");
+       return result;
+
+#else
+       bool negative = a < 0;
+       if (negative)
+       {
+               a = -a;
+       }
+       if (b < 0)
+       {
+               negative = !negative;
+               b = -b;
+       }
+       DMul<btUint64_t, btUint32_t>::mul((btUint64_t)a, (btUint64_t)b, result.low, result.high);
+       return negative ? -result : result;
+#endif
+}
+
+b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btUint64_t a, btUint64_t b)
+{
+       Int128 result;
+
+#ifdef USE_X86_64_ASM
+       __asm__("mulq %[b]"
+                       : "=a"(result.low), "=d"(result.high)
+                       : "0"(a), [b] "r"(b)
+                       : "cc");
+
+#else
+       DMul<btUint64_t, btUint32_t>::mul(a, b, result.low, result.high);
+#endif
+
+       return result;
+}
+
+int b3ConvexHullInternal::Rational64::compare(const Rational64& b) const
+{
+       if (sign != b.sign)
+       {
+               return sign - b.sign;
+       }
+       else if (sign == 0)
+       {
+               return 0;
+       }
+
+       //      return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
+
+#ifdef USE_X86_64_ASM
+
+       int result;
+       btInt64_t tmp;
+       btInt64_t dummy;
+       __asm__(
+               "mulq %[bn]\n\t"
+               "movq %%rax, %[tmp]\n\t"
+               "movq %%rdx, %%rbx\n\t"
+               "movq %[tn], %%rax\n\t"
+               "mulq %[bd]\n\t"
+               "subq %[tmp], %%rax\n\t"
+               "sbbq %%rbx, %%rdx\n\t"  // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
+               "setnsb %%bh\n\t"        // bh=1 if difference is non-negative, bh=0 otherwise
+               "orq %%rdx, %%rax\n\t"
+               "setnzb %%bl\n\t"      // bl=1 if difference if non-zero, bl=0 if it is zero
+               "decb %%bh\n\t"        // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
+               "shll $16, %%ebx\n\t"  // ebx has same sign as difference
+               : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
+               : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
+               : "%rdx", "cc");
+       return result ? result ^ sign  // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
+                                                                  // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
+                                 : 0;
+
+#else
+
+       return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator));
+
+#endif
+}
+
+int b3ConvexHullInternal::Rational128::compare(const Rational128& b) const
+{
+       if (sign != b.sign)
+       {
+               return sign - b.sign;
+       }
+       else if (sign == 0)
+       {
+               return 0;
+       }
+       if (isInt64)
+       {
+               return -b.compare(sign * (btInt64_t)numerator.low);
+       }
+
+       Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
+       DMul<Int128, btUint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh);
+       DMul<Int128, btUint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh);
+
+       int cmp = nbdHigh.ucmp(dbnHigh);
+       if (cmp)
+       {
+               return cmp * sign;
+       }
+       return nbdLow.ucmp(dbnLow) * sign;
+}
+
+int b3ConvexHullInternal::Rational128::compare(btInt64_t b) const
+{
+       if (isInt64)
+       {
+               btInt64_t a = sign * (btInt64_t)numerator.low;
+               return (a > b) ? 1 : (a < b) ? -1 : 0;
+       }
+       if (b > 0)
+       {
+               if (sign <= 0)
+               {
+                       return -1;
+               }
+       }
+       else if (b < 0)
+       {
+               if (sign >= 0)
+               {
+                       return 1;
+               }
+               b = -b;
+       }
+       else
+       {
+               return sign;
+       }
+
+       return numerator.ucmp(denominator * b) * sign;
+}
+
+b3ConvexHullInternal::Edge* b3ConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
+{
+       b3Assert(from && to);
+       Edge* e = edgePool.newObject();
+       Edge* r = edgePool.newObject();
+       e->reverse = r;
+       r->reverse = e;
+       e->copy = mergeStamp;
+       r->copy = mergeStamp;
+       e->target = to;
+       r->target = from;
+       e->face = NULL;
+       r->face = NULL;
+       usedEdgePairs++;
+       if (usedEdgePairs > maxUsedEdgePairs)
+       {
+               maxUsedEdgePairs = usedEdgePairs;
+       }
+       return e;
+}
+
+bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1)
+{
+       Vertex* v0 = h0.maxYx;
+       Vertex* v1 = h1.minYx;
+       if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y))
+       {
+               b3Assert(v0->point.z < v1->point.z);
+               Vertex* v1p = v1->prev;
+               if (v1p == v1)
+               {
+                       c0 = v0;
+                       if (v1->edges)
+                       {
+                               b3Assert(v1->edges->next == v1->edges);
+                               v1 = v1->edges->target;
+                               b3Assert(v1->edges->next == v1->edges);
+                       }
+                       c1 = v1;
+                       return false;
+               }
+               Vertex* v1n = v1->next;
+               v1p->next = v1n;
+               v1n->prev = v1p;
+               if (v1 == h1.minXy)
+               {
+                       if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y)))
+                       {
+                               h1.minXy = v1n;
+                       }
+                       else
+                       {
+                               h1.minXy = v1p;
+                       }
+               }
+               if (v1 == h1.maxXy)
+               {
+                       if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y)))
+                       {
+                               h1.maxXy = v1n;
+                       }
+                       else
+                       {
+                               h1.maxXy = v1p;
+                       }
+               }
+       }
+
+       v0 = h0.maxXy;
+       v1 = h1.maxXy;
+       Vertex* v00 = NULL;
+       Vertex* v10 = NULL;
+       btInt32_t sign = 1;
+
+       for (int side = 0; side <= 1; side++)
+       {
+               btInt32_t dx = (v1->point.x - v0->point.x) * sign;
+               if (dx > 0)
+               {
+                       while (true)
+                       {
+                               btInt32_t dy = v1->point.y - v0->point.y;
+
+                               Vertex* w0 = side ? v0->next : v0->prev;
+                               if (w0 != v0)
+                               {
+                                       btInt32_t dx0 = (w0->point.x - v0->point.x) * sign;
+                                       btInt32_t dy0 = w0->point.y - v0->point.y;
+                                       if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0))))
+                                       {
+                                               v0 = w0;
+                                               dx = (v1->point.x - v0->point.x) * sign;
+                                               continue;
+                                       }
+                               }
+
+                               Vertex* w1 = side ? v1->next : v1->prev;
+                               if (w1 != v1)
+                               {
+                                       btInt32_t dx1 = (w1->point.x - v1->point.x) * sign;
+                                       btInt32_t dy1 = w1->point.y - v1->point.y;
+                                       btInt32_t dxn = (w1->point.x - v0->point.x) * sign;
+                                       if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1))))
+                                       {
+                                               v1 = w1;
+                                               dx = dxn;
+                                               continue;
+                                       }
+                               }
+
+                               break;
+                       }
+               }
+               else if (dx < 0)
+               {
+                       while (true)
+                       {
+                               btInt32_t dy = v1->point.y - v0->point.y;
+
+                               Vertex* w1 = side ? v1->prev : v1->next;
+                               if (w1 != v1)
+                               {
+                                       btInt32_t dx1 = (w1->point.x - v1->point.x) * sign;
+                                       btInt32_t dy1 = w1->point.y - v1->point.y;
+                                       if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1))))
+                                       {
+                                               v1 = w1;
+                                               dx = (v1->point.x - v0->point.x) * sign;
+                                               continue;
+                                       }
+                               }
+
+                               Vertex* w0 = side ? v0->prev : v0->next;
+                               if (w0 != v0)
+                               {
+                                       btInt32_t dx0 = (w0->point.x - v0->point.x) * sign;
+                                       btInt32_t dy0 = w0->point.y - v0->point.y;
+                                       btInt32_t dxn = (v1->point.x - w0->point.x) * sign;
+                                       if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0))))
+                                       {
+                                               v0 = w0;
+                                               dx = dxn;
+                                               continue;
+                                       }
+                               }
+
+                               break;
+                       }
+               }
+               else
+               {
+                       btInt32_t x = v0->point.x;
+                       btInt32_t y0 = v0->point.y;
+                       Vertex* w0 = v0;
+                       Vertex* t;
+                       while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0))
+                       {
+                               w0 = t;
+                               y0 = t->point.y;
+                       }
+                       v0 = w0;
+
+                       btInt32_t y1 = v1->point.y;
+                       Vertex* w1 = v1;
+                       while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1))
+                       {
+                               w1 = t;
+                               y1 = t->point.y;
+                       }
+                       v1 = w1;
+               }
+
+               if (side == 0)
+               {
+                       v00 = v0;
+                       v10 = v1;
+
+                       v0 = h0.minXy;
+                       v1 = h1.minXy;
+                       sign = -1;
+               }
+       }
+
+       v0->prev = v1;
+       v1->next = v0;
+
+       v00->next = v10;
+       v10->prev = v00;
+
+       if (h1.minXy->point.x < h0.minXy->point.x)
+       {
+               h0.minXy = h1.minXy;
+       }
+       if (h1.maxXy->point.x >= h0.maxXy->point.x)
+       {
+               h0.maxXy = h1.maxXy;
+       }
+
+       h0.maxYx = h1.maxYx;
+
+       c0 = v00;
+       c1 = v10;
+
+       return true;
+}
+
+void b3ConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result)
+{
+       int n = end - start;
+       switch (n)
+       {
+               case 0:
+                       result.minXy = NULL;
+                       result.maxXy = NULL;
+                       result.minYx = NULL;
+                       result.maxYx = NULL;
+                       return;
+               case 2:
+               {
+                       Vertex* v = originalVertices[start];
+                       Vertex* w = v + 1;
+                       if (v->point != w->point)
+                       {
+                               btInt32_t dx = v->point.x - w->point.x;
+                               btInt32_t dy = v->point.y - w->point.y;
+
+                               if ((dx == 0) && (dy == 0))
+                               {
+                                       if (v->point.z > w->point.z)
+                                       {
+                                               Vertex* t = w;
+                                               w = v;
+                                               v = t;
+                                       }
+                                       b3Assert(v->point.z < w->point.z);
+                                       v->next = v;
+                                       v->prev = v;
+                                       result.minXy = v;
+                                       result.maxXy = v;
+                                       result.minYx = v;
+                                       result.maxYx = v;
+                               }
+                               else
+                               {
+                                       v->next = w;
+                                       v->prev = w;
+                                       w->next = v;
+                                       w->prev = v;
+
+                                       if ((dx < 0) || ((dx == 0) && (dy < 0)))
+                                       {
+                                               result.minXy = v;
+                                               result.maxXy = w;
+                                       }
+                                       else
+                                       {
+                                               result.minXy = w;
+                                               result.maxXy = v;
+                                       }
+
+                                       if ((dy < 0) || ((dy == 0) && (dx < 0)))
+                                       {
+                                               result.minYx = v;
+                                               result.maxYx = w;
+                                       }
+                                       else
+                                       {
+                                               result.minYx = w;
+                                               result.maxYx = v;
+                                       }
+                               }
+
+                               Edge* e = newEdgePair(v, w);
+                               e->link(e);
+                               v->edges = e;
+
+                               e = e->reverse;
+                               e->link(e);
+                               w->edges = e;
+
+                               return;
+                       }
+               }
+               // lint -fallthrough
+               case 1:
+               {
+                       Vertex* v = originalVertices[start];
+                       v->edges = NULL;
+                       v->next = v;
+                       v->prev = v;
+
+                       result.minXy = v;
+                       result.maxXy = v;
+                       result.minYx = v;
+                       result.maxYx = v;
+
+                       return;
+               }
+       }
+
+       int split0 = start + n / 2;
+       Point32 p = originalVertices[split0 - 1]->point;
+       int split1 = split0;
+       while ((split1 < end) && (originalVertices[split1]->point == p))
+       {
+               split1++;
+       }
+       computeInternal(start, split0, result);
+       IntermediateHull hull1;
+       computeInternal(split1, end, hull1);
+#ifdef DEBUG_CONVEX_HULL
+       b3Printf("\n\nMerge\n");
+       result.print();
+       hull1.print();
+#endif
+       merge(result, hull1);
+#ifdef DEBUG_CONVEX_HULL
+       b3Printf("\n  Result\n");
+       result.print();
+#endif
+}
+
+#ifdef DEBUG_CONVEX_HULL
+void b3ConvexHullInternal::IntermediateHull::print()
+{
+       b3Printf("    Hull\n");
+       for (Vertex* v = minXy; v;)
+       {
+               b3Printf("      ");
+               v->print();
+               if (v == maxXy)
+               {
+                       b3Printf(" maxXy");
+               }
+               if (v == minYx)
+               {
+                       b3Printf(" minYx");
+               }
+               if (v == maxYx)
+               {
+                       b3Printf(" maxYx");
+               }
+               if (v->next->prev != v)
+               {
+                       b3Printf(" Inconsistency");
+               }
+               b3Printf("\n");
+               v = v->next;
+               if (v == minXy)
+               {
+                       break;
+               }
+       }
+       if (minXy)
+       {
+               minXy->copy = (minXy->copy == -1) ? -2 : -1;
+               minXy->printGraph();
+       }
+}
+
+void b3ConvexHullInternal::Vertex::printGraph()
+{
+       print();
+       b3Printf("\nEdges\n");
+       Edge* e = edges;
+       if (e)
+       {
+               do
+               {
+                       e->print();
+                       b3Printf("\n");
+                       e = e->next;
+               } while (e != edges);
+               do
+               {
+                       Vertex* v = e->target;
+                       if (v->copy != copy)
+                       {
+                               v->copy = copy;
+                               v->printGraph();
+                       }
+                       e = e->next;
+               } while (e != edges);
+       }
+}
+#endif
+
+b3ConvexHullInternal::Orientation b3ConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t)
+{
+       b3Assert(prev->reverse->target == next->reverse->target);
+       if (prev->next == next)
+       {
+               if (prev->prev == next)
+               {
+                       Point64 n = t.cross(s);
+                       Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target);
+                       b3Assert(!m.isZero());
+                       btInt64_t dot = n.dot(m);
+                       b3Assert(dot != 0);
+                       return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
+               }
+               return COUNTER_CLOCKWISE;
+       }
+       else if (prev->prev == next)
+       {
+               return CLOCKWISE;
+       }
+       else
+       {
+               return NONE;
+       }
+}
+
+b3ConvexHullInternal::Edge* b3ConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot)
+{
+       Edge* minEdge = NULL;
+
+#ifdef DEBUG_CONVEX_HULL
+       b3Printf("find max edge for %d\n", start->point.index);
+#endif
+       Edge* e = start->edges;
+       if (e)
+       {
+               do
+               {
+                       if (e->copy > mergeStamp)
+                       {
+                               Point32 t = *e->target - *start;
+                               Rational64 cot(t.dot(sxrxs), t.dot(rxs));
+#ifdef DEBUG_CONVEX_HULL
+                               b3Printf("      Angle is %f (%d) for ", (float)b3Atan(cot.toScalar()), (int)cot.isNaN());
+                               e->print();
+#endif
+                               if (cot.isNaN())
+                               {
+                                       b3Assert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0));
+                               }
+                               else
+                               {
+                                       int cmp;
+                                       if (minEdge == NULL)
+                                       {
+                                               minCot = cot;
+                                               minEdge = e;
+                                       }
+                                       else if ((cmp = cot.compare(minCot)) < 0)
+                                       {
+                                               minCot = cot;
+                                               minEdge = e;
+                                       }
+                                       else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE)))
+                                       {
+                                               minEdge = e;
+                                       }
+                               }
+#ifdef DEBUG_CONVEX_HULL
+                               b3Printf("\n");
+#endif
+                       }
+                       e = e->next;
+               } while (e != start->edges);
+       }
+       return minEdge;
+}
+
+void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1)
+{
+       Edge* start0 = e0;
+       Edge* start1 = e1;
+       Point32 et0 = start0 ? start0->target->point : c0->point;
+       Point32 et1 = start1 ? start1->target->point : c1->point;
+       Point32 s = c1->point - c0->point;
+       Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s);
+       btInt64_t dist = c0->point.dot(normal);
+       b3Assert(!start1 || (start1->target->point.dot(normal) == dist));
+       Point64 perp = s.cross(normal);
+       b3Assert(!perp.isZero());
+
+#ifdef DEBUG_CONVEX_HULL
+       b3Printf("   Advancing %d %d  (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
+#endif
+
+       btInt64_t maxDot0 = et0.dot(perp);
+       if (e0)
+       {
+               while (e0->target != stop0)
+               {
+                       Edge* e = e0->reverse->prev;
+                       if (e->target->point.dot(normal) < dist)
+                       {
+                               break;
+                       }
+                       b3Assert(e->target->point.dot(normal) == dist);
+                       if (e->copy == mergeStamp)
+                       {
+                               break;
+                       }
+                       btInt64_t dot = e->target->point.dot(perp);
+                       if (dot <= maxDot0)
+                       {
+                               break;
+                       }
+                       maxDot0 = dot;
+                       e0 = e;
+                       et0 = e->target->point;
+               }
+       }
+
+       btInt64_t maxDot1 = et1.dot(perp);
+       if (e1)
+       {
+               while (e1->target != stop1)
+               {
+                       Edge* e = e1->reverse->next;
+                       if (e->target->point.dot(normal) < dist)
+                       {
+                               break;
+                       }
+                       b3Assert(e->target->point.dot(normal) == dist);
+                       if (e->copy == mergeStamp)
+                       {
+                               break;
+                       }
+                       btInt64_t dot = e->target->point.dot(perp);
+                       if (dot <= maxDot1)
+                       {
+                               break;
+                       }
+                       maxDot1 = dot;
+                       e1 = e;
+                       et1 = e->target->point;
+               }
+       }
+
+#ifdef DEBUG_CONVEX_HULL
+       b3Printf("   Starting at %d %d\n", et0.index, et1.index);
+#endif
+
+       btInt64_t dx = maxDot1 - maxDot0;
+       if (dx > 0)
+       {
+               while (true)
+               {
+                       btInt64_t dy = (et1 - et0).dot(s);
+
+                       if (e0 && (e0->target != stop0))
+                       {
+                               Edge* f0 = e0->next->reverse;
+                               if (f0->copy > mergeStamp)
+                               {
+                                       btInt64_t dx0 = (f0->target->point - et0).dot(perp);
+                                       btInt64_t dy0 = (f0->target->point - et0).dot(s);
+                                       if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0)))
+                                       {
+                                               et0 = f0->target->point;
+                                               dx = (et1 - et0).dot(perp);
+                                               e0 = (e0 == start0) ? NULL : f0;
+                                               continue;
+                                       }
+                               }
+                       }
+
+                       if (e1 && (e1->target != stop1))
+                       {
+                               Edge* f1 = e1->reverse->next;
+                               if (f1->copy > mergeStamp)
+                               {
+                                       Point32 d1 = f1->target->point - et1;
+                                       if (d1.dot(normal) == 0)
+                                       {
+                                               btInt64_t dx1 = d1.dot(perp);
+                                               btInt64_t dy1 = d1.dot(s);
+                                               btInt64_t dxn = (f1->target->point - et0).dot(perp);
+                                               if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0))))
+                                               {
+                                                       e1 = f1;
+                                                       et1 = e1->target->point;
+                                                       dx = dxn;
+                                                       continue;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               b3Assert((e1 == start1) && (d1.dot(normal) < 0));
+                                       }
+                               }
+                       }
+
+                       break;
+               }
+       }
+       else if (dx < 0)
+       {
+               while (true)
+               {
+                       btInt64_t dy = (et1 - et0).dot(s);
+
+                       if (e1 && (e1->target != stop1))
+                       {
+                               Edge* f1 = e1->prev->reverse;
+                               if (f1->copy > mergeStamp)
+                               {
+                                       btInt64_t dx1 = (f1->target->point - et1).dot(perp);
+                                       btInt64_t dy1 = (f1->target->point - et1).dot(s);
+                                       if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0)))
+                                       {
+                                               et1 = f1->target->point;
+                                               dx = (et1 - et0).dot(perp);
+                                               e1 = (e1 == start1) ? NULL : f1;
+                                               continue;
+                                       }
+                               }
+                       }
+
+                       if (e0 && (e0->target != stop0))
+                       {
+                               Edge* f0 = e0->reverse->prev;
+                               if (f0->copy > mergeStamp)
+                               {
+                                       Point32 d0 = f0->target->point - et0;
+                                       if (d0.dot(normal) == 0)
+                                       {
+                                               btInt64_t dx0 = d0.dot(perp);
+                                               btInt64_t dy0 = d0.dot(s);
+                                               btInt64_t dxn = (et1 - f0->target->point).dot(perp);
+                                               if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0))))
+                                               {
+                                                       e0 = f0;
+                                                       et0 = e0->target->point;
+                                                       dx = dxn;
+                                                       continue;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               b3Assert((e0 == start0) && (d0.dot(normal) < 0));
+                                       }
+                               }
+                       }
+
+                       break;
+               }
+       }
+#ifdef DEBUG_CONVEX_HULL
+       b3Printf("   Advanced edges to %d %d\n", et0.index, et1.index);
+#endif
+}
+
+void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
+{
+       if (!h1.maxXy)
+       {
+               return;
+       }
+       if (!h0.maxXy)
+       {
+               h0 = h1;
+               return;
+       }
+
+       mergeStamp--;
+
+       Vertex* c0 = NULL;
+       Edge* toPrev0 = NULL;
+       Edge* firstNew0 = NULL;
+       Edge* pendingHead0 = NULL;
+       Edge* pendingTail0 = NULL;
+       Vertex* c1 = NULL;
+       Edge* toPrev1 = NULL;
+       Edge* firstNew1 = NULL;
+       Edge* pendingHead1 = NULL;
+       Edge* pendingTail1 = NULL;
+       Point32 prevPoint;
+
+       if (mergeProjection(h0, h1, c0, c1))
+       {
+               Point32 s = *c1 - *c0;
+               Point64 normal = Point32(0, 0, -1).cross(s);
+               Point64 t = s.cross(normal);
+               b3Assert(!t.isZero());
+
+               Edge* e = c0->edges;
+               Edge* start0 = NULL;
+               if (e)
+               {
+                       do
+                       {
+                               btInt64_t dot = (*e->target - *c0).dot(normal);
+                               b3Assert(dot <= 0);
+                               if ((dot == 0) && ((*e->target - *c0).dot(t) > 0))
+                               {
+                                       if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE))
+                                       {
+                                               start0 = e;
+                                       }
+                               }
+                               e = e->next;
+                       } while (e != c0->edges);
+               }
+
+               e = c1->edges;
+               Edge* start1 = NULL;
+               if (e)
+               {
+                       do
+                       {
+                               btInt64_t dot = (*e->target - *c1).dot(normal);
+                               b3Assert(dot <= 0);
+                               if ((dot == 0) && ((*e->target - *c1).dot(t) > 0))
+                               {
+                                       if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE))
+                                       {
+                                               start1 = e;
+                                       }
+                               }
+                               e = e->next;
+                       } while (e != c1->edges);
+               }
+
+               if (start0 || start1)
+               {
+                       findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL);
+                       if (start0)
+                       {
+                               c0 = start0->target;
+                       }
+                       if (start1)
+                       {
+                               c1 = start1->target;
+                       }
+               }
+
+               prevPoint = c1->point;
+               prevPoint.z++;
+       }
+       else
+       {
+               prevPoint = c1->point;
+               prevPoint.x++;
+       }
+
+       Vertex* first0 = c0;
+       Vertex* first1 = c1;
+       bool firstRun = true;
+
+       while (true)
+       {
+               Point32 s = *c1 - *c0;
+               Point32 r = prevPoint - c0->point;
+               Point64 rxs = r.cross(s);
+               Point64 sxrxs = s.cross(rxs);
+
+#ifdef DEBUG_CONVEX_HULL
+               b3Printf("\n  Checking %d %d\n", c0->point.index, c1->point.index);
+#endif
+               Rational64 minCot0(0, 0);
+               Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0);
+               Rational64 minCot1(0, 0);
+               Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1);
+               if (!min0 && !min1)
+               {
+                       Edge* e = newEdgePair(c0, c1);
+                       e->link(e);
+                       c0->edges = e;
+
+                       e = e->reverse;
+                       e->link(e);
+                       c1->edges = e;
+                       return;
+               }
+               else
+               {
+                       int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1);
+#ifdef DEBUG_CONVEX_HULL
+                       b3Printf("    -> Result %d\n", cmp);
+#endif
+                       if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity()))
+                       {
+                               Edge* e = newEdgePair(c0, c1);
+                               if (pendingTail0)
+                               {
+                                       pendingTail0->prev = e;
+                               }
+                               else
+                               {
+                                       pendingHead0 = e;
+                               }
+                               e->next = pendingTail0;
+                               pendingTail0 = e;
+
+                               e = e->reverse;
+                               if (pendingTail1)
+                               {
+                                       pendingTail1->next = e;
+                               }
+                               else
+                               {
+                                       pendingHead1 = e;
+                               }
+                               e->prev = pendingTail1;
+                               pendingTail1 = e;
+                       }
+
+                       Edge* e0 = min0;
+                       Edge* e1 = min1;
+
+#ifdef DEBUG_CONVEX_HULL
+                       b3Printf("   Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
+#endif
+
+                       if (cmp == 0)
+                       {
+                               findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL);
+                       }
+
+                       if ((cmp >= 0) && e1)
+                       {
+                               if (toPrev1)
+                               {
+                                       for (Edge *e = toPrev1->next, *n = NULL; e != min1; e = n)
+                                       {
+                                               n = e->next;
+                                               removeEdgePair(e);
+                                       }
+                               }
+
+                               if (pendingTail1)
+                               {
+                                       if (toPrev1)
+                                       {
+                                               toPrev1->link(pendingHead1);
+                                       }
+                                       else
+                                       {
+                                               min1->prev->link(pendingHead1);
+                                               firstNew1 = pendingHead1;
+                                       }
+                                       pendingTail1->link(min1);
+                                       pendingHead1 = NULL;
+                                       pendingTail1 = NULL;
+                               }
+                               else if (!toPrev1)
+                               {
+                                       firstNew1 = min1;
+                               }
+
+                               prevPoint = c1->point;
+                               c1 = e1->target;
+                               toPrev1 = e1->reverse;
+                       }
+
+                       if ((cmp <= 0) && e0)
+                       {
+                               if (toPrev0)
+                               {
+                                       for (Edge *e = toPrev0->prev, *n = NULL; e != min0; e = n)
+                                       {
+                                               n = e->prev;
+                                               removeEdgePair(e);
+                                       }
+                               }
+
+                               if (pendingTail0)
+                               {
+                                       if (toPrev0)
+                                       {
+                                               pendingHead0->link(toPrev0);
+                                       }
+                                       else
+                                       {
+                                               pendingHead0->link(min0->next);
+                                               firstNew0 = pendingHead0;
+                                       }
+                                       min0->link(pendingTail0);
+                                       pendingHead0 = NULL;
+                                       pendingTail0 = NULL;
+                               }
+                               else if (!toPrev0)
+                               {
+                                       firstNew0 = min0;
+                               }
+
+                               prevPoint = c0->point;
+                               c0 = e0->target;
+                               toPrev0 = e0->reverse;
+                       }
+               }
+
+               if ((c0 == first0) && (c1 == first1))
+               {
+                       if (toPrev0 == NULL)
+                       {
+                               pendingHead0->link(pendingTail0);
+                               c0->edges = pendingTail0;
+                       }
+                       else
+                       {
+                               for (Edge *e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
+                               {
+                                       n = e->prev;
+                                       removeEdgePair(e);
+                               }
+                               if (pendingTail0)
+                               {
+                                       pendingHead0->link(toPrev0);
+                                       firstNew0->link(pendingTail0);
+                               }
+                       }
+
+                       if (toPrev1 == NULL)
+                       {
+                               pendingTail1->link(pendingHead1);
+                               c1->edges = pendingTail1;
+                       }
+                       else
+                       {
+                               for (Edge *e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
+                               {
+                                       n = e->next;
+                                       removeEdgePair(e);
+                               }
+                               if (pendingTail1)
+                               {
+                                       toPrev1->link(pendingHead1);
+                                       pendingTail1->link(firstNew1);
+                               }
+                       }
+
+                       return;
+               }
+
+               firstRun = false;
+       }
+}
+
+static bool b3PointCmp(const b3ConvexHullInternal::Point32& p, const b3ConvexHullInternal::Point32& q)
+{
+       return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
+}
+
+void b3ConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
+{
+       b3Vector3 min = b3MakeVector3(b3Scalar(1e30), b3Scalar(1e30), b3Scalar(1e30)), max = b3MakeVector3(b3Scalar(-1e30), b3Scalar(-1e30), b3Scalar(-1e30));
+       const char* ptr = (const char*)coords;
+       if (doubleCoords)
+       {
+               for (int i = 0; i < count; i++)
+               {
+                       const double* v = (const double*)ptr;
+                       b3Vector3 p = b3MakeVector3((b3Scalar)v[0], (b3Scalar)v[1], (b3Scalar)v[2]);
+                       ptr += stride;
+                       min.setMin(p);
+                       max.setMax(p);
+               }
+       }
+       else
+       {
+               for (int i = 0; i < count; i++)
+               {
+                       const float* v = (const float*)ptr;
+                       b3Vector3 p = b3MakeVector3(v[0], v[1], v[2]);
+                       ptr += stride;
+                       min.setMin(p);
+                       max.setMax(p);
+               }
+       }
+
+       b3Vector3 s = max - min;
+       maxAxis = s.maxAxis();
+       minAxis = s.minAxis();
+       if (minAxis == maxAxis)
+       {
+               minAxis = (maxAxis + 1) % 3;
+       }
+       medAxis = 3 - maxAxis - minAxis;
+
+       s /= b3Scalar(10216);
+       if (((medAxis + 1) % 3) != maxAxis)
+       {
+               s *= -1;
+       }
+       scaling = s;
+
+       if (s[0] != 0)
+       {
+               s[0] = b3Scalar(1) / s[0];
+       }
+       if (s[1] != 0)
+       {
+               s[1] = b3Scalar(1) / s[1];
+       }
+       if (s[2] != 0)
+       {
+               s[2] = b3Scalar(1) / s[2];
+       }
+
+       center = (min + max) * b3Scalar(0.5);
+
+       b3AlignedObjectArray<Point32> points;
+       points.resize(count);
+       ptr = (const char*)coords;
+       if (doubleCoords)
+       {
+               for (int i = 0; i < count; i++)
+               {
+                       const double* v = (const double*)ptr;
+                       b3Vector3 p = b3MakeVector3((b3Scalar)v[0], (b3Scalar)v[1], (b3Scalar)v[2]);
+                       ptr += stride;
+                       p = (p - center) * s;
+                       points[i].x = (btInt32_t)p[medAxis];
+                       points[i].y = (btInt32_t)p[maxAxis];
+                       points[i].z = (btInt32_t)p[minAxis];
+                       points[i].index = i;
+               }
+       }
+       else
+       {
+               for (int i = 0; i < count; i++)
+               {
+                       const float* v = (const float*)ptr;
+                       b3Vector3 p = b3MakeVector3(v[0], v[1], v[2]);
+                       ptr += stride;
+                       p = (p - center) * s;
+                       points[i].x = (btInt32_t)p[medAxis];
+                       points[i].y = (btInt32_t)p[maxAxis];
+                       points[i].z = (btInt32_t)p[minAxis];
+                       points[i].index = i;
+               }
+       }
+       points.quickSort(b3PointCmp);
+
+       vertexPool.reset();
+       vertexPool.setArraySize(count);
+       originalVertices.resize(count);
+       for (int i = 0; i < count; i++)
+       {
+               Vertex* v = vertexPool.newObject();
+               v->edges = NULL;
+               v->point = points[i];
+               v->copy = -1;
+               originalVertices[i] = v;
+       }
+
+       points.clear();
+
+       edgePool.reset();
+       edgePool.setArraySize(6 * count);
+
+       usedEdgePairs = 0;
+       maxUsedEdgePairs = 0;
+
+       mergeStamp = -3;
+
+       IntermediateHull hull;
+       computeInternal(0, count, hull);
+       vertexList = hull.minXy;
+#ifdef DEBUG_CONVEX_HULL
+       b3Printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count);
+#endif
+}
+
+b3Vector3 b3ConvexHullInternal::toBtVector(const Point32& v)
+{
+       b3Vector3 p;
+       p[medAxis] = b3Scalar(v.x);
+       p[maxAxis] = b3Scalar(v.y);
+       p[minAxis] = b3Scalar(v.z);
+       return p * scaling;
+}
+
+b3Vector3 b3ConvexHullInternal::getBtNormal(Face* face)
+{
+       return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized();
+}
+
+b3Vector3 b3ConvexHullInternal::getCoordinates(const Vertex* v)
+{
+       b3Vector3 p;
+       p[medAxis] = v->xvalue();
+       p[maxAxis] = v->yvalue();
+       p[minAxis] = v->zvalue();
+       return p * scaling + center;
+}
+
+b3Scalar b3ConvexHullInternal::shrink(b3Scalar amount, b3Scalar clampAmount)
+{
+       if (!vertexList)
+       {
+               return 0;
+       }
+       int stamp = --mergeStamp;
+       b3AlignedObjectArray<Vertex*> stack;
+       vertexList->copy = stamp;
+       stack.push_back(vertexList);
+       b3AlignedObjectArray<Face*> faces;
+
+       Point32 ref = vertexList->point;
+       Int128 hullCenterX(0, 0);
+       Int128 hullCenterY(0, 0);
+       Int128 hullCenterZ(0, 0);
+       Int128 volume(0, 0);
+
+       while (stack.size() > 0)
+       {
+               Vertex* v = stack[stack.size() - 1];
+               stack.pop_back();
+               Edge* e = v->edges;
+               if (e)
+               {
+                       do
+                       {
+                               if (e->target->copy != stamp)
+                               {
+                                       e->target->copy = stamp;
+                                       stack.push_back(e->target);
+                               }
+                               if (e->copy != stamp)
+                               {
+                                       Face* face = facePool.newObject();
+                                       face->init(e->target, e->reverse->prev->target, v);
+                                       faces.push_back(face);
+                                       Edge* f = e;
+
+                                       Vertex* a = NULL;
+                                       Vertex* b = NULL;
+                                       do
+                                       {
+                                               if (a && b)
+                                               {
+                                                       btInt64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
+                                                       b3Assert(vol >= 0);
+                                                       Point32 c = v->point + a->point + b->point + ref;
+                                                       hullCenterX += vol * c.x;
+                                                       hullCenterY += vol * c.y;
+                                                       hullCenterZ += vol * c.z;
+                                                       volume += vol;
+                                               }
+
+                                               b3Assert(f->copy != stamp);
+                                               f->copy = stamp;
+                                               f->face = face;
+
+                                               a = b;
+                                               b = f->target;
+
+                                               f = f->reverse->prev;
+                                       } while (f != e);
+                               }
+                               e = e->next;
+                       } while (e != v->edges);
+               }
+       }
+
+       if (volume.getSign() <= 0)
+       {
+               return 0;
+       }
+
+       b3Vector3 hullCenter;
+       hullCenter[medAxis] = hullCenterX.toScalar();
+       hullCenter[maxAxis] = hullCenterY.toScalar();
+       hullCenter[minAxis] = hullCenterZ.toScalar();
+       hullCenter /= 4 * volume.toScalar();
+       hullCenter *= scaling;
+
+       int faceCount = faces.size();
+
+       if (clampAmount > 0)
+       {
+               b3Scalar minDist = B3_INFINITY;
+               for (int i = 0; i < faceCount; i++)
+               {
+                       b3Vector3 normal = getBtNormal(faces[i]);
+                       b3Scalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter);
+                       if (dist < minDist)
+                       {
+                               minDist = dist;
+                       }
+               }
+
+               if (minDist <= 0)
+               {
+                       return 0;
+               }
+
+               amount = b3Min(amount, minDist * clampAmount);
+       }
+
+       unsigned int seed = 243703;
+       for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223)
+       {
+               b3Swap(faces[i], faces[seed % faceCount]);
+       }
+
+       for (int i = 0; i < faceCount; i++)
+       {
+               if (!shiftFace(faces[i], amount, stack))
+               {
+                       return -amount;
+               }
+       }
+
+       return amount;
+}
+
+bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjectArray<Vertex*> stack)
+{
+       b3Vector3 origShift = getBtNormal(face) * -amount;
+       if (scaling[0] != 0)
+       {
+               origShift[0] /= scaling[0];
+       }
+       if (scaling[1] != 0)
+       {
+               origShift[1] /= scaling[1];
+       }
+       if (scaling[2] != 0)
+       {
+               origShift[2] /= scaling[2];
+       }
+       Point32 shift((btInt32_t)origShift[medAxis], (btInt32_t)origShift[maxAxis], (btInt32_t)origShift[minAxis]);
+       if (shift.isZero())
+       {
+               return true;
+       }
+       Point64 normal = face->getNormal();
+#ifdef DEBUG_CONVEX_HULL
+       b3Printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
+                        face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
+#endif
+       btInt64_t origDot = face->origin.dot(normal);
+       Point32 shiftedOrigin = face->origin + shift;
+       btInt64_t shiftedDot = shiftedOrigin.dot(normal);
+       b3Assert(shiftedDot <= origDot);
+       if (shiftedDot >= origDot)
+       {
+               return false;
+       }
+
+       Edge* intersection = NULL;
+
+       Edge* startEdge = face->nearbyVertex->edges;
+#ifdef DEBUG_CONVEX_HULL
+       b3Printf("Start edge is ");
+       startEdge->print();
+       b3Printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot);
+#endif
+       Rational128 optDot = face->nearbyVertex->dot(normal);
+       int cmp = optDot.compare(shiftedDot);
+#ifdef SHOW_ITERATIONS
+       int n = 0;
+#endif
+       if (cmp >= 0)
+       {
+               Edge* e = startEdge;
+               do
+               {
+#ifdef SHOW_ITERATIONS
+                       n++;
+#endif
+                       Rational128 dot = e->target->dot(normal);
+                       b3Assert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+                       b3Printf("Moving downwards, edge is ");
+                       e->print();
+                       b3Printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
+#endif
+                       if (dot.compare(optDot) < 0)
+                       {
+                               int c = dot.compare(shiftedDot);
+                               optDot = dot;
+                               e = e->reverse;
+                               startEdge = e;
+                               if (c < 0)
+                               {
+                                       intersection = e;
+                                       break;
+                               }
+                               cmp = c;
+                       }
+                       e = e->prev;
+               } while (e != startEdge);
+
+               if (!intersection)
+               {
+                       return false;
+               }
+       }
+       else
+       {
+               Edge* e = startEdge;
+               do
+               {
+#ifdef SHOW_ITERATIONS
+                       n++;
+#endif
+                       Rational128 dot = e->target->dot(normal);
+                       b3Assert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+                       b3Printf("Moving upwards, edge is ");
+                       e->print();
+                       b3Printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
+#endif
+                       if (dot.compare(optDot) > 0)
+                       {
+                               cmp = dot.compare(shiftedDot);
+                               if (cmp >= 0)
+                               {
+                                       intersection = e;
+                                       break;
+                               }
+                               optDot = dot;
+                               e = e->reverse;
+                               startEdge = e;
+                       }
+                       e = e->prev;
+               } while (e != startEdge);
+
+               if (!intersection)
+               {
+                       return true;
+               }
+       }
+
+#ifdef SHOW_ITERATIONS
+       b3Printf("Needed %d iterations to find initial intersection\n", n);
+#endif
+
+       if (cmp == 0)
+       {
+               Edge* e = intersection->reverse->next;
+#ifdef SHOW_ITERATIONS
+               n = 0;
+#endif
+               while (e->target->dot(normal).compare(shiftedDot) <= 0)
+               {
+#ifdef SHOW_ITERATIONS
+                       n++;
+#endif
+                       e = e->next;
+                       if (e == intersection->reverse)
+                       {
+                               return true;
+                       }
+#ifdef DEBUG_CONVEX_HULL
+                       b3Printf("Checking for outwards edge, current edge is ");
+                       e->print();
+                       b3Printf("\n");
+#endif
+               }
+#ifdef SHOW_ITERATIONS
+               b3Printf("Needed %d iterations to check for complete containment\n", n);
+#endif
+       }
+
+       Edge* firstIntersection = NULL;
+       Edge* faceEdge = NULL;
+       Edge* firstFaceEdge = NULL;
+
+#ifdef SHOW_ITERATIONS
+       int m = 0;
+#endif
+       while (true)
+       {
+#ifdef SHOW_ITERATIONS
+               m++;
+#endif
+#ifdef DEBUG_CONVEX_HULL
+               b3Printf("Intersecting edge is ");
+               intersection->print();
+               b3Printf("\n");
+#endif
+               if (cmp == 0)
+               {
+                       Edge* e = intersection->reverse->next;
+                       startEdge = e;
+#ifdef SHOW_ITERATIONS
+                       n = 0;
+#endif
+                       while (true)
+                       {
+#ifdef SHOW_ITERATIONS
+                               n++;
+#endif
+                               if (e->target->dot(normal).compare(shiftedDot) >= 0)
+                               {
+                                       break;
+                               }
+                               intersection = e->reverse;
+                               e = e->next;
+                               if (e == startEdge)
+                               {
+                                       return true;
+                               }
+                       }
+#ifdef SHOW_ITERATIONS
+                       b3Printf("Needed %d iterations to advance intersection\n", n);
+#endif
+               }
+
+#ifdef DEBUG_CONVEX_HULL
+               b3Printf("Advanced intersecting edge to ");
+               intersection->print();
+               b3Printf(", cmp = %d\n", cmp);
+#endif
+
+               if (!firstIntersection)
+               {
+                       firstIntersection = intersection;
+               }
+               else if (intersection == firstIntersection)
+               {
+                       break;
+               }
+
+               int prevCmp = cmp;
+               Edge* prevIntersection = intersection;
+               Edge* prevFaceEdge = faceEdge;
+
+               Edge* e = intersection->reverse;
+#ifdef SHOW_ITERATIONS
+               n = 0;
+#endif
+               while (true)
+               {
+#ifdef SHOW_ITERATIONS
+                       n++;
+#endif
+                       e = e->reverse->prev;
+                       b3Assert(e != intersection->reverse);
+                       cmp = e->target->dot(normal).compare(shiftedDot);
+#ifdef DEBUG_CONVEX_HULL
+                       b3Printf("Testing edge ");
+                       e->print();
+                       b3Printf(" -> cmp = %d\n", cmp);
+#endif
+                       if (cmp >= 0)
+                       {
+                               intersection = e;
+                               break;
+                       }
+               }
+#ifdef SHOW_ITERATIONS
+               b3Printf("Needed %d iterations to find other intersection of face\n", n);
+#endif
+
+               if (cmp > 0)
+               {
+                       Vertex* removed = intersection->target;
+                       e = intersection->reverse;
+                       if (e->prev == e)
+                       {
+                               removed->edges = NULL;
+                       }
+                       else
+                       {
+                               removed->edges = e->prev;
+                               e->prev->link(e->next);
+                               e->link(e);
+                       }
+#ifdef DEBUG_CONVEX_HULL
+                       b3Printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+
+                       Point64 n0 = intersection->face->getNormal();
+                       Point64 n1 = intersection->reverse->face->getNormal();
+                       btInt64_t m00 = face->dir0.dot(n0);
+                       btInt64_t m01 = face->dir1.dot(n0);
+                       btInt64_t m10 = face->dir0.dot(n1);
+                       btInt64_t m11 = face->dir1.dot(n1);
+                       btInt64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0);
+                       btInt64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1);
+                       Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
+                       b3Assert(det.getSign() != 0);
+                       Vertex* v = vertexPool.newObject();
+                       v->point.index = -1;
+                       v->copy = -1;
+                       v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
+                                                                       Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
+                                                                       Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
+                                                                       det);
+                       v->point.x = (btInt32_t)v->point128.xvalue();
+                       v->point.y = (btInt32_t)v->point128.yvalue();
+                       v->point.z = (btInt32_t)v->point128.zvalue();
+                       intersection->target = v;
+                       v->edges = e;
+
+                       stack.push_back(v);
+                       stack.push_back(removed);
+                       stack.push_back(NULL);
+               }
+
+               if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target))
+               {
+                       faceEdge = newEdgePair(prevIntersection->target, intersection->target);
+                       if (prevCmp == 0)
+                       {
+                               faceEdge->link(prevIntersection->reverse->next);
+                       }
+                       if ((prevCmp == 0) || prevFaceEdge)
+                       {
+                               prevIntersection->reverse->link(faceEdge);
+                       }
+                       if (cmp == 0)
+                       {
+                               intersection->reverse->prev->link(faceEdge->reverse);
+                       }
+                       faceEdge->reverse->link(intersection->reverse);
+               }
+               else
+               {
+                       faceEdge = prevIntersection->reverse->next;
+               }
+
+               if (prevFaceEdge)
+               {
+                       if (prevCmp > 0)
+                       {
+                               faceEdge->link(prevFaceEdge->reverse);
+                       }
+                       else if (faceEdge != prevFaceEdge->reverse)
+                       {
+                               stack.push_back(prevFaceEdge->target);
+                               while (faceEdge->next != prevFaceEdge->reverse)
+                               {
+                                       Vertex* removed = faceEdge->next->target;
+                                       removeEdgePair(faceEdge->next);
+                                       stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+                                       b3Printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+                               }
+                               stack.push_back(NULL);
+                       }
+               }
+               faceEdge->face = face;
+               faceEdge->reverse->face = intersection->face;
+
+               if (!firstFaceEdge)
+               {
+                       firstFaceEdge = faceEdge;
+               }
+       }
+#ifdef SHOW_ITERATIONS
+       b3Printf("Needed %d iterations to process all intersections\n", m);
+#endif
+
+       if (cmp > 0)
+       {
+               firstFaceEdge->reverse->target = faceEdge->target;
+               firstIntersection->reverse->link(firstFaceEdge);
+               firstFaceEdge->link(faceEdge->reverse);
+       }
+       else if (firstFaceEdge != faceEdge->reverse)
+       {
+               stack.push_back(faceEdge->target);
+               while (firstFaceEdge->next != faceEdge->reverse)
+               {
+                       Vertex* removed = firstFaceEdge->next->target;
+                       removeEdgePair(firstFaceEdge->next);
+                       stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+                       b3Printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+               }
+               stack.push_back(NULL);
+       }
+
+       b3Assert(stack.size() > 0);
+       vertexList = stack[0];
+
+#ifdef DEBUG_CONVEX_HULL
+       b3Printf("Removing part\n");
+#endif
+#ifdef SHOW_ITERATIONS
+       n = 0;
+#endif
+       int pos = 0;
+       while (pos < stack.size())
+       {
+               int end = stack.size();
+               while (pos < end)
+               {
+                       Vertex* kept = stack[pos++];
+#ifdef DEBUG_CONVEX_HULL
+                       kept->print();
+#endif
+                       bool deeper = false;
+                       Vertex* removed;
+                       while ((removed = stack[pos++]) != NULL)
+                       {
+#ifdef SHOW_ITERATIONS
+                               n++;
+#endif
+                               kept->receiveNearbyFaces(removed);
+                               while (removed->edges)
+                               {
+                                       if (!deeper)
+                                       {
+                                               deeper = true;
+                                               stack.push_back(kept);
+                                       }
+                                       stack.push_back(removed->edges->target);
+                                       removeEdgePair(removed->edges);
+                               }
+                       }
+                       if (deeper)
+                       {
+                               stack.push_back(NULL);
+                       }
+               }
+       }
+#ifdef SHOW_ITERATIONS
+       b3Printf("Needed %d iterations to remove part\n", n);
+#endif
+
+       stack.resize(0);
+       face->origin = shiftedOrigin;
+
+       return true;
+}
+
+static int getVertexCopy(b3ConvexHullInternal::Vertex* vertex, b3AlignedObjectArray<b3ConvexHullInternal::Vertex*>& vertices)
+{
+       int index = vertex->copy;
+       if (index < 0)
+       {
+               index = vertices.size();
+               vertex->copy = index;
+               vertices.push_back(vertex);
+#ifdef DEBUG_CONVEX_HULL
+               b3Printf("Vertex %d gets index *%d\n", vertex->point.index, index);
+#endif
+       }
+       return index;
+}
+
+b3Scalar b3ConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
+{
+       if (count <= 0)
+       {
+               vertices.clear();
+               edges.clear();
+               faces.clear();
+               return 0;
+       }
+
+       b3ConvexHullInternal hull;
+       hull.compute(coords, doubleCoords, stride, count);
+
+       b3Scalar shift = 0;
+       if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0))
+       {
+               vertices.clear();
+               edges.clear();
+               faces.clear();
+               return shift;
+       }
+
+       vertices.resize(0);
+       edges.resize(0);
+       faces.resize(0);
+
+       b3AlignedObjectArray<b3ConvexHullInternal::Vertex*> oldVertices;
+       getVertexCopy(hull.vertexList, oldVertices);
+       int copied = 0;
+       while (copied < oldVertices.size())
+       {
+               b3ConvexHullInternal::Vertex* v = oldVertices[copied];
+               vertices.push_back(hull.getCoordinates(v));
+               b3ConvexHullInternal::Edge* firstEdge = v->edges;
+               if (firstEdge)
+               {
+                       int firstCopy = -1;
+                       int prevCopy = -1;
+                       b3ConvexHullInternal::Edge* e = firstEdge;
+                       do
+                       {
+                               if (e->copy < 0)
+                               {
+                                       int s = edges.size();
+                                       edges.push_back(Edge());
+                                       edges.push_back(Edge());
+                                       Edge* c = &edges[s];
+                                       Edge* r = &edges[s + 1];
+                                       e->copy = s;
+                                       e->reverse->copy = s + 1;
+                                       c->reverse = 1;
+                                       r->reverse = -1;
+                                       c->targetVertex = getVertexCopy(e->target, oldVertices);
+                                       r->targetVertex = copied;
+#ifdef DEBUG_CONVEX_HULL
+                                       b3Printf("      CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex());
+#endif
+                               }
+                               if (prevCopy >= 0)
+                               {
+                                       edges[e->copy].next = prevCopy - e->copy;
+                               }
+                               else
+                               {
+                                       firstCopy = e->copy;
+                               }
+                               prevCopy = e->copy;
+                               e = e->next;
+                       } while (e != firstEdge);
+                       edges[firstCopy].next = prevCopy - firstCopy;
+               }
+               copied++;
+       }
+
+       for (int i = 0; i < copied; i++)
+       {
+               b3ConvexHullInternal::Vertex* v = oldVertices[i];
+               b3ConvexHullInternal::Edge* firstEdge = v->edges;
+               if (firstEdge)
+               {
+                       b3ConvexHullInternal::Edge* e = firstEdge;
+                       do
+                       {
+                               if (e->copy >= 0)
+                               {
+#ifdef DEBUG_CONVEX_HULL
+                                       b3Printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex());
+#endif
+                                       faces.push_back(e->copy);
+                                       b3ConvexHullInternal::Edge* f = e;
+                                       do
+                                       {
+#ifdef DEBUG_CONVEX_HULL
+                                               b3Printf("   Face *%d\n", edges[f->copy].getTargetVertex());
+#endif
+                                               f->copy = -1;
+                                               f = f->reverse->prev;
+                                       } while (f != e);
+                               }
+                               e = e->next;
+                       } while (e != firstEdge);
+               }
+       }
+
+       return shift;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3ConvexHullComputer.h b/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3ConvexHullComputer.h
new file mode 100644 (file)
index 0000000..8852c5a
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_CONVEX_HULL_COMPUTER_H
+#define B3_CONVEX_HULL_COMPUTER_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+/// Convex hull implementation based on Preparata and Hong
+/// See http://code.google.com/p/bullet/issues/detail?id=275
+/// Ole Kniemeyer, MAXON Computer GmbH
+class b3ConvexHullComputer
+{
+private:
+       b3Scalar compute(const void* coords, bool doubleCoords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp);
+
+public:
+       class Edge
+       {
+       private:
+               int next;
+               int reverse;
+               int targetVertex;
+
+               friend class b3ConvexHullComputer;
+
+       public:
+               int getSourceVertex() const
+               {
+                       return (this + reverse)->targetVertex;
+               }
+
+               int getTargetVertex() const
+               {
+                       return targetVertex;
+               }
+
+               const Edge* getNextEdgeOfVertex() const  // clockwise list of all edges of a vertex
+               {
+                       return this + next;
+               }
+
+               const Edge* getNextEdgeOfFace() const  // counter-clockwise list of all edges of a face
+               {
+                       return (this + reverse)->getNextEdgeOfVertex();
+               }
+
+               const Edge* getReverseEdge() const
+               {
+                       return this + reverse;
+               }
+       };
+
+       // Vertices of the output hull
+       b3AlignedObjectArray<b3Vector3> vertices;
+
+       // Edges of the output hull
+       b3AlignedObjectArray<Edge> edges;
+
+       // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
+       b3AlignedObjectArray<int> faces;
+
+       /*
+               Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
+               between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
+               by that amount (each face is moved by "shrink" length units towards the center along its normal).
+               If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius"
+               is the minimum distance of a face to the center of the convex hull.
+
+               The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large
+               that the resulting convex hull is empty.
+
+               The output convex hull can be found in the member variables "vertices", "edges", "faces".
+               */
+       b3Scalar compute(const float* coords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
+       {
+               return compute(coords, false, stride, count, shrink, shrinkClamp);
+       }
+
+       // same as above, but double precision
+       b3Scalar compute(const double* coords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
+       {
+               return compute(coords, true, stride, count, shrink, shrinkClamp);
+       }
+};
+
+#endif  //B3_CONVEX_HULL_COMPUTER_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3GeometryUtil.cpp b/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3GeometryUtil.cpp
new file mode 100644 (file)
index 0000000..1c5d5a7
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3GeometryUtil.h"
+
+/*
+  Make sure this dummy function never changes so that it
+  can be used by probes that are checking whether the
+  library is actually installed.
+*/
+extern "C"
+{
+       void b3BulletMathProbe();
+
+       void b3BulletMathProbe() {}
+}
+
+bool b3GeometryUtil::isPointInsidePlanes(const b3AlignedObjectArray<b3Vector3>& planeEquations, const b3Vector3& point, b3Scalar margin)
+{
+       int numbrushes = planeEquations.size();
+       for (int i = 0; i < numbrushes; i++)
+       {
+               const b3Vector3& N1 = planeEquations[i];
+               b3Scalar dist = b3Scalar(N1.dot(point)) + b3Scalar(N1[3]) - margin;
+               if (dist > b3Scalar(0.))
+               {
+                       return false;
+               }
+       }
+       return true;
+}
+
+bool b3GeometryUtil::areVerticesBehindPlane(const b3Vector3& planeNormal, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar margin)
+{
+       int numvertices = vertices.size();
+       for (int i = 0; i < numvertices; i++)
+       {
+               const b3Vector3& N1 = vertices[i];
+               b3Scalar dist = b3Scalar(planeNormal.dot(N1)) + b3Scalar(planeNormal[3]) - margin;
+               if (dist > b3Scalar(0.))
+               {
+                       return false;
+               }
+       }
+       return true;
+}
+
+bool notExist(const b3Vector3& planeEquation, const b3AlignedObjectArray<b3Vector3>& planeEquations);
+
+bool notExist(const b3Vector3& planeEquation, const b3AlignedObjectArray<b3Vector3>& planeEquations)
+{
+       int numbrushes = planeEquations.size();
+       for (int i = 0; i < numbrushes; i++)
+       {
+               const b3Vector3& N1 = planeEquations[i];
+               if (planeEquation.dot(N1) > b3Scalar(0.999))
+               {
+                       return false;
+               }
+       }
+       return true;
+}
+
+void b3GeometryUtil::getPlaneEquationsFromVertices(b3AlignedObjectArray<b3Vector3>& vertices, b3AlignedObjectArray<b3Vector3>& planeEquationsOut)
+{
+       const int numvertices = vertices.size();
+       // brute force:
+       for (int i = 0; i < numvertices; i++)
+       {
+               const b3Vector3& N1 = vertices[i];
+
+               for (int j = i + 1; j < numvertices; j++)
+               {
+                       const b3Vector3& N2 = vertices[j];
+
+                       for (int k = j + 1; k < numvertices; k++)
+                       {
+                               const b3Vector3& N3 = vertices[k];
+
+                               b3Vector3 planeEquation, edge0, edge1;
+                               edge0 = N2 - N1;
+                               edge1 = N3 - N1;
+                               b3Scalar normalSign = b3Scalar(1.);
+                               for (int ww = 0; ww < 2; ww++)
+                               {
+                                       planeEquation = normalSign * edge0.cross(edge1);
+                                       if (planeEquation.length2() > b3Scalar(0.0001))
+                                       {
+                                               planeEquation.normalize();
+                                               if (notExist(planeEquation, planeEquationsOut))
+                                               {
+                                                       planeEquation[3] = -planeEquation.dot(N1);
+
+                                                       //check if inside, and replace supportingVertexOut if needed
+                                                       if (areVerticesBehindPlane(planeEquation, vertices, b3Scalar(0.01)))
+                                                       {
+                                                               planeEquationsOut.push_back(planeEquation);
+                                                       }
+                                               }
+                                       }
+                                       normalSign = b3Scalar(-1.);
+                               }
+                       }
+               }
+       }
+}
+
+void b3GeometryUtil::getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3Vector3>& planeEquations, b3AlignedObjectArray<b3Vector3>& verticesOut)
+{
+       const int numbrushes = planeEquations.size();
+       // brute force:
+       for (int i = 0; i < numbrushes; i++)
+       {
+               const b3Vector3& N1 = planeEquations[i];
+
+               for (int j = i + 1; j < numbrushes; j++)
+               {
+                       const b3Vector3& N2 = planeEquations[j];
+
+                       for (int k = j + 1; k < numbrushes; k++)
+                       {
+                               const b3Vector3& N3 = planeEquations[k];
+
+                               b3Vector3 n2n3;
+                               n2n3 = N2.cross(N3);
+                               b3Vector3 n3n1;
+                               n3n1 = N3.cross(N1);
+                               b3Vector3 n1n2;
+                               n1n2 = N1.cross(N2);
+
+                               if ((n2n3.length2() > b3Scalar(0.0001)) &&
+                                       (n3n1.length2() > b3Scalar(0.0001)) &&
+                                       (n1n2.length2() > b3Scalar(0.0001)))
+                               {
+                                       //point P out of 3 plane equations:
+
+                                       //      d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
+                                       //P =  -------------------------------------------------------------------------
+                                       //   N1 . ( N2 * N3 )
+
+                                       b3Scalar quotient = (N1.dot(n2n3));
+                                       if (b3Fabs(quotient) > b3Scalar(0.000001))
+                                       {
+                                               quotient = b3Scalar(-1.) / quotient;
+                                               n2n3 *= N1[3];
+                                               n3n1 *= N2[3];
+                                               n1n2 *= N3[3];
+                                               b3Vector3 potentialVertex = n2n3;
+                                               potentialVertex += n3n1;
+                                               potentialVertex += n1n2;
+                                               potentialVertex *= quotient;
+
+                                               //check if inside, and replace supportingVertexOut if needed
+                                               if (isPointInsidePlanes(planeEquations, potentialVertex, b3Scalar(0.01)))
+                                               {
+                                                       verticesOut.push_back(potentialVertex);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3GeometryUtil.h b/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3GeometryUtil.h
new file mode 100644 (file)
index 0000000..9a7bf7e
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_GEOMETRY_UTIL_H
+#define B3_GEOMETRY_UTIL_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+///The b3GeometryUtil helper class provides a few methods to convert between plane equations and vertices.
+class b3GeometryUtil
+{
+public:
+       static void getPlaneEquationsFromVertices(b3AlignedObjectArray<b3Vector3>& vertices, b3AlignedObjectArray<b3Vector3>& planeEquationsOut);
+
+       static void getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3Vector3>& planeEquations, b3AlignedObjectArray<b3Vector3>& verticesOut);
+
+       static bool isInside(const b3AlignedObjectArray<b3Vector3>& vertices, const b3Vector3& planeNormal, b3Scalar margin);
+
+       static bool isPointInsidePlanes(const b3AlignedObjectArray<b3Vector3>& planeEquations, const b3Vector3& point, b3Scalar margin);
+
+       static bool areVerticesBehindPlane(const b3Vector3& planeNormal, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar margin);
+};
+
+#endif  //B3_GEOMETRY_UTIL_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3GrahamScan2dConvexHull.h b/dali-physics/third-party/bullet3/src/Bullet3Geometry/b3GrahamScan2dConvexHull.h
new file mode 100644 (file)
index 0000000..8881c9a
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
+#define B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+struct b3GrahamVector3 : public b3Vector3
+{
+       b3GrahamVector3(const b3Vector3& org, int orgIndex)
+               : b3Vector3(org),
+                 m_orgIndex(orgIndex)
+       {
+       }
+       b3Scalar m_angle;
+       int m_orgIndex;
+};
+
+struct b3AngleCompareFunc
+{
+       b3Vector3 m_anchor;
+       b3AngleCompareFunc(const b3Vector3& anchor)
+               : m_anchor(anchor)
+       {
+       }
+       bool operator()(const b3GrahamVector3& a, const b3GrahamVector3& b) const
+       {
+               if (a.m_angle != b.m_angle)
+                       return a.m_angle < b.m_angle;
+               else
+               {
+                       b3Scalar al = (a - m_anchor).length2();
+                       b3Scalar bl = (b - m_anchor).length2();
+                       if (al != bl)
+                               return al < bl;
+                       else
+                       {
+                               return a.m_orgIndex < b.m_orgIndex;
+                       }
+               }
+       }
+};
+
+inline void b3GrahamScanConvexHull2D(b3AlignedObjectArray<b3GrahamVector3>& originalPoints, b3AlignedObjectArray<b3GrahamVector3>& hull, const b3Vector3& normalAxis)
+{
+       b3Vector3 axis0, axis1;
+       b3PlaneSpace1(normalAxis, axis0, axis1);
+
+       if (originalPoints.size() <= 1)
+       {
+               for (int i = 0; i < originalPoints.size(); i++)
+                       hull.push_back(originalPoints[0]);
+               return;
+       }
+       //step1 : find anchor point with smallest projection on axis0 and move it to first location
+       for (int i = 0; i < originalPoints.size(); i++)
+       {
+               //              const b3Vector3& left = originalPoints[i];
+               //              const b3Vector3& right = originalPoints[0];
+               b3Scalar projL = originalPoints[i].dot(axis0);
+               b3Scalar projR = originalPoints[0].dot(axis0);
+               if (projL < projR)
+               {
+                       originalPoints.swap(0, i);
+               }
+       }
+
+       //also precompute angles
+       originalPoints[0].m_angle = -1e30f;
+       for (int i = 1; i < originalPoints.size(); i++)
+       {
+               b3Vector3 xvec = axis0;
+               b3Vector3 ar = originalPoints[i] - originalPoints[0];
+               originalPoints[i].m_angle = b3Cross(xvec, ar).dot(normalAxis) / ar.length();
+       }
+
+       //step 2: sort all points, based on 'angle' with this anchor
+       b3AngleCompareFunc comp(originalPoints[0]);
+       originalPoints.quickSortInternal(comp, 1, originalPoints.size() - 1);
+
+       int i;
+       for (i = 0; i < 2; i++)
+               hull.push_back(originalPoints[i]);
+
+       //step 3: keep all 'convex' points and discard concave points (using back tracking)
+       for (; i != originalPoints.size(); i++)
+       {
+               bool isConvex = false;
+               while (!isConvex && hull.size() > 1)
+               {
+                       b3Vector3& a = hull[hull.size() - 2];
+                       b3Vector3& b = hull[hull.size() - 1];
+                       isConvex = b3Cross(a - b, a - originalPoints[i]).dot(normalAxis) > 0;
+                       if (!isConvex)
+                               hull.pop_back();
+                       else
+                               hull.push_back(originalPoints[i]);
+               }
+       }
+}
+
+#endif  //B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Geometry/premake4.lua b/dali-physics/third-party/bullet3/src/Bullet3Geometry/premake4.lua
new file mode 100644 (file)
index 0000000..cce93f7
--- /dev/null
@@ -0,0 +1,16 @@
+       project "Bullet3Geometry"
+
+       language "C++"
+                               
+       kind "StaticLib"
+               
+       includedirs {".."}
+       
+    if os.is("Linux") then
+        buildoptions{"-fPIC"}
+    end
+
+       files {
+               "**.cpp",
+               "**.h"
+       }
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h
new file mode 100644 (file)
index 0000000..b296992
--- /dev/null
@@ -0,0 +1,42 @@
+
+#ifndef B3_GPU_BROADPHASE_INTERFACE_H
+#define B3_GPU_BROADPHASE_INTERFACE_H
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "b3SapAabb.h"
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+
+class b3GpuBroadphaseInterface
+{
+public:
+       typedef class b3GpuBroadphaseInterface*(CreateFunc)(cl_context ctx, cl_device_id device, cl_command_queue q);
+
+       virtual ~b3GpuBroadphaseInterface()
+       {
+       }
+
+       virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask) = 0;
+       virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask) = 0;
+
+       virtual void calculateOverlappingPairs(int maxPairs) = 0;
+       virtual void calculateOverlappingPairsHost(int maxPairs) = 0;
+
+       //call writeAabbsToGpu after done making all changes (createProxy etc)
+       virtual void writeAabbsToGpu() = 0;
+
+       virtual cl_mem getAabbBufferWS() = 0;
+       virtual int getNumOverlap() = 0;
+       virtual cl_mem getOverlappingPairBuffer() = 0;
+
+       virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU() = 0;
+       virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU() = 0;
+
+       virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU() = 0;
+       virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU() = 0;
+       virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU() = 0;
+};
+
+#endif  //B3_GPU_BROADPHASE_INTERFACE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp
new file mode 100644 (file)
index 0000000..e714fad
--- /dev/null
@@ -0,0 +1,338 @@
+
+#include "b3GpuGridBroadphase.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+#include "kernels/gridBroadphaseKernels.h"
+#include "kernels/sapKernels.h"
+//#include "kernels/gridBroadphase.cl"
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+
+#define B3_BROADPHASE_SAP_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl"
+#define B3_GRID_BROADPHASE_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl"
+
+cl_kernel kCalcHashAABB;
+cl_kernel kClearCellStart;
+cl_kernel kFindCellStart;
+cl_kernel kFindOverlappingPairs;
+cl_kernel m_copyAabbsKernel;
+cl_kernel m_sap2Kernel;
+
+//int maxPairsPerBody = 64;
+int maxBodiesPerCell = 256;  //??
+
+b3GpuGridBroadphase::b3GpuGridBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q)
+       : m_context(ctx),
+         m_device(device),
+         m_queue(q),
+         m_allAabbsGPU1(ctx, q),
+         m_smallAabbsMappingGPU(ctx, q),
+         m_largeAabbsMappingGPU(ctx, q),
+         m_gpuPairs(ctx, q),
+
+         m_hashGpu(ctx, q),
+
+         m_cellStartGpu(ctx, q),
+         m_paramsGPU(ctx, q)
+{
+       b3Vector3 gridSize = b3MakeVector3(3, 3, 3);
+       b3Vector3 invGridSize = b3MakeVector3(1.f / gridSize[0], 1.f / gridSize[1], 1.f / gridSize[2]);
+
+       m_paramsCPU.m_gridSize[0] = 128;
+       m_paramsCPU.m_gridSize[1] = 128;
+       m_paramsCPU.m_gridSize[2] = 128;
+       m_paramsCPU.m_gridSize[3] = maxBodiesPerCell;
+       m_paramsCPU.setMaxBodiesPerCell(maxBodiesPerCell);
+       m_paramsCPU.m_invCellSize[0] = invGridSize[0];
+       m_paramsCPU.m_invCellSize[1] = invGridSize[1];
+       m_paramsCPU.m_invCellSize[2] = invGridSize[2];
+       m_paramsCPU.m_invCellSize[3] = 0.f;
+       m_paramsGPU.push_back(m_paramsCPU);
+
+       cl_int errNum = 0;
+
+       {
+               const char* sapSrc = sapCL;
+               cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, sapSrc, &errNum, "", B3_BROADPHASE_SAP_PATH);
+               b3Assert(errNum == CL_SUCCESS);
+               m_copyAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "copyAabbsKernel", &errNum, sapProg);
+               m_sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelTwoArrays", &errNum, sapProg);
+               b3Assert(errNum == CL_SUCCESS);
+       }
+
+       {
+               cl_program gridProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, gridBroadphaseCL, &errNum, "", B3_GRID_BROADPHASE_PATH);
+               b3Assert(errNum == CL_SUCCESS);
+
+               kCalcHashAABB = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kCalcHashAABB", &errNum, gridProg);
+               b3Assert(errNum == CL_SUCCESS);
+
+               kClearCellStart = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kClearCellStart", &errNum, gridProg);
+               b3Assert(errNum == CL_SUCCESS);
+
+               kFindCellStart = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kFindCellStart", &errNum, gridProg);
+               b3Assert(errNum == CL_SUCCESS);
+
+               kFindOverlappingPairs = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kFindOverlappingPairs", &errNum, gridProg);
+               b3Assert(errNum == CL_SUCCESS);
+       }
+
+       m_sorter = new b3RadixSort32CL(m_context, m_device, m_queue);
+}
+b3GpuGridBroadphase::~b3GpuGridBroadphase()
+{
+       clReleaseKernel(kCalcHashAABB);
+       clReleaseKernel(kClearCellStart);
+       clReleaseKernel(kFindCellStart);
+       clReleaseKernel(kFindOverlappingPairs);
+       clReleaseKernel(m_sap2Kernel);
+       clReleaseKernel(m_copyAabbsKernel);
+
+       delete m_sorter;
+}
+
+void b3GpuGridBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
+{
+       b3SapAabb aabb;
+       aabb.m_minVec = aabbMin;
+       aabb.m_maxVec = aabbMax;
+       aabb.m_minIndices[3] = userPtr;
+       aabb.m_signedMaxIndices[3] = m_allAabbsCPU1.size();  //NOT userPtr;
+       m_smallAabbsMappingCPU.push_back(m_allAabbsCPU1.size());
+
+       m_allAabbsCPU1.push_back(aabb);
+}
+void b3GpuGridBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
+{
+       b3SapAabb aabb;
+       aabb.m_minVec = aabbMin;
+       aabb.m_maxVec = aabbMax;
+       aabb.m_minIndices[3] = userPtr;
+       aabb.m_signedMaxIndices[3] = m_allAabbsCPU1.size();  //NOT userPtr;
+       m_largeAabbsMappingCPU.push_back(m_allAabbsCPU1.size());
+
+       m_allAabbsCPU1.push_back(aabb);
+}
+
+void b3GpuGridBroadphase::calculateOverlappingPairs(int maxPairs)
+{
+       B3_PROFILE("b3GpuGridBroadphase::calculateOverlappingPairs");
+
+       if (0)
+       {
+               calculateOverlappingPairsHost(maxPairs);
+               /*
+               b3AlignedObjectArray<b3Int4> cpuPairs;
+               m_gpuPairs.copyToHost(cpuPairs);
+               printf("host m_gpuPairs.size()=%d\n",m_gpuPairs.size());
+               for (int i=0;i<m_gpuPairs.size();i++)
+               {
+                       printf("host pair %d = %d,%d\n",i,cpuPairs[i].x,cpuPairs[i].y);
+               }
+               */
+               return;
+       }
+
+       int numSmallAabbs = m_smallAabbsMappingGPU.size();
+
+       b3OpenCLArray<int> pairCount(m_context, m_queue);
+       pairCount.push_back(0);
+       m_gpuPairs.resize(maxPairs);  //numSmallAabbs*maxPairsPerBody);
+
+       {
+               int numLargeAabbs = m_largeAabbsMappingGPU.size();
+               if (numLargeAabbs && numSmallAabbs)
+               {
+                       B3_PROFILE("sap2Kernel");
+                       b3BufferInfoCL bInfo[] = {
+                               b3BufferInfoCL(m_allAabbsGPU1.getBufferCL()),
+                               b3BufferInfoCL(m_largeAabbsMappingGPU.getBufferCL()),
+                               b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL()),
+                               b3BufferInfoCL(m_gpuPairs.getBufferCL()),
+                               b3BufferInfoCL(pairCount.getBufferCL())};
+                       b3LauncherCL launcher(m_queue, m_sap2Kernel, "m_sap2Kernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numLargeAabbs);
+                       launcher.setConst(numSmallAabbs);
+                       launcher.setConst(0);  //axis is not used
+                       launcher.setConst(maxPairs);
+                       //@todo: use actual maximum work item sizes of the device instead of hardcoded values
+                       launcher.launch2D(numLargeAabbs, numSmallAabbs, 4, 64);
+
+                       int numPairs = pairCount.at(0);
+
+                       if (numPairs > maxPairs)
+                       {
+                               b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+                               numPairs = maxPairs;
+                       }
+               }
+       }
+
+       if (numSmallAabbs)
+       {
+               B3_PROFILE("gridKernel");
+               m_hashGpu.resize(numSmallAabbs);
+               {
+                       B3_PROFILE("kCalcHashAABB");
+                       b3LauncherCL launch(m_queue, kCalcHashAABB, "kCalcHashAABB");
+                       launch.setConst(numSmallAabbs);
+                       launch.setBuffer(m_allAabbsGPU1.getBufferCL());
+                       launch.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
+                       launch.setBuffer(m_hashGpu.getBufferCL());
+                       launch.setBuffer(this->m_paramsGPU.getBufferCL());
+                       launch.launch1D(numSmallAabbs);
+               }
+
+               m_sorter->execute(m_hashGpu);
+
+               int numCells = this->m_paramsCPU.m_gridSize[0] * this->m_paramsCPU.m_gridSize[1] * this->m_paramsCPU.m_gridSize[2];
+               m_cellStartGpu.resize(numCells);
+               //b3AlignedObjectArray<int >                    cellStartCpu;
+
+               {
+                       B3_PROFILE("kClearCellStart");
+                       b3LauncherCL launch(m_queue, kClearCellStart, "kClearCellStart");
+                       launch.setConst(numCells);
+                       launch.setBuffer(m_cellStartGpu.getBufferCL());
+                       launch.launch1D(numCells);
+                       //m_cellStartGpu.copyToHost(cellStartCpu);
+                       //printf("??\n");
+               }
+
+               {
+                       B3_PROFILE("kFindCellStart");
+                       b3LauncherCL launch(m_queue, kFindCellStart, "kFindCellStart");
+                       launch.setConst(numSmallAabbs);
+                       launch.setBuffer(m_hashGpu.getBufferCL());
+                       launch.setBuffer(m_cellStartGpu.getBufferCL());
+                       launch.launch1D(numSmallAabbs);
+                       //m_cellStartGpu.copyToHost(cellStartCpu);
+                       //printf("??\n");
+               }
+
+               {
+                       B3_PROFILE("kFindOverlappingPairs");
+
+                       b3LauncherCL launch(m_queue, kFindOverlappingPairs, "kFindOverlappingPairs");
+                       launch.setConst(numSmallAabbs);
+                       launch.setBuffer(m_allAabbsGPU1.getBufferCL());
+                       launch.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
+                       launch.setBuffer(m_hashGpu.getBufferCL());
+                       launch.setBuffer(m_cellStartGpu.getBufferCL());
+
+                       launch.setBuffer(m_paramsGPU.getBufferCL());
+                       //launch.setBuffer(0);
+                       launch.setBuffer(pairCount.getBufferCL());
+                       launch.setBuffer(m_gpuPairs.getBufferCL());
+
+                       launch.setConst(maxPairs);
+                       launch.launch1D(numSmallAabbs);
+
+                       int numPairs = pairCount.at(0);
+                       if (numPairs > maxPairs)
+                       {
+                               b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+                               numPairs = maxPairs;
+                       }
+
+                       m_gpuPairs.resize(numPairs);
+
+                       if (0)
+                       {
+                               b3AlignedObjectArray<b3Int4> pairsCpu;
+                               m_gpuPairs.copyToHost(pairsCpu);
+
+                               int sz = m_gpuPairs.size();
+                               printf("m_gpuPairs.size()=%d\n", sz);
+                               for (int i = 0; i < m_gpuPairs.size(); i++)
+                               {
+                                       printf("pair %d = %d,%d\n", i, pairsCpu[i].x, pairsCpu[i].y);
+                               }
+
+                               printf("?!?\n");
+                       }
+               }
+       }
+
+       //calculateOverlappingPairsHost(maxPairs);
+}
+void b3GpuGridBroadphase::calculateOverlappingPairsHost(int maxPairs)
+{
+       m_hostPairs.resize(0);
+       m_allAabbsGPU1.copyToHost(m_allAabbsCPU1);
+       for (int i = 0; i < m_allAabbsCPU1.size(); i++)
+       {
+               for (int j = i + 1; j < m_allAabbsCPU1.size(); j++)
+               {
+                       if (b3TestAabbAgainstAabb2(m_allAabbsCPU1[i].m_minVec, m_allAabbsCPU1[i].m_maxVec,
+                                                                          m_allAabbsCPU1[j].m_minVec, m_allAabbsCPU1[j].m_maxVec))
+                       {
+                               b3Int4 pair;
+                               int a = m_allAabbsCPU1[j].m_minIndices[3];
+                               int b = m_allAabbsCPU1[i].m_minIndices[3];
+                               if (a <= b)
+                               {
+                                       pair.x = a;
+                                       pair.y = b;  //store the original index in the unsorted aabb array
+                               }
+                               else
+                               {
+                                       pair.x = b;
+                                       pair.y = a;  //store the original index in the unsorted aabb array
+                               }
+
+                               if (m_hostPairs.size() < maxPairs)
+                               {
+                                       m_hostPairs.push_back(pair);
+                               }
+                       }
+               }
+       }
+
+       m_gpuPairs.copyFromHost(m_hostPairs);
+}
+
+//call writeAabbsToGpu after done making all changes (createProxy etc)
+void b3GpuGridBroadphase::writeAabbsToGpu()
+{
+       m_allAabbsGPU1.copyFromHost(m_allAabbsCPU1);
+       m_smallAabbsMappingGPU.copyFromHost(m_smallAabbsMappingCPU);
+       m_largeAabbsMappingGPU.copyFromHost(m_largeAabbsMappingCPU);
+}
+
+cl_mem b3GpuGridBroadphase::getAabbBufferWS()
+{
+       return this->m_allAabbsGPU1.getBufferCL();
+}
+int b3GpuGridBroadphase::getNumOverlap()
+{
+       return m_gpuPairs.size();
+}
+cl_mem b3GpuGridBroadphase::getOverlappingPairBuffer()
+{
+       return m_gpuPairs.getBufferCL();
+}
+
+b3OpenCLArray<b3SapAabb>& b3GpuGridBroadphase::getAllAabbsGPU()
+{
+       return m_allAabbsGPU1;
+}
+
+b3AlignedObjectArray<b3SapAabb>& b3GpuGridBroadphase::getAllAabbsCPU()
+{
+       return m_allAabbsCPU1;
+}
+
+b3OpenCLArray<b3Int4>& b3GpuGridBroadphase::getOverlappingPairsGPU()
+{
+       return m_gpuPairs;
+}
+b3OpenCLArray<int>& b3GpuGridBroadphase::getSmallAabbIndicesGPU()
+{
+       return m_smallAabbsMappingGPU;
+}
+b3OpenCLArray<int>& b3GpuGridBroadphase::getLargeAabbIndicesGPU()
+{
+       return m_largeAabbsMappingGPU;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h
new file mode 100644 (file)
index 0000000..b76cb43
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef B3_GPU_GRID_BROADPHASE_H
+#define B3_GPU_GRID_BROADPHASE_H
+
+#include "b3GpuBroadphaseInterface.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+
+struct b3ParamsGridBroadphaseCL
+{
+       float m_invCellSize[4];
+       int m_gridSize[4];
+
+       int getMaxBodiesPerCell() const
+       {
+               return m_gridSize[3];
+       }
+
+       void setMaxBodiesPerCell(int maxOverlap)
+       {
+               m_gridSize[3] = maxOverlap;
+       }
+};
+
+class b3GpuGridBroadphase : public b3GpuBroadphaseInterface
+{
+protected:
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_queue;
+
+       b3OpenCLArray<b3SapAabb> m_allAabbsGPU1;
+       b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU1;
+
+       b3OpenCLArray<int> m_smallAabbsMappingGPU;
+       b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
+
+       b3OpenCLArray<int> m_largeAabbsMappingGPU;
+       b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
+
+       b3AlignedObjectArray<b3Int4> m_hostPairs;
+       b3OpenCLArray<b3Int4> m_gpuPairs;
+
+       b3OpenCLArray<b3SortData> m_hashGpu;
+       b3OpenCLArray<int> m_cellStartGpu;
+
+       b3ParamsGridBroadphaseCL m_paramsCPU;
+       b3OpenCLArray<b3ParamsGridBroadphaseCL> m_paramsGPU;
+
+       class b3RadixSort32CL* m_sorter;
+
+public:
+       b3GpuGridBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q);
+       virtual ~b3GpuGridBroadphase();
+
+       static b3GpuBroadphaseInterface* CreateFunc(cl_context ctx, cl_device_id device, cl_command_queue q)
+       {
+               return new b3GpuGridBroadphase(ctx, device, q);
+       }
+
+       virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+       virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+
+       virtual void calculateOverlappingPairs(int maxPairs);
+       virtual void calculateOverlappingPairsHost(int maxPairs);
+
+       //call writeAabbsToGpu after done making all changes (createProxy etc)
+       virtual void writeAabbsToGpu();
+
+       virtual cl_mem getAabbBufferWS();
+       virtual int getNumOverlap();
+       virtual cl_mem getOverlappingPairBuffer();
+
+       virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU();
+       virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU();
+
+       virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU();
+       virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU();
+       virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU();
+};
+
+#endif  //B3_GPU_GRID_BROADPHASE_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
new file mode 100644 (file)
index 0000000..616fc34
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Initial Author Jackson Lee, 2014
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+
+#include "b3GpuParallelLinearBvh.h"
+
+b3GpuParallelLinearBvh::b3GpuParallelLinearBvh(cl_context context, cl_device_id device, cl_command_queue queue) : m_queue(queue),
+                                                                                                                                                                                                                                 m_radixSorter(context, device, queue),
+
+                                                                                                                                                                                                                                 m_rootNodeIndex(context, queue),
+                                                                                                                                                                                                                                 m_maxDistanceFromRoot(context, queue),
+                                                                                                                                                                                                                                 m_temp(context, queue),
+
+                                                                                                                                                                                                                                 m_internalNodeAabbs(context, queue),
+                                                                                                                                                                                                                                 m_internalNodeLeafIndexRanges(context, queue),
+                                                                                                                                                                                                                                 m_internalNodeChildNodes(context, queue),
+                                                                                                                                                                                                                                 m_internalNodeParentNodes(context, queue),
+
+                                                                                                                                                                                                                                 m_commonPrefixes(context, queue),
+                                                                                                                                                                                                                                 m_commonPrefixLengths(context, queue),
+                                                                                                                                                                                                                                 m_distanceFromRoot(context, queue),
+
+                                                                                                                                                                                                                                 m_leafNodeParentNodes(context, queue),
+                                                                                                                                                                                                                                 m_mortonCodesAndAabbIndicies(context, queue),
+                                                                                                                                                                                                                                 m_mergedAabb(context, queue),
+                                                                                                                                                                                                                                 m_leafNodeAabbs(context, queue),
+
+                                                                                                                                                                                                                                 m_largeAabbs(context, queue)
+{
+       m_rootNodeIndex.resize(1);
+       m_maxDistanceFromRoot.resize(1);
+       m_temp.resize(1);
+
+       //
+       const char CL_PROGRAM_PATH[] = "src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl";
+
+       const char* kernelSource = parallelLinearBvhCL;  //parallelLinearBvhCL.h
+       cl_int error;
+       char* additionalMacros = 0;
+       m_parallelLinearBvhProgram = b3OpenCLUtils::compileCLProgramFromString(context, device, kernelSource, &error, additionalMacros, CL_PROGRAM_PATH);
+       b3Assert(m_parallelLinearBvhProgram);
+
+       m_separateAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "separateAabbs", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_separateAabbsKernel);
+       m_findAllNodesMergedAabbKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "findAllNodesMergedAabb", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_findAllNodesMergedAabbKernel);
+       m_assignMortonCodesAndAabbIndiciesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "assignMortonCodesAndAabbIndicies", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_assignMortonCodesAndAabbIndiciesKernel);
+
+       m_computeAdjacentPairCommonPrefixKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "computeAdjacentPairCommonPrefix", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_computeAdjacentPairCommonPrefixKernel);
+       m_buildBinaryRadixTreeLeafNodesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "buildBinaryRadixTreeLeafNodes", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_buildBinaryRadixTreeLeafNodesKernel);
+       m_buildBinaryRadixTreeInternalNodesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "buildBinaryRadixTreeInternalNodes", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_buildBinaryRadixTreeInternalNodesKernel);
+       m_findDistanceFromRootKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "findDistanceFromRoot", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_findDistanceFromRootKernel);
+       m_buildBinaryRadixTreeAabbsRecursiveKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "buildBinaryRadixTreeAabbsRecursive", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_buildBinaryRadixTreeAabbsRecursiveKernel);
+
+       m_findLeafIndexRangesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "findLeafIndexRanges", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_findLeafIndexRangesKernel);
+
+       m_plbvhCalculateOverlappingPairsKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhCalculateOverlappingPairs", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_plbvhCalculateOverlappingPairsKernel);
+       m_plbvhRayTraverseKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhRayTraverse", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_plbvhRayTraverseKernel);
+       m_plbvhLargeAabbAabbTestKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhLargeAabbAabbTest", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_plbvhLargeAabbAabbTestKernel);
+       m_plbvhLargeAabbRayTestKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhLargeAabbRayTest", &error, m_parallelLinearBvhProgram, additionalMacros);
+       b3Assert(m_plbvhLargeAabbRayTestKernel);
+}
+
+b3GpuParallelLinearBvh::~b3GpuParallelLinearBvh()
+{
+       clReleaseKernel(m_separateAabbsKernel);
+       clReleaseKernel(m_findAllNodesMergedAabbKernel);
+       clReleaseKernel(m_assignMortonCodesAndAabbIndiciesKernel);
+
+       clReleaseKernel(m_computeAdjacentPairCommonPrefixKernel);
+       clReleaseKernel(m_buildBinaryRadixTreeLeafNodesKernel);
+       clReleaseKernel(m_buildBinaryRadixTreeInternalNodesKernel);
+       clReleaseKernel(m_findDistanceFromRootKernel);
+       clReleaseKernel(m_buildBinaryRadixTreeAabbsRecursiveKernel);
+
+       clReleaseKernel(m_findLeafIndexRangesKernel);
+
+       clReleaseKernel(m_plbvhCalculateOverlappingPairsKernel);
+       clReleaseKernel(m_plbvhRayTraverseKernel);
+       clReleaseKernel(m_plbvhLargeAabbAabbTestKernel);
+       clReleaseKernel(m_plbvhLargeAabbRayTestKernel);
+
+       clReleaseProgram(m_parallelLinearBvhProgram);
+}
+
+void b3GpuParallelLinearBvh::build(const b3OpenCLArray<b3SapAabb>& worldSpaceAabbs, const b3OpenCLArray<int>& smallAabbIndices,
+                                                                  const b3OpenCLArray<int>& largeAabbIndices)
+{
+       B3_PROFILE("b3ParallelLinearBvh::build()");
+
+       int numLargeAabbs = largeAabbIndices.size();
+       int numSmallAabbs = smallAabbIndices.size();
+
+       //Since all AABBs(both large and small) are input as a contiguous array,
+       //with 2 additional arrays used to indicate the indices of large and small AABBs,
+       //it is necessary to separate the AABBs so that the large AABBs will not degrade the quality of the BVH.
+       {
+               B3_PROFILE("Separate large and small AABBs");
+
+               m_largeAabbs.resize(numLargeAabbs);
+               m_leafNodeAabbs.resize(numSmallAabbs);
+
+               //Write large AABBs into m_largeAabbs
+               {
+                       b3BufferInfoCL bufferInfo[] =
+                               {
+                                       b3BufferInfoCL(worldSpaceAabbs.getBufferCL()),
+                                       b3BufferInfoCL(largeAabbIndices.getBufferCL()),
+
+                                       b3BufferInfoCL(m_largeAabbs.getBufferCL())};
+
+                       b3LauncherCL launcher(m_queue, m_separateAabbsKernel, "m_separateAabbsKernel");
+                       launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numLargeAabbs);
+
+                       launcher.launch1D(numLargeAabbs);
+               }
+
+               //Write small AABBs into m_leafNodeAabbs
+               {
+                       b3BufferInfoCL bufferInfo[] =
+                               {
+                                       b3BufferInfoCL(worldSpaceAabbs.getBufferCL()),
+                                       b3BufferInfoCL(smallAabbIndices.getBufferCL()),
+
+                                       b3BufferInfoCL(m_leafNodeAabbs.getBufferCL())};
+
+                       b3LauncherCL launcher(m_queue, m_separateAabbsKernel, "m_separateAabbsKernel");
+                       launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numSmallAabbs);
+
+                       launcher.launch1D(numSmallAabbs);
+               }
+
+               clFinish(m_queue);
+       }
+
+       //
+       int numLeaves = numSmallAabbs;  //Number of leaves in the BVH == Number of rigid bodies with small AABBs
+       int numInternalNodes = numLeaves - 1;
+
+       if (numLeaves < 2)
+       {
+               //Number of leaf nodes is checked in calculateOverlappingPairs() and testRaysAgainstBvhAabbs(),
+               //so it does not matter if numLeaves == 0 and rootNodeIndex == -1
+               int rootNodeIndex = numLeaves - 1;
+               m_rootNodeIndex.copyFromHostPointer(&rootNodeIndex, 1);
+
+               //Since the AABBs need to be rearranged(sorted) for the BVH construction algorithm,
+               //m_mortonCodesAndAabbIndicies.m_value is used to map a sorted AABB index to the unsorted AABB index
+               //instead of directly moving the AABBs. It needs to be set for the ray cast traversal kernel to work.
+               //( m_mortonCodesAndAabbIndicies[].m_value == unsorted index == index of m_leafNodeAabbs )
+               if (numLeaves == 1)
+               {
+                       b3SortData leaf;
+                       leaf.m_value = 0;  //1 leaf so index is always 0; leaf.m_key does not need to be set
+
+                       m_mortonCodesAndAabbIndicies.resize(1);
+                       m_mortonCodesAndAabbIndicies.copyFromHostPointer(&leaf, 1);
+               }
+
+               return;
+       }
+
+       //
+       {
+               m_internalNodeAabbs.resize(numInternalNodes);
+               m_internalNodeLeafIndexRanges.resize(numInternalNodes);
+               m_internalNodeChildNodes.resize(numInternalNodes);
+               m_internalNodeParentNodes.resize(numInternalNodes);
+
+               m_commonPrefixes.resize(numInternalNodes);
+               m_commonPrefixLengths.resize(numInternalNodes);
+               m_distanceFromRoot.resize(numInternalNodes);
+
+               m_leafNodeParentNodes.resize(numLeaves);
+               m_mortonCodesAndAabbIndicies.resize(numLeaves);
+               m_mergedAabb.resize(numLeaves);
+       }
+
+       //Find the merged AABB of all small AABBs; this is used to define the size of
+       //each cell in the virtual grid for the next kernel(2^10 cells in each dimension).
+       {
+               B3_PROFILE("Find AABB of merged nodes");
+
+               m_mergedAabb.copyFromOpenCLArray(m_leafNodeAabbs);  //Need to make a copy since the kernel modifies the array
+
+               for (int numAabbsNeedingMerge = numLeaves; numAabbsNeedingMerge >= 2;
+                        numAabbsNeedingMerge = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2)
+               {
+                       b3BufferInfoCL bufferInfo[] =
+                               {
+                                       b3BufferInfoCL(m_mergedAabb.getBufferCL())  //Resulting AABB is stored in m_mergedAabb[0]
+                               };
+
+                       b3LauncherCL launcher(m_queue, m_findAllNodesMergedAabbKernel, "m_findAllNodesMergedAabbKernel");
+                       launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numAabbsNeedingMerge);
+
+                       launcher.launch1D(numAabbsNeedingMerge);
+               }
+
+               clFinish(m_queue);
+       }
+
+       //Insert the center of the AABBs into a virtual grid,
+       //then convert the discrete grid coordinates into a morton code
+       //For each element in m_mortonCodesAndAabbIndicies, set
+       //      m_key == morton code (value to sort by)
+       //      m_value == small AABB index
+       {
+               B3_PROFILE("Assign morton codes");
+
+               b3BufferInfoCL bufferInfo[] =
+                       {
+                               b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
+                               b3BufferInfoCL(m_mergedAabb.getBufferCL()),
+                               b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_assignMortonCodesAndAabbIndiciesKernel, "m_assignMortonCodesAndAabbIndiciesKernel");
+               launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(numLeaves);
+
+               launcher.launch1D(numLeaves);
+               clFinish(m_queue);
+       }
+
+       //
+       {
+               B3_PROFILE("Sort leaves by morton codes");
+
+               m_radixSorter.execute(m_mortonCodesAndAabbIndicies);
+               clFinish(m_queue);
+       }
+
+       //
+       constructBinaryRadixTree();
+
+       //Since it is a sorted binary radix tree, each internal node contains a contiguous subset of leaf node indices.
+       //The root node contains leaf node indices in the range [0, numLeafNodes - 1].
+       //The child nodes of each node split their parent's index range into 2 contiguous halves.
+       //
+       //For example, if the root has indices [0, 31], its children might partition that range into [0, 11] and [12, 31].
+       //The next level in the tree could then split those ranges into [0, 2], [3, 11], [12, 22], and [23, 31].
+       //
+       //This property can be used for optimizing calculateOverlappingPairs(), to avoid testing each AABB pair twice
+       {
+               B3_PROFILE("m_findLeafIndexRangesKernel");
+
+               b3BufferInfoCL bufferInfo[] =
+                       {
+                               b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeLeafIndexRanges.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_findLeafIndexRangesKernel, "m_findLeafIndexRangesKernel");
+               launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(numInternalNodes);
+
+               launcher.launch1D(numInternalNodes);
+               clFinish(m_queue);
+       }
+}
+
+void b3GpuParallelLinearBvh::calculateOverlappingPairs(b3OpenCLArray<b3Int4>& out_overlappingPairs)
+{
+       int maxPairs = out_overlappingPairs.size();
+       b3OpenCLArray<int>& numPairsGpu = m_temp;
+
+       int reset = 0;
+       numPairsGpu.copyFromHostPointer(&reset, 1);
+
+       //
+       if (m_leafNodeAabbs.size() > 1)
+       {
+               B3_PROFILE("PLBVH small-small AABB test");
+
+               int numQueryAabbs = m_leafNodeAabbs.size();
+
+               b3BufferInfoCL bufferInfo[] =
+                       {
+                               b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
+
+                               b3BufferInfoCL(m_rootNodeIndex.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeAabbs.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeLeafIndexRanges.getBufferCL()),
+                               b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
+
+                               b3BufferInfoCL(numPairsGpu.getBufferCL()),
+                               b3BufferInfoCL(out_overlappingPairs.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_plbvhCalculateOverlappingPairsKernel, "m_plbvhCalculateOverlappingPairsKernel");
+               launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(maxPairs);
+               launcher.setConst(numQueryAabbs);
+
+               launcher.launch1D(numQueryAabbs);
+               clFinish(m_queue);
+       }
+
+       int numLargeAabbRigids = m_largeAabbs.size();
+       if (numLargeAabbRigids > 0 && m_leafNodeAabbs.size() > 0)
+       {
+               B3_PROFILE("PLBVH large-small AABB test");
+
+               int numQueryAabbs = m_leafNodeAabbs.size();
+
+               b3BufferInfoCL bufferInfo[] =
+                       {
+                               b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
+                               b3BufferInfoCL(m_largeAabbs.getBufferCL()),
+
+                               b3BufferInfoCL(numPairsGpu.getBufferCL()),
+                               b3BufferInfoCL(out_overlappingPairs.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_plbvhLargeAabbAabbTestKernel, "m_plbvhLargeAabbAabbTestKernel");
+               launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(maxPairs);
+               launcher.setConst(numLargeAabbRigids);
+               launcher.setConst(numQueryAabbs);
+
+               launcher.launch1D(numQueryAabbs);
+               clFinish(m_queue);
+       }
+
+       //
+       int numPairs = -1;
+       numPairsGpu.copyToHostPointer(&numPairs, 1);
+       if (numPairs > maxPairs)
+       {
+               b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+               numPairs = maxPairs;
+               numPairsGpu.copyFromHostPointer(&maxPairs, 1);
+       }
+
+       out_overlappingPairs.resize(numPairs);
+}
+
+void b3GpuParallelLinearBvh::testRaysAgainstBvhAabbs(const b3OpenCLArray<b3RayInfo>& rays,
+                                                                                                        b3OpenCLArray<int>& out_numRayRigidPairs, b3OpenCLArray<b3Int2>& out_rayRigidPairs)
+{
+       B3_PROFILE("PLBVH testRaysAgainstBvhAabbs()");
+
+       int numRays = rays.size();
+       int maxRayRigidPairs = out_rayRigidPairs.size();
+
+       int reset = 0;
+       out_numRayRigidPairs.copyFromHostPointer(&reset, 1);
+
+       //
+       if (m_leafNodeAabbs.size() > 0)
+       {
+               B3_PROFILE("PLBVH ray test small AABB");
+
+               b3BufferInfoCL bufferInfo[] =
+                       {
+                               b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
+
+                               b3BufferInfoCL(m_rootNodeIndex.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeAabbs.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeLeafIndexRanges.getBufferCL()),
+                               b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
+
+                               b3BufferInfoCL(rays.getBufferCL()),
+
+                               b3BufferInfoCL(out_numRayRigidPairs.getBufferCL()),
+                               b3BufferInfoCL(out_rayRigidPairs.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_plbvhRayTraverseKernel, "m_plbvhRayTraverseKernel");
+               launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(maxRayRigidPairs);
+               launcher.setConst(numRays);
+
+               launcher.launch1D(numRays);
+               clFinish(m_queue);
+       }
+
+       int numLargeAabbRigids = m_largeAabbs.size();
+       if (numLargeAabbRigids > 0)
+       {
+               B3_PROFILE("PLBVH ray test large AABB");
+
+               b3BufferInfoCL bufferInfo[] =
+                       {
+                               b3BufferInfoCL(m_largeAabbs.getBufferCL()),
+                               b3BufferInfoCL(rays.getBufferCL()),
+
+                               b3BufferInfoCL(out_numRayRigidPairs.getBufferCL()),
+                               b3BufferInfoCL(out_rayRigidPairs.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_plbvhLargeAabbRayTestKernel, "m_plbvhLargeAabbRayTestKernel");
+               launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(numLargeAabbRigids);
+               launcher.setConst(maxRayRigidPairs);
+               launcher.setConst(numRays);
+
+               launcher.launch1D(numRays);
+               clFinish(m_queue);
+       }
+
+       //
+       int numRayRigidPairs = -1;
+       out_numRayRigidPairs.copyToHostPointer(&numRayRigidPairs, 1);
+
+       if (numRayRigidPairs > maxRayRigidPairs)
+               b3Error("Error running out of rayRigid pairs: numRayRigidPairs = %d, maxRayRigidPairs = %d.\n", numRayRigidPairs, maxRayRigidPairs);
+}
+
+void b3GpuParallelLinearBvh::constructBinaryRadixTree()
+{
+       B3_PROFILE("b3GpuParallelLinearBvh::constructBinaryRadixTree()");
+
+       int numLeaves = m_leafNodeAabbs.size();
+       int numInternalNodes = numLeaves - 1;
+
+       //Each internal node is placed in between 2 leaf nodes.
+       //By using this arrangement and computing the common prefix between
+       //these 2 adjacent leaf nodes, it is possible to quickly construct a binary radix tree.
+       {
+               B3_PROFILE("m_computeAdjacentPairCommonPrefixKernel");
+
+               b3BufferInfoCL bufferInfo[] =
+                       {
+                               b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
+                               b3BufferInfoCL(m_commonPrefixes.getBufferCL()),
+                               b3BufferInfoCL(m_commonPrefixLengths.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_computeAdjacentPairCommonPrefixKernel, "m_computeAdjacentPairCommonPrefixKernel");
+               launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(numInternalNodes);
+
+               launcher.launch1D(numInternalNodes);
+               clFinish(m_queue);
+       }
+
+       //For each leaf node, select its parent node by
+       //comparing the 2 nearest internal nodes and assign child node indices
+       {
+               B3_PROFILE("m_buildBinaryRadixTreeLeafNodesKernel");
+
+               b3BufferInfoCL bufferInfo[] =
+                       {
+                               b3BufferInfoCL(m_commonPrefixLengths.getBufferCL()),
+                               b3BufferInfoCL(m_leafNodeParentNodes.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeLeafNodesKernel, "m_buildBinaryRadixTreeLeafNodesKernel");
+               launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(numLeaves);
+
+               launcher.launch1D(numLeaves);
+               clFinish(m_queue);
+       }
+
+       //For each internal node, perform 2 binary searches among the other internal nodes
+       //to its left and right to find its potential parent nodes and assign child node indices
+       {
+               B3_PROFILE("m_buildBinaryRadixTreeInternalNodesKernel");
+
+               b3BufferInfoCL bufferInfo[] =
+                       {
+                               b3BufferInfoCL(m_commonPrefixes.getBufferCL()),
+                               b3BufferInfoCL(m_commonPrefixLengths.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeParentNodes.getBufferCL()),
+                               b3BufferInfoCL(m_rootNodeIndex.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeInternalNodesKernel, "m_buildBinaryRadixTreeInternalNodesKernel");
+               launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(numInternalNodes);
+
+               launcher.launch1D(numInternalNodes);
+               clFinish(m_queue);
+       }
+
+       //Find the number of nodes separating each internal node and the root node
+       //so that the AABBs can be set using the next kernel.
+       //Also determine the maximum number of nodes separating an internal node and the root node.
+       {
+               B3_PROFILE("m_findDistanceFromRootKernel");
+
+               b3BufferInfoCL bufferInfo[] =
+                       {
+                               b3BufferInfoCL(m_rootNodeIndex.getBufferCL()),
+                               b3BufferInfoCL(m_internalNodeParentNodes.getBufferCL()),
+                               b3BufferInfoCL(m_maxDistanceFromRoot.getBufferCL()),
+                               b3BufferInfoCL(m_distanceFromRoot.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_findDistanceFromRootKernel, "m_findDistanceFromRootKernel");
+               launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(numInternalNodes);
+
+               launcher.launch1D(numInternalNodes);
+               clFinish(m_queue);
+       }
+
+       //Starting from the internal nodes nearest to the leaf nodes, recursively move up
+       //the tree towards the root to set the AABBs of each internal node; each internal node
+       //checks its children and merges their AABBs
+       {
+               B3_PROFILE("m_buildBinaryRadixTreeAabbsRecursiveKernel");
+
+               int maxDistanceFromRoot = -1;
+               {
+                       B3_PROFILE("copy maxDistanceFromRoot to CPU");
+                       m_maxDistanceFromRoot.copyToHostPointer(&maxDistanceFromRoot, 1);
+                       clFinish(m_queue);
+               }
+
+               for (int distanceFromRoot = maxDistanceFromRoot; distanceFromRoot >= 0; --distanceFromRoot)
+               {
+                       b3BufferInfoCL bufferInfo[] =
+                               {
+                                       b3BufferInfoCL(m_distanceFromRoot.getBufferCL()),
+                                       b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
+                                       b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
+                                       b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
+                                       b3BufferInfoCL(m_internalNodeAabbs.getBufferCL())};
+
+                       b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeAabbsRecursiveKernel, "m_buildBinaryRadixTreeAabbsRecursiveKernel");
+                       launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(maxDistanceFromRoot);
+                       launcher.setConst(distanceFromRoot);
+                       launcher.setConst(numInternalNodes);
+
+                       //It may seem inefficent to launch a thread for each internal node when a
+                       //much smaller number of nodes is actually processed, but this is actually
+                       //faster than determining the exact nodes that are ready to merge their child AABBs.
+                       launcher.launch1D(numInternalNodes);
+               }
+
+               clFinish(m_queue);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h
new file mode 100644 (file)
index 0000000..b390775
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Initial Author Jackson Lee, 2014
+
+#ifndef B3_GPU_PARALLEL_LINEAR_BVH_H
+#define B3_GPU_PARALLEL_LINEAR_BVH_H
+
+//#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
+
+#include "Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h"
+
+#define b3Int64 cl_long
+
+///@brief GPU Parallel Linearized Bounding Volume Heirarchy(LBVH) that is reconstructed every frame
+///@remarks
+///See presentation in docs/b3GpuParallelLinearBvh.pdf for algorithm details.
+///@par
+///Related papers: \n
+///"Fast BVH Construction on GPUs" [Lauterbach et al. 2009] \n
+///"Maximizing Parallelism in the Construction of BVHs, Octrees, and k-d trees" [Karras 2012] \n
+///@par
+///The basic algorithm for building the BVH as presented in [Lauterbach et al. 2009] consists of 4 stages:
+/// - [fully parallel] Assign morton codes for each AABB using its center (after quantizing the AABB centers into a virtual grid)
+/// - [fully parallel] Sort morton codes
+/// - [somewhat parallel] Build binary radix tree (assign parent/child pointers for internal nodes of the BVH)
+/// - [somewhat parallel] Set internal node AABBs
+///@par
+///[Karras 2012] improves on the algorithm by introducing fully parallel methods for the last 2 stages.
+///The BVH implementation here shares many concepts with [Karras 2012], but a different method is used for constructing the tree.
+///Instead of searching for the child nodes of each internal node, we search for the parent node of each node.
+///Additionally, a non-atomic traversal that starts from the leaf nodes and moves towards the root node is used to set the AABBs.
+class b3GpuParallelLinearBvh
+{
+       cl_command_queue m_queue;
+
+       cl_program m_parallelLinearBvhProgram;
+
+       cl_kernel m_separateAabbsKernel;
+       cl_kernel m_findAllNodesMergedAabbKernel;
+       cl_kernel m_assignMortonCodesAndAabbIndiciesKernel;
+
+       //Binary radix tree construction kernels
+       cl_kernel m_computeAdjacentPairCommonPrefixKernel;
+       cl_kernel m_buildBinaryRadixTreeLeafNodesKernel;
+       cl_kernel m_buildBinaryRadixTreeInternalNodesKernel;
+       cl_kernel m_findDistanceFromRootKernel;
+       cl_kernel m_buildBinaryRadixTreeAabbsRecursiveKernel;
+
+       cl_kernel m_findLeafIndexRangesKernel;
+
+       //Traversal kernels
+       cl_kernel m_plbvhCalculateOverlappingPairsKernel;
+       cl_kernel m_plbvhRayTraverseKernel;
+       cl_kernel m_plbvhLargeAabbAabbTestKernel;
+       cl_kernel m_plbvhLargeAabbRayTestKernel;
+
+       b3RadixSort32CL m_radixSorter;
+
+       //1 element
+       b3OpenCLArray<int> m_rootNodeIndex;        //Most significant bit(0x80000000) is set to indicate internal node
+       b3OpenCLArray<int> m_maxDistanceFromRoot;  //Max number of internal nodes between an internal node and the root node
+       b3OpenCLArray<int> m_temp;                 //Used to hold the number of pairs in calculateOverlappingPairs()
+
+       //1 element per internal node (number_of_internal_nodes == number_of_leaves - 1)
+       b3OpenCLArray<b3SapAabb> m_internalNodeAabbs;
+       b3OpenCLArray<b3Int2> m_internalNodeLeafIndexRanges;  //x == min leaf index, y == max leaf index
+       b3OpenCLArray<b3Int2> m_internalNodeChildNodes;       //x == left child, y == right child; msb(0x80000000) is set to indicate internal node
+       b3OpenCLArray<int> m_internalNodeParentNodes;         //For parent node index, msb(0x80000000) is not set since it is always internal
+
+       //1 element per internal node; for binary radix tree construction
+       b3OpenCLArray<b3Int64> m_commonPrefixes;
+       b3OpenCLArray<int> m_commonPrefixLengths;
+       b3OpenCLArray<int> m_distanceFromRoot;  //Number of internal nodes between this node and the root
+
+       //1 element per leaf node (leaf nodes only include small AABBs)
+       b3OpenCLArray<int> m_leafNodeParentNodes;                //For parent node index, msb(0x80000000) is not set since it is always internal
+       b3OpenCLArray<b3SortData> m_mortonCodesAndAabbIndicies;  //m_key == morton code, m_value == aabb index in m_leafNodeAabbs
+       b3OpenCLArray<b3SapAabb> m_mergedAabb;                   //m_mergedAabb[0] contains the merged AABB of all leaf nodes
+       b3OpenCLArray<b3SapAabb> m_leafNodeAabbs;                //Contains only small AABBs
+
+       //1 element per large AABB, which is not stored in the BVH
+       b3OpenCLArray<b3SapAabb> m_largeAabbs;
+
+public:
+       b3GpuParallelLinearBvh(cl_context context, cl_device_id device, cl_command_queue queue);
+       virtual ~b3GpuParallelLinearBvh();
+
+       ///Must be called before any other function
+       void build(const b3OpenCLArray<b3SapAabb>& worldSpaceAabbs, const b3OpenCLArray<int>& smallAabbIndices,
+                          const b3OpenCLArray<int>& largeAabbIndices);
+
+       ///calculateOverlappingPairs() uses the worldSpaceAabbs parameter of b3GpuParallelLinearBvh::build() as the query AABBs.
+       ///@param out_overlappingPairs The size() of this array is used to determine the max number of pairs.
+       ///If the number of overlapping pairs is < out_overlappingPairs.size(), out_overlappingPairs is resized.
+       void calculateOverlappingPairs(b3OpenCLArray<b3Int4>& out_overlappingPairs);
+
+       ///@param out_numRigidRayPairs Array of length 1; contains the number of detected ray-rigid AABB intersections;
+       ///this value may be greater than out_rayRigidPairs.size() if out_rayRigidPairs is not large enough.
+       ///@param out_rayRigidPairs Contains an array of rays intersecting rigid AABBs; x == ray index, y == rigid body index.
+       ///If the size of this array is insufficient to hold all ray-rigid AABB intersections, additional intersections are discarded.
+       void testRaysAgainstBvhAabbs(const b3OpenCLArray<b3RayInfo>& rays,
+                                                                b3OpenCLArray<int>& out_numRayRigidPairs, b3OpenCLArray<b3Int2>& out_rayRigidPairs);
+
+private:
+       void constructBinaryRadixTree();
+};
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp
new file mode 100644 (file)
index 0000000..62ea7a3
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Initial Author Jackson Lee, 2014
+
+#include "b3GpuParallelLinearBvhBroadphase.h"
+
+b3GpuParallelLinearBvhBroadphase::b3GpuParallelLinearBvhBroadphase(cl_context context, cl_device_id device, cl_command_queue queue) : m_plbvh(context, device, queue),
+
+                                                                                                                                                                                                                                                                         m_overlappingPairsGpu(context, queue),
+
+                                                                                                                                                                                                                                                                         m_aabbsGpu(context, queue),
+                                                                                                                                                                                                                                                                         m_smallAabbsMappingGpu(context, queue),
+                                                                                                                                                                                                                                                                         m_largeAabbsMappingGpu(context, queue)
+{
+}
+
+void b3GpuParallelLinearBvhBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
+{
+       int newAabbIndex = m_aabbsCpu.size();
+
+       b3SapAabb aabb;
+       aabb.m_minVec = aabbMin;
+       aabb.m_maxVec = aabbMax;
+
+       aabb.m_minIndices[3] = userPtr;
+       aabb.m_signedMaxIndices[3] = newAabbIndex;
+
+       m_smallAabbsMappingCpu.push_back(newAabbIndex);
+
+       m_aabbsCpu.push_back(aabb);
+}
+void b3GpuParallelLinearBvhBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
+{
+       int newAabbIndex = m_aabbsCpu.size();
+
+       b3SapAabb aabb;
+       aabb.m_minVec = aabbMin;
+       aabb.m_maxVec = aabbMax;
+
+       aabb.m_minIndices[3] = userPtr;
+       aabb.m_signedMaxIndices[3] = newAabbIndex;
+
+       m_largeAabbsMappingCpu.push_back(newAabbIndex);
+
+       m_aabbsCpu.push_back(aabb);
+}
+
+void b3GpuParallelLinearBvhBroadphase::calculateOverlappingPairs(int maxPairs)
+{
+       //Reconstruct BVH
+       m_plbvh.build(m_aabbsGpu, m_smallAabbsMappingGpu, m_largeAabbsMappingGpu);
+
+       //
+       m_overlappingPairsGpu.resize(maxPairs);
+       m_plbvh.calculateOverlappingPairs(m_overlappingPairsGpu);
+}
+void b3GpuParallelLinearBvhBroadphase::calculateOverlappingPairsHost(int maxPairs)
+{
+       b3Assert(0);  //CPU version not implemented
+}
+
+void b3GpuParallelLinearBvhBroadphase::writeAabbsToGpu()
+{
+       m_aabbsGpu.copyFromHost(m_aabbsCpu);
+       m_smallAabbsMappingGpu.copyFromHost(m_smallAabbsMappingCpu);
+       m_largeAabbsMappingGpu.copyFromHost(m_largeAabbsMappingCpu);
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h
new file mode 100644 (file)
index 0000000..dda0eea
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Initial Author Jackson Lee, 2014
+
+#ifndef B3_GPU_PARALLEL_LINEAR_BVH_BROADPHASE_H
+#define B3_GPU_PARALLEL_LINEAR_BVH_BROADPHASE_H
+
+#include "Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h"
+
+#include "b3GpuParallelLinearBvh.h"
+
+class b3GpuParallelLinearBvhBroadphase : public b3GpuBroadphaseInterface
+{
+       b3GpuParallelLinearBvh m_plbvh;
+
+       b3OpenCLArray<b3Int4> m_overlappingPairsGpu;
+
+       b3OpenCLArray<b3SapAabb> m_aabbsGpu;
+       b3OpenCLArray<int> m_smallAabbsMappingGpu;
+       b3OpenCLArray<int> m_largeAabbsMappingGpu;
+
+       b3AlignedObjectArray<b3SapAabb> m_aabbsCpu;
+       b3AlignedObjectArray<int> m_smallAabbsMappingCpu;
+       b3AlignedObjectArray<int> m_largeAabbsMappingCpu;
+
+public:
+       b3GpuParallelLinearBvhBroadphase(cl_context context, cl_device_id device, cl_command_queue queue);
+       virtual ~b3GpuParallelLinearBvhBroadphase() {}
+
+       virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+       virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+
+       virtual void calculateOverlappingPairs(int maxPairs);
+       virtual void calculateOverlappingPairsHost(int maxPairs);
+
+       //call writeAabbsToGpu after done making all changes (createProxy etc)
+       virtual void writeAabbsToGpu();
+
+       virtual int getNumOverlap() { return m_overlappingPairsGpu.size(); }
+       virtual cl_mem getOverlappingPairBuffer() { return m_overlappingPairsGpu.getBufferCL(); }
+
+       virtual cl_mem getAabbBufferWS() { return m_aabbsGpu.getBufferCL(); }
+       virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU() { return m_aabbsGpu; }
+
+       virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU() { return m_overlappingPairsGpu; }
+       virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU() { return m_smallAabbsMappingGpu; }
+       virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU() { return m_largeAabbsMappingGpu; }
+
+       virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU() { return m_aabbsCpu; }
+
+       static b3GpuBroadphaseInterface* CreateFunc(cl_context context, cl_device_id device, cl_command_queue queue)
+       {
+               return new b3GpuParallelLinearBvhBroadphase(context, device, queue);
+       }
+};
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp
new file mode 100644 (file)
index 0000000..4126d03
--- /dev/null
@@ -0,0 +1,1298 @@
+
+bool searchIncremental3dSapOnGpu = true;
+#include <limits.h>
+#include "b3GpuSapBroadphase.h"
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h"
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "kernels/sapKernels.h"
+
+#include "Bullet3Common/b3MinMax.h"
+
+#define B3_BROADPHASE_SAP_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl"
+
+/*
+       
+       
+       
+       
+       b3OpenCLArray<int> m_pairCount;
+       b3OpenCLArray<b3SapAabb>        m_allAabbsGPU;
+       b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
+       virtual b3OpenCLArray<b3SapAabb>&       getAllAabbsGPU()
+       {
+ return m_allAabbsGPU;
+       }
+       virtual b3AlignedObjectArray<b3SapAabb>&        getAllAabbsCPU()
+       {
+ return m_allAabbsCPU;
+       }
+       b3OpenCLArray<b3Vector3>        m_sum;
+       b3OpenCLArray<b3Vector3>        m_sum2;
+       b3OpenCLArray<b3Vector3>        m_dst;
+       b3OpenCLArray<int>      m_smallAabbsMappingGPU;
+       b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
+       b3OpenCLArray<int>      m_largeAabbsMappingGPU;
+       b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
+       
+       b3OpenCLArray<b3Int4>           m_overlappingPairs;
+       //temporary gpu work memory
+       b3OpenCLArray<b3SortData>       m_gpuSmallSortData;
+       b3OpenCLArray<b3SapAabb>        m_gpuSmallSortedAabbs;
+       class b3PrefixScanFloat4CL*             m_prefixScanFloat4;
+ */
+
+b3GpuSapBroadphase::b3GpuSapBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q, b3GpuSapKernelType kernelType)
+       : m_context(ctx),
+         m_device(device),
+         m_queue(q),
+
+         m_objectMinMaxIndexGPUaxis0(ctx, q),
+         m_objectMinMaxIndexGPUaxis1(ctx, q),
+         m_objectMinMaxIndexGPUaxis2(ctx, q),
+         m_objectMinMaxIndexGPUaxis0prev(ctx, q),
+         m_objectMinMaxIndexGPUaxis1prev(ctx, q),
+         m_objectMinMaxIndexGPUaxis2prev(ctx, q),
+         m_sortedAxisGPU0(ctx, q),
+         m_sortedAxisGPU1(ctx, q),
+         m_sortedAxisGPU2(ctx, q),
+         m_sortedAxisGPU0prev(ctx, q),
+         m_sortedAxisGPU1prev(ctx, q),
+         m_sortedAxisGPU2prev(ctx, q),
+         m_addedHostPairsGPU(ctx, q),
+         m_removedHostPairsGPU(ctx, q),
+         m_addedCountGPU(ctx, q),
+         m_removedCountGPU(ctx, q),
+         m_currentBuffer(-1),
+         m_pairCount(ctx, q),
+         m_allAabbsGPU(ctx, q),
+         m_sum(ctx, q),
+         m_sum2(ctx, q),
+         m_dst(ctx, q),
+         m_smallAabbsMappingGPU(ctx, q),
+         m_largeAabbsMappingGPU(ctx, q),
+         m_overlappingPairs(ctx, q),
+         m_gpuSmallSortData(ctx, q),
+         m_gpuSmallSortedAabbs(ctx, q)
+{
+       const char* sapSrc = sapCL;
+
+       cl_int errNum = 0;
+
+       b3Assert(m_context);
+       b3Assert(m_device);
+       cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, sapSrc, &errNum, "", B3_BROADPHASE_SAP_PATH);
+       b3Assert(errNum == CL_SUCCESS);
+
+       b3Assert(errNum == CL_SUCCESS);
+#ifndef __APPLE__
+       m_prefixScanFloat4 = new b3PrefixScanFloat4CL(m_context, m_device, m_queue);
+#else
+       m_prefixScanFloat4 = 0;
+#endif
+       m_sapKernel = 0;
+
+       switch (kernelType)
+       {
+               case B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU:
+               {
+                       m_sapKernel = 0;
+                       break;
+               }
+               case B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU:
+               {
+                       m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelBruteForce", &errNum, sapProg);
+                       break;
+               }
+
+               case B3_GPU_SAP_KERNEL_ORIGINAL:
+               {
+                       m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelOriginal", &errNum, sapProg);
+                       break;
+               }
+               case B3_GPU_SAP_KERNEL_BARRIER:
+               {
+                       m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelBarrier", &errNum, sapProg);
+                       break;
+               }
+               case B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY:
+               {
+                       m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelLocalSharedMemory", &errNum, sapProg);
+                       break;
+               }
+
+               default:
+               {
+                       m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelLocalSharedMemory", &errNum, sapProg);
+                       b3Error("Unknown 3D GPU SAP provided, fallback to computePairsKernelLocalSharedMemory");
+               }
+       };
+
+       m_sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelTwoArrays", &errNum, sapProg);
+       b3Assert(errNum == CL_SUCCESS);
+
+       m_prepareSumVarianceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "prepareSumVarianceKernel", &errNum, sapProg);
+       b3Assert(errNum == CL_SUCCESS);
+
+       m_flipFloatKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "flipFloatKernel", &errNum, sapProg);
+
+       m_copyAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "copyAabbsKernel", &errNum, sapProg);
+
+       m_scatterKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "scatterKernel", &errNum, sapProg);
+
+       m_sorter = new b3RadixSort32CL(m_context, m_device, m_queue);
+}
+
+b3GpuSapBroadphase::~b3GpuSapBroadphase()
+{
+       delete m_sorter;
+       delete m_prefixScanFloat4;
+
+       clReleaseKernel(m_scatterKernel);
+       clReleaseKernel(m_flipFloatKernel);
+       clReleaseKernel(m_copyAabbsKernel);
+       clReleaseKernel(m_sapKernel);
+       clReleaseKernel(m_sap2Kernel);
+       clReleaseKernel(m_prepareSumVarianceKernel);
+}
+
+/// conservative test for overlap between two aabbs
+static bool TestAabbAgainstAabb2(const b3Vector3& aabbMin1, const b3Vector3& aabbMax1,
+                                                                const b3Vector3& aabbMin2, const b3Vector3& aabbMax2)
+{
+       bool overlap = true;
+       overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
+       overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
+       overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
+       return overlap;
+}
+
+//http://stereopsis.com/radix.html
+static unsigned int FloatFlip(float fl)
+{
+       unsigned int f = *(unsigned int*)&fl;
+       unsigned int mask = -(int)(f >> 31) | 0x80000000;
+       return f ^ mask;
+};
+
+void b3GpuSapBroadphase::init3dSap()
+{
+       if (m_currentBuffer < 0)
+       {
+               m_allAabbsGPU.copyToHost(m_allAabbsCPU);
+
+               m_currentBuffer = 0;
+               for (int axis = 0; axis < 3; axis++)
+               {
+                       for (int buf = 0; buf < 2; buf++)
+                       {
+                               int totalNumAabbs = m_allAabbsCPU.size();
+                               int numEndPoints = 2 * totalNumAabbs;
+                               m_sortedAxisCPU[axis][buf].resize(numEndPoints);
+
+                               if (buf == m_currentBuffer)
+                               {
+                                       for (int i = 0; i < totalNumAabbs; i++)
+                                       {
+                                               m_sortedAxisCPU[axis][buf][i * 2].m_key = FloatFlip(m_allAabbsCPU[i].m_min[axis]) - 1;
+                                               m_sortedAxisCPU[axis][buf][i * 2].m_value = i * 2;
+                                               m_sortedAxisCPU[axis][buf][i * 2 + 1].m_key = FloatFlip(m_allAabbsCPU[i].m_max[axis]) + 1;
+                                               m_sortedAxisCPU[axis][buf][i * 2 + 1].m_value = i * 2 + 1;
+                                       }
+                               }
+                       }
+               }
+
+               for (int axis = 0; axis < 3; axis++)
+               {
+                       m_sorter->executeHost(m_sortedAxisCPU[axis][m_currentBuffer]);
+               }
+
+               for (int axis = 0; axis < 3; axis++)
+               {
+                       //int totalNumAabbs = m_allAabbsCPU.size();
+                       int numEndPoints = m_sortedAxisCPU[axis][m_currentBuffer].size();
+                       m_objectMinMaxIndexCPU[axis][m_currentBuffer].resize(numEndPoints);
+                       for (int i = 0; i < numEndPoints; i++)
+                       {
+                               int destIndex = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
+                               int newDest = destIndex / 2;
+                               if (destIndex & 1)
+                               {
+                                       m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].y = i;
+                               }
+                               else
+                               {
+                                       m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].x = i;
+                               }
+                       }
+               }
+       }
+}
+
+static bool b3PairCmp(const b3Int4& p, const b3Int4& q)
+{
+       return ((p.x < q.x) || ((p.x == q.x) && (p.y < q.y)));
+}
+
+static bool operator==(const b3Int4& a, const b3Int4& b)
+{
+       return a.x == b.x && a.y == b.y;
+};
+
+static bool operator<(const b3Int4& a, const b3Int4& b)
+{
+       return a.x < b.x || (a.x == b.x && a.y < b.y);
+};
+
+static bool operator>(const b3Int4& a, const b3Int4& b)
+{
+       return a.x > b.x || (a.x == b.x && a.y > b.y);
+};
+
+b3AlignedObjectArray<b3Int4> addedHostPairs;
+b3AlignedObjectArray<b3Int4> removedHostPairs;
+
+b3AlignedObjectArray<b3SapAabb> preAabbs;
+
+void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
+{
+       //static int framepje = 0;
+       //printf("framepje=%d\n",framepje++);
+
+       B3_PROFILE("calculateOverlappingPairsHostIncremental3Sap");
+
+       addedHostPairs.resize(0);
+       removedHostPairs.resize(0);
+
+       b3Assert(m_currentBuffer >= 0);
+
+       {
+               preAabbs.resize(m_allAabbsCPU.size());
+               for (int i = 0; i < preAabbs.size(); i++)
+               {
+                       preAabbs[i] = m_allAabbsCPU[i];
+               }
+       }
+
+       if (m_currentBuffer < 0)
+               return;
+       {
+               B3_PROFILE("m_allAabbsGPU.copyToHost");
+               m_allAabbsGPU.copyToHost(m_allAabbsCPU);
+       }
+
+       b3AlignedObjectArray<b3Int4> allPairs;
+       {
+               B3_PROFILE("m_overlappingPairs.copyToHost");
+               m_overlappingPairs.copyToHost(allPairs);
+       }
+       if (0)
+       {
+               {
+                       printf("ab[40].min=%f,%f,%f,ab[40].max=%f,%f,%f\n",
+                                  m_allAabbsCPU[40].m_min[0], m_allAabbsCPU[40].m_min[1], m_allAabbsCPU[40].m_min[2],
+                                  m_allAabbsCPU[40].m_max[0], m_allAabbsCPU[40].m_max[1], m_allAabbsCPU[40].m_max[2]);
+               }
+
+               {
+                       printf("ab[53].min=%f,%f,%f,ab[53].max=%f,%f,%f\n",
+                                  m_allAabbsCPU[53].m_min[0], m_allAabbsCPU[53].m_min[1], m_allAabbsCPU[53].m_min[2],
+                                  m_allAabbsCPU[53].m_max[0], m_allAabbsCPU[53].m_max[1], m_allAabbsCPU[53].m_max[2]);
+               }
+
+               {
+                       b3Int4 newPair;
+                       newPair.x = 40;
+                       newPair.y = 53;
+                       int index = allPairs.findBinarySearch(newPair);
+                       printf("hasPair(40,53)=%d out of %d\n", index, allPairs.size());
+
+                       {
+                               int overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[40].m_min, (const b3Vector3&)m_allAabbsCPU[40].m_max, (const b3Vector3&)m_allAabbsCPU[53].m_min, (const b3Vector3&)m_allAabbsCPU[53].m_max);
+                               printf("overlap=%d\n", overlap);
+                       }
+
+                       if (preAabbs.size())
+                       {
+                               int prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[40].m_min, (const b3Vector3&)preAabbs[40].m_max, (const b3Vector3&)preAabbs[53].m_min, (const b3Vector3&)preAabbs[53].m_max);
+                               printf("prevoverlap=%d\n", prevOverlap);
+                       }
+                       else
+                       {
+                               printf("unknown prevoverlap\n");
+                       }
+               }
+       }
+
+       if (0)
+       {
+               for (int i = 0; i < m_allAabbsCPU.size(); i++)
+               {
+                       //printf("aabb[%d] min=%f,%f,%f max=%f,%f,%f\n",i,m_allAabbsCPU[i].m_min[0],m_allAabbsCPU[i].m_min[1],m_allAabbsCPU[i].m_min[2],                        m_allAabbsCPU[i].m_max[0],m_allAabbsCPU[i].m_max[1],m_allAabbsCPU[i].m_max[2]);
+               }
+
+               for (int axis = 0; axis < 3; axis++)
+               {
+                       for (int buf = 0; buf < 2; buf++)
+                       {
+                               b3Assert(m_sortedAxisCPU[axis][buf].size() == m_allAabbsCPU.size() * 2);
+                       }
+               }
+       }
+
+       m_currentBuffer = 1 - m_currentBuffer;
+
+       int totalNumAabbs = m_allAabbsCPU.size();
+
+       {
+               B3_PROFILE("assign m_sortedAxisCPU(FloatFlip)");
+               for (int i = 0; i < totalNumAabbs; i++)
+               {
+                       unsigned int keyMin[3];
+                       unsigned int keyMax[3];
+                       for (int axis = 0; axis < 3; axis++)
+                       {
+                               float vmin = m_allAabbsCPU[i].m_min[axis];
+                               float vmax = m_allAabbsCPU[i].m_max[axis];
+                               keyMin[axis] = FloatFlip(vmin);
+                               keyMax[axis] = FloatFlip(vmax);
+
+                               m_sortedAxisCPU[axis][m_currentBuffer][i * 2].m_key = keyMin[axis] - 1;
+                               m_sortedAxisCPU[axis][m_currentBuffer][i * 2].m_value = i * 2;
+                               m_sortedAxisCPU[axis][m_currentBuffer][i * 2 + 1].m_key = keyMax[axis] + 1;
+                               m_sortedAxisCPU[axis][m_currentBuffer][i * 2 + 1].m_value = i * 2 + 1;
+                       }
+                       //printf("aabb[%d] min=%u,%u,%u max %u,%u,%u\n", i,keyMin[0],keyMin[1],keyMin[2],keyMax[0],keyMax[1],keyMax[2]);
+               }
+       }
+
+       {
+               B3_PROFILE("sort m_sortedAxisCPU");
+               for (int axis = 0; axis < 3; axis++)
+                       m_sorter->executeHost(m_sortedAxisCPU[axis][m_currentBuffer]);
+       }
+
+#if 0
+       if (0)
+       {
+               for (int axis=0;axis<3;axis++)
+               {
+                       //printf("axis %d\n",axis);
+                       for (int i=0;i<m_sortedAxisCPU[axis][m_currentBuffer].size();i++)
+                       {
+                               //int key = m_sortedAxisCPU[axis][m_currentBuffer][i].m_key;
+                               //int value = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
+                               //printf("[%d]=%d\n",i,value);
+                       }
+
+               }
+       }
+#endif
+
+       {
+               B3_PROFILE("assign m_objectMinMaxIndexCPU");
+               for (int axis = 0; axis < 3; axis++)
+               {
+                       int totalNumAabbs = m_allAabbsCPU.size();
+                       int numEndPoints = m_sortedAxisCPU[axis][m_currentBuffer].size();
+                       m_objectMinMaxIndexCPU[axis][m_currentBuffer].resize(totalNumAabbs);
+                       for (int i = 0; i < numEndPoints; i++)
+                       {
+                               int destIndex = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
+                               int newDest = destIndex / 2;
+                               if (destIndex & 1)
+                               {
+                                       m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].y = i;
+                               }
+                               else
+                               {
+                                       m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].x = i;
+                               }
+                       }
+               }
+       }
+
+#if 0
+       if (0)
+       {       
+               printf("==========================\n");
+               for (int axis=0;axis<3;axis++)
+               {
+                       unsigned int curMinIndex40 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][40].x;
+                       unsigned int curMaxIndex40 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][40].y;
+                       unsigned int prevMaxIndex40 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][40].y;
+                       unsigned int prevMinIndex40 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][40].x;
+
+                       int dmin40 = curMinIndex40 - prevMinIndex40;
+                       int dmax40 = curMinIndex40 - prevMinIndex40;
+                       printf("axis %d curMinIndex40=%d prevMinIndex40=%d\n",axis,curMinIndex40, prevMinIndex40);
+                       printf("axis %d curMaxIndex40=%d prevMaxIndex40=%d\n",axis,curMaxIndex40, prevMaxIndex40);
+               }
+               printf(".........................\n");
+               for (int axis=0;axis<3;axis++)
+               {
+                       unsigned int curMinIndex53 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][53].x;
+                       unsigned int curMaxIndex53 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][53].y;
+                       unsigned int prevMaxIndex53 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][53].y;
+                       unsigned int prevMinIndex53 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][53].x;
+
+                       int dmin40 = curMinIndex53 - prevMinIndex53;
+                       int dmax40 = curMinIndex53 - prevMinIndex53;
+                       printf("axis %d curMinIndex53=%d prevMinIndex53=%d\n",axis,curMinIndex53, prevMinIndex53);
+                       printf("axis %d curMaxIndex53=%d prevMaxIndex53=%d\n",axis,curMaxIndex53, prevMaxIndex53);
+               }
+
+       }
+#endif
+
+       int a = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
+       int b = m_objectMinMaxIndexCPU[1][m_currentBuffer].size();
+       int c = m_objectMinMaxIndexCPU[2][m_currentBuffer].size();
+       b3Assert(a == b);
+       b3Assert(b == c);
+       /*
+       if (searchIncremental3dSapOnGpu)
+       {
+               B3_PROFILE("computePairsIncremental3dSapKernelGPU");
+               int numObjects = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
+               int maxCapacity = 1024*1024;
+               {
+                       B3_PROFILE("copy from host");
+                       m_objectMinMaxIndexGPUaxis0.copyFromHost(m_objectMinMaxIndexCPU[0][m_currentBuffer]);
+                       m_objectMinMaxIndexGPUaxis1.copyFromHost(m_objectMinMaxIndexCPU[1][m_currentBuffer]);
+                       m_objectMinMaxIndexGPUaxis2.copyFromHost(m_objectMinMaxIndexCPU[2][m_currentBuffer]);
+                       m_objectMinMaxIndexGPUaxis0prev.copyFromHost(m_objectMinMaxIndexCPU[0][1-m_currentBuffer]);
+                       m_objectMinMaxIndexGPUaxis1prev.copyFromHost(m_objectMinMaxIndexCPU[1][1-m_currentBuffer]);
+                       m_objectMinMaxIndexGPUaxis2prev.copyFromHost(m_objectMinMaxIndexCPU[2][1-m_currentBuffer]);
+
+                       m_sortedAxisGPU0.copyFromHost(m_sortedAxisCPU[0][m_currentBuffer]);
+                       m_sortedAxisGPU1.copyFromHost(m_sortedAxisCPU[1][m_currentBuffer]);
+                       m_sortedAxisGPU2.copyFromHost(m_sortedAxisCPU[2][m_currentBuffer]);
+                       m_sortedAxisGPU0prev.copyFromHost(m_sortedAxisCPU[0][1-m_currentBuffer]);
+                       m_sortedAxisGPU1prev.copyFromHost(m_sortedAxisCPU[1][1-m_currentBuffer]);
+                       m_sortedAxisGPU2prev.copyFromHost(m_sortedAxisCPU[2][1-m_currentBuffer]);
+
+               
+                       m_addedHostPairsGPU.resize(maxCapacity);
+                       m_removedHostPairsGPU.resize(maxCapacity);
+
+                       m_addedCountGPU.resize(0);
+                       m_addedCountGPU.push_back(0);
+                       m_removedCountGPU.resize(0);
+                       m_removedCountGPU.push_back(0);
+               }
+
+               {
+                       B3_PROFILE("launch1D");
+                       b3LauncherCL launcher(m_queue,  m_computePairsIncremental3dSapKernel,"m_computePairsIncremental3dSapKernel");
+                       launcher.setBuffer(m_objectMinMaxIndexGPUaxis0.getBufferCL());
+                       launcher.setBuffer(m_objectMinMaxIndexGPUaxis1.getBufferCL());
+                       launcher.setBuffer(m_objectMinMaxIndexGPUaxis2.getBufferCL());
+                       launcher.setBuffer(m_objectMinMaxIndexGPUaxis0prev.getBufferCL());
+                       launcher.setBuffer(m_objectMinMaxIndexGPUaxis1prev.getBufferCL());
+                       launcher.setBuffer(m_objectMinMaxIndexGPUaxis2prev.getBufferCL());
+
+                       launcher.setBuffer(m_sortedAxisGPU0.getBufferCL());
+                       launcher.setBuffer(m_sortedAxisGPU1.getBufferCL());
+                       launcher.setBuffer(m_sortedAxisGPU2.getBufferCL());
+                       launcher.setBuffer(m_sortedAxisGPU0prev.getBufferCL());
+                       launcher.setBuffer(m_sortedAxisGPU1prev.getBufferCL());
+                       launcher.setBuffer(m_sortedAxisGPU2prev.getBufferCL());
+
+               
+                       launcher.setBuffer(m_addedHostPairsGPU.getBufferCL());
+                       launcher.setBuffer(m_removedHostPairsGPU.getBufferCL());
+                       launcher.setBuffer(m_addedCountGPU.getBufferCL());
+                       launcher.setBuffer(m_removedCountGPU.getBufferCL());
+                       launcher.setConst(maxCapacity);
+                       launcher.setConst( numObjects);
+                       launcher.launch1D( numObjects);
+                       clFinish(m_queue);
+               }
+
+               {
+                       B3_PROFILE("copy to host");
+                       int addedCountGPU = m_addedCountGPU.at(0);
+                       m_addedHostPairsGPU.resize(addedCountGPU);
+                       m_addedHostPairsGPU.copyToHost(addedHostPairs);
+
+                       //printf("addedCountGPU=%d\n",addedCountGPU);
+                       int removedCountGPU = m_removedCountGPU.at(0);
+                       m_removedHostPairsGPU.resize(removedCountGPU);
+                       m_removedHostPairsGPU.copyToHost(removedHostPairs);
+                       //printf("removedCountGPU=%d\n",removedCountGPU);
+
+               }
+
+
+
+       } 
+       else
+       */
+       {
+               int numObjects = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
+
+               B3_PROFILE("actual search");
+               for (int i = 0; i < numObjects; i++)
+               {
+                       //int numObjects = m_objectMinMaxIndexCPU[axis][m_currentBuffer].size();
+                       //int checkObjects[]={40,53};
+                       //int numCheckObjects = sizeof(checkObjects)/sizeof(int);
+
+                       //for (int a=0;a<numCheckObjects ;a++)
+
+                       for (int axis = 0; axis < 3; axis++)
+                       {
+                               //int i = checkObjects[a];
+
+                               unsigned int curMinIndex = m_objectMinMaxIndexCPU[axis][m_currentBuffer][i].x;
+                               unsigned int curMaxIndex = m_objectMinMaxIndexCPU[axis][m_currentBuffer][i].y;
+                               unsigned int prevMinIndex = m_objectMinMaxIndexCPU[axis][1 - m_currentBuffer][i].x;
+                               int dmin = curMinIndex - prevMinIndex;
+
+                               unsigned int prevMaxIndex = m_objectMinMaxIndexCPU[axis][1 - m_currentBuffer][i].y;
+
+                               int dmax = curMaxIndex - prevMaxIndex;
+                               if (dmin != 0)
+                               {
+                                       //printf("for object %d, dmin=%d\n",i,dmin);
+                               }
+                               if (dmax != 0)
+                               {
+                                       //printf("for object %d, dmax=%d\n",i,dmax);
+                               }
+                               for (int otherbuffer = 0; otherbuffer < 2; otherbuffer++)
+                               {
+                                       if (dmin != 0)
+                                       {
+                                               int stepMin = dmin < 0 ? -1 : 1;
+                                               for (int j = prevMinIndex; j != curMinIndex; j += stepMin)
+                                               {
+                                                       int otherIndex2 = m_sortedAxisCPU[axis][otherbuffer][j].y;
+                                                       int otherIndex = otherIndex2 / 2;
+                                                       if (otherIndex != i)
+                                                       {
+                                                               bool otherIsMax = ((otherIndex2 & 1) != 0);
+
+                                                               if (otherIsMax)
+                                                               {
+                                                                       //bool overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[i].m_min, (const b3Vector3&)m_allAabbsCPU[i].m_max,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_min,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_max);
+                                                                       //bool prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[i].m_min, (const b3Vector3&)preAabbs[i].m_max,(const b3Vector3&)preAabbs[otherIndex].m_min,(const b3Vector3&)preAabbs[otherIndex].m_max);
+
+                                                                       bool overlap = true;
+
+                                                                       for (int ax = 0; ax < 3; ax++)
+                                                                       {
+                                                                               if ((m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].y) ||
+                                                                                       (m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].x))
+                                                                                       overlap = false;
+                                                                       }
+
+                                                                       //      b3Assert(overlap2==overlap);
+
+                                                                       bool prevOverlap = true;
+
+                                                                       for (int ax = 0; ax < 3; ax++)
+                                                                       {
+                                                                               if ((m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].y) ||
+                                                                                       (m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].x))
+                                                                                       prevOverlap = false;
+                                                                       }
+
+                                                                       //b3Assert(overlap==overlap2);
+
+                                                                       if (dmin < 0)
+                                                                       {
+                                                                               if (overlap && !prevOverlap)
+                                                                               {
+                                                                                       //add a pair
+                                                                                       b3Int4 newPair;
+                                                                                       if (i <= otherIndex)
+                                                                                       {
+                                                                                               newPair.x = i;
+                                                                                               newPair.y = otherIndex;
+                                                                                       }
+                                                                                       else
+                                                                                       {
+                                                                                               newPair.x = otherIndex;
+                                                                                               newPair.y = i;
+                                                                                       }
+                                                                                       addedHostPairs.push_back(newPair);
+                                                                               }
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               if (!overlap && prevOverlap)
+                                                                               {
+                                                                                       //remove a pair
+                                                                                       b3Int4 removedPair;
+                                                                                       if (i <= otherIndex)
+                                                                                       {
+                                                                                               removedPair.x = i;
+                                                                                               removedPair.y = otherIndex;
+                                                                                       }
+                                                                                       else
+                                                                                       {
+                                                                                               removedPair.x = otherIndex;
+                                                                                               removedPair.y = i;
+                                                                                       }
+                                                                                       removedHostPairs.push_back(removedPair);
+                                                                               }
+                                                                       }  //otherisMax
+                                                               }      //if (dmin<0)
+                                                       }          //if (otherIndex!=i)
+                                               }              //for (int j=
+                                       }
+
+                                       if (dmax != 0)
+                                       {
+                                               int stepMax = dmax < 0 ? -1 : 1;
+                                               for (int j = prevMaxIndex; j != curMaxIndex; j += stepMax)
+                                               {
+                                                       int otherIndex2 = m_sortedAxisCPU[axis][otherbuffer][j].y;
+                                                       int otherIndex = otherIndex2 / 2;
+                                                       if (otherIndex != i)
+                                                       {
+                                                               //bool otherIsMin = ((otherIndex2&1)==0);
+                                                               //if (otherIsMin)
+                                                               {
+                                                                       //bool overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[i].m_min, (const b3Vector3&)m_allAabbsCPU[i].m_max,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_min,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_max);
+                                                                       //bool prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[i].m_min, (const b3Vector3&)preAabbs[i].m_max,(const b3Vector3&)preAabbs[otherIndex].m_min,(const b3Vector3&)preAabbs[otherIndex].m_max);
+
+                                                                       bool overlap = true;
+
+                                                                       for (int ax = 0; ax < 3; ax++)
+                                                                       {
+                                                                               if ((m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].y) ||
+                                                                                       (m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].x))
+                                                                                       overlap = false;
+                                                                       }
+                                                                       //b3Assert(overlap2==overlap);
+
+                                                                       bool prevOverlap = true;
+
+                                                                       for (int ax = 0; ax < 3; ax++)
+                                                                       {
+                                                                               if ((m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].y) ||
+                                                                                       (m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].x))
+                                                                                       prevOverlap = false;
+                                                                       }
+
+                                                                       if (dmax > 0)
+                                                                       {
+                                                                               if (overlap && !prevOverlap)
+                                                                               {
+                                                                                       //add a pair
+                                                                                       b3Int4 newPair;
+                                                                                       if (i <= otherIndex)
+                                                                                       {
+                                                                                               newPair.x = i;
+                                                                                               newPair.y = otherIndex;
+                                                                                       }
+                                                                                       else
+                                                                                       {
+                                                                                               newPair.x = otherIndex;
+                                                                                               newPair.y = i;
+                                                                                       }
+                                                                                       addedHostPairs.push_back(newPair);
+                                                                               }
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               if (!overlap && prevOverlap)
+                                                                               {
+                                                                                       //if (otherIndex2&1==0) -> min?
+                                                                                       //remove a pair
+                                                                                       b3Int4 removedPair;
+                                                                                       if (i <= otherIndex)
+                                                                                       {
+                                                                                               removedPair.x = i;
+                                                                                               removedPair.y = otherIndex;
+                                                                                       }
+                                                                                       else
+                                                                                       {
+                                                                                               removedPair.x = otherIndex;
+                                                                                               removedPair.y = i;
+                                                                                       }
+                                                                                       removedHostPairs.push_back(removedPair);
+                                                                               }
+                                                                       }
+
+                                                               }  //if (dmin<0)
+                                                       }      //if (otherIndex!=i)
+                                               }          //for (int j=
+                                       }
+                               }  //for (int otherbuffer
+                       }      //for (int axis=0;
+               }          //for (int i=0;i<numObjects
+       }
+
+       //remove duplicates and add/remove then to existing m_overlappingPairs
+
+       {
+               {
+                       B3_PROFILE("sort allPairs");
+                       allPairs.quickSort(b3PairCmp);
+               }
+               {
+                       B3_PROFILE("sort addedHostPairs");
+                       addedHostPairs.quickSort(b3PairCmp);
+               }
+               {
+                       B3_PROFILE("sort removedHostPairs");
+                       removedHostPairs.quickSort(b3PairCmp);
+               }
+       }
+
+       b3Int4 prevPair;
+       prevPair.x = -1;
+       prevPair.y = -1;
+
+       int uniqueRemovedPairs = 0;
+
+       b3AlignedObjectArray<int> removedPositions;
+
+       {
+               B3_PROFILE("actual removing");
+               for (int i = 0; i < removedHostPairs.size(); i++)
+               {
+                       b3Int4 removedPair = removedHostPairs[i];
+                       if ((removedPair.x != prevPair.x) || (removedPair.y != prevPair.y))
+                       {
+                               int index1 = allPairs.findBinarySearch(removedPair);
+
+                               //#ifdef _DEBUG
+
+                               int index2 = allPairs.findLinearSearch(removedPair);
+                               b3Assert(index1 == index2);
+
+                               //b3Assert(index1!=allPairs.size());
+                               if (index1 < allPairs.size())
+                               //#endif//_DEBUG
+                               {
+                                       uniqueRemovedPairs++;
+                                       removedPositions.push_back(index1);
+                                       {
+                                               //printf("framepje(%d) remove pair(%d):%d,%d\n",framepje,i,removedPair.x,removedPair.y);
+                                       }
+                               }
+                       }
+                       prevPair = removedPair;
+               }
+
+               if (uniqueRemovedPairs)
+               {
+                       for (int i = 0; i < removedPositions.size(); i++)
+                       {
+                               allPairs[removedPositions[i]].x = INT_MAX;
+                               allPairs[removedPositions[i]].y = INT_MAX;
+                       }
+                       allPairs.quickSort(b3PairCmp);
+                       allPairs.resize(allPairs.size() - uniqueRemovedPairs);
+               }
+       }
+       //if (uniqueRemovedPairs)
+       //      printf("uniqueRemovedPairs=%d\n",uniqueRemovedPairs);
+       //printf("removedHostPairs.size = %d\n",removedHostPairs.size());
+
+       prevPair.x = -1;
+       prevPair.y = -1;
+
+       int uniqueAddedPairs = 0;
+       b3AlignedObjectArray<b3Int4> actualAddedPairs;
+
+       {
+               B3_PROFILE("actual adding");
+               for (int i = 0; i < addedHostPairs.size(); i++)
+               {
+                       b3Int4 newPair = addedHostPairs[i];
+                       if ((newPair.x != prevPair.x) || (newPair.y != prevPair.y))
+                       {
+                               //#ifdef _DEBUG
+                               int index1 = allPairs.findBinarySearch(newPair);
+
+                               int index2 = allPairs.findLinearSearch(newPair);
+                               b3Assert(index1 == index2);
+
+                               b3Assert(index1 == allPairs.size());
+                               if (index1 != allPairs.size())
+                               {
+                                       printf("??\n");
+                               }
+
+                               if (index1 == allPairs.size())
+                               //#endif //_DEBUG
+                               {
+                                       uniqueAddedPairs++;
+                                       actualAddedPairs.push_back(newPair);
+                               }
+                       }
+                       prevPair = newPair;
+               }
+               for (int i = 0; i < actualAddedPairs.size(); i++)
+               {
+                       //printf("framepje (%d), new pair(%d):%d,%d\n",framepje,i,actualAddedPairs[i].x,actualAddedPairs[i].y);
+                       allPairs.push_back(actualAddedPairs[i]);
+               }
+       }
+
+       //if (uniqueAddedPairs)
+       //      printf("uniqueAddedPairs=%d\n", uniqueAddedPairs);
+
+       {
+               B3_PROFILE("m_overlappingPairs.copyFromHost");
+               m_overlappingPairs.copyFromHost(allPairs);
+       }
+}
+
+void b3GpuSapBroadphase::calculateOverlappingPairsHost(int maxPairs)
+{
+       //test
+       //      if (m_currentBuffer>=0)
+       //      return calculateOverlappingPairsHostIncremental3Sap();
+
+       b3Assert(m_allAabbsCPU.size() == m_allAabbsGPU.size());
+       m_allAabbsGPU.copyToHost(m_allAabbsCPU);
+
+       int axis = 0;
+       {
+               B3_PROFILE("CPU compute best variance axis");
+               b3Vector3 s = b3MakeVector3(0, 0, 0), s2 = b3MakeVector3(0, 0, 0);
+               int numRigidBodies = m_smallAabbsMappingCPU.size();
+
+               for (int i = 0; i < numRigidBodies; i++)
+               {
+                       b3SapAabb aabb = this->m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
+
+                       b3Vector3 maxAabb = b3MakeVector3(aabb.m_max[0], aabb.m_max[1], aabb.m_max[2]);
+                       b3Vector3 minAabb = b3MakeVector3(aabb.m_min[0], aabb.m_min[1], aabb.m_min[2]);
+                       b3Vector3 centerAabb = (maxAabb + minAabb) * 0.5f;
+
+                       s += centerAabb;
+                       s2 += centerAabb * centerAabb;
+               }
+               b3Vector3 v = s2 - (s * s) / (float)numRigidBodies;
+
+               if (v[1] > v[0])
+                       axis = 1;
+               if (v[2] > v[axis])
+                       axis = 2;
+       }
+
+       b3AlignedObjectArray<b3Int4> hostPairs;
+
+       {
+               int numSmallAabbs = m_smallAabbsMappingCPU.size();
+               for (int i = 0; i < numSmallAabbs; i++)
+               {
+                       b3SapAabb smallAabbi = m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
+                       //float reference = smallAabbi.m_max[axis];
+
+                       for (int j = i + 1; j < numSmallAabbs; j++)
+                       {
+                               b3SapAabb smallAabbj = m_allAabbsCPU[m_smallAabbsMappingCPU[j]];
+
+                               if (TestAabbAgainstAabb2((b3Vector3&)smallAabbi.m_min, (b3Vector3&)smallAabbi.m_max,
+                                                                                (b3Vector3&)smallAabbj.m_min, (b3Vector3&)smallAabbj.m_max))
+                               {
+                                       b3Int4 pair;
+                                       int a = smallAabbi.m_minIndices[3];
+                                       int b = smallAabbj.m_minIndices[3];
+                                       if (a <= b)
+                                       {
+                                               pair.x = a;  //store the original index in the unsorted aabb array
+                                               pair.y = b;
+                                       }
+                                       else
+                                       {
+                                               pair.x = b;  //store the original index in the unsorted aabb array
+                                               pair.y = a;
+                                       }
+                                       hostPairs.push_back(pair);
+                               }
+                       }
+               }
+       }
+
+       {
+               int numSmallAabbs = m_smallAabbsMappingCPU.size();
+               for (int i = 0; i < numSmallAabbs; i++)
+               {
+                       b3SapAabb smallAabbi = m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
+
+                       //float reference = smallAabbi.m_max[axis];
+                       int numLargeAabbs = m_largeAabbsMappingCPU.size();
+
+                       for (int j = 0; j < numLargeAabbs; j++)
+                       {
+                               b3SapAabb largeAabbj = m_allAabbsCPU[m_largeAabbsMappingCPU[j]];
+                               if (TestAabbAgainstAabb2((b3Vector3&)smallAabbi.m_min, (b3Vector3&)smallAabbi.m_max,
+                                                                                (b3Vector3&)largeAabbj.m_min, (b3Vector3&)largeAabbj.m_max))
+                               {
+                                       b3Int4 pair;
+                                       int a = largeAabbj.m_minIndices[3];
+                                       int b = smallAabbi.m_minIndices[3];
+                                       if (a <= b)
+                                       {
+                                               pair.x = a;
+                                               pair.y = b;  //store the original index in the unsorted aabb array
+                                       }
+                                       else
+                                       {
+                                               pair.x = b;
+                                               pair.y = a;  //store the original index in the unsorted aabb array
+                                       }
+
+                                       hostPairs.push_back(pair);
+                               }
+                       }
+               }
+       }
+
+       if (hostPairs.size() > maxPairs)
+       {
+               hostPairs.resize(maxPairs);
+       }
+
+       if (hostPairs.size())
+       {
+               m_overlappingPairs.copyFromHost(hostPairs);
+       }
+       else
+       {
+               m_overlappingPairs.resize(0);
+       }
+
+       //init3dSap();
+}
+
+void b3GpuSapBroadphase::reset()
+{
+       m_allAabbsGPU.resize(0);
+       m_allAabbsCPU.resize(0);
+
+       m_smallAabbsMappingGPU.resize(0);
+       m_smallAabbsMappingCPU.resize(0);
+
+       m_pairCount.resize(0);
+
+       m_largeAabbsMappingGPU.resize(0);
+       m_largeAabbsMappingCPU.resize(0);
+}
+
+void b3GpuSapBroadphase::calculateOverlappingPairs(int maxPairs)
+{
+       if (m_sapKernel == 0)
+       {
+               calculateOverlappingPairsHost(maxPairs);
+               return;
+       }
+
+       //if (m_currentBuffer>=0)
+       //      return calculateOverlappingPairsHostIncremental3Sap();
+
+       //calculateOverlappingPairsHost(maxPairs);
+
+       B3_PROFILE("GPU 1-axis SAP calculateOverlappingPairs");
+
+       int axis = 0;
+
+       {
+               //bool syncOnHost = false;
+
+               int numSmallAabbs = m_smallAabbsMappingCPU.size();
+               if (m_prefixScanFloat4 && numSmallAabbs)
+               {
+                       B3_PROFILE("GPU compute best variance axis");
+
+                       if (m_dst.size() != (numSmallAabbs + 1))
+                       {
+                               m_dst.resize(numSmallAabbs + 128);
+                               m_sum.resize(numSmallAabbs + 128);
+                               m_sum2.resize(numSmallAabbs + 128);
+                               m_sum.at(numSmallAabbs) = b3MakeVector3(0, 0, 0);   //slow?
+                               m_sum2.at(numSmallAabbs) = b3MakeVector3(0, 0, 0);  //slow?
+                       }
+
+                       b3LauncherCL launcher(m_queue, m_prepareSumVarianceKernel, "m_prepareSumVarianceKernel");
+                       launcher.setBuffer(m_allAabbsGPU.getBufferCL());
+
+                       launcher.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
+                       launcher.setBuffer(m_sum.getBufferCL());
+                       launcher.setBuffer(m_sum2.getBufferCL());
+                       launcher.setConst(numSmallAabbs);
+                       int num = numSmallAabbs;
+                       launcher.launch1D(num);
+
+                       b3Vector3 s;
+                       b3Vector3 s2;
+                       m_prefixScanFloat4->execute(m_sum, m_dst, numSmallAabbs + 1, &s);
+                       m_prefixScanFloat4->execute(m_sum2, m_dst, numSmallAabbs + 1, &s2);
+
+                       b3Vector3 v = s2 - (s * s) / (float)numSmallAabbs;
+
+                       if (v[1] > v[0])
+                               axis = 1;
+                       if (v[2] > v[axis])
+                               axis = 2;
+               }
+
+               m_gpuSmallSortData.resize(numSmallAabbs);
+
+#if 1
+               if (m_smallAabbsMappingGPU.size())
+               {
+                       B3_PROFILE("flipFloatKernel");
+                       b3BufferInfoCL bInfo[] = {
+                               b3BufferInfoCL(m_allAabbsGPU.getBufferCL(), true),
+                               b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL(), true),
+                               b3BufferInfoCL(m_gpuSmallSortData.getBufferCL())};
+                       b3LauncherCL launcher(m_queue, m_flipFloatKernel, "m_flipFloatKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numSmallAabbs);
+                       launcher.setConst(axis);
+
+                       int num = numSmallAabbs;
+                       launcher.launch1D(num);
+                       clFinish(m_queue);
+               }
+
+               if (m_gpuSmallSortData.size())
+               {
+                       B3_PROFILE("gpu radix sort");
+                       m_sorter->execute(m_gpuSmallSortData);
+                       clFinish(m_queue);
+               }
+
+               m_gpuSmallSortedAabbs.resize(numSmallAabbs);
+               if (numSmallAabbs)
+               {
+                       B3_PROFILE("scatterKernel");
+
+                       b3BufferInfoCL bInfo[] = {
+                               b3BufferInfoCL(m_allAabbsGPU.getBufferCL(), true),
+                               b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL(), true),
+                               b3BufferInfoCL(m_gpuSmallSortData.getBufferCL(), true),
+                               b3BufferInfoCL(m_gpuSmallSortedAabbs.getBufferCL())};
+                       b3LauncherCL launcher(m_queue, m_scatterKernel, "m_scatterKernel ");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numSmallAabbs);
+                       int num = numSmallAabbs;
+                       launcher.launch1D(num);
+                       clFinish(m_queue);
+               }
+
+               m_overlappingPairs.resize(maxPairs);
+
+               m_pairCount.resize(0);
+               m_pairCount.push_back(0);
+               int numPairs = 0;
+
+               {
+                       int numLargeAabbs = m_largeAabbsMappingGPU.size();
+                       if (numLargeAabbs && numSmallAabbs)
+                       {
+                               //@todo
+                               B3_PROFILE("sap2Kernel");
+                               b3BufferInfoCL bInfo[] = {
+                                       b3BufferInfoCL(m_allAabbsGPU.getBufferCL()),
+                                       b3BufferInfoCL(m_largeAabbsMappingGPU.getBufferCL()),
+                                       b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL()),
+                                       b3BufferInfoCL(m_overlappingPairs.getBufferCL()),
+                                       b3BufferInfoCL(m_pairCount.getBufferCL())};
+                               b3LauncherCL launcher(m_queue, m_sap2Kernel, "m_sap2Kernel");
+                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                               launcher.setConst(numLargeAabbs);
+                               launcher.setConst(numSmallAabbs);
+                               launcher.setConst(axis);
+                               launcher.setConst(maxPairs);
+                               //@todo: use actual maximum work item sizes of the device instead of hardcoded values
+                               launcher.launch2D(numLargeAabbs, numSmallAabbs, 4, 64);
+
+                               numPairs = m_pairCount.at(0);
+                               if (numPairs > maxPairs)
+                               {
+                                       b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+                                       numPairs = maxPairs;
+                               }
+                       }
+               }
+               if (m_gpuSmallSortedAabbs.size())
+               {
+                       B3_PROFILE("sapKernel");
+                       b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_gpuSmallSortedAabbs.getBufferCL()), b3BufferInfoCL(m_overlappingPairs.getBufferCL()), b3BufferInfoCL(m_pairCount.getBufferCL())};
+                       b3LauncherCL launcher(m_queue, m_sapKernel, "m_sapKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numSmallAabbs);
+                       launcher.setConst(axis);
+                       launcher.setConst(maxPairs);
+
+                       int num = numSmallAabbs;
+#if 0                
+                int buffSize = launcher.getSerializationBufferSize();
+                unsigned char* buf = new unsigned char[buffSize+sizeof(int)];
+                for (int i=0;i<buffSize+1;i++)
+                {
+                    unsigned char* ptr = (unsigned char*)&buf[i];
+                    *ptr = 0xff;
+                }
+                int actualWrite = launcher.serializeArguments(buf,buffSize);
+                
+                unsigned char* cptr = (unsigned char*)&buf[buffSize];
+    //            printf("buf[buffSize] = %d\n",*cptr);
+                
+                assert(buf[buffSize]==0xff);//check for buffer overrun
+                int* ptr = (int*)&buf[buffSize];
+                
+                *ptr = num;
+                
+                FILE* f = fopen("m_sapKernelArgs.bin","wb");
+                fwrite(buf,buffSize+sizeof(int),1,f);
+                fclose(f);
+#endif  //
+
+                       launcher.launch1D(num);
+                       clFinish(m_queue);
+
+                       numPairs = m_pairCount.at(0);
+                       if (numPairs > maxPairs)
+                       {
+                               b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
+                               numPairs = maxPairs;
+                               m_pairCount.resize(0);
+                               m_pairCount.push_back(maxPairs);
+                       }
+               }
+
+#else
+               int numPairs = 0;
+
+               b3LauncherCL launcher(m_queue, m_sapKernel);
+
+               const char* fileName = "m_sapKernelArgs.bin";
+               FILE* f = fopen(fileName, "rb");
+               if (f)
+               {
+                       int sizeInBytes = 0;
+                       if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
+                       {
+                               printf("error, cannot get file size\n");
+                               exit(0);
+                       }
+
+                       unsigned char* buf = (unsigned char*)malloc(sizeInBytes);
+                       fread(buf, sizeInBytes, 1, f);
+                       int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes, m_context);
+                       int num = *(int*)&buf[serializedBytes];
+                       launcher.launch1D(num);
+
+                       b3OpenCLArray<int> pairCount(m_context, m_queue);
+                       int numElements = launcher.m_arrays[2]->size() / sizeof(int);
+                       pairCount.setFromOpenCLBuffer(launcher.m_arrays[2]->getBufferCL(), numElements);
+                       numPairs = pairCount.at(0);
+                       //printf("overlapping pairs = %d\n",numPairs);
+                       b3AlignedObjectArray<b3Int4> hostOoverlappingPairs;
+                       b3OpenCLArray<b3Int4> tmpGpuPairs(m_context, m_queue);
+                       tmpGpuPairs.setFromOpenCLBuffer(launcher.m_arrays[1]->getBufferCL(), numPairs);
+
+                       tmpGpuPairs.copyToHost(hostOoverlappingPairs);
+                       m_overlappingPairs.copyFromHost(hostOoverlappingPairs);
+                       //printf("hello %d\n", m_overlappingPairs.size());
+                       free(buf);
+                       fclose(f);
+               }
+               else
+               {
+                       printf("error: cannot find file %s\n", fileName);
+               }
+
+               clFinish(m_queue);
+
+#endif
+
+               m_overlappingPairs.resize(numPairs);
+
+       }  //B3_PROFILE("GPU_RADIX SORT");
+          //init3dSap();
+}
+
+void b3GpuSapBroadphase::writeAabbsToGpu()
+{
+       m_smallAabbsMappingGPU.copyFromHost(m_smallAabbsMappingCPU);
+       m_largeAabbsMappingGPU.copyFromHost(m_largeAabbsMappingCPU);
+
+       m_allAabbsGPU.copyFromHost(m_allAabbsCPU);  //might not be necessary, the 'setupGpuAabbsFull' already takes care of this
+}
+
+void b3GpuSapBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
+{
+       int index = userPtr;
+       b3SapAabb aabb;
+       for (int i = 0; i < 4; i++)
+       {
+               aabb.m_min[i] = aabbMin[i];
+               aabb.m_max[i] = aabbMax[i];
+       }
+       aabb.m_minIndices[3] = index;
+       aabb.m_signedMaxIndices[3] = m_allAabbsCPU.size();
+       m_largeAabbsMappingCPU.push_back(m_allAabbsCPU.size());
+
+       m_allAabbsCPU.push_back(aabb);
+}
+
+void b3GpuSapBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
+{
+       int index = userPtr;
+       b3SapAabb aabb;
+       for (int i = 0; i < 4; i++)
+       {
+               aabb.m_min[i] = aabbMin[i];
+               aabb.m_max[i] = aabbMax[i];
+       }
+       aabb.m_minIndices[3] = index;
+       aabb.m_signedMaxIndices[3] = m_allAabbsCPU.size();
+       m_smallAabbsMappingCPU.push_back(m_allAabbsCPU.size());
+
+       m_allAabbsCPU.push_back(aabb);
+}
+
+cl_mem b3GpuSapBroadphase::getAabbBufferWS()
+{
+       return m_allAabbsGPU.getBufferCL();
+}
+
+int b3GpuSapBroadphase::getNumOverlap()
+{
+       return m_overlappingPairs.size();
+}
+cl_mem b3GpuSapBroadphase::getOverlappingPairBuffer()
+{
+       return m_overlappingPairs.getBufferCL();
+}
+
+b3OpenCLArray<b3Int4>& b3GpuSapBroadphase::getOverlappingPairsGPU()
+{
+       return m_overlappingPairs;
+}
+b3OpenCLArray<int>& b3GpuSapBroadphase::getSmallAabbIndicesGPU()
+{
+       return m_smallAabbsMappingGPU;
+}
+b3OpenCLArray<int>& b3GpuSapBroadphase::getLargeAabbIndicesGPU()
+{
+       return m_largeAabbsMappingGPU;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h
new file mode 100644 (file)
index 0000000..d17590b
--- /dev/null
@@ -0,0 +1,143 @@
+#ifndef B3_GPU_SAP_BROADPHASE_H
+#define B3_GPU_SAP_BROADPHASE_H
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h"  //b3Int2
+class b3Vector3;
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+
+#include "b3SapAabb.h"
+#include "Bullet3Common/shared/b3Int2.h"
+
+#include "b3GpuBroadphaseInterface.h"
+
+class b3GpuSapBroadphase : public b3GpuBroadphaseInterface
+{
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_queue;
+       cl_kernel m_flipFloatKernel;
+       cl_kernel m_scatterKernel;
+       cl_kernel m_copyAabbsKernel;
+       cl_kernel m_sapKernel;
+       cl_kernel m_sap2Kernel;
+       cl_kernel m_prepareSumVarianceKernel;
+
+       class b3RadixSort32CL* m_sorter;
+
+       ///test for 3d SAP
+       b3AlignedObjectArray<b3SortData> m_sortedAxisCPU[3][2];
+       b3AlignedObjectArray<b3UnsignedInt2> m_objectMinMaxIndexCPU[3][2];
+       b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis0;
+       b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis1;
+       b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis2;
+       b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis0prev;
+       b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis1prev;
+       b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis2prev;
+
+       b3OpenCLArray<b3SortData> m_sortedAxisGPU0;
+       b3OpenCLArray<b3SortData> m_sortedAxisGPU1;
+       b3OpenCLArray<b3SortData> m_sortedAxisGPU2;
+       b3OpenCLArray<b3SortData> m_sortedAxisGPU0prev;
+       b3OpenCLArray<b3SortData> m_sortedAxisGPU1prev;
+       b3OpenCLArray<b3SortData> m_sortedAxisGPU2prev;
+
+       b3OpenCLArray<b3Int4> m_addedHostPairsGPU;
+       b3OpenCLArray<b3Int4> m_removedHostPairsGPU;
+       b3OpenCLArray<int> m_addedCountGPU;
+       b3OpenCLArray<int> m_removedCountGPU;
+
+       int m_currentBuffer;
+
+public:
+       b3OpenCLArray<int> m_pairCount;
+
+       b3OpenCLArray<b3SapAabb> m_allAabbsGPU;
+       b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
+
+       virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU()
+       {
+               return m_allAabbsGPU;
+       }
+       virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU()
+       {
+               return m_allAabbsCPU;
+       }
+
+       b3OpenCLArray<b3Vector3> m_sum;
+       b3OpenCLArray<b3Vector3> m_sum2;
+       b3OpenCLArray<b3Vector3> m_dst;
+
+       b3OpenCLArray<int> m_smallAabbsMappingGPU;
+       b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
+
+       b3OpenCLArray<int> m_largeAabbsMappingGPU;
+       b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
+
+       b3OpenCLArray<b3Int4> m_overlappingPairs;
+
+       //temporary gpu work memory
+       b3OpenCLArray<b3SortData> m_gpuSmallSortData;
+       b3OpenCLArray<b3SapAabb> m_gpuSmallSortedAabbs;
+
+       class b3PrefixScanFloat4CL* m_prefixScanFloat4;
+
+       enum b3GpuSapKernelType
+       {
+               B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU = 1,
+               B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU,
+               B3_GPU_SAP_KERNEL_ORIGINAL,
+               B3_GPU_SAP_KERNEL_BARRIER,
+               B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY
+       };
+
+       b3GpuSapBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q, b3GpuSapKernelType kernelType = B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY);
+       virtual ~b3GpuSapBroadphase();
+
+       static b3GpuBroadphaseInterface* CreateFuncBruteForceCpu(cl_context ctx, cl_device_id device, cl_command_queue q)
+       {
+               return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU);
+       }
+
+       static b3GpuBroadphaseInterface* CreateFuncBruteForceGpu(cl_context ctx, cl_device_id device, cl_command_queue q)
+       {
+               return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU);
+       }
+
+       static b3GpuBroadphaseInterface* CreateFuncOriginal(cl_context ctx, cl_device_id device, cl_command_queue q)
+       {
+               return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_ORIGINAL);
+       }
+       static b3GpuBroadphaseInterface* CreateFuncBarrier(cl_context ctx, cl_device_id device, cl_command_queue q)
+       {
+               return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_BARRIER);
+       }
+       static b3GpuBroadphaseInterface* CreateFuncLocalMemory(cl_context ctx, cl_device_id device, cl_command_queue q)
+       {
+               return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY);
+       }
+
+       virtual void calculateOverlappingPairs(int maxPairs);
+       virtual void calculateOverlappingPairsHost(int maxPairs);
+
+       void reset();
+
+       void init3dSap();
+       virtual void calculateOverlappingPairsHostIncremental3Sap();
+
+       virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+       virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
+
+       //call writeAabbsToGpu after done making all changes (createProxy etc)
+       virtual void writeAabbsToGpu();
+
+       virtual cl_mem getAabbBufferWS();
+       virtual int getNumOverlap();
+       virtual cl_mem getOverlappingPairBuffer();
+
+       virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU();
+       virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU();
+       virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU();
+};
+
+#endif  //B3_GPU_SAP_BROADPHASE_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h
new file mode 100644 (file)
index 0000000..60570f2
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef B3_SAP_AABB_H
+#define B3_SAP_AABB_H
+
+#include "Bullet3Common/b3Scalar.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+
+///just make sure that the b3Aabb is 16-byte aligned
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3SapAabb : public b3Aabb{
+
+                       };
+
+#endif  //B3_SAP_AABB_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl
new file mode 100644 (file)
index 0000000..ded4796
--- /dev/null
@@ -0,0 +1,216 @@
+
+
+int getPosHash(int4 gridPos, __global float4* pParams)
+{
+       int4 gridDim = *((__global int4*)(pParams + 1));
+       gridPos.x &= gridDim.x - 1;
+       gridPos.y &= gridDim.y - 1;
+       gridPos.z &= gridDim.z - 1;
+       int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x;
+       return hash;
+} 
+
+int4 getGridPos(float4 worldPos, __global float4* pParams)
+{
+    int4 gridPos;
+       int4 gridDim = *((__global int4*)(pParams + 1));
+    gridPos.x = (int)floor(worldPos.x * pParams[0].x) & (gridDim.x - 1);
+    gridPos.y = (int)floor(worldPos.y * pParams[0].y) & (gridDim.y - 1);
+    gridPos.z = (int)floor(worldPos.z * pParams[0].z) & (gridDim.z - 1);
+    return gridPos;
+}
+
+
+// calculate grid hash value for each body using its AABB
+__kernel void kCalcHashAABB(int numObjects, __global float4* allpAABB, __global const int* smallAabbMapping, __global int2* pHash, __global float4* pParams )
+{
+    int index = get_global_id(0);
+    if(index >= numObjects)
+       {
+               return;
+       }
+       float4 bbMin = allpAABB[smallAabbMapping[index]*2];
+       float4 bbMax = allpAABB[smallAabbMapping[index]*2 + 1];
+       float4 pos;
+       pos.x = (bbMin.x + bbMax.x) * 0.5f;
+       pos.y = (bbMin.y + bbMax.y) * 0.5f;
+       pos.z = (bbMin.z + bbMax.z) * 0.5f;
+       pos.w = 0.f;
+    // get address in grid
+    int4 gridPos = getGridPos(pos, pParams);
+    int gridHash = getPosHash(gridPos, pParams);
+    // store grid hash and body index
+    int2 hashVal;
+    hashVal.x = gridHash;
+    hashVal.y = index;
+    pHash[index] = hashVal;
+}
+
+__kernel void kClearCellStart( int numCells, 
+                                                               __global int* pCellStart )
+{
+    int index = get_global_id(0);
+    if(index >= numCells)
+       {
+               return;
+       }
+       pCellStart[index] = -1;
+}
+
+__kernel void kFindCellStart(int numObjects, __global int2* pHash, __global int* cellStart )
+{
+       __local int sharedHash[513];
+    int index = get_global_id(0);
+       int2 sortedData;
+
+    if(index < numObjects)
+       {
+               sortedData = pHash[index];
+               // Load hash data into shared memory so that we can look 
+               // at neighboring body's hash value without loading
+               // two hash values per thread
+               sharedHash[get_local_id(0) + 1] = sortedData.x;
+               if((index > 0) && (get_local_id(0) == 0))
+               {
+                       // first thread in block must load neighbor body hash
+                       sharedHash[0] = pHash[index-1].x;
+               }
+       }
+    barrier(CLK_LOCAL_MEM_FENCE);
+    if(index < numObjects)
+       {
+               if((index == 0) || (sortedData.x != sharedHash[get_local_id(0)]))
+               {
+                       cellStart[sortedData.x] = index;
+               }
+       }
+}
+
+int testAABBOverlap(float4 min0, float4 max0, float4 min1, float4 max1)
+{
+       return  (min0.x <= max1.x)&& (min1.x <= max0.x) && 
+                       (min0.y <= max1.y)&& (min1.y <= max0.y) && 
+                       (min0.z <= max1.z)&& (min1.z <= max0.z); 
+}
+
+
+
+
+//search for AABB 'index' against other AABBs' in this cell
+void findPairsInCell(  int numObjects,
+                                               int4    gridPos,
+                                               int    index,
+                                               __global int2*  pHash,
+                                               __global int*   pCellStart,
+                                               __global float4* allpAABB, 
+                                               __global const int* smallAabbMapping,
+                                               __global float4* pParams,
+                                                       volatile  __global int* pairCount,
+                                               __global int4*   pPairBuff2,
+                                               int maxPairs
+                                               )
+{
+       int4 pGridDim = *((__global int4*)(pParams + 1));
+       int maxBodiesPerCell = pGridDim.w;
+    int gridHash = getPosHash(gridPos, pParams);
+    // get start of bucket for this cell
+    int bucketStart = pCellStart[gridHash];
+    if (bucketStart == -1)
+       {
+        return;   // cell empty
+       }
+       // iterate over bodies in this cell
+    int2 sortedData = pHash[index];
+       int unsorted_indx = sortedData.y;
+    float4 min0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0]; 
+       float4 max0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];
+       int handleIndex =  as_int(min0.w);
+       
+       int bucketEnd = bucketStart + maxBodiesPerCell;
+       bucketEnd = (bucketEnd > numObjects) ? numObjects : bucketEnd;
+       for(int index2 = bucketStart; index2 < bucketEnd; index2++) 
+       {
+        int2 cellData = pHash[index2];
+        if (cellData.x != gridHash)
+        {
+                       break;   // no longer in same bucket
+               }
+               int unsorted_indx2 = cellData.y;
+        //if (unsorted_indx2 < unsorted_indx) // check not colliding with self
+               if (unsorted_indx2 != unsorted_indx) // check not colliding with self
+        {   
+                       float4 min1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 0];
+                       float4 max1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 1];
+                       if(testAABBOverlap(min0, max0, min1, max1))
+                       {
+                               if (pairCount)
+                               {
+                                       int handleIndex2 = as_int(min1.w);
+                                       if (handleIndex<handleIndex2)
+                                       {
+                                               int curPair = atomic_add(pairCount,1);
+                                               if (curPair<maxPairs)
+                                               {
+                                                       int4 newpair;
+                                                       newpair.x = handleIndex;
+                                                       newpair.y = handleIndex2;
+                                                       newpair.z = -1;
+                                                       newpair.w = -1;
+                                                       pPairBuff2[curPair] = newpair;
+                                               }
+                                       }
+                               
+                               }
+                       }
+               }
+       }
+}
+
+__kernel void kFindOverlappingPairs(   int numObjects,
+                                                                               __global float4* allpAABB, 
+                                                                               __global const int* smallAabbMapping,
+                                                                               __global int2* pHash, 
+                                                                               __global int* pCellStart, 
+                                                                               __global float4* pParams ,
+                                                                               volatile  __global int* pairCount,
+                                                                               __global int4*   pPairBuff2,
+                                                                               int maxPairs
+                                                                               )
+
+{
+    int index = get_global_id(0);
+    if(index >= numObjects)
+       {
+               return;
+       }
+    int2 sortedData = pHash[index];
+       int unsorted_indx = sortedData.y;
+       float4 bbMin = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0];
+       float4 bbMax = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];
+       float4 pos;
+       pos.x = (bbMin.x + bbMax.x) * 0.5f;
+       pos.y = (bbMin.y + bbMax.y) * 0.5f;
+       pos.z = (bbMin.z + bbMax.z) * 0.5f;
+    // get address in grid
+    int4 gridPosA = getGridPos(pos, pParams);
+    int4 gridPosB; 
+    // examine only neighbouring cells
+    for(int z=-1; z<=1; z++) 
+    {
+               gridPosB.z = gridPosA.z + z;
+        for(int y=-1; y<=1; y++) 
+        {
+                       gridPosB.y = gridPosA.y + y;
+            for(int x=-1; x<=1; x++) 
+            {
+                               gridPosB.x = gridPosA.x + x;
+                findPairsInCell(numObjects, gridPosB, index, pHash, pCellStart, allpAABB,smallAabbMapping, pParams, pairCount,pPairBuff2, maxPairs);
+            }
+        }
+    }
+}
+
+
+
+
+
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h
new file mode 100644 (file)
index 0000000..0185417
--- /dev/null
@@ -0,0 +1,198 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* gridBroadphaseCL =
+       "int getPosHash(int4 gridPos, __global float4* pParams)\n"
+       "{\n"
+       "       int4 gridDim = *((__global int4*)(pParams + 1));\n"
+       "       gridPos.x &= gridDim.x - 1;\n"
+       "       gridPos.y &= gridDim.y - 1;\n"
+       "       gridPos.z &= gridDim.z - 1;\n"
+       "       int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x;\n"
+       "       return hash;\n"
+       "} \n"
+       "int4 getGridPos(float4 worldPos, __global float4* pParams)\n"
+       "{\n"
+       "    int4 gridPos;\n"
+       "       int4 gridDim = *((__global int4*)(pParams + 1));\n"
+       "    gridPos.x = (int)floor(worldPos.x * pParams[0].x) & (gridDim.x - 1);\n"
+       "    gridPos.y = (int)floor(worldPos.y * pParams[0].y) & (gridDim.y - 1);\n"
+       "    gridPos.z = (int)floor(worldPos.z * pParams[0].z) & (gridDim.z - 1);\n"
+       "    return gridPos;\n"
+       "}\n"
+       "// calculate grid hash value for each body using its AABB\n"
+       "__kernel void kCalcHashAABB(int numObjects, __global float4* allpAABB, __global const int* smallAabbMapping, __global int2* pHash, __global float4* pParams )\n"
+       "{\n"
+       "    int index = get_global_id(0);\n"
+       "    if(index >= numObjects)\n"
+       "       {\n"
+       "               return;\n"
+       "       }\n"
+       "       float4 bbMin = allpAABB[smallAabbMapping[index]*2];\n"
+       "       float4 bbMax = allpAABB[smallAabbMapping[index]*2 + 1];\n"
+       "       float4 pos;\n"
+       "       pos.x = (bbMin.x + bbMax.x) * 0.5f;\n"
+       "       pos.y = (bbMin.y + bbMax.y) * 0.5f;\n"
+       "       pos.z = (bbMin.z + bbMax.z) * 0.5f;\n"
+       "       pos.w = 0.f;\n"
+       "    // get address in grid\n"
+       "    int4 gridPos = getGridPos(pos, pParams);\n"
+       "    int gridHash = getPosHash(gridPos, pParams);\n"
+       "    // store grid hash and body index\n"
+       "    int2 hashVal;\n"
+       "    hashVal.x = gridHash;\n"
+       "    hashVal.y = index;\n"
+       "    pHash[index] = hashVal;\n"
+       "}\n"
+       "__kernel void kClearCellStart( int numCells, \n"
+       "                                                               __global int* pCellStart )\n"
+       "{\n"
+       "    int index = get_global_id(0);\n"
+       "    if(index >= numCells)\n"
+       "       {\n"
+       "               return;\n"
+       "       }\n"
+       "       pCellStart[index] = -1;\n"
+       "}\n"
+       "__kernel void kFindCellStart(int numObjects, __global int2* pHash, __global int* cellStart )\n"
+       "{\n"
+       "       __local int sharedHash[513];\n"
+       "    int index = get_global_id(0);\n"
+       "       int2 sortedData;\n"
+       "    if(index < numObjects)\n"
+       "       {\n"
+       "               sortedData = pHash[index];\n"
+       "               // Load hash data into shared memory so that we can look \n"
+       "               // at neighboring body's hash value without loading\n"
+       "               // two hash values per thread\n"
+       "               sharedHash[get_local_id(0) + 1] = sortedData.x;\n"
+       "               if((index > 0) && (get_local_id(0) == 0))\n"
+       "               {\n"
+       "                       // first thread in block must load neighbor body hash\n"
+       "                       sharedHash[0] = pHash[index-1].x;\n"
+       "               }\n"
+       "       }\n"
+       "    barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "    if(index < numObjects)\n"
+       "       {\n"
+       "               if((index == 0) || (sortedData.x != sharedHash[get_local_id(0)]))\n"
+       "               {\n"
+       "                       cellStart[sortedData.x] = index;\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "int testAABBOverlap(float4 min0, float4 max0, float4 min1, float4 max1)\n"
+       "{\n"
+       "       return  (min0.x <= max1.x)&& (min1.x <= max0.x) && \n"
+       "                       (min0.y <= max1.y)&& (min1.y <= max0.y) && \n"
+       "                       (min0.z <= max1.z)&& (min1.z <= max0.z); \n"
+       "}\n"
+       "//search for AABB 'index' against other AABBs' in this cell\n"
+       "void findPairsInCell(  int numObjects,\n"
+       "                                               int4    gridPos,\n"
+       "                                               int    index,\n"
+       "                                               __global int2*  pHash,\n"
+       "                                               __global int*   pCellStart,\n"
+       "                                               __global float4* allpAABB, \n"
+       "                                               __global const int* smallAabbMapping,\n"
+       "                                               __global float4* pParams,\n"
+       "                                                       volatile  __global int* pairCount,\n"
+       "                                               __global int4*   pPairBuff2,\n"
+       "                                               int maxPairs\n"
+       "                                               )\n"
+       "{\n"
+       "       int4 pGridDim = *((__global int4*)(pParams + 1));\n"
+       "       int maxBodiesPerCell = pGridDim.w;\n"
+       "    int gridHash = getPosHash(gridPos, pParams);\n"
+       "    // get start of bucket for this cell\n"
+       "    int bucketStart = pCellStart[gridHash];\n"
+       "    if (bucketStart == -1)\n"
+       "       {\n"
+       "        return;   // cell empty\n"
+       "       }\n"
+       "       // iterate over bodies in this cell\n"
+       "    int2 sortedData = pHash[index];\n"
+       "       int unsorted_indx = sortedData.y;\n"
+       "    float4 min0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0]; \n"
+       "       float4 max0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];\n"
+       "       int handleIndex =  as_int(min0.w);\n"
+       "       \n"
+       "       int bucketEnd = bucketStart + maxBodiesPerCell;\n"
+       "       bucketEnd = (bucketEnd > numObjects) ? numObjects : bucketEnd;\n"
+       "       for(int index2 = bucketStart; index2 < bucketEnd; index2++) \n"
+       "       {\n"
+       "        int2 cellData = pHash[index2];\n"
+       "        if (cellData.x != gridHash)\n"
+       "        {\n"
+       "                       break;   // no longer in same bucket\n"
+       "               }\n"
+       "               int unsorted_indx2 = cellData.y;\n"
+       "        //if (unsorted_indx2 < unsorted_indx) // check not colliding with self\n"
+       "               if (unsorted_indx2 != unsorted_indx) // check not colliding with self\n"
+       "        {   \n"
+       "                       float4 min1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 0];\n"
+       "                       float4 max1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 1];\n"
+       "                       if(testAABBOverlap(min0, max0, min1, max1))\n"
+       "                       {\n"
+       "                               if (pairCount)\n"
+       "                               {\n"
+       "                                       int handleIndex2 = as_int(min1.w);\n"
+       "                                       if (handleIndex<handleIndex2)\n"
+       "                                       {\n"
+       "                                               int curPair = atomic_add(pairCount,1);\n"
+       "                                               if (curPair<maxPairs)\n"
+       "                                               {\n"
+       "                                                       int4 newpair;\n"
+       "                                                       newpair.x = handleIndex;\n"
+       "                                                       newpair.y = handleIndex2;\n"
+       "                                                       newpair.z = -1;\n"
+       "                                                       newpair.w = -1;\n"
+       "                                                       pPairBuff2[curPair] = newpair;\n"
+       "                                               }\n"
+       "                                       }\n"
+       "                               \n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__kernel void kFindOverlappingPairs(   int numObjects,\n"
+       "                                                                               __global float4* allpAABB, \n"
+       "                                                                               __global const int* smallAabbMapping,\n"
+       "                                                                               __global int2* pHash, \n"
+       "                                                                               __global int* pCellStart, \n"
+       "                                                                               __global float4* pParams ,\n"
+       "                                                                               volatile  __global int* pairCount,\n"
+       "                                                                               __global int4*   pPairBuff2,\n"
+       "                                                                               int maxPairs\n"
+       "                                                                               )\n"
+       "{\n"
+       "    int index = get_global_id(0);\n"
+       "    if(index >= numObjects)\n"
+       "       {\n"
+       "               return;\n"
+       "       }\n"
+       "    int2 sortedData = pHash[index];\n"
+       "       int unsorted_indx = sortedData.y;\n"
+       "       float4 bbMin = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0];\n"
+       "       float4 bbMax = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];\n"
+       "       float4 pos;\n"
+       "       pos.x = (bbMin.x + bbMax.x) * 0.5f;\n"
+       "       pos.y = (bbMin.y + bbMax.y) * 0.5f;\n"
+       "       pos.z = (bbMin.z + bbMax.z) * 0.5f;\n"
+       "    // get address in grid\n"
+       "    int4 gridPosA = getGridPos(pos, pParams);\n"
+       "    int4 gridPosB; \n"
+       "    // examine only neighbouring cells\n"
+       "    for(int z=-1; z<=1; z++) \n"
+       "    {\n"
+       "               gridPosB.z = gridPosA.z + z;\n"
+       "        for(int y=-1; y<=1; y++) \n"
+       "        {\n"
+       "                       gridPosB.y = gridPosA.y + y;\n"
+       "            for(int x=-1; x<=1; x++) \n"
+       "            {\n"
+       "                               gridPosB.x = gridPosA.x + x;\n"
+       "                findPairsInCell(numObjects, gridPosB, index, pHash, pCellStart, allpAABB,smallAabbMapping, pParams, pairCount,pPairBuff2, maxPairs);\n"
+       "            }\n"
+       "        }\n"
+       "    }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl
new file mode 100644 (file)
index 0000000..c375b9b
--- /dev/null
@@ -0,0 +1,767 @@
+/*
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Initial Author Jackson Lee, 2014
+
+typedef float b3Scalar;
+typedef float4 b3Vector3;
+#define b3Max max
+#define b3Min min
+#define b3Sqrt sqrt
+
+typedef struct
+{
+       unsigned int m_key;
+       unsigned int m_value;
+} SortDataCL;
+
+typedef struct 
+{
+       union
+       {
+               float4  m_min;
+               float   m_minElems[4];
+               int                     m_minIndices[4];
+       };
+       union
+       {
+               float4  m_max;
+               float   m_maxElems[4];
+               int                     m_maxIndices[4];
+       };
+} b3AabbCL;
+
+
+unsigned int interleaveBits(unsigned int x)
+{
+       //........ ........ ......12 3456789A   //x
+       //....1..2 ..3..4.. 5..6..7. .8..9..A   //x after interleaving bits
+       
+       //......12 3456789A ......12 3456789A   //x ^ (x << 16)
+       //11111111 ........ ........ 11111111   //0x FF 00 00 FF
+       //......12 ........ ........ 3456789A   //x = (x ^ (x << 16)) & 0xFF0000FF;
+       
+       //......12 ........ 3456789A 3456789A   //x ^ (x <<  8)
+       //......11 ........ 1111.... ....1111   //0x 03 00 F0 0F
+       //......12 ........ 3456.... ....789A   //x = (x ^ (x <<  8)) & 0x0300F00F;
+       
+       //..12..12 ....3456 3456.... 789A789A   //x ^ (x <<  4)
+       //......11 ....11.. ..11.... 11....11   //0x 03 0C 30 C3
+       //......12 ....34.. ..56.... 78....9A   //x = (x ^ (x <<  4)) & 0x030C30C3;
+       
+       //....1212 ..3434.. 5656..78 78..9A9A   //x ^ (x <<  2)
+       //....1..1 ..1..1.. 1..1..1. .1..1..1   //0x 09 24 92 49
+       //....1..2 ..3..4.. 5..6..7. .8..9..A   //x = (x ^ (x <<  2)) & 0x09249249;
+       
+       //........ ........ ......11 11111111   //0x000003FF
+       x &= 0x000003FF;                //Clear all bits above bit 10
+       
+       x = (x ^ (x << 16)) & 0xFF0000FF;
+       x = (x ^ (x <<  8)) & 0x0300F00F;
+       x = (x ^ (x <<  4)) & 0x030C30C3;
+       x = (x ^ (x <<  2)) & 0x09249249;
+       
+       return x;
+}
+unsigned int getMortonCode(unsigned int x, unsigned int y, unsigned int z)
+{
+       return interleaveBits(x) << 0 | interleaveBits(y) << 1 | interleaveBits(z) << 2;
+}
+
+__kernel void separateAabbs(__global b3AabbCL* unseparatedAabbs, __global int* aabbIndices, __global b3AabbCL* out_aabbs, int numAabbsToSeparate)
+{
+       int separatedAabbIndex = get_global_id(0);
+       if(separatedAabbIndex >= numAabbsToSeparate) return;
+
+       int unseparatedAabbIndex = aabbIndices[separatedAabbIndex];
+       out_aabbs[separatedAabbIndex] = unseparatedAabbs[unseparatedAabbIndex];
+}
+
+//Should replace with an optimized parallel reduction
+__kernel void findAllNodesMergedAabb(__global b3AabbCL* out_mergedAabb, int numAabbsNeedingMerge)
+{
+       //Each time this kernel is added to the command queue, 
+       //the number of AABBs needing to be merged is halved
+       //
+       //Example with 159 AABBs:
+       //      numRemainingAabbs == 159 / 2 + 159 % 2 == 80
+       //      numMergedAabbs == 159 - 80 == 79
+       //So, indices [0, 78] are merged with [0 + 80, 78 + 80]
+       
+       int numRemainingAabbs = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2;
+       int numMergedAabbs = numAabbsNeedingMerge - numRemainingAabbs;
+       
+       int aabbIndex = get_global_id(0);
+       if(aabbIndex >= numMergedAabbs) return;
+       
+       int otherAabbIndex = aabbIndex + numRemainingAabbs;
+       
+       b3AabbCL aabb = out_mergedAabb[aabbIndex];
+       b3AabbCL otherAabb = out_mergedAabb[otherAabbIndex];
+               
+       b3AabbCL mergedAabb;
+       mergedAabb.m_min = b3Min(aabb.m_min, otherAabb.m_min);
+       mergedAabb.m_max = b3Max(aabb.m_max, otherAabb.m_max);
+       out_mergedAabb[aabbIndex] = mergedAabb;
+}
+
+__kernel void assignMortonCodesAndAabbIndicies(__global b3AabbCL* worldSpaceAabbs, __global b3AabbCL* mergedAabbOfAllNodes, 
+                                                                                               __global SortDataCL* out_mortonCodesAndAabbIndices, int numAabbs)
+{
+       int leafNodeIndex = get_global_id(0);   //Leaf node index == AABB index
+       if(leafNodeIndex >= numAabbs) return;
+       
+       b3AabbCL mergedAabb = mergedAabbOfAllNodes[0];
+       b3Vector3 gridCenter = (mergedAabb.m_min + mergedAabb.m_max) * 0.5f;
+       b3Vector3 gridCellSize = (mergedAabb.m_max - mergedAabb.m_min) / (float)1024;
+       
+       b3AabbCL aabb = worldSpaceAabbs[leafNodeIndex];
+       b3Vector3 aabbCenter = (aabb.m_min + aabb.m_max) * 0.5f;
+       b3Vector3 aabbCenterRelativeToGrid = aabbCenter - gridCenter;
+       
+       //Quantize into integer coordinates
+       //floor() is needed to prevent the center cell, at (0,0,0) from being twice the size
+       b3Vector3 gridPosition = aabbCenterRelativeToGrid / gridCellSize;
+       
+       int4 discretePosition;
+       discretePosition.x = (int)( (gridPosition.x >= 0.0f) ? gridPosition.x : floor(gridPosition.x) );
+       discretePosition.y = (int)( (gridPosition.y >= 0.0f) ? gridPosition.y : floor(gridPosition.y) );
+       discretePosition.z = (int)( (gridPosition.z >= 0.0f) ? gridPosition.z : floor(gridPosition.z) );
+       
+       //Clamp coordinates into [-512, 511], then convert range from [-512, 511] to [0, 1023]
+       discretePosition = b3Max( -512, b3Min(discretePosition, 511) );
+       discretePosition += 512;
+       
+       //Interleave bits(assign a morton code, also known as a z-curve)
+       unsigned int mortonCode = getMortonCode(discretePosition.x, discretePosition.y, discretePosition.z);
+       
+       //
+       SortDataCL mortonCodeIndexPair;
+       mortonCodeIndexPair.m_key = mortonCode;
+       mortonCodeIndexPair.m_value = leafNodeIndex;
+       
+       out_mortonCodesAndAabbIndices[leafNodeIndex] = mortonCodeIndexPair;
+}
+
+#define B3_PLVBH_TRAVERSE_MAX_STACK_SIZE 128
+
+//The most significant bit(0x80000000) of a int32 is used to distinguish between leaf and internal nodes.
+//If it is set, then the index is for an internal node; otherwise, it is a leaf node. 
+//In both cases, the bit should be cleared to access the actual node index.
+int isLeafNode(int index) { return (index >> 31 == 0); }
+int getIndexWithInternalNodeMarkerRemoved(int index) { return index & (~0x80000000); }
+int getIndexWithInternalNodeMarkerSet(int isLeaf, int index) { return (isLeaf) ? index : (index | 0x80000000); }
+
+//From sap.cl
+#define NEW_PAIR_MARKER -1
+
+bool TestAabbAgainstAabb2(const b3AabbCL* aabb1, const b3AabbCL* aabb2)
+{
+       bool overlap = true;
+       overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
+       overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
+       overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
+       return overlap;
+}
+//From sap.cl
+
+__kernel void plbvhCalculateOverlappingPairs(__global b3AabbCL* rigidAabbs, 
+
+                                                                                       __global int* rootNodeIndex, 
+                                                                                       __global int2* internalNodeChildIndices, 
+                                                                                       __global b3AabbCL* internalNodeAabbs,
+                                                                                       __global int2* internalNodeLeafIndexRanges,
+                                                                                       
+                                                                                       __global SortDataCL* mortonCodesAndAabbIndices,
+                                                                                       __global int* out_numPairs, __global int4* out_overlappingPairs, 
+                                                                                       int maxPairs, int numQueryAabbs)
+{
+       //Using get_group_id()/get_local_id() is Faster than get_global_id(0) since
+       //mortonCodesAndAabbIndices[] contains rigid body indices sorted along the z-curve (more spatially coherent)
+       int queryBvhNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);
+       if(queryBvhNodeIndex >= numQueryAabbs) return;
+       
+       int queryRigidIndex = mortonCodesAndAabbIndices[queryBvhNodeIndex].m_value;
+       b3AabbCL queryAabb = rigidAabbs[queryRigidIndex];
+       
+       int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];
+       
+       int stackSize = 1;
+       stack[0] = *rootNodeIndex;
+       
+       while(stackSize)
+       {
+               int internalOrLeafNodeIndex = stack[ stackSize - 1 ];
+               --stackSize;
+               
+               int isLeaf = isLeafNode(internalOrLeafNodeIndex);       //Internal node if false
+               int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);
+               
+               //Optimization - if the BVH is structured as a binary radix tree, then
+               //each internal node corresponds to a contiguous range of leaf nodes(internalNodeLeafIndexRanges[]).
+               //This can be used to avoid testing each AABB-AABB pair twice, including preventing each node from colliding with itself.
+               {
+                       int highestLeafIndex = (isLeaf) ? bvhNodeIndex : internalNodeLeafIndexRanges[bvhNodeIndex].y;
+                       if(highestLeafIndex <= queryBvhNodeIndex) continue;
+               }
+               
+               //bvhRigidIndex is not used if internal node
+               int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;
+       
+               b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];
+               if( TestAabbAgainstAabb2(&queryAabb, &bvhNodeAabb) )
+               {
+                       if(isLeaf)
+                       {
+                               int4 pair;
+                               pair.x = rigidAabbs[queryRigidIndex].m_minIndices[3];
+                               pair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];
+                               pair.z = NEW_PAIR_MARKER;
+                               pair.w = NEW_PAIR_MARKER;
+                               
+                               int pairIndex = atomic_inc(out_numPairs);
+                               if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;
+                       }
+                       
+                       if(!isLeaf)     //Internal node
+                       {
+                               if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)
+                               {
+                                       //Error
+                               }
+                               else
+                               {
+                                       stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;
+                                       stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;
+                               }
+                       }
+               }
+               
+       }
+}
+
+
+//From rayCastKernels.cl
+typedef struct
+{
+       float4 m_from;
+       float4 m_to;
+} b3RayInfo;
+//From rayCastKernels.cl
+
+b3Vector3 b3Vector3_normalize(b3Vector3 v)
+{
+       b3Vector3 normal = (b3Vector3){v.x, v.y, v.z, 0.f};
+       return normalize(normal);       //OpenCL normalize == vector4 normalize
+}
+b3Scalar b3Vector3_length2(b3Vector3 v) { return v.x*v.x + v.y*v.y + v.z*v.z; }
+b3Scalar b3Vector3_dot(b3Vector3 a, b3Vector3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; }
+
+int rayIntersectsAabb(b3Vector3 rayOrigin, b3Scalar rayLength, b3Vector3 rayNormalizedDirection, b3AabbCL aabb)
+{
+       //AABB is considered as 3 pairs of 2 planes( {x_min, x_max}, {y_min, y_max}, {z_min, z_max} ).
+       //t_min is the point of intersection with the closer plane, t_max is the point of intersection with the farther plane.
+       //
+       //if (rayNormalizedDirection.x < 0.0f), then max.x will be the near plane 
+       //and min.x will be the far plane; otherwise, it is reversed.
+       //
+       //In order for there to be a collision, the t_min and t_max of each pair must overlap.
+       //This can be tested for by selecting the highest t_min and lowest t_max and comparing them.
+       
+       int4 isNegative = isless( rayNormalizedDirection, ((b3Vector3){0.0f, 0.0f, 0.0f, 0.0f}) );      //isless(x,y) returns (x < y)
+       
+       //When using vector types, the select() function checks the most signficant bit, 
+       //but isless() sets the least significant bit.
+       isNegative <<= 31;
+
+       //select(b, a, condition) == condition ? a : b
+       //When using select() with vector types, (condition[i]) is true if its most significant bit is 1
+       b3Vector3 t_min = ( select(aabb.m_min, aabb.m_max, isNegative) - rayOrigin ) / rayNormalizedDirection;
+       b3Vector3 t_max = ( select(aabb.m_max, aabb.m_min, isNegative) - rayOrigin ) / rayNormalizedDirection;
+       
+       b3Scalar t_min_final = 0.0f;
+       b3Scalar t_max_final = rayLength;
+       
+       //Must use fmin()/fmax(); if one of the parameters is NaN, then the parameter that is not NaN is returned. 
+       //Behavior of min()/max() with NaNs is undefined. (See OpenCL Specification 1.2 [6.12.2] and [6.12.4])
+       //Since the innermost fmin()/fmax() is always not NaN, this should never return NaN.
+       t_min_final = fmax( t_min.z, fmax(t_min.y, fmax(t_min.x, t_min_final)) );
+       t_max_final = fmin( t_max.z, fmin(t_max.y, fmin(t_max.x, t_max_final)) );
+       
+       return (t_min_final <= t_max_final);
+}
+
+__kernel void plbvhRayTraverse(__global b3AabbCL* rigidAabbs,
+
+                                                               __global int* rootNodeIndex, 
+                                                               __global int2* internalNodeChildIndices, 
+                                                               __global b3AabbCL* internalNodeAabbs,
+                                                               __global int2* internalNodeLeafIndexRanges,
+                                                               __global SortDataCL* mortonCodesAndAabbIndices,
+                                                               
+                                                               __global b3RayInfo* rays,
+                                                               
+                                                               __global int* out_numRayRigidPairs, 
+                                                               __global int2* out_rayRigidPairs,
+                                                               int maxRayRigidPairs, int numRays)
+{
+       int rayIndex = get_global_id(0);
+       if(rayIndex >= numRays) return;
+       
+       //
+       b3Vector3 rayFrom = rays[rayIndex].m_from;
+       b3Vector3 rayTo = rays[rayIndex].m_to;
+       b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);
+       b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );
+       
+       //
+       int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];
+       
+       int stackSize = 1;
+       stack[0] = *rootNodeIndex;
+       
+       while(stackSize)
+       {
+               int internalOrLeafNodeIndex = stack[ stackSize - 1 ];
+               --stackSize;
+               
+               int isLeaf = isLeafNode(internalOrLeafNodeIndex);       //Internal node if false
+               int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);
+               
+               //bvhRigidIndex is not used if internal node
+               int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;
+       
+               b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];
+               if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, bvhNodeAabb)  )
+               {
+                       if(isLeaf)
+                       {
+                               int2 rayRigidPair;
+                               rayRigidPair.x = rayIndex;
+                               rayRigidPair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];
+                               
+                               int pairIndex = atomic_inc(out_numRayRigidPairs);
+                               if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;
+                       }
+                       
+                       if(!isLeaf)     //Internal node
+                       {
+                               if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)
+                               {
+                                       //Error
+                               }
+                               else
+                               {
+                                       stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;
+                                       stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;
+                               }
+                       }
+               }
+       }
+}
+
+__kernel void plbvhLargeAabbAabbTest(__global b3AabbCL* smallAabbs, __global b3AabbCL* largeAabbs, 
+                                                                       __global int* out_numPairs, __global int4* out_overlappingPairs, 
+                                                                       int maxPairs, int numLargeAabbRigids, int numSmallAabbRigids)
+{
+       int smallAabbIndex = get_global_id(0);
+       if(smallAabbIndex >= numSmallAabbRigids) return;
+       
+       b3AabbCL smallAabb = smallAabbs[smallAabbIndex];
+       for(int i = 0; i < numLargeAabbRigids; ++i)
+       {
+               b3AabbCL largeAabb = largeAabbs[i];
+               if( TestAabbAgainstAabb2(&smallAabb, &largeAabb) )
+               {
+                       int4 pair;
+                       pair.x = largeAabb.m_minIndices[3];
+                       pair.y = smallAabb.m_minIndices[3];
+                       pair.z = NEW_PAIR_MARKER;
+                       pair.w = NEW_PAIR_MARKER;
+                       
+                       int pairIndex = atomic_inc(out_numPairs);
+                       if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;
+               }
+       }
+}
+__kernel void plbvhLargeAabbRayTest(__global b3AabbCL* largeRigidAabbs, __global b3RayInfo* rays,
+                                                                       __global int* out_numRayRigidPairs,  __global int2* out_rayRigidPairs,
+                                                                       int numLargeAabbRigids, int maxRayRigidPairs, int numRays)
+{
+       int rayIndex = get_global_id(0);
+       if(rayIndex >= numRays) return;
+       
+       b3Vector3 rayFrom = rays[rayIndex].m_from;
+       b3Vector3 rayTo = rays[rayIndex].m_to;
+       b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);
+       b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );
+       
+       for(int i = 0; i < numLargeAabbRigids; ++i)
+       {
+               b3AabbCL rigidAabb = largeRigidAabbs[i];
+               if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, rigidAabb) )
+               {
+                       int2 rayRigidPair;
+                       rayRigidPair.x = rayIndex;
+                       rayRigidPair.y = rigidAabb.m_minIndices[3];
+                       
+                       int pairIndex = atomic_inc(out_numRayRigidPairs);
+                       if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;
+               }
+       }
+}
+
+
+//Set so that it is always greater than the actual common prefixes, and never selected as a parent node.
+//If there are no duplicates, then the highest common prefix is 32 or 64, depending on the number of bits used for the z-curve.
+//Duplicate common prefixes increase the highest common prefix at most by the number of bits used to index the leaf node.
+//Since 32 bit ints are used to index leaf nodes, the max prefix is 64(32 + 32 bit z-curve) or 96(32 + 64 bit z-curve).
+#define B3_PLBVH_INVALID_COMMON_PREFIX 128
+
+#define B3_PLBVH_ROOT_NODE_MARKER -1
+
+#define b3Int64 long
+
+int computeCommonPrefixLength(b3Int64 i, b3Int64 j) { return (int)clz(i ^ j); }
+b3Int64 computeCommonPrefix(b3Int64 i, b3Int64 j) 
+{
+       //This function only needs to return (i & j) in order for the algorithm to work,
+       //but it may help with debugging to mask out the lower bits.
+
+       b3Int64 commonPrefixLength = (b3Int64)computeCommonPrefixLength(i, j);
+
+       b3Int64 sharedBits = i & j;
+       b3Int64 bitmask = ((b3Int64)(~0)) << (64 - commonPrefixLength); //Set all bits after the common prefix to 0
+       
+       return sharedBits & bitmask;
+}
+
+//Same as computeCommonPrefixLength(), but allows for prefixes with different lengths
+int getSharedPrefixLength(b3Int64 prefixA, int prefixLengthA, b3Int64 prefixB, int prefixLengthB)
+{
+       return b3Min( computeCommonPrefixLength(prefixA, prefixB), b3Min(prefixLengthA, prefixLengthB) );
+}
+
+__kernel void computeAdjacentPairCommonPrefix(__global SortDataCL* mortonCodesAndAabbIndices,
+                                                                                       __global b3Int64* out_commonPrefixes,
+                                                                                       __global int* out_commonPrefixLengths,
+                                                                                       int numInternalNodes)
+{
+       int internalNodeIndex = get_global_id(0);
+       if (internalNodeIndex >= numInternalNodes) return;
+       
+       //Here, (internalNodeIndex + 1) is never out of bounds since it is a leaf node index,
+       //and the number of internal nodes is always numLeafNodes - 1
+       int leftLeafIndex = internalNodeIndex;
+       int rightLeafIndex = internalNodeIndex + 1;
+       
+       int leftLeafMortonCode = mortonCodesAndAabbIndices[leftLeafIndex].m_key;
+       int rightLeafMortonCode = mortonCodesAndAabbIndices[rightLeafIndex].m_key;
+       
+       //Binary radix tree construction algorithm does not work if there are duplicate morton codes.
+       //Append the index of each leaf node to each morton code so that there are no duplicates.
+       //The algorithm also requires that the morton codes are sorted in ascending order; this requirement
+       //is also satisfied with this method, as (leftLeafIndex < rightLeafIndex) is always true.
+       //
+       //upsample(a, b) == ( ((b3Int64)a) << 32) | b
+       b3Int64 nonduplicateLeftMortonCode = upsample(leftLeafMortonCode, leftLeafIndex);
+       b3Int64 nonduplicateRightMortonCode = upsample(rightLeafMortonCode, rightLeafIndex);
+       
+       out_commonPrefixes[internalNodeIndex] = computeCommonPrefix(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);
+       out_commonPrefixLengths[internalNodeIndex] = computeCommonPrefixLength(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);
+}
+
+
+__kernel void buildBinaryRadixTreeLeafNodes(__global int* commonPrefixLengths, __global int* out_leafNodeParentNodes,
+                                                                                       __global int2* out_childNodes, int numLeafNodes)
+{
+       int leafNodeIndex = get_global_id(0);
+       if (leafNodeIndex >= numLeafNodes) return;
+       
+       int numInternalNodes = numLeafNodes - 1;
+       
+       int leftSplitIndex = leafNodeIndex - 1;
+       int rightSplitIndex = leafNodeIndex;
+       
+       int leftCommonPrefix = (leftSplitIndex >= 0) ? commonPrefixLengths[leftSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
+       int rightCommonPrefix = (rightSplitIndex < numInternalNodes) ? commonPrefixLengths[rightSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
+       
+       //Parent node is the highest adjacent common prefix that is lower than the node's common prefix
+       //Leaf nodes are considered as having the highest common prefix
+       int isLeftHigherCommonPrefix = (leftCommonPrefix > rightCommonPrefix);
+       
+       //Handle cases for the edge nodes; the first and last node
+       //For leaf nodes, leftCommonPrefix and rightCommonPrefix should never both be B3_PLBVH_INVALID_COMMON_PREFIX
+       if(leftCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = false;
+       if(rightCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = true;
+       
+       int parentNodeIndex = (isLeftHigherCommonPrefix) ? leftSplitIndex : rightSplitIndex;
+       out_leafNodeParentNodes[leafNodeIndex] = parentNodeIndex;
+       
+       int isRightChild = (isLeftHigherCommonPrefix);  //If the left node is the parent, then this node is its right child and vice versa
+       
+       //out_childNodesAsInt[0] == int2.x == left child
+       //out_childNodesAsInt[1] == int2.y == right child
+       int isLeaf = 1;
+       __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);
+       out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, leafNodeIndex);
+}
+
+__kernel void buildBinaryRadixTreeInternalNodes(__global b3Int64* commonPrefixes, __global int* commonPrefixLengths,
+                                                                                               __global int2* out_childNodes,
+                                                                                               __global int* out_internalNodeParentNodes, __global int* out_rootNodeIndex,
+                                                                                               int numInternalNodes)
+{
+       int internalNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);
+       if(internalNodeIndex >= numInternalNodes) return;
+       
+       b3Int64 nodePrefix = commonPrefixes[internalNodeIndex];
+       int nodePrefixLength = commonPrefixLengths[internalNodeIndex];
+       
+//#define USE_LINEAR_SEARCH
+#ifdef USE_LINEAR_SEARCH
+       int leftIndex = -1;
+       int rightIndex = -1;
+       
+       //Find nearest element to left with a lower common prefix
+       for(int i = internalNodeIndex - 1; i >= 0; --i)
+       {
+               int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);
+               if(nodeLeftSharedPrefixLength < nodePrefixLength)
+               {
+                       leftIndex = i;
+                       break;
+               }
+       }
+       
+       //Find nearest element to right with a lower common prefix
+       for(int i = internalNodeIndex + 1; i < numInternalNodes; ++i)
+       {
+               int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);
+               if(nodeRightSharedPrefixLength < nodePrefixLength)
+               {
+                       rightIndex = i;
+                       break;
+               }
+       }
+       
+#else //Use binary search
+
+       //Find nearest element to left with a lower common prefix
+       int leftIndex = -1;
+       {
+               int lower = 0;
+               int upper = internalNodeIndex - 1;
+               
+               while(lower <= upper)
+               {
+                       int mid = (lower + upper) / 2;
+                       b3Int64 midPrefix = commonPrefixes[mid];
+                       int midPrefixLength = commonPrefixLengths[mid];
+                       
+                       int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);
+                       if(nodeMidSharedPrefixLength < nodePrefixLength) 
+                       {
+                               int right = mid + 1;
+                               if(right < internalNodeIndex)
+                               {
+                                       b3Int64 rightPrefix = commonPrefixes[right];
+                                       int rightPrefixLength = commonPrefixLengths[right];
+                                       
+                                       int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, rightPrefix, rightPrefixLength);
+                                       if(nodeRightSharedPrefixLength < nodePrefixLength) 
+                                       {
+                                               lower = right;
+                                               leftIndex = right;
+                                       }
+                                       else 
+                                       {
+                                               leftIndex = mid;
+                                               break;
+                                       }
+                               }
+                               else 
+                               {
+                                       leftIndex = mid;
+                                       break;
+                               }
+                       }
+                       else upper = mid - 1;
+               }
+       }
+       
+       //Find nearest element to right with a lower common prefix
+       int rightIndex = -1;
+       {
+               int lower = internalNodeIndex + 1;
+               int upper = numInternalNodes - 1;
+               
+               while(lower <= upper)
+               {
+                       int mid = (lower + upper) / 2;
+                       b3Int64 midPrefix = commonPrefixes[mid];
+                       int midPrefixLength = commonPrefixLengths[mid];
+                       
+                       int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);
+                       if(nodeMidSharedPrefixLength < nodePrefixLength) 
+                       {
+                               int left = mid - 1;
+                               if(left > internalNodeIndex)
+                               {
+                                       b3Int64 leftPrefix = commonPrefixes[left];
+                                       int leftPrefixLength = commonPrefixLengths[left];
+                               
+                                       int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, leftPrefix, leftPrefixLength);
+                                       if(nodeLeftSharedPrefixLength < nodePrefixLength) 
+                                       {
+                                               upper = left;
+                                               rightIndex = left;
+                                       }
+                                       else 
+                                       {
+                                               rightIndex = mid;
+                                               break;
+                                       }
+                               }
+                               else 
+                               {
+                                       rightIndex = mid;
+                                       break;
+                               }
+                       }
+                       else lower = mid + 1;
+               }
+       }
+#endif
+       
+       //Select parent
+       {
+               int leftPrefixLength = (leftIndex != -1) ? commonPrefixLengths[leftIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
+               int rightPrefixLength =  (rightIndex != -1) ? commonPrefixLengths[rightIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
+               
+               int isLeftHigherPrefixLength = (leftPrefixLength > rightPrefixLength);
+               
+               if(leftPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = false;
+               else if(rightPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = true;
+               
+               int parentNodeIndex = (isLeftHigherPrefixLength) ? leftIndex : rightIndex;
+               
+               int isRootNode = (leftIndex == -1 && rightIndex == -1);
+               out_internalNodeParentNodes[internalNodeIndex] = (!isRootNode) ? parentNodeIndex : B3_PLBVH_ROOT_NODE_MARKER;
+               
+               int isLeaf = 0;
+               if(!isRootNode)
+               {
+                       int isRightChild = (isLeftHigherPrefixLength);  //If the left node is the parent, then this node is its right child and vice versa
+                       
+                       //out_childNodesAsInt[0] == int2.x == left child
+                       //out_childNodesAsInt[1] == int2.y == right child
+                       __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);
+                       out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);
+               }
+               else *out_rootNodeIndex = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);
+       }
+}
+
+__kernel void findDistanceFromRoot(__global int* rootNodeIndex, __global int* internalNodeParentNodes,
+                                                                       __global int* out_maxDistanceFromRoot, __global int* out_distanceFromRoot, int numInternalNodes)
+{
+       if( get_global_id(0) == 0 ) atomic_xchg(out_maxDistanceFromRoot, 0);
+
+       int internalNodeIndex = get_global_id(0);
+       if(internalNodeIndex >= numInternalNodes) return;
+       
+       //
+       int distanceFromRoot = 0;
+       {
+               int parentIndex = internalNodeParentNodes[internalNodeIndex];
+               while(parentIndex != B3_PLBVH_ROOT_NODE_MARKER)
+               {
+                       parentIndex = internalNodeParentNodes[parentIndex];
+                       ++distanceFromRoot;
+               }
+       }
+       out_distanceFromRoot[internalNodeIndex] = distanceFromRoot;
+       
+       //
+       __local int localMaxDistanceFromRoot;
+       if( get_local_id(0) == 0 ) localMaxDistanceFromRoot = 0;
+       barrier(CLK_LOCAL_MEM_FENCE);
+       
+       atomic_max(&localMaxDistanceFromRoot, distanceFromRoot);
+       barrier(CLK_LOCAL_MEM_FENCE);
+       
+       if( get_local_id(0) == 0 ) atomic_max(out_maxDistanceFromRoot, localMaxDistanceFromRoot);
+}
+
+__kernel void buildBinaryRadixTreeAabbsRecursive(__global int* distanceFromRoot, __global SortDataCL* mortonCodesAndAabbIndices,
+                                                                                               __global int2* childNodes,
+                                                                                               __global b3AabbCL* leafNodeAabbs, __global b3AabbCL* internalNodeAabbs,
+                                                                                               int maxDistanceFromRoot, int processedDistance, int numInternalNodes)
+{
+       int internalNodeIndex = get_global_id(0);
+       if(internalNodeIndex >= numInternalNodes) return;
+       
+       int distance = distanceFromRoot[internalNodeIndex];
+       
+       if(distance == processedDistance)
+       {
+               int leftChildIndex = childNodes[internalNodeIndex].x;
+               int rightChildIndex = childNodes[internalNodeIndex].y;
+               
+               int isLeftChildLeaf = isLeafNode(leftChildIndex);
+               int isRightChildLeaf = isLeafNode(rightChildIndex);
+               
+               leftChildIndex = getIndexWithInternalNodeMarkerRemoved(leftChildIndex);
+               rightChildIndex = getIndexWithInternalNodeMarkerRemoved(rightChildIndex);
+               
+               //leftRigidIndex/rightRigidIndex is not used if internal node
+               int leftRigidIndex = (isLeftChildLeaf) ? mortonCodesAndAabbIndices[leftChildIndex].m_value : -1;
+               int rightRigidIndex = (isRightChildLeaf) ? mortonCodesAndAabbIndices[rightChildIndex].m_value : -1;
+               
+               b3AabbCL leftChildAabb = (isLeftChildLeaf) ? leafNodeAabbs[leftRigidIndex] : internalNodeAabbs[leftChildIndex];
+               b3AabbCL rightChildAabb = (isRightChildLeaf) ? leafNodeAabbs[rightRigidIndex] : internalNodeAabbs[rightChildIndex];
+               
+               b3AabbCL mergedAabb;
+               mergedAabb.m_min = b3Min(leftChildAabb.m_min, rightChildAabb.m_min);
+               mergedAabb.m_max = b3Max(leftChildAabb.m_max, rightChildAabb.m_max);
+               internalNodeAabbs[internalNodeIndex] = mergedAabb;
+       }
+}
+
+__kernel void findLeafIndexRanges(__global int2* internalNodeChildNodes, __global int2* out_leafIndexRanges, int numInternalNodes)
+{
+       int internalNodeIndex = get_global_id(0);
+       if(internalNodeIndex >= numInternalNodes) return;
+       
+       int numLeafNodes = numInternalNodes + 1;
+       
+       int2 childNodes = internalNodeChildNodes[internalNodeIndex];
+       
+       int2 leafIndexRange;    //x == min leaf index, y == max leaf index
+       
+       //Find lowest leaf index covered by this internal node
+       {
+               int lowestIndex = childNodes.x;         //childNodes.x == Left child
+               while( !isLeafNode(lowestIndex) ) lowestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(lowestIndex) ].x;
+               leafIndexRange.x = lowestIndex;
+       }
+       
+       //Find highest leaf index covered by this internal node
+       {
+               int highestIndex = childNodes.y;        //childNodes.y == Right child
+               while( !isLeafNode(highestIndex) ) highestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(highestIndex) ].y;
+               leafIndexRange.y = highestIndex;
+       }
+       
+       //
+       out_leafIndexRanges[internalNodeIndex] = leafIndexRange;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h
new file mode 100644 (file)
index 0000000..c02877d
--- /dev/null
@@ -0,0 +1,728 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* parallelLinearBvhCL =
+       "/*\n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose,\n"
+       "including commercial applications, and to alter it and redistribute it freely,\n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Initial Author Jackson Lee, 2014\n"
+       "typedef float b3Scalar;\n"
+       "typedef float4 b3Vector3;\n"
+       "#define b3Max max\n"
+       "#define b3Min min\n"
+       "#define b3Sqrt sqrt\n"
+       "typedef struct\n"
+       "{\n"
+       "       unsigned int m_key;\n"
+       "       unsigned int m_value;\n"
+       "} SortDataCL;\n"
+       "typedef struct \n"
+       "{\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_min;\n"
+       "               float   m_minElems[4];\n"
+       "               int                     m_minIndices[4];\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_max;\n"
+       "               float   m_maxElems[4];\n"
+       "               int                     m_maxIndices[4];\n"
+       "       };\n"
+       "} b3AabbCL;\n"
+       "unsigned int interleaveBits(unsigned int x)\n"
+       "{\n"
+       "       //........ ........ ......12 3456789A   //x\n"
+       "       //....1..2 ..3..4.. 5..6..7. .8..9..A   //x after interleaving bits\n"
+       "       \n"
+       "       //......12 3456789A ......12 3456789A   //x ^ (x << 16)\n"
+       "       //11111111 ........ ........ 11111111   //0x FF 00 00 FF\n"
+       "       //......12 ........ ........ 3456789A   //x = (x ^ (x << 16)) & 0xFF0000FF;\n"
+       "       \n"
+       "       //......12 ........ 3456789A 3456789A   //x ^ (x <<  8)\n"
+       "       //......11 ........ 1111.... ....1111   //0x 03 00 F0 0F\n"
+       "       //......12 ........ 3456.... ....789A   //x = (x ^ (x <<  8)) & 0x0300F00F;\n"
+       "       \n"
+       "       //..12..12 ....3456 3456.... 789A789A   //x ^ (x <<  4)\n"
+       "       //......11 ....11.. ..11.... 11....11   //0x 03 0C 30 C3\n"
+       "       //......12 ....34.. ..56.... 78....9A   //x = (x ^ (x <<  4)) & 0x030C30C3;\n"
+       "       \n"
+       "       //....1212 ..3434.. 5656..78 78..9A9A   //x ^ (x <<  2)\n"
+       "       //....1..1 ..1..1.. 1..1..1. .1..1..1   //0x 09 24 92 49\n"
+       "       //....1..2 ..3..4.. 5..6..7. .8..9..A   //x = (x ^ (x <<  2)) & 0x09249249;\n"
+       "       \n"
+       "       //........ ........ ......11 11111111   //0x000003FF\n"
+       "       x &= 0x000003FF;                //Clear all bits above bit 10\n"
+       "       \n"
+       "       x = (x ^ (x << 16)) & 0xFF0000FF;\n"
+       "       x = (x ^ (x <<  8)) & 0x0300F00F;\n"
+       "       x = (x ^ (x <<  4)) & 0x030C30C3;\n"
+       "       x = (x ^ (x <<  2)) & 0x09249249;\n"
+       "       \n"
+       "       return x;\n"
+       "}\n"
+       "unsigned int getMortonCode(unsigned int x, unsigned int y, unsigned int z)\n"
+       "{\n"
+       "       return interleaveBits(x) << 0 | interleaveBits(y) << 1 | interleaveBits(z) << 2;\n"
+       "}\n"
+       "__kernel void separateAabbs(__global b3AabbCL* unseparatedAabbs, __global int* aabbIndices, __global b3AabbCL* out_aabbs, int numAabbsToSeparate)\n"
+       "{\n"
+       "       int separatedAabbIndex = get_global_id(0);\n"
+       "       if(separatedAabbIndex >= numAabbsToSeparate) return;\n"
+       "       int unseparatedAabbIndex = aabbIndices[separatedAabbIndex];\n"
+       "       out_aabbs[separatedAabbIndex] = unseparatedAabbs[unseparatedAabbIndex];\n"
+       "}\n"
+       "//Should replace with an optimized parallel reduction\n"
+       "__kernel void findAllNodesMergedAabb(__global b3AabbCL* out_mergedAabb, int numAabbsNeedingMerge)\n"
+       "{\n"
+       "       //Each time this kernel is added to the command queue, \n"
+       "       //the number of AABBs needing to be merged is halved\n"
+       "       //\n"
+       "       //Example with 159 AABBs:\n"
+       "       //      numRemainingAabbs == 159 / 2 + 159 % 2 == 80\n"
+       "       //      numMergedAabbs == 159 - 80 == 79\n"
+       "       //So, indices [0, 78] are merged with [0 + 80, 78 + 80]\n"
+       "       \n"
+       "       int numRemainingAabbs = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2;\n"
+       "       int numMergedAabbs = numAabbsNeedingMerge - numRemainingAabbs;\n"
+       "       \n"
+       "       int aabbIndex = get_global_id(0);\n"
+       "       if(aabbIndex >= numMergedAabbs) return;\n"
+       "       \n"
+       "       int otherAabbIndex = aabbIndex + numRemainingAabbs;\n"
+       "       \n"
+       "       b3AabbCL aabb = out_mergedAabb[aabbIndex];\n"
+       "       b3AabbCL otherAabb = out_mergedAabb[otherAabbIndex];\n"
+       "               \n"
+       "       b3AabbCL mergedAabb;\n"
+       "       mergedAabb.m_min = b3Min(aabb.m_min, otherAabb.m_min);\n"
+       "       mergedAabb.m_max = b3Max(aabb.m_max, otherAabb.m_max);\n"
+       "       out_mergedAabb[aabbIndex] = mergedAabb;\n"
+       "}\n"
+       "__kernel void assignMortonCodesAndAabbIndicies(__global b3AabbCL* worldSpaceAabbs, __global b3AabbCL* mergedAabbOfAllNodes, \n"
+       "                                                                                               __global SortDataCL* out_mortonCodesAndAabbIndices, int numAabbs)\n"
+       "{\n"
+       "       int leafNodeIndex = get_global_id(0);   //Leaf node index == AABB index\n"
+       "       if(leafNodeIndex >= numAabbs) return;\n"
+       "       \n"
+       "       b3AabbCL mergedAabb = mergedAabbOfAllNodes[0];\n"
+       "       b3Vector3 gridCenter = (mergedAabb.m_min + mergedAabb.m_max) * 0.5f;\n"
+       "       b3Vector3 gridCellSize = (mergedAabb.m_max - mergedAabb.m_min) / (float)1024;\n"
+       "       \n"
+       "       b3AabbCL aabb = worldSpaceAabbs[leafNodeIndex];\n"
+       "       b3Vector3 aabbCenter = (aabb.m_min + aabb.m_max) * 0.5f;\n"
+       "       b3Vector3 aabbCenterRelativeToGrid = aabbCenter - gridCenter;\n"
+       "       \n"
+       "       //Quantize into integer coordinates\n"
+       "       //floor() is needed to prevent the center cell, at (0,0,0) from being twice the size\n"
+       "       b3Vector3 gridPosition = aabbCenterRelativeToGrid / gridCellSize;\n"
+       "       \n"
+       "       int4 discretePosition;\n"
+       "       discretePosition.x = (int)( (gridPosition.x >= 0.0f) ? gridPosition.x : floor(gridPosition.x) );\n"
+       "       discretePosition.y = (int)( (gridPosition.y >= 0.0f) ? gridPosition.y : floor(gridPosition.y) );\n"
+       "       discretePosition.z = (int)( (gridPosition.z >= 0.0f) ? gridPosition.z : floor(gridPosition.z) );\n"
+       "       \n"
+       "       //Clamp coordinates into [-512, 511], then convert range from [-512, 511] to [0, 1023]\n"
+       "       discretePosition = b3Max( -512, b3Min(discretePosition, 511) );\n"
+       "       discretePosition += 512;\n"
+       "       \n"
+       "       //Interleave bits(assign a morton code, also known as a z-curve)\n"
+       "       unsigned int mortonCode = getMortonCode(discretePosition.x, discretePosition.y, discretePosition.z);\n"
+       "       \n"
+       "       //\n"
+       "       SortDataCL mortonCodeIndexPair;\n"
+       "       mortonCodeIndexPair.m_key = mortonCode;\n"
+       "       mortonCodeIndexPair.m_value = leafNodeIndex;\n"
+       "       \n"
+       "       out_mortonCodesAndAabbIndices[leafNodeIndex] = mortonCodeIndexPair;\n"
+       "}\n"
+       "#define B3_PLVBH_TRAVERSE_MAX_STACK_SIZE 128\n"
+       "//The most significant bit(0x80000000) of a int32 is used to distinguish between leaf and internal nodes.\n"
+       "//If it is set, then the index is for an internal node; otherwise, it is a leaf node. \n"
+       "//In both cases, the bit should be cleared to access the actual node index.\n"
+       "int isLeafNode(int index) { return (index >> 31 == 0); }\n"
+       "int getIndexWithInternalNodeMarkerRemoved(int index) { return index & (~0x80000000); }\n"
+       "int getIndexWithInternalNodeMarkerSet(int isLeaf, int index) { return (isLeaf) ? index : (index | 0x80000000); }\n"
+       "//From sap.cl\n"
+       "#define NEW_PAIR_MARKER -1\n"
+       "bool TestAabbAgainstAabb2(const b3AabbCL* aabb1, const b3AabbCL* aabb2)\n"
+       "{\n"
+       "       bool overlap = true;\n"
+       "       overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+       "       overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+       "       overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+       "       return overlap;\n"
+       "}\n"
+       "//From sap.cl\n"
+       "__kernel void plbvhCalculateOverlappingPairs(__global b3AabbCL* rigidAabbs, \n"
+       "                                                                                       __global int* rootNodeIndex, \n"
+       "                                                                                       __global int2* internalNodeChildIndices, \n"
+       "                                                                                       __global b3AabbCL* internalNodeAabbs,\n"
+       "                                                                                       __global int2* internalNodeLeafIndexRanges,\n"
+       "                                                                                       \n"
+       "                                                                                       __global SortDataCL* mortonCodesAndAabbIndices,\n"
+       "                                                                                       __global int* out_numPairs, __global int4* out_overlappingPairs, \n"
+       "                                                                                       int maxPairs, int numQueryAabbs)\n"
+       "{\n"
+       "       //Using get_group_id()/get_local_id() is Faster than get_global_id(0) since\n"
+       "       //mortonCodesAndAabbIndices[] contains rigid body indices sorted along the z-curve (more spatially coherent)\n"
+       "       int queryBvhNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);\n"
+       "       if(queryBvhNodeIndex >= numQueryAabbs) return;\n"
+       "       \n"
+       "       int queryRigidIndex = mortonCodesAndAabbIndices[queryBvhNodeIndex].m_value;\n"
+       "       b3AabbCL queryAabb = rigidAabbs[queryRigidIndex];\n"
+       "       \n"
+       "       int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];\n"
+       "       \n"
+       "       int stackSize = 1;\n"
+       "       stack[0] = *rootNodeIndex;\n"
+       "       \n"
+       "       while(stackSize)\n"
+       "       {\n"
+       "               int internalOrLeafNodeIndex = stack[ stackSize - 1 ];\n"
+       "               --stackSize;\n"
+       "               \n"
+       "               int isLeaf = isLeafNode(internalOrLeafNodeIndex);       //Internal node if false\n"
+       "               int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);\n"
+       "               \n"
+       "               //Optimization - if the BVH is structured as a binary radix tree, then\n"
+       "               //each internal node corresponds to a contiguous range of leaf nodes(internalNodeLeafIndexRanges[]).\n"
+       "               //This can be used to avoid testing each AABB-AABB pair twice, including preventing each node from colliding with itself.\n"
+       "               {\n"
+       "                       int highestLeafIndex = (isLeaf) ? bvhNodeIndex : internalNodeLeafIndexRanges[bvhNodeIndex].y;\n"
+       "                       if(highestLeafIndex <= queryBvhNodeIndex) continue;\n"
+       "               }\n"
+       "               \n"
+       "               //bvhRigidIndex is not used if internal node\n"
+       "               int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;\n"
+       "       \n"
+       "               b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];\n"
+       "               if( TestAabbAgainstAabb2(&queryAabb, &bvhNodeAabb) )\n"
+       "               {\n"
+       "                       if(isLeaf)\n"
+       "                       {\n"
+       "                               int4 pair;\n"
+       "                               pair.x = rigidAabbs[queryRigidIndex].m_minIndices[3];\n"
+       "                               pair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];\n"
+       "                               pair.z = NEW_PAIR_MARKER;\n"
+       "                               pair.w = NEW_PAIR_MARKER;\n"
+       "                               \n"
+       "                               int pairIndex = atomic_inc(out_numPairs);\n"
+       "                               if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;\n"
+       "                       }\n"
+       "                       \n"
+       "                       if(!isLeaf)     //Internal node\n"
+       "                       {\n"
+       "                               if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)\n"
+       "                               {\n"
+       "                                       //Error\n"
+       "                               }\n"
+       "                               else\n"
+       "                               {\n"
+       "                                       stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;\n"
+       "                                       stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "       }\n"
+       "}\n"
+       "//From rayCastKernels.cl\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_from;\n"
+       "       float4 m_to;\n"
+       "} b3RayInfo;\n"
+       "//From rayCastKernels.cl\n"
+       "b3Vector3 b3Vector3_normalize(b3Vector3 v)\n"
+       "{\n"
+       "       b3Vector3 normal = (b3Vector3){v.x, v.y, v.z, 0.f};\n"
+       "       return normalize(normal);       //OpenCL normalize == vector4 normalize\n"
+       "}\n"
+       "b3Scalar b3Vector3_length2(b3Vector3 v) { return v.x*v.x + v.y*v.y + v.z*v.z; }\n"
+       "b3Scalar b3Vector3_dot(b3Vector3 a, b3Vector3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; }\n"
+       "int rayIntersectsAabb(b3Vector3 rayOrigin, b3Scalar rayLength, b3Vector3 rayNormalizedDirection, b3AabbCL aabb)\n"
+       "{\n"
+       "       //AABB is considered as 3 pairs of 2 planes( {x_min, x_max}, {y_min, y_max}, {z_min, z_max} ).\n"
+       "       //t_min is the point of intersection with the closer plane, t_max is the point of intersection with the farther plane.\n"
+       "       //\n"
+       "       //if (rayNormalizedDirection.x < 0.0f), then max.x will be the near plane \n"
+       "       //and min.x will be the far plane; otherwise, it is reversed.\n"
+       "       //\n"
+       "       //In order for there to be a collision, the t_min and t_max of each pair must overlap.\n"
+       "       //This can be tested for by selecting the highest t_min and lowest t_max and comparing them.\n"
+       "       \n"
+       "       int4 isNegative = isless( rayNormalizedDirection, ((b3Vector3){0.0f, 0.0f, 0.0f, 0.0f}) );      //isless(x,y) returns (x < y)\n"
+       "       \n"
+       "       //When using vector types, the select() function checks the most signficant bit, \n"
+       "       //but isless() sets the least significant bit.\n"
+       "       isNegative <<= 31;\n"
+       "       //select(b, a, condition) == condition ? a : b\n"
+       "       //When using select() with vector types, (condition[i]) is true if its most significant bit is 1\n"
+       "       b3Vector3 t_min = ( select(aabb.m_min, aabb.m_max, isNegative) - rayOrigin ) / rayNormalizedDirection;\n"
+       "       b3Vector3 t_max = ( select(aabb.m_max, aabb.m_min, isNegative) - rayOrigin ) / rayNormalizedDirection;\n"
+       "       \n"
+       "       b3Scalar t_min_final = 0.0f;\n"
+       "       b3Scalar t_max_final = rayLength;\n"
+       "       \n"
+       "       //Must use fmin()/fmax(); if one of the parameters is NaN, then the parameter that is not NaN is returned. \n"
+       "       //Behavior of min()/max() with NaNs is undefined. (See OpenCL Specification 1.2 [6.12.2] and [6.12.4])\n"
+       "       //Since the innermost fmin()/fmax() is always not NaN, this should never return NaN.\n"
+       "       t_min_final = fmax( t_min.z, fmax(t_min.y, fmax(t_min.x, t_min_final)) );\n"
+       "       t_max_final = fmin( t_max.z, fmin(t_max.y, fmin(t_max.x, t_max_final)) );\n"
+       "       \n"
+       "       return (t_min_final <= t_max_final);\n"
+       "}\n"
+       "__kernel void plbvhRayTraverse(__global b3AabbCL* rigidAabbs,\n"
+       "                                                               __global int* rootNodeIndex, \n"
+       "                                                               __global int2* internalNodeChildIndices, \n"
+       "                                                               __global b3AabbCL* internalNodeAabbs,\n"
+       "                                                               __global int2* internalNodeLeafIndexRanges,\n"
+       "                                                               __global SortDataCL* mortonCodesAndAabbIndices,\n"
+       "                                                               \n"
+       "                                                               __global b3RayInfo* rays,\n"
+       "                                                               \n"
+       "                                                               __global int* out_numRayRigidPairs, \n"
+       "                                                               __global int2* out_rayRigidPairs,\n"
+       "                                                               int maxRayRigidPairs, int numRays)\n"
+       "{\n"
+       "       int rayIndex = get_global_id(0);\n"
+       "       if(rayIndex >= numRays) return;\n"
+       "       \n"
+       "       //\n"
+       "       b3Vector3 rayFrom = rays[rayIndex].m_from;\n"
+       "       b3Vector3 rayTo = rays[rayIndex].m_to;\n"
+       "       b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);\n"
+       "       b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );\n"
+       "       \n"
+       "       //\n"
+       "       int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];\n"
+       "       \n"
+       "       int stackSize = 1;\n"
+       "       stack[0] = *rootNodeIndex;\n"
+       "       \n"
+       "       while(stackSize)\n"
+       "       {\n"
+       "               int internalOrLeafNodeIndex = stack[ stackSize - 1 ];\n"
+       "               --stackSize;\n"
+       "               \n"
+       "               int isLeaf = isLeafNode(internalOrLeafNodeIndex);       //Internal node if false\n"
+       "               int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);\n"
+       "               \n"
+       "               //bvhRigidIndex is not used if internal node\n"
+       "               int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;\n"
+       "       \n"
+       "               b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];\n"
+       "               if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, bvhNodeAabb)  )\n"
+       "               {\n"
+       "                       if(isLeaf)\n"
+       "                       {\n"
+       "                               int2 rayRigidPair;\n"
+       "                               rayRigidPair.x = rayIndex;\n"
+       "                               rayRigidPair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];\n"
+       "                               \n"
+       "                               int pairIndex = atomic_inc(out_numRayRigidPairs);\n"
+       "                               if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;\n"
+       "                       }\n"
+       "                       \n"
+       "                       if(!isLeaf)     //Internal node\n"
+       "                       {\n"
+       "                               if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)\n"
+       "                               {\n"
+       "                                       //Error\n"
+       "                               }\n"
+       "                               else\n"
+       "                               {\n"
+       "                                       stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;\n"
+       "                                       stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__kernel void plbvhLargeAabbAabbTest(__global b3AabbCL* smallAabbs, __global b3AabbCL* largeAabbs, \n"
+       "                                                                       __global int* out_numPairs, __global int4* out_overlappingPairs, \n"
+       "                                                                       int maxPairs, int numLargeAabbRigids, int numSmallAabbRigids)\n"
+       "{\n"
+       "       int smallAabbIndex = get_global_id(0);\n"
+       "       if(smallAabbIndex >= numSmallAabbRigids) return;\n"
+       "       \n"
+       "       b3AabbCL smallAabb = smallAabbs[smallAabbIndex];\n"
+       "       for(int i = 0; i < numLargeAabbRigids; ++i)\n"
+       "       {\n"
+       "               b3AabbCL largeAabb = largeAabbs[i];\n"
+       "               if( TestAabbAgainstAabb2(&smallAabb, &largeAabb) )\n"
+       "               {\n"
+       "                       int4 pair;\n"
+       "                       pair.x = largeAabb.m_minIndices[3];\n"
+       "                       pair.y = smallAabb.m_minIndices[3];\n"
+       "                       pair.z = NEW_PAIR_MARKER;\n"
+       "                       pair.w = NEW_PAIR_MARKER;\n"
+       "                       \n"
+       "                       int pairIndex = atomic_inc(out_numPairs);\n"
+       "                       if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__kernel void plbvhLargeAabbRayTest(__global b3AabbCL* largeRigidAabbs, __global b3RayInfo* rays,\n"
+       "                                                                       __global int* out_numRayRigidPairs,  __global int2* out_rayRigidPairs,\n"
+       "                                                                       int numLargeAabbRigids, int maxRayRigidPairs, int numRays)\n"
+       "{\n"
+       "       int rayIndex = get_global_id(0);\n"
+       "       if(rayIndex >= numRays) return;\n"
+       "       \n"
+       "       b3Vector3 rayFrom = rays[rayIndex].m_from;\n"
+       "       b3Vector3 rayTo = rays[rayIndex].m_to;\n"
+       "       b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);\n"
+       "       b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );\n"
+       "       \n"
+       "       for(int i = 0; i < numLargeAabbRigids; ++i)\n"
+       "       {\n"
+       "               b3AabbCL rigidAabb = largeRigidAabbs[i];\n"
+       "               if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, rigidAabb) )\n"
+       "               {\n"
+       "                       int2 rayRigidPair;\n"
+       "                       rayRigidPair.x = rayIndex;\n"
+       "                       rayRigidPair.y = rigidAabb.m_minIndices[3];\n"
+       "                       \n"
+       "                       int pairIndex = atomic_inc(out_numRayRigidPairs);\n"
+       "                       if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "//Set so that it is always greater than the actual common prefixes, and never selected as a parent node.\n"
+       "//If there are no duplicates, then the highest common prefix is 32 or 64, depending on the number of bits used for the z-curve.\n"
+       "//Duplicate common prefixes increase the highest common prefix at most by the number of bits used to index the leaf node.\n"
+       "//Since 32 bit ints are used to index leaf nodes, the max prefix is 64(32 + 32 bit z-curve) or 96(32 + 64 bit z-curve).\n"
+       "#define B3_PLBVH_INVALID_COMMON_PREFIX 128\n"
+       "#define B3_PLBVH_ROOT_NODE_MARKER -1\n"
+       "#define b3Int64 long\n"
+       "int computeCommonPrefixLength(b3Int64 i, b3Int64 j) { return (int)clz(i ^ j); }\n"
+       "b3Int64 computeCommonPrefix(b3Int64 i, b3Int64 j) \n"
+       "{\n"
+       "       //This function only needs to return (i & j) in order for the algorithm to work,\n"
+       "       //but it may help with debugging to mask out the lower bits.\n"
+       "       b3Int64 commonPrefixLength = (b3Int64)computeCommonPrefixLength(i, j);\n"
+       "       b3Int64 sharedBits = i & j;\n"
+       "       b3Int64 bitmask = ((b3Int64)(~0)) << (64 - commonPrefixLength); //Set all bits after the common prefix to 0\n"
+       "       \n"
+       "       return sharedBits & bitmask;\n"
+       "}\n"
+       "//Same as computeCommonPrefixLength(), but allows for prefixes with different lengths\n"
+       "int getSharedPrefixLength(b3Int64 prefixA, int prefixLengthA, b3Int64 prefixB, int prefixLengthB)\n"
+       "{\n"
+       "       return b3Min( computeCommonPrefixLength(prefixA, prefixB), b3Min(prefixLengthA, prefixLengthB) );\n"
+       "}\n"
+       "__kernel void computeAdjacentPairCommonPrefix(__global SortDataCL* mortonCodesAndAabbIndices,\n"
+       "                                                                                       __global b3Int64* out_commonPrefixes,\n"
+       "                                                                                       __global int* out_commonPrefixLengths,\n"
+       "                                                                                       int numInternalNodes)\n"
+       "{\n"
+       "       int internalNodeIndex = get_global_id(0);\n"
+       "       if (internalNodeIndex >= numInternalNodes) return;\n"
+       "       \n"
+       "       //Here, (internalNodeIndex + 1) is never out of bounds since it is a leaf node index,\n"
+       "       //and the number of internal nodes is always numLeafNodes - 1\n"
+       "       int leftLeafIndex = internalNodeIndex;\n"
+       "       int rightLeafIndex = internalNodeIndex + 1;\n"
+       "       \n"
+       "       int leftLeafMortonCode = mortonCodesAndAabbIndices[leftLeafIndex].m_key;\n"
+       "       int rightLeafMortonCode = mortonCodesAndAabbIndices[rightLeafIndex].m_key;\n"
+       "       \n"
+       "       //Binary radix tree construction algorithm does not work if there are duplicate morton codes.\n"
+       "       //Append the index of each leaf node to each morton code so that there are no duplicates.\n"
+       "       //The algorithm also requires that the morton codes are sorted in ascending order; this requirement\n"
+       "       //is also satisfied with this method, as (leftLeafIndex < rightLeafIndex) is always true.\n"
+       "       //\n"
+       "       //upsample(a, b) == ( ((b3Int64)a) << 32) | b\n"
+       "       b3Int64 nonduplicateLeftMortonCode = upsample(leftLeafMortonCode, leftLeafIndex);\n"
+       "       b3Int64 nonduplicateRightMortonCode = upsample(rightLeafMortonCode, rightLeafIndex);\n"
+       "       \n"
+       "       out_commonPrefixes[internalNodeIndex] = computeCommonPrefix(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);\n"
+       "       out_commonPrefixLengths[internalNodeIndex] = computeCommonPrefixLength(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);\n"
+       "}\n"
+       "__kernel void buildBinaryRadixTreeLeafNodes(__global int* commonPrefixLengths, __global int* out_leafNodeParentNodes,\n"
+       "                                                                                       __global int2* out_childNodes, int numLeafNodes)\n"
+       "{\n"
+       "       int leafNodeIndex = get_global_id(0);\n"
+       "       if (leafNodeIndex >= numLeafNodes) return;\n"
+       "       \n"
+       "       int numInternalNodes = numLeafNodes - 1;\n"
+       "       \n"
+       "       int leftSplitIndex = leafNodeIndex - 1;\n"
+       "       int rightSplitIndex = leafNodeIndex;\n"
+       "       \n"
+       "       int leftCommonPrefix = (leftSplitIndex >= 0) ? commonPrefixLengths[leftSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+       "       int rightCommonPrefix = (rightSplitIndex < numInternalNodes) ? commonPrefixLengths[rightSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+       "       \n"
+       "       //Parent node is the highest adjacent common prefix that is lower than the node's common prefix\n"
+       "       //Leaf nodes are considered as having the highest common prefix\n"
+       "       int isLeftHigherCommonPrefix = (leftCommonPrefix > rightCommonPrefix);\n"
+       "       \n"
+       "       //Handle cases for the edge nodes; the first and last node\n"
+       "       //For leaf nodes, leftCommonPrefix and rightCommonPrefix should never both be B3_PLBVH_INVALID_COMMON_PREFIX\n"
+       "       if(leftCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = false;\n"
+       "       if(rightCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = true;\n"
+       "       \n"
+       "       int parentNodeIndex = (isLeftHigherCommonPrefix) ? leftSplitIndex : rightSplitIndex;\n"
+       "       out_leafNodeParentNodes[leafNodeIndex] = parentNodeIndex;\n"
+       "       \n"
+       "       int isRightChild = (isLeftHigherCommonPrefix);  //If the left node is the parent, then this node is its right child and vice versa\n"
+       "       \n"
+       "       //out_childNodesAsInt[0] == int2.x == left child\n"
+       "       //out_childNodesAsInt[1] == int2.y == right child\n"
+       "       int isLeaf = 1;\n"
+       "       __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);\n"
+       "       out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, leafNodeIndex);\n"
+       "}\n"
+       "__kernel void buildBinaryRadixTreeInternalNodes(__global b3Int64* commonPrefixes, __global int* commonPrefixLengths,\n"
+       "                                                                                               __global int2* out_childNodes,\n"
+       "                                                                                               __global int* out_internalNodeParentNodes, __global int* out_rootNodeIndex,\n"
+       "                                                                                               int numInternalNodes)\n"
+       "{\n"
+       "       int internalNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);\n"
+       "       if(internalNodeIndex >= numInternalNodes) return;\n"
+       "       \n"
+       "       b3Int64 nodePrefix = commonPrefixes[internalNodeIndex];\n"
+       "       int nodePrefixLength = commonPrefixLengths[internalNodeIndex];\n"
+       "       \n"
+       "//#define USE_LINEAR_SEARCH\n"
+       "#ifdef USE_LINEAR_SEARCH\n"
+       "       int leftIndex = -1;\n"
+       "       int rightIndex = -1;\n"
+       "       \n"
+       "       //Find nearest element to left with a lower common prefix\n"
+       "       for(int i = internalNodeIndex - 1; i >= 0; --i)\n"
+       "       {\n"
+       "               int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);\n"
+       "               if(nodeLeftSharedPrefixLength < nodePrefixLength)\n"
+       "               {\n"
+       "                       leftIndex = i;\n"
+       "                       break;\n"
+       "               }\n"
+       "       }\n"
+       "       \n"
+       "       //Find nearest element to right with a lower common prefix\n"
+       "       for(int i = internalNodeIndex + 1; i < numInternalNodes; ++i)\n"
+       "       {\n"
+       "               int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);\n"
+       "               if(nodeRightSharedPrefixLength < nodePrefixLength)\n"
+       "               {\n"
+       "                       rightIndex = i;\n"
+       "                       break;\n"
+       "               }\n"
+       "       }\n"
+       "       \n"
+       "#else //Use binary search\n"
+       "       //Find nearest element to left with a lower common prefix\n"
+       "       int leftIndex = -1;\n"
+       "       {\n"
+       "               int lower = 0;\n"
+       "               int upper = internalNodeIndex - 1;\n"
+       "               \n"
+       "               while(lower <= upper)\n"
+       "               {\n"
+       "                       int mid = (lower + upper) / 2;\n"
+       "                       b3Int64 midPrefix = commonPrefixes[mid];\n"
+       "                       int midPrefixLength = commonPrefixLengths[mid];\n"
+       "                       \n"
+       "                       int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);\n"
+       "                       if(nodeMidSharedPrefixLength < nodePrefixLength) \n"
+       "                       {\n"
+       "                               int right = mid + 1;\n"
+       "                               if(right < internalNodeIndex)\n"
+       "                               {\n"
+       "                                       b3Int64 rightPrefix = commonPrefixes[right];\n"
+       "                                       int rightPrefixLength = commonPrefixLengths[right];\n"
+       "                                       \n"
+       "                                       int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, rightPrefix, rightPrefixLength);\n"
+       "                                       if(nodeRightSharedPrefixLength < nodePrefixLength) \n"
+       "                                       {\n"
+       "                                               lower = right;\n"
+       "                                               leftIndex = right;\n"
+       "                                       }\n"
+       "                                       else \n"
+       "                                       {\n"
+       "                                               leftIndex = mid;\n"
+       "                                               break;\n"
+       "                                       }\n"
+       "                               }\n"
+       "                               else \n"
+       "                               {\n"
+       "                                       leftIndex = mid;\n"
+       "                                       break;\n"
+       "                               }\n"
+       "                       }\n"
+       "                       else upper = mid - 1;\n"
+       "               }\n"
+       "       }\n"
+       "       \n"
+       "       //Find nearest element to right with a lower common prefix\n"
+       "       int rightIndex = -1;\n"
+       "       {\n"
+       "               int lower = internalNodeIndex + 1;\n"
+       "               int upper = numInternalNodes - 1;\n"
+       "               \n"
+       "               while(lower <= upper)\n"
+       "               {\n"
+       "                       int mid = (lower + upper) / 2;\n"
+       "                       b3Int64 midPrefix = commonPrefixes[mid];\n"
+       "                       int midPrefixLength = commonPrefixLengths[mid];\n"
+       "                       \n"
+       "                       int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);\n"
+       "                       if(nodeMidSharedPrefixLength < nodePrefixLength) \n"
+       "                       {\n"
+       "                               int left = mid - 1;\n"
+       "                               if(left > internalNodeIndex)\n"
+       "                               {\n"
+       "                                       b3Int64 leftPrefix = commonPrefixes[left];\n"
+       "                                       int leftPrefixLength = commonPrefixLengths[left];\n"
+       "                               \n"
+       "                                       int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, leftPrefix, leftPrefixLength);\n"
+       "                                       if(nodeLeftSharedPrefixLength < nodePrefixLength) \n"
+       "                                       {\n"
+       "                                               upper = left;\n"
+       "                                               rightIndex = left;\n"
+       "                                       }\n"
+       "                                       else \n"
+       "                                       {\n"
+       "                                               rightIndex = mid;\n"
+       "                                               break;\n"
+       "                                       }\n"
+       "                               }\n"
+       "                               else \n"
+       "                               {\n"
+       "                                       rightIndex = mid;\n"
+       "                                       break;\n"
+       "                               }\n"
+       "                       }\n"
+       "                       else lower = mid + 1;\n"
+       "               }\n"
+       "       }\n"
+       "#endif\n"
+       "       \n"
+       "       //Select parent\n"
+       "       {\n"
+       "               int leftPrefixLength = (leftIndex != -1) ? commonPrefixLengths[leftIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+       "               int rightPrefixLength =  (rightIndex != -1) ? commonPrefixLengths[rightIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
+       "               \n"
+       "               int isLeftHigherPrefixLength = (leftPrefixLength > rightPrefixLength);\n"
+       "               \n"
+       "               if(leftPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = false;\n"
+       "               else if(rightPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = true;\n"
+       "               \n"
+       "               int parentNodeIndex = (isLeftHigherPrefixLength) ? leftIndex : rightIndex;\n"
+       "               \n"
+       "               int isRootNode = (leftIndex == -1 && rightIndex == -1);\n"
+       "               out_internalNodeParentNodes[internalNodeIndex] = (!isRootNode) ? parentNodeIndex : B3_PLBVH_ROOT_NODE_MARKER;\n"
+       "               \n"
+       "               int isLeaf = 0;\n"
+       "               if(!isRootNode)\n"
+       "               {\n"
+       "                       int isRightChild = (isLeftHigherPrefixLength);  //If the left node is the parent, then this node is its right child and vice versa\n"
+       "                       \n"
+       "                       //out_childNodesAsInt[0] == int2.x == left child\n"
+       "                       //out_childNodesAsInt[1] == int2.y == right child\n"
+       "                       __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);\n"
+       "                       out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);\n"
+       "               }\n"
+       "               else *out_rootNodeIndex = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);\n"
+       "       }\n"
+       "}\n"
+       "__kernel void findDistanceFromRoot(__global int* rootNodeIndex, __global int* internalNodeParentNodes,\n"
+       "                                                                       __global int* out_maxDistanceFromRoot, __global int* out_distanceFromRoot, int numInternalNodes)\n"
+       "{\n"
+       "       if( get_global_id(0) == 0 ) atomic_xchg(out_maxDistanceFromRoot, 0);\n"
+       "       int internalNodeIndex = get_global_id(0);\n"
+       "       if(internalNodeIndex >= numInternalNodes) return;\n"
+       "       \n"
+       "       //\n"
+       "       int distanceFromRoot = 0;\n"
+       "       {\n"
+       "               int parentIndex = internalNodeParentNodes[internalNodeIndex];\n"
+       "               while(parentIndex != B3_PLBVH_ROOT_NODE_MARKER)\n"
+       "               {\n"
+       "                       parentIndex = internalNodeParentNodes[parentIndex];\n"
+       "                       ++distanceFromRoot;\n"
+       "               }\n"
+       "       }\n"
+       "       out_distanceFromRoot[internalNodeIndex] = distanceFromRoot;\n"
+       "       \n"
+       "       //\n"
+       "       __local int localMaxDistanceFromRoot;\n"
+       "       if( get_local_id(0) == 0 ) localMaxDistanceFromRoot = 0;\n"
+       "       barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "       \n"
+       "       atomic_max(&localMaxDistanceFromRoot, distanceFromRoot);\n"
+       "       barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "       \n"
+       "       if( get_local_id(0) == 0 ) atomic_max(out_maxDistanceFromRoot, localMaxDistanceFromRoot);\n"
+       "}\n"
+       "__kernel void buildBinaryRadixTreeAabbsRecursive(__global int* distanceFromRoot, __global SortDataCL* mortonCodesAndAabbIndices,\n"
+       "                                                                                               __global int2* childNodes,\n"
+       "                                                                                               __global b3AabbCL* leafNodeAabbs, __global b3AabbCL* internalNodeAabbs,\n"
+       "                                                                                               int maxDistanceFromRoot, int processedDistance, int numInternalNodes)\n"
+       "{\n"
+       "       int internalNodeIndex = get_global_id(0);\n"
+       "       if(internalNodeIndex >= numInternalNodes) return;\n"
+       "       \n"
+       "       int distance = distanceFromRoot[internalNodeIndex];\n"
+       "       \n"
+       "       if(distance == processedDistance)\n"
+       "       {\n"
+       "               int leftChildIndex = childNodes[internalNodeIndex].x;\n"
+       "               int rightChildIndex = childNodes[internalNodeIndex].y;\n"
+       "               \n"
+       "               int isLeftChildLeaf = isLeafNode(leftChildIndex);\n"
+       "               int isRightChildLeaf = isLeafNode(rightChildIndex);\n"
+       "               \n"
+       "               leftChildIndex = getIndexWithInternalNodeMarkerRemoved(leftChildIndex);\n"
+       "               rightChildIndex = getIndexWithInternalNodeMarkerRemoved(rightChildIndex);\n"
+       "               \n"
+       "               //leftRigidIndex/rightRigidIndex is not used if internal node\n"
+       "               int leftRigidIndex = (isLeftChildLeaf) ? mortonCodesAndAabbIndices[leftChildIndex].m_value : -1;\n"
+       "               int rightRigidIndex = (isRightChildLeaf) ? mortonCodesAndAabbIndices[rightChildIndex].m_value : -1;\n"
+       "               \n"
+       "               b3AabbCL leftChildAabb = (isLeftChildLeaf) ? leafNodeAabbs[leftRigidIndex] : internalNodeAabbs[leftChildIndex];\n"
+       "               b3AabbCL rightChildAabb = (isRightChildLeaf) ? leafNodeAabbs[rightRigidIndex] : internalNodeAabbs[rightChildIndex];\n"
+       "               \n"
+       "               b3AabbCL mergedAabb;\n"
+       "               mergedAabb.m_min = b3Min(leftChildAabb.m_min, rightChildAabb.m_min);\n"
+       "               mergedAabb.m_max = b3Max(leftChildAabb.m_max, rightChildAabb.m_max);\n"
+       "               internalNodeAabbs[internalNodeIndex] = mergedAabb;\n"
+       "       }\n"
+       "}\n"
+       "__kernel void findLeafIndexRanges(__global int2* internalNodeChildNodes, __global int2* out_leafIndexRanges, int numInternalNodes)\n"
+       "{\n"
+       "       int internalNodeIndex = get_global_id(0);\n"
+       "       if(internalNodeIndex >= numInternalNodes) return;\n"
+       "       \n"
+       "       int numLeafNodes = numInternalNodes + 1;\n"
+       "       \n"
+       "       int2 childNodes = internalNodeChildNodes[internalNodeIndex];\n"
+       "       \n"
+       "       int2 leafIndexRange;    //x == min leaf index, y == max leaf index\n"
+       "       \n"
+       "       //Find lowest leaf index covered by this internal node\n"
+       "       {\n"
+       "               int lowestIndex = childNodes.x;         //childNodes.x == Left child\n"
+       "               while( !isLeafNode(lowestIndex) ) lowestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(lowestIndex) ].x;\n"
+       "               leafIndexRange.x = lowestIndex;\n"
+       "       }\n"
+       "       \n"
+       "       //Find highest leaf index covered by this internal node\n"
+       "       {\n"
+       "               int highestIndex = childNodes.y;        //childNodes.y == Right child\n"
+       "               while( !isLeafNode(highestIndex) ) highestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(highestIndex) ].y;\n"
+       "               leafIndexRange.y = highestIndex;\n"
+       "       }\n"
+       "       \n"
+       "       //\n"
+       "       out_leafIndexRanges[internalNodeIndex] = leafIndexRange;\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl
new file mode 100644 (file)
index 0000000..93f77a6
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#define NEW_PAIR_MARKER -1
+
+typedef struct 
+{
+       union
+       {
+               float4  m_min;
+               float   m_minElems[4];
+               int                     m_minIndices[4];
+       };
+       union
+       {
+               float4  m_max;
+               float   m_maxElems[4];
+               int                     m_maxIndices[4];
+       };
+} btAabbCL;
+
+
+/// conservative test for overlap between two aabbs
+bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2);
+bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2)
+{
+       bool overlap = true;
+       overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
+       overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
+       overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
+       return overlap;
+}
+bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2);
+bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2)
+{
+       bool overlap = true;
+       overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
+       overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
+       overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
+       return overlap;
+}
+
+bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2);
+bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2)
+{
+       bool overlap = true;
+       overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
+       overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
+       overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
+       return overlap;
+}
+
+
+__kernel void   computePairsKernelTwoArrays( __global const btAabbCL* unsortedAabbs, __global const int* unsortedAabbMapping,  __global const int* unsortedAabbMapping2, volatile __global int4* pairsOut,volatile  __global int* pairCount, int numUnsortedAabbs, int numUnSortedAabbs2, int axis, int maxPairs)
+{
+       int i = get_global_id(0);
+       if (i>=numUnsortedAabbs)
+               return;
+
+       int j = get_global_id(1);
+       if (j>=numUnSortedAabbs2)
+               return;
+
+
+       __global const btAabbCL* unsortedAabbPtr = &unsortedAabbs[unsortedAabbMapping[i]];
+       __global const btAabbCL* unsortedAabbPtr2 = &unsortedAabbs[unsortedAabbMapping2[j]];
+
+       if (TestAabbAgainstAabb2GlobalGlobal(unsortedAabbPtr,unsortedAabbPtr2))
+       {
+               int4 myPair;
+               
+               int xIndex = unsortedAabbPtr[0].m_minIndices[3];
+               int yIndex = unsortedAabbPtr2[0].m_minIndices[3];
+               if (xIndex>yIndex)
+               {
+                       int tmp = xIndex;
+                       xIndex=yIndex;
+                       yIndex=tmp;
+               }
+               
+               myPair.x = xIndex;
+               myPair.y = yIndex;
+               myPair.z = NEW_PAIR_MARKER;
+               myPair.w = NEW_PAIR_MARKER;
+
+
+               int curPair = atomic_inc (pairCount);
+               if (curPair<maxPairs)
+               {
+                               pairsOut[curPair] = myPair; //flush to main memory
+               }
+       }
+}
+
+
+
+__kernel void   computePairsKernelBruteForce( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile  __global int* pairCount, int numObjects, int axis, int maxPairs)
+{
+       int i = get_global_id(0);
+       if (i>=numObjects)
+               return;
+       for (int j=i+1;j<numObjects;j++)
+       {
+               if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))
+               {
+                       int4 myPair;
+                       myPair.x = aabbs[i].m_minIndices[3];
+                       myPair.y = aabbs[j].m_minIndices[3];
+                       myPair.z = NEW_PAIR_MARKER;
+                       myPair.w = NEW_PAIR_MARKER;
+
+                       int curPair = atomic_inc (pairCount);
+                       if (curPair<maxPairs)
+                       {
+                                       pairsOut[curPair] = myPair; //flush to main memory
+                       }
+               }
+       }
+}
+
+__kernel void   computePairsKernelOriginal( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile  __global int* pairCount, int numObjects, int axis, int maxPairs)
+{
+       int i = get_global_id(0);
+       if (i>=numObjects)
+               return;
+       for (int j=i+1;j<numObjects;j++)
+       {
+       if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) 
+               {
+                       break;
+               }
+               if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))
+               {
+                       int4 myPair;
+                       myPair.x = aabbs[i].m_minIndices[3];
+                       myPair.y = aabbs[j].m_minIndices[3];
+                       myPair.z = NEW_PAIR_MARKER;
+                       myPair.w = NEW_PAIR_MARKER;
+
+                       int curPair = atomic_inc (pairCount);
+                       if (curPair<maxPairs)
+                       {
+                                       pairsOut[curPair] = myPair; //flush to main memory
+                       }
+               }
+       }
+}
+
+
+
+
+__kernel void   computePairsKernelBarrier( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile  __global int* pairCount, int numObjects, int axis, int maxPairs)
+{
+       int i = get_global_id(0);
+       int localId = get_local_id(0);
+
+       __local int numActiveWgItems[1];
+       __local int breakRequest[1];
+
+       if (localId==0)
+       {
+               numActiveWgItems[0] = 0;
+               breakRequest[0] = 0;
+       }
+       barrier(CLK_LOCAL_MEM_FENCE);
+       atomic_inc(numActiveWgItems);
+       barrier(CLK_LOCAL_MEM_FENCE);
+       int localBreak = 0;
+
+       int j=i+1;
+       do
+       {
+               barrier(CLK_LOCAL_MEM_FENCE);
+       
+               if (j<numObjects)
+               {
+               if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) 
+                       {
+                               if (!localBreak)
+                               {
+                                       atomic_inc(breakRequest);
+                                       localBreak = 1;
+                               }
+                       }
+               }
+               
+               barrier(CLK_LOCAL_MEM_FENCE);
+               
+               if (j>=numObjects && !localBreak)
+               {
+                       atomic_inc(breakRequest);
+                       localBreak = 1;
+               }
+               barrier(CLK_LOCAL_MEM_FENCE);
+               
+               if (!localBreak)
+               {
+                       if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))
+                       {
+                               int4 myPair;
+                               myPair.x = aabbs[i].m_minIndices[3];
+                               myPair.y = aabbs[j].m_minIndices[3];
+                               myPair.z = NEW_PAIR_MARKER;
+                               myPair.w = NEW_PAIR_MARKER;
+
+                               int curPair = atomic_inc (pairCount);
+                               if (curPair<maxPairs)
+                               {
+                                               pairsOut[curPair] = myPair; //flush to main memory
+                               }
+                       }
+               }
+               j++;
+
+       } while (breakRequest[0]<numActiveWgItems[0]);
+}
+
+
+__kernel void   computePairsKernelLocalSharedMemory( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile  __global int* pairCount, int numObjects, int axis, int maxPairs)
+{
+       int i = get_global_id(0);
+       int localId = get_local_id(0);
+
+       __local int numActiveWgItems[1];
+       __local int breakRequest[1];
+       __local btAabbCL localAabbs[128];// = aabbs[i];
+       
+       btAabbCL myAabb;
+       
+       myAabb = (i<numObjects)? aabbs[i]:aabbs[0];
+       float testValue =       myAabb.m_maxElems[axis];
+       
+       if (localId==0)
+       {
+               numActiveWgItems[0] = 0;
+               breakRequest[0] = 0;
+       }
+       int localCount=0;
+       int block=0;
+       localAabbs[localId] = (i+block)<numObjects? aabbs[i+block] : aabbs[0];
+       localAabbs[localId+64] = (i+block+64)<numObjects? aabbs[i+block+64]: aabbs[0];
+       
+       barrier(CLK_LOCAL_MEM_FENCE);
+       atomic_inc(numActiveWgItems);
+       barrier(CLK_LOCAL_MEM_FENCE);
+       int localBreak = 0;
+       
+       int j=i+1;
+       do
+       {
+               barrier(CLK_LOCAL_MEM_FENCE);
+       
+               if (j<numObjects)
+               {
+               if(testValue < (localAabbs[localCount+localId+1].m_minElems[axis])) 
+                       {
+                               if (!localBreak)
+                               {
+                                       atomic_inc(breakRequest);
+                                       localBreak = 1;
+                               }
+                       }
+               }
+               
+               barrier(CLK_LOCAL_MEM_FENCE);
+               
+               if (j>=numObjects && !localBreak)
+               {
+                       atomic_inc(breakRequest);
+                       localBreak = 1;
+               }
+               barrier(CLK_LOCAL_MEM_FENCE);
+               
+               if (!localBreak)
+               {
+                       if (TestAabbAgainstAabb2(&myAabb,&localAabbs[localCount+localId+1]))
+                       {
+                               int4 myPair;
+                               myPair.x = myAabb.m_minIndices[3];
+                               myPair.y = localAabbs[localCount+localId+1].m_minIndices[3];
+                               myPair.z = NEW_PAIR_MARKER;
+                               myPair.w = NEW_PAIR_MARKER;
+
+                               int curPair = atomic_inc (pairCount);
+                               if (curPair<maxPairs)
+                               {
+                                               pairsOut[curPair] = myPair; //flush to main memory
+                               }
+                       }
+               }
+               
+               barrier(CLK_LOCAL_MEM_FENCE);
+
+               localCount++;
+               if (localCount==64)
+               {
+                       localCount = 0;
+                       block+=64;                      
+                       localAabbs[localId] = ((i+block)<numObjects) ? aabbs[i+block] : aabbs[0];
+                       localAabbs[localId+64] = ((i+64+block)<numObjects) ? aabbs[i+block+64] : aabbs[0];
+               }
+               j++;
+               
+       } while (breakRequest[0]<numActiveWgItems[0]);
+       
+}
+
+
+
+
+//http://stereopsis.com/radix.html
+unsigned int FloatFlip(float fl);
+unsigned int FloatFlip(float fl)
+{
+       unsigned int f = *(unsigned int*)&fl;
+       unsigned int mask = -(int)(f >> 31) | 0x80000000;
+       return f ^ mask;
+}
+float IFloatFlip(unsigned int f);
+float IFloatFlip(unsigned int f)
+{
+       unsigned int mask = ((f >> 31) - 1) | 0x80000000;
+       unsigned int fl = f ^ mask;
+       return *(float*)&fl;
+}
+
+
+
+
+__kernel void   copyAabbsKernel( __global const btAabbCL* allAabbs, __global btAabbCL* destAabbs, int numObjects)
+{
+       int i = get_global_id(0);
+       if (i>=numObjects)
+               return;
+       int src = destAabbs[i].m_maxIndices[3];
+       destAabbs[i] = allAabbs[src];
+       destAabbs[i].m_maxIndices[3] = src;
+}
+
+
+__kernel void   flipFloatKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global int2* sortData, int numObjects, int axis)
+{
+       int i = get_global_id(0);
+       if (i>=numObjects)
+               return;
+       
+       
+       sortData[i].x = FloatFlip(allAabbs[smallAabbMapping[i]].m_minElems[axis]);
+       sortData[i].y = i;
+               
+}
+
+
+__kernel void   scatterKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, volatile __global const int2* sortData, __global btAabbCL* sortedAabbs, int numObjects)
+{
+       int i = get_global_id(0);
+       if (i>=numObjects)
+               return;
+       
+       sortedAabbs[i] = allAabbs[smallAabbMapping[sortData[i].y]];
+}
+
+
+
+__kernel void   prepareSumVarianceKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global float4* sum, __global float4* sum2,int numAabbs)
+{
+       int i = get_global_id(0);
+       if (i>=numAabbs)
+               return;
+       
+       btAabbCL smallAabb = allAabbs[smallAabbMapping[i]];
+       
+       float4 s;
+       s = (smallAabb.m_max+smallAabb.m_min)*0.5f;
+       sum[i]=s;
+       sum2[i]=s*s;    
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h
new file mode 100644 (file)
index 0000000..d6999b9
--- /dev/null
@@ -0,0 +1,341 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* sapCL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Erwin Coumans\n"
+       "#define NEW_PAIR_MARKER -1\n"
+       "typedef struct \n"
+       "{\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_min;\n"
+       "               float   m_minElems[4];\n"
+       "               int                     m_minIndices[4];\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_max;\n"
+       "               float   m_maxElems[4];\n"
+       "               int                     m_maxIndices[4];\n"
+       "       };\n"
+       "} btAabbCL;\n"
+       "/// conservative test for overlap between two aabbs\n"
+       "bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2);\n"
+       "bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2)\n"
+       "{\n"
+       "       bool overlap = true;\n"
+       "       overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+       "       overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+       "       overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+       "       return overlap;\n"
+       "}\n"
+       "bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2);\n"
+       "bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2)\n"
+       "{\n"
+       "       bool overlap = true;\n"
+       "       overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+       "       overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+       "       overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+       "       return overlap;\n"
+       "}\n"
+       "bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2);\n"
+       "bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2)\n"
+       "{\n"
+       "       bool overlap = true;\n"
+       "       overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
+       "       overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
+       "       overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
+       "       return overlap;\n"
+       "}\n"
+       "__kernel void   computePairsKernelTwoArrays( __global const btAabbCL* unsortedAabbs, __global const int* unsortedAabbMapping,  __global const int* unsortedAabbMapping2, volatile __global int4* pairsOut,volatile  __global int* pairCount, int numUnsortedAabbs, int numUnSortedAabbs2, int axis, int maxPairs)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numUnsortedAabbs)\n"
+       "               return;\n"
+       "       int j = get_global_id(1);\n"
+       "       if (j>=numUnSortedAabbs2)\n"
+       "               return;\n"
+       "       __global const btAabbCL* unsortedAabbPtr = &unsortedAabbs[unsortedAabbMapping[i]];\n"
+       "       __global const btAabbCL* unsortedAabbPtr2 = &unsortedAabbs[unsortedAabbMapping2[j]];\n"
+       "       if (TestAabbAgainstAabb2GlobalGlobal(unsortedAabbPtr,unsortedAabbPtr2))\n"
+       "       {\n"
+       "               int4 myPair;\n"
+       "               \n"
+       "               int xIndex = unsortedAabbPtr[0].m_minIndices[3];\n"
+       "               int yIndex = unsortedAabbPtr2[0].m_minIndices[3];\n"
+       "               if (xIndex>yIndex)\n"
+       "               {\n"
+       "                       int tmp = xIndex;\n"
+       "                       xIndex=yIndex;\n"
+       "                       yIndex=tmp;\n"
+       "               }\n"
+       "               \n"
+       "               myPair.x = xIndex;\n"
+       "               myPair.y = yIndex;\n"
+       "               myPair.z = NEW_PAIR_MARKER;\n"
+       "               myPair.w = NEW_PAIR_MARKER;\n"
+       "               int curPair = atomic_inc (pairCount);\n"
+       "               if (curPair<maxPairs)\n"
+       "               {\n"
+       "                               pairsOut[curPair] = myPair; //flush to main memory\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__kernel void   computePairsKernelBruteForce( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile  __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numObjects)\n"
+       "               return;\n"
+       "       for (int j=i+1;j<numObjects;j++)\n"
+       "       {\n"
+       "               if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
+       "               {\n"
+       "                       int4 myPair;\n"
+       "                       myPair.x = aabbs[i].m_minIndices[3];\n"
+       "                       myPair.y = aabbs[j].m_minIndices[3];\n"
+       "                       myPair.z = NEW_PAIR_MARKER;\n"
+       "                       myPair.w = NEW_PAIR_MARKER;\n"
+       "                       int curPair = atomic_inc (pairCount);\n"
+       "                       if (curPair<maxPairs)\n"
+       "                       {\n"
+       "                                       pairsOut[curPair] = myPair; //flush to main memory\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__kernel void   computePairsKernelOriginal( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile  __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numObjects)\n"
+       "               return;\n"
+       "       for (int j=i+1;j<numObjects;j++)\n"
+       "       {\n"
+       "       if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) \n"
+       "               {\n"
+       "                       break;\n"
+       "               }\n"
+       "               if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
+       "               {\n"
+       "                       int4 myPair;\n"
+       "                       myPair.x = aabbs[i].m_minIndices[3];\n"
+       "                       myPair.y = aabbs[j].m_minIndices[3];\n"
+       "                       myPair.z = NEW_PAIR_MARKER;\n"
+       "                       myPair.w = NEW_PAIR_MARKER;\n"
+       "                       int curPair = atomic_inc (pairCount);\n"
+       "                       if (curPair<maxPairs)\n"
+       "                       {\n"
+       "                                       pairsOut[curPair] = myPair; //flush to main memory\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__kernel void   computePairsKernelBarrier( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile  __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       int localId = get_local_id(0);\n"
+       "       __local int numActiveWgItems[1];\n"
+       "       __local int breakRequest[1];\n"
+       "       if (localId==0)\n"
+       "       {\n"
+       "               numActiveWgItems[0] = 0;\n"
+       "               breakRequest[0] = 0;\n"
+       "       }\n"
+       "       barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "       atomic_inc(numActiveWgItems);\n"
+       "       barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "       int localBreak = 0;\n"
+       "       int j=i+1;\n"
+       "       do\n"
+       "       {\n"
+       "               barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "       \n"
+       "               if (j<numObjects)\n"
+       "               {\n"
+       "               if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) \n"
+       "                       {\n"
+       "                               if (!localBreak)\n"
+       "                               {\n"
+       "                                       atomic_inc(breakRequest);\n"
+       "                                       localBreak = 1;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "               barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "               \n"
+       "               if (j>=numObjects && !localBreak)\n"
+       "               {\n"
+       "                       atomic_inc(breakRequest);\n"
+       "                       localBreak = 1;\n"
+       "               }\n"
+       "               barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "               \n"
+       "               if (!localBreak)\n"
+       "               {\n"
+       "                       if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
+       "                       {\n"
+       "                               int4 myPair;\n"
+       "                               myPair.x = aabbs[i].m_minIndices[3];\n"
+       "                               myPair.y = aabbs[j].m_minIndices[3];\n"
+       "                               myPair.z = NEW_PAIR_MARKER;\n"
+       "                               myPair.w = NEW_PAIR_MARKER;\n"
+       "                               int curPair = atomic_inc (pairCount);\n"
+       "                               if (curPair<maxPairs)\n"
+       "                               {\n"
+       "                                               pairsOut[curPair] = myPair; //flush to main memory\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               j++;\n"
+       "       } while (breakRequest[0]<numActiveWgItems[0]);\n"
+       "}\n"
+       "__kernel void   computePairsKernelLocalSharedMemory( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile  __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       int localId = get_local_id(0);\n"
+       "       __local int numActiveWgItems[1];\n"
+       "       __local int breakRequest[1];\n"
+       "       __local btAabbCL localAabbs[128];// = aabbs[i];\n"
+       "       \n"
+       "       btAabbCL myAabb;\n"
+       "       \n"
+       "       myAabb = (i<numObjects)? aabbs[i]:aabbs[0];\n"
+       "       float testValue =       myAabb.m_maxElems[axis];\n"
+       "       \n"
+       "       if (localId==0)\n"
+       "       {\n"
+       "               numActiveWgItems[0] = 0;\n"
+       "               breakRequest[0] = 0;\n"
+       "       }\n"
+       "       int localCount=0;\n"
+       "       int block=0;\n"
+       "       localAabbs[localId] = (i+block)<numObjects? aabbs[i+block] : aabbs[0];\n"
+       "       localAabbs[localId+64] = (i+block+64)<numObjects? aabbs[i+block+64]: aabbs[0];\n"
+       "       \n"
+       "       barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "       atomic_inc(numActiveWgItems);\n"
+       "       barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "       int localBreak = 0;\n"
+       "       \n"
+       "       int j=i+1;\n"
+       "       do\n"
+       "       {\n"
+       "               barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "       \n"
+       "               if (j<numObjects)\n"
+       "               {\n"
+       "               if(testValue < (localAabbs[localCount+localId+1].m_minElems[axis])) \n"
+       "                       {\n"
+       "                               if (!localBreak)\n"
+       "                               {\n"
+       "                                       atomic_inc(breakRequest);\n"
+       "                                       localBreak = 1;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "               barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "               \n"
+       "               if (j>=numObjects && !localBreak)\n"
+       "               {\n"
+       "                       atomic_inc(breakRequest);\n"
+       "                       localBreak = 1;\n"
+       "               }\n"
+       "               barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "               \n"
+       "               if (!localBreak)\n"
+       "               {\n"
+       "                       if (TestAabbAgainstAabb2(&myAabb,&localAabbs[localCount+localId+1]))\n"
+       "                       {\n"
+       "                               int4 myPair;\n"
+       "                               myPair.x = myAabb.m_minIndices[3];\n"
+       "                               myPair.y = localAabbs[localCount+localId+1].m_minIndices[3];\n"
+       "                               myPair.z = NEW_PAIR_MARKER;\n"
+       "                               myPair.w = NEW_PAIR_MARKER;\n"
+       "                               int curPair = atomic_inc (pairCount);\n"
+       "                               if (curPair<maxPairs)\n"
+       "                               {\n"
+       "                                               pairsOut[curPair] = myPair; //flush to main memory\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "               barrier(CLK_LOCAL_MEM_FENCE);\n"
+       "               localCount++;\n"
+       "               if (localCount==64)\n"
+       "               {\n"
+       "                       localCount = 0;\n"
+       "                       block+=64;                      \n"
+       "                       localAabbs[localId] = ((i+block)<numObjects) ? aabbs[i+block] : aabbs[0];\n"
+       "                       localAabbs[localId+64] = ((i+64+block)<numObjects) ? aabbs[i+block+64] : aabbs[0];\n"
+       "               }\n"
+       "               j++;\n"
+       "               \n"
+       "       } while (breakRequest[0]<numActiveWgItems[0]);\n"
+       "       \n"
+       "}\n"
+       "//http://stereopsis.com/radix.html\n"
+       "unsigned int FloatFlip(float fl);\n"
+       "unsigned int FloatFlip(float fl)\n"
+       "{\n"
+       "       unsigned int f = *(unsigned int*)&fl;\n"
+       "       unsigned int mask = -(int)(f >> 31) | 0x80000000;\n"
+       "       return f ^ mask;\n"
+       "}\n"
+       "float IFloatFlip(unsigned int f);\n"
+       "float IFloatFlip(unsigned int f)\n"
+       "{\n"
+       "       unsigned int mask = ((f >> 31) - 1) | 0x80000000;\n"
+       "       unsigned int fl = f ^ mask;\n"
+       "       return *(float*)&fl;\n"
+       "}\n"
+       "__kernel void   copyAabbsKernel( __global const btAabbCL* allAabbs, __global btAabbCL* destAabbs, int numObjects)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numObjects)\n"
+       "               return;\n"
+       "       int src = destAabbs[i].m_maxIndices[3];\n"
+       "       destAabbs[i] = allAabbs[src];\n"
+       "       destAabbs[i].m_maxIndices[3] = src;\n"
+       "}\n"
+       "__kernel void   flipFloatKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global int2* sortData, int numObjects, int axis)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numObjects)\n"
+       "               return;\n"
+       "       \n"
+       "       \n"
+       "       sortData[i].x = FloatFlip(allAabbs[smallAabbMapping[i]].m_minElems[axis]);\n"
+       "       sortData[i].y = i;\n"
+       "               \n"
+       "}\n"
+       "__kernel void   scatterKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, volatile __global const int2* sortData, __global btAabbCL* sortedAabbs, int numObjects)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numObjects)\n"
+       "               return;\n"
+       "       \n"
+       "       sortedAabbs[i] = allAabbs[smallAabbMapping[sortData[i].y]];\n"
+       "}\n"
+       "__kernel void   prepareSumVarianceKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global float4* sum, __global float4* sum2,int numAabbs)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numAabbs)\n"
+       "               return;\n"
+       "       \n"
+       "       btAabbCL smallAabb = allAabbs[smallAabbMapping[i]];\n"
+       "       \n"
+       "       float4 s;\n"
+       "       s = (smallAabb.m_max+smallAabb.m_min)*0.5f;\n"
+       "       sum[i]=s;\n"
+       "       sum2[i]=s*s;    \n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/CMakeLists.txt b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1da58d4
--- /dev/null
@@ -0,0 +1,77 @@
+INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src  )
+
+ADD_DEFINITIONS(-DB3_USE_CLEW)
+
+SET(Bullet3OpenCL_clew_SRCS
+       ../clew/clew.c
+       BroadphaseCollision/b3GpuGridBroadphase.cpp
+       BroadphaseCollision/b3GpuSapBroadphase.cpp
+       BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp
+       BroadphaseCollision/b3GpuParallelLinearBvh.cpp
+       Initialize/b3OpenCLUtils.cpp
+       NarrowphaseCollision/b3ContactCache.cpp
+       NarrowphaseCollision/b3ConvexHullContact.cpp
+       NarrowphaseCollision/b3GjkEpa.cpp
+       NarrowphaseCollision/b3OptimizedBvh.cpp
+       NarrowphaseCollision/b3QuantizedBvh.cpp
+       NarrowphaseCollision/b3StridingMeshInterface.cpp
+       NarrowphaseCollision/b3TriangleCallback.cpp
+       NarrowphaseCollision/b3TriangleIndexVertexArray.cpp
+       NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
+       ParallelPrimitives/b3BoundSearchCL.cpp
+       ParallelPrimitives/b3FillCL.cpp
+       ParallelPrimitives/b3LauncherCL.cpp
+       ParallelPrimitives/b3PrefixScanCL.cpp
+       ParallelPrimitives/b3PrefixScanFloat4CL.cpp
+       ParallelPrimitives/b3RadixSort32CL.cpp
+       Raycast/b3GpuRaycast.cpp
+       RigidBody/b3GpuGenericConstraint.cpp
+       RigidBody/b3GpuJacobiContactSolver.cpp
+       RigidBody/b3GpuNarrowPhase.cpp
+       RigidBody/b3GpuPgsConstraintSolver.cpp
+       RigidBody/b3GpuPgsContactSolver.cpp
+       RigidBody/b3GpuRigidBodyPipeline.cpp
+       RigidBody/b3Solver.cpp
+)
+
+
+SET(Bullet3OpenCL_clew_HDRS
+#      ${Root_HDRS}
+)
+
+
+ADD_LIBRARY(Bullet3OpenCL_clew ${Bullet3OpenCL_clew_SRCS} ${Bullet3OpenCL_clew_HDRS})
+SET_TARGET_PROPERTIES(Bullet3OpenCL_clew PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet3OpenCL_clew PROPERTIES SOVERSION ${BULLET_VERSION})
+IF (BUILD_SHARED_LIBS)
+  TARGET_LINK_LIBRARIES(Bullet3OpenCL_clew LinearMath Bullet3Dynamics ${CMAKE_DL_LIBS})
+ENDIF (BUILD_SHARED_LIBS)
+
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               #INSTALL of other files requires CMake 2.6
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet3OpenCL_clew DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet3OpenCL_clew RUNTIME DESTINATION bin
+                                                               LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                                               ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+#                              INSTALL(FILES ../btBullet3OpenCL_clewCommon.h
+#DESTINATION ${INCLUDE_INSTALL_DIR}/Bullet3OpenCL_clew)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(Bullet3OpenCL_clew PROPERTIES FRAMEWORK true)
+
+                       SET_TARGET_PROPERTIES(Bullet3OpenCL_clew PROPERTIES PUBLIC_HEADER "${Root_HDRS}")
+                       # Have to list out sub-directories manually:
+                       SET_PROPERTY(SOURCE ${BroadphaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/BroadphaseCollision)
+
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Initialize/b3OpenCLInclude.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Initialize/b3OpenCLInclude.h
new file mode 100644 (file)
index 0000000..6146538
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_OPENCL_INCLUDE_H
+#define B3_OPENCL_INCLUDE_H
+
+#ifdef B3_USE_CLEW
+#include "clew/clew.h"
+#else
+
+#ifdef __APPLE__
+#ifdef USE_MINICL
+#include <MiniCL/cl.h>
+#else
+#include <OpenCL/cl.h>
+#include <OpenCL/cl_ext.h>  //clLogMessagesToStderrAPPLE
+#endif
+#else
+#ifdef USE_MINICL
+#include <MiniCL/cl.h>
+#else
+#include <CL/cl.h>
+#ifdef _WIN32
+#include "CL/cl_gl.h"
+#endif  //_WIN32
+#endif
+#endif  //__APPLE__
+#endif  //B3_USE_CLEW
+
+#include <assert.h>
+#include <stdio.h>
+#define oclCHECKERROR(a, b)              \
+       if ((a) != (b))                      \
+       {                                    \
+               printf("OCL Error : %d\n", (a)); \
+               assert((a) == (b));              \
+       }
+
+#endif  //B3_OPENCL_INCLUDE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp
new file mode 100644 (file)
index 0000000..fe54ea5
--- /dev/null
@@ -0,0 +1,963 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc.
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//Original author: Roman Ponomarev
+//Mostly Reimplemented by Erwin Coumans
+
+bool gDebugForceLoadingFromSource = false;
+bool gDebugSkipLoadingBinary = false;
+
+#include "Bullet3Common/b3Logging.h"
+
+#include <string.h>
+
+#ifdef _WIN32
+#pragma warning(disable : 4996)
+#endif
+#include "b3OpenCLUtils.h"
+//#include "b3OpenCLInclude.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define B3_MAX_CL_DEVICES 16  //who needs 16 devices?
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <assert.h>
+#define b3Assert assert
+#ifndef _WIN32
+#include <sys/stat.h>
+
+#endif
+
+static const char* sCachedBinaryPath = "cache";
+
+//Set the preferred platform vendor using the OpenCL SDK
+static const char* spPlatformVendor =
+#if defined(CL_PLATFORM_MINI_CL)
+       "MiniCL, SCEA";
+#elif defined(CL_PLATFORM_AMD)
+       "Advanced Micro Devices, Inc.";
+#elif defined(CL_PLATFORM_NVIDIA)
+       "NVIDIA Corporation";
+#elif defined(CL_PLATFORM_INTEL)
+       "Intel(R) Corporation";
+#elif defined(B3_USE_CLEW)
+       "clew (OpenCL Extension Wrangler library)";
+#else
+       "Unknown Vendor";
+#endif
+
+#ifndef CL_PLATFORM_MINI_CL
+#ifdef _WIN32
+#ifndef B3_USE_CLEW
+#include "CL/cl_gl.h"
+#endif  //B3_USE_CLEW
+#endif  //_WIN32
+#endif
+
+void MyFatalBreakAPPLE(const char* errstr,
+                                          const void* private_info,
+                                          size_t cb,
+                                          void* user_data)
+{
+       const char* patloc = strstr(errstr, "Warning");
+       //find out if it is a warning or error, exit if error
+
+       if (patloc)
+       {
+               b3Warning("Warning: %s\n", errstr);
+       }
+       else
+       {
+               b3Error("Error: %s\n", errstr);
+               b3Assert(0);
+       }
+}
+
+#ifdef B3_USE_CLEW
+
+int b3OpenCLUtils_clewInit()
+{
+       int result = -1;
+
+#ifdef _WIN32
+       const char* cl = "OpenCL.dll";
+#elif defined __APPLE__
+       const char* cl = "/System/Library/Frameworks/OpenCL.framework/Versions/Current/OpenCL";
+#else  //presumable Linux? \
+          //linux (tested on Ubuntu 12.10 with Catalyst 13.4 beta drivers, not that there is no symbolic link from libOpenCL.so
+       const char* cl = "libOpenCL.so.1";
+       result = clewInit(cl);
+       if (result != CLEW_SUCCESS)
+       {
+               cl = "libOpenCL.so";
+       }
+       else
+       {
+               clewExit();
+       }
+#endif
+       result = clewInit(cl);
+       if (result != CLEW_SUCCESS)
+       {
+               b3Error("clewInit failed with error code %d\n", result);
+       }
+       else
+       {
+               b3Printf("clewInit succesfull using %s\n", cl);
+       }
+       return result;
+}
+#endif
+
+int b3OpenCLUtils_getNumPlatforms(cl_int* pErrNum)
+{
+#ifdef B3_USE_CLEW
+       b3OpenCLUtils_clewInit();
+#endif
+
+       cl_platform_id pPlatforms[10] = {0};
+
+       cl_uint numPlatforms = 0;
+       cl_int ciErrNum = clGetPlatformIDs(10, pPlatforms, &numPlatforms);
+       //cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
+
+       if (ciErrNum != CL_SUCCESS)
+       {
+               if (pErrNum != NULL)
+                       *pErrNum = ciErrNum;
+       }
+       return numPlatforms;
+}
+
+const char* b3OpenCLUtils_getSdkVendorName()
+{
+       return spPlatformVendor;
+}
+
+void b3OpenCLUtils_setCachePath(const char* path)
+{
+       sCachedBinaryPath = path;
+}
+
+cl_platform_id b3OpenCLUtils_getPlatform(int platformIndex0, cl_int* pErrNum)
+{
+#ifdef B3_USE_CLEW
+       b3OpenCLUtils_clewInit();
+#endif
+
+       cl_platform_id platform = 0;
+       unsigned int platformIndex = (unsigned int)platformIndex0;
+       cl_uint numPlatforms;
+       cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
+
+       if (platformIndex < numPlatforms)
+       {
+               cl_platform_id* platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * numPlatforms);
+               ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL);
+               if (ciErrNum != CL_SUCCESS)
+               {
+                       if (pErrNum != NULL)
+                               *pErrNum = ciErrNum;
+                       return platform;
+               }
+
+               platform = platforms[platformIndex];
+
+               free(platforms);
+       }
+
+       return platform;
+}
+
+void b3OpenCLUtils::getPlatformInfo(cl_platform_id platform, b3OpenCLPlatformInfo* platformInfo)
+{
+       b3Assert(platform);
+       cl_int ciErrNum;
+       ciErrNum = clGetPlatformInfo(platform, CL_PLATFORM_VENDOR, B3_MAX_STRING_LENGTH, platformInfo->m_platformVendor, NULL);
+       oclCHECKERROR(ciErrNum, CL_SUCCESS);
+       ciErrNum = clGetPlatformInfo(platform, CL_PLATFORM_NAME, B3_MAX_STRING_LENGTH, platformInfo->m_platformName, NULL);
+       oclCHECKERROR(ciErrNum, CL_SUCCESS);
+       ciErrNum = clGetPlatformInfo(platform, CL_PLATFORM_VERSION, B3_MAX_STRING_LENGTH, platformInfo->m_platformVersion, NULL);
+       oclCHECKERROR(ciErrNum, CL_SUCCESS);
+}
+
+void b3OpenCLUtils_printPlatformInfo(cl_platform_id platform)
+{
+       b3OpenCLPlatformInfo platformInfo;
+       b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
+       b3Printf("Platform info:\n");
+       b3Printf("  CL_PLATFORM_VENDOR: \t\t\t%s\n", platformInfo.m_platformVendor);
+       b3Printf("  CL_PLATFORM_NAME: \t\t\t%s\n", platformInfo.m_platformName);
+       b3Printf("  CL_PLATFORM_VERSION: \t\t\t%s\n", platformInfo.m_platformVersion);
+}
+
+cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex)
+{
+       cl_context retContext = 0;
+       cl_int ciErrNum = 0;
+       cl_uint num_entries;
+       cl_device_id devices[B3_MAX_CL_DEVICES];
+       cl_uint num_devices;
+       cl_context_properties* cprops;
+
+       /*
+       * If we could find our platform, use it. Otherwise pass a NULL and get whatever the
+       * implementation thinks we should be using.
+       */
+       cl_context_properties cps[7] = {0, 0, 0, 0, 0, 0, 0};
+       cps[0] = CL_CONTEXT_PLATFORM;
+       cps[1] = (cl_context_properties)platform;
+#ifdef _WIN32
+#ifndef B3_USE_CLEW
+       if (pGLContext && pGLDC)
+       {
+               cps[2] = CL_GL_CONTEXT_KHR;
+               cps[3] = (cl_context_properties)pGLContext;
+               cps[4] = CL_WGL_HDC_KHR;
+               cps[5] = (cl_context_properties)pGLDC;
+       }
+#endif  //B3_USE_CLEW
+#endif  //_WIN32
+       num_entries = B3_MAX_CL_DEVICES;
+
+       num_devices = -1;
+
+       ciErrNum = clGetDeviceIDs(
+               platform,
+               deviceType,
+               num_entries,
+               devices,
+               &num_devices);
+
+       if (ciErrNum < 0)
+       {
+               b3Printf("clGetDeviceIDs returned %d\n", ciErrNum);
+               return 0;
+       }
+       cprops = (NULL == platform) ? NULL : cps;
+
+       if (!num_devices)
+               return 0;
+
+       if (pGLContext)
+       {
+               //search for the GPU that relates to the OpenCL context
+               unsigned int i;
+               for (i = 0; i < num_devices; i++)
+               {
+                       retContext = clCreateContext(cprops, 1, &devices[i], NULL, NULL, &ciErrNum);
+                       if (ciErrNum == CL_SUCCESS)
+                               break;
+               }
+       }
+       else
+       {
+               if (preferredDeviceIndex >= 0 && (unsigned int)preferredDeviceIndex < num_devices)
+               {
+                       //create a context of the preferred device index
+                       retContext = clCreateContext(cprops, 1, &devices[preferredDeviceIndex], NULL, NULL, &ciErrNum);
+               }
+               else
+               {
+                       //create a context of all devices
+#if defined(__APPLE__)
+                       retContext = clCreateContext(cprops, num_devices, devices, MyFatalBreakAPPLE, NULL, &ciErrNum);
+#else
+                       b3Printf("numDevices=%d\n", num_devices);
+
+                       retContext = clCreateContext(cprops, num_devices, devices, NULL, NULL, &ciErrNum);
+#endif
+               }
+       }
+       if (pErrNum != NULL)
+       {
+               *pErrNum = ciErrNum;
+       };
+
+       return retContext;
+}
+
+cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex, cl_platform_id* retPlatformId)
+{
+#ifdef B3_USE_CLEW
+       b3OpenCLUtils_clewInit();
+#endif
+
+       cl_uint numPlatforms;
+       cl_context retContext = 0;
+       unsigned int i;
+
+       cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
+       if (ciErrNum != CL_SUCCESS)
+       {
+               if (pErrNum != NULL) *pErrNum = ciErrNum;
+               return NULL;
+       }
+       if (numPlatforms > 0)
+       {
+               cl_platform_id* platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * numPlatforms);
+               ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL);
+               if (ciErrNum != CL_SUCCESS)
+               {
+                       if (pErrNum != NULL)
+                               *pErrNum = ciErrNum;
+                       free(platforms);
+                       return NULL;
+               }
+
+               for (i = 0; i < numPlatforms; ++i)
+               {
+                       char pbuf[128];
+                       ciErrNum = clGetPlatformInfo(platforms[i],
+                                                                                CL_PLATFORM_VENDOR,
+                                                                                sizeof(pbuf),
+                                                                                pbuf,
+                                                                                NULL);
+                       if (ciErrNum != CL_SUCCESS)
+                       {
+                               if (pErrNum != NULL) *pErrNum = ciErrNum;
+                               return NULL;
+                       }
+
+                       if (preferredPlatformIndex >= 0 && i == preferredPlatformIndex)
+                       {
+                               cl_platform_id tmpPlatform = platforms[0];
+                               platforms[0] = platforms[i];
+                               platforms[i] = tmpPlatform;
+                               break;
+                       }
+                       else
+                       {
+                               if (!strcmp(pbuf, spPlatformVendor))
+                               {
+                                       cl_platform_id tmpPlatform = platforms[0];
+                                       platforms[0] = platforms[i];
+                                       platforms[i] = tmpPlatform;
+                               }
+                       }
+               }
+
+               for (i = 0; i < numPlatforms; ++i)
+               {
+                       cl_platform_id platform = platforms[i];
+                       assert(platform);
+
+                       retContext = b3OpenCLUtils_createContextFromPlatform(platform, deviceType, pErrNum, pGLContext, pGLDC, preferredDeviceIndex, preferredPlatformIndex);
+
+                       if (retContext)
+                       {
+                               //                              printf("OpenCL platform details:\n");
+                               b3OpenCLPlatformInfo platformInfo;
+
+                               b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
+
+                               if (retPlatformId)
+                                       *retPlatformId = platform;
+
+                               break;
+                       }
+               }
+
+               free(platforms);
+       }
+       return retContext;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//! Gets the id of the nth device from the context
+//!
+//! @return the id or -1 when out of range
+//! @param cxMainContext         OpenCL context
+//! @param device_idx            index of the device of interest
+//////////////////////////////////////////////////////////////////////////////
+cl_device_id b3OpenCLUtils_getDevice(cl_context cxMainContext, int deviceIndex)
+{
+       assert(cxMainContext);
+
+       size_t szParmDataBytes;
+       cl_device_id* cdDevices;
+       cl_device_id device;
+
+       // get the list of devices associated with context
+       clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParmDataBytes);
+
+       if (szParmDataBytes / sizeof(cl_device_id) < (unsigned int)deviceIndex)
+       {
+               return (cl_device_id)-1;
+       }
+
+       cdDevices = (cl_device_id*)malloc(szParmDataBytes);
+
+       clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, szParmDataBytes, cdDevices, NULL);
+
+       device = cdDevices[deviceIndex];
+       free(cdDevices);
+
+       return device;
+}
+
+int b3OpenCLUtils_getNumDevices(cl_context cxMainContext)
+{
+       size_t szParamDataBytes;
+       int device_count;
+       clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParamDataBytes);
+       device_count = (int)szParamDataBytes / sizeof(cl_device_id);
+       return device_count;
+}
+
+void b3OpenCLUtils::getDeviceInfo(cl_device_id device, b3OpenCLDeviceInfo* info)
+{
+       // CL_DEVICE_NAME
+       clGetDeviceInfo(device, CL_DEVICE_NAME, B3_MAX_STRING_LENGTH, &info->m_deviceName, NULL);
+
+       // CL_DEVICE_VENDOR
+       clGetDeviceInfo(device, CL_DEVICE_VENDOR, B3_MAX_STRING_LENGTH, &info->m_deviceVendor, NULL);
+
+       // CL_DRIVER_VERSION
+       clGetDeviceInfo(device, CL_DRIVER_VERSION, B3_MAX_STRING_LENGTH, &info->m_driverVersion, NULL);
+
+       // CL_DEVICE_INFO
+       clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(cl_device_type), &info->m_deviceType, NULL);
+
+       // CL_DEVICE_MAX_COMPUTE_UNITS
+       clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(info->m_computeUnits), &info->m_computeUnits, NULL);
+
+       // CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
+       clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(info->m_workitemDims), &info->m_workitemDims, NULL);
+
+       // CL_DEVICE_MAX_WORK_ITEM_SIZES
+       clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(info->m_workItemSize), &info->m_workItemSize, NULL);
+
+       // CL_DEVICE_MAX_WORK_GROUP_SIZE
+       clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(info->m_workgroupSize), &info->m_workgroupSize, NULL);
+
+       // CL_DEVICE_MAX_CLOCK_FREQUENCY
+       clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(info->m_clockFrequency), &info->m_clockFrequency, NULL);
+
+       // CL_DEVICE_ADDRESS_BITS
+       clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(info->m_addressBits), &info->m_addressBits, NULL);
+
+       // CL_DEVICE_MAX_MEM_ALLOC_SIZE
+       clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(info->m_maxMemAllocSize), &info->m_maxMemAllocSize, NULL);
+
+       // CL_DEVICE_GLOBAL_MEM_SIZE
+       clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(info->m_globalMemSize), &info->m_globalMemSize, NULL);
+
+       // CL_DEVICE_ERROR_CORRECTION_SUPPORT
+       clGetDeviceInfo(device, CL_DEVICE_ERROR_CORRECTION_SUPPORT, sizeof(info->m_errorCorrectionSupport), &info->m_errorCorrectionSupport, NULL);
+
+       // CL_DEVICE_LOCAL_MEM_TYPE
+       clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(info->m_localMemType), &info->m_localMemType, NULL);
+
+       // CL_DEVICE_LOCAL_MEM_SIZE
+       clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(info->m_localMemSize), &info->m_localMemSize, NULL);
+
+       // CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
+       clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(info->m_constantBufferSize), &info->m_constantBufferSize, NULL);
+
+       // CL_DEVICE_QUEUE_PROPERTIES
+       clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES, sizeof(info->m_queueProperties), &info->m_queueProperties, NULL);
+
+       // CL_DEVICE_IMAGE_SUPPORT
+       clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, sizeof(info->m_imageSupport), &info->m_imageSupport, NULL);
+
+       // CL_DEVICE_MAX_READ_IMAGE_ARGS
+       clGetDeviceInfo(device, CL_DEVICE_MAX_READ_IMAGE_ARGS, sizeof(info->m_maxReadImageArgs), &info->m_maxReadImageArgs, NULL);
+
+       // CL_DEVICE_MAX_WRITE_IMAGE_ARGS
+       clGetDeviceInfo(device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof(info->m_maxWriteImageArgs), &info->m_maxWriteImageArgs, NULL);
+
+       // CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_DEPTH
+       clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &info->m_image2dMaxWidth, NULL);
+       clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &info->m_image2dMaxHeight, NULL);
+       clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &info->m_image3dMaxWidth, NULL);
+       clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &info->m_image3dMaxHeight, NULL);
+       clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &info->m_image3dMaxDepth, NULL);
+
+       // CL_DEVICE_EXTENSIONS: get device extensions, and if any then parse & log the string onto separate lines
+       clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, B3_MAX_STRING_LENGTH, &info->m_deviceExtensions, NULL);
+
+       // CL_DEVICE_PREFERRED_VECTOR_WIDTH_<type>
+       clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &info->m_vecWidthChar, NULL);
+       clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, sizeof(cl_uint), &info->m_vecWidthShort, NULL);
+       clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, sizeof(cl_uint), &info->m_vecWidthInt, NULL);
+       clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, sizeof(cl_uint), &info->m_vecWidthLong, NULL);
+       clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof(cl_uint), &info->m_vecWidthFloat, NULL);
+       clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &info->m_vecWidthDouble, NULL);
+}
+
+void b3OpenCLUtils_printDeviceInfo(cl_device_id device)
+{
+       b3OpenCLDeviceInfo info;
+       b3OpenCLUtils::getDeviceInfo(device, &info);
+       b3Printf("Device Info:\n");
+       b3Printf("  CL_DEVICE_NAME: \t\t\t%s\n", info.m_deviceName);
+       b3Printf("  CL_DEVICE_VENDOR: \t\t\t%s\n", info.m_deviceVendor);
+       b3Printf("  CL_DRIVER_VERSION: \t\t\t%s\n", info.m_driverVersion);
+
+       if (info.m_deviceType & CL_DEVICE_TYPE_CPU)
+               b3Printf("  CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_CPU");
+       if (info.m_deviceType & CL_DEVICE_TYPE_GPU)
+               b3Printf("  CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_GPU");
+       if (info.m_deviceType & CL_DEVICE_TYPE_ACCELERATOR)
+               b3Printf("  CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR");
+       if (info.m_deviceType & CL_DEVICE_TYPE_DEFAULT)
+               b3Printf("  CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT");
+
+       b3Printf("  CL_DEVICE_MAX_COMPUTE_UNITS:\t\t%u\n", info.m_computeUnits);
+       b3Printf("  CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:\t%u\n", info.m_workitemDims);
+       b3Printf("  CL_DEVICE_MAX_WORK_ITEM_SIZES:\t%u / %u / %u \n", info.m_workItemSize[0], info.m_workItemSize[1], info.m_workItemSize[2]);
+       b3Printf("  CL_DEVICE_MAX_WORK_GROUP_SIZE:\t%u\n", info.m_workgroupSize);
+       b3Printf("  CL_DEVICE_MAX_CLOCK_FREQUENCY:\t%u MHz\n", info.m_clockFrequency);
+       b3Printf("  CL_DEVICE_ADDRESS_BITS:\t\t%u\n", info.m_addressBits);
+       b3Printf("  CL_DEVICE_MAX_MEM_ALLOC_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_maxMemAllocSize / (1024 * 1024)));
+       b3Printf("  CL_DEVICE_GLOBAL_MEM_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_globalMemSize / (1024 * 1024)));
+       b3Printf("  CL_DEVICE_ERROR_CORRECTION_SUPPORT:\t%s\n", info.m_errorCorrectionSupport == CL_TRUE ? "yes" : "no");
+       b3Printf("  CL_DEVICE_LOCAL_MEM_TYPE:\t\t%s\n", info.m_localMemType == 1 ? "local" : "global");
+       b3Printf("  CL_DEVICE_LOCAL_MEM_SIZE:\t\t%u KByte\n", (unsigned int)(info.m_localMemSize / 1024));
+       b3Printf("  CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:\t%u KByte\n", (unsigned int)(info.m_constantBufferSize / 1024));
+       if (info.m_queueProperties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)
+               b3Printf("  CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE");
+       if (info.m_queueProperties & CL_QUEUE_PROFILING_ENABLE)
+               b3Printf("  CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_PROFILING_ENABLE");
+
+       b3Printf("  CL_DEVICE_IMAGE_SUPPORT:\t\t%u\n", info.m_imageSupport);
+
+       b3Printf("  CL_DEVICE_MAX_READ_IMAGE_ARGS:\t%u\n", info.m_maxReadImageArgs);
+       b3Printf("  CL_DEVICE_MAX_WRITE_IMAGE_ARGS:\t%u\n", info.m_maxWriteImageArgs);
+       b3Printf("\n  CL_DEVICE_IMAGE <dim>");
+       b3Printf("\t\t\t2D_MAX_WIDTH\t %u\n", info.m_image2dMaxWidth);
+       b3Printf("\t\t\t\t\t2D_MAX_HEIGHT\t %u\n", info.m_image2dMaxHeight);
+       b3Printf("\t\t\t\t\t3D_MAX_WIDTH\t %u\n", info.m_image3dMaxWidth);
+       b3Printf("\t\t\t\t\t3D_MAX_HEIGHT\t %u\n", info.m_image3dMaxHeight);
+       b3Printf("\t\t\t\t\t3D_MAX_DEPTH\t %u\n", info.m_image3dMaxDepth);
+       if (*info.m_deviceExtensions != 0)
+       {
+               b3Printf("\n  CL_DEVICE_EXTENSIONS:%s\n", info.m_deviceExtensions);
+       }
+       else
+       {
+               b3Printf("  CL_DEVICE_EXTENSIONS: None\n");
+       }
+       b3Printf("  CL_DEVICE_PREFERRED_VECTOR_WIDTH_<t>\t");
+       b3Printf("CHAR %u, SHORT %u, INT %u,LONG %u, FLOAT %u, DOUBLE %u\n\n\n",
+                        info.m_vecWidthChar, info.m_vecWidthShort, info.m_vecWidthInt, info.m_vecWidthLong, info.m_vecWidthFloat, info.m_vecWidthDouble);
+}
+
+static const char* strip2(const char* name, const char* pattern)
+{
+       size_t const patlen = strlen(pattern);
+       size_t patcnt = 0;
+       const char* oriptr;
+       const char* patloc;
+       // find how many times the pattern occurs in the original string
+       for (oriptr = name; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
+       {
+               patcnt++;
+       }
+       return oriptr;
+}
+
+cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSourceOrg, cl_int* pErrNum, const char* additionalMacrosArg, const char* clFileNameForCaching, bool disableBinaryCaching)
+{
+       const char* additionalMacros = additionalMacrosArg ? additionalMacrosArg : "";
+
+       if (disableBinaryCaching)
+       {
+               //kernelSourceOrg = 0;
+       }
+
+       cl_program m_cpProgram = 0;
+       cl_int status;
+
+       char binaryFileName[B3_MAX_STRING_LENGTH];
+
+       char deviceName[256];
+       char driverVersion[256];
+       const char* strippedName;
+       int fileUpToDate = 0;
+#ifdef _WIN32
+       int binaryFileValid = 0;
+#endif
+       if (!disableBinaryCaching && clFileNameForCaching)
+       {
+               clGetDeviceInfo(device, CL_DEVICE_NAME, 256, &deviceName, NULL);
+               clGetDeviceInfo(device, CL_DRIVER_VERSION, 256, &driverVersion, NULL);
+
+               strippedName = strip2(clFileNameForCaching, "\\");
+               strippedName = strip2(strippedName, "/");
+
+#ifdef _MSC_VER
+               sprintf_s(binaryFileName, B3_MAX_STRING_LENGTH, "%s/%s.%s.%s.bin", sCachedBinaryPath, strippedName, deviceName, driverVersion);
+#else
+               sprintf(binaryFileName, "%s/%s.%s.%s.bin", sCachedBinaryPath, strippedName, deviceName, driverVersion);
+#endif
+       }
+       if (clFileNameForCaching && !(disableBinaryCaching || gDebugSkipLoadingBinary || gDebugForceLoadingFromSource))
+       {
+#ifdef _WIN32
+               char* bla = 0;
+
+               //printf("searching for %s\n", binaryFileName);
+
+               FILETIME modtimeBinary;
+               CreateDirectoryA(sCachedBinaryPath, 0);
+               {
+                       HANDLE binaryFileHandle = CreateFileA(binaryFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+                       if (binaryFileHandle == INVALID_HANDLE_VALUE)
+                       {
+                               DWORD errorCode;
+                               errorCode = GetLastError();
+                               switch (errorCode)
+                               {
+                                       case ERROR_FILE_NOT_FOUND:
+                                       {
+                                               b3Warning("\nCached file not found %s\n", binaryFileName);
+                                               break;
+                                       }
+                                       case ERROR_PATH_NOT_FOUND:
+                                       {
+                                               b3Warning("\nCached file path not found %s\n", binaryFileName);
+                                               break;
+                                       }
+                                       default:
+                                       {
+                                               b3Warning("\nFailed reading cached file with errorCode = %d\n", errorCode);
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               if (GetFileTime(binaryFileHandle, NULL, NULL, &modtimeBinary) == 0)
+                               {
+                                       DWORD errorCode;
+                                       errorCode = GetLastError();
+                                       b3Warning("\nGetFileTime errorCode = %d\n", errorCode);
+                               }
+                               else
+                               {
+                                       binaryFileValid = 1;
+                               }
+                               CloseHandle(binaryFileHandle);
+                       }
+
+                       if (binaryFileValid)
+                       {
+                               HANDLE srcFileHandle = CreateFileA(clFileNameForCaching, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+
+                               if (srcFileHandle == INVALID_HANDLE_VALUE)
+                               {
+                                       const char* prefix[] = {"./", "../", "../../", "../../../", "../../../../"};
+                                       for (int i = 0; (srcFileHandle == INVALID_HANDLE_VALUE) && i < 5; i++)
+                                       {
+                                               char relativeFileName[1024];
+                                               sprintf(relativeFileName, "%s%s", prefix[i], clFileNameForCaching);
+                                               srcFileHandle = CreateFileA(relativeFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+                                       }
+                               }
+
+                               if (srcFileHandle != INVALID_HANDLE_VALUE)
+                               {
+                                       FILETIME modtimeSrc;
+                                       if (GetFileTime(srcFileHandle, NULL, NULL, &modtimeSrc) == 0)
+                                       {
+                                               DWORD errorCode;
+                                               errorCode = GetLastError();
+                                               b3Warning("\nGetFileTime errorCode = %d\n", errorCode);
+                                       }
+                                       if ((modtimeSrc.dwHighDateTime < modtimeBinary.dwHighDateTime) || ((modtimeSrc.dwHighDateTime == modtimeBinary.dwHighDateTime) && (modtimeSrc.dwLowDateTime <= modtimeBinary.dwLowDateTime)))
+                                       {
+                                               fileUpToDate = 1;
+                                       }
+                                       else
+                                       {
+                                               b3Warning("\nCached binary file out-of-date (%s)\n", binaryFileName);
+                                       }
+                                       CloseHandle(srcFileHandle);
+                               }
+                               else
+                               {
+#ifdef _DEBUG
+                                       DWORD errorCode;
+                                       errorCode = GetLastError();
+                                       switch (errorCode)
+                                       {
+                                               case ERROR_FILE_NOT_FOUND:
+                                               {
+                                                       b3Warning("\nSrc file not found %s\n", clFileNameForCaching);
+                                                       break;
+                                               }
+                                               case ERROR_PATH_NOT_FOUND:
+                                               {
+                                                       b3Warning("\nSrc path not found %s\n", clFileNameForCaching);
+                                                       break;
+                                               }
+                                               default:
+                                               {
+                                                       b3Warning("\nnSrc file reading errorCode = %d\n", errorCode);
+                                               }
+                                       }
+
+                                       //we should make sure the src file exists so we can verify the timestamp with binary
+                                       //                                      assert(0);
+                                       b3Warning("Warning: cannot find OpenCL kernel %s to verify timestamp of binary cached kernel %s\n", clFileNameForCaching, binaryFileName);
+                                       fileUpToDate = true;
+#else
+                                       //if we cannot find the source, assume it is OK in release builds
+                                       fileUpToDate = true;
+#endif
+                               }
+                       }
+               }
+
+#else
+               fileUpToDate = true;
+               if (mkdir(sCachedBinaryPath, 0777) == -1)
+               {
+               }
+               else
+               {
+                       b3Printf("Succesfully created cache directory: %s\n", sCachedBinaryPath);
+               }
+#endif  //_WIN32
+       }
+
+       if (fileUpToDate)
+       {
+#ifdef _MSC_VER
+               FILE* file;
+               if (fopen_s(&file, binaryFileName, "rb") != 0)
+                       file = 0;
+#else
+               FILE* file = fopen(binaryFileName, "rb");
+#endif
+
+               if (file)
+               {
+                       size_t binarySize = 0;
+                       char* binary = 0;
+
+                       fseek(file, 0L, SEEK_END);
+                       binarySize = ftell(file);
+                       rewind(file);
+                       binary = (char*)malloc(sizeof(char) * binarySize);
+                       int bytesRead;
+                       bytesRead = fread(binary, sizeof(char), binarySize, file);
+                       fclose(file);
+
+                       m_cpProgram = clCreateProgramWithBinary(clContext, 1, &device, &binarySize, (const unsigned char**)&binary, 0, &status);
+                       b3Assert(status == CL_SUCCESS);
+                       status = clBuildProgram(m_cpProgram, 1, &device, additionalMacros, 0, 0);
+                       b3Assert(status == CL_SUCCESS);
+
+                       if (status != CL_SUCCESS)
+                       {
+                               char* build_log;
+                               size_t ret_val_size;
+                               clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
+                               build_log = (char*)malloc(sizeof(char) * (ret_val_size + 1));
+                               clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
+                               build_log[ret_val_size] = '\0';
+                               b3Error("%s\n", build_log);
+                               free(build_log);
+                               b3Assert(0);
+                               m_cpProgram = 0;
+
+                               b3Warning("clBuildProgram reported failure on cached binary: %s\n", binaryFileName);
+                       }
+                       else
+                       {
+                               b3Printf("clBuildProgram successfully compiled cached binary: %s\n", binaryFileName);
+                       }
+                       free(binary);
+               }
+               else
+               {
+                       b3Warning("Cannot open cached binary: %s\n", binaryFileName);
+               }
+       }
+
+       if (!m_cpProgram)
+       {
+               cl_int localErrNum;
+               char* compileFlags;
+               int flagsize;
+
+               const char* kernelSource = kernelSourceOrg;
+
+               if (!kernelSourceOrg || gDebugForceLoadingFromSource)
+               {
+                       if (clFileNameForCaching)
+                       {
+                               FILE* file = fopen(clFileNameForCaching, "rb");
+                               //in many cases the relative path is a few levels up the directory hierarchy, so try it
+                               if (!file)
+                               {
+                                       const char* prefix[] = {"../", "../../", "../../../", "../../../../"};
+                                       for (int i = 0; !file && i < 3; i++)
+                                       {
+                                               char relativeFileName[1024];
+                                               sprintf(relativeFileName, "%s%s", prefix[i], clFileNameForCaching);
+                                               file = fopen(relativeFileName, "rb");
+                                       }
+                               }
+
+                               if (file)
+                               {
+                                       char* kernelSrc = 0;
+                                       fseek(file, 0L, SEEK_END);
+                                       int kernelSize = ftell(file);
+                                       rewind(file);
+                                       kernelSrc = (char*)malloc(kernelSize + 1);
+                                       int readBytes;
+                                       readBytes = fread((void*)kernelSrc, 1, kernelSize, file);
+                                       kernelSrc[kernelSize] = 0;
+                                       fclose(file);
+                                       kernelSource = kernelSrc;
+                               }
+                       }
+               }
+
+               size_t program_length = kernelSource ? strlen(kernelSource) : 0;
+#ifdef MAC  //or __APPLE__?
+               char* flags = "-cl-mad-enable -DMAC ";
+#else
+               const char* flags = "";
+#endif
+
+               m_cpProgram = clCreateProgramWithSource(clContext, 1, (const char**)&kernelSource, &program_length, &localErrNum);
+               if (localErrNum != CL_SUCCESS)
+               {
+                       if (pErrNum)
+                               *pErrNum = localErrNum;
+                       return 0;
+               }
+
+               // Build the program with 'mad' Optimization option
+
+               flagsize = sizeof(char) * (strlen(additionalMacros) + strlen(flags) + 5);
+               compileFlags = (char*)malloc(flagsize);
+#ifdef _MSC_VER
+               sprintf_s(compileFlags, flagsize, "%s %s", flags, additionalMacros);
+#else
+               sprintf(compileFlags, "%s %s", flags, additionalMacros);
+#endif
+               localErrNum = clBuildProgram(m_cpProgram, 1, &device, compileFlags, NULL, NULL);
+               if (localErrNum != CL_SUCCESS)
+               {
+                       char* build_log;
+                       size_t ret_val_size;
+                       clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
+                       build_log = (char*)malloc(sizeof(char) * (ret_val_size + 1));
+                       clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
+
+                       // to be carefully, terminate with \0
+                       // there's no information in the reference whether the string is 0 terminated or not
+                       build_log[ret_val_size] = '\0';
+
+                       b3Error("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log);
+                       free(build_log);
+                       if (pErrNum)
+                               *pErrNum = localErrNum;
+                       return 0;
+               }
+
+               if (!disableBinaryCaching && clFileNameForCaching)
+               {  //   write to binary
+
+                       cl_uint numAssociatedDevices;
+                       status = clGetProgramInfo(m_cpProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &numAssociatedDevices, 0);
+                       b3Assert(status == CL_SUCCESS);
+                       if (numAssociatedDevices == 1)
+                       {
+                               size_t binarySize;
+                               char* binary;
+
+                               status = clGetProgramInfo(m_cpProgram, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, 0);
+                               b3Assert(status == CL_SUCCESS);
+
+                               binary = (char*)malloc(sizeof(char) * binarySize);
+
+                               status = clGetProgramInfo(m_cpProgram, CL_PROGRAM_BINARIES, sizeof(char*), &binary, 0);
+                               b3Assert(status == CL_SUCCESS);
+
+                               {
+                                       FILE* file = 0;
+#ifdef _MSC_VER
+                                       if (fopen_s(&file, binaryFileName, "wb") != 0)
+                                               file = 0;
+#else
+                                       file = fopen(binaryFileName, "wb");
+#endif
+                                       if (file)
+                                       {
+                                               fwrite(binary, sizeof(char), binarySize, file);
+                                               fclose(file);
+                                       }
+                                       else
+                                       {
+                                               b3Warning("cannot write file %s\n", binaryFileName);
+                                       }
+                               }
+
+                               free(binary);
+                       }
+               }
+
+               free(compileFlags);
+       }
+       return m_cpProgram;
+}
+
+cl_kernel b3OpenCLUtils_compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros)
+{
+       cl_kernel kernel;
+       cl_int localErrNum;
+
+       cl_program m_cpProgram = prog;
+
+       b3Printf("compiling kernel %s ", kernelName);
+
+       if (!m_cpProgram)
+       {
+               m_cpProgram = b3OpenCLUtils_compileCLProgramFromString(clContext, device, kernelSource, pErrNum, additionalMacros, 0, false);
+       }
+
+       // Create the kernel
+       kernel = clCreateKernel(m_cpProgram, kernelName, &localErrNum);
+       if (localErrNum != CL_SUCCESS)
+       {
+               b3Error("Error in clCreateKernel, Line %u in file %s, cannot find kernel function %s !!!\n\n", __LINE__, __FILE__, kernelName);
+               assert(0);
+               if (pErrNum)
+                       *pErrNum = localErrNum;
+               return 0;
+       }
+
+       if (!prog && m_cpProgram)
+       {
+               clReleaseProgram(m_cpProgram);
+       }
+       b3Printf("ready. \n");
+
+       if (pErrNum)
+               *pErrNum = CL_SUCCESS;
+       return kernel;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Initialize/b3OpenCLUtils.h
new file mode 100644 (file)
index 0000000..6c82eed
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//original author: Roman Ponomarev
+//cleanup by Erwin Coumans
+
+#ifndef B3_OPENCL_UTILS_H
+#define B3_OPENCL_UTILS_H
+
+#include "b3OpenCLInclude.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+       ///C API for OpenCL utilities: convenience functions, see below for C++ API
+
+       /// CL Context optionally takes a GL context. This is a generic type because we don't really want this code
+       /// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise.
+       cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex, cl_platform_id* platformId);
+
+       int b3OpenCLUtils_getNumDevices(cl_context cxMainContext);
+
+       cl_device_id b3OpenCLUtils_getDevice(cl_context cxMainContext, int nr);
+
+       void b3OpenCLUtils_printDeviceInfo(cl_device_id device);
+
+       cl_kernel b3OpenCLUtils_compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros);
+
+       //optional
+       cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSource, cl_int* pErrNum, const char* additionalMacros, const char* srcFileNameForCaching, bool disableBinaryCaching);
+
+       //the following optional APIs provide access using specific platform information
+       int b3OpenCLUtils_getNumPlatforms(cl_int* pErrNum);
+
+       ///get the nr'th platform, where nr is in the range [0..getNumPlatforms)
+       cl_platform_id b3OpenCLUtils_getPlatform(int nr, cl_int* pErrNum);
+
+       void b3OpenCLUtils_printPlatformInfo(cl_platform_id platform);
+
+       const char* b3OpenCLUtils_getSdkVendorName();
+
+       ///set the path (directory/folder) where the compiled OpenCL kernel are stored
+       void b3OpenCLUtils_setCachePath(const char* path);
+
+       cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex);
+
+#ifdef __cplusplus
+}
+
+#define B3_MAX_STRING_LENGTH 1024
+
+typedef struct
+{
+       char m_deviceName[B3_MAX_STRING_LENGTH];
+       char m_deviceVendor[B3_MAX_STRING_LENGTH];
+       char m_driverVersion[B3_MAX_STRING_LENGTH];
+       char m_deviceExtensions[B3_MAX_STRING_LENGTH];
+
+       cl_device_type m_deviceType;
+       cl_uint m_computeUnits;
+       size_t m_workitemDims;
+       size_t m_workItemSize[3];
+       size_t m_image2dMaxWidth;
+       size_t m_image2dMaxHeight;
+       size_t m_image3dMaxWidth;
+       size_t m_image3dMaxHeight;
+       size_t m_image3dMaxDepth;
+       size_t m_workgroupSize;
+       cl_uint m_clockFrequency;
+       cl_ulong m_constantBufferSize;
+       cl_ulong m_localMemSize;
+       cl_ulong m_globalMemSize;
+       cl_bool m_errorCorrectionSupport;
+       cl_device_local_mem_type m_localMemType;
+       cl_uint m_maxReadImageArgs;
+       cl_uint m_maxWriteImageArgs;
+
+       cl_uint m_addressBits;
+       cl_ulong m_maxMemAllocSize;
+       cl_command_queue_properties m_queueProperties;
+       cl_bool m_imageSupport;
+       cl_uint m_vecWidthChar;
+       cl_uint m_vecWidthShort;
+       cl_uint m_vecWidthInt;
+       cl_uint m_vecWidthLong;
+       cl_uint m_vecWidthFloat;
+       cl_uint m_vecWidthDouble;
+
+} b3OpenCLDeviceInfo;
+
+struct b3OpenCLPlatformInfo
+{
+       char m_platformVendor[B3_MAX_STRING_LENGTH];
+       char m_platformName[B3_MAX_STRING_LENGTH];
+       char m_platformVersion[B3_MAX_STRING_LENGTH];
+
+       b3OpenCLPlatformInfo()
+       {
+               m_platformVendor[0] = 0;
+               m_platformName[0] = 0;
+               m_platformVersion[0] = 0;
+       }
+};
+
+///C++ API for OpenCL utilities: convenience functions
+struct b3OpenCLUtils
+{
+       /// CL Context optionally takes a GL context. This is a generic type because we don't really want this code
+       /// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise.
+       static inline cl_context createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0, int preferredDeviceIndex = -1, int preferredPlatformIndex = -1, cl_platform_id* platformId = 0)
+       {
+               return b3OpenCLUtils_createContextFromType(deviceType, pErrNum, pGLCtx, pGLDC, preferredDeviceIndex, preferredPlatformIndex, platformId);
+       }
+
+       static inline int getNumDevices(cl_context cxMainContext)
+       {
+               return b3OpenCLUtils_getNumDevices(cxMainContext);
+       }
+       static inline cl_device_id getDevice(cl_context cxMainContext, int nr)
+       {
+               return b3OpenCLUtils_getDevice(cxMainContext, nr);
+       }
+
+       static void getDeviceInfo(cl_device_id device, b3OpenCLDeviceInfo* info);
+
+       static inline void printDeviceInfo(cl_device_id device)
+       {
+               b3OpenCLUtils_printDeviceInfo(device);
+       }
+
+       static inline cl_kernel compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum = 0, cl_program prog = 0, const char* additionalMacros = "")
+       {
+               return b3OpenCLUtils_compileCLKernelFromString(clContext, device, kernelSource, kernelName, pErrNum, prog, additionalMacros);
+       }
+
+       //optional
+       static inline cl_program compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSource, cl_int* pErrNum = 0, const char* additionalMacros = "", const char* srcFileNameForCaching = 0, bool disableBinaryCaching = false)
+       {
+               return b3OpenCLUtils_compileCLProgramFromString(clContext, device, kernelSource, pErrNum, additionalMacros, srcFileNameForCaching, disableBinaryCaching);
+       }
+
+       //the following optional APIs provide access using specific platform information
+       static inline int getNumPlatforms(cl_int* pErrNum = 0)
+       {
+               return b3OpenCLUtils_getNumPlatforms(pErrNum);
+       }
+       ///get the nr'th platform, where nr is in the range [0..getNumPlatforms)
+       static inline cl_platform_id getPlatform(int nr, cl_int* pErrNum = 0)
+       {
+               return b3OpenCLUtils_getPlatform(nr, pErrNum);
+       }
+
+       static void getPlatformInfo(cl_platform_id platform, b3OpenCLPlatformInfo* platformInfo);
+
+       static inline void printPlatformInfo(cl_platform_id platform)
+       {
+               b3OpenCLUtils_printPlatformInfo(platform);
+       }
+
+       static inline const char* getSdkVendorName()
+       {
+               return b3OpenCLUtils_getSdkVendorName();
+       }
+       static inline cl_context createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0, int preferredDeviceIndex = -1, int preferredPlatformIndex = -1)
+       {
+               return b3OpenCLUtils_createContextFromPlatform(platform, deviceType, pErrNum, pGLCtx, pGLDC, preferredDeviceIndex, preferredPlatformIndex);
+       }
+       static void setCachePath(const char* path)
+       {
+               b3OpenCLUtils_setCachePath(path);
+       }
+};
+
+#endif  //__cplusplus
+
+#endif  // B3_OPENCL_UTILS_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h
new file mode 100644 (file)
index 0000000..27835bb
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef B3_BVH_INFO_H
+#define B3_BVH_INFO_H
+
+#include "Bullet3Common/b3Vector3.h"
+
+struct b3BvhInfo
+{
+       b3Vector3 m_aabbMin;
+       b3Vector3 m_aabbMax;
+       b3Vector3 m_quantization;
+       int m_numNodes;
+       int m_numSubTrees;
+       int m_nodeOffset;
+       int m_subTreeOffset;
+};
+
+#endif  //B3_BVH_INFO_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp
new file mode 100644 (file)
index 0000000..867b3e0
--- /dev/null
@@ -0,0 +1,253 @@
+
+#if 0
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3ContactCache.h"
+#include "Bullet3Common/b3Transform.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+b3Scalar                                       gContactBreakingThreshold = b3Scalar(0.02);
+
+///gContactCalcArea3Points will approximate the convex hull area using 3 points
+///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower
+bool                                           gContactCalcArea3Points = true;
+
+
+
+
+static inline b3Scalar calcArea4Points(const b3Vector3 &p0,const b3Vector3 &p1,const b3Vector3 &p2,const b3Vector3 &p3)
+{
+       // It calculates possible 3 area constructed from random 4 points and returns the biggest one.
+
+       b3Vector3 a[3],b[3];
+       a[0] = p0 - p1;
+       a[1] = p0 - p2;
+       a[2] = p0 - p3;
+       b[0] = p2 - p3;
+       b[1] = p1 - p3;
+       b[2] = p1 - p2;
+
+       //todo: Following 3 cross production can be easily optimized by SIMD.
+       b3Vector3 tmp0 = a[0].cross(b[0]);
+       b3Vector3 tmp1 = a[1].cross(b[1]);
+       b3Vector3 tmp2 = a[2].cross(b[2]);
+
+       return b3Max(b3Max(tmp0.length2(),tmp1.length2()),tmp2.length2());
+}
+#if 0
+
+//using localPointA for all points
+int b3ContactCache::sortCachedPoints(const b3Vector3& pt) 
+{
+               //calculate 4 possible cases areas, and take biggest area
+               //also need to keep 'deepest'
+               
+               int maxPenetrationIndex = -1;
+#define KEEP_DEEPEST_POINT 1
+#ifdef KEEP_DEEPEST_POINT
+               b3Scalar maxPenetration = pt.getDistance();
+               for (int i=0;i<4;i++)
+               {
+                       if (m_pointCache[i].getDistance() < maxPenetration)
+                       {
+                               maxPenetrationIndex = i;
+                               maxPenetration = m_pointCache[i].getDistance();
+                       }
+               }
+#endif  //KEEP_DEEPEST_POINT
+               
+               b3Scalar res0(b3Scalar(0.)),res1(b3Scalar(0.)),res2(b3Scalar(0.)),res3(b3Scalar(0.));
+
+       if (gContactCalcArea3Points)
+       {
+               if (maxPenetrationIndex != 0)
+               {
+                       b3Vector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
+                       b3Vector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+                       b3Vector3 cross = a0.cross(b0);
+                       res0 = cross.length2();
+               }
+               if (maxPenetrationIndex != 1)
+               {
+                       b3Vector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+                       b3Vector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+                       b3Vector3 cross = a1.cross(b1);
+                       res1 = cross.length2();
+               }
+
+               if (maxPenetrationIndex != 2)
+               {
+                       b3Vector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+                       b3Vector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
+                       b3Vector3 cross = a2.cross(b2);
+                       res2 = cross.length2();
+               }
+
+               if (maxPenetrationIndex != 3)
+               {
+                       b3Vector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+                       b3Vector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
+                       b3Vector3 cross = a3.cross(b3);
+                       res3 = cross.length2();
+               }
+       } 
+       else
+       {
+               if(maxPenetrationIndex != 0) {
+                       res0 = calcArea4Points(pt.m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
+               }
+
+               if(maxPenetrationIndex != 1) {
+                       res1 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
+               }
+
+               if(maxPenetrationIndex != 2) {
+                       res2 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[3].m_localPointA);
+               }
+
+               if(maxPenetrationIndex != 3) {
+                       res3 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA);
+               }
+       }
+       b3Vector4 maxvec(res0,res1,res2,res3);
+       int biggestarea = maxvec.closestAxis4();
+       return biggestarea;
+       
+}
+
+
+int b3ContactCache::getCacheEntry(const b3Vector3& newPoint) const
+{
+       b3Scalar shortestDist =  getContactBreakingThreshold() * getContactBreakingThreshold();
+       int size = getNumContacts();
+       int nearestPoint = -1;
+       for( int i = 0; i < size; i++ )
+       {
+               const b3Vector3 &mp = m_pointCache[i];
+
+               b3Vector3 diffA =  mp.m_localPointA- newPoint.m_localPointA;
+               const b3Scalar distToManiPoint = diffA.dot(diffA);
+               if( distToManiPoint < shortestDist )
+               {
+                       shortestDist = distToManiPoint;
+                       nearestPoint = i;
+               }
+       }
+       return nearestPoint;
+}
+
+int b3ContactCache::addManifoldPoint(const b3Vector3& newPoint)
+{
+       b3Assert(validContactDistance(newPoint));
+       
+       int insertIndex = getNumContacts();
+       if (insertIndex == MANIFOLD_CACHE_SIZE)
+       {
+#if MANIFOLD_CACHE_SIZE >= 4
+               //sort cache so best points come first, based on area
+               insertIndex = sortCachedPoints(newPoint);
+#else
+               insertIndex = 0;
+#endif
+               clearUserCache(m_pointCache[insertIndex]);
+               
+       } else
+       {
+               m_cachedPoints++;
+
+               
+       }
+       if (insertIndex<0)
+               insertIndex=0;
+
+       //b3Assert(m_pointCache[insertIndex].m_userPersistentData==0);
+       m_pointCache[insertIndex] = newPoint;
+       return insertIndex;
+}
+
+#endif
+
+bool b3ContactCache::validContactDistance(const b3Vector3& pt)
+{
+       return pt.w <= gContactBreakingThreshold;
+}
+
+void b3ContactCache::removeContactPoint(struct b3Contact4Data& newContactCache,int i)
+{
+       int numContacts = b3Contact4Data_getNumPoints(&newContactCache);
+       if (i!=(numContacts-1))
+       {
+               b3Swap(newContactCache.m_localPosA[i],newContactCache.m_localPosA[numContacts-1]);
+               b3Swap(newContactCache.m_localPosB[i],newContactCache.m_localPosB[numContacts-1]);
+               b3Swap(newContactCache.m_worldPosB[i],newContactCache.m_worldPosB[numContacts-1]);
+       }
+       b3Contact4Data_setNumPoints(&newContactCache,numContacts-1);
+
+}
+
+
+void b3ContactCache::refreshContactPoints(const b3Transform& trA,const b3Transform& trB, struct b3Contact4Data& contacts)
+{
+
+       int numContacts = b3Contact4Data_getNumPoints(&contacts);
+       
+
+       int i;
+       /// first refresh worldspace positions and distance
+       for (i=numContacts-1;i>=0;i--)
+       {
+               b3Vector3 worldPosA = trA( contacts.m_localPosA[i]);
+               b3Vector3 worldPosB = trB( contacts.m_localPosB[i]);
+               contacts.m_worldPosB[i] = worldPosB;
+               float distance = (worldPosA -  worldPosB).dot(contacts.m_worldNormalOnB);
+               contacts.m_worldPosB[i].w = distance;
+       }
+
+       /// then 
+       b3Scalar distance2d;
+       b3Vector3 projectedDifference,projectedPoint;
+       for (i=numContacts-1;i>=0;i--)
+       {
+               b3Vector3 worldPosA = trA( contacts.m_localPosA[i]);
+               b3Vector3 worldPosB = trB( contacts.m_localPosB[i]);
+               b3Vector3&pt = contacts.m_worldPosB[i];
+               //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
+               if (!validContactDistance(pt))
+               {
+                       removeContactPoint(contacts,i);
+               } else
+               {
+                       //contact also becomes invalid when relative movement orthogonal to normal exceeds margin
+                       projectedPoint = worldPosA - contacts.m_worldNormalOnB * contacts.m_worldPosB[i].w;
+                       projectedDifference = contacts.m_worldPosB[i] - projectedPoint;
+                       distance2d = projectedDifference.dot(projectedDifference);
+                       if (distance2d  > gContactBreakingThreshold*gContactBreakingThreshold )
+                       {
+                               removeContactPoint(contacts,i);
+                       } else
+                       {
+                               ////contact point processed callback
+                               //if (gContactProcessedCallback)
+                               //      (*gContactProcessedCallback)(manifoldPoint,(void*)m_body0,(void*)m_body1);
+                       }
+               }
+       }
+       
+
+}
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h
new file mode 100644 (file)
index 0000000..a15fd0b
--- /dev/null
@@ -0,0 +1,62 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_CONTACT_CACHE_H
+#define B3_CONTACT_CACHE_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Common/b3AlignedAllocator.h"
+
+///maximum contact breaking and merging threshold
+extern b3Scalar gContactBreakingThreshold;
+
+#define MANIFOLD_CACHE_SIZE 4
+
+///b3ContactCache 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.
+B3_ATTRIBUTE_ALIGNED16(class)
+b3ContactCache
+{
+       /// sort cached points so most isolated points come first
+       int sortCachedPoints(const b3Vector3& pt);
+
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       int addManifoldPoint(const b3Vector3& newPoint);
+
+       /*void replaceContactPoint(const b3Vector3& newPoint,int insertIndex)
+       {
+               b3Assert(validContactDistance(newPoint));
+               m_pointCache[insertIndex] = newPoint;
+       }
+       */
+
+       static bool validContactDistance(const b3Vector3& pt);
+
+       /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
+       static void refreshContactPoints(const b3Transform& trA, const b3Transform& trB, struct b3Contact4Data& newContactCache);
+
+       static void removeContactPoint(struct b3Contact4Data & newContactCache, int i);
+};
+
+#endif  //B3_CONTACT_CACHE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp
new file mode 100644 (file)
index 0000000..54a104c
--- /dev/null
@@ -0,0 +1,4408 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+bool findSeparatingAxisOnGpu = true;
+bool splitSearchSepAxisConcave = false;
+bool splitSearchSepAxisConvex = true;
+bool useMprGpu = true;  //use mpr for edge-edge  (+contact point) or sat. Needs testing on main OpenCL platforms, before enabling...
+bool bvhTraversalKernelGPU = true;
+bool findConcaveSeparatingAxisKernelGPU = true;
+bool clipConcaveFacesAndFindContactsCPU = false;  //false;//true;
+bool clipConvexFacesAndFindContactsCPU = false;   //false;//true;
+bool reduceConcaveContactsOnGPU = true;           //false;
+bool reduceConvexContactsOnGPU = true;            //false;
+bool findConvexClippingFacesGPU = true;
+bool useGjk = false;          ///option for CPU/host testing, when findSeparatingAxisOnGpu = false
+bool useGjkContacts = false;  //////option for CPU/host testing when findSeparatingAxisOnGpu = false
+
+static int myframecount = 0;  ///for testing
+
+///This file was written by Erwin Coumans
+///Separating axis rest based on work from Pierre Terdiman, see
+///And contact clipping based on work from Simon Hobbs
+
+//#define B3_DEBUG_SAT_FACE
+
+//#define CHECK_ON_HOST
+
+#ifdef CHECK_ON_HOST
+//#define PERSISTENT_CONTACTS_HOST
+#endif
+
+int b3g_actualSATPairTests = 0;
+
+#include "b3ConvexHullContact.h"
+#include <string.h>  //memcpy
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h"
+
+#include "Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+typedef b3AlignedObjectArray<b3Vector3> b3VertexArray;
+
+#include <float.h>  //for FLT_MAX
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+//#include "AdlQuaternion.h"
+
+#include "kernels/satKernels.h"
+#include "kernels/mprKernels.h"
+
+#include "kernels/satConcaveKernels.h"
+
+#include "kernels/satClipHullContacts.h"
+#include "kernels/bvhTraversal.h"
+#include "kernels/primitiveContacts.h"
+
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+#define BT_NARROWPHASE_SAT_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl"
+#define BT_NARROWPHASE_SAT_CONCAVE_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl"
+
+#define BT_NARROWPHASE_MPR_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl"
+
+#define BT_NARROWPHASE_CLIPHULL_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl"
+#define BT_NARROWPHASE_BVH_TRAVERSAL_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl"
+#define BT_NARROWPHASE_PRIMITIVE_CONTACT_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl"
+
+#ifndef __global
+#define __global
+#endif
+
+#ifndef __kernel
+#define __kernel
+#endif
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h"
+
+#define dot3F4 b3Dot
+
+GpuSatCollision::GpuSatCollision(cl_context ctx, cl_device_id device, cl_command_queue q)
+       : m_context(ctx),
+         m_device(device),
+         m_queue(q),
+
+         m_findSeparatingAxisKernel(0),
+         m_findSeparatingAxisVertexFaceKernel(0),
+         m_findSeparatingAxisEdgeEdgeKernel(0),
+         m_unitSphereDirections(m_context, m_queue),
+
+         m_totalContactsOut(m_context, m_queue),
+         m_sepNormals(m_context, m_queue),
+         m_dmins(m_context, m_queue),
+
+         m_hasSeparatingNormals(m_context, m_queue),
+         m_concaveSepNormals(m_context, m_queue),
+         m_concaveHasSeparatingNormals(m_context, m_queue),
+         m_numConcavePairsOut(m_context, m_queue),
+
+         m_gpuCompoundPairs(m_context, m_queue),
+
+         m_gpuCompoundSepNormals(m_context, m_queue),
+         m_gpuHasCompoundSepNormals(m_context, m_queue),
+
+         m_numCompoundPairsOut(m_context, m_queue)
+{
+       m_totalContactsOut.push_back(0);
+
+       cl_int errNum = 0;
+
+       if (1)
+       {
+               const char* mprSrc = mprKernelsCL;
+
+               const char* srcConcave = satConcaveKernelsCL;
+               char flags[1024] = {0};
+               //#ifdef CL_PLATFORM_INTEL
+               //              sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/sat.cl");
+               //#endif
+               m_mprPenetrationKernel = 0;
+               m_findSeparatingAxisUnitSphereKernel = 0;
+
+               if (useMprGpu)
+               {
+                       cl_program mprProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, mprSrc, &errNum, flags, BT_NARROWPHASE_MPR_PATH);
+                       b3Assert(errNum == CL_SUCCESS);
+
+                       m_mprPenetrationKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, mprSrc, "mprPenetrationKernel", &errNum, mprProg);
+                       b3Assert(m_mprPenetrationKernel);
+                       b3Assert(errNum == CL_SUCCESS);
+
+                       m_findSeparatingAxisUnitSphereKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, mprSrc, "findSeparatingAxisUnitSphereKernel", &errNum, mprProg);
+                       b3Assert(m_findSeparatingAxisUnitSphereKernel);
+                       b3Assert(errNum == CL_SUCCESS);
+
+                       int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
+                       m_unitSphereDirections.resize(numDirections);
+                       m_unitSphereDirections.copyFromHostPointer(unitSphere162, numDirections, 0, true);
+               }
+
+               cl_program satProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, satKernelsCL, &errNum, flags, BT_NARROWPHASE_SAT_PATH);
+               b3Assert(errNum == CL_SUCCESS);
+
+               cl_program satConcaveProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, srcConcave, &errNum, flags, BT_NARROWPHASE_SAT_CONCAVE_PATH);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_findSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findSeparatingAxisKernel", &errNum, satProg);
+               b3Assert(m_findSeparatingAxisKernel);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_findSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findSeparatingAxisVertexFaceKernel", &errNum, satProg);
+               b3Assert(m_findSeparatingAxisVertexFaceKernel);
+
+               m_findSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findSeparatingAxisEdgeEdgeKernel", &errNum, satProg);
+               b3Assert(m_findSeparatingAxisVertexFaceKernel);
+
+               m_findConcaveSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findConcaveSeparatingAxisKernel", &errNum, satProg);
+               b3Assert(m_findConcaveSeparatingAxisKernel);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_findConcaveSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcConcave, "findConcaveSeparatingAxisVertexFaceKernel", &errNum, satConcaveProg);
+               b3Assert(m_findConcaveSeparatingAxisVertexFaceKernel);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_findConcaveSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcConcave, "findConcaveSeparatingAxisEdgeEdgeKernel", &errNum, satConcaveProg);
+               b3Assert(m_findConcaveSeparatingAxisEdgeEdgeKernel);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_findCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findCompoundPairsKernel", &errNum, satProg);
+               b3Assert(m_findCompoundPairsKernel);
+               b3Assert(errNum == CL_SUCCESS);
+               m_processCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "processCompoundPairsKernel", &errNum, satProg);
+               b3Assert(m_processCompoundPairsKernel);
+               b3Assert(errNum == CL_SUCCESS);
+       }
+
+       if (1)
+       {
+               const char* srcClip = satClipKernelsCL;
+
+               char flags[1024] = {0};
+               //#ifdef CL_PLATFORM_INTEL
+               //              sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/satClipHullContacts.cl");
+               //#endif
+
+               cl_program satClipContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, srcClip, &errNum, flags, BT_NARROWPHASE_CLIPHULL_PATH);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_clipHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipHullHullKernel", &errNum, satClipContactsProg);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_clipCompoundsHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipCompoundsHullHullKernel", &errNum, satClipContactsProg);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_findClippingFacesKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "findClippingFacesKernel", &errNum, satClipContactsProg);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_clipFacesAndFindContacts = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipFacesAndFindContactsKernel", &errNum, satClipContactsProg);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_clipHullHullConcaveConvexKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipHullHullConcaveConvexKernel", &errNum, satClipContactsProg);
+               b3Assert(errNum == CL_SUCCESS);
+
+               //              m_extractManifoldAndAddContactKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "extractManifoldAndAddContactKernel",&errNum,satClipContactsProg);
+               //      b3Assert(errNum==CL_SUCCESS);
+
+               m_newContactReductionKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip,
+                                                                                                                                                          "newContactReductionKernel", &errNum, satClipContactsProg);
+               b3Assert(errNum == CL_SUCCESS);
+       }
+       else
+       {
+               m_clipHullHullKernel = 0;
+               m_clipCompoundsHullHullKernel = 0;
+               m_findClippingFacesKernel = 0;
+               m_newContactReductionKernel = 0;
+               m_clipFacesAndFindContacts = 0;
+               m_clipHullHullConcaveConvexKernel = 0;
+               //              m_extractManifoldAndAddContactKernel = 0;
+       }
+
+       if (1)
+       {
+               const char* srcBvh = bvhTraversalKernelCL;
+               cl_program bvhTraversalProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, srcBvh, &errNum, "", BT_NARROWPHASE_BVH_TRAVERSAL_PATH);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_bvhTraversalKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcBvh, "bvhTraversalKernel", &errNum, bvhTraversalProg, "");
+               b3Assert(errNum == CL_SUCCESS);
+       }
+
+       {
+               const char* primitiveContactsSrc = primitiveContactsKernelsCL;
+               cl_program primitiveContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, primitiveContactsSrc, &errNum, "", BT_NARROWPHASE_PRIMITIVE_CONTACT_PATH);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_primitiveContactsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, primitiveContactsSrc, "primitiveContactsKernel", &errNum, primitiveContactsProg, "");
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_findConcaveSphereContactsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, primitiveContactsSrc, "findConcaveSphereContactsKernel", &errNum, primitiveContactsProg);
+               b3Assert(errNum == CL_SUCCESS);
+               b3Assert(m_findConcaveSphereContactsKernel);
+
+               m_processCompoundPairsPrimitivesKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, primitiveContactsSrc, "processCompoundPairsPrimitivesKernel", &errNum, primitiveContactsProg, "");
+               b3Assert(errNum == CL_SUCCESS);
+               b3Assert(m_processCompoundPairsPrimitivesKernel);
+       }
+}
+
+GpuSatCollision::~GpuSatCollision()
+{
+       if (m_findSeparatingAxisVertexFaceKernel)
+               clReleaseKernel(m_findSeparatingAxisVertexFaceKernel);
+
+       if (m_findSeparatingAxisEdgeEdgeKernel)
+               clReleaseKernel(m_findSeparatingAxisEdgeEdgeKernel);
+
+       if (m_findSeparatingAxisUnitSphereKernel)
+               clReleaseKernel(m_findSeparatingAxisUnitSphereKernel);
+
+       if (m_mprPenetrationKernel)
+               clReleaseKernel(m_mprPenetrationKernel);
+
+       if (m_findSeparatingAxisKernel)
+               clReleaseKernel(m_findSeparatingAxisKernel);
+
+       if (m_findConcaveSeparatingAxisVertexFaceKernel)
+               clReleaseKernel(m_findConcaveSeparatingAxisVertexFaceKernel);
+
+       if (m_findConcaveSeparatingAxisEdgeEdgeKernel)
+               clReleaseKernel(m_findConcaveSeparatingAxisEdgeEdgeKernel);
+
+       if (m_findConcaveSeparatingAxisKernel)
+               clReleaseKernel(m_findConcaveSeparatingAxisKernel);
+
+       if (m_findCompoundPairsKernel)
+               clReleaseKernel(m_findCompoundPairsKernel);
+
+       if (m_processCompoundPairsKernel)
+               clReleaseKernel(m_processCompoundPairsKernel);
+
+       if (m_findClippingFacesKernel)
+               clReleaseKernel(m_findClippingFacesKernel);
+
+       if (m_clipFacesAndFindContacts)
+               clReleaseKernel(m_clipFacesAndFindContacts);
+       if (m_newContactReductionKernel)
+               clReleaseKernel(m_newContactReductionKernel);
+       if (m_primitiveContactsKernel)
+               clReleaseKernel(m_primitiveContactsKernel);
+
+       if (m_findConcaveSphereContactsKernel)
+               clReleaseKernel(m_findConcaveSphereContactsKernel);
+
+       if (m_processCompoundPairsPrimitivesKernel)
+               clReleaseKernel(m_processCompoundPairsPrimitivesKernel);
+
+       if (m_clipHullHullKernel)
+               clReleaseKernel(m_clipHullHullKernel);
+       if (m_clipCompoundsHullHullKernel)
+               clReleaseKernel(m_clipCompoundsHullHullKernel);
+
+       if (m_clipHullHullConcaveConvexKernel)
+               clReleaseKernel(m_clipHullHullConcaveConvexKernel);
+       //      if (m_extractManifoldAndAddContactKernel)
+       //      clReleaseKernel(m_extractManifoldAndAddContactKernel);
+
+       if (m_bvhTraversalKernel)
+               clReleaseKernel(m_bvhTraversalKernel);
+}
+
+struct MyTriangleCallback : public b3NodeOverlapCallback
+{
+       int m_bodyIndexA;
+       int m_bodyIndexB;
+
+       virtual void processNode(int subPart, int triangleIndex)
+       {
+               printf("bodyIndexA %d, bodyIndexB %d\n", m_bodyIndexA, m_bodyIndexB);
+               printf("triangleIndex %d\n", triangleIndex);
+       }
+};
+
+#define float4 b3Vector3
+#define make_float4(x, y, z, w) b3MakeVector3(x, y, z, w)
+
+float signedDistanceFromPointToPlane(const float4& point, const float4& planeEqn, float4* closestPointOnFace)
+{
+       float4 n = planeEqn;
+       n[3] = 0.f;
+       float dist = dot3F4(n, point) + planeEqn[3];
+       *closestPointOnFace = point - dist * n;
+       return dist;
+}
+
+#define cross3(a, b) (a.cross(b))
+b3Vector3 transform(const b3Vector3* v, const b3Vector3* pos, const b3Quaternion* orn)
+{
+       b3Transform tr;
+       tr.setIdentity();
+       tr.setOrigin(*pos);
+       tr.setRotation(*orn);
+       b3Vector3 res = tr(*v);
+       return res;
+}
+
+inline bool IsPointInPolygon(const float4& p,
+                                                        const b3GpuFace* face,
+                                                        const float4* baseVertex,
+                                                        const int* convexIndices,
+                                                        float4* out)
+{
+       float4 a;
+       float4 b;
+       float4 ab;
+       float4 ap;
+       float4 v;
+
+       float4 plane = b3MakeVector3(face->m_plane.x, face->m_plane.y, face->m_plane.z, 0.f);
+
+       if (face->m_numIndices < 2)
+               return false;
+
+       float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices - 1]];
+       b = v0;
+
+       for (unsigned i = 0; i != face->m_numIndices; ++i)
+       {
+               a = b;
+               float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];
+               b = vi;
+               ab = b - a;
+               ap = p - a;
+               v = cross3(ab, plane);
+
+               if (b3Dot(ap, v) > 0.f)
+               {
+                       float ab_m2 = b3Dot(ab, ab);
+                       float rt = ab_m2 != 0.f ? b3Dot(ab, ap) / ab_m2 : 0.f;
+                       if (rt <= 0.f)
+                       {
+                               *out = a;
+                       }
+                       else if (rt >= 1.f)
+                       {
+                               *out = b;
+                       }
+                       else
+                       {
+                               float s = 1.f - rt;
+                               out[0].x = s * a.x + rt * b.x;
+                               out[0].y = s * a.y + rt * b.y;
+                               out[0].z = s * a.z + rt * b.z;
+                       }
+                       return false;
+               }
+       }
+       return true;
+}
+
+#define normalize3(a) (a.normalize())
+
+int extractManifoldSequentialGlobal(const float4* p, int nPoints, const float4& nearNormal, b3Int4* contactIdx)
+{
+       if (nPoints == 0)
+               return 0;
+
+       if (nPoints <= 4)
+               return nPoints;
+
+       if (nPoints > 64)
+               nPoints = 64;
+
+       float4 center = b3MakeVector3(0, 0, 0, 0);
+       {
+               for (int i = 0; i < nPoints; i++)
+                       center += p[i];
+               center /= (float)nPoints;
+       }
+
+       //      sample 4 directions
+
+       float4 aVector = p[0] - center;
+       float4 u = cross3(nearNormal, aVector);
+       float4 v = cross3(nearNormal, u);
+       u = normalize3(u);
+       v = normalize3(v);
+
+       //keep point with deepest penetration
+       float minW = FLT_MAX;
+
+       int minIndex = -1;
+
+       float4 maxDots;
+       maxDots.x = FLT_MIN;
+       maxDots.y = FLT_MIN;
+       maxDots.z = FLT_MIN;
+       maxDots.w = FLT_MIN;
+
+       //      idx, distance
+       for (int ie = 0; ie < nPoints; ie++)
+       {
+               if (p[ie].w < minW)
+               {
+                       minW = p[ie].w;
+                       minIndex = ie;
+               }
+               float f;
+               float4 r = p[ie] - center;
+               f = dot3F4(u, r);
+               if (f < maxDots.x)
+               {
+                       maxDots.x = f;
+                       contactIdx[0].x = ie;
+               }
+
+               f = dot3F4(-u, r);
+               if (f < maxDots.y)
+               {
+                       maxDots.y = f;
+                       contactIdx[0].y = ie;
+               }
+
+               f = dot3F4(v, r);
+               if (f < maxDots.z)
+               {
+                       maxDots.z = f;
+                       contactIdx[0].z = ie;
+               }
+
+               f = dot3F4(-v, r);
+               if (f < maxDots.w)
+               {
+                       maxDots.w = f;
+                       contactIdx[0].w = ie;
+               }
+       }
+
+       if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+       {
+               //replace the first contact with minimum (todo: replace contact with least penetration)
+               contactIdx[0].x = minIndex;
+       }
+
+       return 4;
+}
+
+#define MAX_VERTS 1024
+
+inline void project(const b3ConvexPolyhedronData& hull, const float4& pos, const b3Quaternion& orn, const float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
+{
+       min = FLT_MAX;
+       max = -FLT_MAX;
+       int numVerts = hull.m_numVertices;
+
+       const float4 localDir = b3QuatRotate(orn.inverse(), dir);
+
+       b3Scalar offset = dot3F4(pos, dir);
+
+       for (int i = 0; i < numVerts; i++)
+       {
+               //b3Vector3 pt = trans * vertices[m_vertexOffset+i];
+               //b3Scalar dp = pt.dot(dir);
+               //b3Vector3 vertex = vertices[hull.m_vertexOffset+i];
+               b3Scalar dp = dot3F4((float4&)vertices[hull.m_vertexOffset + i], localDir);
+               //b3Assert(dp==dpL);
+               if (dp < min) min = dp;
+               if (dp > max) max = dp;
+       }
+       if (min > max)
+       {
+               b3Scalar tmp = min;
+               min = max;
+               max = tmp;
+       }
+       min += offset;
+       max += offset;
+}
+
+static bool TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+                                               const float4& posA, const b3Quaternion& ornA,
+                                               const float4& posB, const b3Quaternion& ornB,
+                                               const float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB, b3Scalar& depth)
+{
+       b3Scalar Min0, Max0;
+       b3Scalar Min1, Max1;
+       project(hullA, posA, ornA, sep_axis, verticesA, Min0, Max0);
+       project(hullB, posB, ornB, sep_axis, verticesB, Min1, Max1);
+
+       if (Max0 < Min1 || Max1 < Min0)
+               return false;
+
+       b3Scalar d0 = Max0 - Min1;
+       assert(d0 >= 0.0f);
+       b3Scalar d1 = Max1 - Min0;
+       assert(d1 >= 0.0f);
+       depth = d0 < d1 ? d0 : d1;
+       return true;
+}
+
+inline bool IsAlmostZero(const b3Vector3& v)
+{
+       if (fabsf(v.x) > 1e-6 || fabsf(v.y) > 1e-6 || fabsf(v.z) > 1e-6) return false;
+       return true;
+}
+
+static bool findSeparatingAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+                                                          const float4& posA1,
+                                                          const b3Quaternion& ornA,
+                                                          const float4& posB1,
+                                                          const b3Quaternion& ornB,
+                                                          const b3AlignedObjectArray<b3Vector3>& verticesA,
+                                                          const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+                                                          const b3AlignedObjectArray<b3GpuFace>& facesA,
+                                                          const b3AlignedObjectArray<int>& indicesA,
+                                                          const b3AlignedObjectArray<b3Vector3>& verticesB,
+                                                          const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+                                                          const b3AlignedObjectArray<b3GpuFace>& facesB,
+                                                          const b3AlignedObjectArray<int>& indicesB,
+
+                                                          b3Vector3& sep)
+{
+       B3_PROFILE("findSeparatingAxis");
+
+       b3g_actualSATPairTests++;
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+       //#ifdef TEST_INTERNAL_OBJECTS
+       float4 c0local = (float4&)hullA.m_localCenter;
+       float4 c0 = transform(&c0local, &posA, &ornA);
+       float4 c1local = (float4&)hullB.m_localCenter;
+       float4 c1 = transform(&c1local, &posB, &ornB);
+       const float4 deltaC2 = c0 - c1;
+       //#endif
+
+       b3Scalar dmin = FLT_MAX;
+       int curPlaneTests = 0;
+
+       int numFacesA = hullA.m_numFaces;
+       // Test normals from hullA
+       for (int i = 0; i < numFacesA; i++)
+       {
+               const float4& normal = (float4&)facesA[hullA.m_faceOffset + i].m_plane;
+               float4 faceANormalWS = b3QuatRotate(ornA, normal);
+
+               if (dot3F4(deltaC2, faceANormalWS) < 0)
+                       faceANormalWS *= -1.f;
+
+               curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+               gExpectedNbTests++;
+               if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
+                       continue;
+               gActualNbTests++;
+#endif
+
+               b3Scalar d;
+               if (!TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, faceANormalWS, verticesA, verticesB, d))
+                       return false;
+
+               if (d < dmin)
+               {
+                       dmin = d;
+                       sep = (b3Vector3&)faceANormalWS;
+               }
+       }
+
+       int numFacesB = hullB.m_numFaces;
+       // Test normals from hullB
+       for (int i = 0; i < numFacesB; i++)
+       {
+               float4 normal = (float4&)facesB[hullB.m_faceOffset + i].m_plane;
+               float4 WorldNormal = b3QuatRotate(ornB, normal);
+
+               if (dot3F4(deltaC2, WorldNormal) < 0)
+               {
+                       WorldNormal *= -1.f;
+               }
+               curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+               gExpectedNbTests++;
+               if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
+                       continue;
+               gActualNbTests++;
+#endif
+
+               b3Scalar d;
+               if (!TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, WorldNormal, verticesA, verticesB, d))
+                       return false;
+
+               if (d < dmin)
+               {
+                       dmin = d;
+                       sep = (b3Vector3&)WorldNormal;
+               }
+       }
+
+       int curEdgeEdge = 0;
+       // Test edges
+       for (int e0 = 0; e0 < hullA.m_numUniqueEdges; e0++)
+       {
+               const float4& edge0 = (float4&)uniqueEdgesA[hullA.m_uniqueEdgesOffset + e0];
+               float4 edge0World = b3QuatRotate(ornA, (float4&)edge0);
+
+               for (int e1 = 0; e1 < hullB.m_numUniqueEdges; e1++)
+               {
+                       const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset + e1];
+                       float4 edge1World = b3QuatRotate(ornB, (float4&)edge1);
+
+                       float4 crossje = cross3(edge0World, edge1World);
+
+                       curEdgeEdge++;
+                       if (!IsAlmostZero((b3Vector3&)crossje))
+                       {
+                               crossje = normalize3(crossje);
+                               if (dot3F4(deltaC2, crossje) < 0)
+                                       crossje *= -1.f;
+
+#ifdef TEST_INTERNAL_OBJECTS
+                               gExpectedNbTests++;
+                               if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
+                                       continue;
+                               gActualNbTests++;
+#endif
+
+                               b3Scalar dist;
+                               if (!TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, crossje, verticesA, verticesB, dist))
+                                       return false;
+
+                               if (dist < dmin)
+                               {
+                                       dmin = dist;
+                                       sep = (b3Vector3&)crossje;
+                               }
+                       }
+               }
+       }
+
+       if ((dot3F4(-deltaC2, (float4&)sep)) > 0.0f)
+               sep = -sep;
+
+       return true;
+}
+
+bool findSeparatingAxisEdgeEdge(__global const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
+                                                               const b3Float4& posA1,
+                                                               const b3Quat& ornA,
+                                                               const b3Float4& posB1,
+                                                               const b3Quat& ornB,
+                                                               const b3Float4& DeltaC2,
+                                                               __global const b3AlignedObjectArray<float4>& vertices,
+                                                               __global const b3AlignedObjectArray<float4>& uniqueEdges,
+                                                               __global const b3AlignedObjectArray<b3GpuFace>& faces,
+                                                               __global const b3AlignedObjectArray<int>& indices,
+                                                               float4* sep,
+                                                               float* dmin)
+{
+       //      int i = get_global_id(0);
+
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+
+       //int curPlaneTests=0;
+
+       int curEdgeEdge = 0;
+       // Test edges
+       for (int e0 = 0; e0 < hullA->m_numUniqueEdges; e0++)
+       {
+               const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset + e0];
+               float4 edge0World = b3QuatRotate(ornA, edge0);
+
+               for (int e1 = 0; e1 < hullB->m_numUniqueEdges; e1++)
+               {
+                       const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset + e1];
+                       float4 edge1World = b3QuatRotate(ornB, edge1);
+
+                       float4 crossje = cross3(edge0World, edge1World);
+
+                       curEdgeEdge++;
+                       if (!IsAlmostZero(crossje))
+                       {
+                               crossje = normalize3(crossje);
+                               if (dot3F4(DeltaC2, crossje) < 0)
+                                       crossje *= -1.f;
+
+                               float dist;
+                               bool result = true;
+                               {
+                                       float Min0, Max0;
+                                       float Min1, Max1;
+                                       project(*hullA, posA, ornA, crossje, vertices, Min0, Max0);
+                                       project(*hullB, posB, ornB, crossje, vertices, Min1, Max1);
+
+                                       if (Max0 < Min1 || Max1 < Min0)
+                                               result = false;
+
+                                       float d0 = Max0 - Min1;
+                                       float d1 = Max1 - Min0;
+                                       dist = d0 < d1 ? d0 : d1;
+                                       result = true;
+                               }
+
+                               if (dist < *dmin)
+                               {
+                                       *dmin = dist;
+                                       *sep = crossje;
+                               }
+                       }
+               }
+       }
+
+       if ((dot3F4(-DeltaC2, *sep)) > 0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+__inline float4 lerp3(const float4& a, const float4& b, float t)
+{
+       return b3MakeVector3(a.x + (b.x - a.x) * t,
+                                                a.y + (b.y - a.y) * t,
+                                                a.z + (b.z - a.z) * t,
+                                                0.f);
+}
+
+// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
+int clipFace(const float4* pVtxIn, int numVertsIn, float4& planeNormalWS, float planeEqWS, float4* ppVtxOut)
+{
+       int ve;
+       float ds, de;
+       int numVertsOut = 0;
+       if (numVertsIn < 2)
+               return 0;
+
+       float4 firstVertex = pVtxIn[numVertsIn - 1];
+       float4 endVertex = pVtxIn[0];
+
+       ds = dot3F4(planeNormalWS, firstVertex) + planeEqWS;
+
+       for (ve = 0; ve < numVertsIn; ve++)
+       {
+               endVertex = pVtxIn[ve];
+
+               de = dot3F4(planeNormalWS, endVertex) + planeEqWS;
+
+               if (ds < 0)
+               {
+                       if (de < 0)
+                       {
+                               // Start < 0, end < 0, so output endVertex
+                               ppVtxOut[numVertsOut++] = endVertex;
+                       }
+                       else
+                       {
+                               // Start < 0, end >= 0, so output intersection
+                               ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
+                       }
+               }
+               else
+               {
+                       if (de < 0)
+                       {
+                               // Start >= 0, end < 0 so output intersection and end
+                               ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
+                               ppVtxOut[numVertsOut++] = endVertex;
+                       }
+               }
+               firstVertex = endVertex;
+               ds = de;
+       }
+       return numVertsOut;
+}
+
+int clipFaceAgainstHull(const float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
+                                               const float4& posA, const b3Quaternion& ornA, float4* worldVertsB1, int numWorldVertsB1,
+                                               float4* worldVertsB2, int capacityWorldVertsB2,
+                                               const float minDist, float maxDist,
+                                               const b3AlignedObjectArray<float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+                                               //const float4* verticesB,      const b3GpuFace* facesB,        const int* indicesB,
+                                               float4* contactsOut,
+                                               int contactCapacity)
+{
+       int numContactsOut = 0;
+
+       float4* pVtxIn = worldVertsB1;
+       float4* pVtxOut = worldVertsB2;
+
+       int numVertsIn = numWorldVertsB1;
+       int numVertsOut = 0;
+
+       int closestFaceA = -1;
+       {
+               float dmin = FLT_MAX;
+               for (int face = 0; face < hullA->m_numFaces; face++)
+               {
+                       const float4 Normal = b3MakeVector3(
+                               facesA[hullA->m_faceOffset + face].m_plane.x,
+                               facesA[hullA->m_faceOffset + face].m_plane.y,
+                               facesA[hullA->m_faceOffset + face].m_plane.z, 0.f);
+                       const float4 faceANormalWS = b3QuatRotate(ornA, Normal);
+
+                       float d = dot3F4(faceANormalWS, separatingNormal);
+                       if (d < dmin)
+                       {
+                               dmin = d;
+                               closestFaceA = face;
+                       }
+               }
+       }
+       if (closestFaceA < 0)
+               return numContactsOut;
+
+       b3GpuFace polyA = facesA[hullA->m_faceOffset + closestFaceA];
+
+       // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+       //      int numContacts = numWorldVertsB1;
+       int numVerticesA = polyA.m_numIndices;
+       for (int e0 = 0; e0 < numVerticesA; e0++)
+       {
+               const float4 a = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + e0]];
+               const float4 b = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + ((e0 + 1) % numVerticesA)]];
+               const float4 edge0 = a - b;
+               const float4 WorldEdge0 = b3QuatRotate(ornA, edge0);
+               float4 planeNormalA = make_float4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
+               float4 worldPlaneAnormal1 = b3QuatRotate(ornA, planeNormalA);
+
+               float4 planeNormalWS1 = -cross3(WorldEdge0, worldPlaneAnormal1);
+               float4 worldA1 = transform(&a, &posA, &ornA);
+               float planeEqWS1 = -dot3F4(worldA1, planeNormalWS1);
+
+               float4 planeNormalWS = planeNormalWS1;
+               float planeEqWS = planeEqWS1;
+
+               //clip face
+               //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
+               numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS, planeEqWS, pVtxOut);
+
+               //btSwap(pVtxIn,pVtxOut);
+               float4* tmp = pVtxOut;
+               pVtxOut = pVtxIn;
+               pVtxIn = tmp;
+               numVertsIn = numVertsOut;
+               numVertsOut = 0;
+       }
+
+       // only keep points that are behind the witness face
+       {
+               float4 localPlaneNormal = make_float4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
+               float localPlaneEq = polyA.m_plane.w;
+               float4 planeNormalWS = b3QuatRotate(ornA, localPlaneNormal);
+               float planeEqWS = localPlaneEq - dot3F4(planeNormalWS, posA);
+               for (int i = 0; i < numVertsIn; i++)
+               {
+                       float depth = dot3F4(planeNormalWS, pVtxIn[i]) + planeEqWS;
+                       if (depth <= minDist)
+                       {
+                               depth = minDist;
+                       }
+                       if (numContactsOut < contactCapacity)
+                       {
+                               if (depth <= maxDist)
+                               {
+                                       float4 pointInWorld = pVtxIn[i];
+                                       //resultOut.addContactPoint(separatingNormal,point,depth);
+                                       contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x, pointInWorld.y, pointInWorld.z, depth);
+                                       //printf("depth=%f\n",depth);
+                               }
+                       }
+                       else
+                       {
+                               b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut, contactCapacity);
+                       }
+               }
+       }
+
+       return numContactsOut;
+}
+
+static int clipHullAgainstHull(const float4& separatingNormal,
+                                                          const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
+                                                          const float4& posA, const b3Quaternion& ornA, const float4& posB, const b3Quaternion& ornB,
+                                                          float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
+                                                          const float minDist, float maxDist,
+                                                          const b3AlignedObjectArray<float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
+                                                          const b3AlignedObjectArray<float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
+
+                                                          float4* contactsOut,
+                                                          int contactCapacity)
+{
+       int numContactsOut = 0;
+       int numWorldVertsB1 = 0;
+
+       B3_PROFILE("clipHullAgainstHull");
+
+       //      float curMaxDist=maxDist;
+       int closestFaceB = -1;
+       float dmax = -FLT_MAX;
+
+       {
+               //B3_PROFILE("closestFaceB");
+               if (hullB.m_numFaces != 1)
+               {
+                       //printf("wtf\n");
+               }
+               static bool once = true;
+               //printf("separatingNormal=%f,%f,%f\n",separatingNormal.x,separatingNormal.y,separatingNormal.z);
+
+               for (int face = 0; face < hullB.m_numFaces; face++)
+               {
+#ifdef BT_DEBUG_SAT_FACE
+                       if (once)
+                               printf("face %d\n", face);
+                       const b3GpuFace* faceB = &facesB[hullB.m_faceOffset + face];
+                       if (once)
+                       {
+                               for (int i = 0; i < faceB->m_numIndices; i++)
+                               {
+                                       float4 vert = verticesB[hullB.m_vertexOffset + indicesB[faceB->m_indexOffset + i]];
+                                       printf("vert[%d] = %f,%f,%f\n", i, vert.x, vert.y, vert.z);
+                               }
+                       }
+#endif  //BT_DEBUG_SAT_FACE \
+       //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
+                       {
+                               const float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset + face].m_plane.x,
+                                                                                                       facesB[hullB.m_faceOffset + face].m_plane.y, facesB[hullB.m_faceOffset + face].m_plane.z, 0.f);
+                               const float4 WorldNormal = b3QuatRotate(ornB, Normal);
+#ifdef BT_DEBUG_SAT_FACE
+                               if (once)
+                                       printf("faceNormal = %f,%f,%f\n", Normal.x, Normal.y, Normal.z);
+#endif
+                               float d = dot3F4(WorldNormal, separatingNormal);
+                               if (d > dmax)
+                               {
+                                       dmax = d;
+                                       closestFaceB = face;
+                               }
+                       }
+               }
+               once = false;
+       }
+
+       b3Assert(closestFaceB >= 0);
+       {
+               //B3_PROFILE("worldVertsB1");
+               const b3GpuFace& polyB = facesB[hullB.m_faceOffset + closestFaceB];
+               const int numVertices = polyB.m_numIndices;
+               for (int e0 = 0; e0 < numVertices; e0++)
+               {
+                       const float4& b = verticesB[hullB.m_vertexOffset + indicesB[polyB.m_indexOffset + e0]];
+                       worldVertsB1[numWorldVertsB1++] = transform(&b, &posB, &ornB);
+               }
+       }
+
+       if (closestFaceB >= 0)
+       {
+               //B3_PROFILE("clipFaceAgainstHull");
+               numContactsOut = clipFaceAgainstHull((float4&)separatingNormal, &hullA,
+                                                                                        posA, ornA,
+                                                                                        worldVertsB1, numWorldVertsB1, worldVertsB2, capacityWorldVerts, minDist, maxDist,
+                                                                                        verticesA, facesA, indicesA,
+                                                                                        contactsOut, contactCapacity);
+       }
+
+       return numContactsOut;
+}
+
+#define PARALLEL_SUM(v, n) \
+       for (int j = 1; j < n; j++) v[0] += v[j];
+#define PARALLEL_DO(execution, n)  \
+       for (int ie = 0; ie < n; ie++) \
+       {                              \
+               execution;                 \
+       }
+#define REDUCE_MAX(v, n)                                                                                     \
+       {                                                                                                        \
+               int i = 0;                                                                                           \
+               for (int offset = 0; offset < n; offset++) v[i] = (v[i].y > v[i + offset].y) ? v[i] : v[i + offset]; \
+       }
+#define REDUCE_MIN(v, n)                                                                                     \
+       {                                                                                                        \
+               int i = 0;                                                                                           \
+               for (int offset = 0; offset < n; offset++) v[i] = (v[i].y < v[i + offset].y) ? v[i] : v[i + offset]; \
+       }
+
+int extractManifold(const float4* p, int nPoints, const float4& nearNormal, b3Int4* contactIdx)
+{
+       if (nPoints == 0)
+               return 0;
+
+       if (nPoints <= 4)
+               return nPoints;
+
+       if (nPoints > 64)
+               nPoints = 64;
+
+       float4 center = make_float4(0, 0, 0, 0);
+       {
+               for (int i = 0; i < nPoints; i++)
+                       center += p[i];
+               center /= (float)nPoints;
+       }
+
+       //      sample 4 directions
+
+       float4 aVector = p[0] - center;
+       float4 u = cross3(nearNormal, aVector);
+       float4 v = cross3(nearNormal, u);
+       u = normalize3(u);
+       v = normalize3(v);
+
+       //keep point with deepest penetration
+       float minW = FLT_MAX;
+
+       int minIndex = -1;
+
+       float4 maxDots;
+       maxDots.x = FLT_MIN;
+       maxDots.y = FLT_MIN;
+       maxDots.z = FLT_MIN;
+       maxDots.w = FLT_MIN;
+
+       //      idx, distance
+       for (int ie = 0; ie < nPoints; ie++)
+       {
+               if (p[ie].w < minW)
+               {
+                       minW = p[ie].w;
+                       minIndex = ie;
+               }
+               float f;
+               float4 r = p[ie] - center;
+               f = dot3F4(u, r);
+               if (f < maxDots.x)
+               {
+                       maxDots.x = f;
+                       contactIdx[0].x = ie;
+               }
+
+               f = dot3F4(-u, r);
+               if (f < maxDots.y)
+               {
+                       maxDots.y = f;
+                       contactIdx[0].y = ie;
+               }
+
+               f = dot3F4(v, r);
+               if (f < maxDots.z)
+               {
+                       maxDots.z = f;
+                       contactIdx[0].z = ie;
+               }
+
+               f = dot3F4(-v, r);
+               if (f < maxDots.w)
+               {
+                       maxDots.w = f;
+                       contactIdx[0].w = ie;
+               }
+       }
+
+       if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+       {
+               //replace the first contact with minimum (todo: replace contact with least penetration)
+               contactIdx[0].x = minIndex;
+       }
+
+       return 4;
+}
+
+int clipHullHullSingle(
+       int bodyIndexA, int bodyIndexB,
+       const float4& posA,
+       const b3Quaternion& ornA,
+       const float4& posB,
+       const b3Quaternion& ornB,
+
+       int collidableIndexA, int collidableIndexB,
+
+       const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
+       b3AlignedObjectArray<b3Contact4>* globalContactOut,
+       int& nContacts,
+
+       const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
+       const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
+
+       const b3AlignedObjectArray<b3Vector3>& verticesA,
+       const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
+       const b3AlignedObjectArray<b3GpuFace>& facesA,
+       const b3AlignedObjectArray<int>& indicesA,
+
+       const b3AlignedObjectArray<b3Vector3>& verticesB,
+       const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
+       const b3AlignedObjectArray<b3GpuFace>& facesB,
+       const b3AlignedObjectArray<int>& indicesB,
+
+       const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
+       const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
+       const b3Vector3& sepNormalWorldSpace,
+       int maxContactCapacity)
+{
+       int contactIndex = -1;
+       b3ConvexPolyhedronData hullA, hullB;
+
+       b3Collidable colA = hostCollidablesA[collidableIndexA];
+       hullA = hostConvexDataA[colA.m_shapeIndex];
+       //printf("numvertsA = %d\n",hullA.m_numVertices);
+
+       b3Collidable colB = hostCollidablesB[collidableIndexB];
+       hullB = hostConvexDataB[colB.m_shapeIndex];
+       //printf("numvertsB = %d\n",hullB.m_numVertices);
+
+       float4 contactsOut[MAX_VERTS];
+       int localContactCapacity = MAX_VERTS;
+
+#ifdef _WIN32
+       b3Assert(_finite(bodyBuf->at(bodyIndexA).m_pos.x));
+       b3Assert(_finite(bodyBuf->at(bodyIndexB).m_pos.x));
+#endif
+
+       {
+               float4 worldVertsB1[MAX_VERTS];
+               float4 worldVertsB2[MAX_VERTS];
+               int capacityWorldVerts = MAX_VERTS;
+
+               float4 hostNormal = make_float4(sepNormalWorldSpace.x, sepNormalWorldSpace.y, sepNormalWorldSpace.z, 0.f);
+               int shapeA = hostCollidablesA[collidableIndexA].m_shapeIndex;
+               int shapeB = hostCollidablesB[collidableIndexB].m_shapeIndex;
+
+               b3Scalar minDist = -1;
+               b3Scalar maxDist = 0.;
+
+               b3Transform trA, trB;
+               {
+                       //B3_PROFILE("transform computation");
+                       //trA.setIdentity();
+                       trA.setOrigin(b3MakeVector3(posA.x, posA.y, posA.z));
+                       trA.setRotation(b3Quaternion(ornA.x, ornA.y, ornA.z, ornA.w));
+
+                       //trB.setIdentity();
+                       trB.setOrigin(b3MakeVector3(posB.x, posB.y, posB.z));
+                       trB.setRotation(b3Quaternion(ornB.x, ornB.y, ornB.z, ornB.w));
+               }
+
+               b3Quaternion trAorn = trA.getRotation();
+               b3Quaternion trBorn = trB.getRotation();
+
+               int numContactsOut = clipHullAgainstHull(hostNormal,
+                                                                                                hostConvexDataA.at(shapeA),
+                                                                                                hostConvexDataB.at(shapeB),
+                                                                                                (float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
+                                                                                                (float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
+                                                                                                worldVertsB1, worldVertsB2, capacityWorldVerts,
+                                                                                                minDist, maxDist,
+                                                                                                verticesA, facesA, indicesA,
+                                                                                                verticesB, facesB, indicesB,
+
+                                                                                                contactsOut, localContactCapacity);
+
+               if (numContactsOut > 0)
+               {
+                       B3_PROFILE("overlap");
+
+                       float4 normalOnSurfaceB = (float4&)hostNormal;
+
+                       b3Int4 contactIdx;
+                       contactIdx.x = 0;
+                       contactIdx.y = 1;
+                       contactIdx.z = 2;
+                       contactIdx.w = 3;
+
+                       int numPoints = 0;
+
+                       {
+                               //      B3_PROFILE("extractManifold");
+                               numPoints = extractManifold(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
+                       }
+
+                       b3Assert(numPoints);
+
+                       if (nContacts < maxContactCapacity)
+                       {
+                               contactIndex = nContacts;
+                               globalContactOut->expand();
+                               b3Contact4& contact = globalContactOut->at(nContacts);
+                               contact.m_batchIdx = 0;  //i;
+                               contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass == 0) ? -bodyIndexA : bodyIndexA;
+                               contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass == 0) ? -bodyIndexB : bodyIndexB;
+
+                               contact.m_frictionCoeffCmp = 45874;
+                               contact.m_restituitionCoeffCmp = 0;
+
+                               //                      float distance = 0.f;
+                               for (int p = 0; p < numPoints; p++)
+                               {
+                                       contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]];  //check if it is actually on B
+                                       contact.m_worldNormalOnB = normalOnSurfaceB;
+                               }
+                               //printf("bodyIndexA %d,bodyIndexB %d,normal=%f,%f,%f numPoints %d\n",bodyIndexA,bodyIndexB,normalOnSurfaceB.x,normalOnSurfaceB.y,normalOnSurfaceB.z,numPoints);
+                               contact.m_worldNormalOnB.w = (b3Scalar)numPoints;
+                               nContacts++;
+                       }
+                       else
+                       {
+                               b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts, maxContactCapacity);
+                       }
+               }
+       }
+       return contactIndex;
+}
+
+void computeContactPlaneConvex(int pairIndex,
+                                                          int bodyIndexA, int bodyIndexB,
+                                                          int collidableIndexA, int collidableIndexB,
+                                                          const b3RigidBodyData* rigidBodies,
+                                                          const b3Collidable* collidables,
+                                                          const b3ConvexPolyhedronData* convexShapes,
+                                                          const b3Vector3* convexVertices,
+                                                          const int* convexIndices,
+                                                          const b3GpuFace* faces,
+                                                          b3Contact4* globalContactsOut,
+                                                          int& nGlobalContactsOut,
+                                                          int maxContactCapacity)
+{
+       int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
+       const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndex];
+
+       b3Vector3 posB = rigidBodies[bodyIndexB].m_pos;
+       b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
+       b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
+       b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
+
+       //      int numContactsOut = 0;
+       //      int numWorldVertsB1= 0;
+
+       b3Vector3 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
+       b3Vector3 planeNormal = b3MakeVector3(planeEq.x, planeEq.y, planeEq.z);
+       b3Vector3 planeNormalWorld = b3QuatRotate(ornA, planeNormal);
+       float planeConstant = planeEq.w;
+       b3Transform convexWorldTransform;
+       convexWorldTransform.setIdentity();
+       convexWorldTransform.setOrigin(posB);
+       convexWorldTransform.setRotation(ornB);
+       b3Transform planeTransform;
+       planeTransform.setIdentity();
+       planeTransform.setOrigin(posA);
+       planeTransform.setRotation(ornA);
+
+       b3Transform planeInConvex;
+       planeInConvex = convexWorldTransform.inverse() * planeTransform;
+       b3Transform convexInPlane;
+       convexInPlane = planeTransform.inverse() * convexWorldTransform;
+
+       b3Vector3 planeNormalInConvex = planeInConvex.getBasis() * -planeNormal;
+       float maxDot = -1e30;
+       int hitVertex = -1;
+       b3Vector3 hitVtx;
+
+#define MAX_PLANE_CONVEX_POINTS 64
+
+       b3Vector3 contactPoints[MAX_PLANE_CONVEX_POINTS];
+       int numPoints = 0;
+
+       b3Int4 contactIdx;
+       contactIdx.s[0] = 0;
+       contactIdx.s[1] = 1;
+       contactIdx.s[2] = 2;
+       contactIdx.s[3] = 3;
+
+       for (int i = 0; i < hullB->m_numVertices; i++)
+       {
+               b3Vector3 vtx = convexVertices[hullB->m_vertexOffset + i];
+               float curDot = vtx.dot(planeNormalInConvex);
+
+               if (curDot > maxDot)
+               {
+                       hitVertex = i;
+                       maxDot = curDot;
+                       hitVtx = vtx;
+                       //make sure the deepest points is always included
+                       if (numPoints == MAX_PLANE_CONVEX_POINTS)
+                               numPoints--;
+               }
+
+               if (numPoints < MAX_PLANE_CONVEX_POINTS)
+               {
+                       b3Vector3 vtxWorld = convexWorldTransform * vtx;
+                       b3Vector3 vtxInPlane = planeTransform.inverse() * vtxWorld;
+                       float dist = planeNormal.dot(vtxInPlane) - planeConstant;
+                       if (dist < 0.f)
+                       {
+                               vtxWorld.w = dist;
+                               contactPoints[numPoints] = vtxWorld;
+                               numPoints++;
+                       }
+               }
+       }
+
+       int numReducedPoints = 0;
+
+       numReducedPoints = numPoints;
+
+       if (numPoints > 4)
+       {
+               numReducedPoints = extractManifoldSequentialGlobal(contactPoints, numPoints, planeNormalInConvex, &contactIdx);
+       }
+       int dstIdx;
+       //    dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+       if (numReducedPoints > 0)
+       {
+               if (nGlobalContactsOut < maxContactCapacity)
+               {
+                       dstIdx = nGlobalContactsOut;
+                       nGlobalContactsOut++;
+
+                       b3Contact4* c = &globalContactsOut[dstIdx];
+                       c->m_worldNormalOnB = -planeNormalWorld;
+                       c->setFrictionCoeff(0.7);
+                       c->setRestituitionCoeff(0.f);
+
+                       c->m_batchIdx = pairIndex;
+                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
+                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
+                       for (int i = 0; i < numReducedPoints; i++)
+                       {
+                               b3Vector3 pOnB1 = contactPoints[contactIdx.s[i]];
+                               c->m_worldPosB[i] = pOnB1;
+                       }
+                       c->m_worldNormalOnB.w = (b3Scalar)numReducedPoints;
+               }  //if (dstIdx < numPairs)
+       }
+
+       //      printf("computeContactPlaneConvex\n");
+}
+
+B3_FORCE_INLINE b3Vector3 MyUnQuantize(const unsigned short* vecIn, const b3Vector3& quantization, const b3Vector3& bvhAabbMin)
+{
+       b3Vector3 vecOut;
+       vecOut.setValue(
+               (b3Scalar)(vecIn[0]) / (quantization.x),
+               (b3Scalar)(vecIn[1]) / (quantization.y),
+               (b3Scalar)(vecIn[2]) / (quantization.z));
+       vecOut += bvhAabbMin;
+       return vecOut;
+}
+
+void traverseTreeTree()
+{
+}
+
+#include "Bullet3Common/shared/b3Mat3x3.h"
+
+int numAabbChecks = 0;
+int maxNumAabbChecks = 0;
+int maxDepth = 0;
+
+// work-in-progress
+__kernel void findCompoundPairsKernel(
+       int pairIndex,
+       int bodyIndexA,
+       int bodyIndexB,
+       int collidableIndexA,
+       int collidableIndexB,
+       __global const b3RigidBodyData* rigidBodies,
+       __global const b3Collidable* collidables,
+       __global const b3ConvexPolyhedronData* convexShapes,
+       __global const b3AlignedObjectArray<b3Float4>& vertices,
+       __global const b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace,
+       __global const b3AlignedObjectArray<b3Aabb>& aabbsLocalSpace,
+       __global const b3GpuChildShape* gpuChildShapes,
+       __global b3Int4* gpuCompoundPairsOut,
+       __global int* numCompoundPairsOut,
+       int maxNumCompoundPairsCapacity,
+       b3AlignedObjectArray<b3QuantizedBvhNode>& treeNodesCPU,
+       b3AlignedObjectArray<b3BvhSubtreeInfo>& subTreesCPU,
+       b3AlignedObjectArray<b3BvhInfo>& bvhInfoCPU)
+{
+       numAabbChecks = 0;
+       maxNumAabbChecks = 0;
+       //      int i = pairIndex;
+       {
+               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+               //once the broadphase avoids static-static pairs, we can remove this test
+               if ((rigidBodies[bodyIndexA].m_invMass == 0) && (rigidBodies[bodyIndexB].m_invMass == 0))
+               {
+                       return;
+               }
+
+               if ((collidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS) && (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS))
+               {
+                       int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;
+                       int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;
+                       int numSubTreesA = bvhInfoCPU[bvhA].m_numSubTrees;
+                       int subTreesOffsetA = bvhInfoCPU[bvhA].m_subTreeOffset;
+                       int subTreesOffsetB = bvhInfoCPU[bvhB].m_subTreeOffset;
+
+                       int numSubTreesB = bvhInfoCPU[bvhB].m_numSubTrees;
+
+                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+                       b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+
+                       b3Transform transA;
+                       transA.setIdentity();
+                       transA.setOrigin(posA);
+                       transA.setRotation(ornA);
+
+                       b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+                       b3Transform transB;
+                       transB.setIdentity();
+                       transB.setOrigin(posB);
+                       transB.setRotation(ornB);
+
+                       for (int p = 0; p < numSubTreesA; p++)
+                       {
+                               b3BvhSubtreeInfo subtreeA = subTreesCPU[subTreesOffsetA + p];
+                               //bvhInfoCPU[bvhA].m_quantization
+                               b3Vector3 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
+                               b3Vector3 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
+
+                               b3Vector3 aabbAMinOut, aabbAMaxOut;
+                               float margin = 0.f;
+                               b3TransformAabb2(treeAminLocal, treeAmaxLocal, margin, transA.getOrigin(), transA.getRotation(), &aabbAMinOut, &aabbAMaxOut);
+
+                               for (int q = 0; q < numSubTreesB; q++)
+                               {
+                                       b3BvhSubtreeInfo subtreeB = subTreesCPU[subTreesOffsetB + q];
+
+                                       b3Vector3 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
+                                       b3Vector3 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
+
+                                       b3Vector3 aabbBMinOut, aabbBMaxOut;
+                                       float margin = 0.f;
+                                       b3TransformAabb2(treeBminLocal, treeBmaxLocal, margin, transB.getOrigin(), transB.getRotation(), &aabbBMinOut, &aabbBMaxOut);
+
+                                       numAabbChecks = 0;
+                                       bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut, aabbAMaxOut, aabbBMinOut, aabbBMaxOut);
+                                       if (aabbOverlap)
+                                       {
+                                               int startNodeIndexA = subtreeA.m_rootNodeIndex + bvhInfoCPU[bvhA].m_nodeOffset;
+                                               //                              int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;
+
+                                               int startNodeIndexB = subtreeB.m_rootNodeIndex + bvhInfoCPU[bvhB].m_nodeOffset;
+                                               //                              int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;
+
+                                               b3AlignedObjectArray<b3Int2> nodeStack;
+                                               b3Int2 node0;
+                                               node0.x = startNodeIndexA;
+                                               node0.y = startNodeIndexB;
+
+                                               int maxStackDepth = 1024;
+                                               nodeStack.resize(maxStackDepth);
+                                               int depth = 0;
+                                               nodeStack[depth++] = node0;
+
+                                               do
+                                               {
+                                                       if (depth > maxDepth)
+                                                       {
+                                                               maxDepth = depth;
+                                                               printf("maxDepth=%d\n", maxDepth);
+                                                       }
+                                                       b3Int2 node = nodeStack[--depth];
+
+                                                       b3Vector3 aMinLocal = MyUnQuantize(treeNodesCPU[node.x].m_quantizedAabbMin, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
+                                                       b3Vector3 aMaxLocal = MyUnQuantize(treeNodesCPU[node.x].m_quantizedAabbMax, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
+
+                                                       b3Vector3 bMinLocal = MyUnQuantize(treeNodesCPU[node.y].m_quantizedAabbMin, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
+                                                       b3Vector3 bMaxLocal = MyUnQuantize(treeNodesCPU[node.y].m_quantizedAabbMax, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
+
+                                                       float margin = 0.f;
+                                                       b3Vector3 aabbAMinOut, aabbAMaxOut;
+                                                       b3TransformAabb2(aMinLocal, aMaxLocal, margin, transA.getOrigin(), transA.getRotation(), &aabbAMinOut, &aabbAMaxOut);
+
+                                                       b3Vector3 aabbBMinOut, aabbBMaxOut;
+                                                       b3TransformAabb2(bMinLocal, bMaxLocal, margin, transB.getOrigin(), transB.getRotation(), &aabbBMinOut, &aabbBMaxOut);
+
+                                                       numAabbChecks++;
+                                                       bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut, aabbAMaxOut, aabbBMinOut, aabbBMaxOut);
+                                                       if (nodeOverlap)
+                                                       {
+                                                               bool isLeafA = treeNodesCPU[node.x].isLeafNode();
+                                                               bool isLeafB = treeNodesCPU[node.y].isLeafNode();
+                                                               bool isInternalA = !isLeafA;
+                                                               bool isInternalB = !isLeafB;
+
+                                                               //fail, even though it might hit two leaf nodes
+                                                               if (depth + 4 > maxStackDepth && !(isLeafA && isLeafB))
+                                                               {
+                                                                       b3Error("Error: traversal exceeded maxStackDepth\n");
+                                                                       continue;
+                                                               }
+
+                                                               if (isInternalA)
+                                                               {
+                                                                       int nodeAleftChild = node.x + 1;
+                                                                       bool isNodeALeftChildLeaf = treeNodesCPU[node.x + 1].isLeafNode();
+                                                                       int nodeArightChild = isNodeALeftChildLeaf ? node.x + 2 : node.x + 1 + treeNodesCPU[node.x + 1].getEscapeIndex();
+
+                                                                       if (isInternalB)
+                                                                       {
+                                                                               int nodeBleftChild = node.y + 1;
+                                                                               bool isNodeBLeftChildLeaf = treeNodesCPU[node.y + 1].isLeafNode();
+                                                                               int nodeBrightChild = isNodeBLeftChildLeaf ? node.y + 2 : node.y + 1 + treeNodesCPU[node.y + 1].getEscapeIndex();
+
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeAleftChild, node.y);
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeArightChild, node.y);
+                                                                       }
+                                                               }
+                                                               else
+                                                               {
+                                                                       if (isInternalB)
+                                                                       {
+                                                                               int nodeBleftChild = node.y + 1;
+                                                                               bool isNodeBLeftChildLeaf = treeNodesCPU[node.y + 1].isLeafNode();
+                                                                               int nodeBrightChild = isNodeBLeftChildLeaf ? node.y + 2 : node.y + 1 + treeNodesCPU[node.y + 1].getEscapeIndex();
+                                                                               nodeStack[depth++] = b3MakeInt2(node.x, nodeBleftChild);
+                                                                               nodeStack[depth++] = b3MakeInt2(node.x, nodeBrightChild);
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
+                                                                               if (compoundPairIdx < maxNumCompoundPairsCapacity)
+                                                                               {
+                                                                                       int childShapeIndexA = treeNodesCPU[node.x].getTriangleIndex();
+                                                                                       int childShapeIndexB = treeNodesCPU[node.y].getTriangleIndex();
+                                                                                       gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, childShapeIndexA, childShapeIndexB);
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               } while (depth);
+                                               maxNumAabbChecks = b3Max(numAabbChecks, maxNumAabbChecks);
+                                       }
+                               }
+                       }
+
+                       return;
+               }
+
+               if ((collidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS) || (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS))
+               {
+                       if (collidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                       {
+                               int numChildrenA = collidables[collidableIndexA].m_numChildShapes;
+                               for (int c = 0; c < numChildrenA; c++)
+                               {
+                                       int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex + c;
+                                       int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+
+                                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+                                       b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+                                       float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+                                       b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+                                       float4 newPosA = b3QuatRotate(ornA, childPosA) + posA;
+                                       b3Quat newOrnA = b3QuatMul(ornA, childOrnA);
+
+                                       b3Aabb aabbA = aabbsLocalSpace[childColIndexA];
+
+                                       b3Transform transA;
+                                       transA.setIdentity();
+                                       transA.setOrigin(newPosA);
+                                       transA.setRotation(newOrnA);
+                                       b3Scalar margin = 0.0f;
+
+                                       b3Vector3 aabbAMinOut, aabbAMaxOut;
+
+                                       b3TransformAabb2((const b3Float4&)aabbA.m_min, (const b3Float4&)aabbA.m_max, margin, transA.getOrigin(), transA.getRotation(), &aabbAMinOut, &aabbAMaxOut);
+
+                                       if (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                                       {
+                                               int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+                                               for (int b = 0; b < numChildrenB; b++)
+                                               {
+                                                       int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + b;
+                                                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                                                       b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+                                                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+                                                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                                                       b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                                                       float4 newPosB = transform(&childPosB, &posB, &ornB);
+                                                       b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
+
+                                                       b3Aabb aabbB = aabbsLocalSpace[childColIndexB];
+
+                                                       b3Transform transB;
+                                                       transB.setIdentity();
+                                                       transB.setOrigin(newPosB);
+                                                       transB.setRotation(newOrnB);
+
+                                                       b3Vector3 aabbBMinOut, aabbBMaxOut;
+                                                       b3TransformAabb2((const b3Float4&)aabbB.m_min, (const b3Float4&)aabbB.m_max, margin, transB.getOrigin(), transB.getRotation(), &aabbBMinOut, &aabbBMaxOut);
+
+                                                       numAabbChecks++;
+                                                       bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut, aabbAMaxOut, aabbBMinOut, aabbBMaxOut);
+                                                       if (aabbOverlap)
+                                                       {
+                                                               /*
+                                                               int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+                                                               float dmin = FLT_MAX;
+                                                               float4 posA = newPosA;
+                                                               posA.w = 0.f;
+                                                               float4 posB = newPosB;
+                                                               posB.w = 0.f;
+                                                               float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+                                                               b3Quat ornA = newOrnA;
+                                                               float4 c0 = transform(&c0local, &posA, &ornA);
+                                                               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+                                                               b3Quat ornB =newOrnB;
+                                                               float4 c1 = transform(&c1local,&posB,&ornB);
+                                                               const float4 DeltaC2 = c0 - c1;
+                                                               */
+                                                               {  //
+                                                                       int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
+                                                                       if (compoundPairIdx < maxNumCompoundPairsCapacity)
+                                                                       {
+                                                                               gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, childShapeIndexA, childShapeIndexB);
+                                                                       }
+                                                               }  //
+                                                       }      //fi(1)
+                                               }          //for (int b=0
+                                       }              //if (collidables[collidableIndexB].
+                                       else           //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                                       {
+                                               if (1)
+                                               {
+                                                       //      int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+                                                       //      float dmin = FLT_MAX;
+                                                       float4 posA = newPosA;
+                                                       posA.w = 0.f;
+                                                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+                                                       posB.w = 0.f;
+                                                       float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+                                                       b3Quat ornA = newOrnA;
+                                                       float4 c0;
+                                                       c0 = transform(&c0local, &posA, &ornA);
+                                                       float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+                                                       b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+                                                       float4 c1;
+                                                       c1 = transform(&c1local, &posB, &ornB);
+                                                       //      const float4 DeltaC2 = c0 - c1;
+
+                                                       {
+                                                               int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
+                                                               if (compoundPairIdx < maxNumCompoundPairsCapacity)
+                                                               {
+                                                                       gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, childShapeIndexA, -1);
+                                                               }  //if (compoundPairIdx<maxNumCompoundPairsCapacity)
+                                                       }      //
+                                               }          //fi (1)
+                                       }              //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                               }                  //for (int b=0;b<numChildrenB;b++)
+                               return;
+                       }  //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                       if ((collidables[collidableIndexA].m_shapeType != SHAPE_CONCAVE_TRIMESH) && (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS))
+                       {
+                               int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+                               for (int b = 0; b < numChildrenB; b++)
+                               {
+                                       int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + b;
+                                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                                       b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+                                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+                                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                                       b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                                       float4 newPosB = b3QuatRotate(ornB, childPosB) + posB;
+                                       b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
+
+                                       int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+
+                                       //////////////////////////////////////
+
+                                       if (1)
+                                       {
+                                               //      int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+                                               //      float dmin = FLT_MAX;
+                                               float4 posA = rigidBodies[bodyIndexA].m_pos;
+                                               posA.w = 0.f;
+                                               float4 posB = newPosB;
+                                               posB.w = 0.f;
+                                               float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+                                               b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+                                               float4 c0;
+                                               c0 = transform(&c0local, &posA, &ornA);
+                                               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+                                               b3Quat ornB = newOrnB;
+                                               float4 c1;
+                                               c1 = transform(&c1local, &posB, &ornB);
+                                               //      const float4 DeltaC2 = c0 - c1;
+                                               {  //
+                                                       int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
+                                                       if (compoundPairIdx < maxNumCompoundPairsCapacity)
+                                                       {
+                                                               gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, -1, childShapeIndexB);
+                                                       }  //fi (compoundPairIdx<maxNumCompoundPairsCapacity)
+                                               }      //
+                                       }          //fi (1)
+                               }              //for (int b=0;b<numChildrenB;b++)
+                               return;
+                       }  //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                       return;
+               }  //fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+       }      //i<numPairs
+}
+
+__kernel void processCompoundPairsKernel(__global const b3Int4* gpuCompoundPairs,
+                                                                                __global const b3RigidBodyData* rigidBodies,
+                                                                                __global const b3Collidable* collidables,
+                                                                                __global const b3ConvexPolyhedronData* convexShapes,
+                                                                                __global const b3AlignedObjectArray<b3Float4>& vertices,
+                                                                                __global const b3AlignedObjectArray<b3Float4>& uniqueEdges,
+                                                                                __global const b3AlignedObjectArray<b3GpuFace>& faces,
+                                                                                __global const b3AlignedObjectArray<int>& indices,
+                                                                                __global b3Aabb* aabbs,
+                                                                                __global const b3GpuChildShape* gpuChildShapes,
+                                                                                __global b3AlignedObjectArray<b3Float4>& gpuCompoundSepNormalsOut,
+                                                                                __global b3AlignedObjectArray<int>& gpuHasCompoundSepNormalsOut,
+                                                                                int numCompoundPairs,
+                                                                                int i)
+{
+       //      int i = get_global_id(0);
+       if (i < numCompoundPairs)
+       {
+               int bodyIndexA = gpuCompoundPairs[i].x;
+               int bodyIndexB = gpuCompoundPairs[i].y;
+
+               int childShapeIndexA = gpuCompoundPairs[i].z;
+               int childShapeIndexB = gpuCompoundPairs[i].w;
+
+               int collidableIndexA = -1;
+               int collidableIndexB = -1;
+
+               b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+               float4 posA = rigidBodies[bodyIndexA].m_pos;
+
+               b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+               float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+               if (childShapeIndexA >= 0)
+               {
+                       collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+                       float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+                       b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+                       float4 newPosA = b3QuatRotate(ornA, childPosA) + posA;
+                       b3Quat newOrnA = b3QuatMul(ornA, childOrnA);
+                       posA = newPosA;
+                       ornA = newOrnA;
+               }
+               else
+               {
+                       collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               }
+
+               if (childShapeIndexB >= 0)
+               {
+                       collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                       b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                       float4 newPosB = b3QuatRotate(ornB, childPosB) + posB;
+                       b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
+                       posB = newPosB;
+                       ornB = newOrnB;
+               }
+               else
+               {
+                       collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+               }
+
+               gpuHasCompoundSepNormalsOut[i] = 0;
+
+               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+               int shapeTypeA = collidables[collidableIndexA].m_shapeType;
+               int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+
+               if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))
+               {
+                       return;
+               }
+
+               int hasSeparatingAxis = 5;
+
+               //      int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+               float dmin = FLT_MAX;
+               posA.w = 0.f;
+               posB.w = 0.f;
+               float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+               float4 c0 = transform(&c0local, &posA, &ornA);
+               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+               float4 c1 = transform(&c1local, &posB, &ornB);
+               const float4 DeltaC2 = c0 - c1;
+               float4 sepNormal = make_float4(1, 0, 0, 0);
+               //              bool sepA = findSeparatingAxis( convexShapes[shapeIndexA], convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+               bool sepA = findSeparatingAxis(convexShapes[shapeIndexA], convexShapes[shapeIndexB], posA, ornA, posB, ornB, vertices, uniqueEdges, faces, indices, vertices, uniqueEdges, faces, indices, sepNormal);  //,&dmin);
+
+               hasSeparatingAxis = 4;
+               if (!sepA)
+               {
+                       hasSeparatingAxis = 0;
+               }
+               else
+               {
+                       bool sepB = findSeparatingAxis(convexShapes[shapeIndexB], convexShapes[shapeIndexA], posB, ornB, posA, ornA, vertices, uniqueEdges, faces, indices, vertices, uniqueEdges, faces, indices, sepNormal);  //,&dmin);
+
+                       if (!sepB)
+                       {
+                               hasSeparatingAxis = 0;
+                       }
+                       else  //(!sepB)
+                       {
+                               bool sepEE = findSeparatingAxisEdgeEdge(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB], posA, ornA, posB, ornB, DeltaC2, vertices, uniqueEdges, faces, indices, &sepNormal, &dmin);
+                               if (sepEE)
+                               {
+                                       gpuCompoundSepNormalsOut[i] = sepNormal;  //fastNormalize4(sepNormal);
+                                       gpuHasCompoundSepNormalsOut[i] = 1;
+                               }  //sepEE
+                       }      //(!sepB)
+               }          //(!sepA)
+       }
+}
+
+__kernel void clipCompoundsHullHullKernel(__global const b3Int4* gpuCompoundPairs,
+                                                                                 __global const b3RigidBodyData* rigidBodies,
+                                                                                 __global const b3Collidable* collidables,
+                                                                                 __global const b3ConvexPolyhedronData* convexShapes,
+                                                                                 __global const b3AlignedObjectArray<b3Float4>& vertices,
+                                                                                 __global const b3AlignedObjectArray<b3Float4>& uniqueEdges,
+                                                                                 __global const b3AlignedObjectArray<b3GpuFace>& faces,
+                                                                                 __global const b3AlignedObjectArray<int>& indices,
+                                                                                 __global const b3GpuChildShape* gpuChildShapes,
+                                                                                 __global const b3AlignedObjectArray<b3Float4>& gpuCompoundSepNormalsOut,
+                                                                                 __global const b3AlignedObjectArray<int>& gpuHasCompoundSepNormalsOut,
+                                                                                 __global struct b3Contact4Data* globalContactsOut,
+                                                                                 int* nGlobalContactsOut,
+                                                                                 int numCompoundPairs, int maxContactCapacity, int i)
+{
+       //      int i = get_global_id(0);
+       int pairIndex = i;
+
+       float4 worldVertsB1[64];
+       float4 worldVertsB2[64];
+       int capacityWorldVerts = 64;
+
+       float4 localContactsOut[64];
+       int localContactCapacity = 64;
+
+       float minDist = -1e30f;
+       float maxDist = 0.0f;
+
+       if (i < numCompoundPairs)
+       {
+               if (gpuHasCompoundSepNormalsOut[i])
+               {
+                       int bodyIndexA = gpuCompoundPairs[i].x;
+                       int bodyIndexB = gpuCompoundPairs[i].y;
+
+                       int childShapeIndexA = gpuCompoundPairs[i].z;
+                       int childShapeIndexB = gpuCompoundPairs[i].w;
+
+                       int collidableIndexA = -1;
+                       int collidableIndexB = -1;
+
+                       b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+
+                       b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+                       if (childShapeIndexA >= 0)
+                       {
+                               collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+                               float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+                               b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+                               float4 newPosA = b3QuatRotate(ornA, childPosA) + posA;
+                               b3Quat newOrnA = b3QuatMul(ornA, childOrnA);
+                               posA = newPosA;
+                               ornA = newOrnA;
+                       }
+                       else
+                       {
+                               collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+                       }
+
+                       if (childShapeIndexB >= 0)
+                       {
+                               collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                               float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                               b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                               float4 newPosB = b3QuatRotate(ornB, childPosB) + posB;
+                               b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
+                               posB = newPosB;
+                               ornB = newOrnB;
+                       }
+                       else
+                       {
+                               collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+                       }
+
+                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+                       int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],
+                                                                                                                 convexShapes[shapeIndexA], convexShapes[shapeIndexB],
+                                                                                                                 posA, ornA,
+                                                                                                                 posB, ornB,
+                                                                                                                 worldVertsB1, worldVertsB2, capacityWorldVerts,
+                                                                                                                 minDist, maxDist,
+                                                                                                                 vertices, faces, indices,
+                                                                                                                 vertices, faces, indices,
+                                                                                                                 localContactsOut, localContactCapacity);
+
+                       if (numLocalContactsOut > 0)
+                       {
+                               float4 normal = -gpuCompoundSepNormalsOut[i];
+                               int nPoints = numLocalContactsOut;
+                               float4* pointsIn = localContactsOut;
+                               b3Int4 contactIdx;  // = {-1,-1,-1,-1};
+
+                               contactIdx.s[0] = 0;
+                               contactIdx.s[1] = 1;
+                               contactIdx.s[2] = 2;
+                               contactIdx.s[3] = 3;
+
+                               int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
+
+                               int dstIdx;
+                               dstIdx = b3AtomicInc(nGlobalContactsOut);
+                               if ((dstIdx + nReducedContacts) < maxContactCapacity)
+                               {
+                                       __global struct b3Contact4Data* c = globalContactsOut + dstIdx;
+                                       c->m_worldNormalOnB = -normal;
+                                       c->m_restituitionCoeffCmp = (0.f * 0xffff);
+                                       c->m_frictionCoeffCmp = (0.7f * 0xffff);
+                                       c->m_batchIdx = pairIndex;
+                                       int bodyA = gpuCompoundPairs[pairIndex].x;
+                                       int bodyB = gpuCompoundPairs[pairIndex].y;
+                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass == 0 ? -bodyA : bodyA;
+                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass == 0 ? -bodyB : bodyB;
+                                       c->m_childIndexA = childShapeIndexA;
+                                       c->m_childIndexB = childShapeIndexB;
+                                       for (int i = 0; i < nReducedContacts; i++)
+                                       {
+                                               c->m_worldPosB[i] = pointsIn[contactIdx.s[i]];
+                                       }
+                                       b3Contact4Data_setNumPoints(c, nReducedContacts);
+                               }
+
+                       }  //           if (numContactsOut>0)
+               }      //               if (gpuHasCompoundSepNormalsOut[i])
+       }          //   if (i<numCompoundPairs)
+}
+
+void computeContactCompoundCompound(int pairIndex,
+                                                                       int bodyIndexA, int bodyIndexB,
+                                                                       int collidableIndexA, int collidableIndexB,
+                                                                       const b3RigidBodyData* rigidBodies,
+                                                                       const b3Collidable* collidables,
+                                                                       const b3ConvexPolyhedronData* convexShapes,
+                                                                       const b3GpuChildShape* cpuChildShapes,
+                                                                       const b3AlignedObjectArray<b3Aabb>& hostAabbsWorldSpace,
+                                                                       const b3AlignedObjectArray<b3Aabb>& hostAabbsLocalSpace,
+
+                                                                       const b3AlignedObjectArray<b3Vector3>& convexVertices,
+                                                                       const b3AlignedObjectArray<b3Vector3>& hostUniqueEdges,
+                                                                       const b3AlignedObjectArray<int>& convexIndices,
+                                                                       const b3AlignedObjectArray<b3GpuFace>& faces,
+
+                                                                       b3Contact4* globalContactsOut,
+                                                                       int& nGlobalContactsOut,
+                                                                       int maxContactCapacity,
+                                                                       b3AlignedObjectArray<b3QuantizedBvhNode>& treeNodesCPU,
+                                                                       b3AlignedObjectArray<b3BvhSubtreeInfo>& subTreesCPU,
+                                                                       b3AlignedObjectArray<b3BvhInfo>& bvhInfoCPU)
+{
+       int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+       b3Assert(shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS);
+
+       b3AlignedObjectArray<b3Int4> cpuCompoundPairsOut;
+       int numCompoundPairsOut = 0;
+       int maxNumCompoundPairsCapacity = 8192;  //1024;
+       cpuCompoundPairsOut.resize(maxNumCompoundPairsCapacity);
+
+       // work-in-progress
+       findCompoundPairsKernel(
+               pairIndex,
+               bodyIndexA, bodyIndexB,
+               collidableIndexA, collidableIndexB,
+               rigidBodies,
+               collidables,
+               convexShapes,
+               convexVertices,
+               hostAabbsWorldSpace,
+               hostAabbsLocalSpace,
+               cpuChildShapes,
+               &cpuCompoundPairsOut[0],
+               &numCompoundPairsOut,
+               maxNumCompoundPairsCapacity,
+               treeNodesCPU,
+               subTreesCPU,
+               bvhInfoCPU);
+
+       printf("maxNumAabbChecks=%d\n", maxNumAabbChecks);
+       if (numCompoundPairsOut > maxNumCompoundPairsCapacity)
+       {
+               b3Error("numCompoundPairsOut exceeded maxNumCompoundPairsCapacity (%d)\n", maxNumCompoundPairsCapacity);
+               numCompoundPairsOut = maxNumCompoundPairsCapacity;
+       }
+       b3AlignedObjectArray<b3Float4> cpuCompoundSepNormalsOut;
+       b3AlignedObjectArray<int> cpuHasCompoundSepNormalsOut;
+       cpuCompoundSepNormalsOut.resize(numCompoundPairsOut);
+       cpuHasCompoundSepNormalsOut.resize(numCompoundPairsOut);
+
+       for (int i = 0; i < numCompoundPairsOut; i++)
+       {
+               processCompoundPairsKernel(&cpuCompoundPairsOut[0], rigidBodies, collidables, convexShapes, convexVertices, hostUniqueEdges, faces, convexIndices, 0, cpuChildShapes,
+                                                                  cpuCompoundSepNormalsOut, cpuHasCompoundSepNormalsOut, numCompoundPairsOut, i);
+       }
+
+       for (int i = 0; i < numCompoundPairsOut; i++)
+       {
+               clipCompoundsHullHullKernel(&cpuCompoundPairsOut[0], rigidBodies, collidables, convexShapes, convexVertices, hostUniqueEdges, faces, convexIndices, cpuChildShapes,
+                                                                       cpuCompoundSepNormalsOut, cpuHasCompoundSepNormalsOut, globalContactsOut, &nGlobalContactsOut, numCompoundPairsOut, maxContactCapacity, i);
+       }
+       /*
+               int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+
+                                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+                                       b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+                                       float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+                                       b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+                                       float4 newPosA = b3QuatRotate(ornA,childPosA)+posA;
+                                       b3Quat newOrnA = b3QuatMul(ornA,childOrnA);
+
+                                       int shapeIndexA = collidables[childColIndexA].m_shapeIndex;
+
+
+                       bool foundSepAxis = findSeparatingAxis(hullA,hullB,
+                                                       posA,
+                                                       ornA,
+                                                       posB,
+                                                       ornB,
+
+                                                       convexVertices,uniqueEdges,faces,convexIndices,
+                                                       convexVertices,uniqueEdges,faces,convexIndices,
+                                                       
+                                                       sepNormalWorldSpace
+                                                       );
+                                                       */
+
+       /*
+       if (foundSepAxis)
+       {
+               
+               
+               contactIndex = clipHullHullSingle(
+                       bodyIndexA, bodyIndexB,
+                                                  posA,ornA,
+                                                  posB,ornB,
+                       collidableIndexA, collidableIndexB,
+                       &rigidBodies, 
+                       &globalContactsOut,
+                       nGlobalContactsOut,
+                       
+                       convexShapes,
+                       convexShapes,
+       
+                       convexVertices, 
+                       uniqueEdges, 
+                       faces,
+                       convexIndices,
+       
+                       convexVertices,
+                       uniqueEdges,
+                       faces,
+                       convexIndices,
+
+                       collidables,
+                       collidables,
+                       sepNormalWorldSpace,
+                       maxContactCapacity);
+                       
+       }
+       */
+
+       //      return contactIndex;
+
+       /*
+
+       int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+       for (int c=0;c<numChildrenB;c++)
+       {
+               int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+c;
+               int childColIndexB = cpuChildShapes[childShapeIndexB].m_shapeIndex;
+
+               float4 rootPosB = rigidBodies[bodyIndexB].m_pos;
+               b3Quaternion rootOrnB = rigidBodies[bodyIndexB].m_quat;
+               b3Vector3 childPosB = cpuChildShapes[childShapeIndexB].m_childPosition;
+               b3Quaternion childOrnB = cpuChildShapes[childShapeIndexB].m_childOrientation;
+               float4  posB = b3QuatRotate(rootOrnB,childPosB)+rootPosB;
+               b3Quaternion ornB = b3QuatMul(rootOrnB,childOrnB);//b3QuatMul(ornB,childOrnB);
+
+               int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+
+               const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndexB];
+
+       }
+       */
+}
+
+void computeContactPlaneCompound(int pairIndex,
+                                                                int bodyIndexA, int bodyIndexB,
+                                                                int collidableIndexA, int collidableIndexB,
+                                                                const b3RigidBodyData* rigidBodies,
+                                                                const b3Collidable* collidables,
+                                                                const b3ConvexPolyhedronData* convexShapes,
+                                                                const b3GpuChildShape* cpuChildShapes,
+                                                                const b3Vector3* convexVertices,
+                                                                const int* convexIndices,
+                                                                const b3GpuFace* faces,
+
+                                                                b3Contact4* globalContactsOut,
+                                                                int& nGlobalContactsOut,
+                                                                int maxContactCapacity)
+{
+       int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+       b3Assert(shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS);
+
+       int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+       for (int c = 0; c < numChildrenB; c++)
+       {
+               int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + c;
+               int childColIndexB = cpuChildShapes[childShapeIndexB].m_shapeIndex;
+
+               float4 rootPosB = rigidBodies[bodyIndexB].m_pos;
+               b3Quaternion rootOrnB = rigidBodies[bodyIndexB].m_quat;
+               b3Vector3 childPosB = cpuChildShapes[childShapeIndexB].m_childPosition;
+               b3Quaternion childOrnB = cpuChildShapes[childShapeIndexB].m_childOrientation;
+               float4 posB = b3QuatRotate(rootOrnB, childPosB) + rootPosB;
+               b3Quaternion ornB = rootOrnB * childOrnB;  //b3QuatMul(ornB,childOrnB);
+
+               int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+
+               const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndexB];
+
+               b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
+               b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
+
+               //      int numContactsOut = 0;
+               //      int numWorldVertsB1= 0;
+
+               b3Vector3 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
+               b3Vector3 planeNormal = b3MakeVector3(planeEq.x, planeEq.y, planeEq.z);
+               b3Vector3 planeNormalWorld = b3QuatRotate(ornA, planeNormal);
+               float planeConstant = planeEq.w;
+               b3Transform convexWorldTransform;
+               convexWorldTransform.setIdentity();
+               convexWorldTransform.setOrigin(posB);
+               convexWorldTransform.setRotation(ornB);
+               b3Transform planeTransform;
+               planeTransform.setIdentity();
+               planeTransform.setOrigin(posA);
+               planeTransform.setRotation(ornA);
+
+               b3Transform planeInConvex;
+               planeInConvex = convexWorldTransform.inverse() * planeTransform;
+               b3Transform convexInPlane;
+               convexInPlane = planeTransform.inverse() * convexWorldTransform;
+
+               b3Vector3 planeNormalInConvex = planeInConvex.getBasis() * -planeNormal;
+               float maxDot = -1e30;
+               int hitVertex = -1;
+               b3Vector3 hitVtx;
+
+#define MAX_PLANE_CONVEX_POINTS 64
+
+               b3Vector3 contactPoints[MAX_PLANE_CONVEX_POINTS];
+               int numPoints = 0;
+
+               b3Int4 contactIdx;
+               contactIdx.s[0] = 0;
+               contactIdx.s[1] = 1;
+               contactIdx.s[2] = 2;
+               contactIdx.s[3] = 3;
+
+               for (int i = 0; i < hullB->m_numVertices; i++)
+               {
+                       b3Vector3 vtx = convexVertices[hullB->m_vertexOffset + i];
+                       float curDot = vtx.dot(planeNormalInConvex);
+
+                       if (curDot > maxDot)
+                       {
+                               hitVertex = i;
+                               maxDot = curDot;
+                               hitVtx = vtx;
+                               //make sure the deepest points is always included
+                               if (numPoints == MAX_PLANE_CONVEX_POINTS)
+                                       numPoints--;
+                       }
+
+                       if (numPoints < MAX_PLANE_CONVEX_POINTS)
+                       {
+                               b3Vector3 vtxWorld = convexWorldTransform * vtx;
+                               b3Vector3 vtxInPlane = planeTransform.inverse() * vtxWorld;
+                               float dist = planeNormal.dot(vtxInPlane) - planeConstant;
+                               if (dist < 0.f)
+                               {
+                                       vtxWorld.w = dist;
+                                       contactPoints[numPoints] = vtxWorld;
+                                       numPoints++;
+                               }
+                       }
+               }
+
+               int numReducedPoints = 0;
+
+               numReducedPoints = numPoints;
+
+               if (numPoints > 4)
+               {
+                       numReducedPoints = extractManifoldSequentialGlobal(contactPoints, numPoints, planeNormalInConvex, &contactIdx);
+               }
+               int dstIdx;
+               //    dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+               if (numReducedPoints > 0)
+               {
+                       if (nGlobalContactsOut < maxContactCapacity)
+                       {
+                               dstIdx = nGlobalContactsOut;
+                               nGlobalContactsOut++;
+
+                               b3Contact4* c = &globalContactsOut[dstIdx];
+                               c->m_worldNormalOnB = -planeNormalWorld;
+                               c->setFrictionCoeff(0.7);
+                               c->setRestituitionCoeff(0.f);
+
+                               c->m_batchIdx = pairIndex;
+                               c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
+                               c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
+                               for (int i = 0; i < numReducedPoints; i++)
+                               {
+                                       b3Vector3 pOnB1 = contactPoints[contactIdx.s[i]];
+                                       c->m_worldPosB[i] = pOnB1;
+                               }
+                               c->m_worldNormalOnB.w = (b3Scalar)numReducedPoints;
+                       }  //if (dstIdx < numPairs)
+               }
+       }
+}
+
+void computeContactSphereConvex(int pairIndex,
+                                                               int bodyIndexA, int bodyIndexB,
+                                                               int collidableIndexA, int collidableIndexB,
+                                                               const b3RigidBodyData* rigidBodies,
+                                                               const b3Collidable* collidables,
+                                                               const b3ConvexPolyhedronData* convexShapes,
+                                                               const b3Vector3* convexVertices,
+                                                               const int* convexIndices,
+                                                               const b3GpuFace* faces,
+                                                               b3Contact4* globalContactsOut,
+                                                               int& nGlobalContactsOut,
+                                                               int maxContactCapacity)
+{
+       float radius = collidables[collidableIndexA].m_radius;
+       float4 spherePos1 = rigidBodies[bodyIndexA].m_pos;
+       b3Quaternion sphereOrn = rigidBodies[bodyIndexA].m_quat;
+
+       float4 pos = rigidBodies[bodyIndexB].m_pos;
+
+       b3Quaternion quat = rigidBodies[bodyIndexB].m_quat;
+
+       b3Transform tr;
+       tr.setIdentity();
+       tr.setOrigin(pos);
+       tr.setRotation(quat);
+       b3Transform trInv = tr.inverse();
+
+       float4 spherePos = trInv(spherePos1);
+
+       int collidableIndex = rigidBodies[bodyIndexB].m_collidableIdx;
+       int shapeIndex = collidables[collidableIndex].m_shapeIndex;
+       int numFaces = convexShapes[shapeIndex].m_numFaces;
+       float4 closestPnt = b3MakeVector3(0, 0, 0, 0);
+       //      float4 hitNormalWorld = b3MakeVector3(0, 0, 0, 0);
+       float minDist = -1000000.f;  // TODO: What is the largest/smallest float?
+       bool bCollide = true;
+       int region = -1;
+       float4 localHitNormal;
+       for (int f = 0; f < numFaces; f++)
+       {
+               b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset + f];
+               float4 planeEqn;
+               float4 localPlaneNormal = b3MakeVector3(face.m_plane.x, face.m_plane.y, face.m_plane.z, 0.f);
+               float4 n1 = localPlaneNormal;  //quatRotate(quat,localPlaneNormal);
+               planeEqn = n1;
+               planeEqn[3] = face.m_plane.w;
+
+               float4 pntReturn;
+               float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
+
+               if (dist > radius)
+               {
+                       bCollide = false;
+                       break;
+               }
+
+               if (dist > 0)
+               {
+                       //might hit an edge or vertex
+                       b3Vector3 out;
+
+                       bool isInPoly = IsPointInPolygon(spherePos,
+                                                                                        &face,
+                                                                                        &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
+                                                                                        convexIndices,
+                                                                                        &out);
+                       if (isInPoly)
+                       {
+                               if (dist > minDist)
+                               {
+                                       minDist = dist;
+                                       closestPnt = pntReturn;
+                                       localHitNormal = planeEqn;
+                                       region = 1;
+                               }
+                       }
+                       else
+                       {
+                               b3Vector3 tmp = spherePos - out;
+                               b3Scalar l2 = tmp.length2();
+                               if (l2 < radius * radius)
+                               {
+                                       dist = b3Sqrt(l2);
+                                       if (dist > minDist)
+                                       {
+                                               minDist = dist;
+                                               closestPnt = out;
+                                               localHitNormal = tmp / dist;
+                                               region = 2;
+                                       }
+                               }
+                               else
+                               {
+                                       bCollide = false;
+                                       break;
+                               }
+                       }
+               }
+               else
+               {
+                       if (dist > minDist)
+                       {
+                               minDist = dist;
+                               closestPnt = pntReturn;
+                               localHitNormal = planeEqn;
+                               region = 3;
+                       }
+               }
+       }
+       static int numChecks = 0;
+       numChecks++;
+
+       if (bCollide && minDist > -10000)
+       {
+               float4 normalOnSurfaceB1 = tr.getBasis() * localHitNormal;  //-hitNormalWorld;
+               float4 pOnB1 = tr(closestPnt);
+               //printf("dist ,%f,",minDist);
+               float actualDepth = minDist - radius;
+               if (actualDepth < 0)
+               {
+                       //printf("actualDepth = ,%f,", actualDepth);
+                       //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z);
+                       //printf("region=,%d,\n", region);
+                       pOnB1[3] = actualDepth;
+
+                       int dstIdx;
+                       //    dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
+
+                       if (nGlobalContactsOut < maxContactCapacity)
+                       {
+                               dstIdx = nGlobalContactsOut;
+                               nGlobalContactsOut++;
+
+                               b3Contact4* c = &globalContactsOut[dstIdx];
+                               c->m_worldNormalOnB = normalOnSurfaceB1;
+                               c->setFrictionCoeff(0.7);
+                               c->setRestituitionCoeff(0.f);
+
+                               c->m_batchIdx = pairIndex;
+                               c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
+                               c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
+                               c->m_worldPosB[0] = pOnB1;
+                               int numPoints = 1;
+                               c->m_worldNormalOnB.w = (b3Scalar)numPoints;
+                       }  //if (dstIdx < numPairs)
+               }
+       }  //if (hasCollision)
+}
+
+int computeContactConvexConvex2(
+       int pairIndex,
+       int bodyIndexA, int bodyIndexB,
+       int collidableIndexA, int collidableIndexB,
+       const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
+       const b3AlignedObjectArray<b3Collidable>& collidables,
+       const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
+       const b3AlignedObjectArray<b3Vector3>& convexVertices,
+       const b3AlignedObjectArray<b3Vector3>& uniqueEdges,
+       const b3AlignedObjectArray<int>& convexIndices,
+       const b3AlignedObjectArray<b3GpuFace>& faces,
+       b3AlignedObjectArray<b3Contact4>& globalContactsOut,
+       int& nGlobalContactsOut,
+       int maxContactCapacity,
+       const b3AlignedObjectArray<b3Contact4>& oldContacts)
+{
+       int contactIndex = -1;
+       b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
+       b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
+       b3Vector3 posB = rigidBodies[bodyIndexB].m_pos;
+       b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
+
+       b3ConvexPolyhedronData hullA, hullB;
+
+       b3Vector3 sepNormalWorldSpace;
+
+       b3Collidable colA = collidables[collidableIndexA];
+       hullA = convexShapes[colA.m_shapeIndex];
+       //printf("numvertsA = %d\n",hullA.m_numVertices);
+
+       b3Collidable colB = collidables[collidableIndexB];
+       hullB = convexShapes[colB.m_shapeIndex];
+       //printf("numvertsB = %d\n",hullB.m_numVertices);
+
+       //      int contactCapacity = MAX_VERTS;
+       //int numContactsOut=0;
+
+#ifdef _WIN32
+       b3Assert(_finite(rigidBodies[bodyIndexA].m_pos.x));
+       b3Assert(_finite(rigidBodies[bodyIndexB].m_pos.x));
+#endif
+
+       bool foundSepAxis = findSeparatingAxis(hullA, hullB,
+                                                                                  posA,
+                                                                                  ornA,
+                                                                                  posB,
+                                                                                  ornB,
+
+                                                                                  convexVertices, uniqueEdges, faces, convexIndices,
+                                                                                  convexVertices, uniqueEdges, faces, convexIndices,
+
+                                                                                  sepNormalWorldSpace);
+
+       if (foundSepAxis)
+       {
+               contactIndex = clipHullHullSingle(
+                       bodyIndexA, bodyIndexB,
+                       posA, ornA,
+                       posB, ornB,
+                       collidableIndexA, collidableIndexB,
+                       &rigidBodies,
+                       &globalContactsOut,
+                       nGlobalContactsOut,
+
+                       convexShapes,
+                       convexShapes,
+
+                       convexVertices,
+                       uniqueEdges,
+                       faces,
+                       convexIndices,
+
+                       convexVertices,
+                       uniqueEdges,
+                       faces,
+                       convexIndices,
+
+                       collidables,
+                       collidables,
+                       sepNormalWorldSpace,
+                       maxContactCapacity);
+       }
+
+       return contactIndex;
+}
+
+void GpuSatCollision::computeConvexConvexContactsGPUSAT(b3OpenCLArray<b3Int4>* pairs, int nPairs,
+                                                                                                               const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+                                                                                                               b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
+                                                                                                               const b3OpenCLArray<b3Contact4>* oldContacts,
+                                                                                                               int maxContactCapacity,
+                                                                                                               int compoundPairCapacity,
+                                                                                                               const b3OpenCLArray<b3ConvexPolyhedronData>& convexData,
+                                                                                                               const b3OpenCLArray<b3Vector3>& gpuVertices,
+                                                                                                               const b3OpenCLArray<b3Vector3>& gpuUniqueEdges,
+                                                                                                               const b3OpenCLArray<b3GpuFace>& gpuFaces,
+                                                                                                               const b3OpenCLArray<int>& gpuIndices,
+                                                                                                               const b3OpenCLArray<b3Collidable>& gpuCollidables,
+                                                                                                               const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
+
+                                                                                                               const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
+                                                                                                               const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
+
+                                                                                                               b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
+                                                                                                               b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
+                                                                                                               b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
+                                                                                                               b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
+                                                                                                               b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
+                                                                                                               b3AlignedObjectArray<class b3OptimizedBvh*>& bvhDataUnused,
+                                                                                                               b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
+                                                                                                               b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
+                                                                                                               b3OpenCLArray<b3BvhInfo>* bvhInfo,
+
+                                                                                                               int numObjects,
+                                                                                                               int maxTriConvexPairCapacity,
+                                                                                                               b3OpenCLArray<b3Int4>& triangleConvexPairsOut,
+                                                                                                               int& numTriConvexPairsOut)
+{
+       myframecount++;
+
+       if (!nPairs)
+               return;
+
+#ifdef CHECK_ON_HOST
+
+       b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
+       treeNodesGPU->copyToHost(treeNodesCPU);
+
+       b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
+       subTreesGPU->copyToHost(subTreesCPU);
+
+       b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
+       bvhInfo->copyToHost(bvhInfoCPU);
+
+       b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+       clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+
+       b3AlignedObjectArray<b3Aabb> hostAabbsLocalSpace;
+       clAabbsLocalSpace.copyToHost(hostAabbsLocalSpace);
+
+       b3AlignedObjectArray<b3Int4> hostPairs;
+       pairs->copyToHost(hostPairs);
+
+       b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+       bodyBuf->copyToHost(hostBodyBuf);
+
+       b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+       convexData.copyToHost(hostConvexData);
+
+       b3AlignedObjectArray<b3Vector3> hostVertices;
+       gpuVertices.copyToHost(hostVertices);
+
+       b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
+       gpuUniqueEdges.copyToHost(hostUniqueEdges);
+       b3AlignedObjectArray<b3GpuFace> hostFaces;
+       gpuFaces.copyToHost(hostFaces);
+       b3AlignedObjectArray<int> hostIndices;
+       gpuIndices.copyToHost(hostIndices);
+       b3AlignedObjectArray<b3Collidable> hostCollidables;
+       gpuCollidables.copyToHost(hostCollidables);
+
+       b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+       gpuChildShapes.copyToHost(cpuChildShapes);
+
+       b3AlignedObjectArray<b3Int4> hostTriangleConvexPairs;
+
+       b3AlignedObjectArray<b3Contact4> hostContacts;
+       if (nContacts)
+       {
+               contactOut->copyToHost(hostContacts);
+       }
+
+       b3AlignedObjectArray<b3Contact4> oldHostContacts;
+
+       if (oldContacts->size())
+       {
+               oldContacts->copyToHost(oldHostContacts);
+       }
+
+       hostContacts.resize(maxContactCapacity);
+
+       for (int i = 0; i < nPairs; i++)
+       {
+               int bodyIndexA = hostPairs[i].x;
+               int bodyIndexB = hostPairs[i].y;
+               int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+               int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+
+               if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+                       hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+               {
+                       computeContactSphereConvex(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, &hostBodyBuf[0],
+                                                                          &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
+               }
+
+               if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+                       hostCollidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+               {
+                       computeContactSphereConvex(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
+                                                                          &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
+                       //printf("convex-sphere\n");
+               }
+
+               if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+                       hostCollidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
+               {
+                       computeContactPlaneConvex(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
+                                                                         &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
+                       //                      printf("convex-plane\n");
+               }
+
+               if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+                       hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+               {
+                       computeContactPlaneConvex(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, &hostBodyBuf[0],
+                                                                         &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
+                       //                      printf("plane-convex\n");
+               }
+
+               if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+                       hostCollidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+               {
+                       computeContactCompoundCompound(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
+                                                                                  &hostCollidables[0], &hostConvexData[0], &cpuChildShapes[0], hostAabbsWorldSpace, hostAabbsLocalSpace, hostVertices, hostUniqueEdges, hostIndices, hostFaces, &hostContacts[0],
+                                                                                  nContacts, maxContactCapacity, treeNodesCPU, subTreesCPU, bvhInfoCPU);
+                       //                      printf("convex-plane\n");
+               }
+
+               if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
+                       hostCollidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
+               {
+                       computeContactPlaneCompound(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
+                                                                               &hostCollidables[0], &hostConvexData[0], &cpuChildShapes[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
+                       //                      printf("convex-plane\n");
+               }
+
+               if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+                       hostCollidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
+               {
+                       computeContactPlaneCompound(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, &hostBodyBuf[0],
+                                                                               &hostCollidables[0], &hostConvexData[0], &cpuChildShapes[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
+                       //                      printf("plane-convex\n");
+               }
+
+               if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+                       hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+               {
+                       //printf("hostPairs[i].z=%d\n",hostPairs[i].z);
+                       int contactIndex = computeContactConvexConvex2(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, hostBodyBuf, hostCollidables, hostConvexData, hostVertices, hostUniqueEdges, hostIndices, hostFaces, hostContacts, nContacts, maxContactCapacity, oldHostContacts);
+                       //int contactIndex = computeContactConvexConvex(hostPairs,i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf,hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
+
+                       if (contactIndex >= 0)
+                       {
+                               //                              printf("convex convex contactIndex = %d\n",contactIndex);
+                               hostPairs[i].z = contactIndex;
+                       }
+                       //                      printf("plane-convex\n");
+               }
+       }
+
+       if (hostPairs.size())
+       {
+               pairs->copyFromHost(hostPairs);
+       }
+
+       hostContacts.resize(nContacts);
+       if (nContacts)
+       {
+               contactOut->copyFromHost(hostContacts);
+       }
+       else
+       {
+               contactOut->resize(0);
+       }
+
+       m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
+       //printf("(HOST) nContacts = %d\n",nContacts);
+
+#else
+
+       {
+               if (nPairs)
+               {
+                       m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
+
+                       B3_PROFILE("primitiveContactsKernel");
+                       b3BufferInfoCL bInfo[] = {
+                               b3BufferInfoCL(pairs->getBufferCL(), true),
+                               b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                               b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                               b3BufferInfoCL(convexData.getBufferCL(), true),
+                               b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                               b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                               b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                               b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                               b3BufferInfoCL(contactOut->getBufferCL()),
+                               b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+                       b3LauncherCL launcher(m_queue, m_primitiveContactsKernel, "m_primitiveContactsKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(nPairs);
+                       launcher.setConst(maxContactCapacity);
+                       int num = nPairs;
+                       launcher.launch1D(num);
+                       clFinish(m_queue);
+
+                       nContacts = m_totalContactsOut.at(0);
+                       contactOut->resize(nContacts);
+               }
+       }
+
+#endif  //CHECK_ON_HOST
+
+       B3_PROFILE("computeConvexConvexContactsGPUSAT");
+       // printf("nContacts = %d\n",nContacts);
+
+       m_sepNormals.resize(nPairs);
+       m_hasSeparatingNormals.resize(nPairs);
+
+       int concaveCapacity = maxTriConvexPairCapacity;
+       m_concaveSepNormals.resize(concaveCapacity);
+       m_concaveHasSeparatingNormals.resize(concaveCapacity);
+       m_numConcavePairsOut.resize(0);
+       m_numConcavePairsOut.push_back(0);
+
+       m_gpuCompoundPairs.resize(compoundPairCapacity);
+
+       m_gpuCompoundSepNormals.resize(compoundPairCapacity);
+
+       m_gpuHasCompoundSepNormals.resize(compoundPairCapacity);
+
+       m_numCompoundPairsOut.resize(0);
+       m_numCompoundPairsOut.push_back(0);
+
+       int numCompoundPairs = 0;
+
+       int numConcavePairs = 0;
+
+       {
+               clFinish(m_queue);
+               if (findSeparatingAxisOnGpu)
+               {
+                       m_dmins.resize(nPairs);
+                       if (splitSearchSepAxisConvex)
+                       {
+                               if (useMprGpu)
+                               {
+                                       nContacts = m_totalContactsOut.at(0);
+                                       {
+                                               B3_PROFILE("mprPenetrationKernel");
+                                               b3BufferInfoCL bInfo[] = {
+                                                       b3BufferInfoCL(pairs->getBufferCL(), true),
+                                                       b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                                       b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                                       b3BufferInfoCL(convexData.getBufferCL(), true),
+                                                       b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                                       b3BufferInfoCL(m_sepNormals.getBufferCL()),
+                                                       b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+                                                       b3BufferInfoCL(contactOut->getBufferCL()),
+                                                       b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+                                               b3LauncherCL launcher(m_queue, m_mprPenetrationKernel, "mprPenetrationKernel");
+                                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+
+                                               launcher.setConst(maxContactCapacity);
+                                               launcher.setConst(nPairs);
+
+                                               int num = nPairs;
+                                               launcher.launch1D(num);
+                                               clFinish(m_queue);
+                                               /*
+                                               b3AlignedObjectArray<int>hostHasSepAxis;
+                                               m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
+                                               b3AlignedObjectArray<b3Vector3>hostSepAxis;
+                                               m_sepNormals.copyToHost(hostSepAxis);
+                                               */
+                                               nContacts = m_totalContactsOut.at(0);
+                                               contactOut->resize(nContacts);
+                                               //      printf("nContacts (after mprPenetrationKernel) = %d\n",nContacts);
+                                               if (nContacts > maxContactCapacity)
+                                               {
+                                                       b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
+                                                       nContacts = maxContactCapacity;
+                                               }
+                                       }
+                               }
+
+                               if (1)
+                               {
+                                       if (1)
+                                       {
+                                               {
+                                                       B3_PROFILE("findSeparatingAxisVertexFaceKernel");
+                                                       b3BufferInfoCL bInfo[] = {
+                                                               b3BufferInfoCL(pairs->getBufferCL(), true),
+                                                               b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                                               b3BufferInfoCL(convexData.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                                               b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+                                                               b3BufferInfoCL(m_sepNormals.getBufferCL()),
+                                                               b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+                                                               b3BufferInfoCL(m_dmins.getBufferCL())};
+
+                                                       b3LauncherCL launcher(m_queue, m_findSeparatingAxisVertexFaceKernel, "findSeparatingAxisVertexFaceKernel");
+                                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                                       launcher.setConst(nPairs);
+
+                                                       int num = nPairs;
+                                                       launcher.launch1D(num);
+                                                       clFinish(m_queue);
+                                               }
+
+                                               int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
+
+                                               {
+                                                       B3_PROFILE("findSeparatingAxisEdgeEdgeKernel");
+                                                       b3BufferInfoCL bInfo[] = {
+                                                               b3BufferInfoCL(pairs->getBufferCL(), true),
+                                                               b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                                               b3BufferInfoCL(convexData.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                                               b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+                                                               b3BufferInfoCL(m_sepNormals.getBufferCL()),
+                                                               b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+                                                               b3BufferInfoCL(m_dmins.getBufferCL()),
+                                                               b3BufferInfoCL(m_unitSphereDirections.getBufferCL(), true)
+
+                                                       };
+
+                                                       b3LauncherCL launcher(m_queue, m_findSeparatingAxisEdgeEdgeKernel, "findSeparatingAxisEdgeEdgeKernel");
+                                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                                       launcher.setConst(numDirections);
+                                                       launcher.setConst(nPairs);
+                                                       int num = nPairs;
+                                                       launcher.launch1D(num);
+                                                       clFinish(m_queue);
+                                               }
+                                       }
+                                       if (useMprGpu)
+                                       {
+                                               B3_PROFILE("findSeparatingAxisUnitSphereKernel");
+                                               b3BufferInfoCL bInfo[] = {
+                                                       b3BufferInfoCL(pairs->getBufferCL(), true),
+                                                       b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                                       b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                                       b3BufferInfoCL(convexData.getBufferCL(), true),
+                                                       b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                                       b3BufferInfoCL(m_unitSphereDirections.getBufferCL(), true),
+                                                       b3BufferInfoCL(m_sepNormals.getBufferCL()),
+                                                       b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+                                                       b3BufferInfoCL(m_dmins.getBufferCL())};
+
+                                               b3LauncherCL launcher(m_queue, m_findSeparatingAxisUnitSphereKernel, "findSeparatingAxisUnitSphereKernel");
+                                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                               int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
+                                               launcher.setConst(numDirections);
+
+                                               launcher.setConst(nPairs);
+
+                                               int num = nPairs;
+                                               launcher.launch1D(num);
+                                               clFinish(m_queue);
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               B3_PROFILE("findSeparatingAxisKernel");
+                               b3BufferInfoCL bInfo[] = {
+                                       b3BufferInfoCL(pairs->getBufferCL(), true),
+                                       b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                       b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                       b3BufferInfoCL(convexData.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                       b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+                                       b3BufferInfoCL(m_sepNormals.getBufferCL()),
+                                       b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL())};
+
+                               b3LauncherCL launcher(m_queue, m_findSeparatingAxisKernel, "m_findSeparatingAxisKernel");
+                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                               launcher.setConst(nPairs);
+
+                               int num = nPairs;
+                               launcher.launch1D(num);
+                               clFinish(m_queue);
+                       }
+               }
+               else
+               {
+                       B3_PROFILE("findSeparatingAxisKernel CPU");
+
+                       b3AlignedObjectArray<b3Int4> hostPairs;
+                       pairs->copyToHost(hostPairs);
+                       b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+                       bodyBuf->copyToHost(hostBodyBuf);
+
+                       b3AlignedObjectArray<b3Collidable> hostCollidables;
+                       gpuCollidables.copyToHost(hostCollidables);
+
+                       b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+                       gpuChildShapes.copyToHost(cpuChildShapes);
+
+                       b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexShapeData;
+                       convexData.copyToHost(hostConvexShapeData);
+
+                       b3AlignedObjectArray<b3Vector3> hostVertices;
+                       gpuVertices.copyToHost(hostVertices);
+
+                       b3AlignedObjectArray<int> hostHasSepAxis;
+                       hostHasSepAxis.resize(nPairs);
+                       b3AlignedObjectArray<b3Vector3> hostSepAxis;
+                       hostSepAxis.resize(nPairs);
+
+                       b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
+                       gpuUniqueEdges.copyToHost(hostUniqueEdges);
+                       b3AlignedObjectArray<b3GpuFace> hostFaces;
+                       gpuFaces.copyToHost(hostFaces);
+
+                       b3AlignedObjectArray<int> hostIndices;
+                       gpuIndices.copyToHost(hostIndices);
+
+                       b3AlignedObjectArray<b3Contact4> hostContacts;
+                       if (nContacts)
+                       {
+                               contactOut->copyToHost(hostContacts);
+                       }
+                       hostContacts.resize(maxContactCapacity);
+                       int nGlobalContactsOut = nContacts;
+
+                       for (int i = 0; i < nPairs; i++)
+                       {
+                               int bodyIndexA = hostPairs[i].x;
+                               int bodyIndexB = hostPairs[i].y;
+                               int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+                               int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+
+                               int shapeIndexA = hostCollidables[collidableIndexA].m_shapeIndex;
+                               int shapeIndexB = hostCollidables[collidableIndexB].m_shapeIndex;
+
+                               hostHasSepAxis[i] = 0;
+
+                               //once the broadphase avoids static-static pairs, we can remove this test
+                               if ((hostBodyBuf[bodyIndexA].m_invMass == 0) && (hostBodyBuf[bodyIndexB].m_invMass == 0))
+                               {
+                                       continue;
+                               }
+
+                               if ((hostCollidables[collidableIndexA].m_shapeType != SHAPE_CONVEX_HULL) || (hostCollidables[collidableIndexB].m_shapeType != SHAPE_CONVEX_HULL))
+                               {
+                                       continue;
+                               }
+
+                               float dmin = FLT_MAX;
+
+                               b3ConvexPolyhedronData* convexShapeA = &hostConvexShapeData[shapeIndexA];
+                               b3ConvexPolyhedronData* convexShapeB = &hostConvexShapeData[shapeIndexB];
+                               b3Vector3 posA = hostBodyBuf[bodyIndexA].m_pos;
+                               b3Vector3 posB = hostBodyBuf[bodyIndexB].m_pos;
+                               b3Quaternion ornA = hostBodyBuf[bodyIndexA].m_quat;
+                               b3Quaternion ornB = hostBodyBuf[bodyIndexB].m_quat;
+
+                               if (useGjk)
+                               {
+                                       //first approximate the separating axis, to 'fail-proof' GJK+EPA or MPR
+                                       {
+                                               b3Vector3 c0local = hostConvexShapeData[shapeIndexA].m_localCenter;
+                                               b3Vector3 c0 = b3TransformPoint(c0local, posA, ornA);
+                                               b3Vector3 c1local = hostConvexShapeData[shapeIndexB].m_localCenter;
+                                               b3Vector3 c1 = b3TransformPoint(c1local, posB, ornB);
+                                               b3Vector3 DeltaC2 = c0 - c1;
+
+                                               b3Vector3 sepAxis;
+
+                                               bool hasSepAxisA = b3FindSeparatingAxis(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
+                                                                                                                               &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                               &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                               &sepAxis, &dmin);
+
+                                               if (hasSepAxisA)
+                                               {
+                                                       bool hasSepAxisB = b3FindSeparatingAxis(convexShapeB, convexShapeA, posB, ornB, posA, ornA, DeltaC2,
+                                                                                                                                       &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                                       &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                                       &sepAxis, &dmin);
+                                                       if (hasSepAxisB)
+                                                       {
+                                                               bool hasEdgeEdge = b3FindSeparatingAxisEdgeEdge(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
+                                                                                                                                                               &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                                                               &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                                                               &sepAxis, &dmin, false);
+
+                                                               if (hasEdgeEdge)
+                                                               {
+                                                                       hostHasSepAxis[i] = 1;
+                                                                       hostSepAxis[i] = sepAxis;
+                                                                       hostSepAxis[i].w = dmin;
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       if (hostHasSepAxis[i])
+                                       {
+                                               int pairIndex = i;
+
+                                               bool useMpr = true;
+                                               if (useMpr)
+                                               {
+                                                       int res = 0;
+                                                       float depth = 0.f;
+                                                       b3Vector3 sepAxis2 = b3MakeVector3(1, 0, 0);
+                                                       b3Vector3 resultPointOnBWorld = b3MakeVector3(0, 0, 0);
+
+                                                       float depthOut;
+                                                       b3Vector3 dirOut;
+                                                       b3Vector3 posOut;
+
+                                                       //res = b3MprPenetration(bodyIndexA,bodyIndexB,hostBodyBuf,hostConvexShapeData,hostCollidables,hostVertices,&mprConfig,&depthOut,&dirOut,&posOut);
+                                                       res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB, &hostBodyBuf[0], &hostConvexShapeData[0], &hostCollidables[0], &hostVertices[0], &hostSepAxis[0], &hostHasSepAxis[0], &depthOut, &dirOut, &posOut);
+                                                       depth = depthOut;
+                                                       sepAxis2 = b3MakeVector3(-dirOut.x, -dirOut.y, -dirOut.z);
+                                                       resultPointOnBWorld = posOut;
+                                                       //hostHasSepAxis[i] = 0;
+
+                                                       if (res == 0)
+                                                       {
+                                                               //add point?
+                                                               //printf("depth = %f\n",depth);
+                                                               //printf("normal = %f,%f,%f\n",dir.v[0],dir.v[1],dir.v[2]);
+                                                               //qprintf("pos = %f,%f,%f\n",pos.v[0],pos.v[1],pos.v[2]);
+
+                                                               float dist = 0.f;
+
+                                                               const b3ConvexPolyhedronData& hullA = hostConvexShapeData[hostCollidables[hostBodyBuf[bodyIndexA].m_collidableIdx].m_shapeIndex];
+                                                               const b3ConvexPolyhedronData& hullB = hostConvexShapeData[hostCollidables[hostBodyBuf[bodyIndexB].m_collidableIdx].m_shapeIndex];
+
+                                                               if (b3TestSepAxis(&hullA, &hullB, posA, ornA, posB, ornB, &sepAxis2, &hostVertices[0], &hostVertices[0], &dist))
+                                                               {
+                                                                       if (depth > dist)
+                                                                       {
+                                                                               float diff = depth - dist;
+
+                                                                               static float maxdiff = 0.f;
+                                                                               if (maxdiff < diff)
+                                                                               {
+                                                                                       maxdiff = diff;
+                                                                                       printf("maxdiff = %20.10f\n", maxdiff);
+                                                                               }
+                                                                       }
+                                                               }
+                                                               if (depth > dmin)
+                                                               {
+                                                                       b3Vector3 oldAxis = hostSepAxis[i];
+                                                                       depth = dmin;
+                                                                       sepAxis2 = oldAxis;
+                                                               }
+
+                                                               if (b3TestSepAxis(&hullA, &hullB, posA, ornA, posB, ornB, &sepAxis2, &hostVertices[0], &hostVertices[0], &dist))
+                                                               {
+                                                                       if (depth > dist)
+                                                                       {
+                                                                               float diff = depth - dist;
+                                                                               //printf("?diff  = %f\n",diff );
+                                                                               static float maxdiff = 0.f;
+                                                                               if (maxdiff < diff)
+                                                                               {
+                                                                                       maxdiff = diff;
+                                                                                       printf("maxdiff = %20.10f\n", maxdiff);
+                                                                               }
+                                                                       }
+                                                                       //this is used for SAT
+                                                                       //hostHasSepAxis[i] = 1;
+                                                                       //hostSepAxis[i] = sepAxis2;
+
+                                                                       //add contact point
+
+                                                                       //int contactIndex = nGlobalContactsOut;
+                                                                       b3Contact4& newContact = hostContacts.at(nGlobalContactsOut);
+                                                                       nGlobalContactsOut++;
+                                                                       newContact.m_batchIdx = 0;  //i;
+                                                                       newContact.m_bodyAPtrAndSignBit = (hostBodyBuf.at(bodyIndexA).m_invMass == 0) ? -bodyIndexA : bodyIndexA;
+                                                                       newContact.m_bodyBPtrAndSignBit = (hostBodyBuf.at(bodyIndexB).m_invMass == 0) ? -bodyIndexB : bodyIndexB;
+
+                                                                       newContact.m_frictionCoeffCmp = 45874;
+                                                                       newContact.m_restituitionCoeffCmp = 0;
+
+                                                                       static float maxDepth = 0.f;
+
+                                                                       if (depth > maxDepth)
+                                                                       {
+                                                                               maxDepth = depth;
+                                                                               printf("MPR maxdepth = %f\n", maxDepth);
+                                                                       }
+
+                                                                       resultPointOnBWorld.w = -depth;
+                                                                       newContact.m_worldPosB[0] = resultPointOnBWorld;
+                                                                       //b3Vector3 resultPointOnAWorld = resultPointOnBWorld+depth*sepAxis2;
+                                                                       newContact.m_worldNormalOnB = sepAxis2;
+                                                                       newContact.m_worldNormalOnB.w = (b3Scalar)1;
+                                                               }
+                                                               else
+                                                               {
+                                                                       printf("rejected\n");
+                                                               }
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       //int contactIndex = computeContactConvexConvex2(           i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf, hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
+                                                       b3AlignedObjectArray<b3Contact4> oldHostContacts;
+                                                       int result;
+                                                       result = computeContactConvexConvex2(  //hostPairs,
+                                                               pairIndex,
+                                                               bodyIndexA, bodyIndexB,
+                                                               collidableIndexA, collidableIndexB,
+                                                               hostBodyBuf,
+                                                               hostCollidables,
+                                                               hostConvexShapeData,
+                                                               hostVertices,
+                                                               hostUniqueEdges,
+                                                               hostIndices,
+                                                               hostFaces,
+                                                               hostContacts,
+                                                               nGlobalContactsOut,
+                                                               maxContactCapacity,
+                                                               oldHostContacts
+                                                               //hostHasSepAxis,
+                                                               //hostSepAxis
+
+                                                       );
+                                               }  //mpr
+                                       }      //hostHasSepAxis[i] = 1;
+                               }
+                               else
+                               {
+                                       b3Vector3 c0local = hostConvexShapeData[shapeIndexA].m_localCenter;
+                                       b3Vector3 c0 = b3TransformPoint(c0local, posA, ornA);
+                                       b3Vector3 c1local = hostConvexShapeData[shapeIndexB].m_localCenter;
+                                       b3Vector3 c1 = b3TransformPoint(c1local, posB, ornB);
+                                       b3Vector3 DeltaC2 = c0 - c1;
+
+                                       b3Vector3 sepAxis;
+
+                                       bool hasSepAxisA = b3FindSeparatingAxis(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
+                                                                                                                       &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                       &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                       &sepAxis, &dmin);
+
+                                       if (hasSepAxisA)
+                                       {
+                                               bool hasSepAxisB = b3FindSeparatingAxis(convexShapeB, convexShapeA, posB, ornB, posA, ornA, DeltaC2,
+                                                                                                                               &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                               &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                               &sepAxis, &dmin);
+                                               if (hasSepAxisB)
+                                               {
+                                                       bool hasEdgeEdge = b3FindSeparatingAxisEdgeEdge(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
+                                                                                                                                                       &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                                                       &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
+                                                                                                                                                       &sepAxis, &dmin, true);
+
+                                                       if (hasEdgeEdge)
+                                                       {
+                                                               hostHasSepAxis[i] = 1;
+                                                               hostSepAxis[i] = sepAxis;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (useGjkContacts)  //nGlobalContactsOut>0)
+                       {
+                               //printf("nGlobalContactsOut=%d\n",nGlobalContactsOut);
+                               nContacts = nGlobalContactsOut;
+                               contactOut->copyFromHost(hostContacts);
+
+                               m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
+                       }
+
+                       m_hasSeparatingNormals.copyFromHost(hostHasSepAxis);
+                       m_sepNormals.copyFromHost(hostSepAxis);
+
+                       /*
+             //double-check results from GPU (comment-out the 'else' so both paths are executed
+            b3AlignedObjectArray<int> checkHasSepAxis;
+            m_hasSeparatingNormals.copyToHost(checkHasSepAxis);
+            static int frameCount = 0;
+            frameCount++;
+            for (int i=0;i<nPairs;i++)
+            {
+                if (hostHasSepAxis[i] != checkHasSepAxis[i])
+                {
+                    printf("at frameCount %d hostHasSepAxis[%d] = %d but checkHasSepAxis[i] = %d\n",
+                           frameCount,i,hostHasSepAxis[i],checkHasSepAxis[i]);
+                }
+            }
+            //m_hasSeparatingNormals.copyFromHost(hostHasSepAxis);
+            //    m_sepNormals.copyFromHost(hostSepAxis);
+            */
+               }
+
+               numCompoundPairs = m_numCompoundPairsOut.at(0);
+               bool useGpuFindCompoundPairs = true;
+               if (useGpuFindCompoundPairs)
+               {
+                       B3_PROFILE("findCompoundPairsKernel");
+                       b3BufferInfoCL bInfo[] =
+                               {
+                                       b3BufferInfoCL(pairs->getBufferCL(), true),
+                                       b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                       b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                       b3BufferInfoCL(convexData.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                       b3BufferInfoCL(clAabbsLocalSpace.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+                                       b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL()),
+                                       b3BufferInfoCL(m_numCompoundPairsOut.getBufferCL()),
+                                       b3BufferInfoCL(subTreesGPU->getBufferCL()),
+                                       b3BufferInfoCL(treeNodesGPU->getBufferCL()),
+                                       b3BufferInfoCL(bvhInfo->getBufferCL())};
+
+                       b3LauncherCL launcher(m_queue, m_findCompoundPairsKernel, "m_findCompoundPairsKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(nPairs);
+                       launcher.setConst(compoundPairCapacity);
+
+                       int num = nPairs;
+                       launcher.launch1D(num);
+                       clFinish(m_queue);
+
+                       numCompoundPairs = m_numCompoundPairsOut.at(0);
+                       //printf("numCompoundPairs =%d\n",numCompoundPairs );
+                       if (numCompoundPairs)
+                       {
+                               //printf("numCompoundPairs=%d\n",numCompoundPairs);
+                       }
+               }
+               else
+               {
+                       b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
+                       treeNodesGPU->copyToHost(treeNodesCPU);
+
+                       b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
+                       subTreesGPU->copyToHost(subTreesCPU);
+
+                       b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
+                       bvhInfo->copyToHost(bvhInfoCPU);
+
+                       b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+                       clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+
+                       b3AlignedObjectArray<b3Aabb> hostAabbsLocalSpace;
+                       clAabbsLocalSpace.copyToHost(hostAabbsLocalSpace);
+
+                       b3AlignedObjectArray<b3Int4> hostPairs;
+                       pairs->copyToHost(hostPairs);
+
+                       b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+                       bodyBuf->copyToHost(hostBodyBuf);
+
+                       b3AlignedObjectArray<b3Int4> cpuCompoundPairsOut;
+                       cpuCompoundPairsOut.resize(compoundPairCapacity);
+
+                       b3AlignedObjectArray<b3Collidable> hostCollidables;
+                       gpuCollidables.copyToHost(hostCollidables);
+
+                       b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+                       gpuChildShapes.copyToHost(cpuChildShapes);
+
+                       b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+                       convexData.copyToHost(hostConvexData);
+
+                       b3AlignedObjectArray<b3Vector3> hostVertices;
+                       gpuVertices.copyToHost(hostVertices);
+
+                       for (int pairIndex = 0; pairIndex < nPairs; pairIndex++)
+                       {
+                               int bodyIndexA = hostPairs[pairIndex].x;
+                               int bodyIndexB = hostPairs[pairIndex].y;
+                               int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+                               int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+                               if (cpuChildShapes.size())
+                               {
+                                       findCompoundPairsKernel(
+                                               pairIndex,
+                                               bodyIndexA,
+                                               bodyIndexB,
+                                               collidableIndexA,
+                                               collidableIndexB,
+                                               &hostBodyBuf[0],
+                                               &hostCollidables[0],
+                                               &hostConvexData[0],
+                                               hostVertices,
+                                               hostAabbsWorldSpace,
+                                               hostAabbsLocalSpace,
+                                               &cpuChildShapes[0],
+                                               &cpuCompoundPairsOut[0],
+                                               &numCompoundPairs,
+                                               compoundPairCapacity,
+                                               treeNodesCPU,
+                                               subTreesCPU,
+                                               bvhInfoCPU);
+                               }
+                       }
+
+                       m_numCompoundPairsOut.copyFromHostPointer(&numCompoundPairs, 1, 0, true);
+                       if (numCompoundPairs)
+                       {
+                               b3CompoundOverlappingPair* ptr = (b3CompoundOverlappingPair*)&cpuCompoundPairsOut[0];
+                               m_gpuCompoundPairs.copyFromHostPointer(ptr, numCompoundPairs, 0, true);
+                       }
+                       //cpuCompoundPairsOut
+               }
+               if (numCompoundPairs)
+               {
+                       printf("numCompoundPairs=%d\n", numCompoundPairs);
+               }
+
+               if (numCompoundPairs > compoundPairCapacity)
+               {
+                       b3Error("Exceeded compound pair capacity (%d/%d)\n", numCompoundPairs, compoundPairCapacity);
+                       numCompoundPairs = compoundPairCapacity;
+               }
+
+               m_gpuCompoundPairs.resize(numCompoundPairs);
+               m_gpuHasCompoundSepNormals.resize(numCompoundPairs);
+               m_gpuCompoundSepNormals.resize(numCompoundPairs);
+
+               if (numCompoundPairs)
+               {
+                       B3_PROFILE("processCompoundPairsPrimitivesKernel");
+                       b3BufferInfoCL bInfo[] =
+                               {
+                                       b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL(), true),
+                                       b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                       b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                       b3BufferInfoCL(convexData.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                       b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+                                       b3BufferInfoCL(contactOut->getBufferCL()),
+                                       b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+                       b3LauncherCL launcher(m_queue, m_processCompoundPairsPrimitivesKernel, "m_processCompoundPairsPrimitivesKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numCompoundPairs);
+                       launcher.setConst(maxContactCapacity);
+
+                       int num = numCompoundPairs;
+                       launcher.launch1D(num);
+                       clFinish(m_queue);
+                       nContacts = m_totalContactsOut.at(0);
+                       //printf("nContacts (after processCompoundPairsPrimitivesKernel) = %d\n",nContacts);
+                       if (nContacts > maxContactCapacity)
+                       {
+                               b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
+                               nContacts = maxContactCapacity;
+                       }
+               }
+
+               if (numCompoundPairs)
+               {
+                       B3_PROFILE("processCompoundPairsKernel");
+                       b3BufferInfoCL bInfo[] =
+                               {
+                                       b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL(), true),
+                                       b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                       b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                       b3BufferInfoCL(convexData.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                       b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+                                       b3BufferInfoCL(m_gpuCompoundSepNormals.getBufferCL()),
+                                       b3BufferInfoCL(m_gpuHasCompoundSepNormals.getBufferCL())};
+
+                       b3LauncherCL launcher(m_queue, m_processCompoundPairsKernel, "m_processCompoundPairsKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numCompoundPairs);
+
+                       int num = numCompoundPairs;
+                       launcher.launch1D(num);
+                       clFinish(m_queue);
+               }
+
+               //printf("numConcave  = %d\n",numConcave);
+
+               //              printf("hostNormals.size()=%d\n",hostNormals.size());
+               //int numPairs = pairCount.at(0);
+       }
+       int vertexFaceCapacity = 64;
+
+       {
+               //now perform the tree query on GPU
+
+               if (treeNodesGPU->size() && treeNodesGPU->size())
+               {
+                       if (bvhTraversalKernelGPU)
+                       {
+                               B3_PROFILE("m_bvhTraversalKernel");
+
+                               numConcavePairs = m_numConcavePairsOut.at(0);
+
+                               b3LauncherCL launcher(m_queue, m_bvhTraversalKernel, "m_bvhTraversalKernel");
+                               launcher.setBuffer(pairs->getBufferCL());
+                               launcher.setBuffer(bodyBuf->getBufferCL());
+                               launcher.setBuffer(gpuCollidables.getBufferCL());
+                               launcher.setBuffer(clAabbsWorldSpace.getBufferCL());
+                               launcher.setBuffer(triangleConvexPairsOut.getBufferCL());
+                               launcher.setBuffer(m_numConcavePairsOut.getBufferCL());
+                               launcher.setBuffer(subTreesGPU->getBufferCL());
+                               launcher.setBuffer(treeNodesGPU->getBufferCL());
+                               launcher.setBuffer(bvhInfo->getBufferCL());
+
+                               launcher.setConst(nPairs);
+                               launcher.setConst(maxTriConvexPairCapacity);
+                               int num = nPairs;
+                               launcher.launch1D(num);
+                               clFinish(m_queue);
+                               numConcavePairs = m_numConcavePairsOut.at(0);
+                       }
+                       else
+                       {
+                               b3AlignedObjectArray<b3Int4> hostPairs;
+                               pairs->copyToHost(hostPairs);
+                               b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+                               bodyBuf->copyToHost(hostBodyBuf);
+                               b3AlignedObjectArray<b3Collidable> hostCollidables;
+                               gpuCollidables.copyToHost(hostCollidables);
+                               b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+                               clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+
+                               //int maxTriConvexPairCapacity,
+                               b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
+                               triangleConvexPairsOutHost.resize(maxTriConvexPairCapacity);
+
+                               //int numTriConvexPairsOutHost=0;
+                               numConcavePairs = 0;
+                               //m_numConcavePairsOut
+
+                               b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
+                               treeNodesGPU->copyToHost(treeNodesCPU);
+                               b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
+                               subTreesGPU->copyToHost(subTreesCPU);
+                               b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
+                               bvhInfo->copyToHost(bvhInfoCPU);
+                               //compute it...
+
+                               volatile int hostNumConcavePairsOut = 0;
+
+                               //
+                               for (int i = 0; i < nPairs; i++)
+                               {
+                                       b3BvhTraversal(&hostPairs.at(0),
+                                                                  &hostBodyBuf.at(0),
+                                                                  &hostCollidables.at(0),
+                                                                  &hostAabbsWorldSpace.at(0),
+                                                                  &triangleConvexPairsOutHost.at(0),
+                                                                  &hostNumConcavePairsOut,
+                                                                  &subTreesCPU.at(0),
+                                                                  &treeNodesCPU.at(0),
+                                                                  &bvhInfoCPU.at(0),
+                                                                  nPairs,
+                                                                  maxTriConvexPairCapacity,
+                                                                  i);
+                               }
+                               numConcavePairs = hostNumConcavePairsOut;
+
+                               if (hostNumConcavePairsOut)
+                               {
+                                       triangleConvexPairsOutHost.resize(hostNumConcavePairsOut);
+                                       triangleConvexPairsOut.copyFromHost(triangleConvexPairsOutHost);
+                               }
+                               //
+
+                               m_numConcavePairsOut.resize(0);
+                               m_numConcavePairsOut.push_back(numConcavePairs);
+                       }
+
+                       //printf("numConcavePairs=%d (max = %d\n",numConcavePairs,maxTriConvexPairCapacity);
+
+                       if (numConcavePairs > maxTriConvexPairCapacity)
+                       {
+                               static int exceeded_maxTriConvexPairCapacity_count = 0;
+                               b3Error("Exceeded the maxTriConvexPairCapacity (found %d but max is %d, it happened %d times)\n",
+                                               numConcavePairs, maxTriConvexPairCapacity, exceeded_maxTriConvexPairCapacity_count++);
+                               numConcavePairs = maxTriConvexPairCapacity;
+                       }
+                       triangleConvexPairsOut.resize(numConcavePairs);
+
+                       if (numConcavePairs)
+                       {
+                               clippingFacesOutGPU.resize(numConcavePairs);
+                               worldNormalsAGPU.resize(numConcavePairs);
+                               worldVertsA1GPU.resize(vertexFaceCapacity * (numConcavePairs));
+                               worldVertsB1GPU.resize(vertexFaceCapacity * (numConcavePairs));
+
+                               if (findConcaveSeparatingAxisKernelGPU)
+                               {
+                                       /*
+                                       m_concaveHasSeparatingNormals.copyFromHost(concaveHasSeparatingNormalsCPU);
+                                               clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
+                                               worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
+                                               worldNormalsAGPU.copyFromHost(worldNormalsACPU);
+                                               worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
+                                       */
+
+                                       //now perform a SAT test for each triangle-convex element (stored in triangleConvexPairsOut)
+                                       if (splitSearchSepAxisConcave)
+                                       {
+                                               //printf("numConcavePairs = %d\n",numConcavePairs);
+                                               m_dmins.resize(numConcavePairs);
+                                               {
+                                                       B3_PROFILE("findConcaveSeparatingAxisVertexFaceKernel");
+                                                       b3BufferInfoCL bInfo[] = {
+                                                               b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
+                                                               b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                                               b3BufferInfoCL(convexData.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+                                                               b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+                                                               b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+                                                               b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
+                                                               b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+                                                               b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+                                                               b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+                                                               b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
+                                                               b3BufferInfoCL(m_dmins.getBufferCL())};
+
+                                                       b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisVertexFaceKernel, "m_findConcaveSeparatingAxisVertexFaceKernel");
+                                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                                       launcher.setConst(vertexFaceCapacity);
+                                                       launcher.setConst(numConcavePairs);
+
+                                                       int num = numConcavePairs;
+                                                       launcher.launch1D(num);
+                                                       clFinish(m_queue);
+                                               }
+                                               //                        numConcavePairs = 0;
+                                               if (1)
+                                               {
+                                                       B3_PROFILE("findConcaveSeparatingAxisEdgeEdgeKernel");
+                                                       b3BufferInfoCL bInfo[] = {
+                                                               b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
+                                                               b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                                               b3BufferInfoCL(convexData.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                                               b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+                                                               b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+                                                               b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+                                                               b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
+                                                               b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+                                                               b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+                                                               b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+                                                               b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
+                                                               b3BufferInfoCL(m_dmins.getBufferCL())};
+
+                                                       b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisEdgeEdgeKernel, "m_findConcaveSeparatingAxisEdgeEdgeKernel");
+                                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                                       launcher.setConst(vertexFaceCapacity);
+                                                       launcher.setConst(numConcavePairs);
+
+                                                       int num = numConcavePairs;
+                                                       launcher.launch1D(num);
+                                                       clFinish(m_queue);
+                                               }
+
+                                               // numConcavePairs = 0;
+                                       }
+                                       else
+                                       {
+                                               B3_PROFILE("findConcaveSeparatingAxisKernel");
+                                               b3BufferInfoCL bInfo[] = {
+                                                       b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
+                                                       b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                                       b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                                       b3BufferInfoCL(convexData.getBufferCL(), true),
+                                                       b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                                       b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                                       b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                                       b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                                       b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+                                                       b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+                                                       b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+                                                       b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
+                                                       b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldVertsB1GPU.getBufferCL())};
+
+                                               b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisKernel, "m_findConcaveSeparatingAxisKernel");
+                                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                               launcher.setConst(vertexFaceCapacity);
+                                               launcher.setConst(numConcavePairs);
+
+                                               int num = numConcavePairs;
+                                               launcher.launch1D(num);
+                                               clFinish(m_queue);
+                                       }
+                               }
+                               else
+                               {
+                                       b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
+                                       b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
+                                       b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+                                       b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+                                       b3AlignedObjectArray<int> concaveHasSeparatingNormalsCPU;
+
+                                       b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
+                                       triangleConvexPairsOut.copyToHost(triangleConvexPairsOutHost);
+                                       //triangleConvexPairsOutHost.resize(maxTriConvexPairCapacity);
+                                       b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+                                       bodyBuf->copyToHost(hostBodyBuf);
+                                       b3AlignedObjectArray<b3Collidable> hostCollidables;
+                                       gpuCollidables.copyToHost(hostCollidables);
+                                       b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
+                                       clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
+
+                                       b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+                                       convexData.copyToHost(hostConvexData);
+
+                                       b3AlignedObjectArray<b3Vector3> hostVertices;
+                                       gpuVertices.copyToHost(hostVertices);
+
+                                       b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
+                                       gpuUniqueEdges.copyToHost(hostUniqueEdges);
+                                       b3AlignedObjectArray<b3GpuFace> hostFaces;
+                                       gpuFaces.copyToHost(hostFaces);
+                                       b3AlignedObjectArray<int> hostIndices;
+                                       gpuIndices.copyToHost(hostIndices);
+                                       b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
+                                       gpuChildShapes.copyToHost(cpuChildShapes);
+
+                                       b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
+                                       m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
+                                       concaveHasSeparatingNormalsCPU.resize(concaveSepNormalsHost.size());
+
+                                       b3GpuChildShape* childShapePointerCPU = 0;
+                                       if (cpuChildShapes.size())
+                                               childShapePointerCPU = &cpuChildShapes.at(0);
+
+                                       clippingFacesOutCPU.resize(clippingFacesOutGPU.size());
+                                       worldVertsA1CPU.resize(worldVertsA1GPU.size());
+                                       worldNormalsACPU.resize(worldNormalsAGPU.size());
+                                       worldVertsB1CPU.resize(worldVertsB1GPU.size());
+
+                                       for (int i = 0; i < numConcavePairs; i++)
+                                       {
+                                               b3FindConcaveSeparatingAxisKernel(&triangleConvexPairsOutHost.at(0),
+                                                                                                                 &hostBodyBuf.at(0),
+                                                                                                                 &hostCollidables.at(0),
+                                                                                                                 &hostConvexData.at(0), &hostVertices.at(0), &hostUniqueEdges.at(0),
+                                                                                                                 &hostFaces.at(0), &hostIndices.at(0), childShapePointerCPU,
+                                                                                                                 &hostAabbsWorldSpace.at(0),
+                                                                                                                 &concaveSepNormalsHost.at(0),
+                                                                                                                 &clippingFacesOutCPU.at(0),
+                                                                                                                 &worldVertsA1CPU.at(0),
+                                                                                                                 &worldNormalsACPU.at(0),
+                                                                                                                 &worldVertsB1CPU.at(0),
+                                                                                                                 &concaveHasSeparatingNormalsCPU.at(0),
+                                                                                                                 vertexFaceCapacity,
+                                                                                                                 numConcavePairs, i);
+                                       };
+
+                                       m_concaveSepNormals.copyFromHost(concaveSepNormalsHost);
+                                       m_concaveHasSeparatingNormals.copyFromHost(concaveHasSeparatingNormalsCPU);
+                                       clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
+                                       worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
+                                       worldNormalsAGPU.copyFromHost(worldNormalsACPU);
+                                       worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
+                               }
+                               //                                                      b3AlignedObjectArray<b3Vector3> cpuCompoundSepNormals;
+                               //                                              m_concaveSepNormals.copyToHost(cpuCompoundSepNormals);
+                               //                                      b3AlignedObjectArray<b3Int4> cpuConcavePairs;
+                               //                              triangleConvexPairsOut.copyToHost(cpuConcavePairs);
+                       }
+               }
+       }
+
+       if (numConcavePairs)
+       {
+               if (numConcavePairs)
+               {
+                       B3_PROFILE("findConcaveSphereContactsKernel");
+                       nContacts = m_totalContactsOut.at(0);
+                       //                              printf("nContacts1 = %d\n",nContacts);
+                       b3BufferInfoCL bInfo[] = {
+                               b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
+                               b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                               b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                               b3BufferInfoCL(convexData.getBufferCL(), true),
+                               b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                               b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                               b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                               b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                               b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
+                               b3BufferInfoCL(contactOut->getBufferCL()),
+                               b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+                       b3LauncherCL launcher(m_queue, m_findConcaveSphereContactsKernel, "m_findConcaveSphereContactsKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+
+                       launcher.setConst(numConcavePairs);
+                       launcher.setConst(maxContactCapacity);
+
+                       int num = numConcavePairs;
+                       launcher.launch1D(num);
+                       clFinish(m_queue);
+                       nContacts = m_totalContactsOut.at(0);
+                       //printf("nContacts (after findConcaveSphereContactsKernel) = %d\n",nContacts);
+
+                       //printf("nContacts2 = %d\n",nContacts);
+
+                       if (nContacts >= maxContactCapacity)
+                       {
+                               b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
+                               nContacts = maxContactCapacity;
+                       }
+               }
+       }
+
+#ifdef __APPLE__
+       bool contactClippingOnGpu = true;
+#else
+       bool contactClippingOnGpu = true;
+#endif
+
+       if (contactClippingOnGpu)
+       {
+               m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
+               //              printf("nContacts3 = %d\n",nContacts);
+
+               //B3_PROFILE("clipHullHullKernel");
+
+               bool breakupConcaveConvexKernel = true;
+
+#ifdef __APPLE__
+               //actually, some Apple OpenCL platform/device combinations work fine...
+               breakupConcaveConvexKernel = true;
+#endif
+               //concave-convex contact clipping
+               if (numConcavePairs)
+               {
+                       //                      printf("numConcavePairs = %d\n", numConcavePairs);
+                       //              nContacts = m_totalContactsOut.at(0);
+                       //      printf("nContacts before = %d\n", nContacts);
+
+                       if (breakupConcaveConvexKernel)
+                       {
+                               worldVertsB2GPU.resize(vertexFaceCapacity * numConcavePairs);
+
+                               //clipFacesAndFindContacts
+
+                               if (clipConcaveFacesAndFindContactsCPU)
+                               {
+                                       b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
+                                       b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
+                                       b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+                                       b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+
+                                       clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
+                                       worldVertsA1GPU.copyToHost(worldVertsA1CPU);
+                                       worldNormalsAGPU.copyToHost(worldNormalsACPU);
+                                       worldVertsB1GPU.copyToHost(worldVertsB1CPU);
+
+                                       b3AlignedObjectArray<int> concaveHasSeparatingNormalsCPU;
+                                       m_concaveHasSeparatingNormals.copyToHost(concaveHasSeparatingNormalsCPU);
+
+                                       b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
+                                       m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
+
+                                       b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+                                       worldVertsB2CPU.resize(worldVertsB2GPU.size());
+
+                                       for (int i = 0; i < numConcavePairs; i++)
+                                       {
+                                               clipFacesAndFindContactsKernel(&concaveSepNormalsHost.at(0),
+                                                                                                          &concaveHasSeparatingNormalsCPU.at(0),
+                                                                                                          &clippingFacesOutCPU.at(0),
+                                                                                                          &worldVertsA1CPU.at(0),
+                                                                                                          &worldNormalsACPU.at(0),
+                                                                                                          &worldVertsB1CPU.at(0),
+                                                                                                          &worldVertsB2CPU.at(0),
+                                                                                                          vertexFaceCapacity,
+                                                                                                          i);
+                                       }
+
+                                       clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
+                                       worldVertsB2GPU.copyFromHost(worldVertsB2CPU);
+                               }
+                               else
+                               {
+                                       if (1)
+                                       {
+                                               B3_PROFILE("clipFacesAndFindContacts");
+                                               //nContacts = m_totalContactsOut.at(0);
+                                               //int h = m_hasSeparatingNormals.at(0);
+                                               //int4 p = clippingFacesOutGPU.at(0);
+                                               b3BufferInfoCL bInfo[] = {
+                                                       b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+                                                       b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
+                                                       b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldVertsB2GPU.getBufferCL())};
+                                               b3LauncherCL launcher(m_queue, m_clipFacesAndFindContacts, "m_clipFacesAndFindContacts");
+                                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                               launcher.setConst(vertexFaceCapacity);
+
+                                               launcher.setConst(numConcavePairs);
+                                               int debugMode = 0;
+                                               launcher.setConst(debugMode);
+                                               int num = numConcavePairs;
+                                               launcher.launch1D(num);
+                                               clFinish(m_queue);
+                                               //int bla = m_totalContactsOut.at(0);
+                                       }
+                               }
+                               //contactReduction
+                               {
+                                       int newContactCapacity = nContacts + numConcavePairs;
+                                       contactOut->reserve(newContactCapacity);
+                                       if (reduceConcaveContactsOnGPU)
+                                       {
+                                               //                                              printf("newReservation = %d\n",newReservation);
+                                               {
+                                                       B3_PROFILE("newContactReductionKernel");
+                                                       b3BufferInfoCL bInfo[] =
+                                                               {
+                                                                       b3BufferInfoCL(triangleConvexPairsOut.getBufferCL(), true),
+                                                                       b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                                                       b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+                                                                       b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
+                                                                       b3BufferInfoCL(contactOut->getBufferCL()),
+                                                                       b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+                                                                       b3BufferInfoCL(worldVertsB2GPU.getBufferCL()),
+                                                                       b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+                                                       b3LauncherCL launcher(m_queue, m_newContactReductionKernel, "m_newContactReductionKernel");
+                                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                                       launcher.setConst(vertexFaceCapacity);
+                                                       launcher.setConst(newContactCapacity);
+                                                       launcher.setConst(numConcavePairs);
+                                                       int num = numConcavePairs;
+
+                                                       launcher.launch1D(num);
+                                               }
+                                               nContacts = m_totalContactsOut.at(0);
+                                               contactOut->resize(nContacts);
+
+                                               //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
+                                       }
+                                       else
+                                       {
+                                               volatile int nGlobalContactsOut = nContacts;
+                                               b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
+                                               triangleConvexPairsOut.copyToHost(triangleConvexPairsOutHost);
+                                               b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+                                               bodyBuf->copyToHost(hostBodyBuf);
+
+                                               b3AlignedObjectArray<int> concaveHasSeparatingNormalsCPU;
+                                               m_concaveHasSeparatingNormals.copyToHost(concaveHasSeparatingNormalsCPU);
+
+                                               b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
+                                               m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
+
+                                               b3AlignedObjectArray<b3Contact4> hostContacts;
+                                               if (nContacts)
+                                               {
+                                                       contactOut->copyToHost(hostContacts);
+                                               }
+                                               hostContacts.resize(newContactCapacity);
+
+                                               b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
+                                               b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+
+                                               clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
+                                               worldVertsB2GPU.copyToHost(worldVertsB2CPU);
+
+                                               for (int i = 0; i < numConcavePairs; i++)
+                                               {
+                                                       b3NewContactReductionKernel(&triangleConvexPairsOutHost.at(0),
+                                                                                                               &hostBodyBuf.at(0),
+                                                                                                               &concaveSepNormalsHost.at(0),
+                                                                                                               &concaveHasSeparatingNormalsCPU.at(0),
+                                                                                                               &hostContacts.at(0),
+                                                                                                               &clippingFacesOutCPU.at(0),
+                                                                                                               &worldVertsB2CPU.at(0),
+                                                                                                               &nGlobalContactsOut,
+                                                                                                               vertexFaceCapacity,
+                                                                                                               newContactCapacity,
+                                                                                                               numConcavePairs,
+                                                                                                               i);
+                                               }
+
+                                               nContacts = nGlobalContactsOut;
+                                               m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
+                                               //                                              nContacts = m_totalContactsOut.at(0);
+                                               //contactOut->resize(nContacts);
+                                               hostContacts.resize(nContacts);
+                                               //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
+                                               contactOut->copyFromHost(hostContacts);
+                                       }
+                               }
+                               //re-use?
+                       }
+                       else
+                       {
+                               B3_PROFILE("clipHullHullConcaveConvexKernel");
+                               nContacts = m_totalContactsOut.at(0);
+                               int newContactCapacity = contactOut->capacity();
+
+                               //printf("contactOut5 = %d\n",nContacts);
+                               b3BufferInfoCL bInfo[] = {
+                                       b3BufferInfoCL(triangleConvexPairsOut.getBufferCL(), true),
+                                       b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                       b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                       b3BufferInfoCL(convexData.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+                                       b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
+                                       b3BufferInfoCL(contactOut->getBufferCL()),
+                                       b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+                               b3LauncherCL launcher(m_queue, m_clipHullHullConcaveConvexKernel, "m_clipHullHullConcaveConvexKernel");
+                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                               launcher.setConst(newContactCapacity);
+                               launcher.setConst(numConcavePairs);
+                               int num = numConcavePairs;
+                               launcher.launch1D(num);
+                               clFinish(m_queue);
+                               nContacts = m_totalContactsOut.at(0);
+                               contactOut->resize(nContacts);
+                               //printf("contactOut6 = %d\n",nContacts);
+                               b3AlignedObjectArray<b3Contact4> cpuContacts;
+                               contactOut->copyToHost(cpuContacts);
+                       }
+                       //                      printf("nContacts after = %d\n", nContacts);
+               }  //numConcavePairs
+
+               //convex-convex contact clipping
+
+               bool breakupKernel = false;
+
+#ifdef __APPLE__
+               breakupKernel = true;
+#endif
+
+#ifdef CHECK_ON_HOST
+               bool computeConvexConvex = false;
+#else
+               bool computeConvexConvex = true;
+#endif  //CHECK_ON_HOST
+               if (computeConvexConvex)
+               {
+                       B3_PROFILE("clipHullHullKernel");
+                       if (breakupKernel)
+                       {
+                               worldVertsB1GPU.resize(vertexFaceCapacity * nPairs);
+                               clippingFacesOutGPU.resize(nPairs);
+                               worldNormalsAGPU.resize(nPairs);
+                               worldVertsA1GPU.resize(vertexFaceCapacity * nPairs);
+                               worldVertsB2GPU.resize(vertexFaceCapacity * nPairs);
+
+                               if (findConvexClippingFacesGPU)
+                               {
+                                       B3_PROFILE("findClippingFacesKernel");
+                                       b3BufferInfoCL bInfo[] = {
+                                               b3BufferInfoCL(pairs->getBufferCL(), true),
+                                               b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                               b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                               b3BufferInfoCL(convexData.getBufferCL(), true),
+                                               b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                               b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                               b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                               b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                               b3BufferInfoCL(m_sepNormals.getBufferCL()),
+                                               b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+                                               b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+                                               b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+                                               b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+                                               b3BufferInfoCL(worldVertsB1GPU.getBufferCL())};
+
+                                       b3LauncherCL launcher(m_queue, m_findClippingFacesKernel, "m_findClippingFacesKernel");
+                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                       launcher.setConst(vertexFaceCapacity);
+                                       launcher.setConst(nPairs);
+                                       int num = nPairs;
+                                       launcher.launch1D(num);
+                                       clFinish(m_queue);
+                               }
+                               else
+                               {
+                                       float minDist = -1e30f;
+                                       float maxDist = 0.02f;
+
+                                       b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
+                                       convexData.copyToHost(hostConvexData);
+                                       b3AlignedObjectArray<b3Collidable> hostCollidables;
+                                       gpuCollidables.copyToHost(hostCollidables);
+
+                                       b3AlignedObjectArray<int> hostHasSepNormals;
+                                       m_hasSeparatingNormals.copyToHost(hostHasSepNormals);
+                                       b3AlignedObjectArray<b3Vector3> cpuSepNormals;
+                                       m_sepNormals.copyToHost(cpuSepNormals);
+
+                                       b3AlignedObjectArray<b3Int4> hostPairs;
+                                       pairs->copyToHost(hostPairs);
+                                       b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+                                       bodyBuf->copyToHost(hostBodyBuf);
+
+                                       //worldVertsB1GPU.resize(vertexFaceCapacity*nPairs);
+                                       b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+                                       worldVertsB1GPU.copyToHost(worldVertsB1CPU);
+
+                                       b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
+                                       clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
+
+                                       b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+                                       worldNormalsACPU.resize(nPairs);
+
+                                       b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
+                                       worldVertsA1CPU.resize(worldVertsA1GPU.size());
+
+                                       b3AlignedObjectArray<b3Vector3> hostVertices;
+                                       gpuVertices.copyToHost(hostVertices);
+                                       b3AlignedObjectArray<b3GpuFace> hostFaces;
+                                       gpuFaces.copyToHost(hostFaces);
+                                       b3AlignedObjectArray<int> hostIndices;
+                                       gpuIndices.copyToHost(hostIndices);
+
+                                       for (int i = 0; i < nPairs; i++)
+                                       {
+                                               int bodyIndexA = hostPairs[i].x;
+                                               int bodyIndexB = hostPairs[i].y;
+
+                                               int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
+                                               int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
+
+                                               int shapeIndexA = hostCollidables[collidableIndexA].m_shapeIndex;
+                                               int shapeIndexB = hostCollidables[collidableIndexB].m_shapeIndex;
+
+                                               if (hostHasSepNormals[i])
+                                               {
+                                                       b3FindClippingFaces(cpuSepNormals[i],
+                                                                                               &hostConvexData[shapeIndexA],
+                                                                                               &hostConvexData[shapeIndexB],
+                                                                                               hostBodyBuf[bodyIndexA].m_pos, hostBodyBuf[bodyIndexA].m_quat,
+                                                                                               hostBodyBuf[bodyIndexB].m_pos, hostBodyBuf[bodyIndexB].m_quat,
+                                                                                               &worldVertsA1CPU.at(0), &worldNormalsACPU.at(0),
+                                                                                               &worldVertsB1CPU.at(0),
+                                                                                               vertexFaceCapacity, minDist, maxDist,
+                                                                                               &hostVertices.at(0), &hostFaces.at(0),
+                                                                                               &hostIndices.at(0),
+                                                                                               &hostVertices.at(0), &hostFaces.at(0),
+                                                                                               &hostIndices.at(0), &clippingFacesOutCPU.at(0), i);
+                                               }
+                                       }
+
+                                       clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
+                                       worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
+                                       worldNormalsAGPU.copyFromHost(worldNormalsACPU);
+                                       worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
+                               }
+
+                               ///clip face B against face A, reduce contacts and append them to a global contact array
+                               if (1)
+                               {
+                                       if (clipConvexFacesAndFindContactsCPU)
+                                       {
+                                               //b3AlignedObjectArray<b3Int4> hostPairs;
+                                               //pairs->copyToHost(hostPairs);
+
+                                               b3AlignedObjectArray<b3Vector3> hostSepNormals;
+                                               m_sepNormals.copyToHost(hostSepNormals);
+                                               b3AlignedObjectArray<int> hostHasSepAxis;
+                                               m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
+
+                                               b3AlignedObjectArray<b3Int4> hostClippingFaces;
+                                               clippingFacesOutGPU.copyToHost(hostClippingFaces);
+                                               b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+                                               worldVertsB2CPU.resize(vertexFaceCapacity * nPairs);
+
+                                               b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
+                                               worldVertsA1GPU.copyToHost(worldVertsA1CPU);
+                                               b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
+                                               worldNormalsAGPU.copyToHost(worldNormalsACPU);
+
+                                               b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
+                                               worldVertsB1GPU.copyToHost(worldVertsB1CPU);
+
+                                               /*
+                                         __global const b3Float4* separatingNormals,
+                                                   __global const int* hasSeparatingAxis,
+                                                   __global b3Int4* clippingFacesOut,
+                                                   __global b3Float4* worldVertsA1,
+                                                   __global b3Float4* worldNormalsA1,
+                                                   __global b3Float4* worldVertsB1,
+                                                   __global b3Float4* worldVertsB2,
+                                                    int vertexFaceCapacity,
+                                                                                                                       int pairIndex
+                                       */
+                                               for (int i = 0; i < nPairs; i++)
+                                               {
+                                                       clipFacesAndFindContactsKernel(
+                                                               &hostSepNormals.at(0),
+                                                               &hostHasSepAxis.at(0),
+                                                               &hostClippingFaces.at(0),
+                                                               &worldVertsA1CPU.at(0),
+                                                               &worldNormalsACPU.at(0),
+                                                               &worldVertsB1CPU.at(0),
+                                                               &worldVertsB2CPU.at(0),
+
+                                                               vertexFaceCapacity,
+                                                               i);
+                                               }
+
+                                               clippingFacesOutGPU.copyFromHost(hostClippingFaces);
+                                               worldVertsB2GPU.copyFromHost(worldVertsB2CPU);
+                                       }
+                                       else
+                                       {
+                                               B3_PROFILE("clipFacesAndFindContacts");
+                                               //nContacts = m_totalContactsOut.at(0);
+                                               //int h = m_hasSeparatingNormals.at(0);
+                                               //int4 p = clippingFacesOutGPU.at(0);
+                                               b3BufferInfoCL bInfo[] = {
+                                                       b3BufferInfoCL(m_sepNormals.getBufferCL()),
+                                                       b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+                                                       b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
+                                                       b3BufferInfoCL(worldVertsB2GPU.getBufferCL())};
+
+                                               b3LauncherCL launcher(m_queue, m_clipFacesAndFindContacts, "m_clipFacesAndFindContacts");
+                                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                               launcher.setConst(vertexFaceCapacity);
+
+                                               launcher.setConst(nPairs);
+                                               int debugMode = 0;
+                                               launcher.setConst(debugMode);
+                                               int num = nPairs;
+                                               launcher.launch1D(num);
+                                               clFinish(m_queue);
+                                       }
+
+                                       {
+                                               nContacts = m_totalContactsOut.at(0);
+                                               //printf("nContacts = %d\n",nContacts);
+
+                                               int newContactCapacity = nContacts + nPairs;
+                                               contactOut->reserve(newContactCapacity);
+
+                                               if (reduceConvexContactsOnGPU)
+                                               {
+                                                       {
+                                                               B3_PROFILE("newContactReductionKernel");
+                                                               b3BufferInfoCL bInfo[] =
+                                                                       {
+                                                                               b3BufferInfoCL(pairs->getBufferCL(), true),
+                                                                               b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                                                               b3BufferInfoCL(m_sepNormals.getBufferCL()),
+                                                                               b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+                                                                               b3BufferInfoCL(contactOut->getBufferCL()),
+                                                                               b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
+                                                                               b3BufferInfoCL(worldVertsB2GPU.getBufferCL()),
+                                                                               b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+
+                                                               b3LauncherCL launcher(m_queue, m_newContactReductionKernel, "m_newContactReductionKernel");
+                                                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                                               launcher.setConst(vertexFaceCapacity);
+                                                               launcher.setConst(newContactCapacity);
+                                                               launcher.setConst(nPairs);
+                                                               int num = nPairs;
+
+                                                               launcher.launch1D(num);
+                                                       }
+                                                       nContacts = m_totalContactsOut.at(0);
+                                                       contactOut->resize(nContacts);
+                                               }
+                                               else
+                                               {
+                                                       volatile int nGlobalContactsOut = nContacts;
+                                                       b3AlignedObjectArray<b3Int4> hostPairs;
+                                                       pairs->copyToHost(hostPairs);
+                                                       b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
+                                                       bodyBuf->copyToHost(hostBodyBuf);
+                                                       b3AlignedObjectArray<b3Vector3> hostSepNormals;
+                                                       m_sepNormals.copyToHost(hostSepNormals);
+                                                       b3AlignedObjectArray<int> hostHasSepAxis;
+                                                       m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
+                                                       b3AlignedObjectArray<b3Contact4> hostContactsOut;
+                                                       contactOut->copyToHost(hostContactsOut);
+                                                       hostContactsOut.resize(newContactCapacity);
+
+                                                       b3AlignedObjectArray<b3Int4> hostClippingFaces;
+                                                       clippingFacesOutGPU.copyToHost(hostClippingFaces);
+                                                       b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
+                                                       worldVertsB2GPU.copyToHost(worldVertsB2CPU);
+
+                                                       for (int i = 0; i < nPairs; i++)
+                                                       {
+                                                               b3NewContactReductionKernel(&hostPairs.at(0),
+                                                                                                                       &hostBodyBuf.at(0),
+                                                                                                                       &hostSepNormals.at(0),
+                                                                                                                       &hostHasSepAxis.at(0),
+                                                                                                                       &hostContactsOut.at(0),
+                                                                                                                       &hostClippingFaces.at(0),
+                                                                                                                       &worldVertsB2CPU.at(0),
+                                                                                                                       &nGlobalContactsOut,
+                                                                                                                       vertexFaceCapacity,
+                                                                                                                       newContactCapacity,
+                                                                                                                       nPairs,
+                                                                                                                       i);
+                                                       }
+
+                                                       nContacts = nGlobalContactsOut;
+                                                       m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
+                                                       hostContactsOut.resize(nContacts);
+                                                       //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
+                                                       contactOut->copyFromHost(hostContactsOut);
+                                               }
+                                               //                    b3Contact4 pt = contactOut->at(0);
+                                               //                  printf("nContacts = %d\n",nContacts);
+                                       }
+                               }
+                       }
+                       else  //breakupKernel
+                       {
+                               if (nPairs)
+                               {
+                                       b3BufferInfoCL bInfo[] = {
+                                               b3BufferInfoCL(pairs->getBufferCL(), true),
+                                               b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                               b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                               b3BufferInfoCL(convexData.getBufferCL(), true),
+                                               b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                               b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                               b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                               b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                               b3BufferInfoCL(m_sepNormals.getBufferCL()),
+                                               b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
+                                               b3BufferInfoCL(contactOut->getBufferCL()),
+                                               b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+                                       b3LauncherCL launcher(m_queue, m_clipHullHullKernel, "m_clipHullHullKernel");
+                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                       launcher.setConst(nPairs);
+                                       launcher.setConst(maxContactCapacity);
+
+                                       int num = nPairs;
+                                       launcher.launch1D(num);
+                                       clFinish(m_queue);
+
+                                       nContacts = m_totalContactsOut.at(0);
+                                       if (nContacts >= maxContactCapacity)
+                                       {
+                                               b3Error("Exceeded contact capacity (%d/%d)\n", nContacts, maxContactCapacity);
+                                               nContacts = maxContactCapacity;
+                                       }
+                                       contactOut->resize(nContacts);
+                               }
+                       }
+
+                       int nCompoundsPairs = m_gpuCompoundPairs.size();
+
+                       if (nCompoundsPairs)
+                       {
+                               b3BufferInfoCL bInfo[] = {
+                                       b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL(), true),
+                                       b3BufferInfoCL(bodyBuf->getBufferCL(), true),
+                                       b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
+                                       b3BufferInfoCL(convexData.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuVertices.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuFaces.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuIndices.getBufferCL(), true),
+                                       b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
+                                       b3BufferInfoCL(m_gpuCompoundSepNormals.getBufferCL(), true),
+                                       b3BufferInfoCL(m_gpuHasCompoundSepNormals.getBufferCL(), true),
+                                       b3BufferInfoCL(contactOut->getBufferCL()),
+                                       b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
+                               b3LauncherCL launcher(m_queue, m_clipCompoundsHullHullKernel, "m_clipCompoundsHullHullKernel");
+                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                               launcher.setConst(nCompoundsPairs);
+                               launcher.setConst(maxContactCapacity);
+
+                               int num = nCompoundsPairs;
+                               launcher.launch1D(num);
+                               clFinish(m_queue);
+
+                               nContacts = m_totalContactsOut.at(0);
+                               if (nContacts > maxContactCapacity)
+                               {
+                                       b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
+                                       nContacts = maxContactCapacity;
+                               }
+                               contactOut->resize(nContacts);
+                       }  //if nCompoundsPairs
+               }
+       }  //contactClippingOnGpu
+
+       //printf("nContacts end = %d\n",nContacts);
+
+       //printf("frameCount = %d\n",frameCount++);
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h
new file mode 100644 (file)
index 0000000..53e8c4e
--- /dev/null
@@ -0,0 +1,106 @@
+
+#ifndef _CONVEX_HULL_CONTACT_H
+#define _CONVEX_HULL_CONTACT_H
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#include "b3OptimizedBvh.h"
+#include "b3BvhInfo.h"
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+
+//#include "../../dynamics/basic_demo/Stubs/ChNarrowPhase.h"
+
+struct GpuSatCollision
+{
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_queue;
+       cl_kernel m_findSeparatingAxisKernel;
+       cl_kernel m_mprPenetrationKernel;
+       cl_kernel m_findSeparatingAxisUnitSphereKernel;
+
+       cl_kernel m_findSeparatingAxisVertexFaceKernel;
+       cl_kernel m_findSeparatingAxisEdgeEdgeKernel;
+
+       cl_kernel m_findConcaveSeparatingAxisKernel;
+       cl_kernel m_findConcaveSeparatingAxisVertexFaceKernel;
+       cl_kernel m_findConcaveSeparatingAxisEdgeEdgeKernel;
+
+       cl_kernel m_findCompoundPairsKernel;
+       cl_kernel m_processCompoundPairsKernel;
+
+       cl_kernel m_clipHullHullKernel;
+       cl_kernel m_clipCompoundsHullHullKernel;
+
+       cl_kernel m_clipFacesAndFindContacts;
+       cl_kernel m_findClippingFacesKernel;
+
+       cl_kernel m_clipHullHullConcaveConvexKernel;
+       //      cl_kernel                               m_extractManifoldAndAddContactKernel;
+       cl_kernel m_newContactReductionKernel;
+
+       cl_kernel m_bvhTraversalKernel;
+       cl_kernel m_primitiveContactsKernel;
+       cl_kernel m_findConcaveSphereContactsKernel;
+
+       cl_kernel m_processCompoundPairsPrimitivesKernel;
+
+       b3OpenCLArray<b3Vector3> m_unitSphereDirections;
+
+       b3OpenCLArray<int> m_totalContactsOut;
+
+       b3OpenCLArray<b3Vector3> m_sepNormals;
+       b3OpenCLArray<float> m_dmins;
+
+       b3OpenCLArray<int> m_hasSeparatingNormals;
+       b3OpenCLArray<b3Vector3> m_concaveSepNormals;
+       b3OpenCLArray<int> m_concaveHasSeparatingNormals;
+       b3OpenCLArray<int> m_numConcavePairsOut;
+       b3OpenCLArray<b3CompoundOverlappingPair> m_gpuCompoundPairs;
+       b3OpenCLArray<b3Vector3> m_gpuCompoundSepNormals;
+       b3OpenCLArray<int> m_gpuHasCompoundSepNormals;
+       b3OpenCLArray<int> m_numCompoundPairsOut;
+
+       GpuSatCollision(cl_context ctx, cl_device_id device, cl_command_queue q);
+       virtual ~GpuSatCollision();
+
+       void computeConvexConvexContactsGPUSAT(b3OpenCLArray<b3Int4>* pairs, int nPairs,
+                                                                                  const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+                                                                                  b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
+                                                                                  const b3OpenCLArray<b3Contact4>* oldContacts,
+                                                                                  int maxContactCapacity,
+                                                                                  int compoundPairCapacity,
+                                                                                  const b3OpenCLArray<b3ConvexPolyhedronData>& hostConvexData,
+                                                                                  const b3OpenCLArray<b3Vector3>& vertices,
+                                                                                  const b3OpenCLArray<b3Vector3>& uniqueEdges,
+                                                                                  const b3OpenCLArray<b3GpuFace>& faces,
+                                                                                  const b3OpenCLArray<int>& indices,
+                                                                                  const b3OpenCLArray<b3Collidable>& gpuCollidables,
+                                                                                  const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
+
+                                                                                  const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
+                                                                                  const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
+
+                                                                                  b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
+                                                                                  b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
+                                                                                  b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
+                                                                                  b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
+                                                                                  b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
+                                                                                  b3AlignedObjectArray<class b3OptimizedBvh*>& bvhData,
+                                                                                  b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
+                                                                                  b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
+                                                                                  b3OpenCLArray<b3BvhInfo>* bvhInfo,
+                                                                                  int numObjects,
+                                                                                  int maxTriConvexPairCapacity,
+                                                                                  b3OpenCLArray<b3Int4>& triangleConvexPairs,
+                                                                                  int& numTriConvexPairsOut);
+};
+
+#endif  //_CONVEX_HULL_CONTACT_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h
new file mode 100644 (file)
index 0000000..c4cf700
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef CONVEX_POLYHEDRON_CL
+#define CONVEX_POLYHEDRON_CL
+
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+
+#endif  //CONVEX_POLYHEDRON_CL
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp
new file mode 100644 (file)
index 0000000..3a554fe
--- /dev/null
@@ -0,0 +1,1062 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as 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 "b3GjkEpa.h"
+
+#include "b3SupportMappings.h"
+
+namespace gjkepa2_impl2
+{
+// Config
+
+/* GJK */
+#define GJK_MAX_ITERATIONS 128
+#define GJK_ACCURACY ((b3Scalar)0.0001)
+#define GJK_MIN_DISTANCE ((b3Scalar)0.0001)
+#define GJK_DUPLICATED_EPS ((b3Scalar)0.0001)
+#define GJK_SIMPLEX2_EPS ((b3Scalar)0.0)
+#define GJK_SIMPLEX3_EPS ((b3Scalar)0.0)
+#define GJK_SIMPLEX4_EPS ((b3Scalar)0.0)
+
+/* EPA */
+#define EPA_MAX_VERTICES 64
+#define EPA_MAX_FACES (EPA_MAX_VERTICES * 2)
+#define EPA_MAX_ITERATIONS 255
+#define EPA_ACCURACY ((b3Scalar)0.0001)
+#define EPA_FALLBACK (10 * EPA_ACCURACY)
+#define EPA_PLANE_EPS ((b3Scalar)0.00001)
+#define EPA_INSIDE_EPS ((b3Scalar)0.01)
+
+// Shorthands
+
+// MinkowskiDiff
+struct b3MinkowskiDiff
+{
+       const b3ConvexPolyhedronData* m_shapes[2];
+
+       b3Matrix3x3 m_toshape1;
+       b3Transform m_toshape0;
+
+       bool m_enableMargin;
+
+       void EnableMargin(bool enable)
+       {
+               m_enableMargin = enable;
+       }
+       inline b3Vector3 Support0(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA) const
+       {
+               if (m_enableMargin)
+               {
+                       return localGetSupportVertexWithMargin(d, m_shapes[0], verticesA, 0.f);
+               }
+               else
+               {
+                       return localGetSupportVertexWithoutMargin(d, m_shapes[0], verticesA);
+               }
+       }
+       inline b3Vector3 Support1(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+       {
+               if (m_enableMargin)
+               {
+                       return m_toshape0 * (localGetSupportVertexWithMargin(m_toshape1 * d, m_shapes[1], verticesB, 0.f));
+               }
+               else
+               {
+                       return m_toshape0 * (localGetSupportVertexWithoutMargin(m_toshape1 * d, m_shapes[1], verticesB));
+               }
+       }
+
+       inline b3Vector3 Support(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+       {
+               return (Support0(d, verticesA) - Support1(-d, verticesB));
+       }
+       b3Vector3 Support(const b3Vector3& d, unsigned int index, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
+       {
+               if (index)
+                       return (Support1(d, verticesA));
+               else
+                       return (Support0(d, verticesB));
+       }
+};
+
+typedef b3MinkowskiDiff tShape;
+
+// GJK
+struct b3GJK
+{
+       /* Types                */
+       struct sSV
+       {
+               b3Vector3 d, w;
+       };
+       struct sSimplex
+       {
+               sSV* c[4];
+               b3Scalar p[4];
+               unsigned int rank;
+       };
+       struct eStatus
+       {
+               enum _
+               {
+                       Valid,
+                       Inside,
+                       Failed
+               };
+       };
+       /* Fields               */
+       tShape m_shape;
+       const b3AlignedObjectArray<b3Vector3>& m_verticesA;
+       const b3AlignedObjectArray<b3Vector3>& m_verticesB;
+       b3Vector3 m_ray;
+       b3Scalar m_distance;
+       sSimplex m_simplices[2];
+       sSV m_store[4];
+       sSV* m_free[4];
+       unsigned int m_nfree;
+       unsigned int m_current;
+       sSimplex* m_simplex;
+       eStatus::_ m_status;
+       /* Methods              */
+       b3GJK(const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB)
+               : m_verticesA(verticesA), m_verticesB(verticesB)
+       {
+               Initialize();
+       }
+       void Initialize()
+       {
+               m_ray = b3MakeVector3(0, 0, 0);
+               m_nfree = 0;
+               m_status = eStatus::Failed;
+               m_current = 0;
+               m_distance = 0;
+       }
+       eStatus::_ Evaluate(const tShape& shapearg, const b3Vector3& guess)
+       {
+               unsigned int iterations = 0;
+               b3Scalar sqdist = 0;
+               b3Scalar alpha = 0;
+               b3Vector3 lastw[4];
+               unsigned int 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 b3Scalar sqrl = m_ray.length2();
+               appendvertice(m_simplices[0], sqrl > 0 ? -m_ray : b3MakeVector3(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 unsigned int next = 1 - m_current;
+                       sSimplex& cs = m_simplices[m_current];
+                       sSimplex& ns = m_simplices[next];
+                       /* Check zero                                                   */
+                       const b3Scalar 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 b3Vector3& w = cs.c[cs.rank - 1]->w;
+                       bool found = false;
+                       for (unsigned int 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 b3Scalar omega = b3Dot(m_ray, w) / rl;
+                       alpha = b3Max(omega, alpha);
+                       if (((rl - alpha) - (GJK_ACCURACY * rl)) <= 0)
+                       { /* Return old simplex                         */
+                               removevertice(m_simplices[m_current]);
+                               break;
+                       }
+                       /* Reduce simplex                                               */
+                       b3Scalar weights[4];
+                       unsigned int 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 = b3MakeVector3(0, 0, 0);
+                               m_current = next;
+                               for (unsigned int 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;
+                       default:
+                       {
+                       }
+               }
+               return (m_status);
+       }
+       bool EncloseOrigin()
+       {
+               switch (m_simplex->rank)
+               {
+                       case 1:
+                       {
+                               for (unsigned int i = 0; i < 3; ++i)
+                               {
+                                       b3Vector3 axis = b3MakeVector3(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 b3Vector3 d = m_simplex->c[1]->w - m_simplex->c[0]->w;
+                               for (unsigned int i = 0; i < 3; ++i)
+                               {
+                                       b3Vector3 axis = b3MakeVector3(0, 0, 0);
+                                       axis[i] = 1;
+                                       const b3Vector3 p = b3Cross(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 b3Vector3 n = b3Cross(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 (b3Fabs(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 b3Vector3& d, sSV& sv) const
+       {
+               sv.d = d / d.length();
+               sv.w = m_shape.Support(sv.d, m_verticesA, m_verticesB);
+       }
+       void removevertice(sSimplex& simplex)
+       {
+               m_free[m_nfree++] = simplex.c[--simplex.rank];
+       }
+       void appendvertice(sSimplex& simplex, const b3Vector3& v)
+       {
+               simplex.p[simplex.rank] = 0;
+               simplex.c[simplex.rank] = m_free[--m_nfree];
+               getsupport(v, *simplex.c[simplex.rank++]);
+       }
+       static b3Scalar det(const b3Vector3& a, const b3Vector3& b, const b3Vector3& 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 b3Scalar projectorigin(const b3Vector3& a,
+                                                                 const b3Vector3& b,
+                                                                 b3Scalar* w, unsigned int& m)
+       {
+               const b3Vector3 d = b - a;
+               const b3Scalar l = d.length2();
+               if (l > GJK_SIMPLEX2_EPS)
+               {
+                       const b3Scalar t(l > 0 ? -b3Dot(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 b3Scalar projectorigin(const b3Vector3& a,
+                                                                 const b3Vector3& b,
+                                                                 const b3Vector3& c,
+                                                                 b3Scalar* w, unsigned int& m)
+       {
+               static const unsigned int imd3[] = {1, 2, 0};
+               const b3Vector3* vt[] = {&a, &b, &c};
+               const b3Vector3 dl[] = {a - b, b - c, c - a};
+               const b3Vector3 n = b3Cross(dl[0], dl[1]);
+               const b3Scalar l = n.length2();
+               if (l > GJK_SIMPLEX3_EPS)
+               {
+                       b3Scalar mindist = -1;
+                       b3Scalar subw[2] = {0.f, 0.f};
+                       unsigned int subm(0);
+                       for (unsigned int i = 0; i < 3; ++i)
+                       {
+                               if (b3Dot(*vt[i], b3Cross(dl[i], n)) > 0)
+                               {
+                                       const unsigned int j = imd3[i];
+                                       const b3Scalar subd(projectorigin(*vt[i], *vt[j], subw, subm));
+                                       if ((mindist < 0) || (subd < mindist))
+                                       {
+                                               mindist = subd;
+                                               m = static_cast<unsigned int>(((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 b3Scalar d = b3Dot(a, n);
+                               const b3Scalar s = b3Sqrt(l);
+                               const b3Vector3 p = n * (d / l);
+                               mindist = p.length2();
+                               m = 7;
+                               w[0] = (b3Cross(dl[1], b - p)).length() / s;
+                               w[1] = (b3Cross(dl[2], c - p)).length() / s;
+                               w[2] = 1 - (w[0] + w[1]);
+                       }
+                       return (mindist);
+               }
+               return (-1);
+       }
+       static b3Scalar projectorigin(const b3Vector3& a,
+                                                                 const b3Vector3& b,
+                                                                 const b3Vector3& c,
+                                                                 const b3Vector3& d,
+                                                                 b3Scalar* w, unsigned int& m)
+       {
+               static const unsigned int imd3[] = {1, 2, 0};
+               const b3Vector3* vt[] = {&a, &b, &c, &d};
+               const b3Vector3 dl[] = {a - d, b - d, c - d};
+               const b3Scalar vl = det(dl[0], dl[1], dl[2]);
+               const bool ng = (vl * b3Dot(a, b3Cross(b - c, a - b))) <= 0;
+               if (ng && (b3Fabs(vl) > GJK_SIMPLEX4_EPS))
+               {
+                       b3Scalar mindist = -1;
+                       b3Scalar subw[3] = {0.f, 0.f, 0.f};
+                       unsigned int subm(0);
+                       for (unsigned int i = 0; i < 3; ++i)
+                       {
+                               const unsigned int j = imd3[i];
+                               const b3Scalar s = vl * b3Dot(d, b3Cross(dl[i], dl[j]));
+                               if (s > 0)
+                               {
+                                       const b3Scalar subd = projectorigin(*vt[i], *vt[j], d, subw, subm);
+                                       if ((mindist < 0) || (subd < mindist))
+                                       {
+                                               mindist = subd;
+                                               m = static_cast<unsigned int>((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 b3EPA
+{
+       /* Types                */
+       typedef b3GJK::sSV sSV;
+       struct sFace
+       {
+               b3Vector3 n;
+               b3Scalar d;
+               sSV* c[3];
+               sFace* f[3];
+               sFace* l[2];
+               unsigned char e[3];
+               unsigned char pass;
+       };
+       struct sList
+       {
+               sFace* root;
+               unsigned int count;
+               sList() : root(0), count(0) {}
+       };
+       struct sHorizon
+       {
+               sFace* cf;
+               sFace* ff;
+               unsigned int 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;
+       b3GJK::sSimplex m_result;
+       b3Vector3 m_normal;
+       b3Scalar m_depth;
+       sSV m_sv_store[EPA_MAX_VERTICES];
+       sFace m_fc_store[EPA_MAX_FACES];
+       unsigned int m_nextsv;
+       sList m_hull;
+       sList m_stock;
+       /* Methods              */
+       b3EPA()
+       {
+               Initialize();
+       }
+
+       static inline void bind(sFace* fa, unsigned int ea, sFace* fb, unsigned int eb)
+       {
+               fa->e[ea] = (unsigned char)eb;
+               fa->f[ea] = fb;
+               fb->e[eb] = (unsigned char)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 = b3MakeVector3(0, 0, 0);
+               m_depth = 0;
+               m_nextsv = 0;
+               for (unsigned int i = 0; i < EPA_MAX_FACES; ++i)
+               {
+                       append(m_stock, &m_fc_store[EPA_MAX_FACES - i - 1]);
+               }
+       }
+       eStatus::_ Evaluate(b3GJK& gjk, const b3Vector3& guess)
+       {
+               b3GJK::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)
+                       {
+                               b3Swap(simplex.c[0], simplex.c[1]);
+                               b3Swap(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;
+                               unsigned int pass = 0;
+                               unsigned int 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 = (unsigned char)(++pass);
+                                               gjk.getsupport(best->n, *w);
+                                               const b3Scalar wdist = b3Dot(best->n, w->w) - best->d;
+                                               if (wdist > EPA_ACCURACY)
+                                               {
+                                                       for (unsigned int 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();
+                                                               outer = *best;
+                                                       }
+                                                       else
+                                                       {
+                                                               m_status = eStatus::Failed;
+                                                               //m_status=eStatus::InvalidHull;
+                                                               break;
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       m_status = eStatus::AccuraryReached;
+                                                       break;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               m_status = eStatus::OutOfVertices;
+                                               break;
+                                       }
+                               }
+                               const b3Vector3 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] = b3Cross(outer.c[1]->w - projection,
+                                                                               outer.c[2]->w - projection)
+                                                                       .length();
+                               m_result.p[1] = b3Cross(outer.c[2]->w - projection,
+                                                                               outer.c[0]->w - projection)
+                                                                       .length();
+                               m_result.p[2] = b3Cross(outer.c[0]->w - projection,
+                                                                               outer.c[1]->w - projection)
+                                                                       .length();
+                               const b3Scalar 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 b3Scalar nl = m_normal.length();
+               if (nl > 0)
+                       m_normal = m_normal / nl;
+               else
+                       m_normal = b3MakeVector3(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);
+       }
+       bool getedgedist(sFace* face, sSV* a, sSV* b, b3Scalar& dist)
+       {
+               const b3Vector3 ba = b->w - a->w;
+               const b3Vector3 n_ab = b3Cross(ba, face->n);   // Outward facing edge normal direction, on triangle plane
+               const b3Scalar a_dot_nab = b3Dot(a->w, n_ab);  // Only care about the sign to determine inside/outside, so not normalization required
+
+               if (a_dot_nab < 0)
+               {
+                       // Outside of edge a->b
+
+                       const b3Scalar ba_l2 = ba.length2();
+                       const b3Scalar a_dot_ba = b3Dot(a->w, ba);
+                       const b3Scalar b_dot_ba = b3Dot(b->w, ba);
+
+                       if (a_dot_ba > 0)
+                       {
+                               // Pick distance vertex a
+                               dist = a->w.length();
+                       }
+                       else if (b_dot_ba < 0)
+                       {
+                               // Pick distance vertex b
+                               dist = b->w.length();
+                       }
+                       else
+                       {
+                               // Pick distance to edge a->b
+                               const b3Scalar a_dot_b = b3Dot(a->w, b->w);
+                               dist = b3Sqrt(b3Max((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (b3Scalar)0));
+                       }
+
+                       return true;
+               }
+
+               return false;
+       }
+       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 = b3Cross(b->w - a->w, c->w - a->w);
+                       const b3Scalar l = face->n.length();
+                       const bool v = l > EPA_ACCURACY;
+
+                       if (v)
+                       {
+                               if (!(getedgedist(face, a, b, face->d) ||
+                                         getedgedist(face, b, c, face->d) ||
+                                         getedgedist(face, c, a, face->d)))
+                               {
+                                       // Origin projects to the interior of the triangle
+                                       // Use distance to triangle plane
+                                       face->d = b3Dot(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;
+               b3Scalar mind = minf->d * minf->d;
+               for (sFace* f = minf->l[1]; f; f = f->l[1])
+               {
+                       const b3Scalar sqd = f->d * f->d;
+                       if (sqd < mind)
+                       {
+                               minf = f;
+                               mind = sqd;
+                       }
+               }
+               return (minf);
+       }
+       bool expand(unsigned int pass, sSV* w, sFace* f, unsigned int e, sHorizon& horizon)
+       {
+               static const unsigned int i1m3[] = {1, 2, 0};
+               static const unsigned int i2m3[] = {2, 0, 1};
+               if (f->pass != pass)
+               {
+                       const unsigned int e1 = i1m3[e];
+                       if ((b3Dot(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 unsigned int e2 = i2m3[e];
+                               f->pass = (unsigned char)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 b3Transform& transA, const b3Transform& transB,
+                                          const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+                                          const b3AlignedObjectArray<b3Vector3>& verticesA,
+                                          const b3AlignedObjectArray<b3Vector3>& verticesB,
+                                          b3GjkEpaSolver2::sResults& results,
+                                          tShape& shape,
+                                          bool withmargins)
+{
+       /* Results              */
+       results.witnesses[0] =
+               results.witnesses[1] = b3MakeVector3(0, 0, 0);
+       results.status = b3GjkEpaSolver2::sResults::Separated;
+       /* Shape                */
+       shape.m_shapes[0] = hullA;
+       shape.m_shapes[1] = hullB;
+       shape.m_toshape1 = transB.getBasis().transposeTimes(transA.getBasis());
+       shape.m_toshape0 = transA.inverseTimes(transB);
+       shape.EnableMargin(withmargins);
+}
+
+}  // namespace gjkepa2_impl2
+
+//
+// Api
+//
+
+using namespace gjkepa2_impl2;
+
+//
+int b3GjkEpaSolver2::StackSizeRequirement()
+{
+       return (sizeof(b3GJK) + sizeof(b3EPA));
+}
+
+//
+bool b3GjkEpaSolver2::Distance(const b3Transform& transA, const b3Transform& transB,
+                                                          const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+                                                          const b3AlignedObjectArray<b3Vector3>& verticesA,
+                                                          const b3AlignedObjectArray<b3Vector3>& verticesB,
+                                                          const b3Vector3& guess,
+                                                          sResults& results)
+{
+       tShape shape;
+       Initialize(transA, transB, hullA, hullB, verticesA, verticesB, results, shape, false);
+       b3GJK gjk(verticesA, verticesB);
+       b3GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
+       if (gjk_status == b3GJK::eStatus::Valid)
+       {
+               b3Vector3 w0 = b3MakeVector3(0, 0, 0);
+               b3Vector3 w1 = b3MakeVector3(0, 0, 0);
+               for (unsigned int i = 0; i < gjk.m_simplex->rank; ++i)
+               {
+                       const b3Scalar p = gjk.m_simplex->p[i];
+                       w0 += shape.Support(gjk.m_simplex->c[i]->d, 0, verticesA, verticesB) * p;
+                       w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1, verticesA, verticesB) * p;
+               }
+               results.witnesses[0] = transA * w0;
+               results.witnesses[1] = transA * 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 == b3GJK::eStatus::Inside ? sResults::Penetrating : sResults::GJK_Failed;
+               return (false);
+       }
+}
+
+//
+bool b3GjkEpaSolver2::Penetration(const b3Transform& transA, const b3Transform& transB,
+                                                                 const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+                                                                 const b3AlignedObjectArray<b3Vector3>& verticesA,
+                                                                 const b3AlignedObjectArray<b3Vector3>& verticesB,
+                                                                 const b3Vector3& guess,
+                                                                 sResults& results,
+                                                                 bool usemargins)
+{
+       tShape shape;
+       Initialize(transA, transB, hullA, hullB, verticesA, verticesB, results, shape, usemargins);
+       b3GJK gjk(verticesA, verticesB);
+       b3GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
+       switch (gjk_status)
+       {
+               case b3GJK::eStatus::Inside:
+               {
+                       b3EPA epa;
+                       b3EPA::eStatus::_ epa_status = epa.Evaluate(gjk, -guess);
+                       if (epa_status != b3EPA::eStatus::Failed)
+                       {
+                               b3Vector3 w0 = b3MakeVector3(0, 0, 0);
+                               for (unsigned int i = 0; i < epa.m_result.rank; ++i)
+                               {
+                                       w0 += shape.Support(epa.m_result.c[i]->d, 0, verticesA, verticesB) * epa.m_result.p[i];
+                               }
+                               results.status = sResults::Penetrating;
+                               results.witnesses[0] = transA * w0;
+                               results.witnesses[1] = transA * (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 b3GJK::eStatus::Failed:
+                       results.status = sResults::GJK_Failed;
+                       break;
+               default:
+               {
+               }
+       }
+       return (false);
+}
+
+#if 0
+//
+b3Scalar       b3GjkEpaSolver2::SignedDistance(const b3Vector3& position,
+                                                                                       b3Scalar margin,
+                                                                                       const b3Transform&      transA,
+                                                                                       const b3ConvexPolyhedronData& hullA, 
+                                                                                       const b3AlignedObjectArray<b3Vector3>& verticesA,
+                                                                                       sResults& results)
+{
+       tShape                  shape;
+       btSphereShape   shape1(margin);
+       b3Transform             wtrs1(b3Quaternion(0,0,0,1),position);
+       Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
+       GJK                             gjk;    
+       GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,b3Vector3(1,1,1));
+       if(gjk_status==GJK::eStatus::Valid)
+       {
+               b3Vector3       w0=b3Vector3(0,0,0);
+               b3Vector3       w1=b3Vector3(0,0,0);
+               for(unsigned int i=0;i<gjk.m_simplex->rank;++i)
+               {
+                       const b3Scalar  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 b3Vector3 delta=  results.witnesses[1]-
+                       results.witnesses[0];
+               const b3Scalar  margin= shape0->getMarginNonVirtual()+
+                       shape1.getMarginNonVirtual();
+               const b3Scalar  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 b3Vector3 delta=  results.witnesses[0]-
+                                       results.witnesses[1];
+                               const b3Scalar  length= delta.length();
+                               if (length >= B3_EPSILON)
+                                       results.normal  =       delta/length;                   
+                               return(-length);
+                       }
+               }       
+       }
+       return(B3_INFINITY);
+}
+
+//
+bool   b3GjkEpaSolver2::SignedDistance(const btConvexShape*    shape0,
+                                                                               const b3Transform&              wtrs0,
+                                                                               const btConvexShape*    shape1,
+                                                                               const b3Transform&              wtrs1,
+                                                                               const b3Vector3&                guess,
+                                                                               sResults&                               results)
+{
+       if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
+               return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
+       else
+               return(true);
+}
+#endif
+
+/* Symbols cleanup             */
+
+#undef GJK_MAX_ITERATIONS
+#undef GJK_ACCURACY
+#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/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h
new file mode 100644 (file)
index 0000000..1a67a51
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as 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 B3_GJK_EPA2_H
+#define B3_GJK_EPA2_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+
+///btGjkEpaSolver contributed under zlib by Nathanael Presson
+struct b3GjkEpaSolver2
+{
+       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;
+               b3Vector3 witnesses[2];
+               b3Vector3 normal;
+               b3Scalar distance;
+       };
+
+       static int StackSizeRequirement();
+
+       static bool Distance(const b3Transform& transA, const b3Transform& transB,
+                                                const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+                                                const b3AlignedObjectArray<b3Vector3>& verticesA,
+                                                const b3AlignedObjectArray<b3Vector3>& verticesB,
+                                                const b3Vector3& guess,
+                                                sResults& results);
+
+       static bool Penetration(const b3Transform& transA, const b3Transform& transB,
+                                                       const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
+                                                       const b3AlignedObjectArray<b3Vector3>& verticesA,
+                                                       const b3AlignedObjectArray<b3Vector3>& verticesB,
+                                                       const b3Vector3& guess,
+                                                       sResults& results,
+                                                       bool usemargins = true);
+#if 0
+static b3Scalar        SignedDistance( const b3Vector3& position,
+                                                               b3Scalar 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 b3Vector3& guess,
+                                                               sResults& results);
+#endif
+};
+
+#endif  //B3_GJK_EPA2_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp
new file mode 100644 (file)
index 0000000..4938fa1
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3OptimizedBvh.h"
+#include "b3StridingMeshInterface.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+b3OptimizedBvh::b3OptimizedBvh()
+{
+}
+
+b3OptimizedBvh::~b3OptimizedBvh()
+{
+}
+
+void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax)
+{
+       m_useQuantization = useQuantizedAabbCompression;
+
+       // NodeArray    triangleNodes;
+
+       struct NodeTriangleCallback : public b3InternalTriangleIndexCallback
+       {
+               NodeArray& m_triangleNodes;
+
+               NodeTriangleCallback& operator=(NodeTriangleCallback& other)
+               {
+                       m_triangleNodes.copyFromArray(other.m_triangleNodes);
+                       return *this;
+               }
+
+               NodeTriangleCallback(NodeArray& triangleNodes)
+                       : m_triangleNodes(triangleNodes)
+               {
+               }
+
+               virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
+               {
+                       b3OptimizedBvhNode node;
+                       b3Vector3 aabbMin, aabbMax;
+                       aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+                       aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
+                       aabbMin.setMin(triangle[0]);
+                       aabbMax.setMax(triangle[0]);
+                       aabbMin.setMin(triangle[1]);
+                       aabbMax.setMax(triangle[1]);
+                       aabbMin.setMin(triangle[2]);
+                       aabbMax.setMax(triangle[2]);
+
+                       //with quantization?
+                       node.m_aabbMinOrg = aabbMin;
+                       node.m_aabbMaxOrg = aabbMax;
+
+                       node.m_escapeIndex = -1;
+
+                       //for child nodes
+                       node.m_subPart = partId;
+                       node.m_triangleIndex = triangleIndex;
+                       m_triangleNodes.push_back(node);
+               }
+       };
+       struct QuantizedNodeTriangleCallback : public b3InternalTriangleIndexCallback
+       {
+               QuantizedNodeArray& m_triangleNodes;
+               const b3QuantizedBvh* m_optimizedTree;  // for quantization
+
+               QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
+               {
+                       m_triangleNodes.copyFromArray(other.m_triangleNodes);
+                       m_optimizedTree = other.m_optimizedTree;
+                       return *this;
+               }
+
+               QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes, const b3QuantizedBvh* tree)
+                       : m_triangleNodes(triangleNodes), m_optimizedTree(tree)
+               {
+               }
+
+               virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
+               {
+                       // The partId and triangle index must fit in the same (positive) integer
+                       b3Assert(partId < (1 << MAX_NUM_PARTS_IN_BITS));
+                       b3Assert(triangleIndex < (1 << (31 - MAX_NUM_PARTS_IN_BITS)));
+                       //negative indices are reserved for escapeIndex
+                       b3Assert(triangleIndex >= 0);
+
+                       b3QuantizedBvhNode node;
+                       b3Vector3 aabbMin, aabbMax;
+                       aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+                       aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
+                       aabbMin.setMin(triangle[0]);
+                       aabbMax.setMax(triangle[0]);
+                       aabbMin.setMin(triangle[1]);
+                       aabbMax.setMax(triangle[1]);
+                       aabbMin.setMin(triangle[2]);
+                       aabbMax.setMax(triangle[2]);
+
+                       //PCK: add these checks for zero dimensions of aabb
+                       const b3Scalar MIN_AABB_DIMENSION = b3Scalar(0.002);
+                       const b3Scalar MIN_AABB_HALF_DIMENSION = b3Scalar(0.001);
+                       if (aabbMax.getX() - aabbMin.getX() < MIN_AABB_DIMENSION)
+                       {
+                               aabbMax.setX(aabbMax.getX() + MIN_AABB_HALF_DIMENSION);
+                               aabbMin.setX(aabbMin.getX() - MIN_AABB_HALF_DIMENSION);
+                       }
+                       if (aabbMax.getY() - aabbMin.getY() < MIN_AABB_DIMENSION)
+                       {
+                               aabbMax.setY(aabbMax.getY() + MIN_AABB_HALF_DIMENSION);
+                               aabbMin.setY(aabbMin.getY() - MIN_AABB_HALF_DIMENSION);
+                       }
+                       if (aabbMax.getZ() - aabbMin.getZ() < MIN_AABB_DIMENSION)
+                       {
+                               aabbMax.setZ(aabbMax.getZ() + MIN_AABB_HALF_DIMENSION);
+                               aabbMin.setZ(aabbMin.getZ() - MIN_AABB_HALF_DIMENSION);
+                       }
+
+                       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);
+               }
+       };
+
+       int numLeafNodes = 0;
+
+       if (m_useQuantization)
+       {
+               //initialize quantization values
+               setQuantizationValues(bvhAabbMin, bvhAabbMax);
+
+               QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes, this);
+
+               triangles->InternalProcessAllTriangles(&callback, m_bvhAabbMin, m_bvhAabbMax);
+
+               //now we have an array of leafnodes in m_leafNodes
+               numLeafNodes = m_quantizedLeafNodes.size();
+
+               m_quantizedContiguousNodes.resize(2 * numLeafNodes);
+       }
+       else
+       {
+               NodeTriangleCallback callback(m_leafNodes);
+
+               b3Vector3 aabbMin = b3MakeVector3(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
+               b3Vector3 aabbMax = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+
+               triangles->InternalProcessAllTriangles(&callback, aabbMin, aabbMax);
+
+               //now we have an array of leafnodes in m_leafNodes
+               numLeafNodes = m_leafNodes.size();
+
+               m_contiguousNodes.resize(2 * numLeafNodes);
+       }
+
+       m_curNodeIndex = 0;
+
+       buildTree(0, numLeafNodes);
+
+       ///if the entire tree is small then subtree size, we need to create a header info for the tree
+       if (m_useQuantization && !m_SubtreeHeaders.size())
+       {
+               b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+               subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+               subtree.m_rootNodeIndex = 0;
+               subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+       }
+
+       //PCK: update the copy of the size
+       m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+       //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+       m_quantizedLeafNodes.clear();
+       m_leafNodes.clear();
+}
+
+void b3OptimizedBvh::refit(b3StridingMeshInterface* meshInterface, const b3Vector3& aabbMin, const b3Vector3& 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++)
+               {
+                       b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+                       subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+               }
+       }
+       else
+       {
+       }
+}
+
+void b3OptimizedBvh::refitPartial(b3StridingMeshInterface* meshInterface, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
+{
+       //incrementally initialize quantization values
+       b3Assert(m_useQuantization);
+
+       b3Assert(aabbMin.getX() > m_bvhAabbMin.getX());
+       b3Assert(aabbMin.getY() > m_bvhAabbMin.getY());
+       b3Assert(aabbMin.getZ() > m_bvhAabbMin.getZ());
+
+       b3Assert(aabbMax.getX() < m_bvhAabbMax.getX());
+       b3Assert(aabbMax.getY() < m_bvhAabbMax.getY());
+       b3Assert(aabbMax.getZ() < m_bvhAabbMax.getZ());
+
+       ///we should update all quantization values, using updateBvhNodes(meshInterface);
+       ///but we only update chunks that overlap the given aabb
+
+       unsigned short quantizedQueryAabbMin[3];
+       unsigned short quantizedQueryAabbMax[3];
+
+       quantize(&quantizedQueryAabbMin[0], aabbMin, 0);
+       quantize(&quantizedQueryAabbMax[0], aabbMax, 1);
+
+       int i;
+       for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
+       {
+               b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+               //PCK: unsigned instead of bool
+               unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
+               if (overlap != 0)
+               {
+                       updateBvhNodes(meshInterface, subtree.m_rootNodeIndex, subtree.m_rootNodeIndex + subtree.m_subtreeSize, i);
+
+                       subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+               }
+       }
+}
+
+void b3OptimizedBvh::updateBvhNodes(b3StridingMeshInterface* meshInterface, int firstNode, int endNode, int index)
+{
+       (void)index;
+
+       b3Assert(m_useQuantization);
+
+       int curNodeSubPart = -1;
+
+       //get access info to trianglemesh data
+       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;
+
+       b3Vector3 triangleVerts[3];
+       b3Vector3 aabbMin, aabbMax;
+       const b3Vector3& meshScaling = meshInterface->getScaling();
+
+       int i;
+       for (i = endNode - 1; i >= firstNode; i--)
+       {
+               b3QuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
+               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);
+
+                               curNodeSubPart = nodeSubPart;
+                       }
+                       //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
+
+                       unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
+
+                       for (int j = 2; j >= 0; j--)
+                       {
+                               int graphicsindex;
+                                switch (indicestype) {
+                                        case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
+                                        case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
+                                        case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
+                                        default: b3Assert(0);
+                                }
+                               if (type == PHY_FLOAT)
+                               {
+                                       float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
+                                       triangleVerts[j] = b3MakeVector3(
+                                               graphicsbase[0] * meshScaling.getX(),
+                                               graphicsbase[1] * meshScaling.getY(),
+                                               graphicsbase[2] * meshScaling.getZ());
+                               }
+                               else
+                               {
+                                       double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+                                       triangleVerts[j] = b3MakeVector3(b3Scalar(graphicsbase[0] * meshScaling.getX()), b3Scalar(graphicsbase[1] * meshScaling.getY()), b3Scalar(graphicsbase[2] * meshScaling.getZ()));
+                               }
+                       }
+
+                       aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+                       aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
+                       aabbMin.setMin(triangleVerts[0]);
+                       aabbMax.setMax(triangleVerts[0]);
+                       aabbMin.setMin(triangleVerts[1]);
+                       aabbMax.setMax(triangleVerts[1]);
+                       aabbMin.setMin(triangleVerts[2]);
+                       aabbMax.setMax(triangleVerts[2]);
+
+                       quantize(&curNode.m_quantizedAabbMin[0], aabbMin, 0);
+                       quantize(&curNode.m_quantizedAabbMax[0], aabbMax, 1);
+               }
+               else
+               {
+                       //combine aabb from both children
+
+                       b3QuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i + 1];
+
+                       b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i + 2] : &m_quantizedContiguousNodes[i + 1 + leftChildNode->getEscapeIndex()];
+
+                       {
+                               for (int i = 0; i < 3; i++)
+                               {
+                                       curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
+                                       if (curNode.m_quantizedAabbMin[i] > rightChildNode->m_quantizedAabbMin[i])
+                                               curNode.m_quantizedAabbMin[i] = rightChildNode->m_quantizedAabbMin[i];
+
+                                       curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
+                                       if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
+                                               curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
+                               }
+                       }
+               }
+       }
+
+       if (curNodeSubPart >= 0)
+               meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+}
+
+///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+b3OptimizedBvh* b3OptimizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+       b3QuantizedBvh* bvh = b3QuantizedBvh::deSerializeInPlace(i_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
+
+       //we don't add additional data so just do a static upcast
+       return static_cast<b3OptimizedBvh*>(bvh);
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h
new file mode 100644 (file)
index 0000000..1286552
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///Contains contributions from Disney Studio's
+
+#ifndef B3_OPTIMIZED_BVH_H
+#define B3_OPTIMIZED_BVH_H
+
+#include "b3QuantizedBvh.h"
+
+class b3StridingMeshInterface;
+
+///The b3OptimizedBvh extends the b3QuantizedBvh to create AABB tree for triangle meshes, through the b3StridingMeshInterface.
+B3_ATTRIBUTE_ALIGNED16(class)
+b3OptimizedBvh : public b3QuantizedBvh
+{
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+protected:
+public:
+       b3OptimizedBvh();
+
+       virtual ~b3OptimizedBvh();
+
+       void build(b3StridingMeshInterface * triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax);
+
+       void refit(b3StridingMeshInterface * triangles, const b3Vector3& aabbMin, const b3Vector3& aabbMax);
+
+       void refitPartial(b3StridingMeshInterface * triangles, const b3Vector3& aabbMin, const b3Vector3& aabbMax);
+
+       void updateBvhNodes(b3StridingMeshInterface * meshInterface, int firstNode, int endNode, int index);
+
+       /// Data buffer MUST be 16 byte aligned
+       virtual bool serializeInPlace(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
+       {
+               return b3QuantizedBvh::serialize(o_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
+       }
+
+       ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+       static b3OptimizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+};
+
+#endif  //B3_OPTIMIZED_BVH_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp
new file mode 100644 (file)
index 0000000..e9a3d08
--- /dev/null
@@ -0,0 +1,1254 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3QuantizedBvh.h"
+
+#include "Bullet3Geometry/b3AabbUtil.h"
+
+#define RAYAABB2
+
+b3QuantizedBvh::b3QuantizedBvh() : m_bulletVersion(B3_BULLET_VERSION),
+                                                                  m_useQuantization(false),
+                                                                  m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+                                                                  //m_traversalMode(TRAVERSAL_STACKLESS)
+                                                                  //m_traversalMode(TRAVERSAL_RECURSIVE)
+                                                                  ,
+                                                                  m_subtreeHeaderCount(0)  //PCK: add this line
+{
+       m_bvhAabbMin.setValue(-B3_INFINITY, -B3_INFINITY, -B3_INFINITY);
+       m_bvhAabbMax.setValue(B3_INFINITY, B3_INFINITY, B3_INFINITY);
+}
+
+void b3QuantizedBvh::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())
+       {
+               b3BvhSubtreeInfo& 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
+b3Vector3 color[4] =
+       {
+               b3Vector3(1, 0, 0),
+               b3Vector3(0, 1, 0),
+               b3Vector3(0, 0, 1),
+               b3Vector3(0, 1, 1)};
+#endif  //DEBUG_PATCH_COLORS
+
+void b3QuantizedBvh::setQuantizationValues(const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax, b3Scalar quantizationMargin)
+{
+       //enlarge the AABB to avoid division by zero when initializing the quantization values
+       b3Vector3 clampValue = b3MakeVector3(quantizationMargin, quantizationMargin, quantizationMargin);
+       m_bvhAabbMin = bvhAabbMin - clampValue;
+       m_bvhAabbMax = bvhAabbMax + clampValue;
+       b3Vector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+       m_bvhQuantization = b3MakeVector3(b3Scalar(65533.0), b3Scalar(65533.0), b3Scalar(65533.0)) / aabbSize;
+       m_useQuantization = true;
+}
+
+b3QuantizedBvh::~b3QuantizedBvh()
+{
+}
+
+#ifdef DEBUG_TREE_BUILDING
+int gStackDepth = 0;
+int gMaxStackDepth = 0;
+#endif  //DEBUG_TREE_BUILDING
+
+void b3QuantizedBvh::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;
+
+       b3Assert(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;
+
+       //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
+       //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
+       setInternalNodeAabbMin(m_curNodeIndex, m_bvhAabbMax);  //can't use b3Vector3(B3_INFINITY,B3_INFINITY,B3_INFINITY)) because of quantization
+       setInternalNodeAabbMax(m_curNodeIndex, m_bvhAabbMin);  //can't use b3Vector3(-B3_INFINITY,-B3_INFINITY,-B3_INFINITY)) because of quantization
+
+       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(b3QuantizedBvhNode);
+               const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
+               if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
+               {
+                       updateSubtreeHeaders(leftChildNodexIndex, rightChildNodexIndex);
+               }
+       }
+       else
+       {
+       }
+
+       setInternalNodeEscapeIndex(internalNodeIndex, escapeIndex);
+}
+
+void b3QuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex)
+{
+       b3Assert(m_useQuantization);
+
+       b3QuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
+       int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
+       int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(b3QuantizedBvhNode));
+
+       b3QuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
+       int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
+       int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(sizeof(b3QuantizedBvhNode));
+
+       if (leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+       {
+               b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+               subtree.setAabbFromQuantizeNode(leftChildNode);
+               subtree.m_rootNodeIndex = leftChildNodexIndex;
+               subtree.m_subtreeSize = leftSubTreeSize;
+       }
+
+       if (rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+       {
+               b3BvhSubtreeInfo& 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 b3QuantizedBvh::sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis)
+{
+       int i;
+       int splitIndex = startIndex;
+       int numIndices = endIndex - startIndex;
+       b3Scalar splitValue;
+
+       b3Vector3 means = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+       for (i = startIndex; i < endIndex; i++)
+       {
+               b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
+               means += center;
+       }
+       means *= (b3Scalar(1.) / (b3Scalar)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++)
+       {
+               b3Vector3 center = b3Scalar(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;
+       b3Assert(!unbal);
+
+       return splitIndex;
+}
+
+int b3QuantizedBvh::calcSplittingAxis(int startIndex, int endIndex)
+{
+       int i;
+
+       b3Vector3 means = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+       b3Vector3 variance = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+       int numIndices = endIndex - startIndex;
+
+       for (i = startIndex; i < endIndex; i++)
+       {
+               b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
+               means += center;
+       }
+       means *= (b3Scalar(1.) / (b3Scalar)numIndices);
+
+       for (i = startIndex; i < endIndex; i++)
+       {
+               b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
+               b3Vector3 diff2 = center - means;
+               diff2 = diff2 * diff2;
+               variance += diff2;
+       }
+       variance *= (b3Scalar(1.) / ((b3Scalar)numIndices - 1));
+
+       return variance.maxAxis();
+}
+
+void b3QuantizedBvh::reportAabbOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& aabbMin, const b3Vector3& 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 b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
+                               walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
+                       }
+                       break;
+                       default:
+                               //unsupported
+                               b3Assert(0);
+               }
+       }
+       else
+       {
+               walkStacklessTree(nodeCallback, aabbMin, aabbMax);
+       }
+}
+
+static int b3s_maxIterations = 0;
+
+void b3QuantizedBvh::walkStacklessTree(b3NodeOverlapCallback* nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
+{
+       b3Assert(!m_useQuantization);
+
+       const b3OptimizedBvhNode* 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
+               b3Assert(walkIterations < m_curNodeIndex);
+
+               walkIterations++;
+               aabbOverlap = b3TestAabbAgainstAabb2(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 (b3s_maxIterations < walkIterations)
+               b3s_maxIterations = walkIterations;
+}
+
+/*
+///this was the original recursive traversal, before we optimized towards stackless traversal
+void   b3QuantizedBvh::walkTree(b3OptimizedBvhNode* rootNode,b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& 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 b3QuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode, b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
+{
+       b3Assert(m_useQuantization);
+
+       bool isLeafNode;
+       //PCK: unsigned instead of bool
+       unsigned aabbOverlap;
+
+       //PCK: unsigned instead of bool
+       aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(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 b3QuantizedBvhNode* leftChildNode = currentNode + 1;
+                       walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
+
+                       const b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode + 1 : leftChildNode + leftChildNode->getEscapeIndex();
+                       walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
+               }
+       }
+}
+
+void b3QuantizedBvh::walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const
+{
+       b3Assert(!m_useQuantization);
+
+       const b3OptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+       int escapeIndex, curIndex = 0;
+       int walkIterations = 0;
+       bool isLeafNode;
+       //PCK: unsigned instead of bool
+       unsigned aabbOverlap = 0;
+       unsigned rayBoxOverlap = 0;
+       b3Scalar lambda_max = 1.0;
+
+       /* Quick pruning by quantized box */
+       b3Vector3 rayAabbMin = raySource;
+       b3Vector3 rayAabbMax = raySource;
+       rayAabbMin.setMin(rayTarget);
+       rayAabbMax.setMax(rayTarget);
+
+       /* Add box cast extents to bounding box */
+       rayAabbMin += aabbMin;
+       rayAabbMax += aabbMax;
+
+#ifdef RAYAABB2
+       b3Vector3 rayDir = (rayTarget - raySource);
+       rayDir.normalize();
+       lambda_max = rayDir.dot(rayTarget - raySource);
+       ///what about division by zero? --> just set rayDirection[i] to 1.0
+       b3Vector3 rayDirectionInverse;
+       rayDirectionInverse[0] = rayDir[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[0];
+       rayDirectionInverse[1] = rayDir[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[1];
+       rayDirectionInverse[2] = rayDir[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[2];
+       unsigned int sign[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+#endif
+
+       b3Vector3 bounds[2];
+
+       while (curIndex < m_curNodeIndex)
+       {
+               b3Scalar param = 1.0;
+               //catch bugs in tree data
+               b3Assert(walkIterations < m_curNodeIndex);
+
+               walkIterations++;
+
+               bounds[0] = rootNode->m_aabbMinOrg;
+               bounds[1] = rootNode->m_aabbMaxOrg;
+               /* Add box cast extents */
+               bounds[0] -= aabbMax;
+               bounds[1] -= aabbMin;
+
+               aabbOverlap = b3TestAabbAgainstAabb2(rayAabbMin, rayAabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
+               //perhaps profile if it is worth doing the aabbOverlap test first
+
+#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 = aabbOverlap ? b3RayAabb2(raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
+
+#else
+               b3Vector3 normal;
+               rayBoxOverlap = b3RayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+#endif
+
+               isLeafNode = rootNode->m_escapeIndex == -1;
+
+               //PCK: unsigned instead of bool
+               if (isLeafNode && (rayBoxOverlap != 0))
+               {
+                       nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
+               }
+
+               //PCK: unsigned instead of bool
+               if ((rayBoxOverlap != 0) || isLeafNode)
+               {
+                       rootNode++;
+                       curIndex++;
+               }
+               else
+               {
+                       escapeIndex = rootNode->m_escapeIndex;
+                       rootNode += escapeIndex;
+                       curIndex += escapeIndex;
+               }
+       }
+       if (b3s_maxIterations < walkIterations)
+               b3s_maxIterations = walkIterations;
+}
+
+void b3QuantizedBvh::walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const
+{
+       b3Assert(m_useQuantization);
+
+       int curIndex = startNodeIndex;
+       int walkIterations = 0;
+       int subTreeSize = endNodeIndex - startNodeIndex;
+       (void)subTreeSize;
+
+       const b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+       int escapeIndex;
+
+       bool isLeafNode;
+       //PCK: unsigned instead of bool
+       unsigned boxBoxOverlap = 0;
+       unsigned rayBoxOverlap = 0;
+
+       b3Scalar lambda_max = 1.0;
+
+#ifdef RAYAABB2
+       b3Vector3 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] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[0];
+       rayDirection[1] = rayDirection[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[1];
+       rayDirection[2] = rayDirection[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(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 */
+       b3Vector3 rayAabbMin = raySource;
+       b3Vector3 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 b3IDebugDraw* debugDrawerPtr;
+               if (curIndex == drawPatch)
+               {
+                       b3Vector3 aabbMin, aabbMax;
+                       aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+                       aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+                       b3Vector3 color(1, 0, 0);
+                       debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
+               }
+#endif  //VISUALLY_ANALYZE_BVH
+
+               //catch bugs in tree data
+               b3Assert(walkIterations < subTreeSize);
+
+               walkIterations++;
+               //PCK: unsigned instead of bool
+               // only interested if this is closer than any previous hit
+               b3Scalar param = 1.0;
+               rayBoxOverlap = 0;
+               boxBoxOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
+               isLeafNode = rootNode->isLeafNode();
+               if (boxBoxOverlap)
+               {
+                       b3Vector3 bounds[2];
+                       bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
+                       bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
+                       /* Add box cast extents */
+                       bounds[0] -= aabbMax;
+                       bounds[1] -= aabbMin;
+#if 0
+                       b3Vector3 normal;
+                       bool ra2 = b3RayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
+                       bool ra = b3RayAabb (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
+
+                       //B3_PROFILE("b3RayAabb2");
+                       rayBoxOverlap = b3RayAabb2(raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
+
+#else
+                       rayBoxOverlap = true;  //b3RayAabb(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 (b3s_maxIterations < walkIterations)
+               b3s_maxIterations = walkIterations;
+}
+
+void b3QuantizedBvh::walkStacklessQuantizedTree(b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const
+{
+       b3Assert(m_useQuantization);
+
+       int curIndex = startNodeIndex;
+       int walkIterations = 0;
+       int subTreeSize = endNodeIndex - startNodeIndex;
+       (void)subTreeSize;
+
+       const b3QuantizedBvhNode* 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 b3IDebugDraw* debugDrawerPtr;
+               if (curIndex == drawPatch)
+               {
+                       b3Vector3 aabbMin, aabbMax;
+                       aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+                       aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+                       b3Vector3 color(1, 0, 0);
+                       debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
+               }
+#endif  //VISUALLY_ANALYZE_BVH
+
+               //catch bugs in tree data
+               b3Assert(walkIterations < subTreeSize);
+
+               walkIterations++;
+               //PCK: unsigned instead of bool
+               aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(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 (b3s_maxIterations < walkIterations)
+               b3s_maxIterations = walkIterations;
+}
+
+//This traversal can be called from Playstation 3 SPU
+void b3QuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
+{
+       b3Assert(m_useQuantization);
+
+       int i;
+
+       for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
+       {
+               const b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+               //PCK: unsigned instead of bool
+               unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(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 b3QuantizedBvh::reportRayOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const
+{
+       reportBoxCastOverlappingNodex(nodeCallback, raySource, rayTarget, b3MakeVector3(0, 0, 0), b3MakeVector3(0, 0, 0));
+}
+
+void b3QuantizedBvh::reportBoxCastOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
+{
+       //always use stackless
+
+       if (m_useQuantization)
+       {
+               walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+       }
+       else
+       {
+               walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+       }
+       /*
+       {
+               //recursive traversal
+               b3Vector3 qaabbMin = raySource;
+               b3Vector3 qaabbMax = raySource;
+               qaabbMin.setMin(rayTarget);
+               qaabbMax.setMax(rayTarget);
+               qaabbMin += aabbMin;
+               qaabbMax += aabbMax;
+               reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
+       }
+       */
+}
+
+void b3QuantizedBvh::swapLeafNodes(int i, int splitIndex)
+{
+       if (m_useQuantization)
+       {
+               b3QuantizedBvhNode tmp = m_quantizedLeafNodes[i];
+               m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
+               m_quantizedLeafNodes[splitIndex] = tmp;
+       }
+       else
+       {
+               b3OptimizedBvhNode tmp = m_leafNodes[i];
+               m_leafNodes[i] = m_leafNodes[splitIndex];
+               m_leafNodes[splitIndex] = tmp;
+       }
+}
+
+void b3QuantizedBvh::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>
+
+#if 0
+//PCK: consts
+static const unsigned BVH_ALIGNMENT = 16;
+static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
+
+static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
+#endif
+
+unsigned int b3QuantizedBvh::getAlignmentSerializationPadding()
+{
+       // I changed this to 0 since the extra padding is not needed or used.
+       return 0;  //BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+}
+
+unsigned b3QuantizedBvh::calculateSerializeBufferSize() const
+{
+       unsigned baseSize = sizeof(b3QuantizedBvh) + getAlignmentSerializationPadding();
+       baseSize += sizeof(b3BvhSubtreeInfo) * m_subtreeHeaderCount;
+       if (m_useQuantization)
+       {
+               return baseSize + m_curNodeIndex * sizeof(b3QuantizedBvhNode);
+       }
+       return baseSize + m_curNodeIndex * sizeof(b3OptimizedBvhNode);
+}
+
+bool b3QuantizedBvh::serialize(void* o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
+{
+       b3Assert(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?
+               b3Assert(0);
+               return false;
+       }
+*/
+
+       b3QuantizedBvh* targetBvh = (b3QuantizedBvh*)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) b3QuantizedBvh;
+
+       if (i_swapEndian)
+       {
+               targetBvh->m_curNodeIndex = static_cast<int>(b3SwapEndian(m_curNodeIndex));
+
+               b3SwapVector3Endian(m_bvhAabbMin, targetBvh->m_bvhAabbMin);
+               b3SwapVector3Endian(m_bvhAabbMax, targetBvh->m_bvhAabbMax);
+               b3SwapVector3Endian(m_bvhQuantization, targetBvh->m_bvhQuantization);
+
+               targetBvh->m_traversalMode = (b3TraversalMode)b3SwapEndian(m_traversalMode);
+               targetBvh->m_subtreeHeaderCount = static_cast<int>(b3SwapEndian(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(b3QuantizedBvh);
+
+       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] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+                               targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(b3SwapEndian(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(b3QuantizedBvhNode) * nodeCount;
+
+               // this clears the pointer in the member variable it doesn't really do anything to the data
+               // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+               // so the memory (which is not freed) is left alone
+               targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0);
+       }
+       else
+       {
+               targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+               if (i_swapEndian)
+               {
+                       for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+                       {
+                               b3SwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+                               b3SwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+                               targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(b3SwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
+                               targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(b3SwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
+                               targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(b3SwapEndian(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(b3OptimizedBvhNode) * nodeCount;
+
+               // this clears the pointer in the member variable it doesn't really do anything to the data
+               // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+               // so the memory (which is not freed) is left alone
+               targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
+       }
+
+       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] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+                       targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+                       targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(b3SwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
+                       targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(b3SwapEndian(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);
+
+                       // need to clear padding in destination buffer
+                       targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0;
+                       targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0;
+                       targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0;
+               }
+       }
+       nodeData += sizeof(b3BvhSubtreeInfo) * m_subtreeHeaderCount;
+
+       // this clears the pointer in the member variable it doesn't really do anything to the data
+       // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+       // so the memory (which is not freed) is left alone
+       targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0);
+
+       // this wipes the virtual function table pointer at the start of the buffer for the class
+       *((void**)o_alignedDataBuffer) = NULL;
+
+       return true;
+}
+
+b3QuantizedBvh* b3QuantizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+       if (i_alignedDataBuffer == NULL)  // || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+       {
+               return NULL;
+       }
+       b3QuantizedBvh* bvh = (b3QuantizedBvh*)i_alignedDataBuffer;
+
+       if (i_swapEndian)
+       {
+               bvh->m_curNodeIndex = static_cast<int>(b3SwapEndian(bvh->m_curNodeIndex));
+
+               b3UnSwapVector3Endian(bvh->m_bvhAabbMin);
+               b3UnSwapVector3Endian(bvh->m_bvhAabbMax);
+               b3UnSwapVector3Endian(bvh->m_bvhQuantization);
+
+               bvh->m_traversalMode = (b3TraversalMode)b3SwapEndian(bvh->m_traversalMode);
+               bvh->m_subtreeHeaderCount = static_cast<int>(b3SwapEndian(bvh->m_subtreeHeaderCount));
+       }
+
+       unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
+       b3Assert(calculatedBufSize <= i_dataBufferSize);
+
+       if (calculatedBufSize > i_dataBufferSize)
+       {
+               return NULL;
+       }
+
+       unsigned char* nodeData = (unsigned char*)bvh;
+       nodeData += sizeof(b3QuantizedBvh);
+
+       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) b3QuantizedBvh(*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] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+                               bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+                       }
+               }
+               nodeData += sizeof(b3QuantizedBvhNode) * nodeCount;
+       }
+       else
+       {
+               bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+               if (i_swapEndian)
+               {
+                       for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+                       {
+                               b3UnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+                               b3UnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+                               bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
+                               bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
+                               bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
+                       }
+               }
+               nodeData += sizeof(b3OptimizedBvhNode) * 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] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+                       bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+                       bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(b3SwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
+                       bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(b3SwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
+               }
+       }
+
+       return bvh;
+}
+
+// Constructor that prevents b3Vector3's default constructor from being called
+b3QuantizedBvh::b3QuantizedBvh(b3QuantizedBvh& self, bool /* ownsMemory */) : m_bvhAabbMin(self.m_bvhAabbMin),
+                                                                                                                                                         m_bvhAabbMax(self.m_bvhAabbMax),
+                                                                                                                                                         m_bvhQuantization(self.m_bvhQuantization),
+                                                                                                                                                         m_bulletVersion(B3_BULLET_VERSION)
+{
+}
+
+void b3QuantizedBvh::deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedBvhFloatData)
+{
+       m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax);
+       m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin);
+       m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
+
+       m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
+       m_useQuantization = quantizedBvhFloatData.m_useQuantization != 0;
+
+       {
+               int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
+               m_contiguousNodes.resize(numElem);
+
+               if (numElem)
+               {
+                       b3OptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
+
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
+                               m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
+                               m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+                               m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+                               m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+                       }
+               }
+       }
+
+       {
+               int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
+               m_quantizedContiguousNodes.resize(numElem);
+
+               if (numElem)
+               {
+                       b3QuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+                       }
+               }
+       }
+
+       m_traversalMode = b3TraversalMode(quantizedBvhFloatData.m_traversalMode);
+
+       {
+               int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
+               m_SubtreeHeaders.resize(numElem);
+               if (numElem)
+               {
+                       b3BvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+                               m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+                               m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+                       }
+               }
+       }
+}
+
+void b3QuantizedBvh::deSerializeDouble(struct b3QuantizedBvhDoubleData& quantizedBvhDoubleData)
+{
+       m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax);
+       m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin);
+       m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
+
+       m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
+       m_useQuantization = quantizedBvhDoubleData.m_useQuantization != 0;
+
+       {
+               int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
+               m_contiguousNodes.resize(numElem);
+
+               if (numElem)
+               {
+                       b3OptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
+
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
+                               m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
+                               m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+                               m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+                               m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+                       }
+               }
+       }
+
+       {
+               int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
+               m_quantizedContiguousNodes.resize(numElem);
+
+               if (numElem)
+               {
+                       b3QuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+                       }
+               }
+       }
+
+       m_traversalMode = b3TraversalMode(quantizedBvhDoubleData.m_traversalMode);
+
+       {
+               int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
+               m_SubtreeHeaders.resize(numElem);
+               if (numElem)
+               {
+                       b3BvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+                               m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+                               m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+                       }
+               }
+       }
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* b3QuantizedBvh::serialize(void* dataBuffer, b3Serializer* serializer) const
+{
+       b3Assert(0);
+       return 0;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h
new file mode 100644 (file)
index 0000000..1347082
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_QUANTIZED_BVH_H
+#define B3_QUANTIZED_BVH_H
+
+class b3Serializer;
+
+//#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 "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3AlignedAllocator.h"
+
+#ifdef B3_USE_DOUBLE_PRECISION
+#define b3QuantizedBvhData b3QuantizedBvhDoubleData
+#define b3OptimizedBvhNodeData b3OptimizedBvhNodeDoubleData
+#define b3QuantizedBvhDataName "b3QuantizedBvhDoubleData"
+#else
+#define b3QuantizedBvhData b3QuantizedBvhFloatData
+#define b3OptimizedBvhNodeData b3OptimizedBvhNodeFloatData
+#define b3QuantizedBvhDataName "b3QuantizedBvhFloatData"
+#endif
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.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
+
+///b3QuantizedBvhNode 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).
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3QuantizedBvhNode : public b3QuantizedBvhNodeData
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       bool isLeafNode() const
+       {
+               //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+               return (m_escapeIndexOrTriangleIndex >= 0);
+       }
+       int getEscapeIndex() const
+       {
+               b3Assert(!isLeafNode());
+               return -m_escapeIndexOrTriangleIndex;
+       }
+       int getTriangleIndex() const
+       {
+               b3Assert(isLeafNode());
+               unsigned int x = 0;
+               unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
+               // Get only the lower bits where the triangle index is stored
+               return (m_escapeIndexOrTriangleIndex & ~(y));
+       }
+       int getPartId() const
+       {
+               b3Assert(isLeafNode());
+               // Get only the highest bits where the part index is stored
+               return (m_escapeIndexOrTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
+       }
+};
+
+/// b3OptimizedBvhNode contains both internal and leaf node information.
+/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3OptimizedBvhNode
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       //32 bytes
+       b3Vector3 m_aabbMinOrg;
+       b3Vector3 m_aabbMaxOrg;
+
+       //4
+       int m_escapeIndex;
+
+       //8
+       //for child nodes
+       int m_subPart;
+       int m_triangleIndex;
+
+       //pad the size to 64 bytes
+       char m_padding[20];
+};
+
+///b3BvhSubtreeInfo provides info to gather a subtree of limited size
+B3_ATTRIBUTE_ALIGNED16(class)
+b3BvhSubtreeInfo : public b3BvhSubtreeInfoData
+{
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       b3BvhSubtreeInfo()
+       {
+               //memset(&m_padding[0], 0, sizeof(m_padding));
+       }
+
+       void setAabbFromQuantizeNode(const b3QuantizedBvhNode& 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 b3NodeOverlapCallback
+{
+public:
+       virtual ~b3NodeOverlapCallback(){};
+
+       virtual void processNode(int subPart, int triangleIndex) = 0;
+};
+
+#include "Bullet3Common/b3AlignedAllocator.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+///for code readability:
+typedef b3AlignedObjectArray<b3OptimizedBvhNode> NodeArray;
+typedef b3AlignedObjectArray<b3QuantizedBvhNode> QuantizedNodeArray;
+typedef b3AlignedObjectArray<b3BvhSubtreeInfo> BvhSubtreeInfoArray;
+
+///The b3QuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
+///It is used by the b3BvhTriangleMeshShape as midphase
+///It is recommended to use quantization for better performance and lower memory requirements.
+B3_ATTRIBUTE_ALIGNED16(class)
+b3QuantizedBvh
+{
+public:
+       enum b3TraversalMode
+       {
+               TRAVERSAL_STACKLESS = 0,
+               TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
+               TRAVERSAL_RECURSIVE
+       };
+
+       b3Vector3 m_bvhAabbMin;
+       b3Vector3 m_bvhAabbMax;
+       b3Vector3 m_bvhQuantization;
+
+protected:
+       int m_bulletVersion;  //for serialization versioning. It could also be used to detect endianess.
+
+       int m_curNodeIndex;
+       //quantization data
+       bool m_useQuantization;
+
+       NodeArray m_leafNodes;
+       NodeArray m_contiguousNodes;
+       QuantizedNodeArray m_quantizedLeafNodes;
+       QuantizedNodeArray m_quantizedContiguousNodes;
+
+       b3TraversalMode m_traversalMode;
+       BvhSubtreeInfoArray m_SubtreeHeaders;
+
+       //This is only used for serialization so we don't have to add serialization directly to b3AlignedObjectArray
+       mutable 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 b3Vector3& 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 b3Vector3& aabbMax)
+       {
+               if (m_useQuantization)
+               {
+                       quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0], aabbMax, 1);
+               }
+               else
+               {
+                       m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
+               }
+       }
+
+       b3Vector3 getAabbMin(int nodeIndex) const
+       {
+               if (m_useQuantization)
+               {
+                       return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
+               }
+               //non-quantized
+               return m_leafNodes[nodeIndex].m_aabbMinOrg;
+       }
+       b3Vector3 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 b3Vector3& newAabbMin, const b3Vector3& 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(b3NodeOverlapCallback * nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
+
+       void walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
+       void walkStacklessQuantizedTree(b3NodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const;
+       void walkStacklessTreeAgainstRay(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
+
+       ///tree traversal designed for small-memory processors like PS3 SPU
+       void walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback * 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 b3QuantizedBvhNode* currentNode, b3NodeOverlapCallback* 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 b3QuantizedBvhNode* treeNodeA, const b3QuantizedBvhNode* treeNodeB, b3NodeOverlapCallback* nodeCallback) const;
+
+       void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex);
+
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       b3QuantizedBvh();
+
+       virtual ~b3QuantizedBvh();
+
+       ///***************************************** expert/internal use only *************************
+       void setQuantizationValues(const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax, b3Scalar quantizationMargin = b3Scalar(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(b3NodeOverlapCallback * nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
+       void reportRayOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const;
+       void reportBoxCastOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
+
+       B3_FORCE_INLINE void quantize(unsigned short* out, const b3Vector3& point, int isMax) const
+       {
+               b3Assert(m_useQuantization);
+
+               b3Assert(point.getX() <= m_bvhAabbMax.getX());
+               b3Assert(point.getY() <= m_bvhAabbMax.getY());
+               b3Assert(point.getZ() <= m_bvhAabbMax.getZ());
+
+               b3Assert(point.getX() >= m_bvhAabbMin.getX());
+               b3Assert(point.getY() >= m_bvhAabbMin.getY());
+               b3Assert(point.getZ() >= m_bvhAabbMin.getZ());
+
+               b3Vector3 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() + b3Scalar(1.)) | 1));
+                       out[1] = (unsigned short)(((unsigned short)(v.getY() + b3Scalar(1.)) | 1));
+                       out[2] = (unsigned short)(((unsigned short)(v.getZ() + b3Scalar(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
+               b3Vector3 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
+       }
+
+       B3_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const b3Vector3& point2, int isMax) const
+       {
+               b3Assert(m_useQuantization);
+
+               b3Vector3 clampedPoint(point2);
+               clampedPoint.setMax(m_bvhAabbMin);
+               clampedPoint.setMin(m_bvhAabbMax);
+
+               quantize(out, clampedPoint, isMax);
+       }
+
+       B3_FORCE_INLINE b3Vector3 unQuantize(const unsigned short* vecIn) const
+       {
+               b3Vector3 vecOut;
+               vecOut.setValue(
+                       (b3Scalar)(vecIn[0]) / (m_bvhQuantization.getX()),
+                       (b3Scalar)(vecIn[1]) / (m_bvhQuantization.getY()),
+                       (b3Scalar)(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(b3TraversalMode traversalMode)
+       {
+               m_traversalMode = traversalMode;
+       }
+
+       B3_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
+       {
+               return m_quantizedContiguousNodes;
+       }
+
+       B3_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
+       {
+               return m_SubtreeHeaders;
+       }
+
+       ////////////////////////////////////////////////////////////////////
+
+       /////Calculate space needed to store BVH for serialization
+       unsigned calculateSerializeBufferSize() const;
+
+       /// Data buffer MUST be 16 byte aligned
+       virtual bool serialize(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
+
+       ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+       static b3QuantizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+       static unsigned int getAlignmentSerializationPadding();
+       //////////////////////////////////////////////////////////////////////
+
+       virtual int calculateSerializeBufferSizeNew() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
+
+       virtual void deSerializeFloat(struct b3QuantizedBvhFloatData & quantizedBvhFloatData);
+
+       virtual void deSerializeDouble(struct b3QuantizedBvhDoubleData & quantizedBvhDoubleData);
+
+       ////////////////////////////////////////////////////////////////////
+
+       B3_FORCE_INLINE bool isQuantized()
+       {
+               return m_useQuantization;
+       }
+
+private:
+       // Special "copy" constructor that allows for in-place deserialization
+       // Prevents b3Vector3'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)
+       b3QuantizedBvh(b3QuantizedBvh & other, bool ownsMemory);
+};
+
+struct b3OptimizedBvhNodeFloatData
+{
+       b3Vector3FloatData m_aabbMinOrg;
+       b3Vector3FloatData m_aabbMaxOrg;
+       int m_escapeIndex;
+       int m_subPart;
+       int m_triangleIndex;
+       char m_pad[4];
+};
+
+struct b3OptimizedBvhNodeDoubleData
+{
+       b3Vector3DoubleData m_aabbMinOrg;
+       b3Vector3DoubleData m_aabbMaxOrg;
+       int m_escapeIndex;
+       int m_subPart;
+       int m_triangleIndex;
+       char m_pad[4];
+};
+
+struct b3QuantizedBvhFloatData
+{
+       b3Vector3FloatData m_bvhAabbMin;
+       b3Vector3FloatData m_bvhAabbMax;
+       b3Vector3FloatData m_bvhQuantization;
+       int m_curNodeIndex;
+       int m_useQuantization;
+       int m_numContiguousLeafNodes;
+       int m_numQuantizedContiguousNodes;
+       b3OptimizedBvhNodeFloatData* m_contiguousNodesPtr;
+       b3QuantizedBvhNodeData* m_quantizedContiguousNodesPtr;
+       b3BvhSubtreeInfoData* m_subTreeInfoPtr;
+       int m_traversalMode;
+       int m_numSubtreeHeaders;
+};
+
+struct b3QuantizedBvhDoubleData
+{
+       b3Vector3DoubleData m_bvhAabbMin;
+       b3Vector3DoubleData m_bvhAabbMax;
+       b3Vector3DoubleData m_bvhQuantization;
+       int m_curNodeIndex;
+       int m_useQuantization;
+       int m_numContiguousLeafNodes;
+       int m_numQuantizedContiguousNodes;
+       b3OptimizedBvhNodeDoubleData* m_contiguousNodesPtr;
+       b3QuantizedBvhNodeData* m_quantizedContiguousNodesPtr;
+
+       int m_traversalMode;
+       int m_numSubtreeHeaders;
+       b3BvhSubtreeInfoData* m_subTreeInfoPtr;
+};
+
+B3_FORCE_INLINE int b3QuantizedBvh::calculateSerializeBufferSizeNew() const
+{
+       return sizeof(b3QuantizedBvhData);
+}
+
+#endif  //B3_QUANTIZED_BVH_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp
new file mode 100644 (file)
index 0000000..6b0c941
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3StridingMeshInterface.h"
+
+b3StridingMeshInterface::~b3StridingMeshInterface()
+{
+}
+
+void b3StridingMeshInterface::InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
+{
+       (void)aabbMin;
+       (void)aabbMax;
+       int numtotalphysicsverts = 0;
+       int part, graphicssubparts = getNumSubParts();
+       const unsigned char* vertexbase;
+       const unsigned char* indexbase;
+       int indexstride;
+       PHY_ScalarType type;
+       PHY_ScalarType gfxindextype;
+       int stride, numverts, numtriangles;
+       int gfxindex;
+       b3Vector3 triangle[3];
+
+       b3Vector3 meshScaling = getScaling();
+
+       ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
+       for (part = 0; part < graphicssubparts; part++)
+       {
+               getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
+               numtotalphysicsverts += numtriangles * 3;  //upper bound
+
+               ///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
+               ///so disable this feature by default
+               ///see patch http://code.google.com/p/bullet/issues/detail?id=213
+
+               switch (type)
+               {
+                       case PHY_FLOAT:
+                       {
+                               float* graphicsbase;
+
+                               switch (gfxindextype)
+                               {
+                                       case PHY_INTEGER:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       case PHY_SHORT:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       case PHY_UCHAR:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       default:
+                                               b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+                               }
+                               break;
+                       }
+
+                       case PHY_DOUBLE:
+                       {
+                               double* graphicsbase;
+
+                               switch (gfxindextype)
+                               {
+                                       case PHY_INTEGER:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       case PHY_SHORT:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       case PHY_UCHAR:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       default:
+                                               b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+                               }
+                               break;
+                       }
+                       default:
+                               b3Assert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+               }
+
+               unLockReadOnlyVertexBase(part);
+       }
+}
+
+void b3StridingMeshInterface::calculateAabbBruteForce(b3Vector3& aabbMin, b3Vector3& aabbMax)
+{
+       struct AabbCalculationCallback : public b3InternalTriangleIndexCallback
+       {
+               b3Vector3 m_aabbMin;
+               b3Vector3 m_aabbMax;
+
+               AabbCalculationCallback()
+               {
+                       m_aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+                       m_aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
+               }
+
+               virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
+               {
+                       (void)partId;
+                       (void)triangleIndex;
+
+                       m_aabbMin.setMin(triangle[0]);
+                       m_aabbMax.setMax(triangle[0]);
+                       m_aabbMin.setMin(triangle[1]);
+                       m_aabbMax.setMax(triangle[1]);
+                       m_aabbMin.setMin(triangle[2]);
+                       m_aabbMax.setMax(triangle[2]);
+               }
+       };
+
+       //first calculate the total aabb for all triangles
+       AabbCalculationCallback aabbCallback;
+       aabbMin.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
+       aabbMax.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+       InternalProcessAllTriangles(&aabbCallback, aabbMin, aabbMax);
+
+       aabbMin = aabbCallback.m_aabbMin;
+       aabbMax = aabbCallback.m_aabbMax;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
new file mode 100644 (file)
index 0000000..2b1e63b
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_STRIDING_MESHINTERFACE_H
+#define B3_STRIDING_MESHINTERFACE_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "b3TriangleCallback.h"
+//#include "b3ConcaveShape.h"
+
+enum PHY_ScalarType
+{
+       PHY_FLOAT,
+       PHY_DOUBLE,
+       PHY_INTEGER,
+       PHY_SHORT,
+       PHY_FIXEDPOINT88,
+       PHY_UCHAR
+};
+
+///    The b3StridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with b3BvhTriangleMeshShape 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.
+B3_ATTRIBUTE_ALIGNED16(class)
+b3StridingMeshInterface
+{
+protected:
+       b3Vector3 m_scaling;
+
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       b3StridingMeshInterface() : m_scaling(b3MakeVector3(b3Scalar(1.), b3Scalar(1.), b3Scalar(1.)))
+       {
+       }
+
+       virtual ~b3StridingMeshInterface();
+
+       virtual void InternalProcessAllTriangles(b3InternalTriangleIndexCallback * callback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
+
+       ///brute force method to calculate aabb
+       void calculateAabbBruteForce(b3Vector3 & aabbMin, b3Vector3 & aabbMax);
+
+       /// get read and write access to a subpart of a triangle mesh
+       /// this subpart has a continuous array of vertices and indices
+       /// in this way the mesh can be handled as chunks of memory with striding
+       /// very similar to OpenGL vertexarray support
+       /// make a call to unLockVertexBase when the read and write access is finished
+       virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) = 0;
+
+       virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const = 0;
+
+       /// unLockVertexBase finishes the access to a subpart of the triangle mesh
+       /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+       virtual void unLockVertexBase(int subpart) = 0;
+
+       virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
+
+       /// getNumSubParts returns the number of separate subparts
+       /// each subpart has a continuous array of vertices and indices
+       virtual int getNumSubParts() const = 0;
+
+       virtual void preallocateVertices(int numverts) = 0;
+       virtual void preallocateIndices(int numindices) = 0;
+
+       virtual bool hasPremadeAabb() const { return false; }
+       virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
+       {
+               (void)aabbMin;
+               (void)aabbMax;
+       }
+       virtual void getPremadeAabb(b3Vector3 * aabbMin, b3Vector3 * aabbMax) const
+       {
+               (void)aabbMin;
+               (void)aabbMax;
+       }
+
+       const b3Vector3& getScaling() const
+       {
+               return m_scaling;
+       }
+       void setScaling(const b3Vector3& scaling)
+       {
+               m_scaling = scaling;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       //virtual       const char*     serialize(void* dataBuffer, b3Serializer* serializer) const;
+};
+
+struct b3IntIndexData
+{
+       int m_value;
+};
+
+struct b3ShortIntIndexData
+{
+       short m_value;
+       char m_pad[2];
+};
+
+struct b3ShortIntIndexTripletData
+{
+       short m_values[3];
+       char m_pad[2];
+};
+
+struct b3CharIndexTripletData
+{
+       unsigned char m_values[3];
+       char m_pad;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3MeshPartData
+{
+       b3Vector3FloatData* m_vertices3f;
+       b3Vector3DoubleData* m_vertices3d;
+
+       b3IntIndexData* m_indices32;
+       b3ShortIntIndexTripletData* m_3indices16;
+       b3CharIndexTripletData* m_3indices8;
+
+       b3ShortIntIndexData* m_indices16;  //backwards compatibility
+
+       int m_numTriangles;  //length of m_indices = m_numTriangles
+       int m_numVertices;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct b3StridingMeshInterfaceData
+{
+       b3MeshPartData* m_meshPartsPtr;
+       b3Vector3FloatData m_scaling;
+       int m_numMeshParts;
+       char m_padding[4];
+};
+
+B3_FORCE_INLINE int b3StridingMeshInterface::calculateSerializeBufferSize() const
+{
+       return sizeof(b3StridingMeshInterfaceData);
+}
+
+#endif  //B3_STRIDING_MESHINTERFACE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h
new file mode 100644 (file)
index 0000000..9ca1e22
--- /dev/null
@@ -0,0 +1,34 @@
+
+#ifndef B3_SUPPORT_MAPPINGS_H
+#define B3_SUPPORT_MAPPINGS_H
+
+#include "Bullet3Common/b3Transform.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "b3VectorFloat4.h"
+
+struct b3GjkPairDetector;
+
+inline b3Vector3 localGetSupportVertexWithMargin(const float4& supportVec, const struct b3ConvexPolyhedronData* hull,
+                                                                                                const b3AlignedObjectArray<b3Vector3>& verticesA, b3Scalar margin)
+{
+       b3Vector3 supVec = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+       b3Scalar maxDot = b3Scalar(-B3_LARGE_FLOAT);
+
+       // Here we take advantage of dot(a, b*c) = dot(a*b, c).  Note: This is true mathematically, but not numerically.
+       if (0 < hull->m_numVertices)
+       {
+               const b3Vector3 scaled = supportVec;
+               int index = (int)scaled.maxDot(&verticesA[hull->m_vertexOffset], hull->m_numVertices, maxDot);
+               return verticesA[hull->m_vertexOffset + index];
+       }
+
+       return supVec;
+}
+
+inline b3Vector3 localGetSupportVertexWithoutMargin(const float4& supportVec, const struct b3ConvexPolyhedronData* hull,
+                                                                                                       const b3AlignedObjectArray<b3Vector3>& verticesA)
+{
+       return localGetSupportVertexWithMargin(supportVec, hull, verticesA, 0.f);
+}
+
+#endif  //B3_SUPPORT_MAPPINGS_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp
new file mode 100644 (file)
index 0000000..3908c6d
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3TriangleCallback.h"
+
+b3TriangleCallback::~b3TriangleCallback()
+{
+}
+
+b3InternalTriangleIndexCallback::~b3InternalTriangleIndexCallback()
+{
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h
new file mode 100644 (file)
index 0000000..a0fd3e7
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_TRIANGLE_CALLBACK_H
+#define B3_TRIANGLE_CALLBACK_H
+
+#include "Bullet3Common/b3Vector3.h"
+
+///The b3TriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
+///This callback is called by processAllTriangles for all b3ConcaveShape derived class, such as  b3BvhTriangleMeshShape, b3StaticPlaneShape and b3HeightfieldTerrainShape.
+class b3TriangleCallback
+{
+public:
+       virtual ~b3TriangleCallback();
+       virtual void processTriangle(b3Vector3* triangle, int partId, int triangleIndex) = 0;
+};
+
+class b3InternalTriangleIndexCallback
+{
+public:
+       virtual ~b3InternalTriangleIndexCallback();
+       virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex) = 0;
+};
+
+#endif  //B3_TRIANGLE_CALLBACK_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp
new file mode 100644 (file)
index 0000000..73faadb
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "b3TriangleIndexVertexArray.h"
+
+b3TriangleIndexVertexArray::b3TriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, b3Scalar* vertexBase, int vertexStride)
+       : m_hasAabb(0)
+{
+       b3IndexedMesh 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);
+}
+
+b3TriangleIndexVertexArray::~b3TriangleIndexVertexArray()
+{
+}
+
+void b3TriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart)
+{
+       b3Assert(subpart < getNumSubParts());
+
+       b3IndexedMesh& mesh = m_indexedMeshes[subpart];
+
+       numverts = mesh.m_numVertices;
+       (*vertexbase) = (unsigned char*)mesh.m_vertexBase;
+
+       type = mesh.m_vertexType;
+
+       vertexStride = mesh.m_vertexStride;
+
+       numfaces = mesh.m_numTriangles;
+
+       (*indexbase) = (unsigned char*)mesh.m_triangleIndexBase;
+       indexstride = mesh.m_triangleIndexStride;
+       indicestype = mesh.m_indexType;
+}
+
+void b3TriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart) const
+{
+       const b3IndexedMesh& mesh = m_indexedMeshes[subpart];
+
+       numverts = mesh.m_numVertices;
+       (*vertexbase) = (const unsigned char*)mesh.m_vertexBase;
+
+       type = mesh.m_vertexType;
+
+       vertexStride = mesh.m_vertexStride;
+
+       numfaces = mesh.m_numTriangles;
+       (*indexbase) = (const unsigned char*)mesh.m_triangleIndexBase;
+       indexstride = mesh.m_triangleIndexStride;
+       indicestype = mesh.m_indexType;
+}
+
+bool b3TriangleIndexVertexArray::hasPremadeAabb() const
+{
+       return (m_hasAabb == 1);
+}
+
+void b3TriangleIndexVertexArray::setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
+{
+       m_aabbMin = aabbMin;
+       m_aabbMax = aabbMax;
+       m_hasAabb = 1;  // this is intentionally an int see notes in header
+}
+
+void b3TriangleIndexVertexArray::getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax) const
+{
+       *aabbMin = m_aabbMin;
+       *aabbMax = m_aabbMax;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
new file mode 100644 (file)
index 0000000..57cbf03
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#define B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
+
+#include "b3StridingMeshInterface.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Scalar.h"
+
+///The b3IndexedMesh indexes a single vertex and index array. Multiple b3IndexedMesh objects can be passed into a b3TriangleIndexVertexArray using addIndexedMesh.
+///Instead of the number of indices, we pass the number of triangles.
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3IndexedMesh
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       int m_numTriangles;
+       const unsigned char* m_triangleIndexBase;
+       // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
+       int m_triangleIndexStride;
+       int m_numVertices;
+       const unsigned char* m_vertexBase;
+       // Size of a vertex, in bytes
+       int m_vertexStride;
+
+       // The index type is set when adding an indexed mesh to the
+       // b3TriangleIndexVertexArray, do not set it manually
+       PHY_ScalarType m_indexType;
+
+       // The vertex type has a default type similar to Bullet's precision mode (float or double)
+       // but can be set manually if you for example run Bullet with double precision but have
+       // mesh data in single precision..
+       PHY_ScalarType m_vertexType;
+
+       b3IndexedMesh()
+               : m_indexType(PHY_INTEGER),
+#ifdef B3_USE_DOUBLE_PRECISION
+                 m_vertexType(PHY_DOUBLE)
+#else   // B3_USE_DOUBLE_PRECISION
+                 m_vertexType(PHY_FLOAT)
+#endif  // B3_USE_DOUBLE_PRECISION
+       {
+       }
+};
+
+typedef b3AlignedObjectArray<b3IndexedMesh> IndexedMeshArray;
+
+///The b3TriangleIndexVertexArray 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 b3TriangleIndexVertexArray.
+B3_ATTRIBUTE_ALIGNED16(class)
+b3TriangleIndexVertexArray : public b3StridingMeshInterface
+{
+protected:
+       IndexedMeshArray m_indexedMeshes;
+       int m_pad[2];
+       mutable int m_hasAabb;  // using int instead of bool to maintain alignment
+       mutable b3Vector3 m_aabbMin;
+       mutable b3Vector3 m_aabbMax;
+
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       b3TriangleIndexVertexArray() : m_hasAabb(0)
+       {
+       }
+
+       virtual ~b3TriangleIndexVertexArray();
+
+       //just to be backwards compatible
+       b3TriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, b3Scalar* vertexBase, int vertexStride);
+
+       void addIndexedMesh(const b3IndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
+       {
+               m_indexedMeshes.push_back(mesh);
+               m_indexedMeshes[m_indexedMeshes.size() - 1].m_indexType = indexType;
+       }
+
+       virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0);
+
+       virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const;
+
+       /// unLockVertexBase finishes the access to a subpart of the triangle mesh
+       /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+       virtual void unLockVertexBase(int subpart) { (void)subpart; }
+
+       virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
+
+       /// getNumSubParts returns the number of separate subparts
+       /// each subpart has a continuous array of vertices and indices
+       virtual int getNumSubParts() const
+       {
+               return (int)m_indexedMeshes.size();
+       }
+
+       IndexedMeshArray& getIndexedMeshArray()
+       {
+               return m_indexedMeshes;
+       }
+
+       const IndexedMeshArray& getIndexedMeshArray() const
+       {
+               return m_indexedMeshes;
+       }
+
+       virtual void preallocateVertices(int numverts) { (void)numverts; }
+       virtual void preallocateIndices(int numindices) { (void)numindices; }
+
+       virtual bool hasPremadeAabb() const;
+       virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
+       virtual void getPremadeAabb(b3Vector3 * aabbMin, b3Vector3 * aabbMax) const;
+};
+
+#endif  //B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h
new file mode 100644 (file)
index 0000000..5cc4b5a
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef B3_VECTOR_FLOAT4_H
+#define B3_VECTOR_FLOAT4_H
+
+#include "Bullet3Common/b3Transform.h"
+
+//#define cross3(a,b) (a.cross(b))
+#define float4 b3Vector3
+//#define make_float4(x,y,z,w) b3Vector4(x,y,z,w)
+
+#endif  //B3_VECTOR_FLOAT4_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
new file mode 100644 (file)
index 0000000..c599bca
--- /dev/null
@@ -0,0 +1,574 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+       
+       Elsevier CDROM license agreements grants nonexclusive license to use the software
+       for any purpose, commercial or non-commercial as long as the following credit is included
+       identifying the original source of the software:
+
+       Parts of the source are "from the book Real-Time Collision Detection by
+       Christer Ericson, published by Morgan Kaufmann Publishers,
+       (c) 2005 Elsevier Inc."
+               
+*/
+
+#include "b3VoronoiSimplexSolver.h"
+
+#define VERTA 0
+#define VERTB 1
+#define VERTC 2
+#define VERTD 3
+
+#define B3_CATCH_DEGENERATE_TETRAHEDRON 1
+void b3VoronoiSimplexSolver::removeVertex(int index)
+{
+       b3Assert(m_numVertices > 0);
+       m_numVertices--;
+       m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
+       m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
+       m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
+}
+
+void b3VoronoiSimplexSolver::reduceVertices(const b3UsageBitfield& usedVerts)
+{
+       if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
+               removeVertex(3);
+
+       if ((numVertices() >= 3) && (!usedVerts.usedVertexC))
+               removeVertex(2);
+
+       if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
+               removeVertex(1);
+
+       if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
+               removeVertex(0);
+}
+
+//clear the simplex, remove all the vertices
+void b3VoronoiSimplexSolver::reset()
+{
+       m_cachedValidClosest = false;
+       m_numVertices = 0;
+       m_needsUpdate = true;
+       m_lastW = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
+       m_cachedBC.reset();
+}
+
+//add a vertex
+void b3VoronoiSimplexSolver::addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q)
+{
+       m_lastW = w;
+       m_needsUpdate = true;
+
+       m_simplexVectorW[m_numVertices] = w;
+       m_simplexPointsP[m_numVertices] = p;
+       m_simplexPointsQ[m_numVertices] = q;
+
+       m_numVertices++;
+}
+
+bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
+{
+       if (m_needsUpdate)
+       {
+               m_cachedBC.reset();
+
+               m_needsUpdate = false;
+
+               switch (numVertices())
+               {
+                       case 0:
+                               m_cachedValidClosest = false;
+                               break;
+                       case 1:
+                       {
+                               m_cachedP1 = m_simplexPointsP[0];
+                               m_cachedP2 = m_simplexPointsQ[0];
+                               m_cachedV = m_cachedP1 - m_cachedP2;  //== m_simplexVectorW[0]
+                               m_cachedBC.reset();
+                               m_cachedBC.setBarycentricCoordinates(b3Scalar(1.), b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+                               m_cachedValidClosest = m_cachedBC.isValid();
+                               break;
+                       };
+                       case 2:
+                       {
+                               //closest point origin from line segment
+                               const b3Vector3& from = m_simplexVectorW[0];
+                               const b3Vector3& to = m_simplexVectorW[1];
+                               b3Vector3 nearest;
+
+                               b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+                               b3Vector3 diff = p - from;
+                               b3Vector3 v = to - from;
+                               b3Scalar t = v.dot(diff);
+
+                               if (t > 0)
+                               {
+                                       b3Scalar dotVV = v.dot(v);
+                                       if (t < dotVV)
+                                       {
+                                               t /= dotVV;
+                                               diff -= t * v;
+                                               m_cachedBC.m_usedVertices.usedVertexA = true;
+                                               m_cachedBC.m_usedVertices.usedVertexB = true;
+                                       }
+                                       else
+                                       {
+                                               t = 1;
+                                               diff -= v;
+                                               //reduce to 1 point
+                                               m_cachedBC.m_usedVertices.usedVertexB = true;
+                                       }
+                               }
+                               else
+                               {
+                                       t = 0;
+                                       //reduce to 1 point
+                                       m_cachedBC.m_usedVertices.usedVertexA = true;
+                               }
+                               m_cachedBC.setBarycentricCoordinates(1 - t, t);
+                               nearest = from + t * v;
+
+                               m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
+                               m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
+                               m_cachedV = m_cachedP1 - m_cachedP2;
+
+                               reduceVertices(m_cachedBC.m_usedVertices);
+
+                               m_cachedValidClosest = m_cachedBC.isValid();
+                               break;
+                       }
+                       case 3:
+                       {
+                               //closest point origin from triangle
+                               b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+
+                               const b3Vector3& a = m_simplexVectorW[0];
+                               const b3Vector3& b = m_simplexVectorW[1];
+                               const b3Vector3& c = m_simplexVectorW[2];
+
+                               closestPtPointTriangle(p, a, b, c, m_cachedBC);
+                               m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+                                                        m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+                                                        m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
+
+                               m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+                                                        m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+                                                        m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
+
+                               m_cachedV = m_cachedP1 - m_cachedP2;
+
+                               reduceVertices(m_cachedBC.m_usedVertices);
+                               m_cachedValidClosest = m_cachedBC.isValid();
+
+                               break;
+                       }
+                       case 4:
+                       {
+                               b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+
+                               const b3Vector3& a = m_simplexVectorW[0];
+                               const b3Vector3& b = m_simplexVectorW[1];
+                               const b3Vector3& c = m_simplexVectorW[2];
+                               const b3Vector3& d = m_simplexVectorW[3];
+
+                               bool hasSeparation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
+
+                               if (hasSeparation)
+                               {
+                                       m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+                                                                m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+                                                                m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
+                                                                m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
+
+                                       m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+                                                                m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+                                                                m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
+                                                                m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
+
+                                       m_cachedV = m_cachedP1 - m_cachedP2;
+                                       reduceVertices(m_cachedBC.m_usedVertices);
+                               }
+                               else
+                               {
+                                       //                                      printf("sub distance got penetration\n");
+
+                                       if (m_cachedBC.m_degenerate)
+                                       {
+                                               m_cachedValidClosest = false;
+                                       }
+                                       else
+                                       {
+                                               m_cachedValidClosest = true;
+                                               //degenerate case == false, penetration = true + zero
+                                               m_cachedV.setValue(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
+                                       }
+                                       break;
+                               }
+
+                               m_cachedValidClosest = m_cachedBC.isValid();
+
+                               //closest point origin from tetrahedron
+                               break;
+                       }
+                       default:
+                       {
+                               m_cachedValidClosest = false;
+                       }
+               };
+       }
+
+       return m_cachedValidClosest;
+}
+
+//return/calculate the closest vertex
+bool b3VoronoiSimplexSolver::closest(b3Vector3& v)
+{
+       bool succes = updateClosestVectorAndPoints();
+       v = m_cachedV;
+       return succes;
+}
+
+b3Scalar b3VoronoiSimplexSolver::maxVertex()
+{
+       int i, numverts = numVertices();
+       b3Scalar maxV = b3Scalar(0.);
+       for (i = 0; i < numverts; i++)
+       {
+               b3Scalar curLen2 = m_simplexVectorW[i].length2();
+               if (maxV < curLen2)
+                       maxV = curLen2;
+       }
+       return maxV;
+}
+
+//return the current simplex
+int b3VoronoiSimplexSolver::getSimplex(b3Vector3* pBuf, b3Vector3* qBuf, b3Vector3* yBuf) const
+{
+       int i;
+       for (i = 0; i < numVertices(); i++)
+       {
+               yBuf[i] = m_simplexVectorW[i];
+               pBuf[i] = m_simplexPointsP[i];
+               qBuf[i] = m_simplexPointsQ[i];
+       }
+       return numVertices();
+}
+
+bool b3VoronoiSimplexSolver::inSimplex(const b3Vector3& w)
+{
+       bool found = false;
+       int i, numverts = numVertices();
+       //b3Scalar maxV = b3Scalar(0.);
+
+       //w is in the current (reduced) simplex
+       for (i = 0; i < numverts; i++)
+       {
+#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
+               if (m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
+#else
+               if (m_simplexVectorW[i] == w)
+#endif
+                       found = true;
+       }
+
+       //check in case lastW is already removed
+       if (w == m_lastW)
+               return true;
+
+       return found;
+}
+
+void b3VoronoiSimplexSolver::backup_closest(b3Vector3& v)
+{
+       v = m_cachedV;
+}
+
+bool b3VoronoiSimplexSolver::emptySimplex() const
+{
+       return (numVertices() == 0);
+}
+
+void b3VoronoiSimplexSolver::compute_points(b3Vector3& p1, b3Vector3& p2)
+{
+       updateClosestVectorAndPoints();
+       p1 = m_cachedP1;
+       p2 = m_cachedP2;
+}
+
+bool b3VoronoiSimplexSolver::closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, b3SubSimplexClosestResult& result)
+{
+       result.m_usedVertices.reset();
+
+       // Check if P in vertex region outside A
+       b3Vector3 ab = b - a;
+       b3Vector3 ac = c - a;
+       b3Vector3 ap = p - a;
+       b3Scalar d1 = ab.dot(ap);
+       b3Scalar d2 = ac.dot(ap);
+       if (d1 <= b3Scalar(0.0) && d2 <= b3Scalar(0.0))
+       {
+               result.m_closestPointOnSimplex = a;
+               result.m_usedVertices.usedVertexA = true;
+               result.setBarycentricCoordinates(1, 0, 0);
+               return true;  // a; // barycentric coordinates (1,0,0)
+       }
+
+       // Check if P in vertex region outside B
+       b3Vector3 bp = p - b;
+       b3Scalar d3 = ab.dot(bp);
+       b3Scalar d4 = ac.dot(bp);
+       if (d3 >= b3Scalar(0.0) && d4 <= d3)
+       {
+               result.m_closestPointOnSimplex = b;
+               result.m_usedVertices.usedVertexB = true;
+               result.setBarycentricCoordinates(0, 1, 0);
+
+               return true;  // b; // barycentric coordinates (0,1,0)
+       }
+       // Check if P in edge region of AB, if so return projection of P onto AB
+       b3Scalar vc = d1 * d4 - d3 * d2;
+       if (vc <= b3Scalar(0.0) && d1 >= b3Scalar(0.0) && d3 <= b3Scalar(0.0))
+       {
+               b3Scalar v = d1 / (d1 - d3);
+               result.m_closestPointOnSimplex = a + v * ab;
+               result.m_usedVertices.usedVertexA = true;
+               result.m_usedVertices.usedVertexB = true;
+               result.setBarycentricCoordinates(1 - v, v, 0);
+               return true;
+               //return a + v * ab; // barycentric coordinates (1-v,v,0)
+       }
+
+       // Check if P in vertex region outside C
+       b3Vector3 cp = p - c;
+       b3Scalar d5 = ab.dot(cp);
+       b3Scalar d6 = ac.dot(cp);
+       if (d6 >= b3Scalar(0.0) && d5 <= d6)
+       {
+               result.m_closestPointOnSimplex = c;
+               result.m_usedVertices.usedVertexC = true;
+               result.setBarycentricCoordinates(0, 0, 1);
+               return true;  //c; // barycentric coordinates (0,0,1)
+       }
+
+       // Check if P in edge region of AC, if so return projection of P onto AC
+       b3Scalar vb = d5 * d2 - d1 * d6;
+       if (vb <= b3Scalar(0.0) && d2 >= b3Scalar(0.0) && d6 <= b3Scalar(0.0))
+       {
+               b3Scalar w = d2 / (d2 - d6);
+               result.m_closestPointOnSimplex = a + w * ac;
+               result.m_usedVertices.usedVertexA = true;
+               result.m_usedVertices.usedVertexC = true;
+               result.setBarycentricCoordinates(1 - w, 0, w);
+               return true;
+               //return a + w * ac; // barycentric coordinates (1-w,0,w)
+       }
+
+       // Check if P in edge region of BC, if so return projection of P onto BC
+       b3Scalar va = d3 * d6 - d5 * d4;
+       if (va <= b3Scalar(0.0) && (d4 - d3) >= b3Scalar(0.0) && (d5 - d6) >= b3Scalar(0.0))
+       {
+               b3Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
+
+               result.m_closestPointOnSimplex = b + w * (c - b);
+               result.m_usedVertices.usedVertexB = true;
+               result.m_usedVertices.usedVertexC = true;
+               result.setBarycentricCoordinates(0, 1 - w, w);
+               return true;
+               // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
+       }
+
+       // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
+       b3Scalar denom = b3Scalar(1.0) / (va + vb + vc);
+       b3Scalar v = vb * denom;
+       b3Scalar w = vc * denom;
+
+       result.m_closestPointOnSimplex = a + ab * v + ac * w;
+       result.m_usedVertices.usedVertexA = true;
+       result.m_usedVertices.usedVertexB = true;
+       result.m_usedVertices.usedVertexC = true;
+       result.setBarycentricCoordinates(1 - v - w, v, w);
+
+       return true;
+       //      return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = b3Scalar(1.0) - v - w
+}
+
+/// Test if point p and d lie on opposite sides of plane through abc
+int b3VoronoiSimplexSolver::pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d)
+{
+       b3Vector3 normal = (b - a).cross(c - a);
+
+       b3Scalar signp = (p - a).dot(normal);  // [AP AB AC]
+       b3Scalar signd = (d - a).dot(normal);  // [AD AB AC]
+
+#ifdef B3_CATCH_DEGENERATE_TETRAHEDRON
+#ifdef BT_USE_DOUBLE_PRECISION
+       if (signd * signd < (b3Scalar(1e-8) * b3Scalar(1e-8)))
+       {
+               return -1;
+       }
+#else
+       if (signd * signd < (b3Scalar(1e-4) * b3Scalar(1e-4)))
+       {
+               //              printf("affine dependent/degenerate\n");//
+               return -1;
+       }
+#endif
+
+#endif
+       // Points on opposite sides if expression signs are opposite
+       return signp * signd < b3Scalar(0.);
+}
+
+bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult)
+{
+       b3SubSimplexClosestResult tempResult;
+
+       // Start out assuming point inside all halfspaces, so closest to itself
+       finalResult.m_closestPointOnSimplex = p;
+       finalResult.m_usedVertices.reset();
+       finalResult.m_usedVertices.usedVertexA = true;
+       finalResult.m_usedVertices.usedVertexB = true;
+       finalResult.m_usedVertices.usedVertexC = true;
+       finalResult.m_usedVertices.usedVertexD = true;
+
+       int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
+       int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
+       int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
+       int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
+
+       if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
+       {
+               finalResult.m_degenerate = true;
+               return false;
+       }
+
+       if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
+       {
+               return false;
+       }
+
+       b3Scalar bestSqDist = FLT_MAX;
+       // If point outside face abc then compute closest point on abc
+       if (pointOutsideABC)
+       {
+               closestPtPointTriangle(p, a, b, c, tempResult);
+               b3Vector3 q = tempResult.m_closestPointOnSimplex;
+
+               b3Scalar sqDist = (q - p).dot(q - p);
+               // Update best closest point if (squared) distance is less than current best
+               if (sqDist < bestSqDist)
+               {
+                       bestSqDist = sqDist;
+                       finalResult.m_closestPointOnSimplex = q;
+                       //convert result bitmask!
+                       finalResult.m_usedVertices.reset();
+                       finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+                       finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
+                       finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+                       finalResult.setBarycentricCoordinates(
+                               tempResult.m_barycentricCoords[VERTA],
+                               tempResult.m_barycentricCoords[VERTB],
+                               tempResult.m_barycentricCoords[VERTC],
+                               0);
+               }
+       }
+
+       // Repeat test for face acd
+       if (pointOutsideACD)
+       {
+               closestPtPointTriangle(p, a, c, d, tempResult);
+               b3Vector3 q = tempResult.m_closestPointOnSimplex;
+               //convert result bitmask!
+
+               b3Scalar sqDist = (q - p).dot(q - p);
+               if (sqDist < bestSqDist)
+               {
+                       bestSqDist = sqDist;
+                       finalResult.m_closestPointOnSimplex = q;
+                       finalResult.m_usedVertices.reset();
+                       finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+
+                       finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
+                       finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
+                       finalResult.setBarycentricCoordinates(
+                               tempResult.m_barycentricCoords[VERTA],
+                               0,
+                               tempResult.m_barycentricCoords[VERTB],
+                               tempResult.m_barycentricCoords[VERTC]);
+               }
+       }
+       // Repeat test for face adb
+
+       if (pointOutsideADB)
+       {
+               closestPtPointTriangle(p, a, d, b, tempResult);
+               b3Vector3 q = tempResult.m_closestPointOnSimplex;
+               //convert result bitmask!
+
+               b3Scalar sqDist = (q - p).dot(q - p);
+               if (sqDist < bestSqDist)
+               {
+                       bestSqDist = sqDist;
+                       finalResult.m_closestPointOnSimplex = q;
+                       finalResult.m_usedVertices.reset();
+                       finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+                       finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
+
+                       finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+                       finalResult.setBarycentricCoordinates(
+                               tempResult.m_barycentricCoords[VERTA],
+                               tempResult.m_barycentricCoords[VERTC],
+                               0,
+                               tempResult.m_barycentricCoords[VERTB]);
+               }
+       }
+       // Repeat test for face bdc
+
+       if (pointOutsideBDC)
+       {
+               closestPtPointTriangle(p, b, d, c, tempResult);
+               b3Vector3 q = tempResult.m_closestPointOnSimplex;
+               //convert result bitmask!
+               b3Scalar sqDist = (q - p).dot(q - p);
+               if (sqDist < bestSqDist)
+               {
+                       bestSqDist = sqDist;
+                       finalResult.m_closestPointOnSimplex = q;
+                       finalResult.m_usedVertices.reset();
+                       //
+                       finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
+                       finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+                       finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+
+                       finalResult.setBarycentricCoordinates(
+                               0,
+                               tempResult.m_barycentricCoords[VERTA],
+                               tempResult.m_barycentricCoords[VERTC],
+                               tempResult.m_barycentricCoords[VERTB]);
+               }
+       }
+
+       //help! we ended up full !
+
+       if (finalResult.m_usedVertices.usedVertexA &&
+               finalResult.m_usedVertices.usedVertexB &&
+               finalResult.m_usedVertices.usedVertexC &&
+               finalResult.m_usedVertices.usedVertexD)
+       {
+               return true;
+       }
+
+       return true;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h
new file mode 100644 (file)
index 0000000..46e36a3
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_VORONOI_SIMPLEX_SOLVER_H
+#define B3_VORONOI_SIMPLEX_SOLVER_H
+
+#include "Bullet3Common/b3Vector3.h"
+
+#define VORONOI_SIMPLEX_MAX_VERTS 5
+
+///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
+//#define BT_USE_EQUAL_VERTEX_THRESHOLD
+#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
+
+struct b3UsageBitfield
+{
+       b3UsageBitfield()
+       {
+               reset();
+       }
+
+       void reset()
+       {
+               usedVertexA = false;
+               usedVertexB = false;
+               usedVertexC = false;
+               usedVertexD = false;
+       }
+       unsigned short usedVertexA : 1;
+       unsigned short usedVertexB : 1;
+       unsigned short usedVertexC : 1;
+       unsigned short usedVertexD : 1;
+       unsigned short unused1 : 1;
+       unsigned short unused2 : 1;
+       unsigned short unused3 : 1;
+       unsigned short unused4 : 1;
+};
+
+struct b3SubSimplexClosestResult
+{
+       b3Vector3 m_closestPointOnSimplex;
+       //MASK for m_usedVertices
+       //stores the simplex vertex-usage, using the MASK,
+       // if m_usedVertices & MASK then the related vertex is used
+       b3UsageBitfield m_usedVertices;
+       b3Scalar m_barycentricCoords[4];
+       bool m_degenerate;
+
+       void reset()
+       {
+               m_degenerate = false;
+               setBarycentricCoordinates();
+               m_usedVertices.reset();
+       }
+       bool isValid()
+       {
+               bool valid = (m_barycentricCoords[0] >= b3Scalar(0.)) &&
+                                        (m_barycentricCoords[1] >= b3Scalar(0.)) &&
+                                        (m_barycentricCoords[2] >= b3Scalar(0.)) &&
+                                        (m_barycentricCoords[3] >= b3Scalar(0.));
+
+               return valid;
+       }
+       void setBarycentricCoordinates(b3Scalar a = b3Scalar(0.), b3Scalar b = b3Scalar(0.), b3Scalar c = b3Scalar(0.), b3Scalar d = b3Scalar(0.))
+       {
+               m_barycentricCoords[0] = a;
+               m_barycentricCoords[1] = b;
+               m_barycentricCoords[2] = c;
+               m_barycentricCoords[3] = d;
+       }
+};
+
+/// b3VoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
+/// Can be used with GJK, as an alternative to Johnson distance algorithm.
+
+B3_ATTRIBUTE_ALIGNED16(class)
+b3VoronoiSimplexSolver
+{
+public:
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       int m_numVertices;
+
+       b3Vector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
+       b3Vector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
+       b3Vector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
+
+       b3Vector3 m_cachedP1;
+       b3Vector3 m_cachedP2;
+       b3Vector3 m_cachedV;
+       b3Vector3 m_lastW;
+
+       b3Scalar m_equalVertexThreshold;
+       bool m_cachedValidClosest;
+
+       b3SubSimplexClosestResult m_cachedBC;
+
+       bool m_needsUpdate;
+
+       void removeVertex(int index);
+       void reduceVertices(const b3UsageBitfield& usedVerts);
+       bool updateClosestVectorAndPoints();
+
+       bool closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult);
+       int pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d);
+       bool closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, b3SubSimplexClosestResult& result);
+
+public:
+       b3VoronoiSimplexSolver()
+               : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
+       {
+       }
+       void reset();
+
+       void addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q);
+
+       void setEqualVertexThreshold(b3Scalar threshold)
+       {
+               m_equalVertexThreshold = threshold;
+       }
+
+       b3Scalar getEqualVertexThreshold() const
+       {
+               return m_equalVertexThreshold;
+       }
+
+       bool closest(b3Vector3 & v);
+
+       b3Scalar maxVertex();
+
+       bool fullSimplex() const
+       {
+               return (m_numVertices == 4);
+       }
+
+       int getSimplex(b3Vector3 * pBuf, b3Vector3 * qBuf, b3Vector3 * yBuf) const;
+
+       bool inSimplex(const b3Vector3& w);
+
+       void backup_closest(b3Vector3 & v);
+
+       bool emptySimplex() const;
+
+       void compute_points(b3Vector3 & p1, b3Vector3 & p2);
+
+       int numVertices() const
+       {
+               return m_numVertices;
+       }
+};
+
+#endif  //B3_VORONOI_SIMPLEX_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl
new file mode 100644 (file)
index 0000000..faa4134
--- /dev/null
@@ -0,0 +1,283 @@
+//keep this enum in sync with the CPU version (in btCollidable.h)
+//written by Erwin Coumans
+
+#define SHAPE_CONVEX_HULL 3
+#define SHAPE_CONCAVE_TRIMESH 5
+#define TRIANGLE_NUM_CONVEX_FACES 5
+#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
+#define SHAPE_SPHERE 7
+
+typedef unsigned int u32;
+
+#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).
+typedef struct
+{
+       //12 bytes
+       unsigned short int      m_quantizedAabbMin[3];
+       unsigned short int      m_quantizedAabbMax[3];
+       //4 bytes
+       int     m_escapeIndexOrTriangleIndex;
+} btQuantizedBvhNode;
+
+typedef struct
+{
+       float4          m_aabbMin;
+       float4          m_aabbMax;
+       float4          m_quantization;
+       int                     m_numNodes;
+       int                     m_numSubTrees;
+       int                     m_nodeOffset;
+       int                     m_subTreeOffset;
+
+} b3BvhInfo;
+
+int    getTriangleIndex(const btQuantizedBvhNode* rootNode)
+{
+       unsigned int x=0;
+       unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+       // Get only the lower bits where the triangle index is stored
+       return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+int isLeaf(const btQuantizedBvhNode* rootNode)
+{
+       //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+       return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+       
+int getEscapeIndex(const btQuantizedBvhNode* rootNode)
+{
+       return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+typedef struct
+{
+       //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;
+
+///keep this in sync with btCollidable.h
+typedef struct
+{
+       int m_numChildShapes;
+       int blaat2;
+       int m_shapeType;
+       int m_shapeIndex;
+       
+} btCollidableGpu;
+
+typedef struct
+{
+       float4  m_childPosition;
+       float4  m_childOrientation;
+       int m_shapeIndex;
+       int m_unused0;
+       int m_unused1;
+       int m_unused2;
+} btGpuChildShape;
+
+
+typedef struct
+{
+       float4 m_pos;
+       float4 m_quat;
+       float4 m_linVel;
+       float4 m_angVel;
+
+       u32 m_collidableIdx;
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+} BodyData;
+
+typedef struct 
+{
+       union
+       {
+               float4  m_min;
+               float   m_minElems[4];
+               int                     m_minIndices[4];
+       };
+       union
+       {
+               float4  m_max;
+               float   m_maxElems[4];
+               int                     m_maxIndices[4];
+       };
+} btAabbCL;
+
+
+int testQuantizedAabbAgainstQuantizedAabb(
+                                                               const unsigned short int* aabbMin1,
+                                                               const unsigned short int* aabbMax1,
+                                                               const unsigned short int* aabbMin2,
+                                                               const unsigned short int* aabbMax2)
+{
+       //int overlap = 1;
+       if (aabbMin1[0] > aabbMax2[0])
+               return 0;
+       if (aabbMax1[0] < aabbMin2[0])
+               return 0;
+       if (aabbMin1[1] > aabbMax2[1])
+               return 0;
+       if (aabbMax1[1] < aabbMin2[1])
+               return 0;
+       if (aabbMin1[2] > aabbMax2[2])
+               return 0;
+       if (aabbMax1[2] < aabbMin2[2])
+               return 0;
+       return 1;
+       //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;
+       //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;
+       //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;
+       //return overlap;
+}
+
+
+void quantizeWithClamp(unsigned short* out, float4 point2,int isMax, float4 bvhAabbMin, float4 bvhAabbMax, float4 bvhQuantization)
+{
+       float4 clampedPoint = max(point2,bvhAabbMin);
+       clampedPoint = min (clampedPoint, bvhAabbMax);
+
+       float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;
+       if (isMax)
+       {
+               out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));
+               out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));
+               out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));
+       } else
+       {
+               out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));
+               out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));
+               out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));
+       }
+
+}
+
+
+// work-in-progress
+__kernel void   bvhTraversalKernel( __global const int4* pairs, 
+                                                                       __global const BodyData* rigidBodies, 
+                                                                       __global const btCollidableGpu* collidables,
+                                                                       __global btAabbCL* aabbs,
+                                                                       __global int4* concavePairsOut,
+                                                                       __global volatile int* numConcavePairsOut,
+                                                                       __global const btBvhSubtreeInfo* subtreeHeadersRoot,
+                                                                       __global const btQuantizedBvhNode* quantizedNodesRoot,
+                                                                       __global const b3BvhInfo* bvhInfos,
+                                                                       int numPairs,
+                                                                       int maxNumConcavePairsCapacity)
+{
+       int id = get_global_id(0);
+       if (id>=numPairs)
+               return;
+       
+       int bodyIndexA = pairs[id].x;
+       int bodyIndexB = pairs[id].y;
+       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+       
+       //once the broadphase avoids static-static pairs, we can remove this test
+       if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+       {
+               return;
+       }
+               
+       if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)
+               return;
+
+       int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+               
+       if (shapeTypeB!=SHAPE_CONVEX_HULL &&
+               shapeTypeB!=SHAPE_SPHERE        &&
+               shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS
+               )
+               return;
+
+       b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];
+
+       float4 bvhAabbMin = bvhInfo.m_aabbMin;
+       float4 bvhAabbMax = bvhInfo.m_aabbMax;
+       float4 bvhQuantization = bvhInfo.m_quantization;
+       int numSubtreeHeaders = bvhInfo.m_numSubTrees;
+       __global const btBvhSubtreeInfo* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];
+       __global const btQuantizedBvhNode* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];
+       
+
+       unsigned short int quantizedQueryAabbMin[3];
+       unsigned short int quantizedQueryAabbMax[3];
+       quantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_min,false,bvhAabbMin, bvhAabbMax,bvhQuantization);
+       quantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_max,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);
+       
+       for (int i=0;i<numSubtreeHeaders;i++)
+       {
+               btBvhSubtreeInfo subtree = subtreeHeaders[i];
+                               
+               int overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+               if (overlap != 0)
+               {
+                       int startNodeIndex = subtree.m_rootNodeIndex;
+                       int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;
+                       int curIndex = startNodeIndex;
+                       int escapeIndex;
+                       int isLeafNode;
+                       int aabbOverlap;
+                       while (curIndex < endNodeIndex)
+                       {
+                               btQuantizedBvhNode rootNode = quantizedNodes[curIndex];
+                               aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);
+                               isLeafNode = isLeaf(&rootNode);
+                               if (aabbOverlap)
+                               {
+                                       if (isLeafNode)
+                                       {
+                                               int triangleIndex = getTriangleIndex(&rootNode);
+                                               if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                                               {
+                                                               int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+                                                               int pairIdx = atomic_add(numConcavePairsOut,numChildrenB);
+                                                               for (int b=0;b<numChildrenB;b++)
+                                                               {
+                                                                       if ((pairIdx+b)<maxNumConcavePairsCapacity)
+                                                                       {
+                                                                               int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+                                                                               int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);
+                                                                               concavePairsOut[pairIdx+b] = newPair;
+                                                                       }
+                                                               }
+                                               } else
+                                               {
+                                                       int pairIdx = atomic_inc(numConcavePairsOut);
+                                                       if (pairIdx<maxNumConcavePairsCapacity)
+                                                       {
+                                                               int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,0);
+                                                               concavePairsOut[pairIdx] = newPair;
+                                                       }
+                                               }
+                                       } 
+                                       curIndex++;
+                               } else
+                               {
+                                       if (isLeafNode)
+                                       {
+                                               curIndex++;
+                                       } else
+                                       {
+                                               escapeIndex = getEscapeIndex(&rootNode);
+                                               curIndex += escapeIndex;
+                                       }
+                               }
+                       }
+               }
+       }
+
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h
new file mode 100644 (file)
index 0000000..f1df8a6
--- /dev/null
@@ -0,0 +1,257 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* bvhTraversalKernelCL =
+       "//keep this enum in sync with the CPU version (in btCollidable.h)\n"
+       "//written by Erwin Coumans\n"
+       "#define SHAPE_CONVEX_HULL 3\n"
+       "#define SHAPE_CONCAVE_TRIMESH 5\n"
+       "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+       "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+       "#define SHAPE_SPHERE 7\n"
+       "typedef unsigned int u32;\n"
+       "#define MAX_NUM_PARTS_IN_BITS 10\n"
+       "///btQuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
+       "///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
+       "typedef struct\n"
+       "{\n"
+       "       //12 bytes\n"
+       "       unsigned short int      m_quantizedAabbMin[3];\n"
+       "       unsigned short int      m_quantizedAabbMax[3];\n"
+       "       //4 bytes\n"
+       "       int     m_escapeIndexOrTriangleIndex;\n"
+       "} btQuantizedBvhNode;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4          m_aabbMin;\n"
+       "       float4          m_aabbMax;\n"
+       "       float4          m_quantization;\n"
+       "       int                     m_numNodes;\n"
+       "       int                     m_numSubTrees;\n"
+       "       int                     m_nodeOffset;\n"
+       "       int                     m_subTreeOffset;\n"
+       "} b3BvhInfo;\n"
+       "int    getTriangleIndex(const btQuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       unsigned int x=0;\n"
+       "       unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+       "       // Get only the lower bits where the triangle index is stored\n"
+       "       return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+       "}\n"
+       "int isLeaf(const btQuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+       "       return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+       "}\n"
+       "       \n"
+       "int getEscapeIndex(const btQuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+       "}\n"
+       "typedef struct\n"
+       "{\n"
+       "       //12 bytes\n"
+       "       unsigned short int      m_quantizedAabbMin[3];\n"
+       "       unsigned short int      m_quantizedAabbMax[3];\n"
+       "       //4 bytes, points to the root of the subtree\n"
+       "       int                     m_rootNodeIndex;\n"
+       "       //4 bytes\n"
+       "       int                     m_subtreeSize;\n"
+       "       int                     m_padding[3];\n"
+       "} btBvhSubtreeInfo;\n"
+       "///keep this in sync with btCollidable.h\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_numChildShapes;\n"
+       "       int blaat2;\n"
+       "       int m_shapeType;\n"
+       "       int m_shapeIndex;\n"
+       "       \n"
+       "} btCollidableGpu;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4  m_childPosition;\n"
+       "       float4  m_childOrientation;\n"
+       "       int m_shapeIndex;\n"
+       "       int m_unused0;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "} btGpuChildShape;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_pos;\n"
+       "       float4 m_quat;\n"
+       "       float4 m_linVel;\n"
+       "       float4 m_angVel;\n"
+       "       u32 m_collidableIdx;\n"
+       "       float m_invMass;\n"
+       "       float m_restituitionCoeff;\n"
+       "       float m_frictionCoeff;\n"
+       "} BodyData;\n"
+       "typedef struct \n"
+       "{\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_min;\n"
+       "               float   m_minElems[4];\n"
+       "               int                     m_minIndices[4];\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_max;\n"
+       "               float   m_maxElems[4];\n"
+       "               int                     m_maxIndices[4];\n"
+       "       };\n"
+       "} btAabbCL;\n"
+       "int testQuantizedAabbAgainstQuantizedAabb(\n"
+       "                                                               const unsigned short int* aabbMin1,\n"
+       "                                                               const unsigned short int* aabbMax1,\n"
+       "                                                               const unsigned short int* aabbMin2,\n"
+       "                                                               const unsigned short int* aabbMax2)\n"
+       "{\n"
+       "       //int overlap = 1;\n"
+       "       if (aabbMin1[0] > aabbMax2[0])\n"
+       "               return 0;\n"
+       "       if (aabbMax1[0] < aabbMin2[0])\n"
+       "               return 0;\n"
+       "       if (aabbMin1[1] > aabbMax2[1])\n"
+       "               return 0;\n"
+       "       if (aabbMax1[1] < aabbMin2[1])\n"
+       "               return 0;\n"
+       "       if (aabbMin1[2] > aabbMax2[2])\n"
+       "               return 0;\n"
+       "       if (aabbMax1[2] < aabbMin2[2])\n"
+       "               return 0;\n"
+       "       return 1;\n"
+       "       //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;\n"
+       "       //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;\n"
+       "       //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;\n"
+       "       //return overlap;\n"
+       "}\n"
+       "void quantizeWithClamp(unsigned short* out, float4 point2,int isMax, float4 bvhAabbMin, float4 bvhAabbMax, float4 bvhQuantization)\n"
+       "{\n"
+       "       float4 clampedPoint = max(point2,bvhAabbMin);\n"
+       "       clampedPoint = min (clampedPoint, bvhAabbMax);\n"
+       "       float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;\n"
+       "       if (isMax)\n"
+       "       {\n"
+       "               out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));\n"
+       "               out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));\n"
+       "               out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));\n"
+       "       } else\n"
+       "       {\n"
+       "               out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));\n"
+       "               out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));\n"
+       "               out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));\n"
+       "       }\n"
+       "}\n"
+       "// work-in-progress\n"
+       "__kernel void   bvhTraversalKernel( __global const int4* pairs, \n"
+       "                                                                       __global const BodyData* rigidBodies, \n"
+       "                                                                       __global const btCollidableGpu* collidables,\n"
+       "                                                                       __global btAabbCL* aabbs,\n"
+       "                                                                       __global int4* concavePairsOut,\n"
+       "                                                                       __global volatile int* numConcavePairsOut,\n"
+       "                                                                       __global const btBvhSubtreeInfo* subtreeHeadersRoot,\n"
+       "                                                                       __global const btQuantizedBvhNode* quantizedNodesRoot,\n"
+       "                                                                       __global const b3BvhInfo* bvhInfos,\n"
+       "                                                                       int numPairs,\n"
+       "                                                                       int maxNumConcavePairsCapacity)\n"
+       "{\n"
+       "       int id = get_global_id(0);\n"
+       "       if (id>=numPairs)\n"
+       "               return;\n"
+       "       \n"
+       "       int bodyIndexA = pairs[id].x;\n"
+       "       int bodyIndexB = pairs[id].y;\n"
+       "       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "       \n"
+       "       //once the broadphase avoids static-static pairs, we can remove this test\n"
+       "       if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+       "       {\n"
+       "               return;\n"
+       "       }\n"
+       "               \n"
+       "       if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)\n"
+       "               return;\n"
+       "       int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+       "               \n"
+       "       if (shapeTypeB!=SHAPE_CONVEX_HULL &&\n"
+       "               shapeTypeB!=SHAPE_SPHERE        &&\n"
+       "               shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
+       "               )\n"
+       "               return;\n"
+       "       b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];\n"
+       "       float4 bvhAabbMin = bvhInfo.m_aabbMin;\n"
+       "       float4 bvhAabbMax = bvhInfo.m_aabbMax;\n"
+       "       float4 bvhQuantization = bvhInfo.m_quantization;\n"
+       "       int numSubtreeHeaders = bvhInfo.m_numSubTrees;\n"
+       "       __global const btBvhSubtreeInfo* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];\n"
+       "       __global const btQuantizedBvhNode* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];\n"
+       "       \n"
+       "       unsigned short int quantizedQueryAabbMin[3];\n"
+       "       unsigned short int quantizedQueryAabbMax[3];\n"
+       "       quantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_min,false,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
+       "       quantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_max,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
+       "       \n"
+       "       for (int i=0;i<numSubtreeHeaders;i++)\n"
+       "       {\n"
+       "               btBvhSubtreeInfo subtree = subtreeHeaders[i];\n"
+       "                               \n"
+       "               int overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);\n"
+       "               if (overlap != 0)\n"
+       "               {\n"
+       "                       int startNodeIndex = subtree.m_rootNodeIndex;\n"
+       "                       int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;\n"
+       "                       int curIndex = startNodeIndex;\n"
+       "                       int escapeIndex;\n"
+       "                       int isLeafNode;\n"
+       "                       int aabbOverlap;\n"
+       "                       while (curIndex < endNodeIndex)\n"
+       "                       {\n"
+       "                               btQuantizedBvhNode rootNode = quantizedNodes[curIndex];\n"
+       "                               aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);\n"
+       "                               isLeafNode = isLeaf(&rootNode);\n"
+       "                               if (aabbOverlap)\n"
+       "                               {\n"
+       "                                       if (isLeafNode)\n"
+       "                                       {\n"
+       "                                               int triangleIndex = getTriangleIndex(&rootNode);\n"
+       "                                               if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "                                               {\n"
+       "                                                               int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
+       "                                                               int pairIdx = atomic_add(numConcavePairsOut,numChildrenB);\n"
+       "                                                               for (int b=0;b<numChildrenB;b++)\n"
+       "                                                               {\n"
+       "                                                                       if ((pairIdx+b)<maxNumConcavePairsCapacity)\n"
+       "                                                                       {\n"
+       "                                                                               int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
+       "                                                                               int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);\n"
+       "                                                                               concavePairsOut[pairIdx+b] = newPair;\n"
+       "                                                                       }\n"
+       "                                                               }\n"
+       "                                               } else\n"
+       "                                               {\n"
+       "                                                       int pairIdx = atomic_inc(numConcavePairsOut);\n"
+       "                                                       if (pairIdx<maxNumConcavePairsCapacity)\n"
+       "                                                       {\n"
+       "                                                               int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,0);\n"
+       "                                                               concavePairsOut[pairIdx] = newPair;\n"
+       "                                                       }\n"
+       "                                               }\n"
+       "                                       } \n"
+       "                                       curIndex++;\n"
+       "                               } else\n"
+       "                               {\n"
+       "                                       if (isLeafNode)\n"
+       "                                       {\n"
+       "                                               curIndex++;\n"
+       "                                       } else\n"
+       "                                       {\n"
+       "                                               escapeIndex = getEscapeIndex(&rootNode);\n"
+       "                                               curIndex += escapeIndex;\n"
+       "                                       }\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl
new file mode 100644 (file)
index 0000000..e754f4e
--- /dev/null
@@ -0,0 +1,311 @@
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#define AppendInc(x, out) out = atomic_inc(x)
+#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
+#ifdef cl_ext_atomic_counters_32
+       #pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+       #define counter32_t volatile __global int*
+#endif
+
+
+__kernel void   mprPenetrationKernel( __global int4* pairs,
+                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, 
+                                                                                                                                                                       __global const b3Collidable_t* collidables,
+                                                                                                                                                                       __global const b3ConvexPolyhedronData_t* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global float4* separatingNormals,
+                                                                                                                                                                       __global int* hasSeparatingAxis,
+                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                                                                                                                       counter32_t nGlobalContactsOut,
+                                                                                                                                                                       int contactCapacity,
+                                                                                                                                                                       int numPairs)
+{
+       int i = get_global_id(0);
+       int pairIndex = i;
+       if (i<numPairs)
+       {
+               int bodyIndexA = pairs[i].x;
+               int bodyIndexB = pairs[i].y;
+
+               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+       
+               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+               
+               
+               //once the broadphase avoids static-static pairs, we can remove this test
+               if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+               {
+                       return;
+               }
+               
+
+               if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
+               {
+                       return;
+               }
+
+               float depthOut;
+               b3Float4 dirOut;
+               b3Float4 posOut;
+
+
+               int res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB,rigidBodies,convexShapes,collidables,vertices,separatingNormals,hasSeparatingAxis,&depthOut, &dirOut, &posOut);
+               
+               
+               
+               
+
+               if (res==0)
+               {
+                       //add a contact
+
+                       int dstIdx;
+                       AppendInc( nGlobalContactsOut, dstIdx );
+                       if (dstIdx<contactCapacity)
+                       {
+                               pairs[pairIndex].z = dstIdx;
+                               __global struct b3Contact4Data* c = globalContactsOut + dstIdx;
+                               c->m_worldNormalOnB = -dirOut;//normal;
+                               c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                               c->m_batchIdx = pairIndex;
+                               int bodyA = pairs[pairIndex].x;
+                               int bodyB = pairs[pairIndex].y;
+                               c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;
+                               c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;
+                               c->m_childIndexA = -1;
+                               c->m_childIndexB = -1;
+                               //for (int i=0;i<nContacts;i++)
+                               posOut.w = -depthOut;
+                               c->m_worldPosB[0] = posOut;//localPoints[contactIdx[i]];
+                               GET_NPOINTS(*c) = 1;//nContacts;
+                       }
+               }
+
+       }
+}
+
+typedef float4 Quaternion;
+#define make_float4 (float4)
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = make_float4(a.xyz,0.f);
+       float4 b1 = make_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+       return cross(a,b);
+}
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+       Quaternion ans;
+       ans = cross3( a, b );
+       ans += a.w*b+b.w*a;
+//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+       ans.w = a.w*b.w - dot3F4(a, b);
+       return ans;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+       return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+       Quaternion qInv = qtInvert( q );
+       float4 vcpy = vec;
+       vcpy.w = 0.f;
+       float4 out = qtMul(qtMul(q,vcpy),qInv);
+       return out;
+}
+
+__inline
+float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
+{
+       return qtRotate( *orientation, *p ) + (*translation);
+}
+
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+       return qtRotate( qtInvert( q ), vec );
+}
+
+
+inline void project(__global const b3ConvexPolyhedronData_t* hull,  const float4 pos, const float4 orn, 
+const float4* dir, __global const float4* vertices, float* min, float* max)
+{
+       min[0] = FLT_MAX;
+       max[0] = -FLT_MAX;
+       int numVerts = hull->m_numVertices;
+
+       const float4 localDir = qtInvRotate(orn,*dir);
+       float offset = dot(pos,*dir);
+       for(int i=0;i<numVerts;i++)
+       {
+               float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
+               if(dp < min[0]) 
+                       min[0] = dp;
+               if(dp > max[0]) 
+                       max[0] = dp;
+       }
+       if(min[0]>max[0])
+       {
+               float tmp = min[0];
+               min[0] = max[0];
+               max[0] = tmp;
+       }
+       min[0] += offset;
+       max[0] += offset;
+}
+
+
+bool findSeparatingAxisUnitSphere(     __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, 
+       const float4 posA1,
+       const float4 ornA,
+       const float4 posB1,
+       const float4 ornB,
+       const float4 DeltaC2,
+       __global const float4* vertices,
+       __global const float4* unitSphereDirections,
+       int numUnitSphereDirections,
+       float4* sep,
+       float* dmin)
+{
+       
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+
+       int curPlaneTests=0;
+
+       int curEdgeEdge = 0;
+       // Test unit sphere directions
+       for (int i=0;i<numUnitSphereDirections;i++)
+       {
+
+               float4 crossje;
+               crossje = unitSphereDirections[i];      
+
+               if (dot3F4(DeltaC2,crossje)>0)
+                       crossje *= -1.f;
+               {
+                       float dist;
+                       bool result = true;
+                       float Min0,Max0;
+                       float Min1,Max1;
+                       project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);
+                       project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);
+               
+                       if(Max0<Min1 || Max1<Min0)
+                               return false;
+               
+                       float d0 = Max0 - Min1;
+                       float d1 = Max1 - Min0;
+                       dist = d0<d1 ? d0:d1;
+                       result = true;
+       
+                       if(dist<*dmin)
+                       {
+                               *dmin = dist;
+                               *sep = crossje;
+                       }
+               }
+       }
+
+       
+       if((dot3F4(-DeltaC2,*sep))>0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+
+
+__kernel void   findSeparatingAxisUnitSphereKernel( __global const int4* pairs, 
+                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, 
+                                                                                                                                                                       __global const b3Collidable_t* collidables,
+                                                                                                                                                                       __global const b3ConvexPolyhedronData_t* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global const float4* unitSphereDirections,
+                                                                                                                                                                       __global  float4* separatingNormals,
+                                                                                                                                                                       __global  int* hasSeparatingAxis,
+                                                                                                                                                                       __global  float* dmins,
+                                                                                                                                                                       int numUnitSphereDirections,
+                                                                                                                                                                       int numPairs
+                                                                                                                                                                       )
+{
+
+       int i = get_global_id(0);
+       
+       if (i<numPairs)
+       {
+
+               if (hasSeparatingAxis[i])
+               {
+       
+                       int bodyIndexA = pairs[i].x;
+                       int bodyIndexB = pairs[i].y;
+       
+                       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+                       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+               
+                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+                       
+                       
+                       int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+       
+                       float dmin = dmins[i];
+       
+                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+                       posA.w = 0.f;
+                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+                       posB.w = 0.f;
+                       float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+                       float4 ornA = rigidBodies[bodyIndexA].m_quat;
+                       float4 c0 = transform(&c0local, &posA, &ornA);
+                       float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+                       float4 ornB =rigidBodies[bodyIndexB].m_quat;
+                       float4 c1 = transform(&c1local,&posB,&ornB);
+                       const float4 DeltaC2 = c0 - c1;
+                       float4 sepNormal = separatingNormals[i];
+                       
+                       int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;
+                       if (numEdgeEdgeDirections>numUnitSphereDirections)
+                       {
+                               bool sepEE = findSeparatingAxisUnitSphere(      &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+                                                                                                                                                                                                               posB,ornB,
+                                                                                                                                                                                                               DeltaC2,
+                                                                                                                                                                                                               vertices,unitSphereDirections,numUnitSphereDirections,&sepNormal,&dmin);
+                               if (!sepEE)
+                               {
+                                       hasSeparatingAxis[i] = 0;
+                               } else
+                               {
+                                       hasSeparatingAxis[i] = 1;
+                                       separatingNormals[i] = sepNormal;
+                               }
+                       }
+               }               //if (hasSeparatingAxis[i])
+       }//(i<numPairs)
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h
new file mode 100644 (file)
index 0000000..74959a9
--- /dev/null
@@ -0,0 +1,1445 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* mprKernelsCL =
+       "/***\n"
+       " * ---------------------------------\n"
+       " * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>\n"
+       " *\n"
+       " *  This file was ported from mpr.c file, part of libccd.\n"
+       " *  The Minkoski Portal Refinement implementation was ported \n"
+       " *  to OpenCL by Erwin Coumans for the Bullet 3 Physics library.\n"
+       " *  at http://github.com/erwincoumans/bullet3\n"
+       " *\n"
+       " *  Distributed under the OSI-approved BSD License (the \"License\");\n"
+       " *  see <http://www.opensource.org/licenses/bsd-license.php>.\n"
+       " *  This software is distributed WITHOUT ANY WARRANTY; without even the\n"
+       " *  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+       " *  See the License for more information.\n"
+       " */\n"
+       "#ifndef B3_MPR_PENETRATION_H\n"
+       "#define B3_MPR_PENETRATION_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_RIGIDBODY_DATA_H\n"
+       "#define B3_RIGIDBODY_DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#define B3_QUAT_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Quat;\n"
+       "       #define b3QuatConstArg const b3Quat\n"
+       "       \n"
+       "       \n"
+       "inline float4 b3FastNormalize4(float4 v)\n"
+       "{\n"
+       "       v = (float4)(v.xyz,0.f);\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "       \n"
+       "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+       "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+       "{\n"
+       "       b3Quat ans;\n"
+       "       ans = b3Cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+       "{\n"
+       "       b3Quat q;\n"
+       "       q=in;\n"
+       "       //return b3FastNormalize4(in);\n"
+       "       float len = native_sqrt(dot(q, q));\n"
+       "       if(len > 0.f)\n"
+       "       {\n"
+       "               q *= 1.f / len;\n"
+       "       }\n"
+       "       else\n"
+       "       {\n"
+       "               q.x = q.y = q.z = 0.f;\n"
+       "               q.w = 1.f;\n"
+       "       }\n"
+       "       return q;\n"
+       "}\n"
+       "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       b3Quat qInv = b3QuatInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+       "}\n"
+       "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg  orientation)\n"
+       "{\n"
+       "       return b3QuatRotate( orientation, point ) + (translation);\n"
+       "}\n"
+       "       \n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifndef B3_MAT3x3_H\n"
+       "#define B3_MAT3x3_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "typedef struct\n"
+       "{\n"
+       "       b3Float4 m_row[3];\n"
+       "}b3Mat3x3;\n"
+       "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+       "#define b3GetRow(m,row) (m.m_row[row])\n"
+       "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+       "{\n"
+       "       b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+       "       out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+       "       out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+       "       out.m_row[0].w = 0.f;\n"
+       "       out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+       "       out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+       "       out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+       "       out.m_row[1].w = 0.f;\n"
+       "       out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+       "       out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+       "       out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+       "       out.m_row[2].w = 0.f;\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = fabs(matIn.m_row[0]);\n"
+       "       out.m_row[1] = fabs(matIn.m_row[1]);\n"
+       "       out.m_row[2] = fabs(matIn.m_row[2]);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero();\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity();\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(0.f);\n"
+       "       m.m_row[1] = (b3Float4)(0.f);\n"
+       "       m.m_row[2] = (b3Float4)(0.f);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+       "       m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+       "       m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+       "       out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+       "       out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Mat3x3 transB;\n"
+       "       transB = mtTranspose( b );\n"
+       "       b3Mat3x3 ans;\n"
+       "       //      why this doesn't run when 0ing in the for{}\n"
+       "       a.m_row[0].w = 0.f;\n"
+       "       a.m_row[1].w = 0.f;\n"
+       "       a.m_row[2].w = 0.f;\n"
+       "       for(int i=0; i<3; i++)\n"
+       "       {\n"
+       "//     a.m_row[i].w = 0.f;\n"
+       "               ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+       "               ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+       "               ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+       "               ans.m_row[i].w = 0.f;\n"
+       "       }\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+       "{\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a.m_row[0], b );\n"
+       "       ans.y = b3Dot3F4( a.m_row[1], b );\n"
+       "       ans.z = b3Dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a, colx );\n"
+       "       ans.y = b3Dot3F4( a, coly );\n"
+       "       ans.z = b3Dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "#endif\n"
+       "#endif //B3_MAT3x3_H\n"
+       "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+       "struct b3RigidBodyData\n"
+       "{\n"
+       "       b3Float4                                m_pos;\n"
+       "       b3Quat                                  m_quat;\n"
+       "       b3Float4                                m_linVel;\n"
+       "       b3Float4                                m_angVel;\n"
+       "       int                                     m_collidableIdx;\n"
+       "       float                           m_invMass;\n"
+       "       float                           m_restituitionCoeff;\n"
+       "       float                           m_frictionCoeff;\n"
+       "};\n"
+       "typedef struct b3InertiaData b3InertiaData_t;\n"
+       "struct b3InertiaData\n"
+       "{\n"
+       "       b3Mat3x3 m_invInertiaWorld;\n"
+       "       b3Mat3x3 m_initInvInertia;\n"
+       "};\n"
+       "#endif //B3_RIGIDBODY_DATA_H\n"
+       "       \n"
+       "#ifndef B3_CONVEX_POLYHEDRON_DATA_H\n"
+       "#define B3_CONVEX_POLYHEDRON_DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "typedef struct b3GpuFace b3GpuFace_t;\n"
+       "struct b3GpuFace\n"
+       "{\n"
+       "       b3Float4 m_plane;\n"
+       "       int m_indexOffset;\n"
+       "       int m_numIndices;\n"
+       "       int m_unusedPadding1;\n"
+       "       int m_unusedPadding2;\n"
+       "};\n"
+       "typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;\n"
+       "struct b3ConvexPolyhedronData\n"
+       "{\n"
+       "       b3Float4                m_localCenter;\n"
+       "       b3Float4                m_extents;\n"
+       "       b3Float4                mC;\n"
+       "       b3Float4                mE;\n"
+       "       float                   m_radius;\n"
+       "       int     m_faceOffset;\n"
+       "       int m_numFaces;\n"
+       "       int     m_numVertices;\n"
+       "       int m_vertexOffset;\n"
+       "       int     m_uniqueEdgesOffset;\n"
+       "       int     m_numUniqueEdges;\n"
+       "       int m_unused;\n"
+       "};\n"
+       "#endif //B3_CONVEX_POLYHEDRON_DATA_H\n"
+       "#ifndef B3_COLLIDABLE_H\n"
+       "#define B3_COLLIDABLE_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "enum b3ShapeTypes\n"
+       "{\n"
+       "       SHAPE_HEIGHT_FIELD=1,\n"
+       "       SHAPE_CONVEX_HULL=3,\n"
+       "       SHAPE_PLANE=4,\n"
+       "       SHAPE_CONCAVE_TRIMESH=5,\n"
+       "       SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
+       "       SHAPE_SPHERE=7,\n"
+       "       MAX_NUM_SHAPE_TYPES,\n"
+       "};\n"
+       "typedef struct b3Collidable b3Collidable_t;\n"
+       "struct b3Collidable\n"
+       "{\n"
+       "       union {\n"
+       "               int m_numChildShapes;\n"
+       "               int m_bvhIndex;\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float m_radius;\n"
+       "               int     m_compoundBvhIndex;\n"
+       "       };\n"
+       "       int m_shapeType;\n"
+       "       int m_shapeIndex;\n"
+       "};\n"
+       "typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
+       "struct b3GpuChildShape\n"
+       "{\n"
+       "       b3Float4        m_childPosition;\n"
+       "       b3Quat          m_childOrientation;\n"
+       "       int m_shapeIndex;\n"
+       "       int m_unused0;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "};\n"
+       "struct b3CompoundOverlappingPair\n"
+       "{\n"
+       "       int m_bodyIndexA;\n"
+       "       int m_bodyIndexB;\n"
+       "//     int     m_pairType;\n"
+       "       int m_childShapeIndexA;\n"
+       "       int m_childShapeIndexB;\n"
+       "};\n"
+       "#endif //B3_COLLIDABLE_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#define B3_MPR_SQRT sqrt\n"
+       "#endif\n"
+       "#define B3_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))\n"
+       "#define B3_MPR_FABS fabs\n"
+       "#define B3_MPR_TOLERANCE 1E-6f\n"
+       "#define B3_MPR_MAX_ITERATIONS 1000\n"
+       "struct _b3MprSupport_t \n"
+       "{\n"
+       "    b3Float4 v;  //!< Support point in minkowski sum\n"
+       "    b3Float4 v1; //!< Support point in obj1\n"
+       "    b3Float4 v2; //!< Support point in obj2\n"
+       "};\n"
+       "typedef struct _b3MprSupport_t b3MprSupport_t;\n"
+       "struct _b3MprSimplex_t \n"
+       "{\n"
+       "    b3MprSupport_t ps[4];\n"
+       "    int last; //!< index of last added point\n"
+       "};\n"
+       "typedef struct _b3MprSimplex_t b3MprSimplex_t;\n"
+       "inline b3MprSupport_t* b3MprSimplexPointW(b3MprSimplex_t *s, int idx)\n"
+       "{\n"
+       "    return &s->ps[idx];\n"
+       "}\n"
+       "inline void b3MprSimplexSetSize(b3MprSimplex_t *s, int size)\n"
+       "{\n"
+       "    s->last = size - 1;\n"
+       "}\n"
+       "inline int b3MprSimplexSize(const b3MprSimplex_t *s)\n"
+       "{\n"
+       "    return s->last + 1;\n"
+       "}\n"
+       "inline const b3MprSupport_t* b3MprSimplexPoint(const b3MprSimplex_t* s, int idx)\n"
+       "{\n"
+       "    // here is no check on boundaries\n"
+       "    return &s->ps[idx];\n"
+       "}\n"
+       "inline void b3MprSupportCopy(b3MprSupport_t *d, const b3MprSupport_t *s)\n"
+       "{\n"
+       "    *d = *s;\n"
+       "}\n"
+       "inline void b3MprSimplexSet(b3MprSimplex_t *s, size_t pos, const b3MprSupport_t *a)\n"
+       "{\n"
+       "    b3MprSupportCopy(s->ps + pos, a);\n"
+       "}\n"
+       "inline void b3MprSimplexSwap(b3MprSimplex_t *s, size_t pos1, size_t pos2)\n"
+       "{\n"
+       "    b3MprSupport_t supp;\n"
+       "    b3MprSupportCopy(&supp, &s->ps[pos1]);\n"
+       "    b3MprSupportCopy(&s->ps[pos1], &s->ps[pos2]);\n"
+       "    b3MprSupportCopy(&s->ps[pos2], &supp);\n"
+       "}\n"
+       "inline int b3MprIsZero(float val)\n"
+       "{\n"
+       "    return B3_MPR_FABS(val) < FLT_EPSILON;\n"
+       "}\n"
+       "inline int b3MprEq(float _a, float _b)\n"
+       "{\n"
+       "    float ab;\n"
+       "    float a, b;\n"
+       "    ab = B3_MPR_FABS(_a - _b);\n"
+       "    if (B3_MPR_FABS(ab) < FLT_EPSILON)\n"
+       "        return 1;\n"
+       "    a = B3_MPR_FABS(_a);\n"
+       "    b = B3_MPR_FABS(_b);\n"
+       "    if (b > a){\n"
+       "        return ab < FLT_EPSILON * b;\n"
+       "    }else{\n"
+       "        return ab < FLT_EPSILON * a;\n"
+       "    }\n"
+       "}\n"
+       "inline int b3MprVec3Eq(const b3Float4* a, const b3Float4 *b)\n"
+       "{\n"
+       "    return b3MprEq((*a).x, (*b).x)\n"
+       "            && b3MprEq((*a).y, (*b).y)\n"
+       "            && b3MprEq((*a).z, (*b).z);\n"
+       "}\n"
+       "inline b3Float4 b3LocalGetSupportVertex(b3Float4ConstArg supportVec,__global const b3ConvexPolyhedronData_t* hull,     b3ConstArray(b3Float4) verticesA)\n"
+       "{\n"
+       "       b3Float4 supVec = b3MakeFloat4(0,0,0,0);\n"
+       "       float maxDot = -B3_LARGE_FLOAT;\n"
+       "    if( 0 < hull->m_numVertices )\n"
+       "    {\n"
+       "        const b3Float4 scaled = supportVec;\n"
+       "               int index = b3MaxDot(scaled, &verticesA[hull->m_vertexOffset], hull->m_numVertices, &maxDot);\n"
+       "        return verticesA[hull->m_vertexOffset+index];\n"
+       "    }\n"
+       "    return supVec;\n"
+       "}\n"
+       "B3_STATIC void b3MprConvexSupport(int pairIndex,int bodyIndex,  b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+       "                                                                                                       b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+       "                                                                                                       b3ConstArray(b3Collidable_t)                            cpuCollidables,\n"
+       "                                                                                                       b3ConstArray(b3Float4)                                  cpuVertices,\n"
+       "                                                                                                       __global b3Float4* sepAxis,\n"
+       "                                                                                                               const b3Float4* _dir, b3Float4* outp, int logme)\n"
+       "{\n"
+       "       //dir is in worldspace, move to local space\n"
+       "       \n"
+       "       b3Float4 pos = cpuBodyBuf[bodyIndex].m_pos;\n"
+       "       b3Quat orn = cpuBodyBuf[bodyIndex].m_quat;\n"
+       "       \n"
+       "       b3Float4 dir = b3MakeFloat4((*_dir).x,(*_dir).y,(*_dir).z,0.f);\n"
+       "       \n"
+       "       const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn),dir);\n"
+       "       \n"
+       "       //find local support vertex\n"
+       "       int colIndex = cpuBodyBuf[bodyIndex].m_collidableIdx;\n"
+       "       \n"
+       "       b3Assert(cpuCollidables[colIndex].m_shapeType==SHAPE_CONVEX_HULL);\n"
+       "       __global const b3ConvexPolyhedronData_t* hull = &cpuConvexData[cpuCollidables[colIndex].m_shapeIndex];\n"
+       "       \n"
+       "       b3Float4 pInA;\n"
+       "       if (logme)\n"
+       "       {\n"
+       "               b3Float4 supVec = b3MakeFloat4(0,0,0,0);\n"
+       "               float maxDot = -B3_LARGE_FLOAT;\n"
+       "               if( 0 < hull->m_numVertices )\n"
+       "               {\n"
+       "                       const b3Float4 scaled = localDir;\n"
+       "                       int index = b3MaxDot(scaled, &cpuVertices[hull->m_vertexOffset], hull->m_numVertices, &maxDot);\n"
+       "                       pInA = cpuVertices[hull->m_vertexOffset+index];\n"
+       "                       \n"
+       "               }\n"
+       "       } else\n"
+       "       {\n"
+       "               pInA = b3LocalGetSupportVertex(localDir,hull,cpuVertices);\n"
+       "       }\n"
+       "       //move vertex to world space\n"
+       "       *outp = b3TransformPoint(pInA,pos,orn);\n"
+       "       \n"
+       "}\n"
+       "inline void b3MprSupport(int pairIndex,int bodyIndexA, int bodyIndexB,   b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+       "                                                                                                       b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+       "                                                                                                       b3ConstArray(b3Collidable_t)                            cpuCollidables,\n"
+       "                                                                                                       b3ConstArray(b3Float4)                                  cpuVertices,\n"
+       "                                                                                                       __global b3Float4* sepAxis,\n"
+       "                                                                                                       const b3Float4* _dir, b3MprSupport_t *supp)\n"
+       "{\n"
+       "    b3Float4 dir;\n"
+       "       dir = *_dir;\n"
+       "       b3MprConvexSupport(pairIndex,bodyIndexA,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v1,0);\n"
+       "    dir = *_dir*-1.f;\n"
+       "       b3MprConvexSupport(pairIndex,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v2,0);\n"
+       "    supp->v = supp->v1 - supp->v2;\n"
+       "}\n"
+       "inline void b3FindOrigin(int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, b3MprSupport_t *center)\n"
+       "{\n"
+       "    center->v1 = cpuBodyBuf[bodyIndexA].m_pos;\n"
+       "       center->v2 = cpuBodyBuf[bodyIndexB].m_pos;\n"
+       "    center->v = center->v1 - center->v2;\n"
+       "}\n"
+       "inline void b3MprVec3Set(b3Float4 *v, float x, float y, float z)\n"
+       "{\n"
+       "       (*v).x = x;\n"
+       "       (*v).y = y;\n"
+       "       (*v).z = z;\n"
+       "       (*v).w = 0.f;\n"
+       "}\n"
+       "inline void b3MprVec3Add(b3Float4 *v, const b3Float4 *w)\n"
+       "{\n"
+       "    (*v).x += (*w).x;\n"
+       "    (*v).y += (*w).y;\n"
+       "    (*v).z += (*w).z;\n"
+       "}\n"
+       "inline void b3MprVec3Copy(b3Float4 *v, const b3Float4 *w)\n"
+       "{\n"
+       "    *v = *w;\n"
+       "}\n"
+       "inline void b3MprVec3Scale(b3Float4 *d, float k)\n"
+       "{\n"
+       "    *d *= k;\n"
+       "}\n"
+       "inline float b3MprVec3Dot(const b3Float4 *a, const b3Float4 *b)\n"
+       "{\n"
+       "    float dot;\n"
+       "       dot = b3Dot3F4(*a,*b);\n"
+       "    return dot;\n"
+       "}\n"
+       "inline float b3MprVec3Len2(const b3Float4 *v)\n"
+       "{\n"
+       "    return b3MprVec3Dot(v, v);\n"
+       "}\n"
+       "inline void b3MprVec3Normalize(b3Float4 *d)\n"
+       "{\n"
+       "    float k = 1.f / B3_MPR_SQRT(b3MprVec3Len2(d));\n"
+       "    b3MprVec3Scale(d, k);\n"
+       "}\n"
+       "inline void b3MprVec3Cross(b3Float4 *d, const b3Float4 *a, const b3Float4 *b)\n"
+       "{\n"
+       "       *d = b3Cross3(*a,*b);\n"
+       "       \n"
+       "}\n"
+       "inline void b3MprVec3Sub2(b3Float4 *d, const b3Float4 *v, const b3Float4 *w)\n"
+       "{\n"
+       "       *d = *v - *w;\n"
+       "}\n"
+       "inline void b3PortalDir(const b3MprSimplex_t *portal, b3Float4 *dir)\n"
+       "{\n"
+       "    b3Float4 v2v1, v3v1;\n"
+       "    b3MprVec3Sub2(&v2v1, &b3MprSimplexPoint(portal, 2)->v,\n"
+       "                       &b3MprSimplexPoint(portal, 1)->v);\n"
+       "    b3MprVec3Sub2(&v3v1, &b3MprSimplexPoint(portal, 3)->v,\n"
+       "                       &b3MprSimplexPoint(portal, 1)->v);\n"
+       "    b3MprVec3Cross(dir, &v2v1, &v3v1);\n"
+       "    b3MprVec3Normalize(dir);\n"
+       "}\n"
+       "inline int portalEncapsulesOrigin(const b3MprSimplex_t *portal,\n"
+       "                                       const b3Float4 *dir)\n"
+       "{\n"
+       "    float dot;\n"
+       "    dot = b3MprVec3Dot(dir, &b3MprSimplexPoint(portal, 1)->v);\n"
+       "    return b3MprIsZero(dot) || dot > 0.f;\n"
+       "}\n"
+       "inline int portalReachTolerance(const b3MprSimplex_t *portal,\n"
+       "                                     const b3MprSupport_t *v4,\n"
+       "                                     const b3Float4 *dir)\n"
+       "{\n"
+       "    float dv1, dv2, dv3, dv4;\n"
+       "    float dot1, dot2, dot3;\n"
+       "    // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}\n"
+       "    dv1 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, dir);\n"
+       "    dv2 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, dir);\n"
+       "    dv3 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, dir);\n"
+       "    dv4 = b3MprVec3Dot(&v4->v, dir);\n"
+       "    dot1 = dv4 - dv1;\n"
+       "    dot2 = dv4 - dv2;\n"
+       "    dot3 = dv4 - dv3;\n"
+       "    dot1 = B3_MPR_FMIN(dot1, dot2);\n"
+       "    dot1 = B3_MPR_FMIN(dot1, dot3);\n"
+       "    return b3MprEq(dot1, B3_MPR_TOLERANCE) || dot1 < B3_MPR_TOLERANCE;\n"
+       "}\n"
+       "inline int portalCanEncapsuleOrigin(const b3MprSimplex_t *portal,   \n"
+       "                                         const b3MprSupport_t *v4,\n"
+       "                                         const b3Float4 *dir)\n"
+       "{\n"
+       "    float dot;\n"
+       "    dot = b3MprVec3Dot(&v4->v, dir);\n"
+       "    return b3MprIsZero(dot) || dot > 0.f;\n"
+       "}\n"
+       "inline void b3ExpandPortal(b3MprSimplex_t *portal,\n"
+       "                              const b3MprSupport_t *v4)\n"
+       "{\n"
+       "    float dot;\n"
+       "    b3Float4 v4v0;\n"
+       "    b3MprVec3Cross(&v4v0, &v4->v, &b3MprSimplexPoint(portal, 0)->v);\n"
+       "    dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &v4v0);\n"
+       "    if (dot > 0.f){\n"
+       "        dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &v4v0);\n"
+       "        if (dot > 0.f){\n"
+       "            b3MprSimplexSet(portal, 1, v4);\n"
+       "        }else{\n"
+       "            b3MprSimplexSet(portal, 3, v4);\n"
+       "        }\n"
+       "    }else{\n"
+       "        dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &v4v0);\n"
+       "        if (dot > 0.f){\n"
+       "            b3MprSimplexSet(portal, 2, v4);\n"
+       "        }else{\n"
+       "            b3MprSimplexSet(portal, 1, v4);\n"
+       "        }\n"
+       "    }\n"
+       "}\n"
+       "B3_STATIC int b3DiscoverPortal(int pairIndex, int bodyIndexA, int bodyIndexB,  b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+       "                                                                                                       b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+       "                                                                                                       b3ConstArray(b3Collidable_t)                            cpuCollidables,\n"
+       "                                                                                                       b3ConstArray(b3Float4)                                  cpuVertices,\n"
+       "                                                                                                       __global b3Float4* sepAxis,\n"
+       "                                                                                                       __global int*   hasSepAxis,\n"
+       "                                                                                                       b3MprSimplex_t *portal)\n"
+       "{\n"
+       "    b3Float4 dir, va, vb;\n"
+       "    float dot;\n"
+       "    int cont;\n"
+       "       \n"
+       "       \n"
+       "    // vertex 0 is center of portal\n"
+       "    b3FindOrigin(bodyIndexA,bodyIndexB,cpuBodyBuf, b3MprSimplexPointW(portal, 0));\n"
+       "    // vertex 0 is center of portal\n"
+       "    b3MprSimplexSetSize(portal, 1);\n"
+       "       \n"
+       "       b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+       "       b3Float4* b3mpr_vec3_origin = &zero;\n"
+       "    if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 0)->v, b3mpr_vec3_origin)){\n"
+       "        // Portal's center lies on origin (0,0,0) => we know that objects\n"
+       "        // intersect but we would need to know penetration info.\n"
+       "        // So move center little bit...\n"
+       "        b3MprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);\n"
+       "        b3MprVec3Add(&b3MprSimplexPointW(portal, 0)->v, &va);\n"
+       "    }\n"
+       "    // vertex 1 = support in direction of origin\n"
+       "    b3MprVec3Copy(&dir, &b3MprSimplexPoint(portal, 0)->v);\n"
+       "    b3MprVec3Scale(&dir, -1.f);\n"
+       "    b3MprVec3Normalize(&dir);\n"
+       "    b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 1));\n"
+       "    b3MprSimplexSetSize(portal, 2);\n"
+       "    // test if origin isn't outside of v1\n"
+       "    dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &dir);\n"
+       "       \n"
+       "    if (b3MprIsZero(dot) || dot < 0.f)\n"
+       "        return -1;\n"
+       "    // vertex 2\n"
+       "    b3MprVec3Cross(&dir, &b3MprSimplexPoint(portal, 0)->v,\n"
+       "                       &b3MprSimplexPoint(portal, 1)->v);\n"
+       "    if (b3MprIsZero(b3MprVec3Len2(&dir))){\n"
+       "        if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 1)->v, b3mpr_vec3_origin)){\n"
+       "            // origin lies on v1\n"
+       "            return 1;\n"
+       "        }else{\n"
+       "            // origin lies on v0-v1 segment\n"
+       "            return 2;\n"
+       "        }\n"
+       "    }\n"
+       "    b3MprVec3Normalize(&dir);\n"
+       "        b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 2));\n"
+       "    \n"
+       "    dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &dir);\n"
+       "    if (b3MprIsZero(dot) || dot < 0.f)\n"
+       "        return -1;\n"
+       "    b3MprSimplexSetSize(portal, 3);\n"
+       "    // vertex 3 direction\n"
+       "    b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
+       "                     &b3MprSimplexPoint(portal, 0)->v);\n"
+       "    b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,\n"
+       "                     &b3MprSimplexPoint(portal, 0)->v);\n"
+       "    b3MprVec3Cross(&dir, &va, &vb);\n"
+       "    b3MprVec3Normalize(&dir);\n"
+       "    // it is better to form portal faces to be oriented \"outside\" origin\n"
+       "    dot = b3MprVec3Dot(&dir, &b3MprSimplexPoint(portal, 0)->v);\n"
+       "    if (dot > 0.f){\n"
+       "        b3MprSimplexSwap(portal, 1, 2);\n"
+       "        b3MprVec3Scale(&dir, -1.f);\n"
+       "    }\n"
+       "    while (b3MprSimplexSize(portal) < 4){\n"
+       "                b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 3));\n"
+       "        \n"
+       "        dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &dir);\n"
+       "        if (b3MprIsZero(dot) || dot < 0.f)\n"
+       "            return -1;\n"
+       "        cont = 0;\n"
+       "        // test if origin is outside (v1, v0, v3) - set v2 as v3 and\n"
+       "        // continue\n"
+       "        b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
+       "                          &b3MprSimplexPoint(portal, 3)->v);\n"
+       "        dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);\n"
+       "        if (dot < 0.f && !b3MprIsZero(dot)){\n"
+       "            b3MprSimplexSet(portal, 2, b3MprSimplexPoint(portal, 3));\n"
+       "            cont = 1;\n"
+       "        }\n"
+       "        if (!cont){\n"
+       "            // test if origin is outside (v3, v0, v2) - set v1 as v3 and\n"
+       "            // continue\n"
+       "            b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 3)->v,\n"
+       "                              &b3MprSimplexPoint(portal, 2)->v);\n"
+       "            dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);\n"
+       "            if (dot < 0.f && !b3MprIsZero(dot)){\n"
+       "                b3MprSimplexSet(portal, 1, b3MprSimplexPoint(portal, 3));\n"
+       "                cont = 1;\n"
+       "            }\n"
+       "        }\n"
+       "        if (cont){\n"
+       "            b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
+       "                             &b3MprSimplexPoint(portal, 0)->v);\n"
+       "            b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,\n"
+       "                             &b3MprSimplexPoint(portal, 0)->v);\n"
+       "            b3MprVec3Cross(&dir, &va, &vb);\n"
+       "            b3MprVec3Normalize(&dir);\n"
+       "        }else{\n"
+       "            b3MprSimplexSetSize(portal, 4);\n"
+       "        }\n"
+       "    }\n"
+       "    return 0;\n"
+       "}\n"
+       "B3_STATIC int b3RefinePortal(int pairIndex,int bodyIndexA, int bodyIndexB,  b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+       "                                                                                                       b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+       "                                                                                                       b3ConstArray(b3Collidable_t)                            cpuCollidables,\n"
+       "                                                                                                       b3ConstArray(b3Float4)                                  cpuVertices,\n"
+       "                                                                                                       __global b3Float4* sepAxis,\n"
+       "                                                                                                       b3MprSimplex_t *portal)\n"
+       "{\n"
+       "    b3Float4 dir;\n"
+       "    b3MprSupport_t v4;\n"
+       "       for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)\n"
+       "    //while (1)\n"
+       "       {\n"
+       "        // compute direction outside the portal (from v0 throught v1,v2,v3\n"
+       "        // face)\n"
+       "        b3PortalDir(portal, &dir);\n"
+       "        // test if origin is inside the portal\n"
+       "        if (portalEncapsulesOrigin(portal, &dir))\n"
+       "            return 0;\n"
+       "        // get next support point\n"
+       "        \n"
+       "                b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);\n"
+       "        // test if v4 can expand portal to contain origin and if portal\n"
+       "        // expanding doesn't reach given tolerance\n"
+       "        if (!portalCanEncapsuleOrigin(portal, &v4, &dir)\n"
+       "                || portalReachTolerance(portal, &v4, &dir))\n"
+       "               {\n"
+       "            return -1;\n"
+       "        }\n"
+       "        // v1-v2-v3 triangle must be rearranged to face outside Minkowski\n"
+       "        // difference (direction from v0).\n"
+       "        b3ExpandPortal(portal, &v4);\n"
+       "    }\n"
+       "    return -1;\n"
+       "}\n"
+       "B3_STATIC void b3FindPos(const b3MprSimplex_t *portal, b3Float4 *pos)\n"
+       "{\n"
+       "       b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+       "       b3Float4* b3mpr_vec3_origin = &zero;\n"
+       "    b3Float4 dir;\n"
+       "    size_t i;\n"
+       "    float b[4], sum, inv;\n"
+       "    b3Float4 vec, p1, p2;\n"
+       "    b3PortalDir(portal, &dir);\n"
+       "    // use barycentric coordinates of tetrahedron to find origin\n"
+       "    b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,\n"
+       "                       &b3MprSimplexPoint(portal, 2)->v);\n"
+       "    b[0] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);\n"
+       "    b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,\n"
+       "                       &b3MprSimplexPoint(portal, 2)->v);\n"
+       "    b[1] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);\n"
+       "    b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 0)->v,\n"
+       "                       &b3MprSimplexPoint(portal, 1)->v);\n"
+       "    b[2] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);\n"
+       "    b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,\n"
+       "                       &b3MprSimplexPoint(portal, 1)->v);\n"
+       "    b[3] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);\n"
+       "       sum = b[0] + b[1] + b[2] + b[3];\n"
+       "    if (b3MprIsZero(sum) || sum < 0.f){\n"
+       "               b[0] = 0.f;\n"
+       "        b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,\n"
+       "                           &b3MprSimplexPoint(portal, 3)->v);\n"
+       "        b[1] = b3MprVec3Dot(&vec, &dir);\n"
+       "        b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,\n"
+       "                           &b3MprSimplexPoint(portal, 1)->v);\n"
+       "        b[2] = b3MprVec3Dot(&vec, &dir);\n"
+       "        b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,\n"
+       "                           &b3MprSimplexPoint(portal, 2)->v);\n"
+       "        b[3] = b3MprVec3Dot(&vec, &dir);\n"
+       "               sum = b[1] + b[2] + b[3];\n"
+       "       }\n"
+       "       inv = 1.f / sum;\n"
+       "    b3MprVec3Copy(&p1, b3mpr_vec3_origin);\n"
+       "    b3MprVec3Copy(&p2, b3mpr_vec3_origin);\n"
+       "    for (i = 0; i < 4; i++){\n"
+       "        b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v1);\n"
+       "        b3MprVec3Scale(&vec, b[i]);\n"
+       "        b3MprVec3Add(&p1, &vec);\n"
+       "        b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v2);\n"
+       "        b3MprVec3Scale(&vec, b[i]);\n"
+       "        b3MprVec3Add(&p2, &vec);\n"
+       "    }\n"
+       "    b3MprVec3Scale(&p1, inv);\n"
+       "    b3MprVec3Scale(&p2, inv);\n"
+       "    b3MprVec3Copy(pos, &p1);\n"
+       "    b3MprVec3Add(pos, &p2);\n"
+       "    b3MprVec3Scale(pos, 0.5);\n"
+       "}\n"
+       "inline float b3MprVec3Dist2(const b3Float4 *a, const b3Float4 *b)\n"
+       "{\n"
+       "    b3Float4 ab;\n"
+       "    b3MprVec3Sub2(&ab, a, b);\n"
+       "    return b3MprVec3Len2(&ab);\n"
+       "}\n"
+       "inline float _b3MprVec3PointSegmentDist2(const b3Float4 *P,\n"
+       "                                                  const b3Float4 *x0,\n"
+       "                                                  const b3Float4 *b,\n"
+       "                                                  b3Float4 *witness)\n"
+       "{\n"
+       "    // The computation comes from solving equation of segment:\n"
+       "    //      S(t) = x0 + t.d\n"
+       "    //          where - x0 is initial point of segment\n"
+       "    //                - d is direction of segment from x0 (|d| > 0)\n"
+       "    //                - t belongs to <0, 1> interval\n"
+       "    // \n"
+       "    // Than, distance from a segment to some point P can be expressed:\n"
+       "    //      D(t) = |x0 + t.d - P|^2\n"
+       "    //          which is distance from any point on segment. Minimization\n"
+       "    //          of this function brings distance from P to segment.\n"
+       "    // Minimization of D(t) leads to simple quadratic equation that's\n"
+       "    // solving is straightforward.\n"
+       "    //\n"
+       "    // Bonus of this method is witness point for free.\n"
+       "    float dist, t;\n"
+       "    b3Float4 d, a;\n"
+       "    // direction of segment\n"
+       "    b3MprVec3Sub2(&d, b, x0);\n"
+       "    // precompute vector from P to x0\n"
+       "    b3MprVec3Sub2(&a, x0, P);\n"
+       "    t  = -1.f * b3MprVec3Dot(&a, &d);\n"
+       "    t /= b3MprVec3Len2(&d);\n"
+       "    if (t < 0.f || b3MprIsZero(t)){\n"
+       "        dist = b3MprVec3Dist2(x0, P);\n"
+       "        if (witness)\n"
+       "            b3MprVec3Copy(witness, x0);\n"
+       "    }else if (t > 1.f || b3MprEq(t, 1.f)){\n"
+       "        dist = b3MprVec3Dist2(b, P);\n"
+       "        if (witness)\n"
+       "            b3MprVec3Copy(witness, b);\n"
+       "    }else{\n"
+       "        if (witness){\n"
+       "            b3MprVec3Copy(witness, &d);\n"
+       "            b3MprVec3Scale(witness, t);\n"
+       "            b3MprVec3Add(witness, x0);\n"
+       "            dist = b3MprVec3Dist2(witness, P);\n"
+       "        }else{\n"
+       "            // recycling variables\n"
+       "            b3MprVec3Scale(&d, t);\n"
+       "            b3MprVec3Add(&d, &a);\n"
+       "            dist = b3MprVec3Len2(&d);\n"
+       "        }\n"
+       "    }\n"
+       "    return dist;\n"
+       "}\n"
+       "inline float b3MprVec3PointTriDist2(const b3Float4 *P,\n"
+       "                                const b3Float4 *x0, const b3Float4 *B,\n"
+       "                                const b3Float4 *C,\n"
+       "                                b3Float4 *witness)\n"
+       "{\n"
+       "    // Computation comes from analytic expression for triangle (x0, B, C)\n"
+       "    //      T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and\n"
+       "    // Then equation for distance is:\n"
+       "    //      D(s, t) = | T(s, t) - P |^2\n"
+       "    // This leads to minimization of quadratic function of two variables.\n"
+       "    // The solution from is taken only if s is between 0 and 1, t is\n"
+       "    // between 0 and 1 and t + s < 1, otherwise distance from segment is\n"
+       "    // computed.\n"
+       "    b3Float4 d1, d2, a;\n"
+       "    float u, v, w, p, q, r;\n"
+       "    float s, t, dist, dist2;\n"
+       "    b3Float4 witness2;\n"
+       "    b3MprVec3Sub2(&d1, B, x0);\n"
+       "    b3MprVec3Sub2(&d2, C, x0);\n"
+       "    b3MprVec3Sub2(&a, x0, P);\n"
+       "    u = b3MprVec3Dot(&a, &a);\n"
+       "    v = b3MprVec3Dot(&d1, &d1);\n"
+       "    w = b3MprVec3Dot(&d2, &d2);\n"
+       "    p = b3MprVec3Dot(&a, &d1);\n"
+       "    q = b3MprVec3Dot(&a, &d2);\n"
+       "    r = b3MprVec3Dot(&d1, &d2);\n"
+       "    s = (q * r - w * p) / (w * v - r * r);\n"
+       "    t = (-s * r - q) / w;\n"
+       "    if ((b3MprIsZero(s) || s > 0.f)\n"
+       "            && (b3MprEq(s, 1.f) || s < 1.f)\n"
+       "            && (b3MprIsZero(t) || t > 0.f)\n"
+       "            && (b3MprEq(t, 1.f) || t < 1.f)\n"
+       "            && (b3MprEq(t + s, 1.f) || t + s < 1.f)){\n"
+       "        if (witness){\n"
+       "            b3MprVec3Scale(&d1, s);\n"
+       "            b3MprVec3Scale(&d2, t);\n"
+       "            b3MprVec3Copy(witness, x0);\n"
+       "            b3MprVec3Add(witness, &d1);\n"
+       "            b3MprVec3Add(witness, &d2);\n"
+       "            dist = b3MprVec3Dist2(witness, P);\n"
+       "        }else{\n"
+       "            dist  = s * s * v;\n"
+       "            dist += t * t * w;\n"
+       "            dist += 2.f * s * t * r;\n"
+       "            dist += 2.f * s * p;\n"
+       "            dist += 2.f * t * q;\n"
+       "            dist += u;\n"
+       "        }\n"
+       "    }else{\n"
+       "        dist = _b3MprVec3PointSegmentDist2(P, x0, B, witness);\n"
+       "        dist2 = _b3MprVec3PointSegmentDist2(P, x0, C, &witness2);\n"
+       "        if (dist2 < dist){\n"
+       "            dist = dist2;\n"
+       "            if (witness)\n"
+       "                b3MprVec3Copy(witness, &witness2);\n"
+       "        }\n"
+       "        dist2 = _b3MprVec3PointSegmentDist2(P, B, C, &witness2);\n"
+       "        if (dist2 < dist){\n"
+       "            dist = dist2;\n"
+       "            if (witness)\n"
+       "                b3MprVec3Copy(witness, &witness2);\n"
+       "        }\n"
+       "    }\n"
+       "    return dist;\n"
+       "}\n"
+       "B3_STATIC void b3FindPenetr(int pairIndex,int bodyIndexA, int bodyIndexB,  b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
+       "                                                                                                       b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+       "                                                                                                       b3ConstArray(b3Collidable_t)                            cpuCollidables,\n"
+       "                                                                                                       b3ConstArray(b3Float4)                                  cpuVertices,\n"
+       "                                                                                                       __global b3Float4* sepAxis,\n"
+       "                       b3MprSimplex_t *portal,\n"
+       "                       float *depth, b3Float4 *pdir, b3Float4 *pos)\n"
+       "{\n"
+       "    b3Float4 dir;\n"
+       "    b3MprSupport_t v4;\n"
+       "    unsigned long iterations;\n"
+       "       b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+       "       b3Float4* b3mpr_vec3_origin = &zero;\n"
+       "    iterations = 1UL;\n"
+       "       for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)\n"
+       "    //while (1)\n"
+       "       {\n"
+       "        // compute portal direction and obtain next support point\n"
+       "        b3PortalDir(portal, &dir);\n"
+       "        \n"
+       "                b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);\n"
+       "        // reached tolerance -> find penetration info\n"
+       "        if (portalReachTolerance(portal, &v4, &dir)\n"
+       "                || iterations ==B3_MPR_MAX_ITERATIONS)\n"
+       "               {\n"
+       "            *depth = b3MprVec3PointTriDist2(b3mpr_vec3_origin,&b3MprSimplexPoint(portal, 1)->v,&b3MprSimplexPoint(portal, 2)->v,&b3MprSimplexPoint(portal, 3)->v,pdir);\n"
+       "            *depth = B3_MPR_SQRT(*depth);\n"
+       "                       \n"
+       "                       if (b3MprIsZero((*pdir).x) && b3MprIsZero((*pdir).y) && b3MprIsZero((*pdir).z))\n"
+       "                       {\n"
+       "                               \n"
+       "                               *pdir = dir;\n"
+       "                       } \n"
+       "                       b3MprVec3Normalize(pdir);\n"
+       "                       \n"
+       "            // barycentric coordinates:\n"
+       "            b3FindPos(portal, pos);\n"
+       "            return;\n"
+       "        }\n"
+       "        b3ExpandPortal(portal, &v4);\n"
+       "        iterations++;\n"
+       "    }\n"
+       "}\n"
+       "B3_STATIC void b3FindPenetrTouch(b3MprSimplex_t *portal,float *depth, b3Float4 *dir, b3Float4 *pos)\n"
+       "{\n"
+       "    // Touching contact on portal's v1 - so depth is zero and direction\n"
+       "    // is unimportant and pos can be guessed\n"
+       "    *depth = 0.f;\n"
+       "    b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
+       "       b3Float4* b3mpr_vec3_origin = &zero;\n"
+       "       b3MprVec3Copy(dir, b3mpr_vec3_origin);\n"
+       "    b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);\n"
+       "    b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);\n"
+       "    b3MprVec3Scale(pos, 0.5);\n"
+       "}\n"
+       "B3_STATIC void b3FindPenetrSegment(b3MprSimplex_t *portal,\n"
+       "                              float *depth, b3Float4 *dir, b3Float4 *pos)\n"
+       "{\n"
+       "    \n"
+       "    // Origin lies on v0-v1 segment.\n"
+       "    // Depth is distance to v1, direction also and position must be\n"
+       "    // computed\n"
+       "    b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);\n"
+       "    b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);\n"
+       "    b3MprVec3Scale(pos, 0.5f);\n"
+       "    \n"
+       "    b3MprVec3Copy(dir, &b3MprSimplexPoint(portal, 1)->v);\n"
+       "    *depth = B3_MPR_SQRT(b3MprVec3Len2(dir));\n"
+       "    b3MprVec3Normalize(dir);\n"
+       "}\n"
+       "inline int b3MprPenetration(int pairIndex, int bodyIndexA, int bodyIndexB,\n"
+       "                                       b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,\n"
+       "                                       b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
+       "                                       b3ConstArray(b3Collidable_t)    cpuCollidables,\n"
+       "                                       b3ConstArray(b3Float4)  cpuVertices,\n"
+       "                                       __global b3Float4* sepAxis,\n"
+       "                                       __global int*   hasSepAxis,\n"
+       "                                       float *depthOut, b3Float4* dirOut, b3Float4* posOut)\n"
+       "{\n"
+       "       \n"
+       "        b3MprSimplex_t portal;\n"
+       "        \n"
+       "//     if (!hasSepAxis[pairIndex])\n"
+       "       //      return -1;\n"
+       "       \n"
+       "       hasSepAxis[pairIndex] = 0;\n"
+       "        int res;\n"
+       "    // Phase 1: Portal discovery\n"
+       "    res = b3DiscoverPortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,hasSepAxis, &portal);\n"
+       "       \n"
+       "         \n"
+       "       //sepAxis[pairIndex] = *pdir;//or -dir?\n"
+       "       switch (res)\n"
+       "       {\n"
+       "       case 0:\n"
+       "               {\n"
+       "                       // Phase 2: Portal refinement\n"
+       "               \n"
+       "                       res = b3RefinePortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal);\n"
+       "                       if (res < 0)\n"
+       "                               return -1;\n"
+       "                       // Phase 3. Penetration info\n"
+       "                       b3FindPenetr(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal, depthOut, dirOut, posOut);\n"
+       "                       hasSepAxis[pairIndex] = 1;\n"
+       "                       sepAxis[pairIndex] = -*dirOut;\n"
+       "                       break;\n"
+       "               }\n"
+       "       case 1:\n"
+       "               {\n"
+       "                        // Touching contact on portal's v1.\n"
+       "                       b3FindPenetrTouch(&portal, depthOut, dirOut, posOut);\n"
+       "                       break;\n"
+       "               }\n"
+       "       case 2:\n"
+       "               {\n"
+       "                       \n"
+       "                       b3FindPenetrSegment( &portal, depthOut, dirOut, posOut);\n"
+       "                       break;\n"
+       "               }\n"
+       "       default:\n"
+       "               {\n"
+       "                       hasSepAxis[pairIndex]=0;\n"
+       "                       //if (res < 0)\n"
+       "                       //{\n"
+       "                               // Origin isn't inside portal - no collision.\n"
+       "                               return -1;\n"
+       "                       //}\n"
+       "               }\n"
+       "       };\n"
+       "       \n"
+       "       return 0;\n"
+       "};\n"
+       "#endif //B3_MPR_PENETRATION_H\n"
+       "#ifndef B3_CONTACT4DATA_H\n"
+       "#define B3_CONTACT4DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "typedef  struct b3Contact4Data b3Contact4Data_t;\n"
+       "struct b3Contact4Data\n"
+       "{\n"
+       "       b3Float4        m_worldPosB[4];\n"
+       "//     b3Float4        m_localPosA[4];\n"
+       "//     b3Float4        m_localPosB[4];\n"
+       "       b3Float4        m_worldNormalOnB;       //      w: m_nPoints\n"
+       "       unsigned short  m_restituitionCoeffCmp;\n"
+       "       unsigned short  m_frictionCoeffCmp;\n"
+       "       int m_batchIdx;\n"
+       "       int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+       "       int m_bodyBPtrAndSignBit;\n"
+       "       int     m_childIndexA;\n"
+       "       int     m_childIndexB;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "};\n"
+       "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+       "{\n"
+       "       return (int)contact->m_worldNormalOnB.w;\n"
+       "};\n"
+       "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+       "{\n"
+       "       contact->m_worldNormalOnB.w = (float)numPoints;\n"
+       "};\n"
+       "#endif //B3_CONTACT4DATA_H\n"
+       "#define AppendInc(x, out) out = atomic_inc(x)\n"
+       "#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
+       "#ifdef cl_ext_atomic_counters_32\n"
+       "       #pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+       "#else\n"
+       "       #define counter32_t volatile __global int*\n"
+       "#endif\n"
+       "__kernel void   mprPenetrationKernel( __global int4* pairs,\n"
+       "                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, \n"
+       "                                                                                                                                                                       __global const b3Collidable_t* collidables,\n"
+       "                                                                                                                                                                       __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global float4* separatingNormals,\n"
+       "                                                                                                                                                                       __global int* hasSeparatingAxis,\n"
+       "                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                                                                                                                       counter32_t nGlobalContactsOut,\n"
+       "                                                                                                                                                                       int contactCapacity,\n"
+       "                                                                                                                                                                       int numPairs)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       int pairIndex = i;\n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "               int bodyIndexA = pairs[i].x;\n"
+       "               int bodyIndexB = pairs[i].y;\n"
+       "               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "       \n"
+       "               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "               \n"
+       "               \n"
+       "               //once the broadphase avoids static-static pairs, we can remove this test\n"
+       "               if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+       "               {\n"
+       "                       return;\n"
+       "               }\n"
+       "               \n"
+       "               if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
+       "               {\n"
+       "                       return;\n"
+       "               }\n"
+       "               float depthOut;\n"
+       "               b3Float4 dirOut;\n"
+       "               b3Float4 posOut;\n"
+       "               int res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB,rigidBodies,convexShapes,collidables,vertices,separatingNormals,hasSeparatingAxis,&depthOut, &dirOut, &posOut);\n"
+       "               \n"
+       "               \n"
+       "               \n"
+       "               \n"
+       "               if (res==0)\n"
+       "               {\n"
+       "                       //add a contact\n"
+       "                       int dstIdx;\n"
+       "                       AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "                       if (dstIdx<contactCapacity)\n"
+       "                       {\n"
+       "                               pairs[pairIndex].z = dstIdx;\n"
+       "                               __global struct b3Contact4Data* c = globalContactsOut + dstIdx;\n"
+       "                               c->m_worldNormalOnB = -dirOut;//normal;\n"
+       "                               c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                               c->m_batchIdx = pairIndex;\n"
+       "                               int bodyA = pairs[pairIndex].x;\n"
+       "                               int bodyB = pairs[pairIndex].y;\n"
+       "                               c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;\n"
+       "                               c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;\n"
+       "                               c->m_childIndexA = -1;\n"
+       "                               c->m_childIndexB = -1;\n"
+       "                               //for (int i=0;i<nContacts;i++)\n"
+       "                               posOut.w = -depthOut;\n"
+       "                               c->m_worldPosB[0] = posOut;//localPoints[contactIdx[i]];\n"
+       "                               GET_NPOINTS(*c) = 1;//nContacts;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "typedef float4 Quaternion;\n"
+       "#define make_float4 (float4)\n"
+       "__inline\n"
+       "float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = make_float4(a.xyz,0.f);\n"
+       "       float4 b1 = make_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "float4 cross3(float4 a, float4 b)\n"
+       "{\n"
+       "       return cross(a,b);\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+       "{\n"
+       "       Quaternion ans;\n"
+       "       ans = cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q)\n"
+       "{\n"
+       "       return (Quaternion)(-q.xyz, q.w);\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec)\n"
+       "{\n"
+       "       Quaternion qInv = qtInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+       "{\n"
+       "       return qtRotate( *orientation, *p ) + (*translation);\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+       "{\n"
+       "       return qtRotate( qtInvert( q ), vec );\n"
+       "}\n"
+       "inline void project(__global const b3ConvexPolyhedronData_t* hull,  const float4 pos, const float4 orn, \n"
+       "const float4* dir, __global const float4* vertices, float* min, float* max)\n"
+       "{\n"
+       "       min[0] = FLT_MAX;\n"
+       "       max[0] = -FLT_MAX;\n"
+       "       int numVerts = hull->m_numVertices;\n"
+       "       const float4 localDir = qtInvRotate(orn,*dir);\n"
+       "       float offset = dot(pos,*dir);\n"
+       "       for(int i=0;i<numVerts;i++)\n"
+       "       {\n"
+       "               float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+       "               if(dp < min[0]) \n"
+       "                       min[0] = dp;\n"
+       "               if(dp > max[0]) \n"
+       "                       max[0] = dp;\n"
+       "       }\n"
+       "       if(min[0]>max[0])\n"
+       "       {\n"
+       "               float tmp = min[0];\n"
+       "               min[0] = max[0];\n"
+       "               max[0] = tmp;\n"
+       "       }\n"
+       "       min[0] += offset;\n"
+       "       max[0] += offset;\n"
+       "}\n"
+       "bool findSeparatingAxisUnitSphere(     __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
+       "       const float4 posA1,\n"
+       "       const float4 ornA,\n"
+       "       const float4 posB1,\n"
+       "       const float4 ornB,\n"
+       "       const float4 DeltaC2,\n"
+       "       __global const float4* vertices,\n"
+       "       __global const float4* unitSphereDirections,\n"
+       "       int numUnitSphereDirections,\n"
+       "       float4* sep,\n"
+       "       float* dmin)\n"
+       "{\n"
+       "       \n"
+       "       float4 posA = posA1;\n"
+       "       posA.w = 0.f;\n"
+       "       float4 posB = posB1;\n"
+       "       posB.w = 0.f;\n"
+       "       int curPlaneTests=0;\n"
+       "       int curEdgeEdge = 0;\n"
+       "       // Test unit sphere directions\n"
+       "       for (int i=0;i<numUnitSphereDirections;i++)\n"
+       "       {\n"
+       "               float4 crossje;\n"
+       "               crossje = unitSphereDirections[i];      \n"
+       "               if (dot3F4(DeltaC2,crossje)>0)\n"
+       "                       crossje *= -1.f;\n"
+       "               {\n"
+       "                       float dist;\n"
+       "                       bool result = true;\n"
+       "                       float Min0,Max0;\n"
+       "                       float Min1,Max1;\n"
+       "                       project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
+       "                       project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
+       "               \n"
+       "                       if(Max0<Min1 || Max1<Min0)\n"
+       "                               return false;\n"
+       "               \n"
+       "                       float d0 = Max0 - Min1;\n"
+       "                       float d1 = Max1 - Min0;\n"
+       "                       dist = d0<d1 ? d0:d1;\n"
+       "                       result = true;\n"
+       "       \n"
+       "                       if(dist<*dmin)\n"
+       "                       {\n"
+       "                               *dmin = dist;\n"
+       "                               *sep = crossje;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       \n"
+       "       if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+       "       {\n"
+       "               *sep = -(*sep);\n"
+       "       }\n"
+       "       return true;\n"
+       "}\n"
+       "__kernel void   findSeparatingAxisUnitSphereKernel( __global const int4* pairs, \n"
+       "                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, \n"
+       "                                                                                                                                                                       __global const b3Collidable_t* collidables,\n"
+       "                                                                                                                                                                       __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global const float4* unitSphereDirections,\n"
+       "                                                                                                                                                                       __global  float4* separatingNormals,\n"
+       "                                                                                                                                                                       __global  int* hasSeparatingAxis,\n"
+       "                                                                                                                                                                       __global  float* dmins,\n"
+       "                                                                                                                                                                       int numUnitSphereDirections,\n"
+       "                                                                                                                                                                       int numPairs\n"
+       "                                                                                                                                                                       )\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       \n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "               if (hasSeparatingAxis[i])\n"
+       "               {\n"
+       "       \n"
+       "                       int bodyIndexA = pairs[i].x;\n"
+       "                       int bodyIndexB = pairs[i].y;\n"
+       "       \n"
+       "                       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "                       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "               \n"
+       "                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "                       \n"
+       "                       \n"
+       "                       int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "       \n"
+       "                       float dmin = dmins[i];\n"
+       "       \n"
+       "                       float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "                       posA.w = 0.f;\n"
+       "                       float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                       posB.w = 0.f;\n"
+       "                       float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+       "                       float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "                       float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "                       float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "                       float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+       "                       float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "                       const float4 DeltaC2 = c0 - c1;\n"
+       "                       float4 sepNormal = separatingNormals[i];\n"
+       "                       \n"
+       "                       int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;\n"
+       "                       if (numEdgeEdgeDirections>numUnitSphereDirections)\n"
+       "                       {\n"
+       "                               bool sepEE = findSeparatingAxisUnitSphere(      &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+       "                                                                                                                                                                                                               posB,ornB,\n"
+       "                                                                                                                                                                                                               DeltaC2,\n"
+       "                                                                                                                                                                                                               vertices,unitSphereDirections,numUnitSphereDirections,&sepNormal,&dmin);\n"
+       "                               if (!sepEE)\n"
+       "                               {\n"
+       "                                       hasSeparatingAxis[i] = 0;\n"
+       "                               } else\n"
+       "                               {\n"
+       "                                       hasSeparatingAxis[i] = 1;\n"
+       "                                       separatingNormals[i] = sepNormal;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }               //if (hasSeparatingAxis[i])\n"
+       "       }//(i<numPairs)\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl
new file mode 100644 (file)
index 0000000..9c9e920
--- /dev/null
@@ -0,0 +1,1374 @@
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#define SHAPE_CONVEX_HULL 3
+#define SHAPE_PLANE 4
+#define SHAPE_CONCAVE_TRIMESH 5
+#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
+#define SHAPE_SPHERE 7
+
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile __global int*
+#endif
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+#define max2 max
+#define min2 min
+
+typedef unsigned int u32;
+
+
+
+
+typedef struct 
+{
+       union
+       {
+               float4  m_min;
+               float   m_minElems[4];
+               int                     m_minIndices[4];
+       };
+       union
+       {
+               float4  m_max;
+               float   m_maxElems[4];
+               int                     m_maxIndices[4];
+       };
+} btAabbCL;
+
+///keep this in sync with btCollidable.h
+typedef struct
+{
+       int m_numChildShapes;
+       float m_radius;
+       int m_shapeType;
+       int m_shapeIndex;
+       
+} btCollidableGpu;
+
+typedef struct
+{
+       float4  m_childPosition;
+       float4  m_childOrientation;
+       int m_shapeIndex;
+       int m_unused0;
+       int m_unused1;
+       int m_unused2;
+} btGpuChildShape;
+
+#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
+
+typedef struct
+{
+       float4 m_pos;
+       float4 m_quat;
+       float4 m_linVel;
+       float4 m_angVel;
+
+       u32 m_collidableIdx;    
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+} BodyData;
+
+
+typedef struct  
+{
+       float4          m_localCenter;
+       float4          m_extents;
+       float4          mC;
+       float4          mE;
+       
+       float                   m_radius;
+       int     m_faceOffset;
+       int m_numFaces;
+       int     m_numVertices;
+       
+       int m_vertexOffset;
+       int     m_uniqueEdgesOffset;
+       int     m_numUniqueEdges;
+       int m_unused;
+
+} ConvexPolyhedronCL;
+
+typedef struct
+{
+       float4 m_plane;
+       int m_indexOffset;
+       int m_numIndices;
+} btGpuFace;
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+__inline
+float fastDiv(float numerator, float denominator)
+{
+       return native_divide(numerator, denominator);   
+//     return numerator/denominator;   
+}
+
+__inline
+float4 fastDiv4(float4 numerator, float4 denominator)
+{
+       return native_divide(numerator, denominator);   
+}
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+       return cross(a,b);
+}
+
+//#define dot3F4 dot
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = make_float4(a.xyz,0.f);
+       float4 b1 = make_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+       return fast_normalize(v);
+}
+
+
+///////////////////////////////////////
+//     Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+       Quaternion ans;
+       ans = cross3( a, b );
+       ans += a.w*b+b.w*a;
+//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+       ans.w = a.w*b.w - dot3F4(a, b);
+       return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+       return fastNormalize4(in);
+//     in /= length( in );
+//     return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+       Quaternion qInv = qtInvert( q );
+       float4 vcpy = vec;
+       vcpy.w = 0.f;
+       float4 out = qtMul(qtMul(q,vcpy),qInv);
+       return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+       return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+       return qtRotate( qtInvert( q ), vec );
+}
+
+__inline
+float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
+{
+       return qtRotate( *orientation, *p ) + (*translation);
+}
+
+void   trInverse(float4 translationIn, Quaternion orientationIn,
+               float4* translationOut, Quaternion* orientationOut)
+{
+       *orientationOut = qtInvert(orientationIn);
+       *translationOut = qtRotate(*orientationOut, -translationIn);
+}
+
+void   trMul(float4 translationA, Quaternion orientationA,
+                                               float4 translationB, Quaternion orientationB,
+               float4* translationOut, Quaternion* orientationOut)
+{
+       *orientationOut = qtMul(orientationA,orientationB);
+       *translationOut = transform(&translationB,&translationA,&orientationA);
+}
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+       float4 n = make_float4(a.x, a.y, a.z, 0.f);
+       return fastNormalize4( n );
+}
+
+
+__inline float4 lerp3(const float4 a,const float4 b, float  t)
+{
+       return make_float4(     a.x + (b.x - a.x) * t,
+                                               a.y + (b.y - a.y) * t,
+                                               a.z + (b.z - a.z) * t,
+                                               0.f);
+}
+
+
+float signedDistanceFromPointToPlane(float4 point, float4 planeEqn, float4* closestPointOnFace)
+{
+       float4 n = (float4)(planeEqn.x, planeEqn.y, planeEqn.z, 0);
+       float dist = dot3F4(n, point) + planeEqn.w;
+       *closestPointOnFace = point - dist * n;
+       return dist;
+}
+
+
+
+inline bool IsPointInPolygon(float4 p, 
+                                                       const btGpuFace* face,
+                                                       __global const float4* baseVertex,
+                                                       __global const  int* convexIndices,
+                                                       float4* out)
+{
+    float4 a;
+    float4 b;
+    float4 ab;
+    float4 ap;
+    float4 v;
+
+       float4 plane = make_float4(face->m_plane.x,face->m_plane.y,face->m_plane.z,0.f);
+       
+       if (face->m_numIndices<2)
+               return false;
+
+       
+       float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices-1]];
+       
+       b = v0;
+
+    for(unsigned i=0; i != face->m_numIndices; ++i)
+    {
+               a = b;
+               float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];
+               b = vi;
+        ab = b-a;
+        ap = p-a;
+        v = cross3(ab,plane);
+
+        if (dot(ap, v) > 0.f)
+        {
+            float ab_m2 = dot(ab, ab);
+            float rt = ab_m2 != 0.f ? dot(ab, ap) / ab_m2 : 0.f;
+            if (rt <= 0.f)
+            {
+                *out = a;
+            }
+            else if (rt >= 1.f) 
+            {
+                *out = b;
+            }
+            else
+            {
+               float s = 1.f - rt;
+                               out[0].x = s * a.x + rt * b.x;
+                               out[0].y = s * a.y + rt * b.y;
+                               out[0].z = s * a.z + rt * b.z;
+            }
+            return false;
+        }
+    }
+    return true;
+}
+
+
+
+
+void   computeContactSphereConvex(int pairIndex,
+                                                                                                                               int bodyIndexA, int bodyIndexB, 
+                                                                                                                               int collidableIndexA, int collidableIndexB, 
+                                                                                                                               __global const BodyData* rigidBodies, 
+                                                                                                                               __global const btCollidableGpu* collidables,
+                                                                                                                               __global const ConvexPolyhedronCL* convexShapes,
+                                                                                                                               __global const float4* convexVertices,
+                                                                                                                               __global const int* convexIndices,
+                                                                                                                               __global const btGpuFace* faces,
+                                                                                                                               __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                                                                               counter32_t nGlobalContactsOut,
+                                                                                                                               int maxContactCapacity,
+                                                                                                                               float4 spherePos2,
+                                                                                                                               float radius,
+                                                                                                                               float4 pos,
+                                                                                                                               float4 quat
+                                                                                                                               )
+{
+
+       float4 invPos;
+       float4 invOrn;
+
+       trInverse(pos,quat, &invPos,&invOrn);
+
+       float4 spherePos = transform(&spherePos2,&invPos,&invOrn);
+
+       int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
+       int numFaces = convexShapes[shapeIndex].m_numFaces;
+       float4 closestPnt = (float4)(0, 0, 0, 0);
+       float4 hitNormalWorld = (float4)(0, 0, 0, 0);
+       float minDist = -1000000.f;
+       bool bCollide = true;
+
+       for ( int f = 0; f < numFaces; f++ )
+       {
+               btGpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];
+
+               // set up a plane equation 
+               float4 planeEqn;
+               float4 n1 = face.m_plane;
+               n1.w = 0.f;
+               planeEqn = n1;
+               planeEqn.w = face.m_plane.w;
+               
+       
+               // compute a signed distance from the vertex in cloth to the face of rigidbody.
+               float4 pntReturn;
+               float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
+
+               // If the distance is positive, the plane is a separating plane. 
+               if ( dist > radius )
+               {
+                       bCollide = false;
+                       break;
+               }
+
+
+               if (dist>0)
+               {
+                       //might hit an edge or vertex
+                       float4 out;
+                       float4 zeroPos = make_float4(0,0,0,0);
+
+                       bool isInPoly = IsPointInPolygon(spherePos,
+                                       &face,
+                                       &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
+                                       convexIndices,
+           &out);
+                       if (isInPoly)
+                       {
+                               if (dist>minDist)
+                               {
+                                       minDist = dist;
+                                       closestPnt = pntReturn;
+                                       hitNormalWorld = planeEqn;
+                                       
+                               }
+                       } else
+                       {
+                               float4 tmp = spherePos-out;
+                               float l2 = dot(tmp,tmp);
+                               if (l2<radius*radius)
+                               {
+                                       dist  = sqrt(l2);
+                                       if (dist>minDist)
+                                       {
+                                               minDist = dist;
+                                               closestPnt = out;
+                                               hitNormalWorld = tmp/dist;
+                                               
+                                       }
+                                       
+                               } else
+                               {
+                                       bCollide = false;
+                                       break;
+                               }
+                       }
+               } else
+               {
+                       if ( dist > minDist )
+                       {
+                               minDist = dist;
+                               closestPnt = pntReturn;
+                               hitNormalWorld.xyz = planeEqn.xyz;
+                       }
+               }
+               
+       }
+
+       
+
+       if (bCollide && minDist > -10000)
+       {
+               float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);
+               float4 pOnB1 = transform(&closestPnt,&pos,&quat);
+               
+               float actualDepth = minDist-radius;
+               if (actualDepth<=0.f)
+               {
+                       
+
+                       pOnB1.w = actualDepth;
+
+                       int dstIdx;
+                       AppendInc( nGlobalContactsOut, dstIdx );
+               
+                       
+                       if (1)//dstIdx < maxContactCapacity)
+                       {
+                               __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+                               c->m_worldNormalOnB = -normalOnSurfaceB1;
+                               c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                               c->m_batchIdx = pairIndex;
+                               c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+                               c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+                               c->m_worldPosB[0] = pOnB1;
+                               c->m_childIndexA = -1;
+                               c->m_childIndexB = -1;
+
+                               GET_NPOINTS(*c) = 1;
+                       } 
+
+               }
+       }//if (hasCollision)
+
+}
+                                                       
+
+
+int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)
+{
+       if( nPoints == 0 )
+        return 0;
+    
+    if (nPoints <=4)
+        return nPoints;
+    
+    
+    if (nPoints >64)
+        nPoints = 64;
+    
+       float4 center = make_float4(0.f);
+       {
+               
+               for (int i=0;i<nPoints;i++)
+                       center += p[i];
+               center /= (float)nPoints;
+       }
+    
+       
+    
+       //      sample 4 directions
+    
+    float4 aVector = p[0] - center;
+    float4 u = cross3( nearNormal, aVector );
+    float4 v = cross3( nearNormal, u );
+    u = normalize3( u );
+    v = normalize3( v );
+    
+    
+    //keep point with deepest penetration
+    float minW= FLT_MAX;
+    
+    int minIndex=-1;
+    
+    float4 maxDots;
+    maxDots.x = FLT_MIN;
+    maxDots.y = FLT_MIN;
+    maxDots.z = FLT_MIN;
+    maxDots.w = FLT_MIN;
+    
+    // idx, distance
+    for(int ie = 0; ie<nPoints; ie++ )
+    {
+        if (p[ie].w<minW)
+        {
+            minW = p[ie].w;
+            minIndex=ie;
+        }
+        float f;
+        float4 r = p[ie]-center;
+        f = dot3F4( u, r );
+        if (f<maxDots.x)
+        {
+            maxDots.x = f;
+            contactIdx[0].x = ie;
+        }
+        
+        f = dot3F4( -u, r );
+        if (f<maxDots.y)
+        {
+            maxDots.y = f;
+            contactIdx[0].y = ie;
+        }
+        
+        
+        f = dot3F4( v, r );
+        if (f<maxDots.z)
+        {
+            maxDots.z = f;
+            contactIdx[0].z = ie;
+        }
+        
+        f = dot3F4( -v, r );
+        if (f<maxDots.w)
+        {
+            maxDots.w = f;
+            contactIdx[0].w = ie;
+        }
+        
+    }
+    
+    if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+    {
+        //replace the first contact with minimum (todo: replace contact with least penetration)
+        contactIdx[0].x = minIndex;
+    }
+    
+    return 4;
+    
+}
+
+#define MAX_PLANE_CONVEX_POINTS 64
+
+int computeContactPlaneConvex(int pairIndex,
+                                                               int bodyIndexA, int bodyIndexB, 
+                                                               int collidableIndexA, int collidableIndexB, 
+                                                               __global const BodyData* rigidBodies, 
+                                                               __global const btCollidableGpu*collidables,
+                                                               __global const ConvexPolyhedronCL* convexShapes,
+                                                               __global const float4* convexVertices,
+                                                               __global const int* convexIndices,
+                                                               __global const btGpuFace* faces,
+                                                               __global struct b3Contact4Data* restrict globalContactsOut,
+                                                               counter32_t nGlobalContactsOut,
+                                                               int maxContactCapacity,
+                                                               float4 posB,
+                                                               Quaternion ornB
+                                                               )
+{
+       int resultIndex=-1;
+
+               int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
+       __global const ConvexPolyhedronCL* hullB = &convexShapes[shapeIndex];
+       
+       float4 posA;
+       posA = rigidBodies[bodyIndexA].m_pos;
+       Quaternion ornA;
+       ornA = rigidBodies[bodyIndexA].m_quat;
+
+       int numContactsOut = 0;
+       int numWorldVertsB1= 0;
+
+       float4 planeEq;
+        planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
+       float4 planeNormal = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);
+       float4 planeNormalWorld;
+       planeNormalWorld = qtRotate(ornA,planeNormal);
+       float planeConstant = planeEq.w;
+       
+       float4 invPosA;Quaternion invOrnA;
+       float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;
+       {
+               
+               trInverse(posA,ornA,&invPosA,&invOrnA);
+               trMul(invPosA,invOrnA,posB,ornB,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);
+       }
+       float4 invPosB;Quaternion invOrnB;
+       float4 planeInConvexPos1;       Quaternion planeInConvexOrn1;
+       {
+               
+               trInverse(posB,ornB,&invPosB,&invOrnB);
+               trMul(invPosB,invOrnB,posA,ornA,&planeInConvexPos1,&planeInConvexOrn1); 
+       }
+
+       
+       float4 planeNormalInConvex = qtRotate(planeInConvexOrn1,-planeNormal);
+       float maxDot = -1e30;
+       int hitVertex=-1;
+       float4 hitVtx;
+
+
+
+       float4 contactPoints[MAX_PLANE_CONVEX_POINTS];
+       int numPoints = 0;
+
+       int4 contactIdx;
+       contactIdx=make_int4(0,1,2,3);
+    
+       
+       for (int i=0;i<hullB->m_numVertices;i++)
+       {
+               float4 vtx = convexVertices[hullB->m_vertexOffset+i];
+               float curDot = dot(vtx,planeNormalInConvex);
+
+
+               if (curDot>maxDot)
+               {
+                       hitVertex=i;
+                       maxDot=curDot;
+                       hitVtx = vtx;
+                       //make sure the deepest points is always included
+                       if (numPoints==MAX_PLANE_CONVEX_POINTS)
+                               numPoints--;
+               }
+
+               if (numPoints<MAX_PLANE_CONVEX_POINTS)
+               {
+                       float4 vtxWorld = transform(&vtx, &posB, &ornB);
+                       float4 vtxInPlane = transform(&vtxWorld, &invPosA, &invOrnA);//oplaneTransform.inverse()*vtxWorld;
+                       float dist = dot(planeNormal,vtxInPlane)-planeConstant;
+                       if (dist<0.f)
+                       {
+                               vtxWorld.w = dist;
+                               contactPoints[numPoints] = vtxWorld;
+                               numPoints++;
+                       }
+               }
+
+       }
+
+       int numReducedPoints  = numPoints;
+       if (numPoints>4)
+       {
+               numReducedPoints = extractManifoldSequential( contactPoints, numPoints, planeNormalInConvex, &contactIdx);
+       }
+
+       if (numReducedPoints>0)
+       {
+               int dstIdx;
+           AppendInc( nGlobalContactsOut, dstIdx );
+
+               if (dstIdx < maxContactCapacity)
+               {
+                       resultIndex = dstIdx;
+                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+                       c->m_worldNormalOnB = -planeNormalWorld;
+                       //c->setFrictionCoeff(0.7);
+                       //c->setRestituitionCoeff(0.f);
+                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                       c->m_batchIdx = pairIndex;
+                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+                       c->m_childIndexA = -1;
+                       c->m_childIndexB = -1;
+
+                       switch (numReducedPoints)
+            {
+                case 4:
+                    c->m_worldPosB[3] = contactPoints[contactIdx.w];
+                case 3:
+                    c->m_worldPosB[2] = contactPoints[contactIdx.z];
+                case 2:
+                    c->m_worldPosB[1] = contactPoints[contactIdx.y];
+                case 1:
+                    c->m_worldPosB[0] = contactPoints[contactIdx.x];
+                default:
+                {
+                }
+            };
+                       
+                       GET_NPOINTS(*c) = numReducedPoints;
+               }//if (dstIdx < numPairs)
+       }       
+
+       return resultIndex;
+}
+
+
+void   computeContactPlaneSphere(int pairIndex,
+                                                                                                                               int bodyIndexA, int bodyIndexB, 
+                                                                                                                               int collidableIndexA, int collidableIndexB, 
+                                                                                                                               __global const BodyData* rigidBodies, 
+                                                                                                                               __global const btCollidableGpu* collidables,
+                                                                                                                               __global const btGpuFace* faces,
+                                                                                                                               __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                                                                               counter32_t nGlobalContactsOut,
+                                                                                                                               int maxContactCapacity)
+{
+       float4 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
+       float radius = collidables[collidableIndexB].m_radius;
+       float4 posA1 = rigidBodies[bodyIndexA].m_pos;
+       float4 ornA1 = rigidBodies[bodyIndexA].m_quat;
+       float4 posB1 = rigidBodies[bodyIndexB].m_pos;
+       float4 ornB1 = rigidBodies[bodyIndexB].m_quat;
+       
+       bool hasCollision = false;
+       float4 planeNormal1 = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);
+       float planeConstant = planeEq.w;
+       float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;
+       {
+               float4 invPosA;Quaternion invOrnA;
+               trInverse(posA1,ornA1,&invPosA,&invOrnA);
+               trMul(invPosA,invOrnA,posB1,ornB1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);
+       }
+       float4 planeInConvexPos1;       Quaternion planeInConvexOrn1;
+       {
+               float4 invPosB;Quaternion invOrnB;
+               trInverse(posB1,ornB1,&invPosB,&invOrnB);
+               trMul(invPosB,invOrnB,posA1,ornA1,&planeInConvexPos1,&planeInConvexOrn1);       
+       }
+       float4 vtx1 = qtRotate(planeInConvexOrn1,-planeNormal1)*radius;
+       float4 vtxInPlane1 = transform(&vtx1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);
+       float distance = dot3F4(planeNormal1,vtxInPlane1) - planeConstant;
+       hasCollision = distance < 0.f;//m_manifoldPtr->getContactBreakingThreshold();
+       if (hasCollision)
+       {
+               float4 vtxInPlaneProjected1 = vtxInPlane1 -   distance*planeNormal1;
+               float4 vtxInPlaneWorld1 = transform(&vtxInPlaneProjected1,&posA1,&ornA1);
+               float4 normalOnSurfaceB1 = qtRotate(ornA1,planeNormal1);
+               float4 pOnB1 = vtxInPlaneWorld1+normalOnSurfaceB1*distance;
+               pOnB1.w = distance;
+
+               int dstIdx;
+    AppendInc( nGlobalContactsOut, dstIdx );
+               
+               if (dstIdx < maxContactCapacity)
+               {
+                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+                       c->m_worldNormalOnB = -normalOnSurfaceB1;
+                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                       c->m_batchIdx = pairIndex;
+                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+                       c->m_worldPosB[0] = pOnB1;
+                       c->m_childIndexA = -1;
+                       c->m_childIndexB = -1;
+                       GET_NPOINTS(*c) = 1;
+               }//if (dstIdx < numPairs)
+       }//if (hasCollision)
+}
+
+
+__kernel void   primitiveContactsKernel( __global int4* pairs, 
+                                                                                                                                                                       __global const BodyData* rigidBodies, 
+                                                                                                                                                                       __global const btCollidableGpu* collidables,
+                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global const float4* uniqueEdges,
+                                                                                                                                                                       __global const btGpuFace* faces,
+                                                                                                                                                                       __global const int* indices,
+                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                                                                                                                       counter32_t nGlobalContactsOut,
+                                                                                                                                                                       int numPairs, int maxContactCapacity)
+{
+
+       int i = get_global_id(0);
+       int pairIndex = i;
+       
+       float4 worldVertsB1[64];
+       float4 worldVertsB2[64];
+       int capacityWorldVerts = 64;    
+
+       float4 localContactsOut[64];
+       int localContactCapacity=64;
+       
+       float minDist = -1e30f;
+       float maxDist = 0.02f;
+
+       if (i<numPairs)
+       {
+
+               int bodyIndexA = pairs[i].x;
+               int bodyIndexB = pairs[i].y;
+                       
+               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+       
+               if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+                       collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+               {
+
+                       float4 posB;
+                       posB = rigidBodies[bodyIndexB].m_pos;
+                       Quaternion ornB;
+                       ornB = rigidBodies[bodyIndexB].m_quat;
+                       int contactIndex = computeContactPlaneConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, 
+                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,
+                                                                                                                               faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity, posB,ornB);
+                       if (contactIndex>=0)
+                               pairs[pairIndex].z = contactIndex;
+
+                       return;
+               }
+
+
+               if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+                       collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
+               {
+
+                       float4 posA;
+                       posA = rigidBodies[bodyIndexA].m_pos;
+                       Quaternion ornA;
+                       ornA = rigidBodies[bodyIndexA].m_quat;
+
+
+                       int contactIndex = computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA,  collidableIndexB,collidableIndexA, 
+                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,
+                                                                                                                               faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);
+
+                       if (contactIndex>=0)
+                               pairs[pairIndex].z = contactIndex;
+
+                       return;
+               }
+
+               if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
+                       collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+               {
+                       computeContactPlaneSphere(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, 
+                                                                                                                               rigidBodies,collidables,faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity);
+                       return;
+               }
+
+
+               if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+                       collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
+               {
+
+
+                       computeContactPlaneSphere( pairIndex, bodyIndexB,bodyIndexA,  collidableIndexB,collidableIndexA, 
+                                                                                                                               rigidBodies,collidables,
+                                                                                                                               faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity);
+
+                       return;
+               }
+
+               
+
+       
+               if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+                       collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
+               {
+               
+                       float4 spherePos = rigidBodies[bodyIndexA].m_pos;
+                       float sphereRadius = collidables[collidableIndexA].m_radius;
+                       float4 convexPos = rigidBodies[bodyIndexB].m_pos;
+                       float4 convexOrn = rigidBodies[bodyIndexB].m_quat;
+
+                       computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, 
+                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
+                                                                                                                               spherePos,sphereRadius,convexPos,convexOrn);
+
+                       return;
+               }
+
+               if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
+                       collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+               {
+               
+                       float4 spherePos = rigidBodies[bodyIndexB].m_pos;
+                       float sphereRadius = collidables[collidableIndexB].m_radius;
+                       float4 convexPos = rigidBodies[bodyIndexA].m_pos;
+                       float4 convexOrn = rigidBodies[bodyIndexA].m_quat;
+
+                       computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, 
+                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
+                                                                                                                               spherePos,sphereRadius,convexPos,convexOrn);
+                       return;
+               }
+       
+       
+       
+               
+       
+       
+               if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+                       collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+               {
+                       //sphere-sphere
+                       float radiusA = collidables[collidableIndexA].m_radius;
+                       float radiusB = collidables[collidableIndexB].m_radius;
+                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+                       float4 diff = posA-posB;
+                       float len = length(diff);
+                       
+                       ///iff distance positive, don't generate a new contact
+                       if ( len <= (radiusA+radiusB))
+                       {
+                               ///distance (negative means penetration)
+                               float dist = len - (radiusA+radiusB);
+                               float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);
+                               if (len > 0.00001)
+                               {
+                                       normalOnSurfaceB = diff / len;
+                               }
+                               float4 contactPosB = posB + normalOnSurfaceB*radiusB;
+                               contactPosB.w = dist;
+                                                               
+                               int dstIdx;
+                                AppendInc( nGlobalContactsOut, dstIdx );
+                               
+                               if (dstIdx < maxContactCapacity)
+                               {
+                                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+                                       c->m_worldNormalOnB = normalOnSurfaceB;
+                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                                       c->m_batchIdx = pairIndex;
+                                       int bodyA = pairs[pairIndex].x;
+                                       int bodyB = pairs[pairIndex].y;
+                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+                                       c->m_worldPosB[0] = contactPosB;
+                                       c->m_childIndexA = -1;
+                                       c->m_childIndexB = -1;
+                                       GET_NPOINTS(*c) = 1;
+                               }//if (dstIdx < numPairs)
+                       }//if ( len <= (radiusA+radiusB))
+
+                       return;
+               }//SHAPE_SPHERE SHAPE_SPHERE
+
+       }//     if (i<numPairs)
+
+}
+
+
+// work-in-progress
+__kernel void   processCompoundPairsPrimitivesKernel( __global const int4* gpuCompoundPairs,
+                                                                                                       __global const BodyData* rigidBodies, 
+                                                                                                       __global const btCollidableGpu* collidables,
+                                                                                                       __global const ConvexPolyhedronCL* convexShapes, 
+                                                                                                       __global const float4* vertices,
+                                                                                                       __global const float4* uniqueEdges,
+                                                                                                       __global const btGpuFace* faces,
+                                                                                                       __global const int* indices,
+                                                                                                       __global btAabbCL* aabbs,
+                                                                                                       __global const btGpuChildShape* gpuChildShapes,
+                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                                                       counter32_t nGlobalContactsOut,
+                                                                                                       int numCompoundPairs, int maxContactCapacity
+                                                                                                       )
+{
+
+       int i = get_global_id(0);
+       if (i<numCompoundPairs)
+       {
+               int bodyIndexA = gpuCompoundPairs[i].x;
+               int bodyIndexB = gpuCompoundPairs[i].y;
+
+               int childShapeIndexA = gpuCompoundPairs[i].z;
+               int childShapeIndexB = gpuCompoundPairs[i].w;
+               
+               int collidableIndexA = -1;
+               int collidableIndexB = -1;
+               
+               float4 ornA = rigidBodies[bodyIndexA].m_quat;
+               float4 posA = rigidBodies[bodyIndexA].m_pos;
+               
+               float4 ornB = rigidBodies[bodyIndexB].m_quat;
+               float4 posB = rigidBodies[bodyIndexB].m_pos;
+                                                       
+               if (childShapeIndexA >= 0)
+               {
+                       collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+                       float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+                       float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+                       float4 newPosA = qtRotate(ornA,childPosA)+posA;
+                       float4 newOrnA = qtMul(ornA,childOrnA);
+                       posA = newPosA;
+                       ornA = newOrnA;
+               } else
+               {
+                       collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               }
+               
+               if (childShapeIndexB>=0)
+               {
+                       collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                       float4 newPosB = transform(&childPosB,&posB,&ornB);
+                       float4 newOrnB = qtMul(ornB,childOrnB);
+                       posB = newPosB;
+                       ornB = newOrnB;
+               } else
+               {
+                       collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;     
+               }
+       
+               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+       
+               int shapeTypeA = collidables[collidableIndexA].m_shapeType;
+               int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+
+               int pairIndex = i;
+               if ((shapeTypeA == SHAPE_PLANE) && (shapeTypeB==SHAPE_CONVEX_HULL))
+               {
+
+                       computeContactPlaneConvex( pairIndex, bodyIndexA,bodyIndexB,  collidableIndexA,collidableIndexB, 
+                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,
+                                                                                                                               faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity,posB,ornB);
+                       return;
+               }
+
+               if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB==SHAPE_PLANE))
+               {
+
+                       computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA,  collidableIndexB,collidableIndexA, 
+                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,
+                                                                                                                               faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);
+                       return;
+               }
+
+               if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB == SHAPE_SPHERE))
+               {
+                       float4 spherePos = rigidBodies[bodyIndexB].m_pos;
+                       float sphereRadius = collidables[collidableIndexB].m_radius;
+                       float4 convexPos = posA;
+                       float4 convexOrn = ornA;
+                       
+                       computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA , collidableIndexB,collidableIndexA, 
+                                                                               rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
+                                                                               spherePos,sphereRadius,convexPos,convexOrn);
+       
+                       return;
+               }
+
+               if ((shapeTypeA == SHAPE_SPHERE) && (shapeTypeB == SHAPE_CONVEX_HULL))
+               {
+
+                       float4 spherePos = rigidBodies[bodyIndexA].m_pos;
+                       float sphereRadius = collidables[collidableIndexA].m_radius;
+                       float4 convexPos = posB;
+                       float4 convexOrn = ornB;
+
+                       
+                       computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, 
+                                                                               rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
+                                                                               spherePos,sphereRadius,convexPos,convexOrn);
+       
+                       return;
+               }
+       }//     if (i<numCompoundPairs)
+}
+
+
+bool pointInTriangle(const float4* vertices, const float4* normal, float4 *p )
+{
+
+       const float4* p1 = &vertices[0];
+       const float4* p2 = &vertices[1];
+       const float4* p3 = &vertices[2];
+
+       float4 edge1;   edge1 = (*p2 - *p1);
+       float4 edge2;   edge2 = ( *p3 - *p2 );
+       float4 edge3;   edge3 = ( *p1 - *p3 );
+
+       
+       float4 p1_to_p; p1_to_p = ( *p - *p1 );
+       float4 p2_to_p; p2_to_p = ( *p - *p2 );
+       float4 p3_to_p; p3_to_p = ( *p - *p3 );
+
+       float4 edge1_normal; edge1_normal = ( cross(edge1,*normal));
+       float4 edge2_normal; edge2_normal = ( cross(edge2,*normal));
+       float4 edge3_normal; edge3_normal = ( cross(edge3,*normal));
+
+       
+       
+       float r1, r2, r3;
+       r1 = dot(edge1_normal,p1_to_p );
+       r2 = dot(edge2_normal,p2_to_p );
+       r3 = dot(edge3_normal,p3_to_p );
+       
+       if ( r1 > 0 && r2 > 0 && r3 > 0 )
+               return true;
+    if ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) 
+               return true;
+       return false;
+
+}
+
+
+float segmentSqrDistance(float4 from, float4 to,float4 p, float4* nearest) 
+{
+       float4 diff = p - from;
+       float4 v = to - from;
+       float t = dot(v,diff);
+       
+       if (t > 0) 
+       {
+               float dotVV = dot(v,v);
+               if (t < dotVV) 
+               {
+                       t /= dotVV;
+                       diff -= t*v;
+               } else 
+               {
+                       t = 1;
+                       diff -= v;
+               }
+       } else
+       {
+               t = 0;
+       }
+       *nearest = from + t*v;
+       return dot(diff,diff);  
+}
+
+
+void   computeContactSphereTriangle(int pairIndex,
+                                                                       int bodyIndexA, int bodyIndexB,
+                                                                       int collidableIndexA, int collidableIndexB, 
+                                                                       __global const BodyData* rigidBodies, 
+                                                                       __global const btCollidableGpu* collidables,
+                                                                       const float4* triangleVertices,
+                                                                       __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                       counter32_t nGlobalContactsOut,
+                                                                       int maxContactCapacity,
+                                                                       float4 spherePos2,
+                                                                       float radius,
+                                                                       float4 pos,
+                                                                       float4 quat,
+                                                                       int faceIndex
+                                                                       )
+{
+
+       float4 invPos;
+       float4 invOrn;
+
+       trInverse(pos,quat, &invPos,&invOrn);
+       float4 spherePos = transform(&spherePos2,&invPos,&invOrn);
+       int numFaces = 3;
+       float4 closestPnt = (float4)(0, 0, 0, 0);
+       float4 hitNormalWorld = (float4)(0, 0, 0, 0);
+       float minDist = -1000000.f;
+       bool bCollide = false;
+
+       
+       //////////////////////////////////////
+
+       float4 sphereCenter;
+       sphereCenter = spherePos;
+
+       const float4* vertices = triangleVertices;
+       float contactBreakingThreshold = 0.f;//todo?
+       float radiusWithThreshold = radius + contactBreakingThreshold;
+       float4 edge10;
+       edge10 = vertices[1]-vertices[0];
+       edge10.w = 0.f;//is this needed?
+       float4 edge20;
+       edge20 = vertices[2]-vertices[0];
+       edge20.w = 0.f;//is this needed?
+       float4 normal = cross3(edge10,edge20);
+       normal = normalize(normal);
+       float4 p1ToCenter;
+       p1ToCenter = sphereCenter - vertices[0];
+       
+       float distanceFromPlane = dot(p1ToCenter,normal);
+
+       if (distanceFromPlane < 0.f)
+       {
+               //triangle facing the other way
+               distanceFromPlane *= -1.f;
+               normal *= -1.f;
+       }
+       hitNormalWorld = normal;
+
+       bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
+       
+       // Check for contact / intersection
+       bool hasContact = false;
+       float4 contactPoint;
+       if (isInsideContactPlane) 
+       {
+       
+               if (pointInTriangle(vertices,&normal, &sphereCenter)) 
+               {
+                       // Inside the contact wedge - touches a point on the shell plane
+                       hasContact = true;
+                       contactPoint = sphereCenter - normal*distanceFromPlane;
+                       
+               } else {
+                       // Could be inside one of the contact capsules
+                       float contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;
+                       float4 nearestOnEdge;
+                       int numEdges = 3;
+                       for (int i = 0; i < numEdges; i++) 
+                       {
+                               float4 pa =vertices[i];
+                               float4 pb = vertices[(i+1)%3];
+
+                               float distanceSqr = segmentSqrDistance(pa,pb,sphereCenter, &nearestOnEdge);
+                               if (distanceSqr < contactCapsuleRadiusSqr) 
+                               {
+                                       // Yep, we're inside a capsule
+                                       hasContact = true;
+                                       contactPoint = nearestOnEdge;
+                                       
+                               }
+                               
+                       }
+               }
+       }
+
+       if (hasContact) 
+       {
+
+               closestPnt = contactPoint;
+               float4 contactToCenter = sphereCenter - contactPoint;
+               minDist = length(contactToCenter);
+               if (minDist>FLT_EPSILON)
+               {
+                       hitNormalWorld = normalize(contactToCenter);//*(1./minDist);
+                       bCollide  = true;
+               }
+               
+       }
+
+
+       /////////////////////////////////////
+
+       if (bCollide && minDist > -10000)
+       {
+               
+               float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);
+               float4 pOnB1 = transform(&closestPnt,&pos,&quat);
+               float actualDepth = minDist-radius;
+
+               
+               if (actualDepth<=0.f)
+               {
+                       pOnB1.w = actualDepth;
+                       int dstIdx;
+
+                       
+                       float lenSqr = dot3F4(normalOnSurfaceB1,normalOnSurfaceB1);
+                       if (lenSqr>FLT_EPSILON)
+                       {
+                               AppendInc( nGlobalContactsOut, dstIdx );
+                       
+                               if (dstIdx < maxContactCapacity)
+                               {
+                                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+                                       c->m_worldNormalOnB = -normalOnSurfaceB1;
+                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                                       c->m_batchIdx = pairIndex;
+                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
+                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
+                                       c->m_worldPosB[0] = pOnB1;
+
+                                       c->m_childIndexA = -1;
+                                       c->m_childIndexB = faceIndex;
+
+                                       GET_NPOINTS(*c) = 1;
+                               } 
+                       }
+
+               }
+       }//if (hasCollision)
+
+}
+
+
+
+// work-in-progress
+__kernel void   findConcaveSphereContactsKernel( __global int4* concavePairs,
+                                                                                               __global const BodyData* rigidBodies,
+                                                                                               __global const btCollidableGpu* collidables,
+                                                                                               __global const ConvexPolyhedronCL* convexShapes, 
+                                                                                               __global const float4* vertices,
+                                                                                               __global const float4* uniqueEdges,
+                                                                                               __global const btGpuFace* faces,
+                                                                                               __global const int* indices,
+                                                                                               __global btAabbCL* aabbs,
+                                                                                               __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                                               counter32_t nGlobalContactsOut,
+                                                                                                       int numConcavePairs, int maxContactCapacity
+                                                                                               )
+{
+
+       int i = get_global_id(0);
+       if (i>=numConcavePairs)
+               return;
+       int pairIdx = i;
+
+       int bodyIndexA = concavePairs[i].x;
+       int bodyIndexB = concavePairs[i].y;
+
+       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+       if (collidables[collidableIndexB].m_shapeType==SHAPE_SPHERE)
+       {
+               int f = concavePairs[i].z;
+               btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+               
+               float4 verticesA[3];
+               for (int i=0;i<3;i++)
+               {
+                       int index = indices[face.m_indexOffset+i];
+                       float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+                       verticesA[i] = vert;
+               }
+
+               float4 spherePos = rigidBodies[bodyIndexB].m_pos;
+               float sphereRadius = collidables[collidableIndexB].m_radius;
+               float4 convexPos = rigidBodies[bodyIndexA].m_pos;
+               float4 convexOrn = rigidBodies[bodyIndexA].m_quat;
+
+               computeContactSphereTriangle(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, 
+                                                                                                                               rigidBodies,collidables,
+                                                                                                                               verticesA,
+                                                                                                                               globalContactsOut, nGlobalContactsOut,maxContactCapacity,
+                                                                                                                               spherePos,sphereRadius,convexPos,convexOrn, f);
+
+               return;
+       }
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h
new file mode 100644 (file)
index 0000000..b2e0a2d
--- /dev/null
@@ -0,0 +1,1288 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* primitiveContactsKernelsCL =
+       "#ifndef B3_CONTACT4DATA_H\n"
+       "#define B3_CONTACT4DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "typedef  struct b3Contact4Data b3Contact4Data_t;\n"
+       "struct b3Contact4Data\n"
+       "{\n"
+       "       b3Float4        m_worldPosB[4];\n"
+       "//     b3Float4        m_localPosA[4];\n"
+       "//     b3Float4        m_localPosB[4];\n"
+       "       b3Float4        m_worldNormalOnB;       //      w: m_nPoints\n"
+       "       unsigned short  m_restituitionCoeffCmp;\n"
+       "       unsigned short  m_frictionCoeffCmp;\n"
+       "       int m_batchIdx;\n"
+       "       int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+       "       int m_bodyBPtrAndSignBit;\n"
+       "       int     m_childIndexA;\n"
+       "       int     m_childIndexB;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "};\n"
+       "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+       "{\n"
+       "       return (int)contact->m_worldNormalOnB.w;\n"
+       "};\n"
+       "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+       "{\n"
+       "       contact->m_worldNormalOnB.w = (float)numPoints;\n"
+       "};\n"
+       "#endif //B3_CONTACT4DATA_H\n"
+       "#define SHAPE_CONVEX_HULL 3\n"
+       "#define SHAPE_PLANE 4\n"
+       "#define SHAPE_CONCAVE_TRIMESH 5\n"
+       "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+       "#define SHAPE_SPHERE 7\n"
+       "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+       "#ifdef cl_ext_atomic_counters_32\n"
+       "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+       "#else\n"
+       "#define counter32_t volatile __global int*\n"
+       "#endif\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GET_NUM_GROUPS get_num_groups(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define AppendInc(x, out) out = atomic_inc(x)\n"
+       "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+       "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+       "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+       "#define max2 max\n"
+       "#define min2 min\n"
+       "typedef unsigned int u32;\n"
+       "typedef struct \n"
+       "{\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_min;\n"
+       "               float   m_minElems[4];\n"
+       "               int                     m_minIndices[4];\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_max;\n"
+       "               float   m_maxElems[4];\n"
+       "               int                     m_maxIndices[4];\n"
+       "       };\n"
+       "} btAabbCL;\n"
+       "///keep this in sync with btCollidable.h\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_numChildShapes;\n"
+       "       float m_radius;\n"
+       "       int m_shapeType;\n"
+       "       int m_shapeIndex;\n"
+       "       \n"
+       "} btCollidableGpu;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4  m_childPosition;\n"
+       "       float4  m_childOrientation;\n"
+       "       int m_shapeIndex;\n"
+       "       int m_unused0;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "} btGpuChildShape;\n"
+       "#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_pos;\n"
+       "       float4 m_quat;\n"
+       "       float4 m_linVel;\n"
+       "       float4 m_angVel;\n"
+       "       u32 m_collidableIdx;    \n"
+       "       float m_invMass;\n"
+       "       float m_restituitionCoeff;\n"
+       "       float m_frictionCoeff;\n"
+       "} BodyData;\n"
+       "typedef struct  \n"
+       "{\n"
+       "       float4          m_localCenter;\n"
+       "       float4          m_extents;\n"
+       "       float4          mC;\n"
+       "       float4          mE;\n"
+       "       \n"
+       "       float                   m_radius;\n"
+       "       int     m_faceOffset;\n"
+       "       int m_numFaces;\n"
+       "       int     m_numVertices;\n"
+       "       \n"
+       "       int m_vertexOffset;\n"
+       "       int     m_uniqueEdgesOffset;\n"
+       "       int     m_numUniqueEdges;\n"
+       "       int m_unused;\n"
+       "} ConvexPolyhedronCL;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_plane;\n"
+       "       int m_indexOffset;\n"
+       "       int m_numIndices;\n"
+       "} btGpuFace;\n"
+       "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+       "#define make_float4 (float4)\n"
+       "#define make_float2 (float2)\n"
+       "#define make_uint4 (uint4)\n"
+       "#define make_int4 (int4)\n"
+       "#define make_uint2 (uint2)\n"
+       "#define make_int2 (int2)\n"
+       "__inline\n"
+       "float fastDiv(float numerator, float denominator)\n"
+       "{\n"
+       "       return native_divide(numerator, denominator);   \n"
+       "//     return numerator/denominator;   \n"
+       "}\n"
+       "__inline\n"
+       "float4 fastDiv4(float4 numerator, float4 denominator)\n"
+       "{\n"
+       "       return native_divide(numerator, denominator);   \n"
+       "}\n"
+       "__inline\n"
+       "float4 cross3(float4 a, float4 b)\n"
+       "{\n"
+       "       return cross(a,b);\n"
+       "}\n"
+       "//#define dot3F4 dot\n"
+       "__inline\n"
+       "float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = make_float4(a.xyz,0.f);\n"
+       "       float4 b1 = make_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "float4 fastNormalize4(float4 v)\n"
+       "{\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Quaternion\n"
+       "///////////////////////////////////////\n"
+       "typedef float4 Quaternion;\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in);\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec);\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q);\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+       "{\n"
+       "       Quaternion ans;\n"
+       "       ans = cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in)\n"
+       "{\n"
+       "       return fastNormalize4(in);\n"
+       "//     in /= length( in );\n"
+       "//     return in;\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec)\n"
+       "{\n"
+       "       Quaternion qInv = qtInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q)\n"
+       "{\n"
+       "       return (Quaternion)(-q.xyz, q.w);\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+       "{\n"
+       "       return qtRotate( qtInvert( q ), vec );\n"
+       "}\n"
+       "__inline\n"
+       "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+       "{\n"
+       "       return qtRotate( *orientation, *p ) + (*translation);\n"
+       "}\n"
+       "void   trInverse(float4 translationIn, Quaternion orientationIn,\n"
+       "               float4* translationOut, Quaternion* orientationOut)\n"
+       "{\n"
+       "       *orientationOut = qtInvert(orientationIn);\n"
+       "       *translationOut = qtRotate(*orientationOut, -translationIn);\n"
+       "}\n"
+       "void   trMul(float4 translationA, Quaternion orientationA,\n"
+       "                                               float4 translationB, Quaternion orientationB,\n"
+       "               float4* translationOut, Quaternion* orientationOut)\n"
+       "{\n"
+       "       *orientationOut = qtMul(orientationA,orientationB);\n"
+       "       *translationOut = transform(&translationB,&translationA,&orientationA);\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize3(const float4 a)\n"
+       "{\n"
+       "       float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+       "       return fastNormalize4( n );\n"
+       "}\n"
+       "__inline float4 lerp3(const float4 a,const float4 b, float  t)\n"
+       "{\n"
+       "       return make_float4(     a.x + (b.x - a.x) * t,\n"
+       "                                               a.y + (b.y - a.y) * t,\n"
+       "                                               a.z + (b.z - a.z) * t,\n"
+       "                                               0.f);\n"
+       "}\n"
+       "float signedDistanceFromPointToPlane(float4 point, float4 planeEqn, float4* closestPointOnFace)\n"
+       "{\n"
+       "       float4 n = (float4)(planeEqn.x, planeEqn.y, planeEqn.z, 0);\n"
+       "       float dist = dot3F4(n, point) + planeEqn.w;\n"
+       "       *closestPointOnFace = point - dist * n;\n"
+       "       return dist;\n"
+       "}\n"
+       "inline bool IsPointInPolygon(float4 p, \n"
+       "                                                       const btGpuFace* face,\n"
+       "                                                       __global const float4* baseVertex,\n"
+       "                                                       __global const  int* convexIndices,\n"
+       "                                                       float4* out)\n"
+       "{\n"
+       "    float4 a;\n"
+       "    float4 b;\n"
+       "    float4 ab;\n"
+       "    float4 ap;\n"
+       "    float4 v;\n"
+       "       float4 plane = make_float4(face->m_plane.x,face->m_plane.y,face->m_plane.z,0.f);\n"
+       "       \n"
+       "       if (face->m_numIndices<2)\n"
+       "               return false;\n"
+       "       \n"
+       "       float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices-1]];\n"
+       "       \n"
+       "       b = v0;\n"
+       "    for(unsigned i=0; i != face->m_numIndices; ++i)\n"
+       "    {\n"
+       "               a = b;\n"
+       "               float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];\n"
+       "               b = vi;\n"
+       "        ab = b-a;\n"
+       "        ap = p-a;\n"
+       "        v = cross3(ab,plane);\n"
+       "        if (dot(ap, v) > 0.f)\n"
+       "        {\n"
+       "            float ab_m2 = dot(ab, ab);\n"
+       "            float rt = ab_m2 != 0.f ? dot(ab, ap) / ab_m2 : 0.f;\n"
+       "            if (rt <= 0.f)\n"
+       "            {\n"
+       "                *out = a;\n"
+       "            }\n"
+       "            else if (rt >= 1.f) \n"
+       "            {\n"
+       "                *out = b;\n"
+       "            }\n"
+       "            else\n"
+       "            {\n"
+       "               float s = 1.f - rt;\n"
+       "                               out[0].x = s * a.x + rt * b.x;\n"
+       "                               out[0].y = s * a.y + rt * b.y;\n"
+       "                               out[0].z = s * a.z + rt * b.z;\n"
+       "            }\n"
+       "            return false;\n"
+       "        }\n"
+       "    }\n"
+       "    return true;\n"
+       "}\n"
+       "void   computeContactSphereConvex(int pairIndex,\n"
+       "                                                                                                                               int bodyIndexA, int bodyIndexB, \n"
+       "                                                                                                                               int collidableIndexA, int collidableIndexB, \n"
+       "                                                                                                                               __global const BodyData* rigidBodies, \n"
+       "                                                                                                                               __global const btCollidableGpu* collidables,\n"
+       "                                                                                                                               __global const ConvexPolyhedronCL* convexShapes,\n"
+       "                                                                                                                               __global const float4* convexVertices,\n"
+       "                                                                                                                               __global const int* convexIndices,\n"
+       "                                                                                                                               __global const btGpuFace* faces,\n"
+       "                                                                                                                               __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                                                                               counter32_t nGlobalContactsOut,\n"
+       "                                                                                                                               int maxContactCapacity,\n"
+       "                                                                                                                               float4 spherePos2,\n"
+       "                                                                                                                               float radius,\n"
+       "                                                                                                                               float4 pos,\n"
+       "                                                                                                                               float4 quat\n"
+       "                                                                                                                               )\n"
+       "{\n"
+       "       float4 invPos;\n"
+       "       float4 invOrn;\n"
+       "       trInverse(pos,quat, &invPos,&invOrn);\n"
+       "       float4 spherePos = transform(&spherePos2,&invPos,&invOrn);\n"
+       "       int shapeIndex = collidables[collidableIndexB].m_shapeIndex;\n"
+       "       int numFaces = convexShapes[shapeIndex].m_numFaces;\n"
+       "       float4 closestPnt = (float4)(0, 0, 0, 0);\n"
+       "       float4 hitNormalWorld = (float4)(0, 0, 0, 0);\n"
+       "       float minDist = -1000000.f;\n"
+       "       bool bCollide = true;\n"
+       "       for ( int f = 0; f < numFaces; f++ )\n"
+       "       {\n"
+       "               btGpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];\n"
+       "               // set up a plane equation \n"
+       "               float4 planeEqn;\n"
+       "               float4 n1 = face.m_plane;\n"
+       "               n1.w = 0.f;\n"
+       "               planeEqn = n1;\n"
+       "               planeEqn.w = face.m_plane.w;\n"
+       "               \n"
+       "       \n"
+       "               // compute a signed distance from the vertex in cloth to the face of rigidbody.\n"
+       "               float4 pntReturn;\n"
+       "               float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);\n"
+       "               // If the distance is positive, the plane is a separating plane. \n"
+       "               if ( dist > radius )\n"
+       "               {\n"
+       "                       bCollide = false;\n"
+       "                       break;\n"
+       "               }\n"
+       "               if (dist>0)\n"
+       "               {\n"
+       "                       //might hit an edge or vertex\n"
+       "                       float4 out;\n"
+       "                       float4 zeroPos = make_float4(0,0,0,0);\n"
+       "                       bool isInPoly = IsPointInPolygon(spherePos,\n"
+       "                                       &face,\n"
+       "                                       &convexVertices[convexShapes[shapeIndex].m_vertexOffset],\n"
+       "                                       convexIndices,\n"
+       "           &out);\n"
+       "                       if (isInPoly)\n"
+       "                       {\n"
+       "                               if (dist>minDist)\n"
+       "                               {\n"
+       "                                       minDist = dist;\n"
+       "                                       closestPnt = pntReturn;\n"
+       "                                       hitNormalWorld = planeEqn;\n"
+       "                                       \n"
+       "                               }\n"
+       "                       } else\n"
+       "                       {\n"
+       "                               float4 tmp = spherePos-out;\n"
+       "                               float l2 = dot(tmp,tmp);\n"
+       "                               if (l2<radius*radius)\n"
+       "                               {\n"
+       "                                       dist  = sqrt(l2);\n"
+       "                                       if (dist>minDist)\n"
+       "                                       {\n"
+       "                                               minDist = dist;\n"
+       "                                               closestPnt = out;\n"
+       "                                               hitNormalWorld = tmp/dist;\n"
+       "                                               \n"
+       "                                       }\n"
+       "                                       \n"
+       "                               } else\n"
+       "                               {\n"
+       "                                       bCollide = false;\n"
+       "                                       break;\n"
+       "                               }\n"
+       "                       }\n"
+       "               } else\n"
+       "               {\n"
+       "                       if ( dist > minDist )\n"
+       "                       {\n"
+       "                               minDist = dist;\n"
+       "                               closestPnt = pntReturn;\n"
+       "                               hitNormalWorld.xyz = planeEqn.xyz;\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "       }\n"
+       "       \n"
+       "       if (bCollide && minDist > -10000)\n"
+       "       {\n"
+       "               float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);\n"
+       "               float4 pOnB1 = transform(&closestPnt,&pos,&quat);\n"
+       "               \n"
+       "               float actualDepth = minDist-radius;\n"
+       "               if (actualDepth<=0.f)\n"
+       "               {\n"
+       "                       \n"
+       "                       pOnB1.w = actualDepth;\n"
+       "                       int dstIdx;\n"
+       "                       AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "               \n"
+       "                       \n"
+       "                       if (1)//dstIdx < maxContactCapacity)\n"
+       "                       {\n"
+       "                               __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+       "                               c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
+       "                               c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                               c->m_batchIdx = pairIndex;\n"
+       "                               c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+       "                               c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+       "                               c->m_worldPosB[0] = pOnB1;\n"
+       "                               c->m_childIndexA = -1;\n"
+       "                               c->m_childIndexB = -1;\n"
+       "                               GET_NPOINTS(*c) = 1;\n"
+       "                       } \n"
+       "               }\n"
+       "       }//if (hasCollision)\n"
+       "}\n"
+       "                                                       \n"
+       "int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)\n"
+       "{\n"
+       "       if( nPoints == 0 )\n"
+       "        return 0;\n"
+       "    \n"
+       "    if (nPoints <=4)\n"
+       "        return nPoints;\n"
+       "    \n"
+       "    \n"
+       "    if (nPoints >64)\n"
+       "        nPoints = 64;\n"
+       "    \n"
+       "       float4 center = make_float4(0.f);\n"
+       "       {\n"
+       "               \n"
+       "               for (int i=0;i<nPoints;i++)\n"
+       "                       center += p[i];\n"
+       "               center /= (float)nPoints;\n"
+       "       }\n"
+       "    \n"
+       "       \n"
+       "    \n"
+       "       //      sample 4 directions\n"
+       "    \n"
+       "    float4 aVector = p[0] - center;\n"
+       "    float4 u = cross3( nearNormal, aVector );\n"
+       "    float4 v = cross3( nearNormal, u );\n"
+       "    u = normalize3( u );\n"
+       "    v = normalize3( v );\n"
+       "    \n"
+       "    \n"
+       "    //keep point with deepest penetration\n"
+       "    float minW= FLT_MAX;\n"
+       "    \n"
+       "    int minIndex=-1;\n"
+       "    \n"
+       "    float4 maxDots;\n"
+       "    maxDots.x = FLT_MIN;\n"
+       "    maxDots.y = FLT_MIN;\n"
+       "    maxDots.z = FLT_MIN;\n"
+       "    maxDots.w = FLT_MIN;\n"
+       "    \n"
+       "    // idx, distance\n"
+       "    for(int ie = 0; ie<nPoints; ie++ )\n"
+       "    {\n"
+       "        if (p[ie].w<minW)\n"
+       "        {\n"
+       "            minW = p[ie].w;\n"
+       "            minIndex=ie;\n"
+       "        }\n"
+       "        float f;\n"
+       "        float4 r = p[ie]-center;\n"
+       "        f = dot3F4( u, r );\n"
+       "        if (f<maxDots.x)\n"
+       "        {\n"
+       "            maxDots.x = f;\n"
+       "            contactIdx[0].x = ie;\n"
+       "        }\n"
+       "        \n"
+       "        f = dot3F4( -u, r );\n"
+       "        if (f<maxDots.y)\n"
+       "        {\n"
+       "            maxDots.y = f;\n"
+       "            contactIdx[0].y = ie;\n"
+       "        }\n"
+       "        \n"
+       "        \n"
+       "        f = dot3F4( v, r );\n"
+       "        if (f<maxDots.z)\n"
+       "        {\n"
+       "            maxDots.z = f;\n"
+       "            contactIdx[0].z = ie;\n"
+       "        }\n"
+       "        \n"
+       "        f = dot3F4( -v, r );\n"
+       "        if (f<maxDots.w)\n"
+       "        {\n"
+       "            maxDots.w = f;\n"
+       "            contactIdx[0].w = ie;\n"
+       "        }\n"
+       "        \n"
+       "    }\n"
+       "    \n"
+       "    if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)\n"
+       "    {\n"
+       "        //replace the first contact with minimum (todo: replace contact with least penetration)\n"
+       "        contactIdx[0].x = minIndex;\n"
+       "    }\n"
+       "    \n"
+       "    return 4;\n"
+       "    \n"
+       "}\n"
+       "#define MAX_PLANE_CONVEX_POINTS 64\n"
+       "int computeContactPlaneConvex(int pairIndex,\n"
+       "                                                               int bodyIndexA, int bodyIndexB, \n"
+       "                                                               int collidableIndexA, int collidableIndexB, \n"
+       "                                                               __global const BodyData* rigidBodies, \n"
+       "                                                               __global const btCollidableGpu*collidables,\n"
+       "                                                               __global const ConvexPolyhedronCL* convexShapes,\n"
+       "                                                               __global const float4* convexVertices,\n"
+       "                                                               __global const int* convexIndices,\n"
+       "                                                               __global const btGpuFace* faces,\n"
+       "                                                               __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                               counter32_t nGlobalContactsOut,\n"
+       "                                                               int maxContactCapacity,\n"
+       "                                                               float4 posB,\n"
+       "                                                               Quaternion ornB\n"
+       "                                                               )\n"
+       "{\n"
+       "       int resultIndex=-1;\n"
+       "               int shapeIndex = collidables[collidableIndexB].m_shapeIndex;\n"
+       "       __global const ConvexPolyhedronCL* hullB = &convexShapes[shapeIndex];\n"
+       "       \n"
+       "       float4 posA;\n"
+       "       posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "       Quaternion ornA;\n"
+       "       ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "       int numContactsOut = 0;\n"
+       "       int numWorldVertsB1= 0;\n"
+       "       float4 planeEq;\n"
+       "        planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;\n"
+       "       float4 planeNormal = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);\n"
+       "       float4 planeNormalWorld;\n"
+       "       planeNormalWorld = qtRotate(ornA,planeNormal);\n"
+       "       float planeConstant = planeEq.w;\n"
+       "       \n"
+       "       float4 invPosA;Quaternion invOrnA;\n"
+       "       float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;\n"
+       "       {\n"
+       "               \n"
+       "               trInverse(posA,ornA,&invPosA,&invOrnA);\n"
+       "               trMul(invPosA,invOrnA,posB,ornB,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
+       "       }\n"
+       "       float4 invPosB;Quaternion invOrnB;\n"
+       "       float4 planeInConvexPos1;       Quaternion planeInConvexOrn1;\n"
+       "       {\n"
+       "               \n"
+       "               trInverse(posB,ornB,&invPosB,&invOrnB);\n"
+       "               trMul(invPosB,invOrnB,posA,ornA,&planeInConvexPos1,&planeInConvexOrn1); \n"
+       "       }\n"
+       "       \n"
+       "       float4 planeNormalInConvex = qtRotate(planeInConvexOrn1,-planeNormal);\n"
+       "       float maxDot = -1e30;\n"
+       "       int hitVertex=-1;\n"
+       "       float4 hitVtx;\n"
+       "       float4 contactPoints[MAX_PLANE_CONVEX_POINTS];\n"
+       "       int numPoints = 0;\n"
+       "       int4 contactIdx;\n"
+       "       contactIdx=make_int4(0,1,2,3);\n"
+       "    \n"
+       "       \n"
+       "       for (int i=0;i<hullB->m_numVertices;i++)\n"
+       "       {\n"
+       "               float4 vtx = convexVertices[hullB->m_vertexOffset+i];\n"
+       "               float curDot = dot(vtx,planeNormalInConvex);\n"
+       "               if (curDot>maxDot)\n"
+       "               {\n"
+       "                       hitVertex=i;\n"
+       "                       maxDot=curDot;\n"
+       "                       hitVtx = vtx;\n"
+       "                       //make sure the deepest points is always included\n"
+       "                       if (numPoints==MAX_PLANE_CONVEX_POINTS)\n"
+       "                               numPoints--;\n"
+       "               }\n"
+       "               if (numPoints<MAX_PLANE_CONVEX_POINTS)\n"
+       "               {\n"
+       "                       float4 vtxWorld = transform(&vtx, &posB, &ornB);\n"
+       "                       float4 vtxInPlane = transform(&vtxWorld, &invPosA, &invOrnA);//oplaneTransform.inverse()*vtxWorld;\n"
+       "                       float dist = dot(planeNormal,vtxInPlane)-planeConstant;\n"
+       "                       if (dist<0.f)\n"
+       "                       {\n"
+       "                               vtxWorld.w = dist;\n"
+       "                               contactPoints[numPoints] = vtxWorld;\n"
+       "                               numPoints++;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       int numReducedPoints  = numPoints;\n"
+       "       if (numPoints>4)\n"
+       "       {\n"
+       "               numReducedPoints = extractManifoldSequential( contactPoints, numPoints, planeNormalInConvex, &contactIdx);\n"
+       "       }\n"
+       "       if (numReducedPoints>0)\n"
+       "       {\n"
+       "               int dstIdx;\n"
+       "           AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "               if (dstIdx < maxContactCapacity)\n"
+       "               {\n"
+       "                       resultIndex = dstIdx;\n"
+       "                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+       "                       c->m_worldNormalOnB = -planeNormalWorld;\n"
+       "                       //c->setFrictionCoeff(0.7);\n"
+       "                       //c->setRestituitionCoeff(0.f);\n"
+       "                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                       c->m_batchIdx = pairIndex;\n"
+       "                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+       "                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+       "                       c->m_childIndexA = -1;\n"
+       "                       c->m_childIndexB = -1;\n"
+       "                       switch (numReducedPoints)\n"
+       "            {\n"
+       "                case 4:\n"
+       "                    c->m_worldPosB[3] = contactPoints[contactIdx.w];\n"
+       "                case 3:\n"
+       "                    c->m_worldPosB[2] = contactPoints[contactIdx.z];\n"
+       "                case 2:\n"
+       "                    c->m_worldPosB[1] = contactPoints[contactIdx.y];\n"
+       "                case 1:\n"
+       "                    c->m_worldPosB[0] = contactPoints[contactIdx.x];\n"
+       "                default:\n"
+       "                {\n"
+       "                }\n"
+       "            };\n"
+       "                       \n"
+       "                       GET_NPOINTS(*c) = numReducedPoints;\n"
+       "               }//if (dstIdx < numPairs)\n"
+       "       }       \n"
+       "       return resultIndex;\n"
+       "}\n"
+       "void   computeContactPlaneSphere(int pairIndex,\n"
+       "                                                                                                                               int bodyIndexA, int bodyIndexB, \n"
+       "                                                                                                                               int collidableIndexA, int collidableIndexB, \n"
+       "                                                                                                                               __global const BodyData* rigidBodies, \n"
+       "                                                                                                                               __global const btCollidableGpu* collidables,\n"
+       "                                                                                                                               __global const btGpuFace* faces,\n"
+       "                                                                                                                               __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                                                                               counter32_t nGlobalContactsOut,\n"
+       "                                                                                                                               int maxContactCapacity)\n"
+       "{\n"
+       "       float4 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;\n"
+       "       float radius = collidables[collidableIndexB].m_radius;\n"
+       "       float4 posA1 = rigidBodies[bodyIndexA].m_pos;\n"
+       "       float4 ornA1 = rigidBodies[bodyIndexA].m_quat;\n"
+       "       float4 posB1 = rigidBodies[bodyIndexB].m_pos;\n"
+       "       float4 ornB1 = rigidBodies[bodyIndexB].m_quat;\n"
+       "       \n"
+       "       bool hasCollision = false;\n"
+       "       float4 planeNormal1 = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);\n"
+       "       float planeConstant = planeEq.w;\n"
+       "       float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;\n"
+       "       {\n"
+       "               float4 invPosA;Quaternion invOrnA;\n"
+       "               trInverse(posA1,ornA1,&invPosA,&invOrnA);\n"
+       "               trMul(invPosA,invOrnA,posB1,ornB1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
+       "       }\n"
+       "       float4 planeInConvexPos1;       Quaternion planeInConvexOrn1;\n"
+       "       {\n"
+       "               float4 invPosB;Quaternion invOrnB;\n"
+       "               trInverse(posB1,ornB1,&invPosB,&invOrnB);\n"
+       "               trMul(invPosB,invOrnB,posA1,ornA1,&planeInConvexPos1,&planeInConvexOrn1);       \n"
+       "       }\n"
+       "       float4 vtx1 = qtRotate(planeInConvexOrn1,-planeNormal1)*radius;\n"
+       "       float4 vtxInPlane1 = transform(&vtx1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
+       "       float distance = dot3F4(planeNormal1,vtxInPlane1) - planeConstant;\n"
+       "       hasCollision = distance < 0.f;//m_manifoldPtr->getContactBreakingThreshold();\n"
+       "       if (hasCollision)\n"
+       "       {\n"
+       "               float4 vtxInPlaneProjected1 = vtxInPlane1 -   distance*planeNormal1;\n"
+       "               float4 vtxInPlaneWorld1 = transform(&vtxInPlaneProjected1,&posA1,&ornA1);\n"
+       "               float4 normalOnSurfaceB1 = qtRotate(ornA1,planeNormal1);\n"
+       "               float4 pOnB1 = vtxInPlaneWorld1+normalOnSurfaceB1*distance;\n"
+       "               pOnB1.w = distance;\n"
+       "               int dstIdx;\n"
+       "    AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "               \n"
+       "               if (dstIdx < maxContactCapacity)\n"
+       "               {\n"
+       "                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+       "                       c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
+       "                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                       c->m_batchIdx = pairIndex;\n"
+       "                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+       "                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+       "                       c->m_worldPosB[0] = pOnB1;\n"
+       "                       c->m_childIndexA = -1;\n"
+       "                       c->m_childIndexB = -1;\n"
+       "                       GET_NPOINTS(*c) = 1;\n"
+       "               }//if (dstIdx < numPairs)\n"
+       "       }//if (hasCollision)\n"
+       "}\n"
+       "__kernel void   primitiveContactsKernel( __global int4* pairs, \n"
+       "                                                                                                                                                                       __global const BodyData* rigidBodies, \n"
+       "                                                                                                                                                                       __global const btCollidableGpu* collidables,\n"
+       "                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global const float4* uniqueEdges,\n"
+       "                                                                                                                                                                       __global const btGpuFace* faces,\n"
+       "                                                                                                                                                                       __global const int* indices,\n"
+       "                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                                                                                                                       counter32_t nGlobalContactsOut,\n"
+       "                                                                                                                                                                       int numPairs, int maxContactCapacity)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       int pairIndex = i;\n"
+       "       \n"
+       "       float4 worldVertsB1[64];\n"
+       "       float4 worldVertsB2[64];\n"
+       "       int capacityWorldVerts = 64;    \n"
+       "       float4 localContactsOut[64];\n"
+       "       int localContactCapacity=64;\n"
+       "       \n"
+       "       float minDist = -1e30f;\n"
+       "       float maxDist = 0.02f;\n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "               int bodyIndexA = pairs[i].x;\n"
+       "               int bodyIndexB = pairs[i].y;\n"
+       "                       \n"
+       "               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "       \n"
+       "               if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&\n"
+       "                       collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)\n"
+       "               {\n"
+       "                       float4 posB;\n"
+       "                       posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                       Quaternion ornB;\n"
+       "                       ornB = rigidBodies[bodyIndexB].m_quat;\n"
+       "                       int contactIndex = computeContactPlaneConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+       "                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,\n"
+       "                                                                                                                               faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity, posB,ornB);\n"
+       "                       if (contactIndex>=0)\n"
+       "                               pairs[pairIndex].z = contactIndex;\n"
+       "                       return;\n"
+       "               }\n"
+       "               if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&\n"
+       "                       collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)\n"
+       "               {\n"
+       "                       float4 posA;\n"
+       "                       posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "                       Quaternion ornA;\n"
+       "                       ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "                       int contactIndex = computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA,  collidableIndexB,collidableIndexA, \n"
+       "                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,\n"
+       "                                                                                                                               faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);\n"
+       "                       if (contactIndex>=0)\n"
+       "                               pairs[pairIndex].z = contactIndex;\n"
+       "                       return;\n"
+       "               }\n"
+       "               if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&\n"
+       "                       collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+       "               {\n"
+       "                       computeContactPlaneSphere(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+       "                                                                                                                               rigidBodies,collidables,faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity);\n"
+       "                       return;\n"
+       "               }\n"
+       "               if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+       "                       collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)\n"
+       "               {\n"
+       "                       computeContactPlaneSphere( pairIndex, bodyIndexB,bodyIndexA,  collidableIndexB,collidableIndexA, \n"
+       "                                                                                                                               rigidBodies,collidables,\n"
+       "                                                                                                                               faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity);\n"
+       "                       return;\n"
+       "               }\n"
+       "               \n"
+       "       \n"
+       "               if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+       "                       collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)\n"
+       "               {\n"
+       "               \n"
+       "                       float4 spherePos = rigidBodies[bodyIndexA].m_pos;\n"
+       "                       float sphereRadius = collidables[collidableIndexA].m_radius;\n"
+       "                       float4 convexPos = rigidBodies[bodyIndexB].m_pos;\n"
+       "                       float4 convexOrn = rigidBodies[bodyIndexB].m_quat;\n"
+       "                       computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+       "                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+       "                                                                                                                               spherePos,sphereRadius,convexPos,convexOrn);\n"
+       "                       return;\n"
+       "               }\n"
+       "               if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&\n"
+       "                       collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+       "               {\n"
+       "               \n"
+       "                       float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
+       "                       float sphereRadius = collidables[collidableIndexB].m_radius;\n"
+       "                       float4 convexPos = rigidBodies[bodyIndexA].m_pos;\n"
+       "                       float4 convexOrn = rigidBodies[bodyIndexA].m_quat;\n"
+       "                       computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, \n"
+       "                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+       "                                                                                                                               spherePos,sphereRadius,convexPos,convexOrn);\n"
+       "                       return;\n"
+       "               }\n"
+       "       \n"
+       "       \n"
+       "       \n"
+       "               \n"
+       "       \n"
+       "       \n"
+       "               if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+       "                       collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+       "               {\n"
+       "                       //sphere-sphere\n"
+       "                       float radiusA = collidables[collidableIndexA].m_radius;\n"
+       "                       float radiusB = collidables[collidableIndexB].m_radius;\n"
+       "                       float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "                       float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                       float4 diff = posA-posB;\n"
+       "                       float len = length(diff);\n"
+       "                       \n"
+       "                       ///iff distance positive, don't generate a new contact\n"
+       "                       if ( len <= (radiusA+radiusB))\n"
+       "                       {\n"
+       "                               ///distance (negative means penetration)\n"
+       "                               float dist = len - (radiusA+radiusB);\n"
+       "                               float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);\n"
+       "                               if (len > 0.00001)\n"
+       "                               {\n"
+       "                                       normalOnSurfaceB = diff / len;\n"
+       "                               }\n"
+       "                               float4 contactPosB = posB + normalOnSurfaceB*radiusB;\n"
+       "                               contactPosB.w = dist;\n"
+       "                                                               \n"
+       "                               int dstIdx;\n"
+       "                                AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "                               \n"
+       "                               if (dstIdx < maxContactCapacity)\n"
+       "                               {\n"
+       "                                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+       "                                       c->m_worldNormalOnB = normalOnSurfaceB;\n"
+       "                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                                       c->m_batchIdx = pairIndex;\n"
+       "                                       int bodyA = pairs[pairIndex].x;\n"
+       "                                       int bodyB = pairs[pairIndex].y;\n"
+       "                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+       "                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+       "                                       c->m_worldPosB[0] = contactPosB;\n"
+       "                                       c->m_childIndexA = -1;\n"
+       "                                       c->m_childIndexB = -1;\n"
+       "                                       GET_NPOINTS(*c) = 1;\n"
+       "                               }//if (dstIdx < numPairs)\n"
+       "                       }//if ( len <= (radiusA+radiusB))\n"
+       "                       return;\n"
+       "               }//SHAPE_SPHERE SHAPE_SPHERE\n"
+       "       }//     if (i<numPairs)\n"
+       "}\n"
+       "// work-in-progress\n"
+       "__kernel void   processCompoundPairsPrimitivesKernel( __global const int4* gpuCompoundPairs,\n"
+       "                                                                                                       __global const BodyData* rigidBodies, \n"
+       "                                                                                                       __global const btCollidableGpu* collidables,\n"
+       "                                                                                                       __global const ConvexPolyhedronCL* convexShapes, \n"
+       "                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                       __global const float4* uniqueEdges,\n"
+       "                                                                                                       __global const btGpuFace* faces,\n"
+       "                                                                                                       __global const int* indices,\n"
+       "                                                                                                       __global btAabbCL* aabbs,\n"
+       "                                                                                                       __global const btGpuChildShape* gpuChildShapes,\n"
+       "                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                                                       counter32_t nGlobalContactsOut,\n"
+       "                                                                                                       int numCompoundPairs, int maxContactCapacity\n"
+       "                                                                                                       )\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i<numCompoundPairs)\n"
+       "       {\n"
+       "               int bodyIndexA = gpuCompoundPairs[i].x;\n"
+       "               int bodyIndexB = gpuCompoundPairs[i].y;\n"
+       "               int childShapeIndexA = gpuCompoundPairs[i].z;\n"
+       "               int childShapeIndexB = gpuCompoundPairs[i].w;\n"
+       "               \n"
+       "               int collidableIndexA = -1;\n"
+       "               int collidableIndexB = -1;\n"
+       "               \n"
+       "               float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "               float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "               \n"
+       "               float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+       "               float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                                                       \n"
+       "               if (childShapeIndexA >= 0)\n"
+       "               {\n"
+       "                       collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+       "                       float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+       "                       float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+       "                       float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+       "                       float4 newOrnA = qtMul(ornA,childOrnA);\n"
+       "                       posA = newPosA;\n"
+       "                       ornA = newOrnA;\n"
+       "               } else\n"
+       "               {\n"
+       "                       collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "               }\n"
+       "               \n"
+       "               if (childShapeIndexB>=0)\n"
+       "               {\n"
+       "                       collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+       "                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+       "                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+       "                       float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+       "                       float4 newOrnB = qtMul(ornB,childOrnB);\n"
+       "                       posB = newPosB;\n"
+       "                       ornB = newOrnB;\n"
+       "               } else\n"
+       "               {\n"
+       "                       collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;     \n"
+       "               }\n"
+       "       \n"
+       "               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "       \n"
+       "               int shapeTypeA = collidables[collidableIndexA].m_shapeType;\n"
+       "               int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+       "               int pairIndex = i;\n"
+       "               if ((shapeTypeA == SHAPE_PLANE) && (shapeTypeB==SHAPE_CONVEX_HULL))\n"
+       "               {\n"
+       "                       computeContactPlaneConvex( pairIndex, bodyIndexA,bodyIndexB,  collidableIndexA,collidableIndexB, \n"
+       "                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,\n"
+       "                                                                                                                               faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity,posB,ornB);\n"
+       "                       return;\n"
+       "               }\n"
+       "               if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB==SHAPE_PLANE))\n"
+       "               {\n"
+       "                       computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA,  collidableIndexB,collidableIndexA, \n"
+       "                                                                                                                               rigidBodies,collidables,convexShapes,vertices,indices,\n"
+       "                                                                                                                               faces,  globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);\n"
+       "                       return;\n"
+       "               }\n"
+       "               if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB == SHAPE_SPHERE))\n"
+       "               {\n"
+       "                       float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
+       "                       float sphereRadius = collidables[collidableIndexB].m_radius;\n"
+       "                       float4 convexPos = posA;\n"
+       "                       float4 convexOrn = ornA;\n"
+       "                       \n"
+       "                       computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA , collidableIndexB,collidableIndexA, \n"
+       "                                                                               rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+       "                                                                               spherePos,sphereRadius,convexPos,convexOrn);\n"
+       "       \n"
+       "                       return;\n"
+       "               }\n"
+       "               if ((shapeTypeA == SHAPE_SPHERE) && (shapeTypeB == SHAPE_CONVEX_HULL))\n"
+       "               {\n"
+       "                       float4 spherePos = rigidBodies[bodyIndexA].m_pos;\n"
+       "                       float sphereRadius = collidables[collidableIndexA].m_radius;\n"
+       "                       float4 convexPos = posB;\n"
+       "                       float4 convexOrn = ornB;\n"
+       "                       \n"
+       "                       computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
+       "                                                                               rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+       "                                                                               spherePos,sphereRadius,convexPos,convexOrn);\n"
+       "       \n"
+       "                       return;\n"
+       "               }\n"
+       "       }//     if (i<numCompoundPairs)\n"
+       "}\n"
+       "bool pointInTriangle(const float4* vertices, const float4* normal, float4 *p )\n"
+       "{\n"
+       "       const float4* p1 = &vertices[0];\n"
+       "       const float4* p2 = &vertices[1];\n"
+       "       const float4* p3 = &vertices[2];\n"
+       "       float4 edge1;   edge1 = (*p2 - *p1);\n"
+       "       float4 edge2;   edge2 = ( *p3 - *p2 );\n"
+       "       float4 edge3;   edge3 = ( *p1 - *p3 );\n"
+       "       \n"
+       "       float4 p1_to_p; p1_to_p = ( *p - *p1 );\n"
+       "       float4 p2_to_p; p2_to_p = ( *p - *p2 );\n"
+       "       float4 p3_to_p; p3_to_p = ( *p - *p3 );\n"
+       "       float4 edge1_normal; edge1_normal = ( cross(edge1,*normal));\n"
+       "       float4 edge2_normal; edge2_normal = ( cross(edge2,*normal));\n"
+       "       float4 edge3_normal; edge3_normal = ( cross(edge3,*normal));\n"
+       "       \n"
+       "       \n"
+       "       float r1, r2, r3;\n"
+       "       r1 = dot(edge1_normal,p1_to_p );\n"
+       "       r2 = dot(edge2_normal,p2_to_p );\n"
+       "       r3 = dot(edge3_normal,p3_to_p );\n"
+       "       \n"
+       "       if ( r1 > 0 && r2 > 0 && r3 > 0 )\n"
+       "               return true;\n"
+       "    if ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) \n"
+       "               return true;\n"
+       "       return false;\n"
+       "}\n"
+       "float segmentSqrDistance(float4 from, float4 to,float4 p, float4* nearest) \n"
+       "{\n"
+       "       float4 diff = p - from;\n"
+       "       float4 v = to - from;\n"
+       "       float t = dot(v,diff);\n"
+       "       \n"
+       "       if (t > 0) \n"
+       "       {\n"
+       "               float dotVV = dot(v,v);\n"
+       "               if (t < dotVV) \n"
+       "               {\n"
+       "                       t /= dotVV;\n"
+       "                       diff -= t*v;\n"
+       "               } else \n"
+       "               {\n"
+       "                       t = 1;\n"
+       "                       diff -= v;\n"
+       "               }\n"
+       "       } else\n"
+       "       {\n"
+       "               t = 0;\n"
+       "       }\n"
+       "       *nearest = from + t*v;\n"
+       "       return dot(diff,diff);  \n"
+       "}\n"
+       "void   computeContactSphereTriangle(int pairIndex,\n"
+       "                                                                       int bodyIndexA, int bodyIndexB,\n"
+       "                                                                       int collidableIndexA, int collidableIndexB, \n"
+       "                                                                       __global const BodyData* rigidBodies, \n"
+       "                                                                       __global const btCollidableGpu* collidables,\n"
+       "                                                                       const float4* triangleVertices,\n"
+       "                                                                       __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                       counter32_t nGlobalContactsOut,\n"
+       "                                                                       int maxContactCapacity,\n"
+       "                                                                       float4 spherePos2,\n"
+       "                                                                       float radius,\n"
+       "                                                                       float4 pos,\n"
+       "                                                                       float4 quat,\n"
+       "                                                                       int faceIndex\n"
+       "                                                                       )\n"
+       "{\n"
+       "       float4 invPos;\n"
+       "       float4 invOrn;\n"
+       "       trInverse(pos,quat, &invPos,&invOrn);\n"
+       "       float4 spherePos = transform(&spherePos2,&invPos,&invOrn);\n"
+       "       int numFaces = 3;\n"
+       "       float4 closestPnt = (float4)(0, 0, 0, 0);\n"
+       "       float4 hitNormalWorld = (float4)(0, 0, 0, 0);\n"
+       "       float minDist = -1000000.f;\n"
+       "       bool bCollide = false;\n"
+       "       \n"
+       "       //////////////////////////////////////\n"
+       "       float4 sphereCenter;\n"
+       "       sphereCenter = spherePos;\n"
+       "       const float4* vertices = triangleVertices;\n"
+       "       float contactBreakingThreshold = 0.f;//todo?\n"
+       "       float radiusWithThreshold = radius + contactBreakingThreshold;\n"
+       "       float4 edge10;\n"
+       "       edge10 = vertices[1]-vertices[0];\n"
+       "       edge10.w = 0.f;//is this needed?\n"
+       "       float4 edge20;\n"
+       "       edge20 = vertices[2]-vertices[0];\n"
+       "       edge20.w = 0.f;//is this needed?\n"
+       "       float4 normal = cross3(edge10,edge20);\n"
+       "       normal = normalize(normal);\n"
+       "       float4 p1ToCenter;\n"
+       "       p1ToCenter = sphereCenter - vertices[0];\n"
+       "       \n"
+       "       float distanceFromPlane = dot(p1ToCenter,normal);\n"
+       "       if (distanceFromPlane < 0.f)\n"
+       "       {\n"
+       "               //triangle facing the other way\n"
+       "               distanceFromPlane *= -1.f;\n"
+       "               normal *= -1.f;\n"
+       "       }\n"
+       "       hitNormalWorld = normal;\n"
+       "       bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;\n"
+       "       \n"
+       "       // Check for contact / intersection\n"
+       "       bool hasContact = false;\n"
+       "       float4 contactPoint;\n"
+       "       if (isInsideContactPlane) \n"
+       "       {\n"
+       "       \n"
+       "               if (pointInTriangle(vertices,&normal, &sphereCenter)) \n"
+       "               {\n"
+       "                       // Inside the contact wedge - touches a point on the shell plane\n"
+       "                       hasContact = true;\n"
+       "                       contactPoint = sphereCenter - normal*distanceFromPlane;\n"
+       "                       \n"
+       "               } else {\n"
+       "                       // Could be inside one of the contact capsules\n"
+       "                       float contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;\n"
+       "                       float4 nearestOnEdge;\n"
+       "                       int numEdges = 3;\n"
+       "                       for (int i = 0; i < numEdges; i++) \n"
+       "                       {\n"
+       "                               float4 pa =vertices[i];\n"
+       "                               float4 pb = vertices[(i+1)%3];\n"
+       "                               float distanceSqr = segmentSqrDistance(pa,pb,sphereCenter, &nearestOnEdge);\n"
+       "                               if (distanceSqr < contactCapsuleRadiusSqr) \n"
+       "                               {\n"
+       "                                       // Yep, we're inside a capsule\n"
+       "                                       hasContact = true;\n"
+       "                                       contactPoint = nearestOnEdge;\n"
+       "                                       \n"
+       "                               }\n"
+       "                               \n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       if (hasContact) \n"
+       "       {\n"
+       "               closestPnt = contactPoint;\n"
+       "               float4 contactToCenter = sphereCenter - contactPoint;\n"
+       "               minDist = length(contactToCenter);\n"
+       "               if (minDist>FLT_EPSILON)\n"
+       "               {\n"
+       "                       hitNormalWorld = normalize(contactToCenter);//*(1./minDist);\n"
+       "                       bCollide  = true;\n"
+       "               }\n"
+       "               \n"
+       "       }\n"
+       "       /////////////////////////////////////\n"
+       "       if (bCollide && minDist > -10000)\n"
+       "       {\n"
+       "               \n"
+       "               float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);\n"
+       "               float4 pOnB1 = transform(&closestPnt,&pos,&quat);\n"
+       "               float actualDepth = minDist-radius;\n"
+       "               \n"
+       "               if (actualDepth<=0.f)\n"
+       "               {\n"
+       "                       pOnB1.w = actualDepth;\n"
+       "                       int dstIdx;\n"
+       "                       \n"
+       "                       float lenSqr = dot3F4(normalOnSurfaceB1,normalOnSurfaceB1);\n"
+       "                       if (lenSqr>FLT_EPSILON)\n"
+       "                       {\n"
+       "                               AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "                       \n"
+       "                               if (dstIdx < maxContactCapacity)\n"
+       "                               {\n"
+       "                                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+       "                                       c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
+       "                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                                       c->m_batchIdx = pairIndex;\n"
+       "                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
+       "                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
+       "                                       c->m_worldPosB[0] = pOnB1;\n"
+       "                                       c->m_childIndexA = -1;\n"
+       "                                       c->m_childIndexB = faceIndex;\n"
+       "                                       GET_NPOINTS(*c) = 1;\n"
+       "                               } \n"
+       "                       }\n"
+       "               }\n"
+       "       }//if (hasCollision)\n"
+       "}\n"
+       "// work-in-progress\n"
+       "__kernel void   findConcaveSphereContactsKernel( __global int4* concavePairs,\n"
+       "                                                                                               __global const BodyData* rigidBodies,\n"
+       "                                                                                               __global const btCollidableGpu* collidables,\n"
+       "                                                                                               __global const ConvexPolyhedronCL* convexShapes, \n"
+       "                                                                                               __global const float4* vertices,\n"
+       "                                                                                               __global const float4* uniqueEdges,\n"
+       "                                                                                               __global const btGpuFace* faces,\n"
+       "                                                                                               __global const int* indices,\n"
+       "                                                                                               __global btAabbCL* aabbs,\n"
+       "                                                                                               __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                                               counter32_t nGlobalContactsOut,\n"
+       "                                                                                                       int numConcavePairs, int maxContactCapacity\n"
+       "                                                                                               )\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numConcavePairs)\n"
+       "               return;\n"
+       "       int pairIdx = i;\n"
+       "       int bodyIndexA = concavePairs[i].x;\n"
+       "       int bodyIndexB = concavePairs[i].y;\n"
+       "       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "       if (collidables[collidableIndexB].m_shapeType==SHAPE_SPHERE)\n"
+       "       {\n"
+       "               int f = concavePairs[i].z;\n"
+       "               btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+       "               \n"
+       "               float4 verticesA[3];\n"
+       "               for (int i=0;i<3;i++)\n"
+       "               {\n"
+       "                       int index = indices[face.m_indexOffset+i];\n"
+       "                       float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+       "                       verticesA[i] = vert;\n"
+       "               }\n"
+       "               float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
+       "               float sphereRadius = collidables[collidableIndexB].m_radius;\n"
+       "               float4 convexPos = rigidBodies[bodyIndexA].m_pos;\n"
+       "               float4 convexOrn = rigidBodies[bodyIndexA].m_quat;\n"
+       "               computeContactSphereTriangle(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, \n"
+       "                                                                                                                               rigidBodies,collidables,\n"
+       "                                                                                                                               verticesA,\n"
+       "                                                                                                                               globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
+       "                                                                                                                               spherePos,sphereRadius,convexPos,convexOrn, f);\n"
+       "               return;\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl
new file mode 100644 (file)
index 0000000..a6565fd
--- /dev/null
@@ -0,0 +1,2018 @@
+//keep this enum in sync with the CPU version (in btCollidable.h)
+//written by Erwin Coumans
+
+
+#define SHAPE_CONVEX_HULL 3
+#define SHAPE_CONCAVE_TRIMESH 5
+#define TRIANGLE_NUM_CONVEX_FACES 5
+#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
+
+#define B3_MAX_STACK_DEPTH 256
+
+
+typedef unsigned int u32;
+
+///keep this in sync with btCollidable.h
+typedef struct
+{
+       union {
+               int m_numChildShapes;
+               int m_bvhIndex;
+       };
+       union
+       {
+               float m_radius;
+               int     m_compoundBvhIndex;
+       };
+       
+       int m_shapeType;
+       int m_shapeIndex;
+       
+} btCollidableGpu;
+
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///b3QuantizedBvhNode 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).
+typedef struct
+{
+       //12 bytes
+       unsigned short int      m_quantizedAabbMin[3];
+       unsigned short int      m_quantizedAabbMax[3];
+       //4 bytes
+       int     m_escapeIndexOrTriangleIndex;
+} b3QuantizedBvhNode;
+
+typedef struct
+{
+       float4          m_aabbMin;
+       float4          m_aabbMax;
+       float4          m_quantization;
+       int                     m_numNodes;
+       int                     m_numSubTrees;
+       int                     m_nodeOffset;
+       int                     m_subTreeOffset;
+
+} b3BvhInfo;
+
+
+int    getTriangleIndex(const b3QuantizedBvhNode* rootNode)
+{
+       unsigned int x=0;
+       unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+       // Get only the lower bits where the triangle index is stored
+       return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+int    getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+       unsigned int x=0;
+       unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+       // Get only the lower bits where the triangle index is stored
+       return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+int isLeafNode(const b3QuantizedBvhNode* rootNode)
+{
+       //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+       return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+
+int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+       //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+       return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+       
+int getEscapeIndex(const b3QuantizedBvhNode* rootNode)
+{
+       return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+       return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+
+typedef struct
+{
+       //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];
+} b3BvhSubtreeInfo;
+
+
+
+
+
+
+
+typedef struct
+{
+       float4  m_childPosition;
+       float4  m_childOrientation;
+       int m_shapeIndex;
+       int m_unused0;
+       int m_unused1;
+       int m_unused2;
+} btGpuChildShape;
+
+
+typedef struct
+{
+       float4 m_pos;
+       float4 m_quat;
+       float4 m_linVel;
+       float4 m_angVel;
+
+       u32 m_collidableIdx;
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+} BodyData;
+
+
+typedef struct  
+{
+       float4          m_localCenter;
+       float4          m_extents;
+       float4          mC;
+       float4          mE;
+       
+       float                   m_radius;
+       int     m_faceOffset;
+       int m_numFaces;
+       int     m_numVertices;
+
+       int m_vertexOffset;
+       int     m_uniqueEdgesOffset;
+       int     m_numUniqueEdges;
+       int m_unused;
+} ConvexPolyhedronCL;
+
+typedef struct 
+{
+       union
+       {
+               float4  m_min;
+               float   m_minElems[4];
+               int                     m_minIndices[4];
+       };
+       union
+       {
+               float4  m_max;
+               float   m_maxElems[4];
+               int                     m_maxIndices[4];
+       };
+} btAabbCL;
+
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Common/shared/b3Int2.h"
+
+
+
+typedef struct
+{
+       float4 m_plane;
+       int m_indexOffset;
+       int m_numIndices;
+} btGpuFace;
+
+#define make_float4 (float4)
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+       return cross(a,b);
+
+       
+//     float4 a1 = make_float4(a.xyz,0.f);
+//     float4 b1 = make_float4(b.xyz,0.f);
+
+//     return cross(a1,b1);
+
+//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);
+       
+       //      float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);
+       
+       //return c;
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = make_float4(a.xyz,0.f);
+       float4 b1 = make_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+       v = make_float4(v.xyz,0.f);
+       return fast_normalize(v);
+}
+
+
+///////////////////////////////////////
+//     Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+       Quaternion ans;
+       ans = cross3( a, b );
+       ans += a.w*b+b.w*a;
+//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+       ans.w = a.w*b.w - dot3F4(a, b);
+       return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+       return fastNormalize4(in);
+//     in /= length( in );
+//     return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+       Quaternion qInv = qtInvert( q );
+       float4 vcpy = vec;
+       vcpy.w = 0.f;
+       float4 out = qtMul(qtMul(q,vcpy),qInv);
+       return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+       return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+       return qtRotate( qtInvert( q ), vec );
+}
+
+__inline
+float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
+{
+       return qtRotate( *orientation, *p ) + (*translation);
+}
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+       float4 n = make_float4(a.x, a.y, a.z, 0.f);
+       return fastNormalize4( n );
+}
+
+inline void projectLocal(const ConvexPolyhedronCL* hull,  const float4 pos, const float4 orn, 
+const float4* dir, const float4* vertices, float* min, float* max)
+{
+       min[0] = FLT_MAX;
+       max[0] = -FLT_MAX;
+       int numVerts = hull->m_numVertices;
+
+       const float4 localDir = qtInvRotate(orn,*dir);
+       float offset = dot(pos,*dir);
+       for(int i=0;i<numVerts;i++)
+       {
+               float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
+               if(dp < min[0]) 
+                       min[0] = dp;
+               if(dp > max[0]) 
+                       max[0] = dp;
+       }
+       if(min[0]>max[0])
+       {
+               float tmp = min[0];
+               min[0] = max[0];
+               max[0] = tmp;
+       }
+       min[0] += offset;
+       max[0] += offset;
+}
+
+inline void project(__global const ConvexPolyhedronCL* hull,  const float4 pos, const float4 orn, 
+const float4* dir, __global const float4* vertices, float* min, float* max)
+{
+       min[0] = FLT_MAX;
+       max[0] = -FLT_MAX;
+       int numVerts = hull->m_numVertices;
+
+       const float4 localDir = qtInvRotate(orn,*dir);
+       float offset = dot(pos,*dir);
+       for(int i=0;i<numVerts;i++)
+       {
+               float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
+               if(dp < min[0]) 
+                       min[0] = dp;
+               if(dp > max[0]) 
+                       max[0] = dp;
+       }
+       if(min[0]>max[0])
+       {
+               float tmp = min[0];
+               min[0] = max[0];
+               max[0] = tmp;
+       }
+       min[0] += offset;
+       max[0] += offset;
+}
+
+inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, 
+       const float4 posA,const float4 ornA,
+       const float4 posB,const float4 ornB,
+       float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)
+{
+       float Min0,Max0;
+       float Min1,Max1;
+       projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);
+       project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);
+
+       if(Max0<Min1 || Max1<Min0)
+               return false;
+
+       float d0 = Max0 - Min1;
+       float d1 = Max1 - Min0;
+       *depth = d0<d1 ? d0:d1;
+       return true;
+}
+
+
+
+
+inline bool IsAlmostZero(const float4 v)
+{
+       if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)
+               return false;
+       return true;
+}
+
+
+
+bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, 
+       const float4 posA1,
+       const float4 ornA,
+       const float4 posB1,
+       const float4 ornB,
+       const float4 DeltaC2,
+       
+       const float4* verticesA, 
+       const float4* uniqueEdgesA, 
+       const btGpuFace* facesA,
+       const int*  indicesA,
+
+       __global const float4* verticesB, 
+       __global const float4* uniqueEdgesB, 
+       __global const btGpuFace* facesB,
+       __global const int*  indicesB,
+       float4* sep,
+       float* dmin)
+{
+       
+
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+       int curPlaneTests=0;
+       {
+               int numFacesA = hullA->m_numFaces;
+               // Test normals from hullA
+               for(int i=0;i<numFacesA;i++)
+               {
+                       const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
+                       float4 faceANormalWS = qtRotate(ornA,normal);
+                       if (dot3F4(DeltaC2,faceANormalWS)<0)
+                               faceANormalWS*=-1.f;
+                       curPlaneTests++;
+                       float d;
+                       if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))
+                               return false;
+                       if(d<*dmin)
+                       {
+                               *dmin = d;
+                               *sep = faceANormalWS;
+                       }
+               }
+       }
+       if((dot3F4(-DeltaC2,*sep))>0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA,  const ConvexPolyhedronCL* hullB, 
+       const float4 posA1,
+       const float4 ornA,
+       const float4 posB1,
+       const float4 ornB,
+       const float4 DeltaC2,
+       __global const float4* verticesA, 
+       __global const float4* uniqueEdgesA, 
+       __global const btGpuFace* facesA,
+       __global const int*  indicesA,
+       const float4* verticesB,
+       const float4* uniqueEdgesB, 
+       const btGpuFace* facesB,
+       const int*  indicesB,
+       float4* sep,
+       float* dmin)
+{
+
+
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+       int curPlaneTests=0;
+       {
+               int numFacesA = hullA->m_numFaces;
+               // Test normals from hullA
+               for(int i=0;i<numFacesA;i++)
+               {
+                       const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
+                       float4 faceANormalWS = qtRotate(ornA,normal);
+                       if (dot3F4(DeltaC2,faceANormalWS)<0)
+                               faceANormalWS *= -1.f;
+                       curPlaneTests++;
+                       float d;
+                       if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))
+                               return false;
+                       if(d<*dmin)
+                       {
+                               *dmin = d;
+                               *sep = faceANormalWS;
+                       }
+               }
+       }
+       if((dot3F4(-DeltaC2,*sep))>0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+
+
+bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, 
+       const float4 posA1,
+       const float4 ornA,
+       const float4 posB1,
+       const float4 ornB,
+       const float4 DeltaC2,
+       const float4* verticesA, 
+       const float4* uniqueEdgesA, 
+       const btGpuFace* facesA,
+       const int*  indicesA,
+       __global const float4* verticesB, 
+       __global const float4* uniqueEdgesB, 
+       __global const btGpuFace* facesB,
+       __global const int*  indicesB,
+               float4* sep,
+       float* dmin)
+{
+
+
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+
+       int curPlaneTests=0;
+
+       int curEdgeEdge = 0;
+       // Test edges
+       for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
+       {
+               const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];
+               float4 edge0World = qtRotate(ornA,edge0);
+
+               for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
+               {
+                       const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];
+                       float4 edge1World = qtRotate(ornB,edge1);
+
+
+                       float4 crossje = cross3(edge0World,edge1World);
+
+                       curEdgeEdge++;
+                       if(!IsAlmostZero(crossje))
+                       {
+                               crossje = normalize3(crossje);
+                               if (dot3F4(DeltaC2,crossje)<0)
+                                       crossje *= -1.f;
+
+                               float dist;
+                               bool result = true;
+                               {
+                                       float Min0,Max0;
+                                       float Min1,Max1;
+                                       projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);
+                                       project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);
+                               
+                                       if(Max0<Min1 || Max1<Min0)
+                                               result = false;
+                               
+                                       float d0 = Max0 - Min1;
+                                       float d1 = Max1 - Min0;
+                                       dist = d0<d1 ? d0:d1;
+                                       result = true;
+
+                               }
+                               
+
+                               if(dist<*dmin)
+                               {
+                                       *dmin = dist;
+                                       *sep = crossje;
+                               }
+                       }
+               }
+
+       }
+
+       
+       if((dot3F4(-DeltaC2,*sep))>0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+
+inline bool TestSepAxis(__global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, 
+       const float4 posA,const float4 ornA,
+       const float4 posB,const float4 ornB,
+       float4* sep_axis, __global const float4* vertices,float* depth)
+{
+       float Min0,Max0;
+       float Min1,Max1;
+       project(hullA,posA,ornA,sep_axis,vertices, &Min0, &Max0);
+       project(hullB,posB,ornB, sep_axis,vertices, &Min1, &Max1);
+
+       if(Max0<Min1 || Max1<Min0)
+               return false;
+
+       float d0 = Max0 - Min1;
+       float d1 = Max1 - Min0;
+       *depth = d0<d1 ? d0:d1;
+       return true;
+}
+
+
+bool findSeparatingAxis(       __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, 
+       const float4 posA1,
+       const float4 ornA,
+       const float4 posB1,
+       const float4 ornB,
+       const float4 DeltaC2,
+       __global const float4* vertices, 
+       __global const float4* uniqueEdges, 
+       __global const btGpuFace* faces,
+       __global const int*  indices,
+       float4* sep,
+       float* dmin)
+{
+       
+
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+       
+       int curPlaneTests=0;
+
+       {
+               int numFacesA = hullA->m_numFaces;
+               // Test normals from hullA
+               for(int i=0;i<numFacesA;i++)
+               {
+                       const float4 normal = faces[hullA->m_faceOffset+i].m_plane;
+                       float4 faceANormalWS = qtRotate(ornA,normal);
+       
+                       if (dot3F4(DeltaC2,faceANormalWS)<0)
+                               faceANormalWS*=-1.f;
+                               
+                       curPlaneTests++;
+       
+                       float d;
+                       if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, vertices,&d))
+                               return false;
+       
+                       if(d<*dmin)
+                       {
+                               *dmin = d;
+                               *sep = faceANormalWS;
+                       }
+               }
+       }
+
+
+               if((dot3F4(-DeltaC2,*sep))>0.0f)
+               {
+                       *sep = -(*sep);
+               }
+       
+       return true;
+}
+
+
+
+
+bool findSeparatingAxisUnitSphere(     __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, 
+       const float4 posA1,
+       const float4 ornA,
+       const float4 posB1,
+       const float4 ornB,
+       const float4 DeltaC2,
+       __global const float4* vertices,
+       __global const float4* unitSphereDirections,
+       int numUnitSphereDirections,
+       float4* sep,
+       float* dmin)
+{
+       
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+
+       int curPlaneTests=0;
+
+       int curEdgeEdge = 0;
+       // Test unit sphere directions
+       for (int i=0;i<numUnitSphereDirections;i++)
+       {
+
+               float4 crossje;
+               crossje = unitSphereDirections[i];      
+
+               if (dot3F4(DeltaC2,crossje)>0)
+                       crossje *= -1.f;
+               {
+                       float dist;
+                       bool result = true;
+                       float Min0,Max0;
+                       float Min1,Max1;
+                       project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);
+                       project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);
+               
+                       if(Max0<Min1 || Max1<Min0)
+                               return false;
+               
+                       float d0 = Max0 - Min1;
+                       float d1 = Max1 - Min0;
+                       dist = d0<d1 ? d0:d1;
+                       result = true;
+       
+                       if(dist<*dmin)
+                       {
+                               *dmin = dist;
+                               *sep = crossje;
+                       }
+               }
+       }
+
+       
+       if((dot3F4(-DeltaC2,*sep))>0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+
+bool findSeparatingAxisEdgeEdge(       __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, 
+       const float4 posA1,
+       const float4 ornA,
+       const float4 posB1,
+       const float4 ornB,
+       const float4 DeltaC2,
+       __global const float4* vertices, 
+       __global const float4* uniqueEdges, 
+       __global const btGpuFace* faces,
+       __global const int*  indices,
+       float4* sep,
+       float* dmin)
+{
+       
+
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+
+       int curPlaneTests=0;
+
+       int curEdgeEdge = 0;
+       // Test edges
+       for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
+       {
+               const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset+e0];
+               float4 edge0World = qtRotate(ornA,edge0);
+
+               for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
+               {
+                       const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset+e1];
+                       float4 edge1World = qtRotate(ornB,edge1);
+
+
+                       float4 crossje = cross3(edge0World,edge1World);
+
+                       curEdgeEdge++;
+                       if(!IsAlmostZero(crossje))
+                       {
+                               crossje = normalize3(crossje);
+                               if (dot3F4(DeltaC2,crossje)<0)
+                                       crossje*=-1.f;
+                                       
+                               float dist;
+                               bool result = true;
+                               {
+                                       float Min0,Max0;
+                                       float Min1,Max1;
+                                       project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);
+                                       project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);
+                               
+                                       if(Max0<Min1 || Max1<Min0)
+                                               return false;
+                               
+                                       float d0 = Max0 - Min1;
+                                       float d1 = Max1 - Min0;
+                                       dist = d0<d1 ? d0:d1;
+                                       result = true;
+
+                               }
+                               
+
+                               if(dist<*dmin)
+                               {
+                                       *dmin = dist;
+                                       *sep = crossje;
+                               }
+                       }
+               }
+
+       }
+
+       
+       if((dot3F4(-DeltaC2,*sep))>0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+
+// work-in-progress
+__kernel void   processCompoundPairsKernel( __global const int4* gpuCompoundPairs,
+                                                                                                                                                                       __global const BodyData* rigidBodies, 
+                                                                                                                                                                       __global const btCollidableGpu* collidables,
+                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global const float4* uniqueEdges,
+                                                                                                                                                                       __global const btGpuFace* faces,
+                                                                                                                                                                       __global const int* indices,
+                                                                                                                                                                       __global btAabbCL* aabbs,
+                                                                                                                                                                       __global const btGpuChildShape* gpuChildShapes,
+                                                                                                                                                                       __global volatile float4* gpuCompoundSepNormalsOut,
+                                                                                                                                                                       __global volatile int* gpuHasCompoundSepNormalsOut,
+                                                                                                                                                                       int numCompoundPairs
+                                                                                                                                                                       )
+{
+
+       int i = get_global_id(0);
+       if (i<numCompoundPairs)
+       {
+               int bodyIndexA = gpuCompoundPairs[i].x;
+               int bodyIndexB = gpuCompoundPairs[i].y;
+
+               int childShapeIndexA = gpuCompoundPairs[i].z;
+               int childShapeIndexB = gpuCompoundPairs[i].w;
+               
+               int collidableIndexA = -1;
+               int collidableIndexB = -1;
+               
+               float4 ornA = rigidBodies[bodyIndexA].m_quat;
+               float4 posA = rigidBodies[bodyIndexA].m_pos;
+               
+               float4 ornB = rigidBodies[bodyIndexB].m_quat;
+               float4 posB = rigidBodies[bodyIndexB].m_pos;
+                                                       
+               if (childShapeIndexA >= 0)
+               {
+                       collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+                       float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+                       float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+                       float4 newPosA = qtRotate(ornA,childPosA)+posA;
+                       float4 newOrnA = qtMul(ornA,childOrnA);
+                       posA = newPosA;
+                       ornA = newOrnA;
+               } else
+               {
+                       collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               }
+               
+               if (childShapeIndexB>=0)
+               {
+                       collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                       float4 newPosB = transform(&childPosB,&posB,&ornB);
+                       float4 newOrnB = qtMul(ornB,childOrnB);
+                       posB = newPosB;
+                       ornB = newOrnB;
+               } else
+               {
+                       collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;     
+               }
+       
+               gpuHasCompoundSepNormalsOut[i] = 0;
+       
+               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+       
+               int shapeTypeA = collidables[collidableIndexA].m_shapeType;
+               int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+       
+
+               if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))
+               {
+                       return;
+               }
+
+               int hasSeparatingAxis = 5;
+                                                       
+               int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+               float dmin = FLT_MAX;
+               posA.w = 0.f;
+               posB.w = 0.f;
+               float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+               float4 c0 = transform(&c0local, &posA, &ornA);
+               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+               float4 c1 = transform(&c1local,&posB,&ornB);
+               const float4 DeltaC2 = c0 - c1;
+               float4 sepNormal = make_float4(1,0,0,0);
+               bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+               hasSeparatingAxis = 4;
+               if (!sepA)
+               {
+                       hasSeparatingAxis = 0;
+               } else
+               {
+                       bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,posA,ornA,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+
+                       if (!sepB)
+                       {
+                               hasSeparatingAxis = 0;
+                       } else//(!sepB)
+                       {
+                               bool sepEE = findSeparatingAxisEdgeEdge(        &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
+                               if (sepEE)
+                               {
+                                               gpuCompoundSepNormalsOut[i] = sepNormal;//fastNormalize4(sepNormal);
+                                               gpuHasCompoundSepNormalsOut[i] = 1;
+                               }//sepEE
+                       }//(!sepB)
+               }//(!sepA)
+               
+               
+       }
+               
+}
+
+
+inline b3Float4 MyUnQuantize(const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)
+{
+               b3Float4 vecOut;
+               vecOut = b3MakeFloat4(
+                       (float)(vecIn[0]) / (quantization.x),
+                       (float)(vecIn[1]) / (quantization.y),
+                       (float)(vecIn[2]) / (quantization.z),
+                       0.f);
+
+               vecOut += bvhAabbMin;
+               return vecOut;
+}
+
+inline b3Float4 MyUnQuantizeGlobal(__global const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)
+{
+               b3Float4 vecOut;
+               vecOut = b3MakeFloat4(
+                       (float)(vecIn[0]) / (quantization.x),
+                       (float)(vecIn[1]) / (quantization.y),
+                       (float)(vecIn[2]) / (quantization.z),
+                       0.f);
+
+               vecOut += bvhAabbMin;
+               return vecOut;
+}
+
+
+// work-in-progress
+__kernel void   findCompoundPairsKernel( __global const int4* pairs, 
+       __global const BodyData* rigidBodies, 
+       __global const btCollidableGpu* collidables,
+       __global const ConvexPolyhedronCL* convexShapes, 
+       __global const float4* vertices,
+       __global const float4* uniqueEdges,
+       __global const btGpuFace* faces,
+       __global const int* indices,
+       __global b3Aabb_t* aabbLocalSpace,
+       __global const btGpuChildShape* gpuChildShapes,
+       __global volatile int4* gpuCompoundPairsOut,
+       __global volatile int* numCompoundPairsOut,
+       __global const b3BvhSubtreeInfo* subtrees,
+       __global const b3QuantizedBvhNode* quantizedNodes,
+       __global const b3BvhInfo* bvhInfos,
+       int numPairs,
+       int maxNumCompoundPairsCapacity
+       )
+{
+
+       int i = get_global_id(0);
+
+       if (i<numPairs)
+       {
+               int bodyIndexA = pairs[i].x;
+               int bodyIndexB = pairs[i].y;
+
+               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+
+               //once the broadphase avoids static-static pairs, we can remove this test
+               if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+               {
+                       return;
+               }
+
+               if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) &&(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+               {
+                       int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;
+                       int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;
+                       int numSubTreesA = bvhInfos[bvhA].m_numSubTrees;
+                       int subTreesOffsetA = bvhInfos[bvhA].m_subTreeOffset;
+                       int subTreesOffsetB = bvhInfos[bvhB].m_subTreeOffset;
+
+
+                       int numSubTreesB = bvhInfos[bvhB].m_numSubTrees;
+                       
+                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+                       b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
+
+                       b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
+                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+                       
+                       for (int p=0;p<numSubTreesA;p++)
+                       {
+                               b3BvhSubtreeInfo subtreeA = subtrees[subTreesOffsetA+p];
+                               //bvhInfos[bvhA].m_quantization
+                               b3Float4 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
+                               b3Float4 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
+
+                               b3Float4 aabbAMinOut,aabbAMaxOut;
+                               float margin=0.f;
+                               b3TransformAabb2(treeAminLocal,treeAmaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);
+                               
+                               for (int q=0;q<numSubTreesB;q++)
+                               {
+                                       b3BvhSubtreeInfo subtreeB = subtrees[subTreesOffsetB+q];
+
+                                       b3Float4 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
+                                       b3Float4 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
+
+                                       b3Float4 aabbBMinOut,aabbBMaxOut;
+                                       float margin=0.f;
+                                       b3TransformAabb2(treeBminLocal,treeBmaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);
+
+                                       
+                                       
+                                       bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
+                                       if (aabbOverlap)
+                                       {
+                                               
+                                               int startNodeIndexA = subtreeA.m_rootNodeIndex+bvhInfos[bvhA].m_nodeOffset;
+                                               int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;
+
+                                               int startNodeIndexB = subtreeB.m_rootNodeIndex+bvhInfos[bvhB].m_nodeOffset;
+                                               int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;
+
+
+                                               b3Int2 nodeStack[B3_MAX_STACK_DEPTH];
+                                               b3Int2 node0;
+                                               node0.x = startNodeIndexA;
+                                               node0.y = startNodeIndexB;
+                                               int maxStackDepth = B3_MAX_STACK_DEPTH;
+                                               int depth=0;
+                                               nodeStack[depth++]=node0;
+
+                                               do
+                                               {
+                                                       b3Int2 node = nodeStack[--depth];
+
+                                                       b3Float4 aMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
+                                                       b3Float4 aMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
+
+                                                       b3Float4 bMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
+                                                       b3Float4 bMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
+
+                                                       float margin=0.f;
+                                                       b3Float4 aabbAMinOut,aabbAMaxOut;
+                                                       b3TransformAabb2(aMinLocal,aMaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);
+
+                                                       b3Float4 aabbBMinOut,aabbBMaxOut;
+                                                       b3TransformAabb2(bMinLocal,bMaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);
+
+                                                       
+                                                       bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
+                                                       if (nodeOverlap)
+                                                       {
+                                                               bool isLeafA = isLeafNodeGlobal(&quantizedNodes[node.x]);
+                                                               bool isLeafB = isLeafNodeGlobal(&quantizedNodes[node.y]);
+                                                               bool isInternalA = !isLeafA;
+                                                               bool isInternalB = !isLeafB;
+
+                                                               //fail, even though it might hit two leaf nodes
+                                                               if (depth+4>maxStackDepth && !(isLeafA && isLeafB))
+                                                               {
+                                                                       //printf("Error: traversal exceeded maxStackDepth");
+                                                                       continue;
+                                                               }
+
+                                                               if(isInternalA)
+                                                               {
+                                                                       int nodeAleftChild = node.x+1;
+                                                                       bool isNodeALeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.x+1]);
+                                                                       int nodeArightChild = isNodeALeftChildLeaf? node.x+2 : node.x+1 + getEscapeIndexGlobal(&quantizedNodes[node.x+1]);
+
+                                                                       if(isInternalB)
+                                                                       {                                       
+                                                                               int nodeBleftChild = node.y+1;
+                                                                               bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);
+                                                                               int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);
+
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeAleftChild,node.y);
+                                                                               nodeStack[depth++] = b3MakeInt2(nodeArightChild,node.y);
+                                                                       }
+                                                               }
+                                                               else
+                                                               {
+                                                                       if(isInternalB)
+                                                                       {
+                                                                               int nodeBleftChild = node.y+1;
+                                                                               bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);
+                                                                               int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);
+                                                                               nodeStack[depth++] = b3MakeInt2(node.x,nodeBleftChild);
+                                                                               nodeStack[depth++] = b3MakeInt2(node.x,nodeBrightChild);
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               int compoundPairIdx = atomic_inc(numCompoundPairsOut);
+                                                                               if (compoundPairIdx<maxNumCompoundPairsCapacity)
+                                                                               {
+                                                                                       int childShapeIndexA = getTriangleIndexGlobal(&quantizedNodes[node.x]);
+                                                                                       int childShapeIndexB = getTriangleIndexGlobal(&quantizedNodes[node.y]);
+                                                                                       gpuCompoundPairsOut[compoundPairIdx]  = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               } while (depth);
+                                       }
+                               }
+                       }
+                       
+                       return;
+               }
+
+
+
+
+
+               if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+               {
+
+                       if (collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) 
+                       {
+
+                               int numChildrenA = collidables[collidableIndexA].m_numChildShapes;
+                               for (int c=0;c<numChildrenA;c++)
+                               {
+                                       int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex+c;
+                                       int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+
+                                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+                                       float4 ornA = rigidBodies[bodyIndexA].m_quat;
+                                       float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+                                       float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+                                       float4 newPosA = qtRotate(ornA,childPosA)+posA;
+                                       float4 newOrnA = qtMul(ornA,childOrnA);
+
+                                       int shapeIndexA = collidables[childColIndexA].m_shapeIndex;
+                                       b3Aabb_t aabbAlocal = aabbLocalSpace[shapeIndexA];
+                                       float margin = 0.f;
+                                       
+                                       b3Float4 aabbAMinWS;
+                                       b3Float4 aabbAMaxWS;
+                                       
+                                       b3TransformAabb2(aabbAlocal.m_minVec,aabbAlocal.m_maxVec,margin,
+                                               newPosA,
+                                               newOrnA,
+                                               &aabbAMinWS,&aabbAMaxWS);
+                                               
+                                       
+                                       if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                                       {
+                                               int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+                                               for (int b=0;b<numChildrenB;b++)
+                                               {
+                                                       int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+                                                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                                                       float4 ornB = rigidBodies[bodyIndexB].m_quat;
+                                                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+                                                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                                                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                                                       float4 newPosB = transform(&childPosB,&posB,&ornB);
+                                                       float4 newOrnB = qtMul(ornB,childOrnB);
+
+                                                       int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+                                                       b3Aabb_t aabbBlocal = aabbLocalSpace[shapeIndexB];
+                                                       
+                                                       b3Float4 aabbBMinWS;
+                                                       b3Float4 aabbBMaxWS;
+                                                       
+                                                       b3TransformAabb2(aabbBlocal.m_minVec,aabbBlocal.m_maxVec,margin,
+                                                               newPosB,
+                                                               newOrnB,
+                                                               &aabbBMinWS,&aabbBMaxWS);
+                                                               
+                                                               
+                                                       
+                                                       bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinWS,aabbAMaxWS,aabbBMinWS,aabbBMaxWS);
+                                                       if (aabbOverlap)
+                                                       {
+                                                               int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+                                                               float dmin = FLT_MAX;
+                                                               float4 posA = newPosA;
+                                                               posA.w = 0.f;
+                                                               float4 posB = newPosB;
+                                                               posB.w = 0.f;
+                                                               float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+                                                               float4 ornA = newOrnA;
+                                                               float4 c0 = transform(&c0local, &posA, &ornA);
+                                                               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+                                                               float4 ornB =newOrnB;
+                                                               float4 c1 = transform(&c1local,&posB,&ornB);
+                                                               const float4 DeltaC2 = c0 - c1;
+
+                                                               {//
+                                                                       int compoundPairIdx = atomic_inc(numCompoundPairsOut);
+                                                                       if (compoundPairIdx<maxNumCompoundPairsCapacity)
+                                                                       {
+                                                                               gpuCompoundPairsOut[compoundPairIdx]  = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);
+                                                                       }
+                                                               }//
+                                                       }//fi(1)
+                                               } //for (int b=0
+                                       }//if (collidables[collidableIndexB].
+                                       else//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                                       {
+                                               if (1)
+                                               {
+                                                       int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+                                                       float dmin = FLT_MAX;
+                                                       float4 posA = newPosA;
+                                                       posA.w = 0.f;
+                                                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+                                                       posB.w = 0.f;
+                                                       float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+                                                       float4 ornA = newOrnA;
+                                                       float4 c0 = transform(&c0local, &posA, &ornA);
+                                                       float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+                                                       float4 ornB = rigidBodies[bodyIndexB].m_quat;
+                                                       float4 c1 = transform(&c1local,&posB,&ornB);
+                                                       const float4 DeltaC2 = c0 - c1;
+
+                                                       {
+                                                               int compoundPairIdx = atomic_inc(numCompoundPairsOut);
+                                                               if (compoundPairIdx<maxNumCompoundPairsCapacity)
+                                                               {
+                                                                       gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,-1);
+                                                               }//if (compoundPairIdx<maxNumCompoundPairsCapacity)
+                                                       }//
+                                               }//fi (1)
+                                       }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                               }//for (int b=0;b<numChildrenB;b++)     
+                               return;
+                       }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                       if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH) 
+                               && (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+                       {
+                               int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
+                               for (int b=0;b<numChildrenB;b++)
+                               {
+                                       int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
+                                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                                       float4 ornB = rigidBodies[bodyIndexB].m_quat;
+                                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+                                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                                       float4 newPosB = qtRotate(ornB,childPosB)+posB;
+                                       float4 newOrnB = qtMul(ornB,childOrnB);
+
+                                       int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+
+
+                                       //////////////////////////////////////
+
+                                       if (1)
+                                       {
+                                               int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+                                               float dmin = FLT_MAX;
+                                               float4 posA = rigidBodies[bodyIndexA].m_pos;
+                                               posA.w = 0.f;
+                                               float4 posB = newPosB;
+                                               posB.w = 0.f;
+                                               float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+                                               float4 ornA = rigidBodies[bodyIndexA].m_quat;
+                                               float4 c0 = transform(&c0local, &posA, &ornA);
+                                               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+                                               float4 ornB =newOrnB;
+                                               float4 c1 = transform(&c1local,&posB,&ornB);
+                                               const float4 DeltaC2 = c0 - c1;
+                                               {//
+                                                       int compoundPairIdx = atomic_inc(numCompoundPairsOut);
+                                                       if (compoundPairIdx<maxNumCompoundPairsCapacity)
+                                                       {
+                                                               gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,-1,childShapeIndexB);
+                                                       }//fi (compoundPairIdx<maxNumCompoundPairsCapacity)
+                                               }//
+                                       }//fi (1)       
+                               }//for (int b=0;b<numChildrenB;b++)
+                               return;
+                       }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+                       return;
+               }//fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
+       }//i<numPairs
+}
+
+// work-in-progress
+__kernel void   findSeparatingAxisKernel( __global const int4* pairs, 
+                                                                                                                                                                       __global const BodyData* rigidBodies, 
+                                                                                                                                                                       __global const btCollidableGpu* collidables,
+                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global const float4* uniqueEdges,
+                                                                                                                                                                       __global const btGpuFace* faces,
+                                                                                                                                                                       __global const int* indices,
+                                                                                                                                                                       __global btAabbCL* aabbs,
+                                                                                                                                                                       __global volatile float4* separatingNormals,
+                                                                                                                                                                       __global volatile int* hasSeparatingAxis,
+                                                                                                                                                                       int numPairs
+                                                                                                                                                                       )
+{
+
+       int i = get_global_id(0);
+       
+       if (i<numPairs)
+       {
+
+       
+               int bodyIndexA = pairs[i].x;
+               int bodyIndexB = pairs[i].y;
+
+               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+       
+               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+               
+               
+               //once the broadphase avoids static-static pairs, we can remove this test
+               if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+               {
+                       hasSeparatingAxis[i] = 0;
+                       return;
+               }
+               
+
+               if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
+               {
+                       hasSeparatingAxis[i] = 0;
+                       return;
+               }
+                       
+               if ((collidables[collidableIndexA].m_shapeType==SHAPE_CONCAVE_TRIMESH))
+               {
+                       hasSeparatingAxis[i] = 0;
+                       return;
+               }
+
+               int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+
+               float dmin = FLT_MAX;
+
+               float4 posA = rigidBodies[bodyIndexA].m_pos;
+               posA.w = 0.f;
+               float4 posB = rigidBodies[bodyIndexB].m_pos;
+               posB.w = 0.f;
+               float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+               float4 ornA = rigidBodies[bodyIndexA].m_quat;
+               float4 c0 = transform(&c0local, &posA, &ornA);
+               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+               float4 ornB =rigidBodies[bodyIndexB].m_quat;
+               float4 c1 = transform(&c1local,&posB,&ornB);
+               const float4 DeltaC2 = c0 - c1;
+               float4 sepNormal;
+               
+               bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+                                                                                                                                                                                               posB,ornB,
+                                                                                                                                                                                               DeltaC2,
+                                                                                                                                                                                               vertices,uniqueEdges,faces,
+                                                                                                                                                                                               indices,&sepNormal,&dmin);
+               hasSeparatingAxis[i] = 4;
+               if (!sepA)
+               {
+                       hasSeparatingAxis[i] = 0;
+               } else
+               {
+                       bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,
+                                                                                                                                                                                                       posA,ornA,
+                                                                                                                                                                                                       DeltaC2,
+                                                                                                                                                                                                       vertices,uniqueEdges,faces,
+                                                                                                                                                                                                       indices,&sepNormal,&dmin);
+
+                       if (!sepB)
+                       {
+                               hasSeparatingAxis[i] = 0;
+                       } else
+                       {
+                               bool sepEE = findSeparatingAxisEdgeEdge(        &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+                                                                                                                                                                                                       posB,ornB,
+                                                                                                                                                                                                       DeltaC2,
+                                                                                                                                                                                                       vertices,uniqueEdges,faces,
+                                                                                                                                                                                                       indices,&sepNormal,&dmin);
+                               if (!sepEE)
+                               {
+                                       hasSeparatingAxis[i] = 0;
+                               } else
+                               {
+                                       hasSeparatingAxis[i] = 1;
+                                       separatingNormals[i] = sepNormal;
+                               }
+                       }
+               }
+               
+       }
+
+}
+
+
+__kernel void   findSeparatingAxisVertexFaceKernel( __global const int4* pairs, 
+                                                                                                                                                                       __global const BodyData* rigidBodies, 
+                                                                                                                                                                       __global const btCollidableGpu* collidables,
+                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global const float4* uniqueEdges,
+                                                                                                                                                                       __global const btGpuFace* faces,
+                                                                                                                                                                       __global const int* indices,
+                                                                                                                                                                       __global btAabbCL* aabbs,
+                                                                                                                                                                       __global volatile float4* separatingNormals,
+                                                                                                                                                                       __global volatile int* hasSeparatingAxis,
+                                                                                                                                                                       __global  float* dmins,
+                                                                                                                                                                       int numPairs
+                                                                                                                                                                       )
+{
+
+       int i = get_global_id(0);
+       
+       if (i<numPairs)
+       {
+
+       
+               int bodyIndexA = pairs[i].x;
+               int bodyIndexB = pairs[i].y;
+
+               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+       
+               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+       
+               hasSeparatingAxis[i] = 0;       
+               
+               //once the broadphase avoids static-static pairs, we can remove this test
+               if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
+               {
+                       return;
+               }
+               
+
+               if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
+               {
+                       return;
+               }
+                       
+
+               int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+
+               float dmin = FLT_MAX;
+
+               dmins[i] = dmin;
+               
+               float4 posA = rigidBodies[bodyIndexA].m_pos;
+               posA.w = 0.f;
+               float4 posB = rigidBodies[bodyIndexB].m_pos;
+               posB.w = 0.f;
+               float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+               float4 ornA = rigidBodies[bodyIndexA].m_quat;
+               float4 c0 = transform(&c0local, &posA, &ornA);
+               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+               float4 ornB =rigidBodies[bodyIndexB].m_quat;
+               float4 c1 = transform(&c1local,&posB,&ornB);
+               const float4 DeltaC2 = c0 - c1;
+               float4 sepNormal;
+               
+               bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+                                                                                                                                                                                               posB,ornB,
+                                                                                                                                                                                               DeltaC2,
+                                                                                                                                                                                               vertices,uniqueEdges,faces,
+                                                                                                                                                                                               indices,&sepNormal,&dmin);
+               hasSeparatingAxis[i] = 4;
+               if (!sepA)
+               {
+                       hasSeparatingAxis[i] = 0;
+               } else
+               {
+                       bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,
+                                                                                                                                                                                                       posA,ornA,
+                                                                                                                                                                                                       DeltaC2,
+                                                                                                                                                                                                       vertices,uniqueEdges,faces,
+                                                                                                                                                                                                       indices,&sepNormal,&dmin);
+
+                       if (sepB)
+                       {
+                               dmins[i] = dmin;
+                               hasSeparatingAxis[i] = 1;
+                               separatingNormals[i] = sepNormal;
+                       }
+               }
+               
+       }
+
+}
+
+
+__kernel void   findSeparatingAxisEdgeEdgeKernel( __global const int4* pairs, 
+                                                                                                                                                                       __global const BodyData* rigidBodies, 
+                                                                                                                                                                       __global const btCollidableGpu* collidables,
+                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global const float4* uniqueEdges,
+                                                                                                                                                                       __global const btGpuFace* faces,
+                                                                                                                                                                       __global const int* indices,
+                                                                                                                                                                       __global btAabbCL* aabbs,
+                                                                                                                                                                       __global  float4* separatingNormals,
+                                                                                                                                                                       __global  int* hasSeparatingAxis,
+                                                                                                                                                                       __global  float* dmins,
+                                                                                                                                                                       __global const float4* unitSphereDirections,
+                                                                                                                                                                       int numUnitSphereDirections,
+                                                                                                                                                                       int numPairs
+                                                                                                                                                                       )
+{
+
+       int i = get_global_id(0);
+       
+       if (i<numPairs)
+       {
+
+               if (hasSeparatingAxis[i])
+               {
+       
+                       int bodyIndexA = pairs[i].x;
+                       int bodyIndexB = pairs[i].y;
+       
+                       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+                       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+               
+                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+                       
+                       
+                       int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+       
+                       float dmin = dmins[i];
+       
+                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+                       posA.w = 0.f;
+                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+                       posB.w = 0.f;
+                       float4 c0local = convexShapes[shapeIndexA].m_localCenter;
+                       float4 ornA = rigidBodies[bodyIndexA].m_quat;
+                       float4 c0 = transform(&c0local, &posA, &ornA);
+                       float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+                       float4 ornB =rigidBodies[bodyIndexB].m_quat;
+                       float4 c1 = transform(&c1local,&posB,&ornB);
+                       const float4 DeltaC2 = c0 - c1;
+                       float4 sepNormal = separatingNormals[i];
+                       
+                       
+                       
+                       bool sepEE = false;
+                       int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;
+                       if (numEdgeEdgeDirections<=numUnitSphereDirections)
+                       {
+                               sepEE = findSeparatingAxisEdgeEdge(     &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+                                                                                                                                                                                                       posB,ornB,
+                                                                                                                                                                                                       DeltaC2,
+                                                                                                                                                                                                       vertices,uniqueEdges,faces,
+                                                                                                                                                                                                       indices,&sepNormal,&dmin);
+                                                                                                                                                                                                       
+                                       if (!sepEE)
+                                       {
+                                               hasSeparatingAxis[i] = 0;
+                                       } else
+                                       {
+                                               hasSeparatingAxis[i] = 1;
+                                               separatingNormals[i] = sepNormal;
+                                       }
+                       }
+                       /*
+                       ///else case is a separate kernel, to make Mac OSX OpenCL compiler happy
+                       else
+                       {
+                               sepEE = findSeparatingAxisUnitSphere(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
+                                                                                                                                                                                                       posB,ornB,
+                                                                                                                                                                                                       DeltaC2,
+                                                                                                                                                                                                       vertices,unitSphereDirections,numUnitSphereDirections,
+                                                                                                                                                                                                       &sepNormal,&dmin);
+                                       if (!sepEE)
+                                       {
+                                               hasSeparatingAxis[i] = 0;
+                                       } else
+                                       {
+                                               hasSeparatingAxis[i] = 1;
+                                               separatingNormals[i] = sepNormal;
+                                       }
+                       }
+                       */
+               }               //if (hasSeparatingAxis[i])
+       }//(i<numPairs)
+}
+
+
+
+
+
+inline int     findClippingFaces(const float4 separatingNormal,
+                      const ConvexPolyhedronCL* hullA, 
+                                         __global const ConvexPolyhedronCL* hullB,
+                      const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
+                       __global float4* worldVertsA1,
+                      __global float4* worldNormalsA1,
+                      __global float4* worldVertsB1,
+                      int capacityWorldVerts,
+                      const float minDist, float maxDist,
+                                         const float4* verticesA,
+                      const btGpuFace* facesA,
+                      const int* indicesA,
+                                         __global const float4* verticesB,
+                      __global const btGpuFace* facesB,
+                      __global const int* indicesB,
+                      __global int4* clippingFaces, int pairIndex)
+{
+       int numContactsOut = 0;
+       int numWorldVertsB1= 0;
+    
+    
+       int closestFaceB=0;
+       float dmax = -FLT_MAX;
+    
+       {
+               for(int face=0;face<hullB->m_numFaces;face++)
+               {
+                       const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,
+                                              facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
+                       const float4 WorldNormal = qtRotate(ornB, Normal);
+                       float d = dot3F4(WorldNormal,separatingNormal);
+                       if (d > dmax)
+                       {
+                               dmax = d;
+                               closestFaceB = face;
+                       }
+               }
+       }
+    
+       {
+               const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];
+               int numVertices = polyB.m_numIndices;
+        if (numVertices>capacityWorldVerts)
+            numVertices = capacityWorldVerts;
+        
+               for(int e0=0;e0<numVertices;e0++)
+               {
+            if (e0<capacityWorldVerts)
+            {
+                const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
+                worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);
+            }
+               }
+       }
+    
+    int closestFaceA=0;
+       {
+               float dmin = FLT_MAX;
+               for(int face=0;face<hullA->m_numFaces;face++)
+               {
+                       const float4 Normal = make_float4(
+                                              facesA[hullA->m_faceOffset+face].m_plane.x,
+                                              facesA[hullA->m_faceOffset+face].m_plane.y,
+                                              facesA[hullA->m_faceOffset+face].m_plane.z,
+                                              0.f);
+                       const float4 faceANormalWS = qtRotate(ornA,Normal);
+            
+                       float d = dot3F4(faceANormalWS,separatingNormal);
+                       if (d < dmin)
+                       {
+                               dmin = d;
+                               closestFaceA = face;
+                worldNormalsA1[pairIndex] = faceANormalWS;
+                       }
+               }
+       }
+    
+    int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;
+    if (numVerticesA>capacityWorldVerts)
+       numVerticesA = capacityWorldVerts;
+    
+       for(int e0=0;e0<numVerticesA;e0++)
+       {
+        if (e0<capacityWorldVerts)
+        {
+            const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
+            worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);
+        }
+    }
+    
+    clippingFaces[pairIndex].x = closestFaceA;
+    clippingFaces[pairIndex].y = closestFaceB;
+    clippingFaces[pairIndex].z = numVerticesA;
+    clippingFaces[pairIndex].w = numWorldVertsB1;
+    
+    
+       return numContactsOut;
+}
+
+
+
+
+// work-in-progress
+__kernel void   findConcaveSeparatingAxisKernel( __global int4* concavePairs,
+                                                                                                                                                                       __global const BodyData* rigidBodies,
+                                                                                                                                                                       __global const btCollidableGpu* collidables,
+                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global const float4* uniqueEdges,
+                                                                                                                                                                       __global const btGpuFace* faces,
+                                                                                                                                                                       __global const int* indices,
+                                                                                                                                                                       __global const btGpuChildShape* gpuChildShapes,
+                                                                                                                                                                       __global btAabbCL* aabbs,
+                                                                                                                                                                       __global float4* concaveSeparatingNormalsOut,
+                                                                                                                                                                       __global int* concaveHasSeparatingNormals,
+                                                                                                                                                                       __global int4* clippingFacesOut,
+                                                                                                                                                                       __global float4* worldVertsA1GPU,
+                                                                                                                                                                       __global float4*  worldNormalsAGPU,
+                                                                                                                                                                       __global float4* worldVertsB1GPU,
+                                                                                                                                                                       int vertexFaceCapacity,
+                                                                                                                                                                       int numConcavePairs
+                                                                                                                                                                       )
+{
+
+       int i = get_global_id(0);
+       if (i>=numConcavePairs)
+               return;
+
+       concaveHasSeparatingNormals[i] = 0;
+
+       int pairIdx = i;
+
+       int bodyIndexA = concavePairs[i].x;
+       int bodyIndexB = concavePairs[i].y;
+
+       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+
+       if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&
+               collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)
+       {
+               concavePairs[pairIdx].w = -1;
+               return;
+       }
+
+
+
+       int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+       int numActualConcaveConvexTests = 0;
+       
+       int f = concavePairs[i].z;
+       
+       bool overlap = false;
+       
+       ConvexPolyhedronCL convexPolyhedronA;
+
+       //add 3 vertices of the triangle
+       convexPolyhedronA.m_numVertices = 3;
+       convexPolyhedronA.m_vertexOffset = 0;
+       float4  localCenter = make_float4(0.f,0.f,0.f,0.f);
+
+       btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+       float4 triMinAabb, triMaxAabb;
+       btAabbCL triAabb;
+       triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);
+       triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);
+       
+       float4 verticesA[3];
+       for (int i=0;i<3;i++)
+       {
+               int index = indices[face.m_indexOffset+i];
+               float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+               verticesA[i] = vert;
+               localCenter += vert;
+                       
+               triAabb.m_min = min(triAabb.m_min,vert);                
+               triAabb.m_max = max(triAabb.m_max,vert);                
+
+       }
+
+       overlap = true;
+       overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;
+       overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;
+       overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;
+               
+       if (overlap)
+       {
+               float dmin = FLT_MAX;
+               int hasSeparatingAxis=5;
+               float4 sepAxis=make_float4(1,2,3,4);
+
+               int localCC=0;
+               numActualConcaveConvexTests++;
+
+               //a triangle has 3 unique edges
+               convexPolyhedronA.m_numUniqueEdges = 3;
+               convexPolyhedronA.m_uniqueEdgesOffset = 0;
+               float4 uniqueEdgesA[3];
+               
+               uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
+               uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
+               uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
+
+
+               convexPolyhedronA.m_faceOffset = 0;
+                                  
+               float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+                             
+               btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];
+               int indicesA[3+3+2+2+2];
+               int curUsedIndices=0;
+               int fidx=0;
+
+               //front size of triangle
+               {
+                       facesA[fidx].m_indexOffset=curUsedIndices;
+                       indicesA[0] = 0;
+                       indicesA[1] = 1;
+                       indicesA[2] = 2;
+                       curUsedIndices+=3;
+                       float c = face.m_plane.w;
+                       facesA[fidx].m_plane.x = normal.x;
+                       facesA[fidx].m_plane.y = normal.y;
+                       facesA[fidx].m_plane.z = normal.z;
+                       facesA[fidx].m_plane.w = c;
+                       facesA[fidx].m_numIndices=3;
+               }
+               fidx++;
+               //back size of triangle
+               {
+                       facesA[fidx].m_indexOffset=curUsedIndices;
+                       indicesA[3]=2;
+                       indicesA[4]=1;
+                       indicesA[5]=0;
+                       curUsedIndices+=3;
+                       float c = dot(normal,verticesA[0]);
+                       float c1 = -face.m_plane.w;
+                       facesA[fidx].m_plane.x = -normal.x;
+                       facesA[fidx].m_plane.y = -normal.y;
+                       facesA[fidx].m_plane.z = -normal.z;
+                       facesA[fidx].m_plane.w = c;
+                       facesA[fidx].m_numIndices=3;
+               }
+               fidx++;
+
+               bool addEdgePlanes = true;
+               if (addEdgePlanes)
+               {
+                       int numVertices=3;
+                       int prevVertex = numVertices-1;
+                       for (int i=0;i<numVertices;i++)
+                       {
+                               float4 v0 = verticesA[i];
+                               float4 v1 = verticesA[prevVertex];
+                                            
+                               float4 edgeNormal = normalize(cross(normal,v1-v0));
+                               float c = -dot(edgeNormal,v0);
+
+                               facesA[fidx].m_numIndices = 2;
+                               facesA[fidx].m_indexOffset=curUsedIndices;
+                               indicesA[curUsedIndices++]=i;
+                               indicesA[curUsedIndices++]=prevVertex;
+                                            
+                               facesA[fidx].m_plane.x = edgeNormal.x;
+                               facesA[fidx].m_plane.y = edgeNormal.y;
+                               facesA[fidx].m_plane.z = edgeNormal.z;
+                               facesA[fidx].m_plane.w = c;
+                               fidx++;
+                               prevVertex = i;
+                       }
+               }
+               convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
+               convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
+
+
+               float4 posA = rigidBodies[bodyIndexA].m_pos;
+               posA.w = 0.f;
+               float4 posB = rigidBodies[bodyIndexB].m_pos;
+               posB.w = 0.f;
+
+               float4 ornA = rigidBodies[bodyIndexA].m_quat;
+               float4 ornB =rigidBodies[bodyIndexB].m_quat;
+
+               
+
+
+               ///////////////////
+               ///compound shape support
+
+               if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+               {
+                       int compoundChild = concavePairs[pairIdx].w;
+                       int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
+                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                       float4 newPosB = transform(&childPosB,&posB,&ornB);
+                       float4 newOrnB = qtMul(ornB,childOrnB);
+                       posB = newPosB;
+                       ornB = newOrnB;
+                       shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+               }
+               //////////////////
+
+               float4 c0local = convexPolyhedronA.m_localCenter;
+               float4 c0 = transform(&c0local, &posA, &ornA);
+               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+               float4 c1 = transform(&c1local,&posB,&ornB);
+               const float4 DeltaC2 = c0 - c1;
+
+
+               bool sepA = findSeparatingAxisLocalA(   &convexPolyhedronA, &convexShapes[shapeIndexB],
+                                                                                               posA,ornA,
+                                                                                               posB,ornB,
+                                                                                               DeltaC2,
+                                                                                               verticesA,uniqueEdgesA,facesA,indicesA,
+                                                                                               vertices,uniqueEdges,faces,indices,
+                                                                                               &sepAxis,&dmin);
+               hasSeparatingAxis = 4;
+               if (!sepA)
+               {
+                       hasSeparatingAxis = 0;
+               } else
+               {
+                       bool sepB = findSeparatingAxisLocalB(   &convexShapes[shapeIndexB],&convexPolyhedronA,
+                                                                                               posB,ornB,
+                                                                                               posA,ornA,
+                                                                                               DeltaC2,
+                                                                                               vertices,uniqueEdges,faces,indices,
+                                                                                               verticesA,uniqueEdgesA,facesA,indicesA,
+                                                                                               &sepAxis,&dmin);
+
+                       if (!sepB)
+                       {
+                               hasSeparatingAxis = 0;
+                       } else
+                       {
+                               bool sepEE = findSeparatingAxisEdgeEdgeLocalA(  &convexPolyhedronA, &convexShapes[shapeIndexB],
+                                                                                                                       posA,ornA,
+                                                                                                                       posB,ornB,
+                                                                                                                       DeltaC2,
+                                                                                                                       verticesA,uniqueEdgesA,facesA,indicesA,
+                                                                                                                       vertices,uniqueEdges,faces,indices,
+                                                                                                                       &sepAxis,&dmin);
+       
+                               if (!sepEE)
+                               {
+                                       hasSeparatingAxis = 0;
+                               } else
+                               {
+                                       hasSeparatingAxis = 1;
+                               }
+                       }
+               }       
+               
+               if (hasSeparatingAxis)
+               {
+                       sepAxis.w = dmin;
+                       concaveSeparatingNormalsOut[pairIdx]=sepAxis;
+                       concaveHasSeparatingNormals[i]=1;
+
+
+                       float minDist = -1e30f;
+                       float maxDist = 0.02f;
+
+               
+
+                       findClippingFaces(sepAxis,
+                     &convexPolyhedronA,
+                                        &convexShapes[shapeIndexB],
+                                        posA,ornA,
+                                        posB,ornB,
+                      worldVertsA1GPU,
+                      worldNormalsAGPU,
+                      worldVertsB1GPU,
+                                         vertexFaceCapacity,
+                      minDist, maxDist,
+                      verticesA,
+                      facesA,
+                      indicesA,
+                                         vertices,
+                      faces,
+                      indices,
+                      clippingFacesOut, pairIdx);
+
+
+               } else
+               {       
+                       //mark this pair as in-active
+                       concavePairs[pairIdx].w = -1;
+               }
+       }
+       else
+       {       
+               //mark this pair as in-active
+               concavePairs[pairIdx].w = -1;
+       }
+       
+       concavePairs[pairIdx].z = -1;//now z is used for existing/persistent contacts
+}
+
+
+
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl
new file mode 100644 (file)
index 0000000..f433971
--- /dev/null
@@ -0,0 +1,1888 @@
+
+#define TRIANGLE_NUM_CONVEX_FACES 5
+
+
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile __global int*
+#endif
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+#define max2 max
+#define min2 min
+
+typedef unsigned int u32;
+
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+
+
+#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
+
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+__inline
+float fastDiv(float numerator, float denominator)
+{
+       return native_divide(numerator, denominator);   
+//     return numerator/denominator;   
+}
+
+__inline
+float4 fastDiv4(float4 numerator, float4 denominator)
+{
+       return native_divide(numerator, denominator);   
+}
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+       return cross(a,b);
+}
+
+//#define dot3F4 dot
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = make_float4(a.xyz,0.f);
+       float4 b1 = make_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+       return fast_normalize(v);
+}
+
+
+///////////////////////////////////////
+//     Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+       Quaternion ans;
+       ans = cross3( a, b );
+       ans += a.w*b+b.w*a;
+//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+       ans.w = a.w*b.w - dot3F4(a, b);
+       return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+       return fastNormalize4(in);
+//     in /= length( in );
+//     return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+       Quaternion qInv = qtInvert( q );
+       float4 vcpy = vec;
+       vcpy.w = 0.f;
+       float4 out = qtMul(qtMul(q,vcpy),qInv);
+       return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+       return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+       return qtRotate( qtInvert( q ), vec );
+}
+
+__inline
+float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
+{
+       return qtRotate( *orientation, *p ) + (*translation);
+}
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+       float4 n = make_float4(a.x, a.y, a.z, 0.f);
+       return fastNormalize4( n );
+}
+
+
+__inline float4 lerp3(const float4 a,const float4 b, float  t)
+{
+       return make_float4(     a.x + (b.x - a.x) * t,
+                                               a.y + (b.y - a.y) * t,
+                                               a.z + (b.z - a.z) * t,
+                                               0.f);
+}
+
+
+
+// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
+int clipFaceGlobal(__global const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, __global float4* ppVtxOut)
+{
+       
+       int ve;
+       float ds, de;
+       int numVertsOut = 0;
+    //double-check next test
+       if (numVertsIn < 2)
+               return 0;
+    
+       float4 firstVertex=pVtxIn[numVertsIn-1];
+       float4 endVertex = pVtxIn[0];
+       
+       ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;
+    
+       for (ve = 0; ve < numVertsIn; ve++)
+       {
+               endVertex=pVtxIn[ve];
+               de = dot3F4(planeNormalWS,endVertex)+planeEqWS;
+               if (ds<0)
+               {
+                       if (de<0)
+                       {
+                               // Start < 0, end < 0, so output endVertex
+                               ppVtxOut[numVertsOut++] = endVertex;
+                       }
+                       else
+                       {
+                               // Start < 0, end >= 0, so output intersection
+                               ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+                       }
+               }
+               else
+               {
+                       if (de<0)
+                       {
+                               // Start >= 0, end < 0 so output intersection and end
+                               ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+                               ppVtxOut[numVertsOut++] = endVertex;
+                       }
+               }
+               firstVertex = endVertex;
+               ds = de;
+       }
+       return numVertsOut;
+}
+
+
+
+// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
+int clipFace(const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, float4* ppVtxOut)
+{
+       
+       int ve;
+       float ds, de;
+       int numVertsOut = 0;
+//double-check next test
+       if (numVertsIn < 2)
+               return 0;
+
+       float4 firstVertex=pVtxIn[numVertsIn-1];
+       float4 endVertex = pVtxIn[0];
+       
+       ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;
+
+       for (ve = 0; ve < numVertsIn; ve++)
+       {
+               endVertex=pVtxIn[ve];
+
+               de = dot3F4(planeNormalWS,endVertex)+planeEqWS;
+
+               if (ds<0)
+               {
+                       if (de<0)
+                       {
+                               // Start < 0, end < 0, so output endVertex
+                               ppVtxOut[numVertsOut++] = endVertex;
+                       }
+                       else
+                       {
+                               // Start < 0, end >= 0, so output intersection
+                               ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+                       }
+               }
+               else
+               {
+                       if (de<0)
+                       {
+                               // Start >= 0, end < 0 so output intersection and end
+                               ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
+                               ppVtxOut[numVertsOut++] = endVertex;
+                       }
+               }
+               firstVertex = endVertex;
+               ds = de;
+       }
+       return numVertsOut;
+}
+
+
+int clipFaceAgainstHull(const float4 separatingNormal, __global const b3ConvexPolyhedronData_t* hullA,  
+       const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,
+       float4* worldVertsB2, int capacityWorldVertsB2,
+       const float minDist, float maxDist,
+       __global const float4* vertices,
+       __global const b3GpuFace_t* faces,
+       __global const int* indices,
+       float4* contactsOut,
+       int contactCapacity)
+{
+       int numContactsOut = 0;
+
+       float4* pVtxIn = worldVertsB1;
+       float4* pVtxOut = worldVertsB2;
+       
+       int numVertsIn = numWorldVertsB1;
+       int numVertsOut = 0;
+
+       int closestFaceA=-1;
+       {
+               float dmin = FLT_MAX;
+               for(int face=0;face<hullA->m_numFaces;face++)
+               {
+                       const float4 Normal = make_float4(
+                               faces[hullA->m_faceOffset+face].m_plane.x, 
+                               faces[hullA->m_faceOffset+face].m_plane.y, 
+                               faces[hullA->m_faceOffset+face].m_plane.z,0.f);
+                       const float4 faceANormalWS = qtRotate(ornA,Normal);
+               
+                       float d = dot3F4(faceANormalWS,separatingNormal);
+                       if (d < dmin)
+                       {
+                               dmin = d;
+                               closestFaceA = face;
+                       }
+               }
+       }
+       if (closestFaceA<0)
+               return numContactsOut;
+
+       b3GpuFace_t polyA = faces[hullA->m_faceOffset+closestFaceA];
+
+       // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+       int numVerticesA = polyA.m_numIndices;
+       for(int e0=0;e0<numVerticesA;e0++)
+       {
+               const float4 a = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+e0]];
+               const float4 b = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+((e0+1)%numVerticesA)]];
+               const float4 edge0 = a - b;
+               const float4 WorldEdge0 = qtRotate(ornA,edge0);
+               float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+               float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);
+
+               float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
+               float4 worldA1 = transform(&a,&posA,&ornA);
+               float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
+               
+               float4 planeNormalWS = planeNormalWS1;
+               float planeEqWS=planeEqWS1;
+               
+               //clip face
+               //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
+               numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);
+
+               //btSwap(pVtxIn,pVtxOut);
+               float4* tmp = pVtxOut;
+               pVtxOut = pVtxIn;
+               pVtxIn = tmp;
+               numVertsIn = numVertsOut;
+               numVertsOut = 0;
+       }
+
+       
+       // only keep points that are behind the witness face
+       {
+               float4 localPlaneNormal  = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+               float localPlaneEq = polyA.m_plane.w;
+               float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);
+               float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);
+               for (int i=0;i<numVertsIn;i++)
+               {
+                       float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
+                       if (depth <=minDist)
+                       {
+                               depth = minDist;
+                       }
+
+                       if (depth <=maxDist)
+                       {
+                               float4 pointInWorld = pVtxIn[i];
+                               //resultOut.addContactPoint(separatingNormal,point,depth);
+                               contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+                       }
+               }
+       }
+
+       return numContactsOut;
+}
+
+
+
+int clipFaceAgainstHullLocalA(const float4 separatingNormal, const b3ConvexPolyhedronData_t* hullA,  
+       const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,
+       float4* worldVertsB2, int capacityWorldVertsB2,
+       const float minDist, float maxDist,
+       const float4* verticesA,
+       const b3GpuFace_t* facesA,
+       const int* indicesA,
+       __global const float4* verticesB,
+       __global const b3GpuFace_t* facesB,
+       __global const int* indicesB,
+       float4* contactsOut,
+       int contactCapacity)
+{
+       int numContactsOut = 0;
+
+       float4* pVtxIn = worldVertsB1;
+       float4* pVtxOut = worldVertsB2;
+       
+       int numVertsIn = numWorldVertsB1;
+       int numVertsOut = 0;
+
+       int closestFaceA=-1;
+       {
+               float dmin = FLT_MAX;
+               for(int face=0;face<hullA->m_numFaces;face++)
+               {
+                       const float4 Normal = make_float4(
+                               facesA[hullA->m_faceOffset+face].m_plane.x, 
+                               facesA[hullA->m_faceOffset+face].m_plane.y, 
+                               facesA[hullA->m_faceOffset+face].m_plane.z,0.f);
+                       const float4 faceANormalWS = qtRotate(ornA,Normal);
+               
+                       float d = dot3F4(faceANormalWS,separatingNormal);
+                       if (d < dmin)
+                       {
+                               dmin = d;
+                               closestFaceA = face;
+                       }
+               }
+       }
+       if (closestFaceA<0)
+               return numContactsOut;
+
+       b3GpuFace_t polyA = facesA[hullA->m_faceOffset+closestFaceA];
+
+       // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+       int numVerticesA = polyA.m_numIndices;
+       for(int e0=0;e0<numVerticesA;e0++)
+       {
+               const float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];
+               const float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];
+               const float4 edge0 = a - b;
+               const float4 WorldEdge0 = qtRotate(ornA,edge0);
+               float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+               float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);
+
+               float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
+               float4 worldA1 = transform(&a,&posA,&ornA);
+               float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
+               
+               float4 planeNormalWS = planeNormalWS1;
+               float planeEqWS=planeEqWS1;
+               
+               //clip face
+               //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
+               numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);
+
+               //btSwap(pVtxIn,pVtxOut);
+               float4* tmp = pVtxOut;
+               pVtxOut = pVtxIn;
+               pVtxIn = tmp;
+               numVertsIn = numVertsOut;
+               numVertsOut = 0;
+       }
+
+       
+       // only keep points that are behind the witness face
+       {
+               float4 localPlaneNormal  = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
+               float localPlaneEq = polyA.m_plane.w;
+               float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);
+               float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);
+               for (int i=0;i<numVertsIn;i++)
+               {
+                       float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
+                       if (depth <=minDist)
+                       {
+                               depth = minDist;
+                       }
+
+                       if (depth <=maxDist)
+                       {
+                               float4 pointInWorld = pVtxIn[i];
+                               //resultOut.addContactPoint(separatingNormal,point,depth);
+                               contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+                       }
+               }
+       }
+
+       return numContactsOut;
+}
+
+int    clipHullAgainstHull(const float4 separatingNormal,
+       __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, 
+       const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, 
+       float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
+       const float minDist, float maxDist,
+       __global const float4* vertices,
+       __global const b3GpuFace_t* faces,
+       __global const int* indices,
+       float4* localContactsOut,
+       int localContactCapacity)
+{
+       int numContactsOut = 0;
+       int numWorldVertsB1= 0;
+
+
+       int closestFaceB=-1;
+       float dmax = -FLT_MAX;
+
+       {
+               for(int face=0;face<hullB->m_numFaces;face++)
+               {
+                       const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x, 
+                               faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);
+                       const float4 WorldNormal = qtRotate(ornB, Normal);
+                       float d = dot3F4(WorldNormal,separatingNormal);
+                       if (d > dmax)
+                       {
+                               dmax = d;
+                               closestFaceB = face;
+                       }
+               }
+       }
+
+       {
+               const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];
+               const int numVertices = polyB.m_numIndices;
+               for(int e0=0;e0<numVertices;e0++)
+               {
+                       const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];
+                       worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);
+               }
+       }
+
+       if (closestFaceB>=0)
+       {
+               numContactsOut = clipFaceAgainstHull(separatingNormal, hullA, 
+                               posA,ornA,
+                               worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,vertices,
+                               faces,
+                               indices,localContactsOut,localContactCapacity);
+       }
+
+       return numContactsOut;
+}
+
+
+int    clipHullAgainstHullLocalA(const float4 separatingNormal,
+       const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, 
+       const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, 
+       float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
+       const float minDist, float maxDist,
+       const float4* verticesA,
+       const b3GpuFace_t* facesA,
+       const int* indicesA,
+       __global const float4* verticesB,
+       __global const b3GpuFace_t* facesB,
+       __global const int* indicesB,
+       float4* localContactsOut,
+       int localContactCapacity)
+{
+       int numContactsOut = 0;
+       int numWorldVertsB1= 0;
+
+
+       int closestFaceB=-1;
+       float dmax = -FLT_MAX;
+
+       {
+               for(int face=0;face<hullB->m_numFaces;face++)
+               {
+                       const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x, 
+                               facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
+                       const float4 WorldNormal = qtRotate(ornB, Normal);
+                       float d = dot3F4(WorldNormal,separatingNormal);
+                       if (d > dmax)
+                       {
+                               dmax = d;
+                               closestFaceB = face;
+                       }
+               }
+       }
+
+       {
+               const b3GpuFace_t polyB = facesB[hullB->m_faceOffset+closestFaceB];
+               const int numVertices = polyB.m_numIndices;
+               for(int e0=0;e0<numVertices;e0++)
+               {
+                       const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
+                       worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);
+               }
+       }
+
+       if (closestFaceB>=0)
+       {
+               numContactsOut = clipFaceAgainstHullLocalA(separatingNormal, hullA, 
+                               posA,ornA,
+                               worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,
+                               verticesA,facesA,indicesA,
+                               verticesB,facesB,indicesB,
+                               localContactsOut,localContactCapacity);
+       }
+
+       return numContactsOut;
+}
+
+#define PARALLEL_SUM(v, n) for(int j=1; j<n; j++) v[0] += v[j];
+#define PARALLEL_DO(execution, n) for(int ie=0; ie<n; ie++){execution;}
+#define REDUCE_MAX(v, n) {int i=0;\
+for(int offset=0; offset<n; offset++) v[i] = (v[i].y > v[i+offset].y)? v[i]: v[i+offset]; }
+#define REDUCE_MIN(v, n) {int i=0;\
+for(int offset=0; offset<n; offset++) v[i] = (v[i].y < v[i+offset].y)? v[i]: v[i+offset]; }
+
+int extractManifoldSequentialGlobal(__global const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)
+{
+       if( nPoints == 0 )
+        return 0;
+    
+    if (nPoints <=4)
+        return nPoints;
+    
+    
+    if (nPoints >64)
+        nPoints = 64;
+    
+       float4 center = make_float4(0.f);
+       {
+               
+               for (int i=0;i<nPoints;i++)
+                       center += p[i];
+               center /= (float)nPoints;
+       }
+    
+       
+    
+       //      sample 4 directions
+    
+    float4 aVector = p[0] - center;
+    float4 u = cross3( nearNormal, aVector );
+    float4 v = cross3( nearNormal, u );
+    u = normalize3( u );
+    v = normalize3( v );
+    
+    
+    //keep point with deepest penetration
+    float minW= FLT_MAX;
+    
+    int minIndex=-1;
+    
+    float4 maxDots;
+    maxDots.x = FLT_MIN;
+    maxDots.y = FLT_MIN;
+    maxDots.z = FLT_MIN;
+    maxDots.w = FLT_MIN;
+    
+    // idx, distance
+    for(int ie = 0; ie<nPoints; ie++ )
+    {
+        if (p[ie].w<minW)
+        {
+            minW = p[ie].w;
+            minIndex=ie;
+        }
+        float f;
+        float4 r = p[ie]-center;
+        f = dot3F4( u, r );
+        if (f<maxDots.x)
+        {
+            maxDots.x = f;
+            contactIdx[0].x = ie;
+        }
+        
+        f = dot3F4( -u, r );
+        if (f<maxDots.y)
+        {
+            maxDots.y = f;
+            contactIdx[0].y = ie;
+        }
+        
+        
+        f = dot3F4( v, r );
+        if (f<maxDots.z)
+        {
+            maxDots.z = f;
+            contactIdx[0].z = ie;
+        }
+        
+        f = dot3F4( -v, r );
+        if (f<maxDots.w)
+        {
+            maxDots.w = f;
+            contactIdx[0].w = ie;
+        }
+        
+    }
+    
+    if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
+    {
+        //replace the first contact with minimum (todo: replace contact with least penetration)
+        contactIdx[0].x = minIndex;
+    }
+    
+    return 4;
+    
+}
+
+
+int extractManifoldSequentialGlobalFake(__global const float4* p, int nPoints, float4 nearNormal, int* contactIdx)
+{
+    contactIdx[0] = 0;
+    contactIdx[1] = 1;
+    contactIdx[2] = 2;
+    contactIdx[3] = 3;
+    
+       if( nPoints == 0 ) return 0;
+    
+       nPoints = min2( nPoints, 4 );
+    return nPoints;
+    
+}
+
+
+
+int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int* contactIdx)
+{
+       if( nPoints == 0 ) return 0;
+
+       nPoints = min2( nPoints, 64 );
+
+       float4 center = make_float4(0.f);
+       {
+               float4 v[64];
+               for (int i=0;i<nPoints;i++)
+                       v[i] = p[i];
+               //memcpy( v, p, nPoints*sizeof(float4) );
+               PARALLEL_SUM( v, nPoints );
+               center = v[0]/(float)nPoints;
+       }
+
+       
+
+       {       //      sample 4 directions
+               if( nPoints < 4 )
+               {
+                       for(int i=0; i<nPoints; i++) 
+                               contactIdx[i] = i;
+                       return nPoints;
+               }
+
+               float4 aVector = p[0] - center;
+               float4 u = cross3( nearNormal, aVector );
+               float4 v = cross3( nearNormal, u );
+               u = normalize3( u );
+               v = normalize3( v );
+
+               int idx[4];
+
+               float2 max00 = make_float2(0,FLT_MAX);
+               {
+                       //      idx, distance
+                       {
+                               {
+                                       int4 a[64];
+                                       for(int ie = 0; ie<nPoints; ie++ )
+                                       {
+                                               
+                                               
+                                               float f;
+                                               float4 r = p[ie]-center;
+                                               f = dot3F4( u, r );
+                                               a[ie].x = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
+
+                                               f = dot3F4( -u, r );
+                                               a[ie].y = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
+
+                                               f = dot3F4( v, r );
+                                               a[ie].z = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
+
+                                               f = dot3F4( -v, r );
+                                               a[ie].w = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
+                                       }
+
+                                       for(int ie=0; ie<nPoints; ie++)
+                                       {
+                                               a[0].x = (a[0].x > a[ie].x )? a[0].x: a[ie].x;
+                                               a[0].y = (a[0].y > a[ie].y )? a[0].y: a[ie].y;
+                                               a[0].z = (a[0].z > a[ie].z )? a[0].z: a[ie].z;
+                                               a[0].w = (a[0].w > a[ie].w )? a[0].w: a[ie].w;
+                                       }
+
+                                       idx[0] = (int)a[0].x & 0xff;
+                                       idx[1] = (int)a[0].y & 0xff;
+                                       idx[2] = (int)a[0].z & 0xff;
+                                       idx[3] = (int)a[0].w & 0xff;
+                               }
+                       }
+
+                       {
+                               float2 h[64];
+                               PARALLEL_DO( h[ie] = make_float2((float)ie, p[ie].w), nPoints );
+                               REDUCE_MIN( h, nPoints );
+                               max00 = h[0];
+                       }
+               }
+
+               contactIdx[0] = idx[0];
+               contactIdx[1] = idx[1];
+               contactIdx[2] = idx[2];
+               contactIdx[3] = idx[3];
+
+
+               return 4;
+       }
+}
+
+
+
+__kernel void   extractManifoldAndAddContactKernel(__global const int4* pairs, 
+                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, 
+                                                                                                                                       __global const float4* closestPointsWorld,
+                                                                                                                                       __global const float4* separatingNormalsWorld,
+                                                                                                                                       __global const int* contactCounts,
+                                                                                                                                       __global const int* contactOffsets,
+                                                                                                                                       __global struct b3Contact4Data* restrict contactsOut,
+                                                                                                                                       counter32_t nContactsOut,
+                                                                                                                                       int contactCapacity,
+                                                                                                                                       int numPairs,
+                                                                                                                                       int pairIndex
+                                                                                                                                       )
+{
+       int idx = get_global_id(0);
+       
+       if (idx<numPairs)
+       {
+               float4 normal = separatingNormalsWorld[idx];
+               int nPoints = contactCounts[idx];
+               __global const float4* pointsIn = &closestPointsWorld[contactOffsets[idx]];
+               float4 localPoints[64];
+               for (int i=0;i<nPoints;i++)
+               {
+                       localPoints[i] = pointsIn[i];
+               }
+
+               int contactIdx[4];// = {-1,-1,-1,-1};
+               contactIdx[0] = -1;
+               contactIdx[1] = -1;
+               contactIdx[2] = -1;
+               contactIdx[3] = -1;
+
+               int nContacts = extractManifoldSequential(localPoints, nPoints, normal, contactIdx);
+
+               int dstIdx;
+               AppendInc( nContactsOut, dstIdx );
+               if (dstIdx<contactCapacity)
+               {
+                       __global struct b3Contact4Data* c = contactsOut + dstIdx;
+                       c->m_worldNormalOnB = -normal;
+                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                       c->m_batchIdx = idx;
+                       int bodyA = pairs[pairIndex].x;
+                       int bodyB = pairs[pairIndex].y;
+                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;
+                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;
+                       c->m_childIndexA = -1;
+                       c->m_childIndexB = -1;
+                       for (int i=0;i<nContacts;i++)
+                       {
+                               c->m_worldPosB[i] = localPoints[contactIdx[i]];
+                       }
+                       GET_NPOINTS(*c) = nContacts;
+               }
+       }
+}
+
+
+void   trInverse(float4 translationIn, Quaternion orientationIn,
+               float4* translationOut, Quaternion* orientationOut)
+{
+       *orientationOut = qtInvert(orientationIn);
+       *translationOut = qtRotate(*orientationOut, -translationIn);
+}
+
+void   trMul(float4 translationA, Quaternion orientationA,
+                                               float4 translationB, Quaternion orientationB,
+               float4* translationOut, Quaternion* orientationOut)
+{
+       *orientationOut = qtMul(orientationA,orientationB);
+       *translationOut = transform(&translationB,&translationA,&orientationA);
+}
+
+
+
+
+__kernel void   clipHullHullKernel( __global int4* pairs, 
+                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, 
+                                                                                                                                                                       __global const b3Collidable_t* collidables,
+                                                                                                                                                                       __global const b3ConvexPolyhedronData_t* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global const float4* uniqueEdges,
+                                                                                                                                                                       __global const b3GpuFace_t* faces,
+                                                                                                                                                                       __global const int* indices,
+                                                                                                                                                                       __global const float4* separatingNormals,
+                                                                                                                                                                       __global const int* hasSeparatingAxis,
+                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                                                                                                                       counter32_t nGlobalContactsOut,
+                                                                                                                                                                       int numPairs,
+                                                                                                                                                                       int contactCapacity)
+{
+
+       int i = get_global_id(0);
+       int pairIndex = i;
+       
+       float4 worldVertsB1[64];
+       float4 worldVertsB2[64];
+       int capacityWorldVerts = 64;    
+
+       float4 localContactsOut[64];
+       int localContactCapacity=64;
+       
+       float minDist = -1e30f;
+       float maxDist = 0.02f;
+
+       if (i<numPairs)
+       {
+
+               int bodyIndexA = pairs[i].x;
+               int bodyIndexB = pairs[i].y;
+                       
+               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+               if (hasSeparatingAxis[i])
+               {
+
+                       
+                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+                       
+
+
+               
+                       int numLocalContactsOut = clipHullAgainstHull(separatingNormals[i],
+                                                                                                               &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],
+                                                                                                               rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,
+                                                                                                         rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,
+                                                                                                         worldVertsB1,worldVertsB2,capacityWorldVerts,
+                                                                                                               minDist, maxDist,
+                                                                                                               vertices,faces,indices,
+                                                                                                               localContactsOut,localContactCapacity);
+                                                                                               
+               if (numLocalContactsOut>0)
+               {
+                               float4 normal = -separatingNormals[i];
+                               int nPoints = numLocalContactsOut;
+                               float4* pointsIn = localContactsOut;
+                               int contactIdx[4];// = {-1,-1,-1,-1};
+
+                               contactIdx[0] = -1;
+                               contactIdx[1] = -1;
+                               contactIdx[2] = -1;
+                               contactIdx[3] = -1;
+               
+                               int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);
+               
+                               
+                               int mprContactIndex = pairs[pairIndex].z;
+
+                               int dstIdx = mprContactIndex;
+                               if (dstIdx<0)
+                               {
+                                       AppendInc( nGlobalContactsOut, dstIdx );
+                               }
+
+                               if (dstIdx<contactCapacity)
+                               {
+                                       pairs[pairIndex].z = dstIdx;
+
+                                       __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
+                                       c->m_worldNormalOnB = -normal;
+                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                                       c->m_batchIdx = pairIndex;
+                                       int bodyA = pairs[pairIndex].x;
+                                       int bodyB = pairs[pairIndex].y;
+                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+                                       c->m_childIndexA = -1;
+                                       c->m_childIndexB = -1;
+
+                                       for (int i=0;i<nReducedContacts;i++)
+                                       {
+                                       //this condition means: overwrite contact point, unless at index i==0 we have a valid 'mpr' contact
+                                               if (i>0||(mprContactIndex<0))
+                                               {
+                                                       c->m_worldPosB[i] = pointsIn[contactIdx[i]];
+                                               }
+                                       }
+                                       GET_NPOINTS(*c) = nReducedContacts;
+                               }
+                               
+                       }//             if (numContactsOut>0)
+               }//             if (hasSeparatingAxis[i])
+       }//     if (i<numPairs)
+
+}
+
+
+__kernel void   clipCompoundsHullHullKernel( __global const int4* gpuCompoundPairs, 
+                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, 
+                                                                                                                                                                       __global const b3Collidable_t* collidables,
+                                                                                                                                                                       __global const b3ConvexPolyhedronData_t* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global const float4* uniqueEdges,
+                                                                                                                                                                       __global const b3GpuFace_t* faces,
+                                                                                                                                                                       __global const int* indices,
+                                                                                                                                                                       __global const b3GpuChildShape_t* gpuChildShapes,
+                                                                                                                                                                       __global const float4* gpuCompoundSepNormalsOut,
+                                                                                                                                                                       __global const int* gpuHasCompoundSepNormalsOut,
+                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                                                                                                                       counter32_t nGlobalContactsOut,
+                                                                                                                                                                       int numCompoundPairs, int maxContactCapacity)
+{
+
+       int i = get_global_id(0);
+       int pairIndex = i;
+       
+       float4 worldVertsB1[64];
+       float4 worldVertsB2[64];
+       int capacityWorldVerts = 64;    
+
+       float4 localContactsOut[64];
+       int localContactCapacity=64;
+       
+       float minDist = -1e30f;
+       float maxDist = 0.02f;
+
+       if (i<numCompoundPairs)
+       {
+
+               if (gpuHasCompoundSepNormalsOut[i])
+               {
+
+                       int bodyIndexA = gpuCompoundPairs[i].x;
+                       int bodyIndexB = gpuCompoundPairs[i].y;
+                       
+                       int childShapeIndexA = gpuCompoundPairs[i].z;
+                       int childShapeIndexB = gpuCompoundPairs[i].w;
+                       
+                       int collidableIndexA = -1;
+                       int collidableIndexB = -1;
+                       
+                       float4 ornA = rigidBodies[bodyIndexA].m_quat;
+                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+                       
+                       float4 ornB = rigidBodies[bodyIndexB].m_quat;
+                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+                                                               
+                       if (childShapeIndexA >= 0)
+                       {
+                               collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
+                               float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
+                               float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
+                               float4 newPosA = qtRotate(ornA,childPosA)+posA;
+                               float4 newOrnA = qtMul(ornA,childOrnA);
+                               posA = newPosA;
+                               ornA = newOrnA;
+                       } else
+                       {
+                               collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+                       }
+                       
+                       if (childShapeIndexB>=0)
+                       {
+                               collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                               float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                               float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                               float4 newPosB = transform(&childPosB,&posB,&ornB);
+                               float4 newOrnB = qtMul(ornB,childOrnB);
+                               posB = newPosB;
+                               ornB = newOrnB;
+                       } else
+                       {
+                               collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;     
+                       }
+                       
+                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+               
+                       int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],
+                                                                                                               &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],
+                                                                                                               posA,ornA,
+                                                                                                         posB,ornB,
+                                                                                                         worldVertsB1,worldVertsB2,capacityWorldVerts,
+                                                                                                               minDist, maxDist,
+                                                                                                               vertices,faces,indices,
+                                                                                                               localContactsOut,localContactCapacity);
+                                                                                               
+               if (numLocalContactsOut>0)
+               {
+                               float4 normal = -gpuCompoundSepNormalsOut[i];
+                               int nPoints = numLocalContactsOut;
+                               float4* pointsIn = localContactsOut;
+                               int contactIdx[4];// = {-1,-1,-1,-1};
+
+                               contactIdx[0] = -1;
+                               contactIdx[1] = -1;
+                               contactIdx[2] = -1;
+                               contactIdx[3] = -1;
+               
+                               int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);
+               
+                               int dstIdx;
+                               AppendInc( nGlobalContactsOut, dstIdx );
+                               if ((dstIdx+nReducedContacts) < maxContactCapacity)
+                               {
+                                       __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
+                                       c->m_worldNormalOnB = -normal;
+                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                                       c->m_batchIdx = pairIndex;
+                                       int bodyA = gpuCompoundPairs[pairIndex].x;
+                                       int bodyB = gpuCompoundPairs[pairIndex].y;
+                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+                                       c->m_childIndexA = childShapeIndexA;
+                                       c->m_childIndexB = childShapeIndexB;
+                                       for (int i=0;i<nReducedContacts;i++)
+                                       {
+                                               c->m_worldPosB[i] = pointsIn[contactIdx[i]];
+                                       }
+                                       GET_NPOINTS(*c) = nReducedContacts;
+                               }
+                               
+                       }//             if (numContactsOut>0)
+               }//             if (gpuHasCompoundSepNormalsOut[i])
+       }//     if (i<numCompoundPairs)
+
+}
+
+
+
+__kernel void   sphereSphereCollisionKernel( __global const int4* pairs, 
+                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, 
+                                                                                                                                                                       __global const b3Collidable_t* collidables,
+                                                                                                                                                                       __global const float4* separatingNormals,
+                                                                                                                                                                       __global const int* hasSeparatingAxis,
+                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                                                                                                                       counter32_t nGlobalContactsOut,
+                                                                                                                                                                       int contactCapacity,
+                                                                                                                                                                       int numPairs)
+{
+
+       int i = get_global_id(0);
+       int pairIndex = i;
+       
+       if (i<numPairs)
+       {
+               int bodyIndexA = pairs[i].x;
+               int bodyIndexB = pairs[i].y;
+                       
+               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+
+               if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
+                       collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
+               {
+                       //sphere-sphere
+                       float radiusA = collidables[collidableIndexA].m_radius;
+                       float radiusB = collidables[collidableIndexB].m_radius;
+                       float4 posA = rigidBodies[bodyIndexA].m_pos;
+                       float4 posB = rigidBodies[bodyIndexB].m_pos;
+
+                       float4 diff = posA-posB;
+                       float len = length(diff);
+                       
+                       ///iff distance positive, don't generate a new contact
+                       if ( len <= (radiusA+radiusB))
+                       {
+                               ///distance (negative means penetration)
+                               float dist = len - (radiusA+radiusB);
+                               float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);
+                               if (len > 0.00001)
+                               {
+                                       normalOnSurfaceB = diff / len;
+                               }
+                               float4 contactPosB = posB + normalOnSurfaceB*radiusB;
+                               contactPosB.w = dist;
+                                                               
+                               int dstIdx;
+                               AppendInc( nGlobalContactsOut, dstIdx );
+                               if (dstIdx < contactCapacity)
+                               {
+                                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+                                       c->m_worldNormalOnB = -normalOnSurfaceB;
+                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                                       c->m_batchIdx = pairIndex;
+                                       int bodyA = pairs[pairIndex].x;
+                                       int bodyB = pairs[pairIndex].y;
+                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+                                       c->m_worldPosB[0] = contactPosB;
+                                       c->m_childIndexA = -1;
+                                       c->m_childIndexB = -1;
+
+                                       GET_NPOINTS(*c) = 1;
+                               }//if (dstIdx < numPairs)
+                       }//if ( len <= (radiusA+radiusB))
+               }//SHAPE_SPHERE SHAPE_SPHERE
+       }//if (i<numPairs)
+}                              
+
+__kernel void   clipHullHullConcaveConvexKernel( __global int4* concavePairsIn,
+                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, 
+                                                                                                                                                                       __global const b3Collidable_t* collidables,
+                                                                                                                                                                       __global const b3ConvexPolyhedronData_t* convexShapes, 
+                                                                                                                                                                       __global const float4* vertices,
+                                                                                                                                                                       __global const float4* uniqueEdges,
+                                                                                                                                                                       __global const b3GpuFace_t* faces,
+                                                                                                                                                                       __global const int* indices,
+                                                                                                                                                                       __global const b3GpuChildShape_t* gpuChildShapes,
+                                                                                                                                                                       __global const float4* separatingNormals,
+                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,
+                                                                                                                                                                       counter32_t nGlobalContactsOut,
+                                                                                                                                                                       int contactCapacity,
+                                                                                                                                                                       int numConcavePairs)
+{
+
+       int i = get_global_id(0);
+       int pairIndex = i;
+       
+       float4 worldVertsB1[64];
+       float4 worldVertsB2[64];
+       int capacityWorldVerts = 64;    
+
+       float4 localContactsOut[64];
+       int localContactCapacity=64;
+       
+       float minDist = -1e30f;
+       float maxDist = 0.02f;
+
+       if (i<numConcavePairs)
+       {
+               //negative value means that the pair is invalid
+               if (concavePairsIn[i].w<0)
+                       return;
+
+               int bodyIndexA = concavePairsIn[i].x;
+               int bodyIndexB = concavePairsIn[i].y;
+               int f = concavePairsIn[i].z;
+               int childShapeIndexA = f;
+               
+               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+               
+               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+               
+               ///////////////////////////////////////////////////////////////
+               
+       
+               bool overlap = false;
+               
+               b3ConvexPolyhedronData_t convexPolyhedronA;
+
+       //add 3 vertices of the triangle
+               convexPolyhedronA.m_numVertices = 3;
+               convexPolyhedronA.m_vertexOffset = 0;
+               float4  localCenter = make_float4(0.f,0.f,0.f,0.f);
+
+               b3GpuFace_t face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+               
+               float4 verticesA[3];
+               for (int i=0;i<3;i++)
+               {
+                       int index = indices[face.m_indexOffset+i];
+                       float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+                       verticesA[i] = vert;
+                       localCenter += vert;
+               }
+
+               float dmin = FLT_MAX;
+
+               int localCC=0;
+
+               //a triangle has 3 unique edges
+               convexPolyhedronA.m_numUniqueEdges = 3;
+               convexPolyhedronA.m_uniqueEdgesOffset = 0;
+               float4 uniqueEdgesA[3];
+               
+               uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
+               uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
+               uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
+
+
+               convexPolyhedronA.m_faceOffset = 0;
+                                  
+               float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+                             
+               b3GpuFace_t facesA[TRIANGLE_NUM_CONVEX_FACES];
+               int indicesA[3+3+2+2+2];
+               int curUsedIndices=0;
+               int fidx=0;
+
+               //front size of triangle
+               {
+                       facesA[fidx].m_indexOffset=curUsedIndices;
+                       indicesA[0] = 0;
+                       indicesA[1] = 1;
+                       indicesA[2] = 2;
+                       curUsedIndices+=3;
+                       float c = face.m_plane.w;
+                       facesA[fidx].m_plane.x = normal.x;
+                       facesA[fidx].m_plane.y = normal.y;
+                       facesA[fidx].m_plane.z = normal.z;
+                       facesA[fidx].m_plane.w = c;
+                       facesA[fidx].m_numIndices=3;
+               }
+               fidx++;
+               //back size of triangle
+               {
+                       facesA[fidx].m_indexOffset=curUsedIndices;
+                       indicesA[3]=2;
+                       indicesA[4]=1;
+                       indicesA[5]=0;
+                       curUsedIndices+=3;
+                       float c = dot3F4(normal,verticesA[0]);
+                       float c1 = -face.m_plane.w;
+                       facesA[fidx].m_plane.x = -normal.x;
+                       facesA[fidx].m_plane.y = -normal.y;
+                       facesA[fidx].m_plane.z = -normal.z;
+                       facesA[fidx].m_plane.w = c;
+                       facesA[fidx].m_numIndices=3;
+               }
+               fidx++;
+
+               bool addEdgePlanes = true;
+               if (addEdgePlanes)
+               {
+                       int numVertices=3;
+                       int prevVertex = numVertices-1;
+                       for (int i=0;i<numVertices;i++)
+                       {
+                               float4 v0 = verticesA[i];
+                               float4 v1 = verticesA[prevVertex];
+                                            
+                               float4 edgeNormal = normalize(cross(normal,v1-v0));
+                               float c = -dot3F4(edgeNormal,v0);
+
+                               facesA[fidx].m_numIndices = 2;
+                               facesA[fidx].m_indexOffset=curUsedIndices;
+                               indicesA[curUsedIndices++]=i;
+                               indicesA[curUsedIndices++]=prevVertex;
+                                            
+                               facesA[fidx].m_plane.x = edgeNormal.x;
+                               facesA[fidx].m_plane.y = edgeNormal.y;
+                               facesA[fidx].m_plane.z = edgeNormal.z;
+                               facesA[fidx].m_plane.w = c;
+                               fidx++;
+                               prevVertex = i;
+                       }
+               }
+               convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
+               convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
+
+
+               float4 posA = rigidBodies[bodyIndexA].m_pos;
+               posA.w = 0.f;
+               float4 posB = rigidBodies[bodyIndexB].m_pos;
+               posB.w = 0.f;
+               float4 ornA = rigidBodies[bodyIndexA].m_quat;
+               float4 ornB =rigidBodies[bodyIndexB].m_quat;
+
+
+               float4 sepAxis = separatingNormals[i];
+               
+               int shapeTypeB = collidables[collidableIndexB].m_shapeType;
+               int childShapeIndexB =-1;
+               if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+               {
+                       ///////////////////
+                       ///compound shape support
+                       
+                       childShapeIndexB = concavePairsIn[pairIndex].w;
+                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                       shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                       float4 newPosB = transform(&childPosB,&posB,&ornB);
+                       float4 newOrnB = qtMul(ornB,childOrnB);
+                       posB = newPosB;
+                       ornB = newOrnB;
+                       
+               }
+               
+               ////////////////////////////////////////
+               
+               
+               
+               int numLocalContactsOut = clipHullAgainstHullLocalA(sepAxis,
+                                                                                                               &convexPolyhedronA, &convexShapes[shapeIndexB],
+                                                                                                               posA,ornA,
+                                                                                                         posB,ornB,
+                                                                                                         worldVertsB1,worldVertsB2,capacityWorldVerts,
+                                                                                                               minDist, maxDist,
+                                                                                                               &verticesA,&facesA,&indicesA,
+                                                                                                               vertices,faces,indices,
+                                                                                                               localContactsOut,localContactCapacity);
+                                                                                               
+               if (numLocalContactsOut>0)
+               {
+                       float4 normal = -separatingNormals[i];
+                       int nPoints = numLocalContactsOut;
+                       float4* pointsIn = localContactsOut;
+                       int contactIdx[4];// = {-1,-1,-1,-1};
+
+                       contactIdx[0] = -1;
+                       contactIdx[1] = -1;
+                       contactIdx[2] = -1;
+                       contactIdx[3] = -1;
+       
+                       int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);
+       
+                       int dstIdx;
+                       AppendInc( nGlobalContactsOut, dstIdx );
+                       if (dstIdx<contactCapacity)
+                       {
+                               __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
+                               c->m_worldNormalOnB = -normal;
+                               c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                               c->m_batchIdx = pairIndex;
+                               int bodyA = concavePairsIn[pairIndex].x;
+                               int bodyB = concavePairsIn[pairIndex].y;
+                               c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+                               c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+                               c->m_childIndexA = childShapeIndexA;
+                               c->m_childIndexB = childShapeIndexB;
+                               for (int i=0;i<nReducedContacts;i++)
+                               {
+                                       c->m_worldPosB[i] = pointsIn[contactIdx[i]];
+                               }
+                               GET_NPOINTS(*c) = nReducedContacts;
+                       }
+                               
+               }//             if (numContactsOut>0)
+       }//     if (i<numPairs)
+}
+
+
+
+
+
+
+int    findClippingFaces(const float4 separatingNormal,
+                      __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
+                      const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
+                       __global float4* worldVertsA1,
+                      __global float4* worldNormalsA1,
+                      __global float4* worldVertsB1,
+                      int capacityWorldVerts,
+                      const float minDist, float maxDist,
+                      __global const float4* vertices,
+                      __global const b3GpuFace_t* faces,
+                      __global const int* indices,
+                      __global int4* clippingFaces, int pairIndex)
+{
+       int numContactsOut = 0;
+       int numWorldVertsB1= 0;
+    
+    
+       int closestFaceB=-1;
+       float dmax = -FLT_MAX;
+    
+       {
+               for(int face=0;face<hullB->m_numFaces;face++)
+               {
+                       const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x,
+                                              faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);
+                       const float4 WorldNormal = qtRotate(ornB, Normal);
+                       float d = dot3F4(WorldNormal,separatingNormal);
+                       if (d > dmax)
+                       {
+                               dmax = d;
+                               closestFaceB = face;
+                       }
+               }
+       }
+    
+       {
+               const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];
+               const int numVertices = polyB.m_numIndices;
+               for(int e0=0;e0<numVertices;e0++)
+               {
+                       const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];
+                       worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);
+               }
+       }
+    
+    int closestFaceA=-1;
+       {
+               float dmin = FLT_MAX;
+               for(int face=0;face<hullA->m_numFaces;face++)
+               {
+                       const float4 Normal = make_float4(
+                                              faces[hullA->m_faceOffset+face].m_plane.x,
+                                              faces[hullA->m_faceOffset+face].m_plane.y,
+                                              faces[hullA->m_faceOffset+face].m_plane.z,
+                                              0.f);
+                       const float4 faceANormalWS = qtRotate(ornA,Normal);
+            
+                       float d = dot3F4(faceANormalWS,separatingNormal);
+                       if (d < dmin)
+                       {
+                               dmin = d;
+                               closestFaceA = face;
+                worldNormalsA1[pairIndex] = faceANormalWS;
+                       }
+               }
+       }
+    
+    int numVerticesA = faces[hullA->m_faceOffset+closestFaceA].m_numIndices;
+       for(int e0=0;e0<numVerticesA;e0++)
+       {
+        const float4 a = vertices[hullA->m_vertexOffset+indices[faces[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
+        worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);
+    }
+    
+    clippingFaces[pairIndex].x = closestFaceA;
+    clippingFaces[pairIndex].y = closestFaceB;
+    clippingFaces[pairIndex].z = numVerticesA;
+    clippingFaces[pairIndex].w = numWorldVertsB1;
+    
+    
+       return numContactsOut;
+}
+
+
+
+int clipFaces(__global float4* worldVertsA1,
+              __global float4* worldNormalsA1,
+              __global float4* worldVertsB1,
+              __global float4* worldVertsB2, 
+              int capacityWorldVertsB2,
+              const float minDist, float maxDist,
+              __global int4* clippingFaces,
+              int pairIndex)
+{
+       int numContactsOut = 0;
+    
+    int closestFaceA = clippingFaces[pairIndex].x;
+    int closestFaceB = clippingFaces[pairIndex].y;
+       int numVertsInA = clippingFaces[pairIndex].z;
+       int numVertsInB = clippingFaces[pairIndex].w;
+    
+       int numVertsOut = 0;
+    
+       if (closestFaceA<0)
+               return numContactsOut;
+    
+    __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];
+    __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];
+    
+    
+       
+       // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+    
+       for(int e0=0;e0<numVertsInA;e0++)
+       {
+               const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];
+               const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];
+               const float4 WorldEdge0 = aw - bw;
+               float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
+               float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
+               float4 worldA1 = aw;
+               float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
+               float4 planeNormalWS = planeNormalWS1;
+               float planeEqWS=planeEqWS1;
+               numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);
+               __global float4* tmp = pVtxOut;
+               pVtxOut = pVtxIn;
+               pVtxIn = tmp;
+               numVertsInB = numVertsOut;
+               numVertsOut = 0;
+       }
+    
+    //float4 planeNormalWS = worldNormalsA1[pairIndex];
+    //float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
+
+
+    
+    /*for (int i=0;i<numVertsInB;i++)
+    {
+        pVtxOut[i] = pVtxIn[i];
+    }*/
+    
+    
+    
+    
+    //numVertsInB=0;
+       
+    float4 planeNormalWS = worldNormalsA1[pairIndex];
+    float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
+
+    for (int i=0;i<numVertsInB;i++)
+    {
+        float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
+        if (depth <=minDist)
+        {
+            depth = minDist;
+        }
+        
+        if (depth <=maxDist)
+        {
+            float4 pointInWorld = pVtxIn[i];
+            pVtxOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+        }
+    }
+   
+    clippingFaces[pairIndex].w =numContactsOut;
+   
+    
+       return numContactsOut;
+
+}
+
+
+
+
+__kernel void   findClippingFacesKernel(  __global const int4* pairs,
+                                        __global const b3RigidBodyData_t* rigidBodies,
+                                        __global const b3Collidable_t* collidables,
+                                        __global const b3ConvexPolyhedronData_t* convexShapes,
+                                        __global const float4* vertices,
+                                        __global const float4* uniqueEdges,
+                                        __global const b3GpuFace_t* faces,
+                                        __global const int* indices,
+                                        __global const float4* separatingNormals,
+                                        __global const int* hasSeparatingAxis,
+                                        __global int4* clippingFacesOut,
+                                        __global float4* worldVertsA1,
+                                        __global float4* worldNormalsA1,
+                                        __global float4* worldVertsB1,
+                                        int capacityWorldVerts,
+                                        int numPairs
+                                        )
+{
+    
+       int i = get_global_id(0);
+       int pairIndex = i;
+    
+       
+       float minDist = -1e30f;
+       float maxDist = 0.02f;
+    
+       if (i<numPairs)
+       {
+        
+               if (hasSeparatingAxis[i])
+               {
+            
+                       int bodyIndexA = pairs[i].x;
+                       int bodyIndexB = pairs[i].y;
+                       
+                       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+                       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+                       
+                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+                       
+            
+            
+                       int numLocalContactsOut = findClippingFaces(separatingNormals[i],
+                                                        &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],
+                                                        rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,
+                                                        rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,
+                                                        worldVertsA1,
+                                                        worldNormalsA1,
+                                                        worldVertsB1,capacityWorldVerts,
+                                                        minDist, maxDist,
+                                                        vertices,faces,indices,
+                                                        clippingFacesOut,i);
+            
+            
+               }//             if (hasSeparatingAxis[i])
+       }//     if (i<numPairs)
+    
+}
+
+
+
+
+__kernel void   clipFacesAndFindContactsKernel(    __global const float4* separatingNormals,
+                                                   __global const int* hasSeparatingAxis,
+                                                   __global int4* clippingFacesOut,
+                                                   __global float4* worldVertsA1,
+                                                   __global float4* worldNormalsA1,
+                                                   __global float4* worldVertsB1,
+                                                   __global float4* worldVertsB2,
+                                                    int vertexFaceCapacity,
+                                                   int numPairs,
+                                                                               int debugMode
+                                                   )
+{
+    int i = get_global_id(0);
+       int pairIndex = i;
+       
+    
+       float minDist = -1e30f;
+       float maxDist = 0.02f;
+    
+       if (i<numPairs)
+       {
+        
+               if (hasSeparatingAxis[i])
+               {
+            
+//                     int bodyIndexA = pairs[i].x;
+       //              int bodyIndexB = pairs[i].y;
+                   
+            int numLocalContactsOut = 0;
+
+            int capacityWorldVertsB2 = vertexFaceCapacity;
+            
+            __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];
+            __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];
+            
+
+            {
+                __global int4* clippingFaces = clippingFacesOut;
+            
+                
+                int closestFaceA = clippingFaces[pairIndex].x;
+                int closestFaceB = clippingFaces[pairIndex].y;
+                int numVertsInA = clippingFaces[pairIndex].z;
+                int numVertsInB = clippingFaces[pairIndex].w;
+                
+                int numVertsOut = 0;
+                
+                if (closestFaceA>=0)
+                {
+                    
+                    
+                    
+                    // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+                    
+                    for(int e0=0;e0<numVertsInA;e0++)
+                    {
+                        const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];
+                        const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];
+                        const float4 WorldEdge0 = aw - bw;
+                        float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
+                        float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
+                        float4 worldA1 = aw;
+                        float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
+                        float4 planeNormalWS = planeNormalWS1;
+                        float planeEqWS=planeEqWS1;
+                        numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);
+                        __global float4* tmp = pVtxOut;
+                        pVtxOut = pVtxIn;
+                        pVtxIn = tmp;
+                        numVertsInB = numVertsOut;
+                        numVertsOut = 0;
+                    }
+                    
+                    float4 planeNormalWS = worldNormalsA1[pairIndex];
+                    float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
+                    
+                    for (int i=0;i<numVertsInB;i++)
+                    {
+                        float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
+                        if (depth <=minDist)
+                        {
+                            depth = minDist;
+                        }
+                        
+                        if (depth <=maxDist)
+                        {
+                            float4 pointInWorld = pVtxIn[i];
+                            pVtxOut[numLocalContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
+                        }
+                    }
+                    
+                }
+                clippingFaces[pairIndex].w =numLocalContactsOut;
+                
+
+            }
+            
+            for (int i=0;i<numLocalContactsOut;i++)
+                pVtxIn[i] = pVtxOut[i];
+                
+               }//             if (hasSeparatingAxis[i])
+       }//     if (i<numPairs)
+    
+}
+
+
+
+
+
+__kernel void   newContactReductionKernel( __global int4* pairs,
+                                                   __global const b3RigidBodyData_t* rigidBodies,
+                                                   __global const float4* separatingNormals,
+                                                   __global const int* hasSeparatingAxis,
+                                                   __global struct b3Contact4Data* globalContactsOut,
+                                                   __global int4* clippingFaces,
+                                                   __global float4* worldVertsB2,
+                                                   volatile __global int* nGlobalContactsOut,
+                                                   int vertexFaceCapacity,
+                                                                                                  int contactCapacity,
+                                                   int numPairs
+                                                   )
+{
+    int i = get_global_id(0);
+       int pairIndex = i;
+       
+    int4 contactIdx;
+    contactIdx=make_int4(0,1,2,3);
+    
+       if (i<numPairs)
+       {
+        
+               if (hasSeparatingAxis[i])
+               {
+            
+                       
+            
+            
+                       int nPoints = clippingFaces[pairIndex].w;
+           
+            if (nPoints>0)
+            {
+
+                 __global float4* pointsIn = &worldVertsB2[pairIndex*vertexFaceCapacity];
+                float4 normal = -separatingNormals[i];
+                
+                int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
+            
+                               int mprContactIndex = pairs[pairIndex].z;
+
+                int dstIdx = mprContactIndex;
+
+                               if (dstIdx<0)
+                               {
+                       AppendInc( nGlobalContactsOut, dstIdx );
+                               }
+//#if 0
+                
+                               if (dstIdx < contactCapacity)
+                               {
+
+                                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
+                                       c->m_worldNormalOnB = -normal;
+                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
+                                       c->m_batchIdx = pairIndex;
+                                       int bodyA = pairs[pairIndex].x;
+                                       int bodyB = pairs[pairIndex].y;
+
+                                       pairs[pairIndex].w = dstIdx;
+
+                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
+                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
+                    c->m_childIndexA =-1;
+                                       c->m_childIndexB =-1;
+
+                    switch (nReducedContacts)
+                    {
+                        case 4:
+                            c->m_worldPosB[3] = pointsIn[contactIdx.w];
+                        case 3:
+                            c->m_worldPosB[2] = pointsIn[contactIdx.z];
+                        case 2:
+                            c->m_worldPosB[1] = pointsIn[contactIdx.y];
+                        case 1:
+                                                       if (mprContactIndex<0)//test
+                                   c->m_worldPosB[0] = pointsIn[contactIdx.x];
+                        default:
+                        {
+                        }
+                    };
+                    
+                                       GET_NPOINTS(*c) = nReducedContacts;
+                    
+                 }
+                 
+                
+//#endif
+                               
+                       }//             if (numContactsOut>0)
+               }//             if (hasSeparatingAxis[i])
+       }//     if (i<numPairs)
+
+    
+    
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h
new file mode 100644 (file)
index 0000000..907809d
--- /dev/null
@@ -0,0 +1,2098 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* satClipKernelsCL =
+       "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+       "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+       "#ifdef cl_ext_atomic_counters_32\n"
+       "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+       "#else\n"
+       "#define counter32_t volatile __global int*\n"
+       "#endif\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GET_NUM_GROUPS get_num_groups(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define AppendInc(x, out) out = atomic_inc(x)\n"
+       "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+       "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+       "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+       "#define max2 max\n"
+       "#define min2 min\n"
+       "typedef unsigned int u32;\n"
+       "#ifndef B3_CONTACT4DATA_H\n"
+       "#define B3_CONTACT4DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "typedef  struct b3Contact4Data b3Contact4Data_t;\n"
+       "struct b3Contact4Data\n"
+       "{\n"
+       "       b3Float4        m_worldPosB[4];\n"
+       "//     b3Float4        m_localPosA[4];\n"
+       "//     b3Float4        m_localPosB[4];\n"
+       "       b3Float4        m_worldNormalOnB;       //      w: m_nPoints\n"
+       "       unsigned short  m_restituitionCoeffCmp;\n"
+       "       unsigned short  m_frictionCoeffCmp;\n"
+       "       int m_batchIdx;\n"
+       "       int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+       "       int m_bodyBPtrAndSignBit;\n"
+       "       int     m_childIndexA;\n"
+       "       int     m_childIndexB;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "};\n"
+       "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+       "{\n"
+       "       return (int)contact->m_worldNormalOnB.w;\n"
+       "};\n"
+       "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+       "{\n"
+       "       contact->m_worldNormalOnB.w = (float)numPoints;\n"
+       "};\n"
+       "#endif //B3_CONTACT4DATA_H\n"
+       "#ifndef B3_CONVEX_POLYHEDRON_DATA_H\n"
+       "#define B3_CONVEX_POLYHEDRON_DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#define B3_QUAT_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Quat;\n"
+       "       #define b3QuatConstArg const b3Quat\n"
+       "       \n"
+       "       \n"
+       "inline float4 b3FastNormalize4(float4 v)\n"
+       "{\n"
+       "       v = (float4)(v.xyz,0.f);\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "       \n"
+       "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+       "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+       "{\n"
+       "       b3Quat ans;\n"
+       "       ans = b3Cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+       "{\n"
+       "       b3Quat q;\n"
+       "       q=in;\n"
+       "       //return b3FastNormalize4(in);\n"
+       "       float len = native_sqrt(dot(q, q));\n"
+       "       if(len > 0.f)\n"
+       "       {\n"
+       "               q *= 1.f / len;\n"
+       "       }\n"
+       "       else\n"
+       "       {\n"
+       "               q.x = q.y = q.z = 0.f;\n"
+       "               q.w = 1.f;\n"
+       "       }\n"
+       "       return q;\n"
+       "}\n"
+       "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       b3Quat qInv = b3QuatInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+       "}\n"
+       "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg  orientation)\n"
+       "{\n"
+       "       return b3QuatRotate( orientation, point ) + (translation);\n"
+       "}\n"
+       "       \n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "typedef struct b3GpuFace b3GpuFace_t;\n"
+       "struct b3GpuFace\n"
+       "{\n"
+       "       b3Float4 m_plane;\n"
+       "       int m_indexOffset;\n"
+       "       int m_numIndices;\n"
+       "       int m_unusedPadding1;\n"
+       "       int m_unusedPadding2;\n"
+       "};\n"
+       "typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;\n"
+       "struct b3ConvexPolyhedronData\n"
+       "{\n"
+       "       b3Float4                m_localCenter;\n"
+       "       b3Float4                m_extents;\n"
+       "       b3Float4                mC;\n"
+       "       b3Float4                mE;\n"
+       "       float                   m_radius;\n"
+       "       int     m_faceOffset;\n"
+       "       int m_numFaces;\n"
+       "       int     m_numVertices;\n"
+       "       int m_vertexOffset;\n"
+       "       int     m_uniqueEdgesOffset;\n"
+       "       int     m_numUniqueEdges;\n"
+       "       int m_unused;\n"
+       "};\n"
+       "#endif //B3_CONVEX_POLYHEDRON_DATA_H\n"
+       "#ifndef B3_COLLIDABLE_H\n"
+       "#define B3_COLLIDABLE_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "enum b3ShapeTypes\n"
+       "{\n"
+       "       SHAPE_HEIGHT_FIELD=1,\n"
+       "       SHAPE_CONVEX_HULL=3,\n"
+       "       SHAPE_PLANE=4,\n"
+       "       SHAPE_CONCAVE_TRIMESH=5,\n"
+       "       SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
+       "       SHAPE_SPHERE=7,\n"
+       "       MAX_NUM_SHAPE_TYPES,\n"
+       "};\n"
+       "typedef struct b3Collidable b3Collidable_t;\n"
+       "struct b3Collidable\n"
+       "{\n"
+       "       union {\n"
+       "               int m_numChildShapes;\n"
+       "               int m_bvhIndex;\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float m_radius;\n"
+       "               int     m_compoundBvhIndex;\n"
+       "       };\n"
+       "       int m_shapeType;\n"
+       "       int m_shapeIndex;\n"
+       "};\n"
+       "typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
+       "struct b3GpuChildShape\n"
+       "{\n"
+       "       b3Float4        m_childPosition;\n"
+       "       b3Quat          m_childOrientation;\n"
+       "       int m_shapeIndex;\n"
+       "       int m_unused0;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "};\n"
+       "struct b3CompoundOverlappingPair\n"
+       "{\n"
+       "       int m_bodyIndexA;\n"
+       "       int m_bodyIndexB;\n"
+       "//     int     m_pairType;\n"
+       "       int m_childShapeIndexA;\n"
+       "       int m_childShapeIndexB;\n"
+       "};\n"
+       "#endif //B3_COLLIDABLE_H\n"
+       "#ifndef B3_RIGIDBODY_DATA_H\n"
+       "#define B3_RIGIDBODY_DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifndef B3_MAT3x3_H\n"
+       "#define B3_MAT3x3_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "typedef struct\n"
+       "{\n"
+       "       b3Float4 m_row[3];\n"
+       "}b3Mat3x3;\n"
+       "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+       "#define b3GetRow(m,row) (m.m_row[row])\n"
+       "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+       "{\n"
+       "       b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+       "       out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+       "       out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+       "       out.m_row[0].w = 0.f;\n"
+       "       out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+       "       out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+       "       out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+       "       out.m_row[1].w = 0.f;\n"
+       "       out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+       "       out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+       "       out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+       "       out.m_row[2].w = 0.f;\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = fabs(matIn.m_row[0]);\n"
+       "       out.m_row[1] = fabs(matIn.m_row[1]);\n"
+       "       out.m_row[2] = fabs(matIn.m_row[2]);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero();\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity();\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(0.f);\n"
+       "       m.m_row[1] = (b3Float4)(0.f);\n"
+       "       m.m_row[2] = (b3Float4)(0.f);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+       "       m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+       "       m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+       "       out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+       "       out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Mat3x3 transB;\n"
+       "       transB = mtTranspose( b );\n"
+       "       b3Mat3x3 ans;\n"
+       "       //      why this doesn't run when 0ing in the for{}\n"
+       "       a.m_row[0].w = 0.f;\n"
+       "       a.m_row[1].w = 0.f;\n"
+       "       a.m_row[2].w = 0.f;\n"
+       "       for(int i=0; i<3; i++)\n"
+       "       {\n"
+       "//     a.m_row[i].w = 0.f;\n"
+       "               ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+       "               ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+       "               ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+       "               ans.m_row[i].w = 0.f;\n"
+       "       }\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+       "{\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a.m_row[0], b );\n"
+       "       ans.y = b3Dot3F4( a.m_row[1], b );\n"
+       "       ans.z = b3Dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a, colx );\n"
+       "       ans.y = b3Dot3F4( a, coly );\n"
+       "       ans.z = b3Dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "#endif\n"
+       "#endif //B3_MAT3x3_H\n"
+       "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+       "struct b3RigidBodyData\n"
+       "{\n"
+       "       b3Float4                                m_pos;\n"
+       "       b3Quat                                  m_quat;\n"
+       "       b3Float4                                m_linVel;\n"
+       "       b3Float4                                m_angVel;\n"
+       "       int                                     m_collidableIdx;\n"
+       "       float                           m_invMass;\n"
+       "       float                           m_restituitionCoeff;\n"
+       "       float                           m_frictionCoeff;\n"
+       "};\n"
+       "typedef struct b3InertiaData b3InertiaData_t;\n"
+       "struct b3InertiaData\n"
+       "{\n"
+       "       b3Mat3x3 m_invInertiaWorld;\n"
+       "       b3Mat3x3 m_initInvInertia;\n"
+       "};\n"
+       "#endif //B3_RIGIDBODY_DATA_H\n"
+       "       \n"
+       "#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
+       "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+       "#define make_float4 (float4)\n"
+       "#define make_float2 (float2)\n"
+       "#define make_uint4 (uint4)\n"
+       "#define make_int4 (int4)\n"
+       "#define make_uint2 (uint2)\n"
+       "#define make_int2 (int2)\n"
+       "__inline\n"
+       "float fastDiv(float numerator, float denominator)\n"
+       "{\n"
+       "       return native_divide(numerator, denominator);   \n"
+       "//     return numerator/denominator;   \n"
+       "}\n"
+       "__inline\n"
+       "float4 fastDiv4(float4 numerator, float4 denominator)\n"
+       "{\n"
+       "       return native_divide(numerator, denominator);   \n"
+       "}\n"
+       "__inline\n"
+       "float4 cross3(float4 a, float4 b)\n"
+       "{\n"
+       "       return cross(a,b);\n"
+       "}\n"
+       "//#define dot3F4 dot\n"
+       "__inline\n"
+       "float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = make_float4(a.xyz,0.f);\n"
+       "       float4 b1 = make_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "float4 fastNormalize4(float4 v)\n"
+       "{\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Quaternion\n"
+       "///////////////////////////////////////\n"
+       "typedef float4 Quaternion;\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in);\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec);\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q);\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+       "{\n"
+       "       Quaternion ans;\n"
+       "       ans = cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in)\n"
+       "{\n"
+       "       return fastNormalize4(in);\n"
+       "//     in /= length( in );\n"
+       "//     return in;\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec)\n"
+       "{\n"
+       "       Quaternion qInv = qtInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q)\n"
+       "{\n"
+       "       return (Quaternion)(-q.xyz, q.w);\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+       "{\n"
+       "       return qtRotate( qtInvert( q ), vec );\n"
+       "}\n"
+       "__inline\n"
+       "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+       "{\n"
+       "       return qtRotate( *orientation, *p ) + (*translation);\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize3(const float4 a)\n"
+       "{\n"
+       "       float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+       "       return fastNormalize4( n );\n"
+       "}\n"
+       "__inline float4 lerp3(const float4 a,const float4 b, float  t)\n"
+       "{\n"
+       "       return make_float4(     a.x + (b.x - a.x) * t,\n"
+       "                                               a.y + (b.y - a.y) * t,\n"
+       "                                               a.z + (b.z - a.z) * t,\n"
+       "                                               0.f);\n"
+       "}\n"
+       "// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut\n"
+       "int clipFaceGlobal(__global const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, __global float4* ppVtxOut)\n"
+       "{\n"
+       "       \n"
+       "       int ve;\n"
+       "       float ds, de;\n"
+       "       int numVertsOut = 0;\n"
+       "    //double-check next test\n"
+       "       if (numVertsIn < 2)\n"
+       "               return 0;\n"
+       "    \n"
+       "       float4 firstVertex=pVtxIn[numVertsIn-1];\n"
+       "       float4 endVertex = pVtxIn[0];\n"
+       "       \n"
+       "       ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;\n"
+       "    \n"
+       "       for (ve = 0; ve < numVertsIn; ve++)\n"
+       "       {\n"
+       "               endVertex=pVtxIn[ve];\n"
+       "               de = dot3F4(planeNormalWS,endVertex)+planeEqWS;\n"
+       "               if (ds<0)\n"
+       "               {\n"
+       "                       if (de<0)\n"
+       "                       {\n"
+       "                               // Start < 0, end < 0, so output endVertex\n"
+       "                               ppVtxOut[numVertsOut++] = endVertex;\n"
+       "                       }\n"
+       "                       else\n"
+       "                       {\n"
+       "                               // Start < 0, end >= 0, so output intersection\n"
+       "                               ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+       "                       }\n"
+       "               }\n"
+       "               else\n"
+       "               {\n"
+       "                       if (de<0)\n"
+       "                       {\n"
+       "                               // Start >= 0, end < 0 so output intersection and end\n"
+       "                               ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+       "                               ppVtxOut[numVertsOut++] = endVertex;\n"
+       "                       }\n"
+       "               }\n"
+       "               firstVertex = endVertex;\n"
+       "               ds = de;\n"
+       "       }\n"
+       "       return numVertsOut;\n"
+       "}\n"
+       "// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut\n"
+       "int clipFace(const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, float4* ppVtxOut)\n"
+       "{\n"
+       "       \n"
+       "       int ve;\n"
+       "       float ds, de;\n"
+       "       int numVertsOut = 0;\n"
+       "//double-check next test\n"
+       "       if (numVertsIn < 2)\n"
+       "               return 0;\n"
+       "       float4 firstVertex=pVtxIn[numVertsIn-1];\n"
+       "       float4 endVertex = pVtxIn[0];\n"
+       "       \n"
+       "       ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;\n"
+       "       for (ve = 0; ve < numVertsIn; ve++)\n"
+       "       {\n"
+       "               endVertex=pVtxIn[ve];\n"
+       "               de = dot3F4(planeNormalWS,endVertex)+planeEqWS;\n"
+       "               if (ds<0)\n"
+       "               {\n"
+       "                       if (de<0)\n"
+       "                       {\n"
+       "                               // Start < 0, end < 0, so output endVertex\n"
+       "                               ppVtxOut[numVertsOut++] = endVertex;\n"
+       "                       }\n"
+       "                       else\n"
+       "                       {\n"
+       "                               // Start < 0, end >= 0, so output intersection\n"
+       "                               ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+       "                       }\n"
+       "               }\n"
+       "               else\n"
+       "               {\n"
+       "                       if (de<0)\n"
+       "                       {\n"
+       "                               // Start >= 0, end < 0 so output intersection and end\n"
+       "                               ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
+       "                               ppVtxOut[numVertsOut++] = endVertex;\n"
+       "                       }\n"
+       "               }\n"
+       "               firstVertex = endVertex;\n"
+       "               ds = de;\n"
+       "       }\n"
+       "       return numVertsOut;\n"
+       "}\n"
+       "int clipFaceAgainstHull(const float4 separatingNormal, __global const b3ConvexPolyhedronData_t* hullA,  \n"
+       "       const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,\n"
+       "       float4* worldVertsB2, int capacityWorldVertsB2,\n"
+       "       const float minDist, float maxDist,\n"
+       "       __global const float4* vertices,\n"
+       "       __global const b3GpuFace_t* faces,\n"
+       "       __global const int* indices,\n"
+       "       float4* contactsOut,\n"
+       "       int contactCapacity)\n"
+       "{\n"
+       "       int numContactsOut = 0;\n"
+       "       float4* pVtxIn = worldVertsB1;\n"
+       "       float4* pVtxOut = worldVertsB2;\n"
+       "       \n"
+       "       int numVertsIn = numWorldVertsB1;\n"
+       "       int numVertsOut = 0;\n"
+       "       int closestFaceA=-1;\n"
+       "       {\n"
+       "               float dmin = FLT_MAX;\n"
+       "               for(int face=0;face<hullA->m_numFaces;face++)\n"
+       "               {\n"
+       "                       const float4 Normal = make_float4(\n"
+       "                               faces[hullA->m_faceOffset+face].m_plane.x, \n"
+       "                               faces[hullA->m_faceOffset+face].m_plane.y, \n"
+       "                               faces[hullA->m_faceOffset+face].m_plane.z,0.f);\n"
+       "                       const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+       "               \n"
+       "                       float d = dot3F4(faceANormalWS,separatingNormal);\n"
+       "                       if (d < dmin)\n"
+       "                       {\n"
+       "                               dmin = d;\n"
+       "                               closestFaceA = face;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       if (closestFaceA<0)\n"
+       "               return numContactsOut;\n"
+       "       b3GpuFace_t polyA = faces[hullA->m_faceOffset+closestFaceA];\n"
+       "       // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+       "       int numVerticesA = polyA.m_numIndices;\n"
+       "       for(int e0=0;e0<numVerticesA;e0++)\n"
+       "       {\n"
+       "               const float4 a = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+e0]];\n"
+       "               const float4 b = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+((e0+1)%numVerticesA)]];\n"
+       "               const float4 edge0 = a - b;\n"
+       "               const float4 WorldEdge0 = qtRotate(ornA,edge0);\n"
+       "               float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+       "               float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);\n"
+       "               float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+       "               float4 worldA1 = transform(&a,&posA,&ornA);\n"
+       "               float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+       "               \n"
+       "               float4 planeNormalWS = planeNormalWS1;\n"
+       "               float planeEqWS=planeEqWS1;\n"
+       "               \n"
+       "               //clip face\n"
+       "               //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);\n"
+       "               numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);\n"
+       "               //btSwap(pVtxIn,pVtxOut);\n"
+       "               float4* tmp = pVtxOut;\n"
+       "               pVtxOut = pVtxIn;\n"
+       "               pVtxIn = tmp;\n"
+       "               numVertsIn = numVertsOut;\n"
+       "               numVertsOut = 0;\n"
+       "       }\n"
+       "       \n"
+       "       // only keep points that are behind the witness face\n"
+       "       {\n"
+       "               float4 localPlaneNormal  = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+       "               float localPlaneEq = polyA.m_plane.w;\n"
+       "               float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);\n"
+       "               float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);\n"
+       "               for (int i=0;i<numVertsIn;i++)\n"
+       "               {\n"
+       "                       float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+       "                       if (depth <=minDist)\n"
+       "                       {\n"
+       "                               depth = minDist;\n"
+       "                       }\n"
+       "                       if (depth <=maxDist)\n"
+       "                       {\n"
+       "                               float4 pointInWorld = pVtxIn[i];\n"
+       "                               //resultOut.addContactPoint(separatingNormal,point,depth);\n"
+       "                               contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       return numContactsOut;\n"
+       "}\n"
+       "int clipFaceAgainstHullLocalA(const float4 separatingNormal, const b3ConvexPolyhedronData_t* hullA,  \n"
+       "       const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,\n"
+       "       float4* worldVertsB2, int capacityWorldVertsB2,\n"
+       "       const float minDist, float maxDist,\n"
+       "       const float4* verticesA,\n"
+       "       const b3GpuFace_t* facesA,\n"
+       "       const int* indicesA,\n"
+       "       __global const float4* verticesB,\n"
+       "       __global const b3GpuFace_t* facesB,\n"
+       "       __global const int* indicesB,\n"
+       "       float4* contactsOut,\n"
+       "       int contactCapacity)\n"
+       "{\n"
+       "       int numContactsOut = 0;\n"
+       "       float4* pVtxIn = worldVertsB1;\n"
+       "       float4* pVtxOut = worldVertsB2;\n"
+       "       \n"
+       "       int numVertsIn = numWorldVertsB1;\n"
+       "       int numVertsOut = 0;\n"
+       "       int closestFaceA=-1;\n"
+       "       {\n"
+       "               float dmin = FLT_MAX;\n"
+       "               for(int face=0;face<hullA->m_numFaces;face++)\n"
+       "               {\n"
+       "                       const float4 Normal = make_float4(\n"
+       "                               facesA[hullA->m_faceOffset+face].m_plane.x, \n"
+       "                               facesA[hullA->m_faceOffset+face].m_plane.y, \n"
+       "                               facesA[hullA->m_faceOffset+face].m_plane.z,0.f);\n"
+       "                       const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+       "               \n"
+       "                       float d = dot3F4(faceANormalWS,separatingNormal);\n"
+       "                       if (d < dmin)\n"
+       "                       {\n"
+       "                               dmin = d;\n"
+       "                               closestFaceA = face;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       if (closestFaceA<0)\n"
+       "               return numContactsOut;\n"
+       "       b3GpuFace_t polyA = facesA[hullA->m_faceOffset+closestFaceA];\n"
+       "       // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+       "       int numVerticesA = polyA.m_numIndices;\n"
+       "       for(int e0=0;e0<numVerticesA;e0++)\n"
+       "       {\n"
+       "               const float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];\n"
+       "               const float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];\n"
+       "               const float4 edge0 = a - b;\n"
+       "               const float4 WorldEdge0 = qtRotate(ornA,edge0);\n"
+       "               float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+       "               float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);\n"
+       "               float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+       "               float4 worldA1 = transform(&a,&posA,&ornA);\n"
+       "               float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+       "               \n"
+       "               float4 planeNormalWS = planeNormalWS1;\n"
+       "               float planeEqWS=planeEqWS1;\n"
+       "               \n"
+       "               //clip face\n"
+       "               //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);\n"
+       "               numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);\n"
+       "               //btSwap(pVtxIn,pVtxOut);\n"
+       "               float4* tmp = pVtxOut;\n"
+       "               pVtxOut = pVtxIn;\n"
+       "               pVtxIn = tmp;\n"
+       "               numVertsIn = numVertsOut;\n"
+       "               numVertsOut = 0;\n"
+       "       }\n"
+       "       \n"
+       "       // only keep points that are behind the witness face\n"
+       "       {\n"
+       "               float4 localPlaneNormal  = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
+       "               float localPlaneEq = polyA.m_plane.w;\n"
+       "               float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);\n"
+       "               float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);\n"
+       "               for (int i=0;i<numVertsIn;i++)\n"
+       "               {\n"
+       "                       float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+       "                       if (depth <=minDist)\n"
+       "                       {\n"
+       "                               depth = minDist;\n"
+       "                       }\n"
+       "                       if (depth <=maxDist)\n"
+       "                       {\n"
+       "                               float4 pointInWorld = pVtxIn[i];\n"
+       "                               //resultOut.addContactPoint(separatingNormal,point,depth);\n"
+       "                               contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       return numContactsOut;\n"
+       "}\n"
+       "int    clipHullAgainstHull(const float4 separatingNormal,\n"
+       "       __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
+       "       const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, \n"
+       "       float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,\n"
+       "       const float minDist, float maxDist,\n"
+       "       __global const float4* vertices,\n"
+       "       __global const b3GpuFace_t* faces,\n"
+       "       __global const int* indices,\n"
+       "       float4* localContactsOut,\n"
+       "       int localContactCapacity)\n"
+       "{\n"
+       "       int numContactsOut = 0;\n"
+       "       int numWorldVertsB1= 0;\n"
+       "       int closestFaceB=-1;\n"
+       "       float dmax = -FLT_MAX;\n"
+       "       {\n"
+       "               for(int face=0;face<hullB->m_numFaces;face++)\n"
+       "               {\n"
+       "                       const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x, \n"
+       "                               faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+       "                       const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+       "                       float d = dot3F4(WorldNormal,separatingNormal);\n"
+       "                       if (d > dmax)\n"
+       "                       {\n"
+       "                               dmax = d;\n"
+       "                               closestFaceB = face;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       {\n"
+       "               const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];\n"
+       "               const int numVertices = polyB.m_numIndices;\n"
+       "               for(int e0=0;e0<numVertices;e0++)\n"
+       "               {\n"
+       "                       const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];\n"
+       "                       worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+       "               }\n"
+       "       }\n"
+       "       if (closestFaceB>=0)\n"
+       "       {\n"
+       "               numContactsOut = clipFaceAgainstHull(separatingNormal, hullA, \n"
+       "                               posA,ornA,\n"
+       "                               worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,vertices,\n"
+       "                               faces,\n"
+       "                               indices,localContactsOut,localContactCapacity);\n"
+       "       }\n"
+       "       return numContactsOut;\n"
+       "}\n"
+       "int    clipHullAgainstHullLocalA(const float4 separatingNormal,\n"
+       "       const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
+       "       const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, \n"
+       "       float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,\n"
+       "       const float minDist, float maxDist,\n"
+       "       const float4* verticesA,\n"
+       "       const b3GpuFace_t* facesA,\n"
+       "       const int* indicesA,\n"
+       "       __global const float4* verticesB,\n"
+       "       __global const b3GpuFace_t* facesB,\n"
+       "       __global const int* indicesB,\n"
+       "       float4* localContactsOut,\n"
+       "       int localContactCapacity)\n"
+       "{\n"
+       "       int numContactsOut = 0;\n"
+       "       int numWorldVertsB1= 0;\n"
+       "       int closestFaceB=-1;\n"
+       "       float dmax = -FLT_MAX;\n"
+       "       {\n"
+       "               for(int face=0;face<hullB->m_numFaces;face++)\n"
+       "               {\n"
+       "                       const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x, \n"
+       "                               facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+       "                       const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+       "                       float d = dot3F4(WorldNormal,separatingNormal);\n"
+       "                       if (d > dmax)\n"
+       "                       {\n"
+       "                               dmax = d;\n"
+       "                               closestFaceB = face;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       {\n"
+       "               const b3GpuFace_t polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
+       "               const int numVertices = polyB.m_numIndices;\n"
+       "               for(int e0=0;e0<numVertices;e0++)\n"
+       "               {\n"
+       "                       const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
+       "                       worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+       "               }\n"
+       "       }\n"
+       "       if (closestFaceB>=0)\n"
+       "       {\n"
+       "               numContactsOut = clipFaceAgainstHullLocalA(separatingNormal, hullA, \n"
+       "                               posA,ornA,\n"
+       "                               worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,\n"
+       "                               verticesA,facesA,indicesA,\n"
+       "                               verticesB,facesB,indicesB,\n"
+       "                               localContactsOut,localContactCapacity);\n"
+       "       }\n"
+       "       return numContactsOut;\n"
+       "}\n"
+       "#define PARALLEL_SUM(v, n) for(int j=1; j<n; j++) v[0] += v[j];\n"
+       "#define PARALLEL_DO(execution, n) for(int ie=0; ie<n; ie++){execution;}\n"
+       "#define REDUCE_MAX(v, n) {int i=0; for(int offset=0; offset<n; offset++) v[i] = (v[i].y > v[i+offset].y)? v[i]: v[i+offset]; }\n"
+       "#define REDUCE_MIN(v, n) {int i=0; for(int offset=0; offset<n; offset++) v[i] = (v[i].y < v[i+offset].y)? v[i]: v[i+offset]; }\n"
+       "int extractManifoldSequentialGlobal(__global const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)\n"
+       "{\n"
+       "       if( nPoints == 0 )\n"
+       "        return 0;\n"
+       "    \n"
+       "    if (nPoints <=4)\n"
+       "        return nPoints;\n"
+       "    \n"
+       "    \n"
+       "    if (nPoints >64)\n"
+       "        nPoints = 64;\n"
+       "    \n"
+       "       float4 center = make_float4(0.f);\n"
+       "       {\n"
+       "               \n"
+       "               for (int i=0;i<nPoints;i++)\n"
+       "                       center += p[i];\n"
+       "               center /= (float)nPoints;\n"
+       "       }\n"
+       "    \n"
+       "       \n"
+       "    \n"
+       "       //      sample 4 directions\n"
+       "    \n"
+       "    float4 aVector = p[0] - center;\n"
+       "    float4 u = cross3( nearNormal, aVector );\n"
+       "    float4 v = cross3( nearNormal, u );\n"
+       "    u = normalize3( u );\n"
+       "    v = normalize3( v );\n"
+       "    \n"
+       "    \n"
+       "    //keep point with deepest penetration\n"
+       "    float minW= FLT_MAX;\n"
+       "    \n"
+       "    int minIndex=-1;\n"
+       "    \n"
+       "    float4 maxDots;\n"
+       "    maxDots.x = FLT_MIN;\n"
+       "    maxDots.y = FLT_MIN;\n"
+       "    maxDots.z = FLT_MIN;\n"
+       "    maxDots.w = FLT_MIN;\n"
+       "    \n"
+       "    // idx, distance\n"
+       "    for(int ie = 0; ie<nPoints; ie++ )\n"
+       "    {\n"
+       "        if (p[ie].w<minW)\n"
+       "        {\n"
+       "            minW = p[ie].w;\n"
+       "            minIndex=ie;\n"
+       "        }\n"
+       "        float f;\n"
+       "        float4 r = p[ie]-center;\n"
+       "        f = dot3F4( u, r );\n"
+       "        if (f<maxDots.x)\n"
+       "        {\n"
+       "            maxDots.x = f;\n"
+       "            contactIdx[0].x = ie;\n"
+       "        }\n"
+       "        \n"
+       "        f = dot3F4( -u, r );\n"
+       "        if (f<maxDots.y)\n"
+       "        {\n"
+       "            maxDots.y = f;\n"
+       "            contactIdx[0].y = ie;\n"
+       "        }\n"
+       "        \n"
+       "        \n"
+       "        f = dot3F4( v, r );\n"
+       "        if (f<maxDots.z)\n"
+       "        {\n"
+       "            maxDots.z = f;\n"
+       "            contactIdx[0].z = ie;\n"
+       "        }\n"
+       "        \n"
+       "        f = dot3F4( -v, r );\n"
+       "        if (f<maxDots.w)\n"
+       "        {\n"
+       "            maxDots.w = f;\n"
+       "            contactIdx[0].w = ie;\n"
+       "        }\n"
+       "        \n"
+       "    }\n"
+       "    \n"
+       "    if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)\n"
+       "    {\n"
+       "        //replace the first contact with minimum (todo: replace contact with least penetration)\n"
+       "        contactIdx[0].x = minIndex;\n"
+       "    }\n"
+       "    \n"
+       "    return 4;\n"
+       "    \n"
+       "}\n"
+       "int extractManifoldSequentialGlobalFake(__global const float4* p, int nPoints, float4 nearNormal, int* contactIdx)\n"
+       "{\n"
+       "    contactIdx[0] = 0;\n"
+       "    contactIdx[1] = 1;\n"
+       "    contactIdx[2] = 2;\n"
+       "    contactIdx[3] = 3;\n"
+       "    \n"
+       "       if( nPoints == 0 ) return 0;\n"
+       "    \n"
+       "       nPoints = min2( nPoints, 4 );\n"
+       "    return nPoints;\n"
+       "    \n"
+       "}\n"
+       "int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int* contactIdx)\n"
+       "{\n"
+       "       if( nPoints == 0 ) return 0;\n"
+       "       nPoints = min2( nPoints, 64 );\n"
+       "       float4 center = make_float4(0.f);\n"
+       "       {\n"
+       "               float4 v[64];\n"
+       "               for (int i=0;i<nPoints;i++)\n"
+       "                       v[i] = p[i];\n"
+       "               //memcpy( v, p, nPoints*sizeof(float4) );\n"
+       "               PARALLEL_SUM( v, nPoints );\n"
+       "               center = v[0]/(float)nPoints;\n"
+       "       }\n"
+       "       \n"
+       "       {       //      sample 4 directions\n"
+       "               if( nPoints < 4 )\n"
+       "               {\n"
+       "                       for(int i=0; i<nPoints; i++) \n"
+       "                               contactIdx[i] = i;\n"
+       "                       return nPoints;\n"
+       "               }\n"
+       "               float4 aVector = p[0] - center;\n"
+       "               float4 u = cross3( nearNormal, aVector );\n"
+       "               float4 v = cross3( nearNormal, u );\n"
+       "               u = normalize3( u );\n"
+       "               v = normalize3( v );\n"
+       "               int idx[4];\n"
+       "               float2 max00 = make_float2(0,FLT_MAX);\n"
+       "               {\n"
+       "                       //      idx, distance\n"
+       "                       {\n"
+       "                               {\n"
+       "                                       int4 a[64];\n"
+       "                                       for(int ie = 0; ie<nPoints; ie++ )\n"
+       "                                       {\n"
+       "                                               \n"
+       "                                               \n"
+       "                                               float f;\n"
+       "                                               float4 r = p[ie]-center;\n"
+       "                                               f = dot3F4( u, r );\n"
+       "                                               a[ie].x = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+       "                                               f = dot3F4( -u, r );\n"
+       "                                               a[ie].y = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+       "                                               f = dot3F4( v, r );\n"
+       "                                               a[ie].z = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+       "                                               f = dot3F4( -v, r );\n"
+       "                                               a[ie].w = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
+       "                                       }\n"
+       "                                       for(int ie=0; ie<nPoints; ie++)\n"
+       "                                       {\n"
+       "                                               a[0].x = (a[0].x > a[ie].x )? a[0].x: a[ie].x;\n"
+       "                                               a[0].y = (a[0].y > a[ie].y )? a[0].y: a[ie].y;\n"
+       "                                               a[0].z = (a[0].z > a[ie].z )? a[0].z: a[ie].z;\n"
+       "                                               a[0].w = (a[0].w > a[ie].w )? a[0].w: a[ie].w;\n"
+       "                                       }\n"
+       "                                       idx[0] = (int)a[0].x & 0xff;\n"
+       "                                       idx[1] = (int)a[0].y & 0xff;\n"
+       "                                       idx[2] = (int)a[0].z & 0xff;\n"
+       "                                       idx[3] = (int)a[0].w & 0xff;\n"
+       "                               }\n"
+       "                       }\n"
+       "                       {\n"
+       "                               float2 h[64];\n"
+       "                               PARALLEL_DO( h[ie] = make_float2((float)ie, p[ie].w), nPoints );\n"
+       "                               REDUCE_MIN( h, nPoints );\n"
+       "                               max00 = h[0];\n"
+       "                       }\n"
+       "               }\n"
+       "               contactIdx[0] = idx[0];\n"
+       "               contactIdx[1] = idx[1];\n"
+       "               contactIdx[2] = idx[2];\n"
+       "               contactIdx[3] = idx[3];\n"
+       "               return 4;\n"
+       "       }\n"
+       "}\n"
+       "__kernel void   extractManifoldAndAddContactKernel(__global const int4* pairs, \n"
+       "                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, \n"
+       "                                                                                                                                       __global const float4* closestPointsWorld,\n"
+       "                                                                                                                                       __global const float4* separatingNormalsWorld,\n"
+       "                                                                                                                                       __global const int* contactCounts,\n"
+       "                                                                                                                                       __global const int* contactOffsets,\n"
+       "                                                                                                                                       __global struct b3Contact4Data* restrict contactsOut,\n"
+       "                                                                                                                                       counter32_t nContactsOut,\n"
+       "                                                                                                                                       int contactCapacity,\n"
+       "                                                                                                                                       int numPairs,\n"
+       "                                                                                                                                       int pairIndex\n"
+       "                                                                                                                                       )\n"
+       "{\n"
+       "       int idx = get_global_id(0);\n"
+       "       \n"
+       "       if (idx<numPairs)\n"
+       "       {\n"
+       "               float4 normal = separatingNormalsWorld[idx];\n"
+       "               int nPoints = contactCounts[idx];\n"
+       "               __global const float4* pointsIn = &closestPointsWorld[contactOffsets[idx]];\n"
+       "               float4 localPoints[64];\n"
+       "               for (int i=0;i<nPoints;i++)\n"
+       "               {\n"
+       "                       localPoints[i] = pointsIn[i];\n"
+       "               }\n"
+       "               int contactIdx[4];// = {-1,-1,-1,-1};\n"
+       "               contactIdx[0] = -1;\n"
+       "               contactIdx[1] = -1;\n"
+       "               contactIdx[2] = -1;\n"
+       "               contactIdx[3] = -1;\n"
+       "               int nContacts = extractManifoldSequential(localPoints, nPoints, normal, contactIdx);\n"
+       "               int dstIdx;\n"
+       "               AppendInc( nContactsOut, dstIdx );\n"
+       "               if (dstIdx<contactCapacity)\n"
+       "               {\n"
+       "                       __global struct b3Contact4Data* c = contactsOut + dstIdx;\n"
+       "                       c->m_worldNormalOnB = -normal;\n"
+       "                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                       c->m_batchIdx = idx;\n"
+       "                       int bodyA = pairs[pairIndex].x;\n"
+       "                       int bodyB = pairs[pairIndex].y;\n"
+       "                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;\n"
+       "                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;\n"
+       "                       c->m_childIndexA = -1;\n"
+       "                       c->m_childIndexB = -1;\n"
+       "                       for (int i=0;i<nContacts;i++)\n"
+       "                       {\n"
+       "                               c->m_worldPosB[i] = localPoints[contactIdx[i]];\n"
+       "                       }\n"
+       "                       GET_NPOINTS(*c) = nContacts;\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "void   trInverse(float4 translationIn, Quaternion orientationIn,\n"
+       "               float4* translationOut, Quaternion* orientationOut)\n"
+       "{\n"
+       "       *orientationOut = qtInvert(orientationIn);\n"
+       "       *translationOut = qtRotate(*orientationOut, -translationIn);\n"
+       "}\n"
+       "void   trMul(float4 translationA, Quaternion orientationA,\n"
+       "                                               float4 translationB, Quaternion orientationB,\n"
+       "               float4* translationOut, Quaternion* orientationOut)\n"
+       "{\n"
+       "       *orientationOut = qtMul(orientationA,orientationB);\n"
+       "       *translationOut = transform(&translationB,&translationA,&orientationA);\n"
+       "}\n"
+       "__kernel void   clipHullHullKernel( __global int4* pairs, \n"
+       "                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, \n"
+       "                                                                                                                                                                       __global const b3Collidable_t* collidables,\n"
+       "                                                                                                                                                                       __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global const float4* uniqueEdges,\n"
+       "                                                                                                                                                                       __global const b3GpuFace_t* faces,\n"
+       "                                                                                                                                                                       __global const int* indices,\n"
+       "                                                                                                                                                                       __global const float4* separatingNormals,\n"
+       "                                                                                                                                                                       __global const int* hasSeparatingAxis,\n"
+       "                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                                                                                                                       counter32_t nGlobalContactsOut,\n"
+       "                                                                                                                                                                       int numPairs,\n"
+       "                                                                                                                                                                       int contactCapacity)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       int pairIndex = i;\n"
+       "       \n"
+       "       float4 worldVertsB1[64];\n"
+       "       float4 worldVertsB2[64];\n"
+       "       int capacityWorldVerts = 64;    \n"
+       "       float4 localContactsOut[64];\n"
+       "       int localContactCapacity=64;\n"
+       "       \n"
+       "       float minDist = -1e30f;\n"
+       "       float maxDist = 0.02f;\n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "               int bodyIndexA = pairs[i].x;\n"
+       "               int bodyIndexB = pairs[i].y;\n"
+       "                       \n"
+       "               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "               if (hasSeparatingAxis[i])\n"
+       "               {\n"
+       "                       \n"
+       "                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "                       \n"
+       "               \n"
+       "                       int numLocalContactsOut = clipHullAgainstHull(separatingNormals[i],\n"
+       "                                                                                                               &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
+       "                                                                                                               rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,\n"
+       "                                                                                                         rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,\n"
+       "                                                                                                         worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
+       "                                                                                                               minDist, maxDist,\n"
+       "                                                                                                               vertices,faces,indices,\n"
+       "                                                                                                               localContactsOut,localContactCapacity);\n"
+       "                                                                                               \n"
+       "               if (numLocalContactsOut>0)\n"
+       "               {\n"
+       "                               float4 normal = -separatingNormals[i];\n"
+       "                               int nPoints = numLocalContactsOut;\n"
+       "                               float4* pointsIn = localContactsOut;\n"
+       "                               int contactIdx[4];// = {-1,-1,-1,-1};\n"
+       "                               contactIdx[0] = -1;\n"
+       "                               contactIdx[1] = -1;\n"
+       "                               contactIdx[2] = -1;\n"
+       "                               contactIdx[3] = -1;\n"
+       "               \n"
+       "                               int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
+       "               \n"
+       "                               \n"
+       "                               int mprContactIndex = pairs[pairIndex].z;\n"
+       "                               int dstIdx = mprContactIndex;\n"
+       "                               if (dstIdx<0)\n"
+       "                               {\n"
+       "                                       AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "                               }\n"
+       "                               if (dstIdx<contactCapacity)\n"
+       "                               {\n"
+       "                                       pairs[pairIndex].z = dstIdx;\n"
+       "                                       __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
+       "                                       c->m_worldNormalOnB = -normal;\n"
+       "                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                                       c->m_batchIdx = pairIndex;\n"
+       "                                       int bodyA = pairs[pairIndex].x;\n"
+       "                                       int bodyB = pairs[pairIndex].y;\n"
+       "                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+       "                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+       "                                       c->m_childIndexA = -1;\n"
+       "                                       c->m_childIndexB = -1;\n"
+       "                                       for (int i=0;i<nReducedContacts;i++)\n"
+       "                                       {\n"
+       "                                       //this condition means: overwrite contact point, unless at index i==0 we have a valid 'mpr' contact\n"
+       "                                               if (i>0||(mprContactIndex<0))\n"
+       "                                               {\n"
+       "                                                       c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
+       "                                               }\n"
+       "                                       }\n"
+       "                                       GET_NPOINTS(*c) = nReducedContacts;\n"
+       "                               }\n"
+       "                               \n"
+       "                       }//             if (numContactsOut>0)\n"
+       "               }//             if (hasSeparatingAxis[i])\n"
+       "       }//     if (i<numPairs)\n"
+       "}\n"
+       "__kernel void   clipCompoundsHullHullKernel( __global const int4* gpuCompoundPairs, \n"
+       "                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, \n"
+       "                                                                                                                                                                       __global const b3Collidable_t* collidables,\n"
+       "                                                                                                                                                                       __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global const float4* uniqueEdges,\n"
+       "                                                                                                                                                                       __global const b3GpuFace_t* faces,\n"
+       "                                                                                                                                                                       __global const int* indices,\n"
+       "                                                                                                                                                                       __global const b3GpuChildShape_t* gpuChildShapes,\n"
+       "                                                                                                                                                                       __global const float4* gpuCompoundSepNormalsOut,\n"
+       "                                                                                                                                                                       __global const int* gpuHasCompoundSepNormalsOut,\n"
+       "                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                                                                                                                       counter32_t nGlobalContactsOut,\n"
+       "                                                                                                                                                                       int numCompoundPairs, int maxContactCapacity)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       int pairIndex = i;\n"
+       "       \n"
+       "       float4 worldVertsB1[64];\n"
+       "       float4 worldVertsB2[64];\n"
+       "       int capacityWorldVerts = 64;    \n"
+       "       float4 localContactsOut[64];\n"
+       "       int localContactCapacity=64;\n"
+       "       \n"
+       "       float minDist = -1e30f;\n"
+       "       float maxDist = 0.02f;\n"
+       "       if (i<numCompoundPairs)\n"
+       "       {\n"
+       "               if (gpuHasCompoundSepNormalsOut[i])\n"
+       "               {\n"
+       "                       int bodyIndexA = gpuCompoundPairs[i].x;\n"
+       "                       int bodyIndexB = gpuCompoundPairs[i].y;\n"
+       "                       \n"
+       "                       int childShapeIndexA = gpuCompoundPairs[i].z;\n"
+       "                       int childShapeIndexB = gpuCompoundPairs[i].w;\n"
+       "                       \n"
+       "                       int collidableIndexA = -1;\n"
+       "                       int collidableIndexB = -1;\n"
+       "                       \n"
+       "                       float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "                       float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "                       \n"
+       "                       float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+       "                       float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                                                               \n"
+       "                       if (childShapeIndexA >= 0)\n"
+       "                       {\n"
+       "                               collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+       "                               float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+       "                               float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+       "                               float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+       "                               float4 newOrnA = qtMul(ornA,childOrnA);\n"
+       "                               posA = newPosA;\n"
+       "                               ornA = newOrnA;\n"
+       "                       } else\n"
+       "                       {\n"
+       "                               collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "                       }\n"
+       "                       \n"
+       "                       if (childShapeIndexB>=0)\n"
+       "                       {\n"
+       "                               collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+       "                               float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+       "                               float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+       "                               float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+       "                               float4 newOrnB = qtMul(ornB,childOrnB);\n"
+       "                               posB = newPosB;\n"
+       "                               ornB = newOrnB;\n"
+       "                       } else\n"
+       "                       {\n"
+       "                               collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;     \n"
+       "                       }\n"
+       "                       \n"
+       "                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "               \n"
+       "                       int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],\n"
+       "                                                                                                               &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
+       "                                                                                                               posA,ornA,\n"
+       "                                                                                                         posB,ornB,\n"
+       "                                                                                                         worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
+       "                                                                                                               minDist, maxDist,\n"
+       "                                                                                                               vertices,faces,indices,\n"
+       "                                                                                                               localContactsOut,localContactCapacity);\n"
+       "                                                                                               \n"
+       "               if (numLocalContactsOut>0)\n"
+       "               {\n"
+       "                               float4 normal = -gpuCompoundSepNormalsOut[i];\n"
+       "                               int nPoints = numLocalContactsOut;\n"
+       "                               float4* pointsIn = localContactsOut;\n"
+       "                               int contactIdx[4];// = {-1,-1,-1,-1};\n"
+       "                               contactIdx[0] = -1;\n"
+       "                               contactIdx[1] = -1;\n"
+       "                               contactIdx[2] = -1;\n"
+       "                               contactIdx[3] = -1;\n"
+       "               \n"
+       "                               int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
+       "               \n"
+       "                               int dstIdx;\n"
+       "                               AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "                               if ((dstIdx+nReducedContacts) < maxContactCapacity)\n"
+       "                               {\n"
+       "                                       __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
+       "                                       c->m_worldNormalOnB = -normal;\n"
+       "                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                                       c->m_batchIdx = pairIndex;\n"
+       "                                       int bodyA = gpuCompoundPairs[pairIndex].x;\n"
+       "                                       int bodyB = gpuCompoundPairs[pairIndex].y;\n"
+       "                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+       "                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+       "                                       c->m_childIndexA = childShapeIndexA;\n"
+       "                                       c->m_childIndexB = childShapeIndexB;\n"
+       "                                       for (int i=0;i<nReducedContacts;i++)\n"
+       "                                       {\n"
+       "                                               c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
+       "                                       }\n"
+       "                                       GET_NPOINTS(*c) = nReducedContacts;\n"
+       "                               }\n"
+       "                               \n"
+       "                       }//             if (numContactsOut>0)\n"
+       "               }//             if (gpuHasCompoundSepNormalsOut[i])\n"
+       "       }//     if (i<numCompoundPairs)\n"
+       "}\n"
+       "__kernel void   sphereSphereCollisionKernel( __global const int4* pairs, \n"
+       "                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, \n"
+       "                                                                                                                                                                       __global const b3Collidable_t* collidables,\n"
+       "                                                                                                                                                                       __global const float4* separatingNormals,\n"
+       "                                                                                                                                                                       __global const int* hasSeparatingAxis,\n"
+       "                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                                                                                                                       counter32_t nGlobalContactsOut,\n"
+       "                                                                                                                                                                       int contactCapacity,\n"
+       "                                                                                                                                                                       int numPairs)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       int pairIndex = i;\n"
+       "       \n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "               int bodyIndexA = pairs[i].x;\n"
+       "               int bodyIndexB = pairs[i].y;\n"
+       "                       \n"
+       "               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "               if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
+       "                       collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
+       "               {\n"
+       "                       //sphere-sphere\n"
+       "                       float radiusA = collidables[collidableIndexA].m_radius;\n"
+       "                       float radiusB = collidables[collidableIndexB].m_radius;\n"
+       "                       float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "                       float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                       float4 diff = posA-posB;\n"
+       "                       float len = length(diff);\n"
+       "                       \n"
+       "                       ///iff distance positive, don't generate a new contact\n"
+       "                       if ( len <= (radiusA+radiusB))\n"
+       "                       {\n"
+       "                               ///distance (negative means penetration)\n"
+       "                               float dist = len - (radiusA+radiusB);\n"
+       "                               float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);\n"
+       "                               if (len > 0.00001)\n"
+       "                               {\n"
+       "                                       normalOnSurfaceB = diff / len;\n"
+       "                               }\n"
+       "                               float4 contactPosB = posB + normalOnSurfaceB*radiusB;\n"
+       "                               contactPosB.w = dist;\n"
+       "                                                               \n"
+       "                               int dstIdx;\n"
+       "                               AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "                               if (dstIdx < contactCapacity)\n"
+       "                               {\n"
+       "                                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+       "                                       c->m_worldNormalOnB = -normalOnSurfaceB;\n"
+       "                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                                       c->m_batchIdx = pairIndex;\n"
+       "                                       int bodyA = pairs[pairIndex].x;\n"
+       "                                       int bodyB = pairs[pairIndex].y;\n"
+       "                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+       "                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+       "                                       c->m_worldPosB[0] = contactPosB;\n"
+       "                                       c->m_childIndexA = -1;\n"
+       "                                       c->m_childIndexB = -1;\n"
+       "                                       GET_NPOINTS(*c) = 1;\n"
+       "                               }//if (dstIdx < numPairs)\n"
+       "                       }//if ( len <= (radiusA+radiusB))\n"
+       "               }//SHAPE_SPHERE SHAPE_SPHERE\n"
+       "       }//if (i<numPairs)\n"
+       "}                              \n"
+       "__kernel void   clipHullHullConcaveConvexKernel( __global int4* concavePairsIn,\n"
+       "                                                                                                                                                                       __global const b3RigidBodyData_t* rigidBodies, \n"
+       "                                                                                                                                                                       __global const b3Collidable_t* collidables,\n"
+       "                                                                                                                                                                       __global const b3ConvexPolyhedronData_t* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global const float4* uniqueEdges,\n"
+       "                                                                                                                                                                       __global const b3GpuFace_t* faces,\n"
+       "                                                                                                                                                                       __global const int* indices,\n"
+       "                                                                                                                                                                       __global const b3GpuChildShape_t* gpuChildShapes,\n"
+       "                                                                                                                                                                       __global const float4* separatingNormals,\n"
+       "                                                                                                                                                                       __global struct b3Contact4Data* restrict globalContactsOut,\n"
+       "                                                                                                                                                                       counter32_t nGlobalContactsOut,\n"
+       "                                                                                                                                                                       int contactCapacity,\n"
+       "                                                                                                                                                                       int numConcavePairs)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       int pairIndex = i;\n"
+       "       \n"
+       "       float4 worldVertsB1[64];\n"
+       "       float4 worldVertsB2[64];\n"
+       "       int capacityWorldVerts = 64;    \n"
+       "       float4 localContactsOut[64];\n"
+       "       int localContactCapacity=64;\n"
+       "       \n"
+       "       float minDist = -1e30f;\n"
+       "       float maxDist = 0.02f;\n"
+       "       if (i<numConcavePairs)\n"
+       "       {\n"
+       "               //negative value means that the pair is invalid\n"
+       "               if (concavePairsIn[i].w<0)\n"
+       "                       return;\n"
+       "               int bodyIndexA = concavePairsIn[i].x;\n"
+       "               int bodyIndexB = concavePairsIn[i].y;\n"
+       "               int f = concavePairsIn[i].z;\n"
+       "               int childShapeIndexA = f;\n"
+       "               \n"
+       "               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "               \n"
+       "               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "               \n"
+       "               ///////////////////////////////////////////////////////////////\n"
+       "               \n"
+       "       \n"
+       "               bool overlap = false;\n"
+       "               \n"
+       "               b3ConvexPolyhedronData_t convexPolyhedronA;\n"
+       "       //add 3 vertices of the triangle\n"
+       "               convexPolyhedronA.m_numVertices = 3;\n"
+       "               convexPolyhedronA.m_vertexOffset = 0;\n"
+       "               float4  localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+       "               b3GpuFace_t face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+       "               \n"
+       "               float4 verticesA[3];\n"
+       "               for (int i=0;i<3;i++)\n"
+       "               {\n"
+       "                       int index = indices[face.m_indexOffset+i];\n"
+       "                       float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+       "                       verticesA[i] = vert;\n"
+       "                       localCenter += vert;\n"
+       "               }\n"
+       "               float dmin = FLT_MAX;\n"
+       "               int localCC=0;\n"
+       "               //a triangle has 3 unique edges\n"
+       "               convexPolyhedronA.m_numUniqueEdges = 3;\n"
+       "               convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+       "               float4 uniqueEdgesA[3];\n"
+       "               \n"
+       "               uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+       "               uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+       "               uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+       "               convexPolyhedronA.m_faceOffset = 0;\n"
+       "                                  \n"
+       "               float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+       "                             \n"
+       "               b3GpuFace_t facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+       "               int indicesA[3+3+2+2+2];\n"
+       "               int curUsedIndices=0;\n"
+       "               int fidx=0;\n"
+       "               //front size of triangle\n"
+       "               {\n"
+       "                       facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                       indicesA[0] = 0;\n"
+       "                       indicesA[1] = 1;\n"
+       "                       indicesA[2] = 2;\n"
+       "                       curUsedIndices+=3;\n"
+       "                       float c = face.m_plane.w;\n"
+       "                       facesA[fidx].m_plane.x = normal.x;\n"
+       "                       facesA[fidx].m_plane.y = normal.y;\n"
+       "                       facesA[fidx].m_plane.z = normal.z;\n"
+       "                       facesA[fidx].m_plane.w = c;\n"
+       "                       facesA[fidx].m_numIndices=3;\n"
+       "               }\n"
+       "               fidx++;\n"
+       "               //back size of triangle\n"
+       "               {\n"
+       "                       facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                       indicesA[3]=2;\n"
+       "                       indicesA[4]=1;\n"
+       "                       indicesA[5]=0;\n"
+       "                       curUsedIndices+=3;\n"
+       "                       float c = dot3F4(normal,verticesA[0]);\n"
+       "                       float c1 = -face.m_plane.w;\n"
+       "                       facesA[fidx].m_plane.x = -normal.x;\n"
+       "                       facesA[fidx].m_plane.y = -normal.y;\n"
+       "                       facesA[fidx].m_plane.z = -normal.z;\n"
+       "                       facesA[fidx].m_plane.w = c;\n"
+       "                       facesA[fidx].m_numIndices=3;\n"
+       "               }\n"
+       "               fidx++;\n"
+       "               bool addEdgePlanes = true;\n"
+       "               if (addEdgePlanes)\n"
+       "               {\n"
+       "                       int numVertices=3;\n"
+       "                       int prevVertex = numVertices-1;\n"
+       "                       for (int i=0;i<numVertices;i++)\n"
+       "                       {\n"
+       "                               float4 v0 = verticesA[i];\n"
+       "                               float4 v1 = verticesA[prevVertex];\n"
+       "                                            \n"
+       "                               float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+       "                               float c = -dot3F4(edgeNormal,v0);\n"
+       "                               facesA[fidx].m_numIndices = 2;\n"
+       "                               facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                               indicesA[curUsedIndices++]=i;\n"
+       "                               indicesA[curUsedIndices++]=prevVertex;\n"
+       "                                            \n"
+       "                               facesA[fidx].m_plane.x = edgeNormal.x;\n"
+       "                               facesA[fidx].m_plane.y = edgeNormal.y;\n"
+       "                               facesA[fidx].m_plane.z = edgeNormal.z;\n"
+       "                               facesA[fidx].m_plane.w = c;\n"
+       "                               fidx++;\n"
+       "                               prevVertex = i;\n"
+       "                       }\n"
+       "               }\n"
+       "               convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+       "               convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+       "               float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "               posA.w = 0.f;\n"
+       "               float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "               posB.w = 0.f;\n"
+       "               float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "               float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+       "               float4 sepAxis = separatingNormals[i];\n"
+       "               \n"
+       "               int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+       "               int childShapeIndexB =-1;\n"
+       "               if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "               {\n"
+       "                       ///////////////////\n"
+       "                       ///compound shape support\n"
+       "                       \n"
+       "                       childShapeIndexB = concavePairsIn[pairIndex].w;\n"
+       "                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+       "                       shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+       "                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+       "                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+       "                       float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+       "                       float4 newOrnB = qtMul(ornB,childOrnB);\n"
+       "                       posB = newPosB;\n"
+       "                       ornB = newOrnB;\n"
+       "                       \n"
+       "               }\n"
+       "               \n"
+       "               ////////////////////////////////////////\n"
+       "               \n"
+       "               \n"
+       "               \n"
+       "               int numLocalContactsOut = clipHullAgainstHullLocalA(sepAxis,\n"
+       "                                                                                                               &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+       "                                                                                                               posA,ornA,\n"
+       "                                                                                                         posB,ornB,\n"
+       "                                                                                                         worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
+       "                                                                                                               minDist, maxDist,\n"
+       "                                                                                                               &verticesA,&facesA,&indicesA,\n"
+       "                                                                                                               vertices,faces,indices,\n"
+       "                                                                                                               localContactsOut,localContactCapacity);\n"
+       "                                                                                               \n"
+       "               if (numLocalContactsOut>0)\n"
+       "               {\n"
+       "                       float4 normal = -separatingNormals[i];\n"
+       "                       int nPoints = numLocalContactsOut;\n"
+       "                       float4* pointsIn = localContactsOut;\n"
+       "                       int contactIdx[4];// = {-1,-1,-1,-1};\n"
+       "                       contactIdx[0] = -1;\n"
+       "                       contactIdx[1] = -1;\n"
+       "                       contactIdx[2] = -1;\n"
+       "                       contactIdx[3] = -1;\n"
+       "       \n"
+       "                       int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
+       "       \n"
+       "                       int dstIdx;\n"
+       "                       AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "                       if (dstIdx<contactCapacity)\n"
+       "                       {\n"
+       "                               __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
+       "                               c->m_worldNormalOnB = -normal;\n"
+       "                               c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                               c->m_batchIdx = pairIndex;\n"
+       "                               int bodyA = concavePairsIn[pairIndex].x;\n"
+       "                               int bodyB = concavePairsIn[pairIndex].y;\n"
+       "                               c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+       "                               c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+       "                               c->m_childIndexA = childShapeIndexA;\n"
+       "                               c->m_childIndexB = childShapeIndexB;\n"
+       "                               for (int i=0;i<nReducedContacts;i++)\n"
+       "                               {\n"
+       "                                       c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
+       "                               }\n"
+       "                               GET_NPOINTS(*c) = nReducedContacts;\n"
+       "                       }\n"
+       "                               \n"
+       "               }//             if (numContactsOut>0)\n"
+       "       }//     if (i<numPairs)\n"
+       "}\n"
+       "int    findClippingFaces(const float4 separatingNormal,\n"
+       "                      __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,\n"
+       "                      const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
+       "                       __global float4* worldVertsA1,\n"
+       "                      __global float4* worldNormalsA1,\n"
+       "                      __global float4* worldVertsB1,\n"
+       "                      int capacityWorldVerts,\n"
+       "                      const float minDist, float maxDist,\n"
+       "                      __global const float4* vertices,\n"
+       "                      __global const b3GpuFace_t* faces,\n"
+       "                      __global const int* indices,\n"
+       "                      __global int4* clippingFaces, int pairIndex)\n"
+       "{\n"
+       "       int numContactsOut = 0;\n"
+       "       int numWorldVertsB1= 0;\n"
+       "    \n"
+       "    \n"
+       "       int closestFaceB=-1;\n"
+       "       float dmax = -FLT_MAX;\n"
+       "    \n"
+       "       {\n"
+       "               for(int face=0;face<hullB->m_numFaces;face++)\n"
+       "               {\n"
+       "                       const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x,\n"
+       "                                              faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+       "                       const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+       "                       float d = dot3F4(WorldNormal,separatingNormal);\n"
+       "                       if (d > dmax)\n"
+       "                       {\n"
+       "                               dmax = d;\n"
+       "                               closestFaceB = face;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "    \n"
+       "       {\n"
+       "               const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];\n"
+       "               const int numVertices = polyB.m_numIndices;\n"
+       "               for(int e0=0;e0<numVertices;e0++)\n"
+       "               {\n"
+       "                       const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];\n"
+       "                       worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+       "               }\n"
+       "       }\n"
+       "    \n"
+       "    int closestFaceA=-1;\n"
+       "       {\n"
+       "               float dmin = FLT_MAX;\n"
+       "               for(int face=0;face<hullA->m_numFaces;face++)\n"
+       "               {\n"
+       "                       const float4 Normal = make_float4(\n"
+       "                                              faces[hullA->m_faceOffset+face].m_plane.x,\n"
+       "                                              faces[hullA->m_faceOffset+face].m_plane.y,\n"
+       "                                              faces[hullA->m_faceOffset+face].m_plane.z,\n"
+       "                                              0.f);\n"
+       "                       const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+       "            \n"
+       "                       float d = dot3F4(faceANormalWS,separatingNormal);\n"
+       "                       if (d < dmin)\n"
+       "                       {\n"
+       "                               dmin = d;\n"
+       "                               closestFaceA = face;\n"
+       "                worldNormalsA1[pairIndex] = faceANormalWS;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "    \n"
+       "    int numVerticesA = faces[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
+       "       for(int e0=0;e0<numVerticesA;e0++)\n"
+       "       {\n"
+       "        const float4 a = vertices[hullA->m_vertexOffset+indices[faces[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
+       "        worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
+       "    }\n"
+       "    \n"
+       "    clippingFaces[pairIndex].x = closestFaceA;\n"
+       "    clippingFaces[pairIndex].y = closestFaceB;\n"
+       "    clippingFaces[pairIndex].z = numVerticesA;\n"
+       "    clippingFaces[pairIndex].w = numWorldVertsB1;\n"
+       "    \n"
+       "    \n"
+       "       return numContactsOut;\n"
+       "}\n"
+       "int clipFaces(__global float4* worldVertsA1,\n"
+       "              __global float4* worldNormalsA1,\n"
+       "              __global float4* worldVertsB1,\n"
+       "              __global float4* worldVertsB2, \n"
+       "              int capacityWorldVertsB2,\n"
+       "              const float minDist, float maxDist,\n"
+       "              __global int4* clippingFaces,\n"
+       "              int pairIndex)\n"
+       "{\n"
+       "       int numContactsOut = 0;\n"
+       "    \n"
+       "    int closestFaceA = clippingFaces[pairIndex].x;\n"
+       "    int closestFaceB = clippingFaces[pairIndex].y;\n"
+       "       int numVertsInA = clippingFaces[pairIndex].z;\n"
+       "       int numVertsInB = clippingFaces[pairIndex].w;\n"
+       "    \n"
+       "       int numVertsOut = 0;\n"
+       "    \n"
+       "       if (closestFaceA<0)\n"
+       "               return numContactsOut;\n"
+       "    \n"
+       "    __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];\n"
+       "    __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];\n"
+       "    \n"
+       "    \n"
+       "       \n"
+       "       // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+       "    \n"
+       "       for(int e0=0;e0<numVertsInA;e0++)\n"
+       "       {\n"
+       "               const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];\n"
+       "               const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];\n"
+       "               const float4 WorldEdge0 = aw - bw;\n"
+       "               float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];\n"
+       "               float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+       "               float4 worldA1 = aw;\n"
+       "               float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+       "               float4 planeNormalWS = planeNormalWS1;\n"
+       "               float planeEqWS=planeEqWS1;\n"
+       "               numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);\n"
+       "               __global float4* tmp = pVtxOut;\n"
+       "               pVtxOut = pVtxIn;\n"
+       "               pVtxIn = tmp;\n"
+       "               numVertsInB = numVertsOut;\n"
+       "               numVertsOut = 0;\n"
+       "       }\n"
+       "    \n"
+       "    //float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
+       "    //float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
+       "    \n"
+       "    /*for (int i=0;i<numVertsInB;i++)\n"
+       "    {\n"
+       "        pVtxOut[i] = pVtxIn[i];\n"
+       "    }*/\n"
+       "    \n"
+       "    \n"
+       "    \n"
+       "    \n"
+       "    //numVertsInB=0;\n"
+       "       \n"
+       "    float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
+       "    float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
+       "    for (int i=0;i<numVertsInB;i++)\n"
+       "    {\n"
+       "        float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+       "        if (depth <=minDist)\n"
+       "        {\n"
+       "            depth = minDist;\n"
+       "        }\n"
+       "        \n"
+       "        if (depth <=maxDist)\n"
+       "        {\n"
+       "            float4 pointInWorld = pVtxIn[i];\n"
+       "            pVtxOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+       "        }\n"
+       "    }\n"
+       "   \n"
+       "    clippingFaces[pairIndex].w =numContactsOut;\n"
+       "   \n"
+       "    \n"
+       "       return numContactsOut;\n"
+       "}\n"
+       "__kernel void   findClippingFacesKernel(  __global const int4* pairs,\n"
+       "                                        __global const b3RigidBodyData_t* rigidBodies,\n"
+       "                                        __global const b3Collidable_t* collidables,\n"
+       "                                        __global const b3ConvexPolyhedronData_t* convexShapes,\n"
+       "                                        __global const float4* vertices,\n"
+       "                                        __global const float4* uniqueEdges,\n"
+       "                                        __global const b3GpuFace_t* faces,\n"
+       "                                        __global const int* indices,\n"
+       "                                        __global const float4* separatingNormals,\n"
+       "                                        __global const int* hasSeparatingAxis,\n"
+       "                                        __global int4* clippingFacesOut,\n"
+       "                                        __global float4* worldVertsA1,\n"
+       "                                        __global float4* worldNormalsA1,\n"
+       "                                        __global float4* worldVertsB1,\n"
+       "                                        int capacityWorldVerts,\n"
+       "                                        int numPairs\n"
+       "                                        )\n"
+       "{\n"
+       "    \n"
+       "       int i = get_global_id(0);\n"
+       "       int pairIndex = i;\n"
+       "    \n"
+       "       \n"
+       "       float minDist = -1e30f;\n"
+       "       float maxDist = 0.02f;\n"
+       "    \n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "        \n"
+       "               if (hasSeparatingAxis[i])\n"
+       "               {\n"
+       "            \n"
+       "                       int bodyIndexA = pairs[i].x;\n"
+       "                       int bodyIndexB = pairs[i].y;\n"
+       "                       \n"
+       "                       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "                       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "                       \n"
+       "                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "                       \n"
+       "            \n"
+       "            \n"
+       "                       int numLocalContactsOut = findClippingFaces(separatingNormals[i],\n"
+       "                                                        &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
+       "                                                        rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,\n"
+       "                                                        rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,\n"
+       "                                                        worldVertsA1,\n"
+       "                                                        worldNormalsA1,\n"
+       "                                                        worldVertsB1,capacityWorldVerts,\n"
+       "                                                        minDist, maxDist,\n"
+       "                                                        vertices,faces,indices,\n"
+       "                                                        clippingFacesOut,i);\n"
+       "            \n"
+       "            \n"
+       "               }//             if (hasSeparatingAxis[i])\n"
+       "       }//     if (i<numPairs)\n"
+       "    \n"
+       "}\n"
+       "__kernel void   clipFacesAndFindContactsKernel(    __global const float4* separatingNormals,\n"
+       "                                                   __global const int* hasSeparatingAxis,\n"
+       "                                                   __global int4* clippingFacesOut,\n"
+       "                                                   __global float4* worldVertsA1,\n"
+       "                                                   __global float4* worldNormalsA1,\n"
+       "                                                   __global float4* worldVertsB1,\n"
+       "                                                   __global float4* worldVertsB2,\n"
+       "                                                    int vertexFaceCapacity,\n"
+       "                                                   int numPairs,\n"
+       "                                                                               int debugMode\n"
+       "                                                   )\n"
+       "{\n"
+       "    int i = get_global_id(0);\n"
+       "       int pairIndex = i;\n"
+       "       \n"
+       "    \n"
+       "       float minDist = -1e30f;\n"
+       "       float maxDist = 0.02f;\n"
+       "    \n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "        \n"
+       "               if (hasSeparatingAxis[i])\n"
+       "               {\n"
+       "            \n"
+       "//                     int bodyIndexA = pairs[i].x;\n"
+       "       //              int bodyIndexB = pairs[i].y;\n"
+       "                   \n"
+       "            int numLocalContactsOut = 0;\n"
+       "            int capacityWorldVertsB2 = vertexFaceCapacity;\n"
+       "            \n"
+       "            __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];\n"
+       "            __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];\n"
+       "            \n"
+       "            {\n"
+       "                __global int4* clippingFaces = clippingFacesOut;\n"
+       "            \n"
+       "                \n"
+       "                int closestFaceA = clippingFaces[pairIndex].x;\n"
+       "                int closestFaceB = clippingFaces[pairIndex].y;\n"
+       "                int numVertsInA = clippingFaces[pairIndex].z;\n"
+       "                int numVertsInB = clippingFaces[pairIndex].w;\n"
+       "                \n"
+       "                int numVertsOut = 0;\n"
+       "                \n"
+       "                if (closestFaceA>=0)\n"
+       "                {\n"
+       "                    \n"
+       "                    \n"
+       "                    \n"
+       "                    // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
+       "                    \n"
+       "                    for(int e0=0;e0<numVertsInA;e0++)\n"
+       "                    {\n"
+       "                        const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];\n"
+       "                        const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];\n"
+       "                        const float4 WorldEdge0 = aw - bw;\n"
+       "                        float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];\n"
+       "                        float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
+       "                        float4 worldA1 = aw;\n"
+       "                        float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
+       "                        float4 planeNormalWS = planeNormalWS1;\n"
+       "                        float planeEqWS=planeEqWS1;\n"
+       "                        numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);\n"
+       "                        __global float4* tmp = pVtxOut;\n"
+       "                        pVtxOut = pVtxIn;\n"
+       "                        pVtxIn = tmp;\n"
+       "                        numVertsInB = numVertsOut;\n"
+       "                        numVertsOut = 0;\n"
+       "                    }\n"
+       "                    \n"
+       "                    float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
+       "                    float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
+       "                    \n"
+       "                    for (int i=0;i<numVertsInB;i++)\n"
+       "                    {\n"
+       "                        float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
+       "                        if (depth <=minDist)\n"
+       "                        {\n"
+       "                            depth = minDist;\n"
+       "                        }\n"
+       "                        \n"
+       "                        if (depth <=maxDist)\n"
+       "                        {\n"
+       "                            float4 pointInWorld = pVtxIn[i];\n"
+       "                            pVtxOut[numLocalContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
+       "                        }\n"
+       "                    }\n"
+       "                    \n"
+       "                }\n"
+       "                clippingFaces[pairIndex].w =numLocalContactsOut;\n"
+       "                \n"
+       "            }\n"
+       "            \n"
+       "            for (int i=0;i<numLocalContactsOut;i++)\n"
+       "                pVtxIn[i] = pVtxOut[i];\n"
+       "                \n"
+       "               }//             if (hasSeparatingAxis[i])\n"
+       "       }//     if (i<numPairs)\n"
+       "    \n"
+       "}\n"
+       "__kernel void   newContactReductionKernel( __global int4* pairs,\n"
+       "                                                   __global const b3RigidBodyData_t* rigidBodies,\n"
+       "                                                   __global const float4* separatingNormals,\n"
+       "                                                   __global const int* hasSeparatingAxis,\n"
+       "                                                   __global struct b3Contact4Data* globalContactsOut,\n"
+       "                                                   __global int4* clippingFaces,\n"
+       "                                                   __global float4* worldVertsB2,\n"
+       "                                                   volatile __global int* nGlobalContactsOut,\n"
+       "                                                   int vertexFaceCapacity,\n"
+       "                                                                                                  int contactCapacity,\n"
+       "                                                   int numPairs\n"
+       "                                                   )\n"
+       "{\n"
+       "    int i = get_global_id(0);\n"
+       "       int pairIndex = i;\n"
+       "       \n"
+       "    int4 contactIdx;\n"
+       "    contactIdx=make_int4(0,1,2,3);\n"
+       "    \n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "        \n"
+       "               if (hasSeparatingAxis[i])\n"
+       "               {\n"
+       "            \n"
+       "                       \n"
+       "            \n"
+       "            \n"
+       "                       int nPoints = clippingFaces[pairIndex].w;\n"
+       "           \n"
+       "            if (nPoints>0)\n"
+       "            {\n"
+       "                 __global float4* pointsIn = &worldVertsB2[pairIndex*vertexFaceCapacity];\n"
+       "                float4 normal = -separatingNormals[i];\n"
+       "                \n"
+       "                int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);\n"
+       "            \n"
+       "                               int mprContactIndex = pairs[pairIndex].z;\n"
+       "                int dstIdx = mprContactIndex;\n"
+       "                               if (dstIdx<0)\n"
+       "                               {\n"
+       "                       AppendInc( nGlobalContactsOut, dstIdx );\n"
+       "                               }\n"
+       "//#if 0\n"
+       "                \n"
+       "                               if (dstIdx < contactCapacity)\n"
+       "                               {\n"
+       "                                       __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
+       "                                       c->m_worldNormalOnB = -normal;\n"
+       "                                       c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
+       "                                       c->m_batchIdx = pairIndex;\n"
+       "                                       int bodyA = pairs[pairIndex].x;\n"
+       "                                       int bodyB = pairs[pairIndex].y;\n"
+       "                                       pairs[pairIndex].w = dstIdx;\n"
+       "                                       c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
+       "                                       c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
+       "                    c->m_childIndexA =-1;\n"
+       "                                       c->m_childIndexB =-1;\n"
+       "                    switch (nReducedContacts)\n"
+       "                    {\n"
+       "                        case 4:\n"
+       "                            c->m_worldPosB[3] = pointsIn[contactIdx.w];\n"
+       "                        case 3:\n"
+       "                            c->m_worldPosB[2] = pointsIn[contactIdx.z];\n"
+       "                        case 2:\n"
+       "                            c->m_worldPosB[1] = pointsIn[contactIdx.y];\n"
+       "                        case 1:\n"
+       "                                                       if (mprContactIndex<0)//test\n"
+       "                                   c->m_worldPosB[0] = pointsIn[contactIdx.x];\n"
+       "                        default:\n"
+       "                        {\n"
+       "                        }\n"
+       "                    };\n"
+       "                    \n"
+       "                                       GET_NPOINTS(*c) = nReducedContacts;\n"
+       "                    \n"
+       "                 }\n"
+       "                 \n"
+       "                \n"
+       "//#endif\n"
+       "                               \n"
+       "                       }//             if (numContactsOut>0)\n"
+       "               }//             if (hasSeparatingAxis[i])\n"
+       "       }//     if (i<numPairs)\n"
+       "    \n"
+       "    \n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl
new file mode 100644 (file)
index 0000000..31ca43b
--- /dev/null
@@ -0,0 +1,1220 @@
+
+//keep this enum in sync with the CPU version (in btCollidable.h)
+//written by Erwin Coumans
+
+
+#define SHAPE_CONVEX_HULL 3
+#define SHAPE_CONCAVE_TRIMESH 5
+#define TRIANGLE_NUM_CONVEX_FACES 5
+#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
+
+#define B3_MAX_STACK_DEPTH 256
+
+
+typedef unsigned int u32;
+
+///keep this in sync with btCollidable.h
+typedef struct
+{
+       union {
+               int m_numChildShapes;
+               int m_bvhIndex;
+       };
+       union
+       {
+               float m_radius;
+               int     m_compoundBvhIndex;
+       };
+       
+       int m_shapeType;
+       int m_shapeIndex;
+       
+} btCollidableGpu;
+
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///b3QuantizedBvhNode 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).
+typedef struct
+{
+       //12 bytes
+       unsigned short int      m_quantizedAabbMin[3];
+       unsigned short int      m_quantizedAabbMax[3];
+       //4 bytes
+       int     m_escapeIndexOrTriangleIndex;
+} b3QuantizedBvhNode;
+
+typedef struct
+{
+       float4          m_aabbMin;
+       float4          m_aabbMax;
+       float4          m_quantization;
+       int                     m_numNodes;
+       int                     m_numSubTrees;
+       int                     m_nodeOffset;
+       int                     m_subTreeOffset;
+
+} b3BvhInfo;
+
+
+int    getTriangleIndex(const b3QuantizedBvhNode* rootNode)
+{
+       unsigned int x=0;
+       unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+       // Get only the lower bits where the triangle index is stored
+       return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+int    getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+       unsigned int x=0;
+       unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
+       // Get only the lower bits where the triangle index is stored
+       return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
+}
+
+int isLeafNode(const b3QuantizedBvhNode* rootNode)
+{
+       //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+       return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+
+int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+       //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+       return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
+}
+       
+int getEscapeIndex(const b3QuantizedBvhNode* rootNode)
+{
+       return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
+{
+       return -rootNode->m_escapeIndexOrTriangleIndex;
+}
+
+
+typedef struct
+{
+       //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];
+} b3BvhSubtreeInfo;
+
+
+
+
+
+
+
+typedef struct
+{
+       float4  m_childPosition;
+       float4  m_childOrientation;
+       int m_shapeIndex;
+       int m_unused0;
+       int m_unused1;
+       int m_unused2;
+} btGpuChildShape;
+
+
+typedef struct
+{
+       float4 m_pos;
+       float4 m_quat;
+       float4 m_linVel;
+       float4 m_angVel;
+
+       u32 m_collidableIdx;
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+} BodyData;
+
+
+typedef struct  
+{
+       float4          m_localCenter;
+       float4          m_extents;
+       float4          mC;
+       float4          mE;
+       
+       float                   m_radius;
+       int     m_faceOffset;
+       int m_numFaces;
+       int     m_numVertices;
+
+       int m_vertexOffset;
+       int     m_uniqueEdgesOffset;
+       int     m_numUniqueEdges;
+       int m_unused;
+} ConvexPolyhedronCL;
+
+typedef struct 
+{
+       union
+       {
+               float4  m_min;
+               float   m_minElems[4];
+               int                     m_minIndices[4];
+       };
+       union
+       {
+               float4  m_max;
+               float   m_maxElems[4];
+               int                     m_maxIndices[4];
+       };
+} btAabbCL;
+
+#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
+#include "Bullet3Common/shared/b3Int2.h"
+
+
+
+typedef struct
+{
+       float4 m_plane;
+       int m_indexOffset;
+       int m_numIndices;
+} btGpuFace;
+
+#define make_float4 (float4)
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+       return cross(a,b);
+
+       
+//     float4 a1 = make_float4(a.xyz,0.f);
+//     float4 b1 = make_float4(b.xyz,0.f);
+
+//     return cross(a1,b1);
+
+//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);
+       
+       //      float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);
+       
+       //return c;
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = make_float4(a.xyz,0.f);
+       float4 b1 = make_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+       v = make_float4(v.xyz,0.f);
+       return fast_normalize(v);
+}
+
+
+///////////////////////////////////////
+//     Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+       Quaternion ans;
+       ans = cross3( a, b );
+       ans += a.w*b+b.w*a;
+//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+       ans.w = a.w*b.w - dot3F4(a, b);
+       return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+       return fastNormalize4(in);
+//     in /= length( in );
+//     return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+       Quaternion qInv = qtInvert( q );
+       float4 vcpy = vec;
+       vcpy.w = 0.f;
+       float4 out = qtMul(qtMul(q,vcpy),qInv);
+       return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+       return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+       return qtRotate( qtInvert( q ), vec );
+}
+
+__inline
+float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
+{
+       return qtRotate( *orientation, *p ) + (*translation);
+}
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+       float4 n = make_float4(a.x, a.y, a.z, 0.f);
+       return fastNormalize4( n );
+}
+
+inline void projectLocal(const ConvexPolyhedronCL* hull,  const float4 pos, const float4 orn, 
+const float4* dir, const float4* vertices, float* min, float* max)
+{
+       min[0] = FLT_MAX;
+       max[0] = -FLT_MAX;
+       int numVerts = hull->m_numVertices;
+
+       const float4 localDir = qtInvRotate(orn,*dir);
+       float offset = dot(pos,*dir);
+       for(int i=0;i<numVerts;i++)
+       {
+               float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
+               if(dp < min[0]) 
+                       min[0] = dp;
+               if(dp > max[0]) 
+                       max[0] = dp;
+       }
+       if(min[0]>max[0])
+       {
+               float tmp = min[0];
+               min[0] = max[0];
+               max[0] = tmp;
+       }
+       min[0] += offset;
+       max[0] += offset;
+}
+
+inline void project(__global const ConvexPolyhedronCL* hull,  const float4 pos, const float4 orn, 
+const float4* dir, __global const float4* vertices, float* min, float* max)
+{
+       min[0] = FLT_MAX;
+       max[0] = -FLT_MAX;
+       int numVerts = hull->m_numVertices;
+
+       const float4 localDir = qtInvRotate(orn,*dir);
+       float offset = dot(pos,*dir);
+       for(int i=0;i<numVerts;i++)
+       {
+               float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
+               if(dp < min[0]) 
+                       min[0] = dp;
+               if(dp > max[0]) 
+                       max[0] = dp;
+       }
+       if(min[0]>max[0])
+       {
+               float tmp = min[0];
+               min[0] = max[0];
+               max[0] = tmp;
+       }
+       min[0] += offset;
+       max[0] += offset;
+}
+
+inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, 
+       const float4 posA,const float4 ornA,
+       const float4 posB,const float4 ornB,
+       float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)
+{
+       float Min0,Max0;
+       float Min1,Max1;
+       projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);
+       project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);
+
+       if(Max0<Min1 || Max1<Min0)
+               return false;
+
+       float d0 = Max0 - Min1;
+       float d1 = Max1 - Min0;
+       *depth = d0<d1 ? d0:d1;
+       return true;
+}
+
+
+
+
+inline bool IsAlmostZero(const float4 v)
+{
+       if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)
+               return false;
+       return true;
+}
+
+
+
+bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, 
+       const float4 posA1,
+       const float4 ornA,
+       const float4 posB1,
+       const float4 ornB,
+       const float4 DeltaC2,
+       
+       const float4* verticesA, 
+       const float4* uniqueEdgesA, 
+       const btGpuFace* facesA,
+       const int*  indicesA,
+
+       __global const float4* verticesB, 
+       __global const float4* uniqueEdgesB, 
+       __global const btGpuFace* facesB,
+       __global const int*  indicesB,
+       float4* sep,
+       float* dmin)
+{
+       
+
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+       int curPlaneTests=0;
+       {
+               int numFacesA = hullA->m_numFaces;
+               // Test normals from hullA
+               for(int i=0;i<numFacesA;i++)
+               {
+                       const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
+                       float4 faceANormalWS = qtRotate(ornA,normal);
+                       if (dot3F4(DeltaC2,faceANormalWS)<0)
+                               faceANormalWS*=-1.f;
+                       curPlaneTests++;
+                       float d;
+                       if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))
+                               return false;
+                       if(d<*dmin)
+                       {
+                               *dmin = d;
+                               *sep = faceANormalWS;
+                       }
+               }
+       }
+       if((dot3F4(-DeltaC2,*sep))>0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA,  const ConvexPolyhedronCL* hullB, 
+       const float4 posA1,
+       const float4 ornA,
+       const float4 posB1,
+       const float4 ornB,
+       const float4 DeltaC2,
+       __global const float4* verticesA, 
+       __global const float4* uniqueEdgesA, 
+       __global const btGpuFace* facesA,
+       __global const int*  indicesA,
+       const float4* verticesB,
+       const float4* uniqueEdgesB, 
+       const btGpuFace* facesB,
+       const int*  indicesB,
+       float4* sep,
+       float* dmin)
+{
+
+
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+       int curPlaneTests=0;
+       {
+               int numFacesA = hullA->m_numFaces;
+               // Test normals from hullA
+               for(int i=0;i<numFacesA;i++)
+               {
+                       const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
+                       float4 faceANormalWS = qtRotate(ornA,normal);
+                       if (dot3F4(DeltaC2,faceANormalWS)<0)
+                               faceANormalWS *= -1.f;
+                       curPlaneTests++;
+                       float d;
+                       if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))
+                               return false;
+                       if(d<*dmin)
+                       {
+                               *dmin = d;
+                               *sep = faceANormalWS;
+                       }
+               }
+       }
+       if((dot3F4(-DeltaC2,*sep))>0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+
+
+bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, 
+       const float4 posA1,
+       const float4 ornA,
+       const float4 posB1,
+       const float4 ornB,
+       const float4 DeltaC2,
+       const float4* verticesA, 
+       const float4* uniqueEdgesA, 
+       const btGpuFace* facesA,
+       const int*  indicesA,
+       __global const float4* verticesB, 
+       __global const float4* uniqueEdgesB, 
+       __global const btGpuFace* facesB,
+       __global const int*  indicesB,
+               float4* sep,
+       float* dmin)
+{
+
+
+       float4 posA = posA1;
+       posA.w = 0.f;
+       float4 posB = posB1;
+       posB.w = 0.f;
+
+       int curPlaneTests=0;
+
+       int curEdgeEdge = 0;
+       // Test edges
+       for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
+       {
+               const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];
+               float4 edge0World = qtRotate(ornA,edge0);
+
+               for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
+               {
+                       const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];
+                       float4 edge1World = qtRotate(ornB,edge1);
+
+
+                       float4 crossje = cross3(edge0World,edge1World);
+
+                       curEdgeEdge++;
+                       if(!IsAlmostZero(crossje))
+                       {
+                               crossje = normalize3(crossje);
+                               if (dot3F4(DeltaC2,crossje)<0)
+                                       crossje *= -1.f;
+
+                               float dist;
+                               bool result = true;
+                               {
+                                       float Min0,Max0;
+                                       float Min1,Max1;
+                                       projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);
+                                       project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);
+                               
+                                       if(Max0<Min1 || Max1<Min0)
+                                               result = false;
+                               
+                                       float d0 = Max0 - Min1;
+                                       float d1 = Max1 - Min0;
+                                       dist = d0<d1 ? d0:d1;
+                                       result = true;
+
+                               }
+                               
+
+                               if(dist<*dmin)
+                               {
+                                       *dmin = dist;
+                                       *sep = crossje;
+                               }
+                       }
+               }
+
+       }
+
+       
+       if((dot3F4(-DeltaC2,*sep))>0.0f)
+       {
+               *sep = -(*sep);
+       }
+       return true;
+}
+
+
+
+inline int     findClippingFaces(const float4 separatingNormal,
+                      const ConvexPolyhedronCL* hullA, 
+                                         __global const ConvexPolyhedronCL* hullB,
+                      const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
+                       __global float4* worldVertsA1,
+                      __global float4* worldNormalsA1,
+                      __global float4* worldVertsB1,
+                      int capacityWorldVerts,
+                      const float minDist, float maxDist,
+                                         const float4* verticesA,
+                      const btGpuFace* facesA,
+                      const int* indicesA,
+                                         __global const float4* verticesB,
+                      __global const btGpuFace* facesB,
+                      __global const int* indicesB,
+                      __global int4* clippingFaces, int pairIndex)
+{
+       int numContactsOut = 0;
+       int numWorldVertsB1= 0;
+    
+    
+       int closestFaceB=0;
+       float dmax = -FLT_MAX;
+    
+       {
+               for(int face=0;face<hullB->m_numFaces;face++)
+               {
+                       const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,
+                                              facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
+                       const float4 WorldNormal = qtRotate(ornB, Normal);
+                       float d = dot3F4(WorldNormal,separatingNormal);
+                       if (d > dmax)
+                       {
+                               dmax = d;
+                               closestFaceB = face;
+                       }
+               }
+       }
+    
+       {
+               const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];
+               int numVertices = polyB.m_numIndices;
+        if (numVertices>capacityWorldVerts)
+            numVertices = capacityWorldVerts;
+        if (numVertices<0)
+            numVertices = 0;
+        
+               for(int e0=0;e0<numVertices;e0++)
+               {
+            if (e0<capacityWorldVerts)
+            {
+                const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
+                worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);
+            }
+               }
+       }
+    
+    int closestFaceA=0;
+       {
+               float dmin = FLT_MAX;
+               for(int face=0;face<hullA->m_numFaces;face++)
+               {
+                       const float4 Normal = make_float4(
+                                              facesA[hullA->m_faceOffset+face].m_plane.x,
+                                              facesA[hullA->m_faceOffset+face].m_plane.y,
+                                              facesA[hullA->m_faceOffset+face].m_plane.z,
+                                              0.f);
+                       const float4 faceANormalWS = qtRotate(ornA,Normal);
+            
+                       float d = dot3F4(faceANormalWS,separatingNormal);
+                       if (d < dmin)
+                       {
+                               dmin = d;
+                               closestFaceA = face;
+                worldNormalsA1[pairIndex] = faceANormalWS;
+                       }
+               }
+       }
+    
+    int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;
+    if (numVerticesA>capacityWorldVerts)
+       numVerticesA = capacityWorldVerts;
+    if (numVerticesA<0)
+        numVerticesA=0;
+    
+       for(int e0=0;e0<numVerticesA;e0++)
+       {
+        if (e0<capacityWorldVerts)
+        {
+            const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
+            worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);
+        }
+    }
+    
+    clippingFaces[pairIndex].x = closestFaceA;
+    clippingFaces[pairIndex].y = closestFaceB;
+    clippingFaces[pairIndex].z = numVerticesA;
+    clippingFaces[pairIndex].w = numWorldVertsB1;
+    
+    
+       return numContactsOut;
+}
+
+
+
+
+// work-in-progress
+__kernel void   findConcaveSeparatingAxisVertexFaceKernel( __global int4* concavePairs,
+                                                __global const BodyData* rigidBodies,
+                                                __global const btCollidableGpu* collidables,
+                                                __global const ConvexPolyhedronCL* convexShapes,
+                                                __global const float4* vertices,
+                                                __global const float4* uniqueEdges,
+                                                __global const btGpuFace* faces,
+                                                __global const int* indices,
+                                                __global const btGpuChildShape* gpuChildShapes,
+                                                __global btAabbCL* aabbs,
+                                                __global float4* concaveSeparatingNormalsOut,
+                                                __global int* concaveHasSeparatingNormals,
+                                                __global int4* clippingFacesOut,
+                                                __global float4* worldVertsA1GPU,
+                                                __global float4*  worldNormalsAGPU,
+                                                __global float4* worldVertsB1GPU,
+                                                __global float* dmins,
+                                                int vertexFaceCapacity,
+                                                int numConcavePairs
+                                                )
+{
+    
+       int i = get_global_id(0);
+       if (i>=numConcavePairs)
+               return;
+    
+       concaveHasSeparatingNormals[i] = 0;
+    
+       int pairIdx = i;
+    
+       int bodyIndexA = concavePairs[i].x;
+       int bodyIndexB = concavePairs[i].y;
+    
+       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+    
+       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+    
+       if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&
+               collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)
+       {
+               concavePairs[pairIdx].w = -1;
+               return;
+       }
+    
+    
+    
+       int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+       int numActualConcaveConvexTests = 0;
+       
+       int f = concavePairs[i].z;
+       
+       bool overlap = false;
+       
+       ConvexPolyhedronCL convexPolyhedronA;
+    
+       //add 3 vertices of the triangle
+       convexPolyhedronA.m_numVertices = 3;
+       convexPolyhedronA.m_vertexOffset = 0;
+       float4  localCenter = make_float4(0.f,0.f,0.f,0.f);
+    
+       btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+       float4 triMinAabb, triMaxAabb;
+       btAabbCL triAabb;
+       triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);
+       triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);
+       
+       float4 verticesA[3];
+       for (int i=0;i<3;i++)
+       {
+               int index = indices[face.m_indexOffset+i];
+               float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+               verticesA[i] = vert;
+               localCenter += vert;
+        
+               triAabb.m_min = min(triAabb.m_min,vert);
+               triAabb.m_max = max(triAabb.m_max,vert);
+        
+       }
+    
+       overlap = true;
+       overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;
+       overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;
+       overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;
+    
+       if (overlap)
+       {
+               float dmin = FLT_MAX;
+               int hasSeparatingAxis=5;
+               float4 sepAxis=make_float4(1,2,3,4);
+        
+               int localCC=0;
+               numActualConcaveConvexTests++;
+        
+               //a triangle has 3 unique edges
+               convexPolyhedronA.m_numUniqueEdges = 3;
+               convexPolyhedronA.m_uniqueEdgesOffset = 0;
+               float4 uniqueEdgesA[3];
+               
+               uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
+               uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
+               uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
+        
+        
+               convexPolyhedronA.m_faceOffset = 0;
+        
+               float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+        
+               btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];
+               int indicesA[3+3+2+2+2];
+               int curUsedIndices=0;
+               int fidx=0;
+        
+               //front size of triangle
+               {
+                       facesA[fidx].m_indexOffset=curUsedIndices;
+                       indicesA[0] = 0;
+                       indicesA[1] = 1;
+                       indicesA[2] = 2;
+                       curUsedIndices+=3;
+                       float c = face.m_plane.w;
+                       facesA[fidx].m_plane.x = normal.x;
+                       facesA[fidx].m_plane.y = normal.y;
+                       facesA[fidx].m_plane.z = normal.z;
+                       facesA[fidx].m_plane.w = c;
+                       facesA[fidx].m_numIndices=3;
+               }
+               fidx++;
+               //back size of triangle
+               {
+                       facesA[fidx].m_indexOffset=curUsedIndices;
+                       indicesA[3]=2;
+                       indicesA[4]=1;
+                       indicesA[5]=0;
+                       curUsedIndices+=3;
+                       float c = dot(normal,verticesA[0]);
+                       float c1 = -face.m_plane.w;
+                       facesA[fidx].m_plane.x = -normal.x;
+                       facesA[fidx].m_plane.y = -normal.y;
+                       facesA[fidx].m_plane.z = -normal.z;
+                       facesA[fidx].m_plane.w = c;
+                       facesA[fidx].m_numIndices=3;
+               }
+               fidx++;
+        
+               bool addEdgePlanes = true;
+               if (addEdgePlanes)
+               {
+                       int numVertices=3;
+                       int prevVertex = numVertices-1;
+                       for (int i=0;i<numVertices;i++)
+                       {
+                               float4 v0 = verticesA[i];
+                               float4 v1 = verticesA[prevVertex];
+                
+                               float4 edgeNormal = normalize(cross(normal,v1-v0));
+                               float c = -dot(edgeNormal,v0);
+                
+                               facesA[fidx].m_numIndices = 2;
+                               facesA[fidx].m_indexOffset=curUsedIndices;
+                               indicesA[curUsedIndices++]=i;
+                               indicesA[curUsedIndices++]=prevVertex;
+                
+                               facesA[fidx].m_plane.x = edgeNormal.x;
+                               facesA[fidx].m_plane.y = edgeNormal.y;
+                               facesA[fidx].m_plane.z = edgeNormal.z;
+                               facesA[fidx].m_plane.w = c;
+                               fidx++;
+                               prevVertex = i;
+                       }
+               }
+               convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
+               convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
+        
+        
+               float4 posA = rigidBodies[bodyIndexA].m_pos;
+               posA.w = 0.f;
+               float4 posB = rigidBodies[bodyIndexB].m_pos;
+               posB.w = 0.f;
+        
+               float4 ornA = rigidBodies[bodyIndexA].m_quat;
+               float4 ornB =rigidBodies[bodyIndexB].m_quat;
+        
+               
+        
+        
+               ///////////////////
+               ///compound shape support
+        
+               if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+               {
+                       int compoundChild = concavePairs[pairIdx].w;
+                       int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
+                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                       float4 newPosB = transform(&childPosB,&posB,&ornB);
+                       float4 newOrnB = qtMul(ornB,childOrnB);
+                       posB = newPosB;
+                       ornB = newOrnB;
+                       shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+               }
+               //////////////////
+        
+               float4 c0local = convexPolyhedronA.m_localCenter;
+               float4 c0 = transform(&c0local, &posA, &ornA);
+               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+               float4 c1 = transform(&c1local,&posB,&ornB);
+               const float4 DeltaC2 = c0 - c1;
+        
+        
+               bool sepA = findSeparatingAxisLocalA(   &convexPolyhedronA, &convexShapes[shapeIndexB],
+                                             posA,ornA,
+                                             posB,ornB,
+                                             DeltaC2,
+                                             verticesA,uniqueEdgesA,facesA,indicesA,
+                                             vertices,uniqueEdges,faces,indices,
+                                             &sepAxis,&dmin);
+               hasSeparatingAxis = 4;
+               if (!sepA)
+               {
+                       hasSeparatingAxis = 0;
+               } else
+               {
+                       bool sepB = findSeparatingAxisLocalB(   &convexShapes[shapeIndexB],&convexPolyhedronA,
+                                                 posB,ornB,
+                                                 posA,ornA,
+                                                 DeltaC2,
+                                                 vertices,uniqueEdges,faces,indices,
+                                                 verticesA,uniqueEdgesA,facesA,indicesA,
+                                                 &sepAxis,&dmin);
+            
+                       if (!sepB)
+                       {
+                               hasSeparatingAxis = 0;
+                       } else
+                       {
+                               hasSeparatingAxis = 1;
+                       }
+               }       
+               
+               if (hasSeparatingAxis)
+               {
+            dmins[i] = dmin;
+                       concaveSeparatingNormalsOut[pairIdx]=sepAxis;
+                       concaveHasSeparatingNormals[i]=1;
+            
+               } else
+               {       
+                       //mark this pair as in-active
+                       concavePairs[pairIdx].w = -1;
+               }
+       }
+       else
+       {       
+               //mark this pair as in-active
+               concavePairs[pairIdx].w = -1;
+       }
+}
+
+
+
+
+// work-in-progress
+__kernel void   findConcaveSeparatingAxisEdgeEdgeKernel( __global int4* concavePairs,
+                                                          __global const BodyData* rigidBodies,
+                                                          __global const btCollidableGpu* collidables,
+                                                          __global const ConvexPolyhedronCL* convexShapes,
+                                                          __global const float4* vertices,
+                                                          __global const float4* uniqueEdges,
+                                                          __global const btGpuFace* faces,
+                                                          __global const int* indices,
+                                                          __global const btGpuChildShape* gpuChildShapes,
+                                                          __global btAabbCL* aabbs,
+                                                          __global float4* concaveSeparatingNormalsOut,
+                                                          __global int* concaveHasSeparatingNormals,
+                                                          __global int4* clippingFacesOut,
+                                                          __global float4* worldVertsA1GPU,
+                                                          __global float4*  worldNormalsAGPU,
+                                                          __global float4* worldVertsB1GPU,
+                                                          __global float* dmins,
+                                                          int vertexFaceCapacity,
+                                                          int numConcavePairs
+                                                          )
+{
+    
+       int i = get_global_id(0);
+       if (i>=numConcavePairs)
+               return;
+    
+       if (!concaveHasSeparatingNormals[i])
+        return;
+    
+       int pairIdx = i;
+    
+       int bodyIndexA = concavePairs[i].x;
+       int bodyIndexB = concavePairs[i].y;
+    
+       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
+       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
+    
+       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
+       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
+    
+    
+       int numFacesA = convexShapes[shapeIndexA].m_numFaces;
+       int numActualConcaveConvexTests = 0;
+       
+       int f = concavePairs[i].z;
+       
+       bool overlap = false;
+       
+       ConvexPolyhedronCL convexPolyhedronA;
+    
+       //add 3 vertices of the triangle
+       convexPolyhedronA.m_numVertices = 3;
+       convexPolyhedronA.m_vertexOffset = 0;
+       float4  localCenter = make_float4(0.f,0.f,0.f,0.f);
+    
+       btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
+       float4 triMinAabb, triMaxAabb;
+       btAabbCL triAabb;
+       triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);
+       triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);
+       
+       float4 verticesA[3];
+       for (int i=0;i<3;i++)
+       {
+               int index = indices[face.m_indexOffset+i];
+               float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
+               verticesA[i] = vert;
+               localCenter += vert;
+        
+               triAabb.m_min = min(triAabb.m_min,vert);
+               triAabb.m_max = max(triAabb.m_max,vert);
+        
+       }
+    
+       overlap = true;
+       overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;
+       overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;
+       overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;
+    
+       if (overlap)
+       {
+               float dmin = dmins[i];
+               int hasSeparatingAxis=5;
+               float4 sepAxis=make_float4(1,2,3,4);
+        sepAxis = concaveSeparatingNormalsOut[pairIdx];
+        
+               int localCC=0;
+               numActualConcaveConvexTests++;
+        
+               //a triangle has 3 unique edges
+               convexPolyhedronA.m_numUniqueEdges = 3;
+               convexPolyhedronA.m_uniqueEdgesOffset = 0;
+               float4 uniqueEdgesA[3];
+               
+               uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
+               uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
+               uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
+        
+        
+               convexPolyhedronA.m_faceOffset = 0;
+        
+               float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
+        
+               btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];
+               int indicesA[3+3+2+2+2];
+               int curUsedIndices=0;
+               int fidx=0;
+        
+               //front size of triangle
+               {
+                       facesA[fidx].m_indexOffset=curUsedIndices;
+                       indicesA[0] = 0;
+                       indicesA[1] = 1;
+                       indicesA[2] = 2;
+                       curUsedIndices+=3;
+                       float c = face.m_plane.w;
+                       facesA[fidx].m_plane.x = normal.x;
+                       facesA[fidx].m_plane.y = normal.y;
+                       facesA[fidx].m_plane.z = normal.z;
+                       facesA[fidx].m_plane.w = c;
+                       facesA[fidx].m_numIndices=3;
+               }
+               fidx++;
+               //back size of triangle
+               {
+                       facesA[fidx].m_indexOffset=curUsedIndices;
+                       indicesA[3]=2;
+                       indicesA[4]=1;
+                       indicesA[5]=0;
+                       curUsedIndices+=3;
+                       float c = dot(normal,verticesA[0]);
+                       float c1 = -face.m_plane.w;
+                       facesA[fidx].m_plane.x = -normal.x;
+                       facesA[fidx].m_plane.y = -normal.y;
+                       facesA[fidx].m_plane.z = -normal.z;
+                       facesA[fidx].m_plane.w = c;
+                       facesA[fidx].m_numIndices=3;
+               }
+               fidx++;
+        
+               bool addEdgePlanes = true;
+               if (addEdgePlanes)
+               {
+                       int numVertices=3;
+                       int prevVertex = numVertices-1;
+                       for (int i=0;i<numVertices;i++)
+                       {
+                               float4 v0 = verticesA[i];
+                               float4 v1 = verticesA[prevVertex];
+                
+                               float4 edgeNormal = normalize(cross(normal,v1-v0));
+                               float c = -dot(edgeNormal,v0);
+                
+                               facesA[fidx].m_numIndices = 2;
+                               facesA[fidx].m_indexOffset=curUsedIndices;
+                               indicesA[curUsedIndices++]=i;
+                               indicesA[curUsedIndices++]=prevVertex;
+                
+                               facesA[fidx].m_plane.x = edgeNormal.x;
+                               facesA[fidx].m_plane.y = edgeNormal.y;
+                               facesA[fidx].m_plane.z = edgeNormal.z;
+                               facesA[fidx].m_plane.w = c;
+                               fidx++;
+                               prevVertex = i;
+                       }
+               }
+               convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
+               convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
+        
+        
+               float4 posA = rigidBodies[bodyIndexA].m_pos;
+               posA.w = 0.f;
+               float4 posB = rigidBodies[bodyIndexB].m_pos;
+               posB.w = 0.f;
+        
+               float4 ornA = rigidBodies[bodyIndexA].m_quat;
+               float4 ornB =rigidBodies[bodyIndexB].m_quat;
+        
+               
+        
+        
+               ///////////////////
+               ///compound shape support
+        
+               if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
+               {
+                       int compoundChild = concavePairs[pairIdx].w;
+                       int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
+                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
+                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
+                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
+                       float4 newPosB = transform(&childPosB,&posB,&ornB);
+                       float4 newOrnB = qtMul(ornB,childOrnB);
+                       posB = newPosB;
+                       ornB = newOrnB;
+                       shapeIndexB = collidables[childColIndexB].m_shapeIndex;
+               }
+               //////////////////
+        
+               float4 c0local = convexPolyhedronA.m_localCenter;
+               float4 c0 = transform(&c0local, &posA, &ornA);
+               float4 c1local = convexShapes[shapeIndexB].m_localCenter;
+               float4 c1 = transform(&c1local,&posB,&ornB);
+               const float4 DeltaC2 = c0 - c1;
+        
+        
+               {
+                       bool sepEE = findSeparatingAxisEdgeEdgeLocalA(  &convexPolyhedronA, &convexShapes[shapeIndexB],
+                                                              posA,ornA,
+                                                              posB,ornB,
+                                                              DeltaC2,
+                                                              verticesA,uniqueEdgesA,facesA,indicesA,
+                                                              vertices,uniqueEdges,faces,indices,
+                                                              &sepAxis,&dmin);
+                
+                       if (!sepEE)
+                       {
+                               hasSeparatingAxis = 0;
+                       } else
+                       {
+                               hasSeparatingAxis = 1;
+                       }
+               }
+               
+               
+               if (hasSeparatingAxis)
+               {
+                       sepAxis.w = dmin;
+            dmins[i] = dmin;
+                       concaveSeparatingNormalsOut[pairIdx]=sepAxis;
+                       concaveHasSeparatingNormals[i]=1;
+           
+       float minDist = -1e30f;
+                       float maxDist = 0.02f;
+
+            
+            findClippingFaces(sepAxis,
+                              &convexPolyhedronA,
+                              &convexShapes[shapeIndexB],
+                              posA,ornA,
+                              posB,ornB,
+                              worldVertsA1GPU,
+                              worldNormalsAGPU,
+                              worldVertsB1GPU,
+                              vertexFaceCapacity,
+                              minDist, maxDist,
+                              verticesA,
+                              facesA,
+                              indicesA,
+                              vertices,
+                              faces,
+                              indices,
+                              clippingFacesOut, pairIdx);
+                  
+            
+               } else
+               {       
+                       //mark this pair as in-active
+                       concavePairs[pairIdx].w = -1;
+               }
+       }
+       else
+       {       
+               //mark this pair as in-active
+               concavePairs[pairIdx].w = -1;
+       }
+       
+       concavePairs[i].z = -1;//for the next stage, z is used to determine existing contact points
+}
+
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h
new file mode 100644 (file)
index 0000000..a60702c
--- /dev/null
@@ -0,0 +1,1456 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* satConcaveKernelsCL =
+       "//keep this enum in sync with the CPU version (in btCollidable.h)\n"
+       "//written by Erwin Coumans\n"
+       "#define SHAPE_CONVEX_HULL 3\n"
+       "#define SHAPE_CONCAVE_TRIMESH 5\n"
+       "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+       "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+       "#define B3_MAX_STACK_DEPTH 256\n"
+       "typedef unsigned int u32;\n"
+       "///keep this in sync with btCollidable.h\n"
+       "typedef struct\n"
+       "{\n"
+       "       union {\n"
+       "               int m_numChildShapes;\n"
+       "               int m_bvhIndex;\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float m_radius;\n"
+       "               int     m_compoundBvhIndex;\n"
+       "       };\n"
+       "       \n"
+       "       int m_shapeType;\n"
+       "       int m_shapeIndex;\n"
+       "       \n"
+       "} btCollidableGpu;\n"
+       "#define MAX_NUM_PARTS_IN_BITS 10\n"
+       "///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
+       "///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
+       "typedef struct\n"
+       "{\n"
+       "       //12 bytes\n"
+       "       unsigned short int      m_quantizedAabbMin[3];\n"
+       "       unsigned short int      m_quantizedAabbMax[3];\n"
+       "       //4 bytes\n"
+       "       int     m_escapeIndexOrTriangleIndex;\n"
+       "} b3QuantizedBvhNode;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4          m_aabbMin;\n"
+       "       float4          m_aabbMax;\n"
+       "       float4          m_quantization;\n"
+       "       int                     m_numNodes;\n"
+       "       int                     m_numSubTrees;\n"
+       "       int                     m_nodeOffset;\n"
+       "       int                     m_subTreeOffset;\n"
+       "} b3BvhInfo;\n"
+       "int    getTriangleIndex(const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       unsigned int x=0;\n"
+       "       unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+       "       // Get only the lower bits where the triangle index is stored\n"
+       "       return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+       "}\n"
+       "int    getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       unsigned int x=0;\n"
+       "       unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+       "       // Get only the lower bits where the triangle index is stored\n"
+       "       return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+       "}\n"
+       "int isLeafNode(const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+       "       return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+       "}\n"
+       "int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+       "       return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+       "}\n"
+       "       \n"
+       "int getEscapeIndex(const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+       "}\n"
+       "int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+       "}\n"
+       "typedef struct\n"
+       "{\n"
+       "       //12 bytes\n"
+       "       unsigned short int      m_quantizedAabbMin[3];\n"
+       "       unsigned short int      m_quantizedAabbMax[3];\n"
+       "       //4 bytes, points to the root of the subtree\n"
+       "       int                     m_rootNodeIndex;\n"
+       "       //4 bytes\n"
+       "       int                     m_subtreeSize;\n"
+       "       int                     m_padding[3];\n"
+       "} b3BvhSubtreeInfo;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4  m_childPosition;\n"
+       "       float4  m_childOrientation;\n"
+       "       int m_shapeIndex;\n"
+       "       int m_unused0;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "} btGpuChildShape;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_pos;\n"
+       "       float4 m_quat;\n"
+       "       float4 m_linVel;\n"
+       "       float4 m_angVel;\n"
+       "       u32 m_collidableIdx;\n"
+       "       float m_invMass;\n"
+       "       float m_restituitionCoeff;\n"
+       "       float m_frictionCoeff;\n"
+       "} BodyData;\n"
+       "typedef struct  \n"
+       "{\n"
+       "       float4          m_localCenter;\n"
+       "       float4          m_extents;\n"
+       "       float4          mC;\n"
+       "       float4          mE;\n"
+       "       \n"
+       "       float                   m_radius;\n"
+       "       int     m_faceOffset;\n"
+       "       int m_numFaces;\n"
+       "       int     m_numVertices;\n"
+       "       int m_vertexOffset;\n"
+       "       int     m_uniqueEdgesOffset;\n"
+       "       int     m_numUniqueEdges;\n"
+       "       int m_unused;\n"
+       "} ConvexPolyhedronCL;\n"
+       "typedef struct \n"
+       "{\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_min;\n"
+       "               float   m_minElems[4];\n"
+       "               int                     m_minIndices[4];\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_max;\n"
+       "               float   m_maxElems[4];\n"
+       "               int                     m_maxIndices[4];\n"
+       "       };\n"
+       "} btAabbCL;\n"
+       "#ifndef B3_AABB_H\n"
+       "#define B3_AABB_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_MAT3x3_H\n"
+       "#define B3_MAT3x3_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#define B3_QUAT_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Quat;\n"
+       "       #define b3QuatConstArg const b3Quat\n"
+       "       \n"
+       "       \n"
+       "inline float4 b3FastNormalize4(float4 v)\n"
+       "{\n"
+       "       v = (float4)(v.xyz,0.f);\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "       \n"
+       "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+       "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+       "{\n"
+       "       b3Quat ans;\n"
+       "       ans = b3Cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+       "{\n"
+       "       b3Quat q;\n"
+       "       q=in;\n"
+       "       //return b3FastNormalize4(in);\n"
+       "       float len = native_sqrt(dot(q, q));\n"
+       "       if(len > 0.f)\n"
+       "       {\n"
+       "               q *= 1.f / len;\n"
+       "       }\n"
+       "       else\n"
+       "       {\n"
+       "               q.x = q.y = q.z = 0.f;\n"
+       "               q.w = 1.f;\n"
+       "       }\n"
+       "       return q;\n"
+       "}\n"
+       "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       b3Quat qInv = b3QuatInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+       "}\n"
+       "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg  orientation)\n"
+       "{\n"
+       "       return b3QuatRotate( orientation, point ) + (translation);\n"
+       "}\n"
+       "       \n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "typedef struct\n"
+       "{\n"
+       "       b3Float4 m_row[3];\n"
+       "}b3Mat3x3;\n"
+       "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+       "#define b3GetRow(m,row) (m.m_row[row])\n"
+       "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+       "{\n"
+       "       b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+       "       out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+       "       out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+       "       out.m_row[0].w = 0.f;\n"
+       "       out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+       "       out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+       "       out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+       "       out.m_row[1].w = 0.f;\n"
+       "       out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+       "       out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+       "       out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+       "       out.m_row[2].w = 0.f;\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = fabs(matIn.m_row[0]);\n"
+       "       out.m_row[1] = fabs(matIn.m_row[1]);\n"
+       "       out.m_row[2] = fabs(matIn.m_row[2]);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero();\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity();\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(0.f);\n"
+       "       m.m_row[1] = (b3Float4)(0.f);\n"
+       "       m.m_row[2] = (b3Float4)(0.f);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+       "       m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+       "       m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+       "       out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+       "       out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Mat3x3 transB;\n"
+       "       transB = mtTranspose( b );\n"
+       "       b3Mat3x3 ans;\n"
+       "       //      why this doesn't run when 0ing in the for{}\n"
+       "       a.m_row[0].w = 0.f;\n"
+       "       a.m_row[1].w = 0.f;\n"
+       "       a.m_row[2].w = 0.f;\n"
+       "       for(int i=0; i<3; i++)\n"
+       "       {\n"
+       "//     a.m_row[i].w = 0.f;\n"
+       "               ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+       "               ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+       "               ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+       "               ans.m_row[i].w = 0.f;\n"
+       "       }\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+       "{\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a.m_row[0], b );\n"
+       "       ans.y = b3Dot3F4( a.m_row[1], b );\n"
+       "       ans.z = b3Dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a, colx );\n"
+       "       ans.y = b3Dot3F4( a, coly );\n"
+       "       ans.z = b3Dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "#endif\n"
+       "#endif //B3_MAT3x3_H\n"
+       "typedef struct b3Aabb b3Aabb_t;\n"
+       "struct b3Aabb\n"
+       "{\n"
+       "       union\n"
+       "       {\n"
+       "               float m_min[4];\n"
+       "               b3Float4 m_minVec;\n"
+       "               int m_minIndices[4];\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float   m_max[4];\n"
+       "               b3Float4 m_maxVec;\n"
+       "               int m_signedMaxIndices[4];\n"
+       "       };\n"
+       "};\n"
+       "inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
+       "                                               b3Float4ConstArg pos,\n"
+       "                                               b3QuatConstArg orn,\n"
+       "                                               b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
+       "{\n"
+       "               b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
+       "               localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
+       "               b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
+       "               b3Mat3x3 m;\n"
+       "               m = b3QuatGetRotationMatrix(orn);\n"
+       "               b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
+       "               b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
+       "               \n"
+       "               b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
+       "                                                                                b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
+       "                                                                                b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
+       "                                                                                0.f);\n"
+       "               *aabbMinOut = center-extent;\n"
+       "               *aabbMaxOut = center+extent;\n"
+       "}\n"
+       "/// conservative test for overlap between two aabbs\n"
+       "inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
+       "                                                               b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
+       "{\n"
+       "       bool overlap = true;\n"
+       "       overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
+       "       overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
+       "       overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
+       "       return overlap;\n"
+       "}\n"
+       "#endif //B3_AABB_H\n"
+       "/*\n"
+       "Bullet Continuous Collision Detection and Physics Library\n"
+       "Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org\n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose,\n"
+       "including commercial applications, and to alter it and redistribute it freely,\n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "#ifndef B3_INT2_H\n"
+       "#define B3_INT2_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#define b3UnsignedInt2 uint2\n"
+       "#define b3Int2 int2\n"
+       "#define b3MakeInt2 (int2)\n"
+       "#endif //__cplusplus\n"
+       "#endif\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_plane;\n"
+       "       int m_indexOffset;\n"
+       "       int m_numIndices;\n"
+       "} btGpuFace;\n"
+       "#define make_float4 (float4)\n"
+       "__inline\n"
+       "float4 cross3(float4 a, float4 b)\n"
+       "{\n"
+       "       return cross(a,b);\n"
+       "       \n"
+       "//     float4 a1 = make_float4(a.xyz,0.f);\n"
+       "//     float4 b1 = make_float4(b.xyz,0.f);\n"
+       "//     return cross(a1,b1);\n"
+       "//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);\n"
+       "       \n"
+       "       //      float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);\n"
+       "       \n"
+       "       //return c;\n"
+       "}\n"
+       "__inline\n"
+       "float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = make_float4(a.xyz,0.f);\n"
+       "       float4 b1 = make_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "float4 fastNormalize4(float4 v)\n"
+       "{\n"
+       "       v = make_float4(v.xyz,0.f);\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Quaternion\n"
+       "///////////////////////////////////////\n"
+       "typedef float4 Quaternion;\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in);\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec);\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q);\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+       "{\n"
+       "       Quaternion ans;\n"
+       "       ans = cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in)\n"
+       "{\n"
+       "       return fastNormalize4(in);\n"
+       "//     in /= length( in );\n"
+       "//     return in;\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec)\n"
+       "{\n"
+       "       Quaternion qInv = qtInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q)\n"
+       "{\n"
+       "       return (Quaternion)(-q.xyz, q.w);\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+       "{\n"
+       "       return qtRotate( qtInvert( q ), vec );\n"
+       "}\n"
+       "__inline\n"
+       "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+       "{\n"
+       "       return qtRotate( *orientation, *p ) + (*translation);\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize3(const float4 a)\n"
+       "{\n"
+       "       float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+       "       return fastNormalize4( n );\n"
+       "}\n"
+       "inline void projectLocal(const ConvexPolyhedronCL* hull,  const float4 pos, const float4 orn, \n"
+       "const float4* dir, const float4* vertices, float* min, float* max)\n"
+       "{\n"
+       "       min[0] = FLT_MAX;\n"
+       "       max[0] = -FLT_MAX;\n"
+       "       int numVerts = hull->m_numVertices;\n"
+       "       const float4 localDir = qtInvRotate(orn,*dir);\n"
+       "       float offset = dot(pos,*dir);\n"
+       "       for(int i=0;i<numVerts;i++)\n"
+       "       {\n"
+       "               float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+       "               if(dp < min[0]) \n"
+       "                       min[0] = dp;\n"
+       "               if(dp > max[0]) \n"
+       "                       max[0] = dp;\n"
+       "       }\n"
+       "       if(min[0]>max[0])\n"
+       "       {\n"
+       "               float tmp = min[0];\n"
+       "               min[0] = max[0];\n"
+       "               max[0] = tmp;\n"
+       "       }\n"
+       "       min[0] += offset;\n"
+       "       max[0] += offset;\n"
+       "}\n"
+       "inline void project(__global const ConvexPolyhedronCL* hull,  const float4 pos, const float4 orn, \n"
+       "const float4* dir, __global const float4* vertices, float* min, float* max)\n"
+       "{\n"
+       "       min[0] = FLT_MAX;\n"
+       "       max[0] = -FLT_MAX;\n"
+       "       int numVerts = hull->m_numVertices;\n"
+       "       const float4 localDir = qtInvRotate(orn,*dir);\n"
+       "       float offset = dot(pos,*dir);\n"
+       "       for(int i=0;i<numVerts;i++)\n"
+       "       {\n"
+       "               float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+       "               if(dp < min[0]) \n"
+       "                       min[0] = dp;\n"
+       "               if(dp > max[0]) \n"
+       "                       max[0] = dp;\n"
+       "       }\n"
+       "       if(min[0]>max[0])\n"
+       "       {\n"
+       "               float tmp = min[0];\n"
+       "               min[0] = max[0];\n"
+       "               max[0] = tmp;\n"
+       "       }\n"
+       "       min[0] += offset;\n"
+       "       max[0] += offset;\n"
+       "}\n"
+       "inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA,const float4 ornA,\n"
+       "       const float4 posB,const float4 ornB,\n"
+       "       float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)\n"
+       "{\n"
+       "       float Min0,Max0;\n"
+       "       float Min1,Max1;\n"
+       "       projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);\n"
+       "       project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);\n"
+       "       if(Max0<Min1 || Max1<Min0)\n"
+       "               return false;\n"
+       "       float d0 = Max0 - Min1;\n"
+       "       float d1 = Max1 - Min0;\n"
+       "       *depth = d0<d1 ? d0:d1;\n"
+       "       return true;\n"
+       "}\n"
+       "inline bool IsAlmostZero(const float4 v)\n"
+       "{\n"
+       "       if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)\n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA1,\n"
+       "       const float4 ornA,\n"
+       "       const float4 posB1,\n"
+       "       const float4 ornB,\n"
+       "       const float4 DeltaC2,\n"
+       "       \n"
+       "       const float4* verticesA, \n"
+       "       const float4* uniqueEdgesA, \n"
+       "       const btGpuFace* facesA,\n"
+       "       const int*  indicesA,\n"
+       "       __global const float4* verticesB, \n"
+       "       __global const float4* uniqueEdgesB, \n"
+       "       __global const btGpuFace* facesB,\n"
+       "       __global const int*  indicesB,\n"
+       "       float4* sep,\n"
+       "       float* dmin)\n"
+       "{\n"
+       "       \n"
+       "       float4 posA = posA1;\n"
+       "       posA.w = 0.f;\n"
+       "       float4 posB = posB1;\n"
+       "       posB.w = 0.f;\n"
+       "       int curPlaneTests=0;\n"
+       "       {\n"
+       "               int numFacesA = hullA->m_numFaces;\n"
+       "               // Test normals from hullA\n"
+       "               for(int i=0;i<numFacesA;i++)\n"
+       "               {\n"
+       "                       const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+       "                       float4 faceANormalWS = qtRotate(ornA,normal);\n"
+       "                       if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+       "                               faceANormalWS*=-1.f;\n"
+       "                       curPlaneTests++;\n"
+       "                       float d;\n"
+       "                       if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))\n"
+       "                               return false;\n"
+       "                       if(d<*dmin)\n"
+       "                       {\n"
+       "                               *dmin = d;\n"
+       "                               *sep = faceANormalWS;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+       "       {\n"
+       "               *sep = -(*sep);\n"
+       "       }\n"
+       "       return true;\n"
+       "}\n"
+       "bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA,  const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA1,\n"
+       "       const float4 ornA,\n"
+       "       const float4 posB1,\n"
+       "       const float4 ornB,\n"
+       "       const float4 DeltaC2,\n"
+       "       __global const float4* verticesA, \n"
+       "       __global const float4* uniqueEdgesA, \n"
+       "       __global const btGpuFace* facesA,\n"
+       "       __global const int*  indicesA,\n"
+       "       const float4* verticesB,\n"
+       "       const float4* uniqueEdgesB, \n"
+       "       const btGpuFace* facesB,\n"
+       "       const int*  indicesB,\n"
+       "       float4* sep,\n"
+       "       float* dmin)\n"
+       "{\n"
+       "       float4 posA = posA1;\n"
+       "       posA.w = 0.f;\n"
+       "       float4 posB = posB1;\n"
+       "       posB.w = 0.f;\n"
+       "       int curPlaneTests=0;\n"
+       "       {\n"
+       "               int numFacesA = hullA->m_numFaces;\n"
+       "               // Test normals from hullA\n"
+       "               for(int i=0;i<numFacesA;i++)\n"
+       "               {\n"
+       "                       const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+       "                       float4 faceANormalWS = qtRotate(ornA,normal);\n"
+       "                       if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+       "                               faceANormalWS *= -1.f;\n"
+       "                       curPlaneTests++;\n"
+       "                       float d;\n"
+       "                       if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))\n"
+       "                               return false;\n"
+       "                       if(d<*dmin)\n"
+       "                       {\n"
+       "                               *dmin = d;\n"
+       "                               *sep = faceANormalWS;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+       "       {\n"
+       "               *sep = -(*sep);\n"
+       "       }\n"
+       "       return true;\n"
+       "}\n"
+       "bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA1,\n"
+       "       const float4 ornA,\n"
+       "       const float4 posB1,\n"
+       "       const float4 ornB,\n"
+       "       const float4 DeltaC2,\n"
+       "       const float4* verticesA, \n"
+       "       const float4* uniqueEdgesA, \n"
+       "       const btGpuFace* facesA,\n"
+       "       const int*  indicesA,\n"
+       "       __global const float4* verticesB, \n"
+       "       __global const float4* uniqueEdgesB, \n"
+       "       __global const btGpuFace* facesB,\n"
+       "       __global const int*  indicesB,\n"
+       "               float4* sep,\n"
+       "       float* dmin)\n"
+       "{\n"
+       "       float4 posA = posA1;\n"
+       "       posA.w = 0.f;\n"
+       "       float4 posB = posB1;\n"
+       "       posB.w = 0.f;\n"
+       "       int curPlaneTests=0;\n"
+       "       int curEdgeEdge = 0;\n"
+       "       // Test edges\n"
+       "       for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
+       "       {\n"
+       "               const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];\n"
+       "               float4 edge0World = qtRotate(ornA,edge0);\n"
+       "               for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
+       "               {\n"
+       "                       const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];\n"
+       "                       float4 edge1World = qtRotate(ornB,edge1);\n"
+       "                       float4 crossje = cross3(edge0World,edge1World);\n"
+       "                       curEdgeEdge++;\n"
+       "                       if(!IsAlmostZero(crossje))\n"
+       "                       {\n"
+       "                               crossje = normalize3(crossje);\n"
+       "                               if (dot3F4(DeltaC2,crossje)<0)\n"
+       "                                       crossje *= -1.f;\n"
+       "                               float dist;\n"
+       "                               bool result = true;\n"
+       "                               {\n"
+       "                                       float Min0,Max0;\n"
+       "                                       float Min1,Max1;\n"
+       "                                       projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);\n"
+       "                                       project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);\n"
+       "                               \n"
+       "                                       if(Max0<Min1 || Max1<Min0)\n"
+       "                                               result = false;\n"
+       "                               \n"
+       "                                       float d0 = Max0 - Min1;\n"
+       "                                       float d1 = Max1 - Min0;\n"
+       "                                       dist = d0<d1 ? d0:d1;\n"
+       "                                       result = true;\n"
+       "                               }\n"
+       "                               \n"
+       "                               if(dist<*dmin)\n"
+       "                               {\n"
+       "                                       *dmin = dist;\n"
+       "                                       *sep = crossje;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       \n"
+       "       if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+       "       {\n"
+       "               *sep = -(*sep);\n"
+       "       }\n"
+       "       return true;\n"
+       "}\n"
+       "inline int     findClippingFaces(const float4 separatingNormal,\n"
+       "                      const ConvexPolyhedronCL* hullA, \n"
+       "                                         __global const ConvexPolyhedronCL* hullB,\n"
+       "                      const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
+       "                       __global float4* worldVertsA1,\n"
+       "                      __global float4* worldNormalsA1,\n"
+       "                      __global float4* worldVertsB1,\n"
+       "                      int capacityWorldVerts,\n"
+       "                      const float minDist, float maxDist,\n"
+       "                                         const float4* verticesA,\n"
+       "                      const btGpuFace* facesA,\n"
+       "                      const int* indicesA,\n"
+       "                                         __global const float4* verticesB,\n"
+       "                      __global const btGpuFace* facesB,\n"
+       "                      __global const int* indicesB,\n"
+       "                      __global int4* clippingFaces, int pairIndex)\n"
+       "{\n"
+       "       int numContactsOut = 0;\n"
+       "       int numWorldVertsB1= 0;\n"
+       "    \n"
+       "    \n"
+       "       int closestFaceB=0;\n"
+       "       float dmax = -FLT_MAX;\n"
+       "    \n"
+       "       {\n"
+       "               for(int face=0;face<hullB->m_numFaces;face++)\n"
+       "               {\n"
+       "                       const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,\n"
+       "                                              facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+       "                       const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+       "                       float d = dot3F4(WorldNormal,separatingNormal);\n"
+       "                       if (d > dmax)\n"
+       "                       {\n"
+       "                               dmax = d;\n"
+       "                               closestFaceB = face;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "    \n"
+       "       {\n"
+       "               const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
+       "               int numVertices = polyB.m_numIndices;\n"
+       "        if (numVertices>capacityWorldVerts)\n"
+       "            numVertices = capacityWorldVerts;\n"
+       "        if (numVertices<0)\n"
+       "            numVertices = 0;\n"
+       "        \n"
+       "               for(int e0=0;e0<numVertices;e0++)\n"
+       "               {\n"
+       "            if (e0<capacityWorldVerts)\n"
+       "            {\n"
+       "                const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
+       "                worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+       "            }\n"
+       "               }\n"
+       "       }\n"
+       "    \n"
+       "    int closestFaceA=0;\n"
+       "       {\n"
+       "               float dmin = FLT_MAX;\n"
+       "               for(int face=0;face<hullA->m_numFaces;face++)\n"
+       "               {\n"
+       "                       const float4 Normal = make_float4(\n"
+       "                                              facesA[hullA->m_faceOffset+face].m_plane.x,\n"
+       "                                              facesA[hullA->m_faceOffset+face].m_plane.y,\n"
+       "                                              facesA[hullA->m_faceOffset+face].m_plane.z,\n"
+       "                                              0.f);\n"
+       "                       const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+       "            \n"
+       "                       float d = dot3F4(faceANormalWS,separatingNormal);\n"
+       "                       if (d < dmin)\n"
+       "                       {\n"
+       "                               dmin = d;\n"
+       "                               closestFaceA = face;\n"
+       "                worldNormalsA1[pairIndex] = faceANormalWS;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "    \n"
+       "    int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
+       "    if (numVerticesA>capacityWorldVerts)\n"
+       "       numVerticesA = capacityWorldVerts;\n"
+       "    if (numVerticesA<0)\n"
+       "        numVerticesA=0;\n"
+       "    \n"
+       "       for(int e0=0;e0<numVerticesA;e0++)\n"
+       "       {\n"
+       "        if (e0<capacityWorldVerts)\n"
+       "        {\n"
+       "            const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
+       "            worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
+       "        }\n"
+       "    }\n"
+       "    \n"
+       "    clippingFaces[pairIndex].x = closestFaceA;\n"
+       "    clippingFaces[pairIndex].y = closestFaceB;\n"
+       "    clippingFaces[pairIndex].z = numVerticesA;\n"
+       "    clippingFaces[pairIndex].w = numWorldVertsB1;\n"
+       "    \n"
+       "    \n"
+       "       return numContactsOut;\n"
+       "}\n"
+       "// work-in-progress\n"
+       "__kernel void   findConcaveSeparatingAxisVertexFaceKernel( __global int4* concavePairs,\n"
+       "                                                __global const BodyData* rigidBodies,\n"
+       "                                                __global const btCollidableGpu* collidables,\n"
+       "                                                __global const ConvexPolyhedronCL* convexShapes,\n"
+       "                                                __global const float4* vertices,\n"
+       "                                                __global const float4* uniqueEdges,\n"
+       "                                                __global const btGpuFace* faces,\n"
+       "                                                __global const int* indices,\n"
+       "                                                __global const btGpuChildShape* gpuChildShapes,\n"
+       "                                                __global btAabbCL* aabbs,\n"
+       "                                                __global float4* concaveSeparatingNormalsOut,\n"
+       "                                                __global int* concaveHasSeparatingNormals,\n"
+       "                                                __global int4* clippingFacesOut,\n"
+       "                                                __global float4* worldVertsA1GPU,\n"
+       "                                                __global float4*  worldNormalsAGPU,\n"
+       "                                                __global float4* worldVertsB1GPU,\n"
+       "                                                __global float* dmins,\n"
+       "                                                int vertexFaceCapacity,\n"
+       "                                                int numConcavePairs\n"
+       "                                                )\n"
+       "{\n"
+       "    \n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numConcavePairs)\n"
+       "               return;\n"
+       "    \n"
+       "       concaveHasSeparatingNormals[i] = 0;\n"
+       "    \n"
+       "       int pairIdx = i;\n"
+       "    \n"
+       "       int bodyIndexA = concavePairs[i].x;\n"
+       "       int bodyIndexB = concavePairs[i].y;\n"
+       "    \n"
+       "       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "    \n"
+       "       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "    \n"
+       "       if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&\n"
+       "               collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "       {\n"
+       "               concavePairs[pairIdx].w = -1;\n"
+       "               return;\n"
+       "       }\n"
+       "    \n"
+       "    \n"
+       "    \n"
+       "       int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "       int numActualConcaveConvexTests = 0;\n"
+       "       \n"
+       "       int f = concavePairs[i].z;\n"
+       "       \n"
+       "       bool overlap = false;\n"
+       "       \n"
+       "       ConvexPolyhedronCL convexPolyhedronA;\n"
+       "    \n"
+       "       //add 3 vertices of the triangle\n"
+       "       convexPolyhedronA.m_numVertices = 3;\n"
+       "       convexPolyhedronA.m_vertexOffset = 0;\n"
+       "       float4  localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+       "    \n"
+       "       btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+       "       float4 triMinAabb, triMaxAabb;\n"
+       "       btAabbCL triAabb;\n"
+       "       triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
+       "       triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
+       "       \n"
+       "       float4 verticesA[3];\n"
+       "       for (int i=0;i<3;i++)\n"
+       "       {\n"
+       "               int index = indices[face.m_indexOffset+i];\n"
+       "               float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+       "               verticesA[i] = vert;\n"
+       "               localCenter += vert;\n"
+       "        \n"
+       "               triAabb.m_min = min(triAabb.m_min,vert);\n"
+       "               triAabb.m_max = max(triAabb.m_max,vert);\n"
+       "        \n"
+       "       }\n"
+       "    \n"
+       "       overlap = true;\n"
+       "       overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
+       "       overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
+       "       overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
+       "    \n"
+       "       if (overlap)\n"
+       "       {\n"
+       "               float dmin = FLT_MAX;\n"
+       "               int hasSeparatingAxis=5;\n"
+       "               float4 sepAxis=make_float4(1,2,3,4);\n"
+       "        \n"
+       "               int localCC=0;\n"
+       "               numActualConcaveConvexTests++;\n"
+       "        \n"
+       "               //a triangle has 3 unique edges\n"
+       "               convexPolyhedronA.m_numUniqueEdges = 3;\n"
+       "               convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+       "               float4 uniqueEdgesA[3];\n"
+       "               \n"
+       "               uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+       "               uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+       "               uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+       "        \n"
+       "        \n"
+       "               convexPolyhedronA.m_faceOffset = 0;\n"
+       "        \n"
+       "               float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+       "        \n"
+       "               btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+       "               int indicesA[3+3+2+2+2];\n"
+       "               int curUsedIndices=0;\n"
+       "               int fidx=0;\n"
+       "        \n"
+       "               //front size of triangle\n"
+       "               {\n"
+       "                       facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                       indicesA[0] = 0;\n"
+       "                       indicesA[1] = 1;\n"
+       "                       indicesA[2] = 2;\n"
+       "                       curUsedIndices+=3;\n"
+       "                       float c = face.m_plane.w;\n"
+       "                       facesA[fidx].m_plane.x = normal.x;\n"
+       "                       facesA[fidx].m_plane.y = normal.y;\n"
+       "                       facesA[fidx].m_plane.z = normal.z;\n"
+       "                       facesA[fidx].m_plane.w = c;\n"
+       "                       facesA[fidx].m_numIndices=3;\n"
+       "               }\n"
+       "               fidx++;\n"
+       "               //back size of triangle\n"
+       "               {\n"
+       "                       facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                       indicesA[3]=2;\n"
+       "                       indicesA[4]=1;\n"
+       "                       indicesA[5]=0;\n"
+       "                       curUsedIndices+=3;\n"
+       "                       float c = dot(normal,verticesA[0]);\n"
+       "                       float c1 = -face.m_plane.w;\n"
+       "                       facesA[fidx].m_plane.x = -normal.x;\n"
+       "                       facesA[fidx].m_plane.y = -normal.y;\n"
+       "                       facesA[fidx].m_plane.z = -normal.z;\n"
+       "                       facesA[fidx].m_plane.w = c;\n"
+       "                       facesA[fidx].m_numIndices=3;\n"
+       "               }\n"
+       "               fidx++;\n"
+       "        \n"
+       "               bool addEdgePlanes = true;\n"
+       "               if (addEdgePlanes)\n"
+       "               {\n"
+       "                       int numVertices=3;\n"
+       "                       int prevVertex = numVertices-1;\n"
+       "                       for (int i=0;i<numVertices;i++)\n"
+       "                       {\n"
+       "                               float4 v0 = verticesA[i];\n"
+       "                               float4 v1 = verticesA[prevVertex];\n"
+       "                \n"
+       "                               float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+       "                               float c = -dot(edgeNormal,v0);\n"
+       "                \n"
+       "                               facesA[fidx].m_numIndices = 2;\n"
+       "                               facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                               indicesA[curUsedIndices++]=i;\n"
+       "                               indicesA[curUsedIndices++]=prevVertex;\n"
+       "                \n"
+       "                               facesA[fidx].m_plane.x = edgeNormal.x;\n"
+       "                               facesA[fidx].m_plane.y = edgeNormal.y;\n"
+       "                               facesA[fidx].m_plane.z = edgeNormal.z;\n"
+       "                               facesA[fidx].m_plane.w = c;\n"
+       "                               fidx++;\n"
+       "                               prevVertex = i;\n"
+       "                       }\n"
+       "               }\n"
+       "               convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+       "               convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+       "        \n"
+       "        \n"
+       "               float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "               posA.w = 0.f;\n"
+       "               float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "               posB.w = 0.f;\n"
+       "        \n"
+       "               float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "               float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+       "        \n"
+       "               \n"
+       "        \n"
+       "        \n"
+       "               ///////////////////\n"
+       "               ///compound shape support\n"
+       "        \n"
+       "               if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "               {\n"
+       "                       int compoundChild = concavePairs[pairIdx].w;\n"
+       "                       int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
+       "                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+       "                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+       "                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+       "                       float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+       "                       float4 newOrnB = qtMul(ornB,childOrnB);\n"
+       "                       posB = newPosB;\n"
+       "                       ornB = newOrnB;\n"
+       "                       shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+       "               }\n"
+       "               //////////////////\n"
+       "        \n"
+       "               float4 c0local = convexPolyhedronA.m_localCenter;\n"
+       "               float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "               float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "               float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "               const float4 DeltaC2 = c0 - c1;\n"
+       "        \n"
+       "        \n"
+       "               bool sepA = findSeparatingAxisLocalA(   &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+       "                                             posA,ornA,\n"
+       "                                             posB,ornB,\n"
+       "                                             DeltaC2,\n"
+       "                                             verticesA,uniqueEdgesA,facesA,indicesA,\n"
+       "                                             vertices,uniqueEdges,faces,indices,\n"
+       "                                             &sepAxis,&dmin);\n"
+       "               hasSeparatingAxis = 4;\n"
+       "               if (!sepA)\n"
+       "               {\n"
+       "                       hasSeparatingAxis = 0;\n"
+       "               } else\n"
+       "               {\n"
+       "                       bool sepB = findSeparatingAxisLocalB(   &convexShapes[shapeIndexB],&convexPolyhedronA,\n"
+       "                                                 posB,ornB,\n"
+       "                                                 posA,ornA,\n"
+       "                                                 DeltaC2,\n"
+       "                                                 vertices,uniqueEdges,faces,indices,\n"
+       "                                                 verticesA,uniqueEdgesA,facesA,indicesA,\n"
+       "                                                 &sepAxis,&dmin);\n"
+       "            \n"
+       "                       if (!sepB)\n"
+       "                       {\n"
+       "                               hasSeparatingAxis = 0;\n"
+       "                       } else\n"
+       "                       {\n"
+       "                               hasSeparatingAxis = 1;\n"
+       "                       }\n"
+       "               }       \n"
+       "               \n"
+       "               if (hasSeparatingAxis)\n"
+       "               {\n"
+       "            dmins[i] = dmin;\n"
+       "                       concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
+       "                       concaveHasSeparatingNormals[i]=1;\n"
+       "            \n"
+       "               } else\n"
+       "               {       \n"
+       "                       //mark this pair as in-active\n"
+       "                       concavePairs[pairIdx].w = -1;\n"
+       "               }\n"
+       "       }\n"
+       "       else\n"
+       "       {       \n"
+       "               //mark this pair as in-active\n"
+       "               concavePairs[pairIdx].w = -1;\n"
+       "       }\n"
+       "}\n"
+       "// work-in-progress\n"
+       "__kernel void   findConcaveSeparatingAxisEdgeEdgeKernel( __global int4* concavePairs,\n"
+       "                                                          __global const BodyData* rigidBodies,\n"
+       "                                                          __global const btCollidableGpu* collidables,\n"
+       "                                                          __global const ConvexPolyhedronCL* convexShapes,\n"
+       "                                                          __global const float4* vertices,\n"
+       "                                                          __global const float4* uniqueEdges,\n"
+       "                                                          __global const btGpuFace* faces,\n"
+       "                                                          __global const int* indices,\n"
+       "                                                          __global const btGpuChildShape* gpuChildShapes,\n"
+       "                                                          __global btAabbCL* aabbs,\n"
+       "                                                          __global float4* concaveSeparatingNormalsOut,\n"
+       "                                                          __global int* concaveHasSeparatingNormals,\n"
+       "                                                          __global int4* clippingFacesOut,\n"
+       "                                                          __global float4* worldVertsA1GPU,\n"
+       "                                                          __global float4*  worldNormalsAGPU,\n"
+       "                                                          __global float4* worldVertsB1GPU,\n"
+       "                                                          __global float* dmins,\n"
+       "                                                          int vertexFaceCapacity,\n"
+       "                                                          int numConcavePairs\n"
+       "                                                          )\n"
+       "{\n"
+       "    \n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numConcavePairs)\n"
+       "               return;\n"
+       "    \n"
+       "       if (!concaveHasSeparatingNormals[i])\n"
+       "        return;\n"
+       "    \n"
+       "       int pairIdx = i;\n"
+       "    \n"
+       "       int bodyIndexA = concavePairs[i].x;\n"
+       "       int bodyIndexB = concavePairs[i].y;\n"
+       "    \n"
+       "       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "    \n"
+       "       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "    \n"
+       "    \n"
+       "       int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "       int numActualConcaveConvexTests = 0;\n"
+       "       \n"
+       "       int f = concavePairs[i].z;\n"
+       "       \n"
+       "       bool overlap = false;\n"
+       "       \n"
+       "       ConvexPolyhedronCL convexPolyhedronA;\n"
+       "    \n"
+       "       //add 3 vertices of the triangle\n"
+       "       convexPolyhedronA.m_numVertices = 3;\n"
+       "       convexPolyhedronA.m_vertexOffset = 0;\n"
+       "       float4  localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+       "    \n"
+       "       btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+       "       float4 triMinAabb, triMaxAabb;\n"
+       "       btAabbCL triAabb;\n"
+       "       triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
+       "       triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
+       "       \n"
+       "       float4 verticesA[3];\n"
+       "       for (int i=0;i<3;i++)\n"
+       "       {\n"
+       "               int index = indices[face.m_indexOffset+i];\n"
+       "               float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+       "               verticesA[i] = vert;\n"
+       "               localCenter += vert;\n"
+       "        \n"
+       "               triAabb.m_min = min(triAabb.m_min,vert);\n"
+       "               triAabb.m_max = max(triAabb.m_max,vert);\n"
+       "        \n"
+       "       }\n"
+       "    \n"
+       "       overlap = true;\n"
+       "       overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
+       "       overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
+       "       overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
+       "    \n"
+       "       if (overlap)\n"
+       "       {\n"
+       "               float dmin = dmins[i];\n"
+       "               int hasSeparatingAxis=5;\n"
+       "               float4 sepAxis=make_float4(1,2,3,4);\n"
+       "        sepAxis = concaveSeparatingNormalsOut[pairIdx];\n"
+       "        \n"
+       "               int localCC=0;\n"
+       "               numActualConcaveConvexTests++;\n"
+       "        \n"
+       "               //a triangle has 3 unique edges\n"
+       "               convexPolyhedronA.m_numUniqueEdges = 3;\n"
+       "               convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+       "               float4 uniqueEdgesA[3];\n"
+       "               \n"
+       "               uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+       "               uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+       "               uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+       "        \n"
+       "        \n"
+       "               convexPolyhedronA.m_faceOffset = 0;\n"
+       "        \n"
+       "               float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+       "        \n"
+       "               btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+       "               int indicesA[3+3+2+2+2];\n"
+       "               int curUsedIndices=0;\n"
+       "               int fidx=0;\n"
+       "        \n"
+       "               //front size of triangle\n"
+       "               {\n"
+       "                       facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                       indicesA[0] = 0;\n"
+       "                       indicesA[1] = 1;\n"
+       "                       indicesA[2] = 2;\n"
+       "                       curUsedIndices+=3;\n"
+       "                       float c = face.m_plane.w;\n"
+       "                       facesA[fidx].m_plane.x = normal.x;\n"
+       "                       facesA[fidx].m_plane.y = normal.y;\n"
+       "                       facesA[fidx].m_plane.z = normal.z;\n"
+       "                       facesA[fidx].m_plane.w = c;\n"
+       "                       facesA[fidx].m_numIndices=3;\n"
+       "               }\n"
+       "               fidx++;\n"
+       "               //back size of triangle\n"
+       "               {\n"
+       "                       facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                       indicesA[3]=2;\n"
+       "                       indicesA[4]=1;\n"
+       "                       indicesA[5]=0;\n"
+       "                       curUsedIndices+=3;\n"
+       "                       float c = dot(normal,verticesA[0]);\n"
+       "                       float c1 = -face.m_plane.w;\n"
+       "                       facesA[fidx].m_plane.x = -normal.x;\n"
+       "                       facesA[fidx].m_plane.y = -normal.y;\n"
+       "                       facesA[fidx].m_plane.z = -normal.z;\n"
+       "                       facesA[fidx].m_plane.w = c;\n"
+       "                       facesA[fidx].m_numIndices=3;\n"
+       "               }\n"
+       "               fidx++;\n"
+       "        \n"
+       "               bool addEdgePlanes = true;\n"
+       "               if (addEdgePlanes)\n"
+       "               {\n"
+       "                       int numVertices=3;\n"
+       "                       int prevVertex = numVertices-1;\n"
+       "                       for (int i=0;i<numVertices;i++)\n"
+       "                       {\n"
+       "                               float4 v0 = verticesA[i];\n"
+       "                               float4 v1 = verticesA[prevVertex];\n"
+       "                \n"
+       "                               float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+       "                               float c = -dot(edgeNormal,v0);\n"
+       "                \n"
+       "                               facesA[fidx].m_numIndices = 2;\n"
+       "                               facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                               indicesA[curUsedIndices++]=i;\n"
+       "                               indicesA[curUsedIndices++]=prevVertex;\n"
+       "                \n"
+       "                               facesA[fidx].m_plane.x = edgeNormal.x;\n"
+       "                               facesA[fidx].m_plane.y = edgeNormal.y;\n"
+       "                               facesA[fidx].m_plane.z = edgeNormal.z;\n"
+       "                               facesA[fidx].m_plane.w = c;\n"
+       "                               fidx++;\n"
+       "                               prevVertex = i;\n"
+       "                       }\n"
+       "               }\n"
+       "               convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+       "               convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+       "        \n"
+       "        \n"
+       "               float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "               posA.w = 0.f;\n"
+       "               float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "               posB.w = 0.f;\n"
+       "        \n"
+       "               float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "               float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+       "        \n"
+       "               \n"
+       "        \n"
+       "        \n"
+       "               ///////////////////\n"
+       "               ///compound shape support\n"
+       "        \n"
+       "               if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "               {\n"
+       "                       int compoundChild = concavePairs[pairIdx].w;\n"
+       "                       int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
+       "                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+       "                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+       "                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+       "                       float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+       "                       float4 newOrnB = qtMul(ornB,childOrnB);\n"
+       "                       posB = newPosB;\n"
+       "                       ornB = newOrnB;\n"
+       "                       shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+       "               }\n"
+       "               //////////////////\n"
+       "        \n"
+       "               float4 c0local = convexPolyhedronA.m_localCenter;\n"
+       "               float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "               float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "               float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "               const float4 DeltaC2 = c0 - c1;\n"
+       "        \n"
+       "        \n"
+       "               {\n"
+       "                       bool sepEE = findSeparatingAxisEdgeEdgeLocalA(  &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+       "                                                              posA,ornA,\n"
+       "                                                              posB,ornB,\n"
+       "                                                              DeltaC2,\n"
+       "                                                              verticesA,uniqueEdgesA,facesA,indicesA,\n"
+       "                                                              vertices,uniqueEdges,faces,indices,\n"
+       "                                                              &sepAxis,&dmin);\n"
+       "                \n"
+       "                       if (!sepEE)\n"
+       "                       {\n"
+       "                               hasSeparatingAxis = 0;\n"
+       "                       } else\n"
+       "                       {\n"
+       "                               hasSeparatingAxis = 1;\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "               \n"
+       "               if (hasSeparatingAxis)\n"
+       "               {\n"
+       "                       sepAxis.w = dmin;\n"
+       "            dmins[i] = dmin;\n"
+       "                       concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
+       "                       concaveHasSeparatingNormals[i]=1;\n"
+       "           \n"
+       "       float minDist = -1e30f;\n"
+       "                       float maxDist = 0.02f;\n"
+       "            \n"
+       "            findClippingFaces(sepAxis,\n"
+       "                              &convexPolyhedronA,\n"
+       "                              &convexShapes[shapeIndexB],\n"
+       "                              posA,ornA,\n"
+       "                              posB,ornB,\n"
+       "                              worldVertsA1GPU,\n"
+       "                              worldNormalsAGPU,\n"
+       "                              worldVertsB1GPU,\n"
+       "                              vertexFaceCapacity,\n"
+       "                              minDist, maxDist,\n"
+       "                              verticesA,\n"
+       "                              facesA,\n"
+       "                              indicesA,\n"
+       "                              vertices,\n"
+       "                              faces,\n"
+       "                              indices,\n"
+       "                              clippingFacesOut, pairIdx);\n"
+       "                  \n"
+       "            \n"
+       "               } else\n"
+       "               {       \n"
+       "                       //mark this pair as in-active\n"
+       "                       concavePairs[pairIdx].w = -1;\n"
+       "               }\n"
+       "       }\n"
+       "       else\n"
+       "       {       \n"
+       "               //mark this pair as in-active\n"
+       "               concavePairs[pairIdx].w = -1;\n"
+       "       }\n"
+       "       \n"
+       "       concavePairs[i].z = -1;//for the next stage, z is used to determine existing contact points\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h
new file mode 100644 (file)
index 0000000..e627af2
--- /dev/null
@@ -0,0 +1,2103 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* satKernelsCL =
+       "//keep this enum in sync with the CPU version (in btCollidable.h)\n"
+       "//written by Erwin Coumans\n"
+       "#define SHAPE_CONVEX_HULL 3\n"
+       "#define SHAPE_CONCAVE_TRIMESH 5\n"
+       "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
+       "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+       "#define B3_MAX_STACK_DEPTH 256\n"
+       "typedef unsigned int u32;\n"
+       "///keep this in sync with btCollidable.h\n"
+       "typedef struct\n"
+       "{\n"
+       "       union {\n"
+       "               int m_numChildShapes;\n"
+       "               int m_bvhIndex;\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float m_radius;\n"
+       "               int     m_compoundBvhIndex;\n"
+       "       };\n"
+       "       \n"
+       "       int m_shapeType;\n"
+       "       int m_shapeIndex;\n"
+       "       \n"
+       "} btCollidableGpu;\n"
+       "#define MAX_NUM_PARTS_IN_BITS 10\n"
+       "///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
+       "///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
+       "typedef struct\n"
+       "{\n"
+       "       //12 bytes\n"
+       "       unsigned short int      m_quantizedAabbMin[3];\n"
+       "       unsigned short int      m_quantizedAabbMax[3];\n"
+       "       //4 bytes\n"
+       "       int     m_escapeIndexOrTriangleIndex;\n"
+       "} b3QuantizedBvhNode;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4          m_aabbMin;\n"
+       "       float4          m_aabbMax;\n"
+       "       float4          m_quantization;\n"
+       "       int                     m_numNodes;\n"
+       "       int                     m_numSubTrees;\n"
+       "       int                     m_nodeOffset;\n"
+       "       int                     m_subTreeOffset;\n"
+       "} b3BvhInfo;\n"
+       "int    getTriangleIndex(const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       unsigned int x=0;\n"
+       "       unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+       "       // Get only the lower bits where the triangle index is stored\n"
+       "       return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+       "}\n"
+       "int    getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       unsigned int x=0;\n"
+       "       unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
+       "       // Get only the lower bits where the triangle index is stored\n"
+       "       return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
+       "}\n"
+       "int isLeafNode(const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+       "       return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+       "}\n"
+       "int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
+       "       return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
+       "}\n"
+       "       \n"
+       "int getEscapeIndex(const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+       "}\n"
+       "int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
+       "{\n"
+       "       return -rootNode->m_escapeIndexOrTriangleIndex;\n"
+       "}\n"
+       "typedef struct\n"
+       "{\n"
+       "       //12 bytes\n"
+       "       unsigned short int      m_quantizedAabbMin[3];\n"
+       "       unsigned short int      m_quantizedAabbMax[3];\n"
+       "       //4 bytes, points to the root of the subtree\n"
+       "       int                     m_rootNodeIndex;\n"
+       "       //4 bytes\n"
+       "       int                     m_subtreeSize;\n"
+       "       int                     m_padding[3];\n"
+       "} b3BvhSubtreeInfo;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4  m_childPosition;\n"
+       "       float4  m_childOrientation;\n"
+       "       int m_shapeIndex;\n"
+       "       int m_unused0;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "} btGpuChildShape;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_pos;\n"
+       "       float4 m_quat;\n"
+       "       float4 m_linVel;\n"
+       "       float4 m_angVel;\n"
+       "       u32 m_collidableIdx;\n"
+       "       float m_invMass;\n"
+       "       float m_restituitionCoeff;\n"
+       "       float m_frictionCoeff;\n"
+       "} BodyData;\n"
+       "typedef struct  \n"
+       "{\n"
+       "       float4          m_localCenter;\n"
+       "       float4          m_extents;\n"
+       "       float4          mC;\n"
+       "       float4          mE;\n"
+       "       \n"
+       "       float                   m_radius;\n"
+       "       int     m_faceOffset;\n"
+       "       int m_numFaces;\n"
+       "       int     m_numVertices;\n"
+       "       int m_vertexOffset;\n"
+       "       int     m_uniqueEdgesOffset;\n"
+       "       int     m_numUniqueEdges;\n"
+       "       int m_unused;\n"
+       "} ConvexPolyhedronCL;\n"
+       "typedef struct \n"
+       "{\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_min;\n"
+       "               float   m_minElems[4];\n"
+       "               int                     m_minIndices[4];\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float4  m_max;\n"
+       "               float   m_maxElems[4];\n"
+       "               int                     m_maxIndices[4];\n"
+       "       };\n"
+       "} btAabbCL;\n"
+       "#ifndef B3_AABB_H\n"
+       "#define B3_AABB_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_MAT3x3_H\n"
+       "#define B3_MAT3x3_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#define B3_QUAT_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Quat;\n"
+       "       #define b3QuatConstArg const b3Quat\n"
+       "       \n"
+       "       \n"
+       "inline float4 b3FastNormalize4(float4 v)\n"
+       "{\n"
+       "       v = (float4)(v.xyz,0.f);\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "       \n"
+       "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+       "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+       "{\n"
+       "       b3Quat ans;\n"
+       "       ans = b3Cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+       "{\n"
+       "       b3Quat q;\n"
+       "       q=in;\n"
+       "       //return b3FastNormalize4(in);\n"
+       "       float len = native_sqrt(dot(q, q));\n"
+       "       if(len > 0.f)\n"
+       "       {\n"
+       "               q *= 1.f / len;\n"
+       "       }\n"
+       "       else\n"
+       "       {\n"
+       "               q.x = q.y = q.z = 0.f;\n"
+       "               q.w = 1.f;\n"
+       "       }\n"
+       "       return q;\n"
+       "}\n"
+       "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       b3Quat qInv = b3QuatInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+       "}\n"
+       "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg  orientation)\n"
+       "{\n"
+       "       return b3QuatRotate( orientation, point ) + (translation);\n"
+       "}\n"
+       "       \n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "typedef struct\n"
+       "{\n"
+       "       b3Float4 m_row[3];\n"
+       "}b3Mat3x3;\n"
+       "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+       "#define b3GetRow(m,row) (m.m_row[row])\n"
+       "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+       "{\n"
+       "       b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+       "       out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+       "       out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+       "       out.m_row[0].w = 0.f;\n"
+       "       out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+       "       out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+       "       out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+       "       out.m_row[1].w = 0.f;\n"
+       "       out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+       "       out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+       "       out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+       "       out.m_row[2].w = 0.f;\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = fabs(matIn.m_row[0]);\n"
+       "       out.m_row[1] = fabs(matIn.m_row[1]);\n"
+       "       out.m_row[2] = fabs(matIn.m_row[2]);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero();\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity();\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(0.f);\n"
+       "       m.m_row[1] = (b3Float4)(0.f);\n"
+       "       m.m_row[2] = (b3Float4)(0.f);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+       "       m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+       "       m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+       "       out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+       "       out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Mat3x3 transB;\n"
+       "       transB = mtTranspose( b );\n"
+       "       b3Mat3x3 ans;\n"
+       "       //      why this doesn't run when 0ing in the for{}\n"
+       "       a.m_row[0].w = 0.f;\n"
+       "       a.m_row[1].w = 0.f;\n"
+       "       a.m_row[2].w = 0.f;\n"
+       "       for(int i=0; i<3; i++)\n"
+       "       {\n"
+       "//     a.m_row[i].w = 0.f;\n"
+       "               ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+       "               ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+       "               ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+       "               ans.m_row[i].w = 0.f;\n"
+       "       }\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+       "{\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a.m_row[0], b );\n"
+       "       ans.y = b3Dot3F4( a.m_row[1], b );\n"
+       "       ans.z = b3Dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a, colx );\n"
+       "       ans.y = b3Dot3F4( a, coly );\n"
+       "       ans.z = b3Dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "#endif\n"
+       "#endif //B3_MAT3x3_H\n"
+       "typedef struct b3Aabb b3Aabb_t;\n"
+       "struct b3Aabb\n"
+       "{\n"
+       "       union\n"
+       "       {\n"
+       "               float m_min[4];\n"
+       "               b3Float4 m_minVec;\n"
+       "               int m_minIndices[4];\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float   m_max[4];\n"
+       "               b3Float4 m_maxVec;\n"
+       "               int m_signedMaxIndices[4];\n"
+       "       };\n"
+       "};\n"
+       "inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
+       "                                               b3Float4ConstArg pos,\n"
+       "                                               b3QuatConstArg orn,\n"
+       "                                               b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
+       "{\n"
+       "               b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
+       "               localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
+       "               b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
+       "               b3Mat3x3 m;\n"
+       "               m = b3QuatGetRotationMatrix(orn);\n"
+       "               b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
+       "               b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
+       "               \n"
+       "               b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
+       "                                                                                b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
+       "                                                                                b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
+       "                                                                                0.f);\n"
+       "               *aabbMinOut = center-extent;\n"
+       "               *aabbMaxOut = center+extent;\n"
+       "}\n"
+       "/// conservative test for overlap between two aabbs\n"
+       "inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
+       "                                                               b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
+       "{\n"
+       "       bool overlap = true;\n"
+       "       overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
+       "       overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
+       "       overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
+       "       return overlap;\n"
+       "}\n"
+       "#endif //B3_AABB_H\n"
+       "/*\n"
+       "Bullet Continuous Collision Detection and Physics Library\n"
+       "Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org\n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose,\n"
+       "including commercial applications, and to alter it and redistribute it freely,\n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "#ifndef B3_INT2_H\n"
+       "#define B3_INT2_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#define b3UnsignedInt2 uint2\n"
+       "#define b3Int2 int2\n"
+       "#define b3MakeInt2 (int2)\n"
+       "#endif //__cplusplus\n"
+       "#endif\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_plane;\n"
+       "       int m_indexOffset;\n"
+       "       int m_numIndices;\n"
+       "} btGpuFace;\n"
+       "#define make_float4 (float4)\n"
+       "__inline\n"
+       "float4 cross3(float4 a, float4 b)\n"
+       "{\n"
+       "       return cross(a,b);\n"
+       "       \n"
+       "//     float4 a1 = make_float4(a.xyz,0.f);\n"
+       "//     float4 b1 = make_float4(b.xyz,0.f);\n"
+       "//     return cross(a1,b1);\n"
+       "//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);\n"
+       "       \n"
+       "       //      float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);\n"
+       "       \n"
+       "       //return c;\n"
+       "}\n"
+       "__inline\n"
+       "float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = make_float4(a.xyz,0.f);\n"
+       "       float4 b1 = make_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "float4 fastNormalize4(float4 v)\n"
+       "{\n"
+       "       v = make_float4(v.xyz,0.f);\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Quaternion\n"
+       "///////////////////////////////////////\n"
+       "typedef float4 Quaternion;\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in);\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec);\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q);\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+       "{\n"
+       "       Quaternion ans;\n"
+       "       ans = cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in)\n"
+       "{\n"
+       "       return fastNormalize4(in);\n"
+       "//     in /= length( in );\n"
+       "//     return in;\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec)\n"
+       "{\n"
+       "       Quaternion qInv = qtInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q)\n"
+       "{\n"
+       "       return (Quaternion)(-q.xyz, q.w);\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+       "{\n"
+       "       return qtRotate( qtInvert( q ), vec );\n"
+       "}\n"
+       "__inline\n"
+       "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
+       "{\n"
+       "       return qtRotate( *orientation, *p ) + (*translation);\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize3(const float4 a)\n"
+       "{\n"
+       "       float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+       "       return fastNormalize4( n );\n"
+       "}\n"
+       "inline void projectLocal(const ConvexPolyhedronCL* hull,  const float4 pos, const float4 orn, \n"
+       "const float4* dir, const float4* vertices, float* min, float* max)\n"
+       "{\n"
+       "       min[0] = FLT_MAX;\n"
+       "       max[0] = -FLT_MAX;\n"
+       "       int numVerts = hull->m_numVertices;\n"
+       "       const float4 localDir = qtInvRotate(orn,*dir);\n"
+       "       float offset = dot(pos,*dir);\n"
+       "       for(int i=0;i<numVerts;i++)\n"
+       "       {\n"
+       "               float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+       "               if(dp < min[0]) \n"
+       "                       min[0] = dp;\n"
+       "               if(dp > max[0]) \n"
+       "                       max[0] = dp;\n"
+       "       }\n"
+       "       if(min[0]>max[0])\n"
+       "       {\n"
+       "               float tmp = min[0];\n"
+       "               min[0] = max[0];\n"
+       "               max[0] = tmp;\n"
+       "       }\n"
+       "       min[0] += offset;\n"
+       "       max[0] += offset;\n"
+       "}\n"
+       "inline void project(__global const ConvexPolyhedronCL* hull,  const float4 pos, const float4 orn, \n"
+       "const float4* dir, __global const float4* vertices, float* min, float* max)\n"
+       "{\n"
+       "       min[0] = FLT_MAX;\n"
+       "       max[0] = -FLT_MAX;\n"
+       "       int numVerts = hull->m_numVertices;\n"
+       "       const float4 localDir = qtInvRotate(orn,*dir);\n"
+       "       float offset = dot(pos,*dir);\n"
+       "       for(int i=0;i<numVerts;i++)\n"
+       "       {\n"
+       "               float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
+       "               if(dp < min[0]) \n"
+       "                       min[0] = dp;\n"
+       "               if(dp > max[0]) \n"
+       "                       max[0] = dp;\n"
+       "       }\n"
+       "       if(min[0]>max[0])\n"
+       "       {\n"
+       "               float tmp = min[0];\n"
+       "               min[0] = max[0];\n"
+       "               max[0] = tmp;\n"
+       "       }\n"
+       "       min[0] += offset;\n"
+       "       max[0] += offset;\n"
+       "}\n"
+       "inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA,const float4 ornA,\n"
+       "       const float4 posB,const float4 ornB,\n"
+       "       float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)\n"
+       "{\n"
+       "       float Min0,Max0;\n"
+       "       float Min1,Max1;\n"
+       "       projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);\n"
+       "       project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);\n"
+       "       if(Max0<Min1 || Max1<Min0)\n"
+       "               return false;\n"
+       "       float d0 = Max0 - Min1;\n"
+       "       float d1 = Max1 - Min0;\n"
+       "       *depth = d0<d1 ? d0:d1;\n"
+       "       return true;\n"
+       "}\n"
+       "inline bool IsAlmostZero(const float4 v)\n"
+       "{\n"
+       "       if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)\n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA1,\n"
+       "       const float4 ornA,\n"
+       "       const float4 posB1,\n"
+       "       const float4 ornB,\n"
+       "       const float4 DeltaC2,\n"
+       "       \n"
+       "       const float4* verticesA, \n"
+       "       const float4* uniqueEdgesA, \n"
+       "       const btGpuFace* facesA,\n"
+       "       const int*  indicesA,\n"
+       "       __global const float4* verticesB, \n"
+       "       __global const float4* uniqueEdgesB, \n"
+       "       __global const btGpuFace* facesB,\n"
+       "       __global const int*  indicesB,\n"
+       "       float4* sep,\n"
+       "       float* dmin)\n"
+       "{\n"
+       "       \n"
+       "       float4 posA = posA1;\n"
+       "       posA.w = 0.f;\n"
+       "       float4 posB = posB1;\n"
+       "       posB.w = 0.f;\n"
+       "       int curPlaneTests=0;\n"
+       "       {\n"
+       "               int numFacesA = hullA->m_numFaces;\n"
+       "               // Test normals from hullA\n"
+       "               for(int i=0;i<numFacesA;i++)\n"
+       "               {\n"
+       "                       const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+       "                       float4 faceANormalWS = qtRotate(ornA,normal);\n"
+       "                       if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+       "                               faceANormalWS*=-1.f;\n"
+       "                       curPlaneTests++;\n"
+       "                       float d;\n"
+       "                       if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))\n"
+       "                               return false;\n"
+       "                       if(d<*dmin)\n"
+       "                       {\n"
+       "                               *dmin = d;\n"
+       "                               *sep = faceANormalWS;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+       "       {\n"
+       "               *sep = -(*sep);\n"
+       "       }\n"
+       "       return true;\n"
+       "}\n"
+       "bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA,  const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA1,\n"
+       "       const float4 ornA,\n"
+       "       const float4 posB1,\n"
+       "       const float4 ornB,\n"
+       "       const float4 DeltaC2,\n"
+       "       __global const float4* verticesA, \n"
+       "       __global const float4* uniqueEdgesA, \n"
+       "       __global const btGpuFace* facesA,\n"
+       "       __global const int*  indicesA,\n"
+       "       const float4* verticesB,\n"
+       "       const float4* uniqueEdgesB, \n"
+       "       const btGpuFace* facesB,\n"
+       "       const int*  indicesB,\n"
+       "       float4* sep,\n"
+       "       float* dmin)\n"
+       "{\n"
+       "       float4 posA = posA1;\n"
+       "       posA.w = 0.f;\n"
+       "       float4 posB = posB1;\n"
+       "       posB.w = 0.f;\n"
+       "       int curPlaneTests=0;\n"
+       "       {\n"
+       "               int numFacesA = hullA->m_numFaces;\n"
+       "               // Test normals from hullA\n"
+       "               for(int i=0;i<numFacesA;i++)\n"
+       "               {\n"
+       "                       const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
+       "                       float4 faceANormalWS = qtRotate(ornA,normal);\n"
+       "                       if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+       "                               faceANormalWS *= -1.f;\n"
+       "                       curPlaneTests++;\n"
+       "                       float d;\n"
+       "                       if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))\n"
+       "                               return false;\n"
+       "                       if(d<*dmin)\n"
+       "                       {\n"
+       "                               *dmin = d;\n"
+       "                               *sep = faceANormalWS;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+       "       {\n"
+       "               *sep = -(*sep);\n"
+       "       }\n"
+       "       return true;\n"
+       "}\n"
+       "bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA1,\n"
+       "       const float4 ornA,\n"
+       "       const float4 posB1,\n"
+       "       const float4 ornB,\n"
+       "       const float4 DeltaC2,\n"
+       "       const float4* verticesA, \n"
+       "       const float4* uniqueEdgesA, \n"
+       "       const btGpuFace* facesA,\n"
+       "       const int*  indicesA,\n"
+       "       __global const float4* verticesB, \n"
+       "       __global const float4* uniqueEdgesB, \n"
+       "       __global const btGpuFace* facesB,\n"
+       "       __global const int*  indicesB,\n"
+       "               float4* sep,\n"
+       "       float* dmin)\n"
+       "{\n"
+       "       float4 posA = posA1;\n"
+       "       posA.w = 0.f;\n"
+       "       float4 posB = posB1;\n"
+       "       posB.w = 0.f;\n"
+       "       int curPlaneTests=0;\n"
+       "       int curEdgeEdge = 0;\n"
+       "       // Test edges\n"
+       "       for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
+       "       {\n"
+       "               const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];\n"
+       "               float4 edge0World = qtRotate(ornA,edge0);\n"
+       "               for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
+       "               {\n"
+       "                       const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];\n"
+       "                       float4 edge1World = qtRotate(ornB,edge1);\n"
+       "                       float4 crossje = cross3(edge0World,edge1World);\n"
+       "                       curEdgeEdge++;\n"
+       "                       if(!IsAlmostZero(crossje))\n"
+       "                       {\n"
+       "                               crossje = normalize3(crossje);\n"
+       "                               if (dot3F4(DeltaC2,crossje)<0)\n"
+       "                                       crossje *= -1.f;\n"
+       "                               float dist;\n"
+       "                               bool result = true;\n"
+       "                               {\n"
+       "                                       float Min0,Max0;\n"
+       "                                       float Min1,Max1;\n"
+       "                                       projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);\n"
+       "                                       project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);\n"
+       "                               \n"
+       "                                       if(Max0<Min1 || Max1<Min0)\n"
+       "                                               result = false;\n"
+       "                               \n"
+       "                                       float d0 = Max0 - Min1;\n"
+       "                                       float d1 = Max1 - Min0;\n"
+       "                                       dist = d0<d1 ? d0:d1;\n"
+       "                                       result = true;\n"
+       "                               }\n"
+       "                               \n"
+       "                               if(dist<*dmin)\n"
+       "                               {\n"
+       "                                       *dmin = dist;\n"
+       "                                       *sep = crossje;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       \n"
+       "       if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+       "       {\n"
+       "               *sep = -(*sep);\n"
+       "       }\n"
+       "       return true;\n"
+       "}\n"
+       "inline bool TestSepAxis(__global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA,const float4 ornA,\n"
+       "       const float4 posB,const float4 ornB,\n"
+       "       float4* sep_axis, __global const float4* vertices,float* depth)\n"
+       "{\n"
+       "       float Min0,Max0;\n"
+       "       float Min1,Max1;\n"
+       "       project(hullA,posA,ornA,sep_axis,vertices, &Min0, &Max0);\n"
+       "       project(hullB,posB,ornB, sep_axis,vertices, &Min1, &Max1);\n"
+       "       if(Max0<Min1 || Max1<Min0)\n"
+       "               return false;\n"
+       "       float d0 = Max0 - Min1;\n"
+       "       float d1 = Max1 - Min0;\n"
+       "       *depth = d0<d1 ? d0:d1;\n"
+       "       return true;\n"
+       "}\n"
+       "bool findSeparatingAxis(       __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA1,\n"
+       "       const float4 ornA,\n"
+       "       const float4 posB1,\n"
+       "       const float4 ornB,\n"
+       "       const float4 DeltaC2,\n"
+       "       __global const float4* vertices, \n"
+       "       __global const float4* uniqueEdges, \n"
+       "       __global const btGpuFace* faces,\n"
+       "       __global const int*  indices,\n"
+       "       float4* sep,\n"
+       "       float* dmin)\n"
+       "{\n"
+       "       \n"
+       "       float4 posA = posA1;\n"
+       "       posA.w = 0.f;\n"
+       "       float4 posB = posB1;\n"
+       "       posB.w = 0.f;\n"
+       "       \n"
+       "       int curPlaneTests=0;\n"
+       "       {\n"
+       "               int numFacesA = hullA->m_numFaces;\n"
+       "               // Test normals from hullA\n"
+       "               for(int i=0;i<numFacesA;i++)\n"
+       "               {\n"
+       "                       const float4 normal = faces[hullA->m_faceOffset+i].m_plane;\n"
+       "                       float4 faceANormalWS = qtRotate(ornA,normal);\n"
+       "       \n"
+       "                       if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
+       "                               faceANormalWS*=-1.f;\n"
+       "                               \n"
+       "                       curPlaneTests++;\n"
+       "       \n"
+       "                       float d;\n"
+       "                       if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, vertices,&d))\n"
+       "                               return false;\n"
+       "       \n"
+       "                       if(d<*dmin)\n"
+       "                       {\n"
+       "                               *dmin = d;\n"
+       "                               *sep = faceANormalWS;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "               if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+       "               {\n"
+       "                       *sep = -(*sep);\n"
+       "               }\n"
+       "       \n"
+       "       return true;\n"
+       "}\n"
+       "bool findSeparatingAxisUnitSphere(     __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA1,\n"
+       "       const float4 ornA,\n"
+       "       const float4 posB1,\n"
+       "       const float4 ornB,\n"
+       "       const float4 DeltaC2,\n"
+       "       __global const float4* vertices,\n"
+       "       __global const float4* unitSphereDirections,\n"
+       "       int numUnitSphereDirections,\n"
+       "       float4* sep,\n"
+       "       float* dmin)\n"
+       "{\n"
+       "       \n"
+       "       float4 posA = posA1;\n"
+       "       posA.w = 0.f;\n"
+       "       float4 posB = posB1;\n"
+       "       posB.w = 0.f;\n"
+       "       int curPlaneTests=0;\n"
+       "       int curEdgeEdge = 0;\n"
+       "       // Test unit sphere directions\n"
+       "       for (int i=0;i<numUnitSphereDirections;i++)\n"
+       "       {\n"
+       "               float4 crossje;\n"
+       "               crossje = unitSphereDirections[i];      \n"
+       "               if (dot3F4(DeltaC2,crossje)>0)\n"
+       "                       crossje *= -1.f;\n"
+       "               {\n"
+       "                       float dist;\n"
+       "                       bool result = true;\n"
+       "                       float Min0,Max0;\n"
+       "                       float Min1,Max1;\n"
+       "                       project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
+       "                       project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
+       "               \n"
+       "                       if(Max0<Min1 || Max1<Min0)\n"
+       "                               return false;\n"
+       "               \n"
+       "                       float d0 = Max0 - Min1;\n"
+       "                       float d1 = Max1 - Min0;\n"
+       "                       dist = d0<d1 ? d0:d1;\n"
+       "                       result = true;\n"
+       "       \n"
+       "                       if(dist<*dmin)\n"
+       "                       {\n"
+       "                               *dmin = dist;\n"
+       "                               *sep = crossje;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       \n"
+       "       if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+       "       {\n"
+       "               *sep = -(*sep);\n"
+       "       }\n"
+       "       return true;\n"
+       "}\n"
+       "bool findSeparatingAxisEdgeEdge(       __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
+       "       const float4 posA1,\n"
+       "       const float4 ornA,\n"
+       "       const float4 posB1,\n"
+       "       const float4 ornB,\n"
+       "       const float4 DeltaC2,\n"
+       "       __global const float4* vertices, \n"
+       "       __global const float4* uniqueEdges, \n"
+       "       __global const btGpuFace* faces,\n"
+       "       __global const int*  indices,\n"
+       "       float4* sep,\n"
+       "       float* dmin)\n"
+       "{\n"
+       "       \n"
+       "       float4 posA = posA1;\n"
+       "       posA.w = 0.f;\n"
+       "       float4 posB = posB1;\n"
+       "       posB.w = 0.f;\n"
+       "       int curPlaneTests=0;\n"
+       "       int curEdgeEdge = 0;\n"
+       "       // Test edges\n"
+       "       for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
+       "       {\n"
+       "               const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset+e0];\n"
+       "               float4 edge0World = qtRotate(ornA,edge0);\n"
+       "               for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
+       "               {\n"
+       "                       const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset+e1];\n"
+       "                       float4 edge1World = qtRotate(ornB,edge1);\n"
+       "                       float4 crossje = cross3(edge0World,edge1World);\n"
+       "                       curEdgeEdge++;\n"
+       "                       if(!IsAlmostZero(crossje))\n"
+       "                       {\n"
+       "                               crossje = normalize3(crossje);\n"
+       "                               if (dot3F4(DeltaC2,crossje)<0)\n"
+       "                                       crossje*=-1.f;\n"
+       "                                       \n"
+       "                               float dist;\n"
+       "                               bool result = true;\n"
+       "                               {\n"
+       "                                       float Min0,Max0;\n"
+       "                                       float Min1,Max1;\n"
+       "                                       project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
+       "                                       project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
+       "                               \n"
+       "                                       if(Max0<Min1 || Max1<Min0)\n"
+       "                                               return false;\n"
+       "                               \n"
+       "                                       float d0 = Max0 - Min1;\n"
+       "                                       float d1 = Max1 - Min0;\n"
+       "                                       dist = d0<d1 ? d0:d1;\n"
+       "                                       result = true;\n"
+       "                               }\n"
+       "                               \n"
+       "                               if(dist<*dmin)\n"
+       "                               {\n"
+       "                                       *dmin = dist;\n"
+       "                                       *sep = crossje;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       \n"
+       "       if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
+       "       {\n"
+       "               *sep = -(*sep);\n"
+       "       }\n"
+       "       return true;\n"
+       "}\n"
+       "// work-in-progress\n"
+       "__kernel void   processCompoundPairsKernel( __global const int4* gpuCompoundPairs,\n"
+       "                                                                                                                                                                       __global const BodyData* rigidBodies, \n"
+       "                                                                                                                                                                       __global const btCollidableGpu* collidables,\n"
+       "                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global const float4* uniqueEdges,\n"
+       "                                                                                                                                                                       __global const btGpuFace* faces,\n"
+       "                                                                                                                                                                       __global const int* indices,\n"
+       "                                                                                                                                                                       __global btAabbCL* aabbs,\n"
+       "                                                                                                                                                                       __global const btGpuChildShape* gpuChildShapes,\n"
+       "                                                                                                                                                                       __global volatile float4* gpuCompoundSepNormalsOut,\n"
+       "                                                                                                                                                                       __global volatile int* gpuHasCompoundSepNormalsOut,\n"
+       "                                                                                                                                                                       int numCompoundPairs\n"
+       "                                                                                                                                                                       )\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i<numCompoundPairs)\n"
+       "       {\n"
+       "               int bodyIndexA = gpuCompoundPairs[i].x;\n"
+       "               int bodyIndexB = gpuCompoundPairs[i].y;\n"
+       "               int childShapeIndexA = gpuCompoundPairs[i].z;\n"
+       "               int childShapeIndexB = gpuCompoundPairs[i].w;\n"
+       "               \n"
+       "               int collidableIndexA = -1;\n"
+       "               int collidableIndexB = -1;\n"
+       "               \n"
+       "               float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "               float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "               \n"
+       "               float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+       "               float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                                                       \n"
+       "               if (childShapeIndexA >= 0)\n"
+       "               {\n"
+       "                       collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+       "                       float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+       "                       float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+       "                       float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+       "                       float4 newOrnA = qtMul(ornA,childOrnA);\n"
+       "                       posA = newPosA;\n"
+       "                       ornA = newOrnA;\n"
+       "               } else\n"
+       "               {\n"
+       "                       collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "               }\n"
+       "               \n"
+       "               if (childShapeIndexB>=0)\n"
+       "               {\n"
+       "                       collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+       "                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+       "                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+       "                       float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+       "                       float4 newOrnB = qtMul(ornB,childOrnB);\n"
+       "                       posB = newPosB;\n"
+       "                       ornB = newOrnB;\n"
+       "               } else\n"
+       "               {\n"
+       "                       collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;     \n"
+       "               }\n"
+       "       \n"
+       "               gpuHasCompoundSepNormalsOut[i] = 0;\n"
+       "       \n"
+       "               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "       \n"
+       "               int shapeTypeA = collidables[collidableIndexA].m_shapeType;\n"
+       "               int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
+       "       \n"
+       "               if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))\n"
+       "               {\n"
+       "                       return;\n"
+       "               }\n"
+       "               int hasSeparatingAxis = 5;\n"
+       "                                                       \n"
+       "               int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "               float dmin = FLT_MAX;\n"
+       "               posA.w = 0.f;\n"
+       "               posB.w = 0.f;\n"
+       "               float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+       "               float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "               float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "               float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "               const float4 DeltaC2 = c0 - c1;\n"
+       "               float4 sepNormal = make_float4(1,0,0,0);\n"
+       "               bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
+       "               hasSeparatingAxis = 4;\n"
+       "               if (!sepA)\n"
+       "               {\n"
+       "                       hasSeparatingAxis = 0;\n"
+       "               } else\n"
+       "               {\n"
+       "                       bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,posA,ornA,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
+       "                       if (!sepB)\n"
+       "                       {\n"
+       "                               hasSeparatingAxis = 0;\n"
+       "                       } else//(!sepB)\n"
+       "                       {\n"
+       "                               bool sepEE = findSeparatingAxisEdgeEdge(        &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
+       "                               if (sepEE)\n"
+       "                               {\n"
+       "                                               gpuCompoundSepNormalsOut[i] = sepNormal;//fastNormalize4(sepNormal);\n"
+       "                                               gpuHasCompoundSepNormalsOut[i] = 1;\n"
+       "                               }//sepEE\n"
+       "                       }//(!sepB)\n"
+       "               }//(!sepA)\n"
+       "               \n"
+       "               \n"
+       "       }\n"
+       "               \n"
+       "}\n"
+       "inline b3Float4 MyUnQuantize(const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)\n"
+       "{\n"
+       "               b3Float4 vecOut;\n"
+       "               vecOut = b3MakeFloat4(\n"
+       "                       (float)(vecIn[0]) / (quantization.x),\n"
+       "                       (float)(vecIn[1]) / (quantization.y),\n"
+       "                       (float)(vecIn[2]) / (quantization.z),\n"
+       "                       0.f);\n"
+       "               vecOut += bvhAabbMin;\n"
+       "               return vecOut;\n"
+       "}\n"
+       "inline b3Float4 MyUnQuantizeGlobal(__global const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)\n"
+       "{\n"
+       "               b3Float4 vecOut;\n"
+       "               vecOut = b3MakeFloat4(\n"
+       "                       (float)(vecIn[0]) / (quantization.x),\n"
+       "                       (float)(vecIn[1]) / (quantization.y),\n"
+       "                       (float)(vecIn[2]) / (quantization.z),\n"
+       "                       0.f);\n"
+       "               vecOut += bvhAabbMin;\n"
+       "               return vecOut;\n"
+       "}\n"
+       "// work-in-progress\n"
+       "__kernel void   findCompoundPairsKernel( __global const int4* pairs, \n"
+       "       __global const BodyData* rigidBodies, \n"
+       "       __global const btCollidableGpu* collidables,\n"
+       "       __global const ConvexPolyhedronCL* convexShapes, \n"
+       "       __global const float4* vertices,\n"
+       "       __global const float4* uniqueEdges,\n"
+       "       __global const btGpuFace* faces,\n"
+       "       __global const int* indices,\n"
+       "       __global b3Aabb_t* aabbLocalSpace,\n"
+       "       __global const btGpuChildShape* gpuChildShapes,\n"
+       "       __global volatile int4* gpuCompoundPairsOut,\n"
+       "       __global volatile int* numCompoundPairsOut,\n"
+       "       __global const b3BvhSubtreeInfo* subtrees,\n"
+       "       __global const b3QuantizedBvhNode* quantizedNodes,\n"
+       "       __global const b3BvhInfo* bvhInfos,\n"
+       "       int numPairs,\n"
+       "       int maxNumCompoundPairsCapacity\n"
+       "       )\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "               int bodyIndexA = pairs[i].x;\n"
+       "               int bodyIndexB = pairs[i].y;\n"
+       "               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "               //once the broadphase avoids static-static pairs, we can remove this test\n"
+       "               if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+       "               {\n"
+       "                       return;\n"
+       "               }\n"
+       "               if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) &&(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+       "               {\n"
+       "                       int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;\n"
+       "                       int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;\n"
+       "                       int numSubTreesA = bvhInfos[bvhA].m_numSubTrees;\n"
+       "                       int subTreesOffsetA = bvhInfos[bvhA].m_subTreeOffset;\n"
+       "                       int subTreesOffsetB = bvhInfos[bvhB].m_subTreeOffset;\n"
+       "                       int numSubTreesB = bvhInfos[bvhB].m_numSubTrees;\n"
+       "                       \n"
+       "                       float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "                       b3Quat ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "                       b3Quat ornB = rigidBodies[bodyIndexB].m_quat;\n"
+       "                       float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                       \n"
+       "                       for (int p=0;p<numSubTreesA;p++)\n"
+       "                       {\n"
+       "                               b3BvhSubtreeInfo subtreeA = subtrees[subTreesOffsetA+p];\n"
+       "                               //bvhInfos[bvhA].m_quantization\n"
+       "                               b3Float4 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+       "                               b3Float4 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+       "                               b3Float4 aabbAMinOut,aabbAMaxOut;\n"
+       "                               float margin=0.f;\n"
+       "                               b3TransformAabb2(treeAminLocal,treeAmaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);\n"
+       "                               \n"
+       "                               for (int q=0;q<numSubTreesB;q++)\n"
+       "                               {\n"
+       "                                       b3BvhSubtreeInfo subtreeB = subtrees[subTreesOffsetB+q];\n"
+       "                                       b3Float4 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+       "                                       b3Float4 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+       "                                       b3Float4 aabbBMinOut,aabbBMaxOut;\n"
+       "                                       float margin=0.f;\n"
+       "                                       b3TransformAabb2(treeBminLocal,treeBmaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);\n"
+       "                                       \n"
+       "                                       \n"
+       "                                       bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);\n"
+       "                                       if (aabbOverlap)\n"
+       "                                       {\n"
+       "                                               \n"
+       "                                               int startNodeIndexA = subtreeA.m_rootNodeIndex+bvhInfos[bvhA].m_nodeOffset;\n"
+       "                                               int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;\n"
+       "                                               int startNodeIndexB = subtreeB.m_rootNodeIndex+bvhInfos[bvhB].m_nodeOffset;\n"
+       "                                               int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;\n"
+       "                                               b3Int2 nodeStack[B3_MAX_STACK_DEPTH];\n"
+       "                                               b3Int2 node0;\n"
+       "                                               node0.x = startNodeIndexA;\n"
+       "                                               node0.y = startNodeIndexB;\n"
+       "                                               int maxStackDepth = B3_MAX_STACK_DEPTH;\n"
+       "                                               int depth=0;\n"
+       "                                               nodeStack[depth++]=node0;\n"
+       "                                               do\n"
+       "                                               {\n"
+       "                                                       b3Int2 node = nodeStack[--depth];\n"
+       "                                                       b3Float4 aMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+       "                                                       b3Float4 aMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
+       "                                                       b3Float4 bMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+       "                                                       b3Float4 bMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
+       "                                                       float margin=0.f;\n"
+       "                                                       b3Float4 aabbAMinOut,aabbAMaxOut;\n"
+       "                                                       b3TransformAabb2(aMinLocal,aMaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);\n"
+       "                                                       b3Float4 aabbBMinOut,aabbBMaxOut;\n"
+       "                                                       b3TransformAabb2(bMinLocal,bMaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);\n"
+       "                                                       \n"
+       "                                                       bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);\n"
+       "                                                       if (nodeOverlap)\n"
+       "                                                       {\n"
+       "                                                               bool isLeafA = isLeafNodeGlobal(&quantizedNodes[node.x]);\n"
+       "                                                               bool isLeafB = isLeafNodeGlobal(&quantizedNodes[node.y]);\n"
+       "                                                               bool isInternalA = !isLeafA;\n"
+       "                                                               bool isInternalB = !isLeafB;\n"
+       "                                                               //fail, even though it might hit two leaf nodes\n"
+       "                                                               if (depth+4>maxStackDepth && !(isLeafA && isLeafB))\n"
+       "                                                               {\n"
+       "                                                                       //printf(\"Error: traversal exceeded maxStackDepth\");\n"
+       "                                                                       continue;\n"
+       "                                                               }\n"
+       "                                                               if(isInternalA)\n"
+       "                                                               {\n"
+       "                                                                       int nodeAleftChild = node.x+1;\n"
+       "                                                                       bool isNodeALeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.x+1]);\n"
+       "                                                                       int nodeArightChild = isNodeALeftChildLeaf? node.x+2 : node.x+1 + getEscapeIndexGlobal(&quantizedNodes[node.x+1]);\n"
+       "                                                                       if(isInternalB)\n"
+       "                                                                       {                                       \n"
+       "                                                                               int nodeBleftChild = node.y+1;\n"
+       "                                                                               bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);\n"
+       "                                                                               int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);\n"
+       "                                                                               nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);\n"
+       "                                                                               nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);\n"
+       "                                                                               nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);\n"
+       "                                                                               nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);\n"
+       "                                                                       }\n"
+       "                                                                       else\n"
+       "                                                                       {\n"
+       "                                                                               nodeStack[depth++] = b3MakeInt2(nodeAleftChild,node.y);\n"
+       "                                                                               nodeStack[depth++] = b3MakeInt2(nodeArightChild,node.y);\n"
+       "                                                                       }\n"
+       "                                                               }\n"
+       "                                                               else\n"
+       "                                                               {\n"
+       "                                                                       if(isInternalB)\n"
+       "                                                                       {\n"
+       "                                                                               int nodeBleftChild = node.y+1;\n"
+       "                                                                               bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);\n"
+       "                                                                               int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);\n"
+       "                                                                               nodeStack[depth++] = b3MakeInt2(node.x,nodeBleftChild);\n"
+       "                                                                               nodeStack[depth++] = b3MakeInt2(node.x,nodeBrightChild);\n"
+       "                                                                       }\n"
+       "                                                                       else\n"
+       "                                                                       {\n"
+       "                                                                               int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+       "                                                                               if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+       "                                                                               {\n"
+       "                                                                                       int childShapeIndexA = getTriangleIndexGlobal(&quantizedNodes[node.x]);\n"
+       "                                                                                       int childShapeIndexB = getTriangleIndexGlobal(&quantizedNodes[node.y]);\n"
+       "                                                                                       gpuCompoundPairsOut[compoundPairIdx]  = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);\n"
+       "                                                                               }\n"
+       "                                                                       }\n"
+       "                                                               }\n"
+       "                                                       }\n"
+       "                                               } while (depth);\n"
+       "                                       }\n"
+       "                               }\n"
+       "                       }\n"
+       "                       \n"
+       "                       return;\n"
+       "               }\n"
+       "               if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+       "               {\n"
+       "                       if (collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) \n"
+       "                       {\n"
+       "                               int numChildrenA = collidables[collidableIndexA].m_numChildShapes;\n"
+       "                               for (int c=0;c<numChildrenA;c++)\n"
+       "                               {\n"
+       "                                       int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex+c;\n"
+       "                                       int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
+       "                                       float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "                                       float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "                                       float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
+       "                                       float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
+       "                                       float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
+       "                                       float4 newOrnA = qtMul(ornA,childOrnA);\n"
+       "                                       int shapeIndexA = collidables[childColIndexA].m_shapeIndex;\n"
+       "                                       b3Aabb_t aabbAlocal = aabbLocalSpace[shapeIndexA];\n"
+       "                                       float margin = 0.f;\n"
+       "                                       \n"
+       "                                       b3Float4 aabbAMinWS;\n"
+       "                                       b3Float4 aabbAMaxWS;\n"
+       "                                       \n"
+       "                                       b3TransformAabb2(aabbAlocal.m_minVec,aabbAlocal.m_maxVec,margin,\n"
+       "                                               newPosA,\n"
+       "                                               newOrnA,\n"
+       "                                               &aabbAMinWS,&aabbAMaxWS);\n"
+       "                                               \n"
+       "                                       \n"
+       "                                       if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "                                       {\n"
+       "                                               int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
+       "                                               for (int b=0;b<numChildrenB;b++)\n"
+       "                                               {\n"
+       "                                                       int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
+       "                                                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+       "                                                       float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+       "                                                       float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                                                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+       "                                                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+       "                                                       float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+       "                                                       float4 newOrnB = qtMul(ornB,childOrnB);\n"
+       "                                                       int shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+       "                                                       b3Aabb_t aabbBlocal = aabbLocalSpace[shapeIndexB];\n"
+       "                                                       \n"
+       "                                                       b3Float4 aabbBMinWS;\n"
+       "                                                       b3Float4 aabbBMaxWS;\n"
+       "                                                       \n"
+       "                                                       b3TransformAabb2(aabbBlocal.m_minVec,aabbBlocal.m_maxVec,margin,\n"
+       "                                                               newPosB,\n"
+       "                                                               newOrnB,\n"
+       "                                                               &aabbBMinWS,&aabbBMaxWS);\n"
+       "                                                               \n"
+       "                                                               \n"
+       "                                                       \n"
+       "                                                       bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinWS,aabbAMaxWS,aabbBMinWS,aabbBMaxWS);\n"
+       "                                                       if (aabbOverlap)\n"
+       "                                                       {\n"
+       "                                                               int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "                                                               float dmin = FLT_MAX;\n"
+       "                                                               float4 posA = newPosA;\n"
+       "                                                               posA.w = 0.f;\n"
+       "                                                               float4 posB = newPosB;\n"
+       "                                                               posB.w = 0.f;\n"
+       "                                                               float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+       "                                                               float4 ornA = newOrnA;\n"
+       "                                                               float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "                                                               float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "                                                               float4 ornB =newOrnB;\n"
+       "                                                               float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "                                                               const float4 DeltaC2 = c0 - c1;\n"
+       "                                                               {//\n"
+       "                                                                       int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+       "                                                                       if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+       "                                                                       {\n"
+       "                                                                               gpuCompoundPairsOut[compoundPairIdx]  = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);\n"
+       "                                                                       }\n"
+       "                                                               }//\n"
+       "                                                       }//fi(1)\n"
+       "                                               } //for (int b=0\n"
+       "                                       }//if (collidables[collidableIndexB].\n"
+       "                                       else//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "                                       {\n"
+       "                                               if (1)\n"
+       "                                               {\n"
+       "                                                       int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "                                                       float dmin = FLT_MAX;\n"
+       "                                                       float4 posA = newPosA;\n"
+       "                                                       posA.w = 0.f;\n"
+       "                                                       float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                                                       posB.w = 0.f;\n"
+       "                                                       float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+       "                                                       float4 ornA = newOrnA;\n"
+       "                                                       float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "                                                       float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "                                                       float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+       "                                                       float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "                                                       const float4 DeltaC2 = c0 - c1;\n"
+       "                                                       {\n"
+       "                                                               int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+       "                                                               if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+       "                                                               {\n"
+       "                                                                       gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,-1);\n"
+       "                                                               }//if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+       "                                                       }//\n"
+       "                                               }//fi (1)\n"
+       "                                       }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "                               }//for (int b=0;b<numChildrenB;b++)     \n"
+       "                               return;\n"
+       "                       }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "                       if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH) \n"
+       "                               && (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+       "                       {\n"
+       "                               int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
+       "                               for (int b=0;b<numChildrenB;b++)\n"
+       "                               {\n"
+       "                                       int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
+       "                                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+       "                                       float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
+       "                                       float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+       "                                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+       "                                       float4 newPosB = qtRotate(ornB,childPosB)+posB;\n"
+       "                                       float4 newOrnB = qtMul(ornB,childOrnB);\n"
+       "                                       int shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+       "                                       //////////////////////////////////////\n"
+       "                                       if (1)\n"
+       "                                       {\n"
+       "                                               int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "                                               float dmin = FLT_MAX;\n"
+       "                                               float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "                                               posA.w = 0.f;\n"
+       "                                               float4 posB = newPosB;\n"
+       "                                               posB.w = 0.f;\n"
+       "                                               float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+       "                                               float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "                                               float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "                                               float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "                                               float4 ornB =newOrnB;\n"
+       "                                               float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "                                               const float4 DeltaC2 = c0 - c1;\n"
+       "                                               {//\n"
+       "                                                       int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
+       "                                                       if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+       "                                                       {\n"
+       "                                                               gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,-1,childShapeIndexB);\n"
+       "                                                       }//fi (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
+       "                                               }//\n"
+       "                                       }//fi (1)       \n"
+       "                               }//for (int b=0;b<numChildrenB;b++)\n"
+       "                               return;\n"
+       "                       }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "                       return;\n"
+       "               }//fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
+       "       }//i<numPairs\n"
+       "}\n"
+       "// work-in-progress\n"
+       "__kernel void   findSeparatingAxisKernel( __global const int4* pairs, \n"
+       "                                                                                                                                                                       __global const BodyData* rigidBodies, \n"
+       "                                                                                                                                                                       __global const btCollidableGpu* collidables,\n"
+       "                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global const float4* uniqueEdges,\n"
+       "                                                                                                                                                                       __global const btGpuFace* faces,\n"
+       "                                                                                                                                                                       __global const int* indices,\n"
+       "                                                                                                                                                                       __global btAabbCL* aabbs,\n"
+       "                                                                                                                                                                       __global volatile float4* separatingNormals,\n"
+       "                                                                                                                                                                       __global volatile int* hasSeparatingAxis,\n"
+       "                                                                                                                                                                       int numPairs\n"
+       "                                                                                                                                                                       )\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       \n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "       \n"
+       "               int bodyIndexA = pairs[i].x;\n"
+       "               int bodyIndexB = pairs[i].y;\n"
+       "               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "       \n"
+       "               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "               \n"
+       "               \n"
+       "               //once the broadphase avoids static-static pairs, we can remove this test\n"
+       "               if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+       "               {\n"
+       "                       hasSeparatingAxis[i] = 0;\n"
+       "                       return;\n"
+       "               }\n"
+       "               \n"
+       "               if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
+       "               {\n"
+       "                       hasSeparatingAxis[i] = 0;\n"
+       "                       return;\n"
+       "               }\n"
+       "                       \n"
+       "               if ((collidables[collidableIndexA].m_shapeType==SHAPE_CONCAVE_TRIMESH))\n"
+       "               {\n"
+       "                       hasSeparatingAxis[i] = 0;\n"
+       "                       return;\n"
+       "               }\n"
+       "               int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "               float dmin = FLT_MAX;\n"
+       "               float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "               posA.w = 0.f;\n"
+       "               float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "               posB.w = 0.f;\n"
+       "               float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+       "               float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "               float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "               float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "               float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+       "               float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "               const float4 DeltaC2 = c0 - c1;\n"
+       "               float4 sepNormal;\n"
+       "               \n"
+       "               bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+       "                                                                                                                                                                                               posB,ornB,\n"
+       "                                                                                                                                                                                               DeltaC2,\n"
+       "                                                                                                                                                                                               vertices,uniqueEdges,faces,\n"
+       "                                                                                                                                                                                               indices,&sepNormal,&dmin);\n"
+       "               hasSeparatingAxis[i] = 4;\n"
+       "               if (!sepA)\n"
+       "               {\n"
+       "                       hasSeparatingAxis[i] = 0;\n"
+       "               } else\n"
+       "               {\n"
+       "                       bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,\n"
+       "                                                                                                                                                                                                       posA,ornA,\n"
+       "                                                                                                                                                                                                       DeltaC2,\n"
+       "                                                                                                                                                                                                       vertices,uniqueEdges,faces,\n"
+       "                                                                                                                                                                                                       indices,&sepNormal,&dmin);\n"
+       "                       if (!sepB)\n"
+       "                       {\n"
+       "                               hasSeparatingAxis[i] = 0;\n"
+       "                       } else\n"
+       "                       {\n"
+       "                               bool sepEE = findSeparatingAxisEdgeEdge(        &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+       "                                                                                                                                                                                                       posB,ornB,\n"
+       "                                                                                                                                                                                                       DeltaC2,\n"
+       "                                                                                                                                                                                                       vertices,uniqueEdges,faces,\n"
+       "                                                                                                                                                                                                       indices,&sepNormal,&dmin);\n"
+       "                               if (!sepEE)\n"
+       "                               {\n"
+       "                                       hasSeparatingAxis[i] = 0;\n"
+       "                               } else\n"
+       "                               {\n"
+       "                                       hasSeparatingAxis[i] = 1;\n"
+       "                                       separatingNormals[i] = sepNormal;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "       }\n"
+       "}\n"
+       "__kernel void   findSeparatingAxisVertexFaceKernel( __global const int4* pairs, \n"
+       "                                                                                                                                                                       __global const BodyData* rigidBodies, \n"
+       "                                                                                                                                                                       __global const btCollidableGpu* collidables,\n"
+       "                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global const float4* uniqueEdges,\n"
+       "                                                                                                                                                                       __global const btGpuFace* faces,\n"
+       "                                                                                                                                                                       __global const int* indices,\n"
+       "                                                                                                                                                                       __global btAabbCL* aabbs,\n"
+       "                                                                                                                                                                       __global volatile float4* separatingNormals,\n"
+       "                                                                                                                                                                       __global volatile int* hasSeparatingAxis,\n"
+       "                                                                                                                                                                       __global  float* dmins,\n"
+       "                                                                                                                                                                       int numPairs\n"
+       "                                                                                                                                                                       )\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       \n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "       \n"
+       "               int bodyIndexA = pairs[i].x;\n"
+       "               int bodyIndexB = pairs[i].y;\n"
+       "               int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "               int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "       \n"
+       "               int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "               int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "       \n"
+       "               hasSeparatingAxis[i] = 0;       \n"
+       "               \n"
+       "               //once the broadphase avoids static-static pairs, we can remove this test\n"
+       "               if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
+       "               {\n"
+       "                       return;\n"
+       "               }\n"
+       "               \n"
+       "               if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
+       "               {\n"
+       "                       return;\n"
+       "               }\n"
+       "                       \n"
+       "               int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "               float dmin = FLT_MAX;\n"
+       "               dmins[i] = dmin;\n"
+       "               \n"
+       "               float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "               posA.w = 0.f;\n"
+       "               float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "               posB.w = 0.f;\n"
+       "               float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+       "               float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "               float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "               float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "               float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+       "               float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "               const float4 DeltaC2 = c0 - c1;\n"
+       "               float4 sepNormal;\n"
+       "               \n"
+       "               bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+       "                                                                                                                                                                                               posB,ornB,\n"
+       "                                                                                                                                                                                               DeltaC2,\n"
+       "                                                                                                                                                                                               vertices,uniqueEdges,faces,\n"
+       "                                                                                                                                                                                               indices,&sepNormal,&dmin);\n"
+       "               hasSeparatingAxis[i] = 4;\n"
+       "               if (!sepA)\n"
+       "               {\n"
+       "                       hasSeparatingAxis[i] = 0;\n"
+       "               } else\n"
+       "               {\n"
+       "                       bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,\n"
+       "                                                                                                                                                                                                       posA,ornA,\n"
+       "                                                                                                                                                                                                       DeltaC2,\n"
+       "                                                                                                                                                                                                       vertices,uniqueEdges,faces,\n"
+       "                                                                                                                                                                                                       indices,&sepNormal,&dmin);\n"
+       "                       if (sepB)\n"
+       "                       {\n"
+       "                               dmins[i] = dmin;\n"
+       "                               hasSeparatingAxis[i] = 1;\n"
+       "                               separatingNormals[i] = sepNormal;\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "       }\n"
+       "}\n"
+       "__kernel void   findSeparatingAxisEdgeEdgeKernel( __global const int4* pairs, \n"
+       "                                                                                                                                                                       __global const BodyData* rigidBodies, \n"
+       "                                                                                                                                                                       __global const btCollidableGpu* collidables,\n"
+       "                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global const float4* uniqueEdges,\n"
+       "                                                                                                                                                                       __global const btGpuFace* faces,\n"
+       "                                                                                                                                                                       __global const int* indices,\n"
+       "                                                                                                                                                                       __global btAabbCL* aabbs,\n"
+       "                                                                                                                                                                       __global  float4* separatingNormals,\n"
+       "                                                                                                                                                                       __global  int* hasSeparatingAxis,\n"
+       "                                                                                                                                                                       __global  float* dmins,\n"
+       "                                                                                                                                                                       __global const float4* unitSphereDirections,\n"
+       "                                                                                                                                                                       int numUnitSphereDirections,\n"
+       "                                                                                                                                                                       int numPairs\n"
+       "                                                                                                                                                                       )\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       \n"
+       "       if (i<numPairs)\n"
+       "       {\n"
+       "               if (hasSeparatingAxis[i])\n"
+       "               {\n"
+       "       \n"
+       "                       int bodyIndexA = pairs[i].x;\n"
+       "                       int bodyIndexB = pairs[i].y;\n"
+       "       \n"
+       "                       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "                       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "               \n"
+       "                       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "                       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "                       \n"
+       "                       \n"
+       "                       int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "       \n"
+       "                       float dmin = dmins[i];\n"
+       "       \n"
+       "                       float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "                       posA.w = 0.f;\n"
+       "                       float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "                       posB.w = 0.f;\n"
+       "                       float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
+       "                       float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "                       float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "                       float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "                       float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+       "                       float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "                       const float4 DeltaC2 = c0 - c1;\n"
+       "                       float4 sepNormal = separatingNormals[i];\n"
+       "                       \n"
+       "                       \n"
+       "                       \n"
+       "                       bool sepEE = false;\n"
+       "                       int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;\n"
+       "                       if (numEdgeEdgeDirections<=numUnitSphereDirections)\n"
+       "                       {\n"
+       "                               sepEE = findSeparatingAxisEdgeEdge(     &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+       "                                                                                                                                                                                                       posB,ornB,\n"
+       "                                                                                                                                                                                                       DeltaC2,\n"
+       "                                                                                                                                                                                                       vertices,uniqueEdges,faces,\n"
+       "                                                                                                                                                                                                       indices,&sepNormal,&dmin);\n"
+       "                                                                                                                                                                                                       \n"
+       "                                       if (!sepEE)\n"
+       "                                       {\n"
+       "                                               hasSeparatingAxis[i] = 0;\n"
+       "                                       } else\n"
+       "                                       {\n"
+       "                                               hasSeparatingAxis[i] = 1;\n"
+       "                                               separatingNormals[i] = sepNormal;\n"
+       "                                       }\n"
+       "                       }\n"
+       "                       /*\n"
+       "                       ///else case is a separate kernel, to make Mac OSX OpenCL compiler happy\n"
+       "                       else\n"
+       "                       {\n"
+       "                               sepEE = findSeparatingAxisUnitSphere(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
+       "                                                                                                                                                                                                       posB,ornB,\n"
+       "                                                                                                                                                                                                       DeltaC2,\n"
+       "                                                                                                                                                                                                       vertices,unitSphereDirections,numUnitSphereDirections,\n"
+       "                                                                                                                                                                                                       &sepNormal,&dmin);\n"
+       "                                       if (!sepEE)\n"
+       "                                       {\n"
+       "                                               hasSeparatingAxis[i] = 0;\n"
+       "                                       } else\n"
+       "                                       {\n"
+       "                                               hasSeparatingAxis[i] = 1;\n"
+       "                                               separatingNormals[i] = sepNormal;\n"
+       "                                       }\n"
+       "                       }\n"
+       "                       */\n"
+       "               }               //if (hasSeparatingAxis[i])\n"
+       "       }//(i<numPairs)\n"
+       "}\n"
+       "inline int     findClippingFaces(const float4 separatingNormal,\n"
+       "                      const ConvexPolyhedronCL* hullA, \n"
+       "                                         __global const ConvexPolyhedronCL* hullB,\n"
+       "                      const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
+       "                       __global float4* worldVertsA1,\n"
+       "                      __global float4* worldNormalsA1,\n"
+       "                      __global float4* worldVertsB1,\n"
+       "                      int capacityWorldVerts,\n"
+       "                      const float minDist, float maxDist,\n"
+       "                                         const float4* verticesA,\n"
+       "                      const btGpuFace* facesA,\n"
+       "                      const int* indicesA,\n"
+       "                                         __global const float4* verticesB,\n"
+       "                      __global const btGpuFace* facesB,\n"
+       "                      __global const int* indicesB,\n"
+       "                      __global int4* clippingFaces, int pairIndex)\n"
+       "{\n"
+       "       int numContactsOut = 0;\n"
+       "       int numWorldVertsB1= 0;\n"
+       "    \n"
+       "    \n"
+       "       int closestFaceB=0;\n"
+       "       float dmax = -FLT_MAX;\n"
+       "    \n"
+       "       {\n"
+       "               for(int face=0;face<hullB->m_numFaces;face++)\n"
+       "               {\n"
+       "                       const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,\n"
+       "                                              facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
+       "                       const float4 WorldNormal = qtRotate(ornB, Normal);\n"
+       "                       float d = dot3F4(WorldNormal,separatingNormal);\n"
+       "                       if (d > dmax)\n"
+       "                       {\n"
+       "                               dmax = d;\n"
+       "                               closestFaceB = face;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "    \n"
+       "       {\n"
+       "               const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
+       "               int numVertices = polyB.m_numIndices;\n"
+       "        if (numVertices>capacityWorldVerts)\n"
+       "            numVertices = capacityWorldVerts;\n"
+       "        \n"
+       "               for(int e0=0;e0<numVertices;e0++)\n"
+       "               {\n"
+       "            if (e0<capacityWorldVerts)\n"
+       "            {\n"
+       "                const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
+       "                worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
+       "            }\n"
+       "               }\n"
+       "       }\n"
+       "    \n"
+       "    int closestFaceA=0;\n"
+       "       {\n"
+       "               float dmin = FLT_MAX;\n"
+       "               for(int face=0;face<hullA->m_numFaces;face++)\n"
+       "               {\n"
+       "                       const float4 Normal = make_float4(\n"
+       "                                              facesA[hullA->m_faceOffset+face].m_plane.x,\n"
+       "                                              facesA[hullA->m_faceOffset+face].m_plane.y,\n"
+       "                                              facesA[hullA->m_faceOffset+face].m_plane.z,\n"
+       "                                              0.f);\n"
+       "                       const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
+       "            \n"
+       "                       float d = dot3F4(faceANormalWS,separatingNormal);\n"
+       "                       if (d < dmin)\n"
+       "                       {\n"
+       "                               dmin = d;\n"
+       "                               closestFaceA = face;\n"
+       "                worldNormalsA1[pairIndex] = faceANormalWS;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "    \n"
+       "    int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
+       "    if (numVerticesA>capacityWorldVerts)\n"
+       "       numVerticesA = capacityWorldVerts;\n"
+       "    \n"
+       "       for(int e0=0;e0<numVerticesA;e0++)\n"
+       "       {\n"
+       "        if (e0<capacityWorldVerts)\n"
+       "        {\n"
+       "            const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
+       "            worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
+       "        }\n"
+       "    }\n"
+       "    \n"
+       "    clippingFaces[pairIndex].x = closestFaceA;\n"
+       "    clippingFaces[pairIndex].y = closestFaceB;\n"
+       "    clippingFaces[pairIndex].z = numVerticesA;\n"
+       "    clippingFaces[pairIndex].w = numWorldVertsB1;\n"
+       "    \n"
+       "    \n"
+       "       return numContactsOut;\n"
+       "}\n"
+       "// work-in-progress\n"
+       "__kernel void   findConcaveSeparatingAxisKernel( __global int4* concavePairs,\n"
+       "                                                                                                                                                                       __global const BodyData* rigidBodies,\n"
+       "                                                                                                                                                                       __global const btCollidableGpu* collidables,\n"
+       "                                                                                                                                                                       __global const ConvexPolyhedronCL* convexShapes, \n"
+       "                                                                                                                                                                       __global const float4* vertices,\n"
+       "                                                                                                                                                                       __global const float4* uniqueEdges,\n"
+       "                                                                                                                                                                       __global const btGpuFace* faces,\n"
+       "                                                                                                                                                                       __global const int* indices,\n"
+       "                                                                                                                                                                       __global const btGpuChildShape* gpuChildShapes,\n"
+       "                                                                                                                                                                       __global btAabbCL* aabbs,\n"
+       "                                                                                                                                                                       __global float4* concaveSeparatingNormalsOut,\n"
+       "                                                                                                                                                                       __global int* concaveHasSeparatingNormals,\n"
+       "                                                                                                                                                                       __global int4* clippingFacesOut,\n"
+       "                                                                                                                                                                       __global float4* worldVertsA1GPU,\n"
+       "                                                                                                                                                                       __global float4*  worldNormalsAGPU,\n"
+       "                                                                                                                                                                       __global float4* worldVertsB1GPU,\n"
+       "                                                                                                                                                                       int vertexFaceCapacity,\n"
+       "                                                                                                                                                                       int numConcavePairs\n"
+       "                                                                                                                                                                       )\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numConcavePairs)\n"
+       "               return;\n"
+       "       concaveHasSeparatingNormals[i] = 0;\n"
+       "       int pairIdx = i;\n"
+       "       int bodyIndexA = concavePairs[i].x;\n"
+       "       int bodyIndexB = concavePairs[i].y;\n"
+       "       int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
+       "       int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
+       "       int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
+       "       int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
+       "       if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&\n"
+       "               collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "       {\n"
+       "               concavePairs[pairIdx].w = -1;\n"
+       "               return;\n"
+       "       }\n"
+       "       int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
+       "       int numActualConcaveConvexTests = 0;\n"
+       "       \n"
+       "       int f = concavePairs[i].z;\n"
+       "       \n"
+       "       bool overlap = false;\n"
+       "       \n"
+       "       ConvexPolyhedronCL convexPolyhedronA;\n"
+       "       //add 3 vertices of the triangle\n"
+       "       convexPolyhedronA.m_numVertices = 3;\n"
+       "       convexPolyhedronA.m_vertexOffset = 0;\n"
+       "       float4  localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
+       "       btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
+       "       float4 triMinAabb, triMaxAabb;\n"
+       "       btAabbCL triAabb;\n"
+       "       triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
+       "       triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
+       "       \n"
+       "       float4 verticesA[3];\n"
+       "       for (int i=0;i<3;i++)\n"
+       "       {\n"
+       "               int index = indices[face.m_indexOffset+i];\n"
+       "               float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
+       "               verticesA[i] = vert;\n"
+       "               localCenter += vert;\n"
+       "                       \n"
+       "               triAabb.m_min = min(triAabb.m_min,vert);                \n"
+       "               triAabb.m_max = max(triAabb.m_max,vert);                \n"
+       "       }\n"
+       "       overlap = true;\n"
+       "       overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
+       "       overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
+       "       overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
+       "               \n"
+       "       if (overlap)\n"
+       "       {\n"
+       "               float dmin = FLT_MAX;\n"
+       "               int hasSeparatingAxis=5;\n"
+       "               float4 sepAxis=make_float4(1,2,3,4);\n"
+       "               int localCC=0;\n"
+       "               numActualConcaveConvexTests++;\n"
+       "               //a triangle has 3 unique edges\n"
+       "               convexPolyhedronA.m_numUniqueEdges = 3;\n"
+       "               convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
+       "               float4 uniqueEdgesA[3];\n"
+       "               \n"
+       "               uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
+       "               uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
+       "               uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
+       "               convexPolyhedronA.m_faceOffset = 0;\n"
+       "                                  \n"
+       "               float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
+       "                             \n"
+       "               btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
+       "               int indicesA[3+3+2+2+2];\n"
+       "               int curUsedIndices=0;\n"
+       "               int fidx=0;\n"
+       "               //front size of triangle\n"
+       "               {\n"
+       "                       facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                       indicesA[0] = 0;\n"
+       "                       indicesA[1] = 1;\n"
+       "                       indicesA[2] = 2;\n"
+       "                       curUsedIndices+=3;\n"
+       "                       float c = face.m_plane.w;\n"
+       "                       facesA[fidx].m_plane.x = normal.x;\n"
+       "                       facesA[fidx].m_plane.y = normal.y;\n"
+       "                       facesA[fidx].m_plane.z = normal.z;\n"
+       "                       facesA[fidx].m_plane.w = c;\n"
+       "                       facesA[fidx].m_numIndices=3;\n"
+       "               }\n"
+       "               fidx++;\n"
+       "               //back size of triangle\n"
+       "               {\n"
+       "                       facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                       indicesA[3]=2;\n"
+       "                       indicesA[4]=1;\n"
+       "                       indicesA[5]=0;\n"
+       "                       curUsedIndices+=3;\n"
+       "                       float c = dot(normal,verticesA[0]);\n"
+       "                       float c1 = -face.m_plane.w;\n"
+       "                       facesA[fidx].m_plane.x = -normal.x;\n"
+       "                       facesA[fidx].m_plane.y = -normal.y;\n"
+       "                       facesA[fidx].m_plane.z = -normal.z;\n"
+       "                       facesA[fidx].m_plane.w = c;\n"
+       "                       facesA[fidx].m_numIndices=3;\n"
+       "               }\n"
+       "               fidx++;\n"
+       "               bool addEdgePlanes = true;\n"
+       "               if (addEdgePlanes)\n"
+       "               {\n"
+       "                       int numVertices=3;\n"
+       "                       int prevVertex = numVertices-1;\n"
+       "                       for (int i=0;i<numVertices;i++)\n"
+       "                       {\n"
+       "                               float4 v0 = verticesA[i];\n"
+       "                               float4 v1 = verticesA[prevVertex];\n"
+       "                                            \n"
+       "                               float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
+       "                               float c = -dot(edgeNormal,v0);\n"
+       "                               facesA[fidx].m_numIndices = 2;\n"
+       "                               facesA[fidx].m_indexOffset=curUsedIndices;\n"
+       "                               indicesA[curUsedIndices++]=i;\n"
+       "                               indicesA[curUsedIndices++]=prevVertex;\n"
+       "                                            \n"
+       "                               facesA[fidx].m_plane.x = edgeNormal.x;\n"
+       "                               facesA[fidx].m_plane.y = edgeNormal.y;\n"
+       "                               facesA[fidx].m_plane.z = edgeNormal.z;\n"
+       "                               facesA[fidx].m_plane.w = c;\n"
+       "                               fidx++;\n"
+       "                               prevVertex = i;\n"
+       "                       }\n"
+       "               }\n"
+       "               convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
+       "               convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
+       "               float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
+       "               posA.w = 0.f;\n"
+       "               float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
+       "               posB.w = 0.f;\n"
+       "               float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
+       "               float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
+       "               \n"
+       "               ///////////////////\n"
+       "               ///compound shape support\n"
+       "               if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
+       "               {\n"
+       "                       int compoundChild = concavePairs[pairIdx].w;\n"
+       "                       int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
+       "                       int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
+       "                       float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
+       "                       float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
+       "                       float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
+       "                       float4 newOrnB = qtMul(ornB,childOrnB);\n"
+       "                       posB = newPosB;\n"
+       "                       ornB = newOrnB;\n"
+       "                       shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
+       "               }\n"
+       "               //////////////////\n"
+       "               float4 c0local = convexPolyhedronA.m_localCenter;\n"
+       "               float4 c0 = transform(&c0local, &posA, &ornA);\n"
+       "               float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
+       "               float4 c1 = transform(&c1local,&posB,&ornB);\n"
+       "               const float4 DeltaC2 = c0 - c1;\n"
+       "               bool sepA = findSeparatingAxisLocalA(   &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+       "                                                                                               posA,ornA,\n"
+       "                                                                                               posB,ornB,\n"
+       "                                                                                               DeltaC2,\n"
+       "                                                                                               verticesA,uniqueEdgesA,facesA,indicesA,\n"
+       "                                                                                               vertices,uniqueEdges,faces,indices,\n"
+       "                                                                                               &sepAxis,&dmin);\n"
+       "               hasSeparatingAxis = 4;\n"
+       "               if (!sepA)\n"
+       "               {\n"
+       "                       hasSeparatingAxis = 0;\n"
+       "               } else\n"
+       "               {\n"
+       "                       bool sepB = findSeparatingAxisLocalB(   &convexShapes[shapeIndexB],&convexPolyhedronA,\n"
+       "                                                                                               posB,ornB,\n"
+       "                                                                                               posA,ornA,\n"
+       "                                                                                               DeltaC2,\n"
+       "                                                                                               vertices,uniqueEdges,faces,indices,\n"
+       "                                                                                               verticesA,uniqueEdgesA,facesA,indicesA,\n"
+       "                                                                                               &sepAxis,&dmin);\n"
+       "                       if (!sepB)\n"
+       "                       {\n"
+       "                               hasSeparatingAxis = 0;\n"
+       "                       } else\n"
+       "                       {\n"
+       "                               bool sepEE = findSeparatingAxisEdgeEdgeLocalA(  &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
+       "                                                                                                                       posA,ornA,\n"
+       "                                                                                                                       posB,ornB,\n"
+       "                                                                                                                       DeltaC2,\n"
+       "                                                                                                                       verticesA,uniqueEdgesA,facesA,indicesA,\n"
+       "                                                                                                                       vertices,uniqueEdges,faces,indices,\n"
+       "                                                                                                                       &sepAxis,&dmin);\n"
+       "       \n"
+       "                               if (!sepEE)\n"
+       "                               {\n"
+       "                                       hasSeparatingAxis = 0;\n"
+       "                               } else\n"
+       "                               {\n"
+       "                                       hasSeparatingAxis = 1;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }       \n"
+       "               \n"
+       "               if (hasSeparatingAxis)\n"
+       "               {\n"
+       "                       sepAxis.w = dmin;\n"
+       "                       concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
+       "                       concaveHasSeparatingNormals[i]=1;\n"
+       "                       float minDist = -1e30f;\n"
+       "                       float maxDist = 0.02f;\n"
+       "               \n"
+       "                       findClippingFaces(sepAxis,\n"
+       "                     &convexPolyhedronA,\n"
+       "                                        &convexShapes[shapeIndexB],\n"
+       "                                        posA,ornA,\n"
+       "                                        posB,ornB,\n"
+       "                      worldVertsA1GPU,\n"
+       "                      worldNormalsAGPU,\n"
+       "                      worldVertsB1GPU,\n"
+       "                                         vertexFaceCapacity,\n"
+       "                      minDist, maxDist,\n"
+       "                      verticesA,\n"
+       "                      facesA,\n"
+       "                      indicesA,\n"
+       "                                         vertices,\n"
+       "                      faces,\n"
+       "                      indices,\n"
+       "                      clippingFacesOut, pairIdx);\n"
+       "               } else\n"
+       "               {       \n"
+       "                       //mark this pair as in-active\n"
+       "                       concavePairs[pairIdx].w = -1;\n"
+       "               }\n"
+       "       }\n"
+       "       else\n"
+       "       {       \n"
+       "               //mark this pair as in-active\n"
+       "               concavePairs[pairIdx].w = -1;\n"
+       "       }\n"
+       "       \n"
+       "       concavePairs[pairIdx].z = -1;//now z is used for existing/persistent contacts\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp
new file mode 100644 (file)
index 0000000..c0e11bf
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+//Host-code rewritten by Erwin Coumans
+
+#define BOUNDSEARCH_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl"
+#define KERNEL0 "SearchSortDataLowerKernel"
+#define KERNEL1 "SearchSortDataUpperKernel"
+#define KERNEL2 "SubtractKernel"
+
+#include "b3BoundSearchCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "b3LauncherCL.h"
+#include "kernels/BoundSearchKernelsCL.h"
+
+b3BoundSearchCL::b3BoundSearchCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int maxSize)
+       : m_context(ctx),
+         m_device(device),
+         m_queue(queue)
+{
+       const char* additionalMacros = "";
+       //const char* srcFileNameForCaching="";
+
+       cl_int pErrNum;
+       const char* kernelSource = boundSearchKernelsCL;
+
+       cl_program boundSearchProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, kernelSource, &pErrNum, additionalMacros, BOUNDSEARCH_PATH);
+       b3Assert(boundSearchProg);
+
+       m_lowerSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SearchSortDataLowerKernel", &pErrNum, boundSearchProg, additionalMacros);
+       b3Assert(m_lowerSortDataKernel);
+
+       m_upperSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SearchSortDataUpperKernel", &pErrNum, boundSearchProg, additionalMacros);
+       b3Assert(m_upperSortDataKernel);
+
+       m_subtractKernel = 0;
+
+       if (maxSize)
+       {
+               m_subtractKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SubtractKernel", &pErrNum, boundSearchProg, additionalMacros);
+               b3Assert(m_subtractKernel);
+       }
+
+       //m_constBuffer = new b3OpenCLArray<b3Int4>( device, 1, BufferBase::BUFFER_CONST );
+
+       m_lower = (maxSize == 0) ? 0 : new b3OpenCLArray<unsigned int>(ctx, queue, maxSize);
+       m_upper = (maxSize == 0) ? 0 : new b3OpenCLArray<unsigned int>(ctx, queue, maxSize);
+
+       m_filler = new b3FillCL(ctx, device, queue);
+}
+
+b3BoundSearchCL::~b3BoundSearchCL()
+{
+       delete m_lower;
+       delete m_upper;
+       delete m_filler;
+
+       clReleaseKernel(m_lowerSortDataKernel);
+       clReleaseKernel(m_upperSortDataKernel);
+       clReleaseKernel(m_subtractKernel);
+}
+
+void b3BoundSearchCL::execute(b3OpenCLArray<b3SortData>& src, int nSrc, b3OpenCLArray<unsigned int>& dst, int nDst, Option option)
+{
+       b3Int4 constBuffer;
+       constBuffer.x = nSrc;
+       constBuffer.y = nDst;
+
+       if (option == BOUND_LOWER)
+       {
+               b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL(), true), b3BufferInfoCL(dst.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_lowerSortDataKernel, "m_lowerSortDataKernel");
+               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(nSrc);
+               launcher.setConst(nDst);
+
+               launcher.launch1D(nSrc, 64);
+       }
+       else if (option == BOUND_UPPER)
+       {
+               b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL(), true), b3BufferInfoCL(dst.getBufferCL())};
+
+               b3LauncherCL launcher(m_queue, m_upperSortDataKernel, "m_upperSortDataKernel");
+               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(nSrc);
+               launcher.setConst(nDst);
+
+               launcher.launch1D(nSrc, 64);
+       }
+       else if (option == COUNT)
+       {
+               b3Assert(m_lower);
+               b3Assert(m_upper);
+               b3Assert(m_lower->capacity() <= (int)nDst);
+               b3Assert(m_upper->capacity() <= (int)nDst);
+
+               int zero = 0;
+               m_filler->execute(*m_lower, zero, nDst);
+               m_filler->execute(*m_upper, zero, nDst);
+
+               execute(src, nSrc, *m_lower, nDst, BOUND_LOWER);
+               execute(src, nSrc, *m_upper, nDst, BOUND_UPPER);
+
+               {
+                       b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_upper->getBufferCL(), true), b3BufferInfoCL(m_lower->getBufferCL(), true), b3BufferInfoCL(dst.getBufferCL())};
+
+                       b3LauncherCL launcher(m_queue, m_subtractKernel, "m_subtractKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(nSrc);
+                       launcher.setConst(nDst);
+
+                       launcher.launch1D(nDst, 64);
+               }
+       }
+       else
+       {
+               b3Assert(0);
+       }
+}
+
+void b3BoundSearchCL::executeHost(b3AlignedObjectArray<b3SortData>& src, int nSrc,
+                                                                 b3AlignedObjectArray<unsigned int>& dst, int nDst, Option option)
+{
+       for (int i = 0; i < nSrc - 1; i++)
+               b3Assert(src[i].m_key <= src[i + 1].m_key);
+
+       b3SortData minData, zeroData, maxData;
+       minData.m_key = -1;
+       minData.m_value = -1;
+       zeroData.m_key = 0;
+       zeroData.m_value = 0;
+       maxData.m_key = nDst;
+       maxData.m_value = nDst;
+
+       if (option == BOUND_LOWER)
+       {
+               for (int i = 0; i < nSrc; i++)
+               {
+                       b3SortData& iData = (i == 0) ? minData : src[i - 1];
+                       b3SortData& jData = (i == nSrc) ? maxData : src[i];
+
+                       if (iData.m_key != jData.m_key)
+                       {
+                               int k = jData.m_key;
+                               {
+                                       dst[k] = i;
+                               }
+                       }
+               }
+       }
+       else if (option == BOUND_UPPER)
+       {
+               for (int i = 1; i < nSrc + 1; i++)
+               {
+                       b3SortData& iData = src[i - 1];
+                       b3SortData& jData = (i == nSrc) ? maxData : src[i];
+
+                       if (iData.m_key != jData.m_key)
+                       {
+                               int k = iData.m_key;
+                               {
+                                       dst[k] = i;
+                               }
+                       }
+               }
+       }
+       else if (option == COUNT)
+       {
+               b3AlignedObjectArray<unsigned int> lower;
+               lower.resize(nDst);
+               b3AlignedObjectArray<unsigned int> upper;
+               upper.resize(nDst);
+
+               for (int i = 0; i < nDst; i++)
+               {
+                       lower[i] = upper[i] = 0;
+               }
+
+               executeHost(src, nSrc, lower, nDst, BOUND_LOWER);
+               executeHost(src, nSrc, upper, nDst, BOUND_UPPER);
+
+               for (int i = 0; i < nDst; i++)
+               {
+                       dst[i] = upper[i] - lower[i];
+               }
+       }
+       else
+       {
+               b3Assert(0);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h
new file mode 100644 (file)
index 0000000..0d633e3
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+#ifndef B3_BOUNDSEARCH_H
+#define B3_BOUNDSEARCH_H
+
+#pragma once
+
+/*#include <Adl/Adl.h>
+#include <AdlPrimitives/Math/Math.h>
+#include <AdlPrimitives/Sort/SortData.h>
+#include <AdlPrimitives/Fill/Fill.h>
+*/
+
+#include "b3OpenCLArray.h"
+#include "b3FillCL.h"
+#include "b3RadixSort32CL.h"  //for b3SortData (perhaps move it?)
+class b3BoundSearchCL
+{
+public:
+       enum Option
+       {
+               BOUND_LOWER,
+               BOUND_UPPER,
+               COUNT,
+       };
+
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_queue;
+
+       cl_kernel m_lowerSortDataKernel;
+       cl_kernel m_upperSortDataKernel;
+       cl_kernel m_subtractKernel;
+
+       b3OpenCLArray<b3Int4>* m_constbtOpenCLArray;
+       b3OpenCLArray<unsigned int>* m_lower;
+       b3OpenCLArray<unsigned int>* m_upper;
+
+       b3FillCL* m_filler;
+
+       b3BoundSearchCL(cl_context context, cl_device_id device, cl_command_queue queue, int size);
+
+       virtual ~b3BoundSearchCL();
+
+       //      src has to be src[i].m_key <= src[i+1].m_key
+       void execute(b3OpenCLArray<b3SortData>& src, int nSrc, b3OpenCLArray<unsigned int>& dst, int nDst, Option option = BOUND_LOWER);
+
+       void executeHost(b3AlignedObjectArray<b3SortData>& src, int nSrc, b3AlignedObjectArray<unsigned int>& dst, int nDst, Option option = BOUND_LOWER);
+};
+
+#endif  //B3_BOUNDSEARCH_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h
new file mode 100644 (file)
index 0000000..35fc467
--- /dev/null
@@ -0,0 +1,18 @@
+
+#ifndef B3_BUFFER_INFO_CL_H
+#define B3_BUFFER_INFO_CL_H
+
+#include "b3OpenCLArray.h"
+
+struct b3BufferInfoCL
+{
+       //b3BufferInfoCL(){}
+
+       //      template<typename T>
+       b3BufferInfoCL(cl_mem buff, bool isReadOnly = false) : m_clBuffer(buff), m_isReadOnly(isReadOnly) {}
+
+       cl_mem m_clBuffer;
+       bool m_isReadOnly;
+};
+
+#endif  //B3_BUFFER_INFO_CL_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp
new file mode 100644 (file)
index 0000000..bd25bb2
--- /dev/null
@@ -0,0 +1,119 @@
+#include "b3FillCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "b3BufferInfoCL.h"
+#include "b3LauncherCL.h"
+
+#define FILL_CL_PROGRAM_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl"
+
+#include "kernels/FillKernelsCL.h"
+
+b3FillCL::b3FillCL(cl_context ctx, cl_device_id device, cl_command_queue queue)
+       : m_commandQueue(queue)
+{
+       const char* kernelSource = fillKernelsCL;
+       cl_int pErrNum;
+       const char* additionalMacros = "";
+
+       cl_program fillProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, kernelSource, &pErrNum, additionalMacros, FILL_CL_PROGRAM_PATH);
+       b3Assert(fillProg);
+
+       m_fillIntKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillIntKernel", &pErrNum, fillProg, additionalMacros);
+       b3Assert(m_fillIntKernel);
+
+       m_fillUnsignedIntKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillUnsignedIntKernel", &pErrNum, fillProg, additionalMacros);
+       b3Assert(m_fillIntKernel);
+
+       m_fillFloatKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillFloatKernel", &pErrNum, fillProg, additionalMacros);
+       b3Assert(m_fillFloatKernel);
+
+       m_fillKernelInt2 = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillInt2Kernel", &pErrNum, fillProg, additionalMacros);
+       b3Assert(m_fillKernelInt2);
+}
+
+b3FillCL::~b3FillCL()
+{
+       clReleaseKernel(m_fillKernelInt2);
+       clReleaseKernel(m_fillIntKernel);
+       clReleaseKernel(m_fillUnsignedIntKernel);
+       clReleaseKernel(m_fillFloatKernel);
+}
+
+void b3FillCL::execute(b3OpenCLArray<float>& src, const float value, int n, int offset)
+{
+       b3Assert(n > 0);
+
+       {
+               b3LauncherCL launcher(m_commandQueue, m_fillFloatKernel, "m_fillFloatKernel");
+               launcher.setBuffer(src.getBufferCL());
+               launcher.setConst(n);
+               launcher.setConst(value);
+               launcher.setConst(offset);
+
+               launcher.launch1D(n);
+       }
+}
+
+void b3FillCL::execute(b3OpenCLArray<int>& src, const int value, int n, int offset)
+{
+       b3Assert(n > 0);
+
+       {
+               b3LauncherCL launcher(m_commandQueue, m_fillIntKernel, "m_fillIntKernel");
+               launcher.setBuffer(src.getBufferCL());
+               launcher.setConst(n);
+               launcher.setConst(value);
+               launcher.setConst(offset);
+               launcher.launch1D(n);
+       }
+}
+
+void b3FillCL::execute(b3OpenCLArray<unsigned int>& src, const unsigned int value, int n, int offset)
+{
+       b3Assert(n > 0);
+
+       {
+               b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL())};
+
+               b3LauncherCL launcher(m_commandQueue, m_fillUnsignedIntKernel, "m_fillUnsignedIntKernel");
+               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(n);
+               launcher.setConst(value);
+               launcher.setConst(offset);
+
+               launcher.launch1D(n);
+       }
+}
+
+void b3FillCL::executeHost(b3AlignedObjectArray<b3Int2>& src, const b3Int2& value, int n, int offset)
+{
+       for (int i = 0; i < n; i++)
+       {
+               src[i + offset] = value;
+       }
+}
+
+void b3FillCL::executeHost(b3AlignedObjectArray<int>& src, const int value, int n, int offset)
+{
+       for (int i = 0; i < n; i++)
+       {
+               src[i + offset] = value;
+       }
+}
+
+void b3FillCL::execute(b3OpenCLArray<b3Int2>& src, const b3Int2& value, int n, int offset)
+{
+       b3Assert(n > 0);
+
+       {
+               b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL())};
+
+               b3LauncherCL launcher(m_commandQueue, m_fillKernelInt2, "m_fillKernelInt2");
+               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(n);
+               launcher.setConst(value);
+               launcher.setConst(offset);
+
+               //( constBuffer );
+               launcher.launch1D(n);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h
new file mode 100644 (file)
index 0000000..c92c3e5
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef B3_FILL_CL_H
+#define B3_FILL_CL_H
+
+#include "b3OpenCLArray.h"
+#include "Bullet3Common/b3Scalar.h"
+
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/shared/b3Int4.h"
+
+class b3FillCL
+{
+       cl_command_queue m_commandQueue;
+
+       cl_kernel m_fillKernelInt2;
+       cl_kernel m_fillIntKernel;
+       cl_kernel m_fillUnsignedIntKernel;
+       cl_kernel m_fillFloatKernel;
+
+public:
+       struct b3ConstData
+       {
+               union {
+                       b3Int4 m_data;
+                       b3UnsignedInt4 m_UnsignedData;
+               };
+               int m_offset;
+               int m_n;
+               int m_padding[2];
+       };
+
+protected:
+public:
+       b3FillCL(cl_context ctx, cl_device_id device, cl_command_queue queue);
+
+       virtual ~b3FillCL();
+
+       void execute(b3OpenCLArray<unsigned int>& src, const unsigned int value, int n, int offset = 0);
+
+       void execute(b3OpenCLArray<int>& src, const int value, int n, int offset = 0);
+
+       void execute(b3OpenCLArray<float>& src, const float value, int n, int offset = 0);
+
+       void execute(b3OpenCLArray<b3Int2>& src, const b3Int2& value, int n, int offset = 0);
+
+       void executeHost(b3AlignedObjectArray<b3Int2>& src, const b3Int2& value, int n, int offset);
+
+       void executeHost(b3AlignedObjectArray<int>& src, const int value, int n, int offset);
+
+       //      void execute(b3OpenCLArray<b3Int4>& src, const b3Int4& value, int n, int offset = 0);
+};
+
+#endif  //B3_FILL_CL_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp
new file mode 100644 (file)
index 0000000..c97d02e
--- /dev/null
@@ -0,0 +1,296 @@
+#include "b3LauncherCL.h"
+
+bool gDebugLauncherCL = false;
+
+b3LauncherCL::b3LauncherCL(cl_command_queue queue, cl_kernel kernel, const char* name)
+       : m_commandQueue(queue),
+         m_kernel(kernel),
+         m_idx(0),
+         m_enableSerialization(false),
+         m_name(name)
+{
+       if (gDebugLauncherCL)
+       {
+               static int counter = 0;
+               printf("[%d] Prepare to launch OpenCL kernel %s\n", counter++, name);
+       }
+
+       m_serializationSizeInBytes = sizeof(int);
+}
+
+b3LauncherCL::~b3LauncherCL()
+{
+       for (int i = 0; i < m_arrays.size(); i++)
+       {
+               delete (m_arrays[i]);
+       }
+
+       m_arrays.clear();
+       if (gDebugLauncherCL)
+       {
+               static int counter = 0;
+               printf("[%d] Finished launching OpenCL kernel %s\n", counter++, m_name);
+       }
+}
+
+void b3LauncherCL::setBuffer(cl_mem clBuffer)
+{
+       if (m_enableSerialization)
+       {
+               b3KernelArgData kernelArg;
+               kernelArg.m_argIndex = m_idx;
+               kernelArg.m_isBuffer = 1;
+               kernelArg.m_clBuffer = clBuffer;
+
+               cl_mem_info param_name = CL_MEM_SIZE;
+               size_t param_value;
+               size_t sizeInBytes = sizeof(size_t);
+               size_t actualSizeInBytes;
+               cl_int err;
+               err = clGetMemObjectInfo(kernelArg.m_clBuffer,
+                                                                param_name,
+                                                                sizeInBytes,
+                                                                &param_value,
+                                                                &actualSizeInBytes);
+
+               b3Assert(err == CL_SUCCESS);
+               kernelArg.m_argSizeInBytes = param_value;
+
+               m_kernelArguments.push_back(kernelArg);
+               m_serializationSizeInBytes += sizeof(b3KernelArgData);
+               m_serializationSizeInBytes += param_value;
+       }
+       cl_int status = clSetKernelArg(m_kernel, m_idx++, sizeof(cl_mem), &clBuffer);
+       b3Assert(status == CL_SUCCESS);
+}
+
+void b3LauncherCL::setBuffers(b3BufferInfoCL* buffInfo, int n)
+{
+       for (int i = 0; i < n; i++)
+       {
+               if (m_enableSerialization)
+               {
+                       b3KernelArgData kernelArg;
+                       kernelArg.m_argIndex = m_idx;
+                       kernelArg.m_isBuffer = 1;
+                       kernelArg.m_clBuffer = buffInfo[i].m_clBuffer;
+
+                       cl_mem_info param_name = CL_MEM_SIZE;
+                       size_t param_value;
+                       size_t sizeInBytes = sizeof(size_t);
+                       size_t actualSizeInBytes;
+                       cl_int err;
+                       err = clGetMemObjectInfo(kernelArg.m_clBuffer,
+                                                                        param_name,
+                                                                        sizeInBytes,
+                                                                        &param_value,
+                                                                        &actualSizeInBytes);
+
+                       b3Assert(err == CL_SUCCESS);
+                       kernelArg.m_argSizeInBytes = param_value;
+
+                       m_kernelArguments.push_back(kernelArg);
+                       m_serializationSizeInBytes += sizeof(b3KernelArgData);
+                       m_serializationSizeInBytes += param_value;
+               }
+               cl_int status = clSetKernelArg(m_kernel, m_idx++, sizeof(cl_mem), &buffInfo[i].m_clBuffer);
+               b3Assert(status == CL_SUCCESS);
+       }
+}
+
+struct b3KernelArgDataUnaligned
+{
+       int m_isBuffer;
+       int m_argIndex;
+       int m_argSizeInBytes;
+       int m_unusedPadding;
+       union {
+               cl_mem m_clBuffer;
+               unsigned char m_argData[B3_CL_MAX_ARG_SIZE];
+       };
+};
+#include <string.h>
+
+int b3LauncherCL::deserializeArgs(unsigned char* buf, int bufSize, cl_context ctx)
+{
+       int index = 0;
+
+       int numArguments = *(int*)&buf[index];
+       index += sizeof(int);
+
+       for (int i = 0; i < numArguments; i++)
+       {
+               b3KernelArgDataUnaligned* arg = (b3KernelArgDataUnaligned*)&buf[index];
+
+               index += sizeof(b3KernelArgData);
+               if (arg->m_isBuffer)
+               {
+                       b3OpenCLArray<unsigned char>* clData = new b3OpenCLArray<unsigned char>(ctx, m_commandQueue, arg->m_argSizeInBytes);
+                       clData->resize(arg->m_argSizeInBytes);
+
+                       clData->copyFromHostPointer(&buf[index], arg->m_argSizeInBytes);
+
+                       arg->m_clBuffer = clData->getBufferCL();
+
+                       m_arrays.push_back(clData);
+
+                       cl_int status = clSetKernelArg(m_kernel, m_idx++, sizeof(cl_mem), &arg->m_clBuffer);
+                       b3Assert(status == CL_SUCCESS);
+                       index += arg->m_argSizeInBytes;
+               }
+               else
+               {
+                       cl_int status = clSetKernelArg(m_kernel, m_idx++, arg->m_argSizeInBytes, &arg->m_argData);
+                       b3Assert(status == CL_SUCCESS);
+               }
+               b3KernelArgData b;
+               memcpy(&b, arg, sizeof(b3KernelArgDataUnaligned));
+               m_kernelArguments.push_back(b);
+       }
+       m_serializationSizeInBytes = index;
+       return index;
+}
+
+int b3LauncherCL::validateResults(unsigned char* goldBuffer, int goldBufferCapacity, cl_context ctx)
+{
+       int index = 0;
+
+       int numArguments = *(int*)&goldBuffer[index];
+       index += sizeof(int);
+
+       if (numArguments != m_kernelArguments.size())
+       {
+               printf("failed validation: expected %d arguments, found %d\n", numArguments, m_kernelArguments.size());
+               return -1;
+       }
+
+       for (int ii = 0; ii < numArguments; ii++)
+       {
+               b3KernelArgData* argGold = (b3KernelArgData*)&goldBuffer[index];
+
+               if (m_kernelArguments[ii].m_argSizeInBytes != argGold->m_argSizeInBytes)
+               {
+                       printf("failed validation: argument %d sizeInBytes expected: %d, found %d\n", ii, argGold->m_argSizeInBytes, m_kernelArguments[ii].m_argSizeInBytes);
+                       return -2;
+               }
+
+               {
+                       int expected = argGold->m_isBuffer;
+                       int found = m_kernelArguments[ii].m_isBuffer;
+
+                       if (expected != found)
+                       {
+                               printf("failed validation: argument %d isBuffer expected: %d, found %d\n", ii, expected, found);
+                               return -3;
+                       }
+               }
+               index += sizeof(b3KernelArgData);
+
+               if (argGold->m_isBuffer)
+               {
+                       unsigned char* memBuf = (unsigned char*)malloc(m_kernelArguments[ii].m_argSizeInBytes);
+                       unsigned char* goldBuf = &goldBuffer[index];
+                       for (int j = 0; j < m_kernelArguments[j].m_argSizeInBytes; j++)
+                       {
+                               memBuf[j] = 0xaa;
+                       }
+
+                       cl_int status = 0;
+                       status = clEnqueueReadBuffer(m_commandQueue, m_kernelArguments[ii].m_clBuffer, CL_TRUE, 0, m_kernelArguments[ii].m_argSizeInBytes,
+                                                                                memBuf, 0, 0, 0);
+                       b3Assert(status == CL_SUCCESS);
+                       clFinish(m_commandQueue);
+
+                       for (int b = 0; b < m_kernelArguments[ii].m_argSizeInBytes; b++)
+                       {
+                               int expected = goldBuf[b];
+                               int found = memBuf[b];
+                               if (expected != found)
+                               {
+                                       printf("failed validation: argument %d OpenCL data at byte position %d expected: %d, found %d\n",
+                                                  ii, b, expected, found);
+                                       return -4;
+                               }
+                       }
+
+                       index += argGold->m_argSizeInBytes;
+               }
+               else
+               {
+                       //compare content
+                       for (int b = 0; b < m_kernelArguments[ii].m_argSizeInBytes; b++)
+                       {
+                               int expected = argGold->m_argData[b];
+                               int found = m_kernelArguments[ii].m_argData[b];
+                               if (expected != found)
+                               {
+                                       printf("failed validation: argument %d const data at byte position %d expected: %d, found %d\n",
+                                                  ii, b, expected, found);
+                                       return -5;
+                               }
+                       }
+               }
+       }
+       return index;
+}
+
+int b3LauncherCL::serializeArguments(unsigned char* destBuffer, int destBufferCapacity)
+{
+       //initialize to known values
+       for (int i = 0; i < destBufferCapacity; i++)
+               destBuffer[i] = 0xec;
+
+       assert(destBufferCapacity >= m_serializationSizeInBytes);
+
+       //todo: use the b3Serializer for this to allow for 32/64bit, endianness etc
+       int numArguments = m_kernelArguments.size();
+       int curBufferSize = 0;
+       int* dest = (int*)&destBuffer[curBufferSize];
+       *dest = numArguments;
+       curBufferSize += sizeof(int);
+
+       for (int i = 0; i < this->m_kernelArguments.size(); i++)
+       {
+               b3KernelArgData* arg = (b3KernelArgData*)&destBuffer[curBufferSize];
+               *arg = m_kernelArguments[i];
+               curBufferSize += sizeof(b3KernelArgData);
+               if (arg->m_isBuffer == 1)
+               {
+                       //copy the OpenCL buffer content
+                       cl_int status = 0;
+                       status = clEnqueueReadBuffer(m_commandQueue, arg->m_clBuffer, 0, 0, arg->m_argSizeInBytes,
+                                                                                &destBuffer[curBufferSize], 0, 0, 0);
+                       b3Assert(status == CL_SUCCESS);
+                       clFinish(m_commandQueue);
+                       curBufferSize += arg->m_argSizeInBytes;
+               }
+       }
+       return curBufferSize;
+}
+
+void b3LauncherCL::serializeToFile(const char* fileName, int numWorkItems)
+{
+       int num = numWorkItems;
+       int buffSize = getSerializationBufferSize();
+       unsigned char* buf = new unsigned char[buffSize + sizeof(int)];
+       for (int i = 0; i < buffSize + 1; i++)
+       {
+               unsigned char* ptr = (unsigned char*)&buf[i];
+               *ptr = 0xff;
+       }
+       //      int actualWrite = serializeArguments(buf,buffSize);
+
+       //      unsigned char* cptr = (unsigned char*)&buf[buffSize];
+       //            printf("buf[buffSize] = %d\n",*cptr);
+
+       assert(buf[buffSize] == 0xff);  //check for buffer overrun
+       int* ptr = (int*)&buf[buffSize];
+
+       *ptr = num;
+
+       FILE* f = fopen(fileName, "wb");
+       fwrite(buf, buffSize + sizeof(int), 1, f);
+       fclose(f);
+
+       delete[] buf;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h
new file mode 100644 (file)
index 0000000..18e9c1d
--- /dev/null
@@ -0,0 +1,128 @@
+
+#ifndef B3_LAUNCHER_CL_H
+#define B3_LAUNCHER_CL_H
+
+#include "b3BufferInfoCL.h"
+#include "Bullet3Common/b3MinMax.h"
+#include "b3OpenCLArray.h"
+#include <stdio.h>
+
+#define B3_DEBUG_SERIALIZE_CL
+
+#ifdef _WIN32
+#pragma warning(disable : 4996)
+#endif
+#define B3_CL_MAX_ARG_SIZE 16
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3KernelArgData
+{
+       int m_isBuffer;
+       int m_argIndex;
+       int m_argSizeInBytes;
+       int m_unusedPadding;
+       union {
+               cl_mem m_clBuffer;
+               unsigned char m_argData[B3_CL_MAX_ARG_SIZE];
+       };
+};
+
+class b3LauncherCL
+{
+       cl_command_queue m_commandQueue;
+       cl_kernel m_kernel;
+       int m_idx;
+
+       b3AlignedObjectArray<b3KernelArgData> m_kernelArguments;
+       int m_serializationSizeInBytes;
+       bool m_enableSerialization;
+
+       const char* m_name;
+
+public:
+       b3AlignedObjectArray<b3OpenCLArray<unsigned char>*> m_arrays;
+
+       b3LauncherCL(cl_command_queue queue, cl_kernel kernel, const char* name);
+
+       virtual ~b3LauncherCL();
+
+       void setBuffer(cl_mem clBuffer);
+
+       void setBuffers(b3BufferInfoCL* buffInfo, int n);
+
+       int getSerializationBufferSize() const
+       {
+               return m_serializationSizeInBytes;
+       }
+
+       int deserializeArgs(unsigned char* buf, int bufSize, cl_context ctx);
+
+       inline int validateResults(unsigned char* goldBuffer, int goldBufferCapacity, cl_context ctx);
+
+       int serializeArguments(unsigned char* destBuffer, int destBufferCapacity);
+
+       int getNumArguments() const
+       {
+               return m_kernelArguments.size();
+       }
+
+       b3KernelArgData getArgument(int index)
+       {
+               return m_kernelArguments[index];
+       }
+
+       void serializeToFile(const char* fileName, int numWorkItems);
+
+       template <typename T>
+       inline void setConst(const T& consts)
+       {
+               int sz = sizeof(T);
+               b3Assert(sz <= B3_CL_MAX_ARG_SIZE);
+
+               if (m_enableSerialization)
+               {
+                       b3KernelArgData kernelArg;
+                       kernelArg.m_argIndex = m_idx;
+                       kernelArg.m_isBuffer = 0;
+                       T* destArg = (T*)kernelArg.m_argData;
+                       *destArg = consts;
+                       kernelArg.m_argSizeInBytes = sizeof(T);
+                       m_kernelArguments.push_back(kernelArg);
+                       m_serializationSizeInBytes += sizeof(b3KernelArgData);
+               }
+
+               cl_int status = clSetKernelArg(m_kernel, m_idx++, sz, &consts);
+               b3Assert(status == CL_SUCCESS);
+       }
+
+       inline void launch1D(int numThreads, int localSize = 64)
+       {
+               launch2D(numThreads, 1, localSize, 1);
+       }
+
+       inline void launch2D(int numThreadsX, int numThreadsY, int localSizeX, int localSizeY)
+       {
+               size_t gRange[3] = {1, 1, 1};
+               size_t lRange[3] = {1, 1, 1};
+               lRange[0] = localSizeX;
+               lRange[1] = localSizeY;
+               gRange[0] = b3Max((size_t)1, (numThreadsX / lRange[0]) + (!(numThreadsX % lRange[0]) ? 0 : 1));
+               gRange[0] *= lRange[0];
+               gRange[1] = b3Max((size_t)1, (numThreadsY / lRange[1]) + (!(numThreadsY % lRange[1]) ? 0 : 1));
+               gRange[1] *= lRange[1];
+
+               cl_int status = clEnqueueNDRangeKernel(m_commandQueue,
+                                                                                          m_kernel, 2, NULL, gRange, lRange, 0, 0, 0);
+               if (status != CL_SUCCESS)
+               {
+                       printf("Error: OpenCL status = %d\n", status);
+               }
+               b3Assert(status == CL_SUCCESS);
+       }
+
+       void enableSerialization(bool serialize)
+       {
+               m_enableSerialization = serialize;
+       }
+};
+
+#endif  //B3_LAUNCHER_CL_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h
new file mode 100644 (file)
index 0000000..e837cce
--- /dev/null
@@ -0,0 +1,300 @@
+#ifndef B3_OPENCL_ARRAY_H
+#define B3_OPENCL_ARRAY_H
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+
+template <typename T>
+class b3OpenCLArray
+{
+       size_t m_size;
+       size_t m_capacity;
+       cl_mem m_clBuffer;
+
+       cl_context m_clContext;
+       cl_command_queue m_commandQueue;
+
+       bool m_ownsMemory;
+
+       bool m_allowGrowingCapacity;
+
+       void deallocate()
+       {
+               if (m_clBuffer && m_ownsMemory)
+               {
+                       clReleaseMemObject(m_clBuffer);
+               }
+               m_clBuffer = 0;
+               m_capacity = 0;
+       }
+
+       b3OpenCLArray<T>& operator=(const b3OpenCLArray<T>& src);
+
+       B3_FORCE_INLINE size_t allocSize(size_t size)
+       {
+               return (size ? size * 2 : 1);
+       }
+
+public:
+       b3OpenCLArray(cl_context ctx, cl_command_queue queue, size_t initialCapacity = 0, bool allowGrowingCapacity = true)
+               : m_size(0), m_capacity(0), m_clBuffer(0), m_clContext(ctx), m_commandQueue(queue), m_ownsMemory(true), m_allowGrowingCapacity(true)
+       {
+               if (initialCapacity)
+               {
+                       reserve(initialCapacity);
+               }
+               m_allowGrowingCapacity = allowGrowingCapacity;
+       }
+
+       ///this is an error-prone method with no error checking, be careful!
+       void setFromOpenCLBuffer(cl_mem buffer, size_t sizeInElements)
+       {
+               deallocate();
+               m_ownsMemory = false;
+               m_allowGrowingCapacity = false;
+               m_clBuffer = buffer;
+               m_size = sizeInElements;
+               m_capacity = sizeInElements;
+       }
+
+       // we could enable this assignment, but need to make sure to avoid accidental deep copies
+       //      b3OpenCLArray<T>& operator=(const b3AlignedObjectArray<T>& src)
+       //      {
+       //              copyFromArray(src);
+       //              return *this;
+       //      }
+
+       cl_mem getBufferCL() const
+       {
+               return m_clBuffer;
+       }
+
+       virtual ~b3OpenCLArray()
+       {
+               deallocate();
+               m_size = 0;
+               m_capacity = 0;
+       }
+
+       B3_FORCE_INLINE bool push_back(const T& _Val, bool waitForCompletion = true)
+       {
+               bool result = true;
+               size_t sz = size();
+               if (sz == capacity())
+               {
+                       result = reserve(allocSize(size()));
+               }
+               copyFromHostPointer(&_Val, 1, sz, waitForCompletion);
+               m_size++;
+               return result;
+       }
+
+       B3_FORCE_INLINE T forcedAt(size_t n) const
+       {
+               b3Assert(n >= 0);
+               b3Assert(n < capacity());
+               T elem;
+               copyToHostPointer(&elem, 1, n, true);
+               return elem;
+       }
+
+       B3_FORCE_INLINE T at(size_t n) const
+       {
+               b3Assert(n >= 0);
+               b3Assert(n < size());
+               T elem;
+               copyToHostPointer(&elem, 1, n, true);
+               return elem;
+       }
+
+       B3_FORCE_INLINE bool resize(size_t newsize, bool copyOldContents = true)
+       {
+               bool result = true;
+               size_t curSize = size();
+
+               if (newsize < curSize)
+               {
+                       //leave the OpenCL memory for now
+               }
+               else
+               {
+                       if (newsize > size())
+                       {
+                               result = reserve(newsize, copyOldContents);
+                       }
+
+                       //leave new data uninitialized (init in debug mode?)
+                       //for (size_t i=curSize;i<newsize;i++) ...
+               }
+
+               if (result)
+               {
+                       m_size = newsize;
+               }
+               else
+               {
+                       m_size = 0;
+               }
+               return result;
+       }
+
+       B3_FORCE_INLINE size_t size() const
+       {
+               return m_size;
+       }
+
+       B3_FORCE_INLINE size_t capacity() const
+       {
+               return m_capacity;
+       }
+
+       B3_FORCE_INLINE bool reserve(size_t _Count, bool copyOldContents = true)
+       {
+               bool result = true;
+               // determine new minimum length of allocated storage
+               if (capacity() < _Count)
+               {  // not enough room, reallocate
+
+                       if (m_allowGrowingCapacity)
+                       {
+                               cl_int ciErrNum;
+                               //create a new OpenCL buffer
+                               size_t memSizeInBytes = sizeof(T) * _Count;
+                               cl_mem buf = clCreateBuffer(m_clContext, CL_MEM_READ_WRITE, memSizeInBytes, NULL, &ciErrNum);
+                               if (ciErrNum != CL_SUCCESS)
+                               {
+                                       b3Error("OpenCL out-of-memory\n");
+                                       _Count = 0;
+                                       result = false;
+                               }
+//#define B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
+#ifdef B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
+                               unsigned char* src = (unsigned char*)malloc(memSizeInBytes);
+                               for (size_t i = 0; i < memSizeInBytes; i++)
+                                       src[i] = 0xbb;
+                               ciErrNum = clEnqueueWriteBuffer(m_commandQueue, buf, CL_TRUE, 0, memSizeInBytes, src, 0, 0, 0);
+                               b3Assert(ciErrNum == CL_SUCCESS);
+                               clFinish(m_commandQueue);
+                               free(src);
+#endif  //B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
+
+                               if (result)
+                               {
+                                       if (copyOldContents)
+                                               copyToCL(buf, size());
+                               }
+
+                               //deallocate the old buffer
+                               deallocate();
+
+                               m_clBuffer = buf;
+
+                               m_capacity = _Count;
+                       }
+                       else
+                       {
+                               //fail: assert and
+                               b3Assert(0);
+                               deallocate();
+                               result = false;
+                       }
+               }
+               return result;
+       }
+
+       void copyToCL(cl_mem destination, size_t numElements, size_t firstElem = 0, size_t dstOffsetInElems = 0) const
+       {
+               if (numElements <= 0)
+                       return;
+
+               b3Assert(m_clBuffer);
+               b3Assert(destination);
+
+               //likely some error, destination is same as source
+               b3Assert(m_clBuffer != destination);
+
+               b3Assert((firstElem + numElements) <= m_size);
+
+               cl_int status = 0;
+
+               b3Assert(numElements > 0);
+               b3Assert(numElements <= m_size);
+
+               size_t srcOffsetBytes = sizeof(T) * firstElem;
+               size_t dstOffsetInBytes = sizeof(T) * dstOffsetInElems;
+
+               status = clEnqueueCopyBuffer(m_commandQueue, m_clBuffer, destination,
+                                                                        srcOffsetBytes, dstOffsetInBytes, sizeof(T) * numElements, 0, 0, 0);
+
+               b3Assert(status == CL_SUCCESS);
+       }
+
+       void copyFromHost(const b3AlignedObjectArray<T>& srcArray, bool waitForCompletion = true)
+       {
+               size_t newSize = srcArray.size();
+
+               bool copyOldContents = false;
+               resize(newSize, copyOldContents);
+               if (newSize)
+                       copyFromHostPointer(&srcArray[0], newSize, 0, waitForCompletion);
+       }
+
+       void copyFromHostPointer(const T* src, size_t numElems, size_t destFirstElem = 0, bool waitForCompletion = true)
+       {
+               b3Assert(numElems + destFirstElem <= capacity());
+
+               if (numElems + destFirstElem)
+               {
+                       cl_int status = 0;
+                       size_t sizeInBytes = sizeof(T) * numElems;
+                       status = clEnqueueWriteBuffer(m_commandQueue, m_clBuffer, 0, sizeof(T) * destFirstElem, sizeInBytes,
+                                                                                 src, 0, 0, 0);
+                       b3Assert(status == CL_SUCCESS);
+                       if (waitForCompletion)
+                               clFinish(m_commandQueue);
+               }
+               else
+               {
+                       b3Error("copyFromHostPointer invalid range\n");
+               }
+       }
+
+       void copyToHost(b3AlignedObjectArray<T>& destArray, bool waitForCompletion = true) const
+       {
+               destArray.resize(this->size());
+               if (size())
+                       copyToHostPointer(&destArray[0], size(), 0, waitForCompletion);
+       }
+
+       void copyToHostPointer(T* destPtr, size_t numElem, size_t srcFirstElem = 0, bool waitForCompletion = true) const
+       {
+               b3Assert(numElem + srcFirstElem <= capacity());
+
+               if (numElem + srcFirstElem <= capacity())
+               {
+                       cl_int status = 0;
+                       status = clEnqueueReadBuffer(m_commandQueue, m_clBuffer, 0, sizeof(T) * srcFirstElem, sizeof(T) * numElem,
+                                                                                destPtr, 0, 0, 0);
+                       b3Assert(status == CL_SUCCESS);
+
+                       if (waitForCompletion)
+                               clFinish(m_commandQueue);
+               }
+               else
+               {
+                       b3Error("copyToHostPointer invalid range\n");
+               }
+       }
+
+       void copyFromOpenCLArray(const b3OpenCLArray& src)
+       {
+               size_t newSize = src.size();
+               resize(newSize);
+               if (size())
+               {
+                       src.copyToCL(m_clBuffer, size());
+               }
+       }
+};
+
+#endif  //B3_OPENCL_ARRAY_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp
new file mode 100644 (file)
index 0000000..822b511
--- /dev/null
@@ -0,0 +1,120 @@
+#include "b3PrefixScanCL.h"
+#include "b3FillCL.h"
+#define B3_PREFIXSCAN_PROG_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl"
+
+#include "b3LauncherCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "kernels/PrefixScanKernelsCL.h"
+
+b3PrefixScanCL::b3PrefixScanCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size)
+       : m_commandQueue(queue)
+{
+       const char* scanKernelSource = prefixScanKernelsCL;
+       cl_int pErrNum;
+       char* additionalMacros = 0;
+
+       m_workBuffer = new b3OpenCLArray<unsigned int>(ctx, queue, size);
+       cl_program scanProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, scanKernelSource, &pErrNum, additionalMacros, B3_PREFIXSCAN_PROG_PATH);
+       b3Assert(scanProg);
+
+       m_localScanKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "LocalScanKernel", &pErrNum, scanProg, additionalMacros);
+       b3Assert(m_localScanKernel);
+       m_blockSumKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "TopLevelScanKernel", &pErrNum, scanProg, additionalMacros);
+       b3Assert(m_blockSumKernel);
+       m_propagationKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "AddOffsetKernel", &pErrNum, scanProg, additionalMacros);
+       b3Assert(m_propagationKernel);
+}
+
+b3PrefixScanCL::~b3PrefixScanCL()
+{
+       delete m_workBuffer;
+       clReleaseKernel(m_localScanKernel);
+       clReleaseKernel(m_blockSumKernel);
+       clReleaseKernel(m_propagationKernel);
+}
+
+template <class T>
+T b3NextPowerOf2(T n)
+{
+       n -= 1;
+       for (int i = 0; i < sizeof(T) * 8; i++)
+               n = n | (n >> i);
+       return n + 1;
+}
+
+void b3PrefixScanCL::execute(b3OpenCLArray<unsigned int>& src, b3OpenCLArray<unsigned int>& dst, int n, unsigned int* sum)
+{
+       //      b3Assert( data->m_option == EXCLUSIVE );
+       const unsigned int numBlocks = (const unsigned int)((n + BLOCK_SIZE * 2 - 1) / (BLOCK_SIZE * 2));
+
+       dst.resize(src.size());
+       m_workBuffer->resize(src.size());
+
+       b3Int4 constBuffer;
+       constBuffer.x = n;
+       constBuffer.y = numBlocks;
+       constBuffer.z = (int)b3NextPowerOf2(numBlocks);
+
+       b3OpenCLArray<unsigned int>* srcNative = &src;
+       b3OpenCLArray<unsigned int>* dstNative = &dst;
+
+       {
+               b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(srcNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
+
+               b3LauncherCL launcher(m_commandQueue, m_localScanKernel, "m_localScanKernel");
+               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(constBuffer);
+               launcher.launch1D(numBlocks * BLOCK_SIZE, BLOCK_SIZE);
+       }
+
+       {
+               b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_workBuffer->getBufferCL())};
+
+               b3LauncherCL launcher(m_commandQueue, m_blockSumKernel, "m_blockSumKernel");
+               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(constBuffer);
+               launcher.launch1D(BLOCK_SIZE, BLOCK_SIZE);
+       }
+
+       if (numBlocks > 1)
+       {
+               b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
+               b3LauncherCL launcher(m_commandQueue, m_propagationKernel, "m_propagationKernel");
+               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(constBuffer);
+               launcher.launch1D((numBlocks - 1) * BLOCK_SIZE, BLOCK_SIZE);
+       }
+
+       if (sum)
+       {
+               clFinish(m_commandQueue);
+               dstNative->copyToHostPointer(sum, 1, n - 1, true);
+       }
+}
+
+void b3PrefixScanCL::executeHost(b3AlignedObjectArray<unsigned int>& src, b3AlignedObjectArray<unsigned int>& dst, int n, unsigned int* sum)
+{
+       unsigned int s = 0;
+       //if( data->m_option == EXCLUSIVE )
+       {
+               for (int i = 0; i < n; i++)
+               {
+                       dst[i] = s;
+                       s += src[i];
+               }
+       }
+       /*else
+       {
+               for(int i=0; i<n; i++)
+               {
+                       s += hSrc[i];
+                       hDst[i] = s;
+               }
+       }
+       */
+
+       if (sum)
+       {
+               *sum = dst[n - 1];
+       }
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h
new file mode 100644 (file)
index 0000000..346efa0
--- /dev/null
@@ -0,0 +1,35 @@
+
+#ifndef B3_PREFIX_SCAN_CL_H
+#define B3_PREFIX_SCAN_CL_H
+
+#include "b3OpenCLArray.h"
+#include "b3BufferInfoCL.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+class b3PrefixScanCL
+{
+       enum
+       {
+               BLOCK_SIZE = 128
+       };
+
+       //      Option m_option;
+
+       cl_command_queue m_commandQueue;
+
+       cl_kernel m_localScanKernel;
+       cl_kernel m_blockSumKernel;
+       cl_kernel m_propagationKernel;
+
+       b3OpenCLArray<unsigned int>* m_workBuffer;
+
+public:
+       b3PrefixScanCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size = 0);
+
+       virtual ~b3PrefixScanCL();
+
+       void execute(b3OpenCLArray<unsigned int>& src, b3OpenCLArray<unsigned int>& dst, int n, unsigned int* sum = 0);
+       void executeHost(b3AlignedObjectArray<unsigned int>& src, b3AlignedObjectArray<unsigned int>& dst, int n, unsigned int* sum = 0);
+};
+
+#endif  //B3_PREFIX_SCAN_CL_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp
new file mode 100644 (file)
index 0000000..1cac97c
--- /dev/null
@@ -0,0 +1,120 @@
+#include "b3PrefixScanFloat4CL.h"
+#include "b3FillCL.h"
+#define B3_PREFIXSCAN_FLOAT4_PROG_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl"
+
+#include "b3LauncherCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "kernels/PrefixScanKernelsFloat4CL.h"
+
+b3PrefixScanFloat4CL::b3PrefixScanFloat4CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size)
+       : m_commandQueue(queue)
+{
+       const char* scanKernelSource = prefixScanKernelsFloat4CL;
+       cl_int pErrNum;
+       char* additionalMacros = 0;
+
+       m_workBuffer = new b3OpenCLArray<b3Vector3>(ctx, queue, size);
+       cl_program scanProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, scanKernelSource, &pErrNum, additionalMacros, B3_PREFIXSCAN_FLOAT4_PROG_PATH);
+       b3Assert(scanProg);
+
+       m_localScanKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "LocalScanKernel", &pErrNum, scanProg, additionalMacros);
+       b3Assert(m_localScanKernel);
+       m_blockSumKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "TopLevelScanKernel", &pErrNum, scanProg, additionalMacros);
+       b3Assert(m_blockSumKernel);
+       m_propagationKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "AddOffsetKernel", &pErrNum, scanProg, additionalMacros);
+       b3Assert(m_propagationKernel);
+}
+
+b3PrefixScanFloat4CL::~b3PrefixScanFloat4CL()
+{
+       delete m_workBuffer;
+       clReleaseKernel(m_localScanKernel);
+       clReleaseKernel(m_blockSumKernel);
+       clReleaseKernel(m_propagationKernel);
+}
+
+template <class T>
+T b3NextPowerOf2(T n)
+{
+       n -= 1;
+       for (int i = 0; i < sizeof(T) * 8; i++)
+               n = n | (n >> i);
+       return n + 1;
+}
+
+void b3PrefixScanFloat4CL::execute(b3OpenCLArray<b3Vector3>& src, b3OpenCLArray<b3Vector3>& dst, int n, b3Vector3* sum)
+{
+       //      b3Assert( data->m_option == EXCLUSIVE );
+       const unsigned int numBlocks = (const unsigned int)((n + BLOCK_SIZE * 2 - 1) / (BLOCK_SIZE * 2));
+
+       dst.resize(src.size());
+       m_workBuffer->resize(src.size());
+
+       b3Int4 constBuffer;
+       constBuffer.x = n;
+       constBuffer.y = numBlocks;
+       constBuffer.z = (int)b3NextPowerOf2(numBlocks);
+
+       b3OpenCLArray<b3Vector3>* srcNative = &src;
+       b3OpenCLArray<b3Vector3>* dstNative = &dst;
+
+       {
+               b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(srcNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
+
+               b3LauncherCL launcher(m_commandQueue, m_localScanKernel, "m_localScanKernel");
+               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(constBuffer);
+               launcher.launch1D(numBlocks * BLOCK_SIZE, BLOCK_SIZE);
+       }
+
+       {
+               b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_workBuffer->getBufferCL())};
+
+               b3LauncherCL launcher(m_commandQueue, m_blockSumKernel, "m_blockSumKernel");
+               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(constBuffer);
+               launcher.launch1D(BLOCK_SIZE, BLOCK_SIZE);
+       }
+
+       if (numBlocks > 1)
+       {
+               b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
+               b3LauncherCL launcher(m_commandQueue, m_propagationKernel, "m_propagationKernel");
+               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+               launcher.setConst(constBuffer);
+               launcher.launch1D((numBlocks - 1) * BLOCK_SIZE, BLOCK_SIZE);
+       }
+
+       if (sum)
+       {
+               clFinish(m_commandQueue);
+               dstNative->copyToHostPointer(sum, 1, n - 1, true);
+       }
+}
+
+void b3PrefixScanFloat4CL::executeHost(b3AlignedObjectArray<b3Vector3>& src, b3AlignedObjectArray<b3Vector3>& dst, int n, b3Vector3* sum)
+{
+       b3Vector3 s = b3MakeVector3(0, 0, 0);
+       //if( data->m_option == EXCLUSIVE )
+       {
+               for (int i = 0; i < n; i++)
+               {
+                       dst[i] = s;
+                       s += src[i];
+               }
+       }
+       /*else
+       {
+               for(int i=0; i<n; i++)
+               {
+                       s += hSrc[i];
+                       hDst[i] = s;
+               }
+       }
+       */
+
+       if (sum)
+       {
+               *sum = dst[n - 1];
+       }
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h
new file mode 100644 (file)
index 0000000..122b0bf
--- /dev/null
@@ -0,0 +1,36 @@
+
+#ifndef B3_PREFIX_SCAN_CL_H
+#define B3_PREFIX_SCAN_CL_H
+
+#include "b3OpenCLArray.h"
+#include "b3BufferInfoCL.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Vector3.h"
+
+class b3PrefixScanFloat4CL
+{
+       enum
+       {
+               BLOCK_SIZE = 128
+       };
+
+       //      Option m_option;
+
+       cl_command_queue m_commandQueue;
+
+       cl_kernel m_localScanKernel;
+       cl_kernel m_blockSumKernel;
+       cl_kernel m_propagationKernel;
+
+       b3OpenCLArray<b3Vector3>* m_workBuffer;
+
+public:
+       b3PrefixScanFloat4CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size = 0);
+
+       virtual ~b3PrefixScanFloat4CL();
+
+       void execute(b3OpenCLArray<b3Vector3>& src, b3OpenCLArray<b3Vector3>& dst, int n, b3Vector3* sum = 0);
+       void executeHost(b3AlignedObjectArray<b3Vector3>& src, b3AlignedObjectArray<b3Vector3>& dst, int n, b3Vector3* sum);
+};
+
+#endif  //B3_PREFIX_SCAN_CL_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp
new file mode 100644 (file)
index 0000000..e86af65
--- /dev/null
@@ -0,0 +1,646 @@
+
+#include "b3RadixSort32CL.h"
+#include "b3LauncherCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "b3PrefixScanCL.h"
+#include "b3FillCL.h"
+
+#define RADIXSORT32_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl"
+
+#include "kernels/RadixSort32KernelsCL.h"
+
+b3RadixSort32CL::b3RadixSort32CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int initialCapacity)
+       : m_commandQueue(queue)
+{
+       b3OpenCLDeviceInfo info;
+       b3OpenCLUtils::getDeviceInfo(device, &info);
+       m_deviceCPU = (info.m_deviceType & CL_DEVICE_TYPE_CPU) != 0;
+
+       m_workBuffer1 = new b3OpenCLArray<unsigned int>(ctx, queue);
+       m_workBuffer2 = new b3OpenCLArray<unsigned int>(ctx, queue);
+       m_workBuffer3 = new b3OpenCLArray<b3SortData>(ctx, queue);
+       m_workBuffer3a = new b3OpenCLArray<unsigned int>(ctx, queue);
+       m_workBuffer4 = new b3OpenCLArray<b3SortData>(ctx, queue);
+       m_workBuffer4a = new b3OpenCLArray<unsigned int>(ctx, queue);
+
+       if (initialCapacity > 0)
+       {
+               m_workBuffer1->resize(initialCapacity);
+               m_workBuffer3->resize(initialCapacity);
+               m_workBuffer3a->resize(initialCapacity);
+               m_workBuffer4->resize(initialCapacity);
+               m_workBuffer4a->resize(initialCapacity);
+       }
+
+       m_scan = new b3PrefixScanCL(ctx, device, queue);
+       m_fill = new b3FillCL(ctx, device, queue);
+
+       const char* additionalMacros = "";
+
+       cl_int pErrNum;
+       const char* kernelSource = radixSort32KernelsCL;
+
+       cl_program sortProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, kernelSource, &pErrNum, additionalMacros, RADIXSORT32_PATH);
+       b3Assert(sortProg);
+
+       m_streamCountSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "StreamCountSortDataKernel", &pErrNum, sortProg, additionalMacros);
+       b3Assert(m_streamCountSortDataKernel);
+
+       m_streamCountKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "StreamCountKernel", &pErrNum, sortProg, additionalMacros);
+       b3Assert(m_streamCountKernel);
+
+       if (m_deviceCPU)
+       {
+               m_sortAndScatterSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterSortDataKernelSerial", &pErrNum, sortProg, additionalMacros);
+               b3Assert(m_sortAndScatterSortDataKernel);
+               m_sortAndScatterKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterKernelSerial", &pErrNum, sortProg, additionalMacros);
+               b3Assert(m_sortAndScatterKernel);
+       }
+       else
+       {
+               m_sortAndScatterSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterSortDataKernel", &pErrNum, sortProg, additionalMacros);
+               b3Assert(m_sortAndScatterSortDataKernel);
+               m_sortAndScatterKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterKernel", &pErrNum, sortProg, additionalMacros);
+               b3Assert(m_sortAndScatterKernel);
+       }
+
+       m_prefixScanKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "PrefixScanKernel", &pErrNum, sortProg, additionalMacros);
+       b3Assert(m_prefixScanKernel);
+}
+
+b3RadixSort32CL::~b3RadixSort32CL()
+{
+       delete m_scan;
+       delete m_fill;
+       delete m_workBuffer1;
+       delete m_workBuffer2;
+       delete m_workBuffer3;
+       delete m_workBuffer3a;
+       delete m_workBuffer4;
+       delete m_workBuffer4a;
+
+       clReleaseKernel(m_streamCountSortDataKernel);
+       clReleaseKernel(m_streamCountKernel);
+       clReleaseKernel(m_sortAndScatterSortDataKernel);
+       clReleaseKernel(m_sortAndScatterKernel);
+       clReleaseKernel(m_prefixScanKernel);
+}
+
+void b3RadixSort32CL::executeHost(b3AlignedObjectArray<b3SortData>& inout, int sortBits /* = 32 */)
+{
+       int n = inout.size();
+       const int BITS_PER_PASS = 8;
+       const int NUM_TABLES = (1 << BITS_PER_PASS);
+
+       int tables[NUM_TABLES];
+       int counter[NUM_TABLES];
+
+       b3SortData* src = &inout[0];
+       b3AlignedObjectArray<b3SortData> workbuffer;
+       workbuffer.resize(inout.size());
+       b3SortData* dst = &workbuffer[0];
+
+       int count = 0;
+       for (int startBit = 0; startBit < sortBits; startBit += BITS_PER_PASS)
+       {
+               for (int i = 0; i < NUM_TABLES; i++)
+               {
+                       tables[i] = 0;
+               }
+
+               for (int i = 0; i < n; i++)
+               {
+                       int tableIdx = (src[i].m_key >> startBit) & (NUM_TABLES - 1);
+                       tables[tableIdx]++;
+               }
+//#define TEST
+#ifdef TEST
+               printf("histogram size=%d\n", NUM_TABLES);
+               for (int i = 0; i < NUM_TABLES; i++)
+               {
+                       if (tables[i] != 0)
+                       {
+                               printf("tables[%d]=%d]\n", i, tables[i]);
+                       }
+               }
+#endif  //TEST \
+       //      prefix scan
+               int sum = 0;
+               for (int i = 0; i < NUM_TABLES; i++)
+               {
+                       int iData = tables[i];
+                       tables[i] = sum;
+                       sum += iData;
+                       counter[i] = 0;
+               }
+
+               //      distribute
+               for (int i = 0; i < n; i++)
+               {
+                       int tableIdx = (src[i].m_key >> startBit) & (NUM_TABLES - 1);
+
+                       dst[tables[tableIdx] + counter[tableIdx]] = src[i];
+                       counter[tableIdx]++;
+               }
+
+               b3Swap(src, dst);
+               count++;
+       }
+
+       if (count & 1)
+       {
+               b3Assert(0);  //need to copy
+       }
+}
+
+void b3RadixSort32CL::executeHost(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits /* = 32 */)
+{
+       b3AlignedObjectArray<b3SortData> inout;
+       keyValuesInOut.copyToHost(inout);
+
+       executeHost(inout, sortBits);
+
+       keyValuesInOut.copyFromHost(inout);
+}
+
+void b3RadixSort32CL::execute(b3OpenCLArray<unsigned int>& keysIn, b3OpenCLArray<unsigned int>& keysOut, b3OpenCLArray<unsigned int>& valuesIn,
+                                                         b3OpenCLArray<unsigned int>& valuesOut, int n, int sortBits)
+{
+}
+
+//#define DEBUG_RADIXSORT
+//#define DEBUG_RADIXSORT2
+
+void b3RadixSort32CL::execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits /* = 32 */)
+{
+       int originalSize = keyValuesInOut.size();
+       int workingSize = originalSize;
+
+       int dataAlignment = DATA_ALIGNMENT;
+
+#ifdef DEBUG_RADIXSORT2
+       b3AlignedObjectArray<b3SortData> test2;
+       keyValuesInOut.copyToHost(test2);
+       printf("numElem = %d\n", test2.size());
+       for (int i = 0; i < test2.size(); i++)
+       {
+               printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
+               printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
+       }
+#endif  //DEBUG_RADIXSORT2
+
+       b3OpenCLArray<b3SortData>* src = 0;
+
+       if (workingSize % dataAlignment)
+       {
+               workingSize += dataAlignment - (workingSize % dataAlignment);
+               m_workBuffer4->copyFromOpenCLArray(keyValuesInOut);
+               m_workBuffer4->resize(workingSize);
+               b3SortData fillValue;
+               fillValue.m_key = 0xffffffff;
+               fillValue.m_value = 0xffffffff;
+
+#define USE_BTFILL
+#ifdef USE_BTFILL
+               m_fill->execute((b3OpenCLArray<b3Int2>&)*m_workBuffer4, (b3Int2&)fillValue, workingSize - originalSize, originalSize);
+#else
+               //fill the remaining bits (very slow way, todo: fill on GPU/OpenCL side)
+
+               for (int i = originalSize; i < workingSize; i++)
+               {
+                       m_workBuffer4->copyFromHostPointer(&fillValue, 1, i);
+               }
+#endif  //USE_BTFILL
+
+               src = m_workBuffer4;
+       }
+       else
+       {
+               src = &keyValuesInOut;
+               m_workBuffer4->resize(0);
+       }
+
+       b3Assert(workingSize % DATA_ALIGNMENT == 0);
+       int minCap = NUM_BUCKET * NUM_WGS;
+
+       int n = workingSize;
+
+       m_workBuffer1->resize(minCap);
+       m_workBuffer3->resize(workingSize);
+
+       //      ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 );
+       b3Assert(BITS_PER_PASS == 4);
+       b3Assert(WG_SIZE == 64);
+       b3Assert((sortBits & 0x3) == 0);
+
+       b3OpenCLArray<b3SortData>* dst = m_workBuffer3;
+
+       b3OpenCLArray<unsigned int>* srcHisto = m_workBuffer1;
+       b3OpenCLArray<unsigned int>* destHisto = m_workBuffer2;
+
+       int nWGs = NUM_WGS;
+       b3ConstData cdata;
+
+       {
+               int blockSize = ELEMENTS_PER_WORK_ITEM * WG_SIZE;  //set at 256
+               int nBlocks = (n + blockSize - 1) / (blockSize);
+               cdata.m_n = n;
+               cdata.m_nWGs = NUM_WGS;
+               cdata.m_startBit = 0;
+               cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1) / cdata.m_nWGs;
+               if (nBlocks < NUM_WGS)
+               {
+                       cdata.m_nBlocksPerWG = 1;
+                       nWGs = nBlocks;
+               }
+       }
+
+       int count = 0;
+       for (int ib = 0; ib < sortBits; ib += 4)
+       {
+#ifdef DEBUG_RADIXSORT2
+               keyValuesInOut.copyToHost(test2);
+               printf("numElem = %d\n", test2.size());
+               for (int i = 0; i < test2.size(); i++)
+               {
+                       if (test2[i].m_key != test2[i].m_value)
+                       {
+                               printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
+                               printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
+                       }
+               }
+#endif  //DEBUG_RADIXSORT2
+
+               cdata.m_startBit = ib;
+
+               if (src->size())
+               {
+                       b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(srcHisto->getBufferCL())};
+                       b3LauncherCL launcher(m_commandQueue, m_streamCountSortDataKernel, "m_streamCountSortDataKernel");
+
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(cdata);
+
+                       int num = NUM_WGS * WG_SIZE;
+                       launcher.launch1D(num, WG_SIZE);
+               }
+
+#ifdef DEBUG_RADIXSORT
+               b3AlignedObjectArray<unsigned int> testHist;
+               srcHisto->copyToHost(testHist);
+               printf("ib = %d, testHist size = %d, non zero elements:\n", ib, testHist.size());
+               for (int i = 0; i < testHist.size(); i++)
+               {
+                       if (testHist[i] != 0)
+                               printf("testHist[%d]=%d\n", i, testHist[i]);
+               }
+#endif  //DEBUG_RADIXSORT
+
+//fast prefix scan is not working properly on Mac OSX yet
+#ifdef __APPLE__
+               bool fastScan = false;
+#else
+               bool fastScan = !m_deviceCPU;  //only use fast scan on GPU
+#endif
+
+               if (fastScan)
+               {  //   prefix scan group histogram
+                       b3BufferInfoCL bInfo[] = {b3BufferInfoCL(srcHisto->getBufferCL())};
+                       b3LauncherCL launcher(m_commandQueue, m_prefixScanKernel, "m_prefixScanKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(cdata);
+                       launcher.launch1D(128, 128);
+                       destHisto = srcHisto;
+               }
+               else
+               {
+                       //unsigned int sum; //for debugging
+                       m_scan->execute(*srcHisto, *destHisto, 1920, 0);  //,&sum);
+               }
+
+#ifdef DEBUG_RADIXSORT
+               destHisto->copyToHost(testHist);
+               printf("ib = %d, testHist size = %d, non zero elements:\n", ib, testHist.size());
+               for (int i = 0; i < testHist.size(); i++)
+               {
+                       if (testHist[i] != 0)
+                               printf("testHist[%d]=%d\n", i, testHist[i]);
+               }
+
+               for (int i = 0; i < testHist.size(); i += NUM_WGS)
+               {
+                       printf("testHist[%d]=%d\n", i / NUM_WGS, testHist[i]);
+               }
+
+#endif  //DEBUG_RADIXSORT
+
+#define USE_GPU
+#ifdef USE_GPU
+
+               if (src->size())
+               {  //   local sort and distribute
+                       b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(destHisto->getBufferCL(), true), b3BufferInfoCL(dst->getBufferCL())};
+                       b3LauncherCL launcher(m_commandQueue, m_sortAndScatterSortDataKernel, "m_sortAndScatterSortDataKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(cdata);
+                       launcher.launch1D(nWGs * WG_SIZE, WG_SIZE);
+               }
+#else
+               {
+#define NUM_TABLES 16
+//#define SEQUENTIAL
+#ifdef SEQUENTIAL
+                       int counter2[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+                       int tables[NUM_TABLES];
+                       int startBit = ib;
+
+                       destHisto->copyToHost(testHist);
+                       b3AlignedObjectArray<b3SortData> srcHost;
+                       b3AlignedObjectArray<b3SortData> dstHost;
+                       dstHost.resize(src->size());
+
+                       src->copyToHost(srcHost);
+
+                       for (int i = 0; i < NUM_TABLES; i++)
+                       {
+                               tables[i] = testHist[i * NUM_WGS];
+                       }
+
+                       //      distribute
+                       for (int i = 0; i < n; i++)
+                       {
+                               int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES - 1);
+
+                               dstHost[tables[tableIdx] + counter2[tableIdx]] = srcHost[i];
+                               counter2[tableIdx]++;
+                       }
+
+#else
+
+                       int counter2[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+                       int tables[NUM_TABLES];
+                       b3AlignedObjectArray<b3SortData> dstHostOK;
+                       dstHostOK.resize(src->size());
+
+                       destHisto->copyToHost(testHist);
+                       b3AlignedObjectArray<b3SortData> srcHost;
+                       src->copyToHost(srcHost);
+
+                       int blockSize = 256;
+                       int nBlocksPerWG = cdata.m_nBlocksPerWG;
+                       int startBit = ib;
+
+                       {
+                               for (int i = 0; i < NUM_TABLES; i++)
+                               {
+                                       tables[i] = testHist[i * NUM_WGS];
+                               }
+
+                               //      distribute
+                               for (int i = 0; i < n; i++)
+                               {
+                                       int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES - 1);
+
+                                       dstHostOK[tables[tableIdx] + counter2[tableIdx]] = srcHost[i];
+                                       counter2[tableIdx]++;
+                               }
+                       }
+
+                       b3AlignedObjectArray<b3SortData> dstHost;
+                       dstHost.resize(src->size());
+
+                       int counter[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+                       for (int wgIdx = 0; wgIdx < NUM_WGS; wgIdx++)
+                       {
+                               int counter[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+                               int nBlocks = (n) / blockSize - nBlocksPerWG * wgIdx;
+
+                               for (int iblock = 0; iblock < b3Min(cdata.m_nBlocksPerWG, nBlocks); iblock++)
+                               {
+                                       for (int lIdx = 0; lIdx < 64; lIdx++)
+                                       {
+                                               int addr = iblock * blockSize + blockSize * cdata.m_nBlocksPerWG * wgIdx + ELEMENTS_PER_WORK_ITEM * lIdx;
+
+                                               //      MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
+                                               //      Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
+                                               //      AMD: AtomInc performs better while NV prefers ++
+                                               for (int j = 0; j < ELEMENTS_PER_WORK_ITEM; j++)
+                                               {
+                                                       if (addr + j < n)
+                                                       {
+                                                               //  printf ("addr+j=%d\n", addr+j);
+
+                                                               int i = addr + j;
+
+                                                               int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES - 1);
+
+                                                               int destIndex = testHist[tableIdx * NUM_WGS + wgIdx] + counter[tableIdx];
+
+                                                               b3SortData ok = dstHostOK[destIndex];
+
+                                                               if (ok.m_key != srcHost[i].m_key)
+                                                               {
+                                                                       printf("ok.m_key = %d, srcHost[i].m_key = %d\n", ok.m_key, srcHost[i].m_key);
+                                                                       printf("(ok.m_value = %d, srcHost[i].m_value = %d)\n", ok.m_value, srcHost[i].m_value);
+                                                               }
+                                                               if (ok.m_value != srcHost[i].m_value)
+                                                               {
+                                                                       printf("ok.m_value = %d, srcHost[i].m_value = %d\n", ok.m_value, srcHost[i].m_value);
+                                                                       printf("(ok.m_key = %d, srcHost[i].m_key = %d)\n", ok.m_key, srcHost[i].m_key);
+                                                               }
+
+                                                               dstHost[destIndex] = srcHost[i];
+                                                               counter[tableIdx]++;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+#endif  //SEQUENTIAL
+
+                       dst->copyFromHost(dstHost);
+               }
+#endif  //USE_GPU
+
+#ifdef DEBUG_RADIXSORT
+               destHisto->copyToHost(testHist);
+               printf("ib = %d, testHist size = %d, non zero elements:\n", ib, testHist.size());
+               for (int i = 0; i < testHist.size(); i++)
+               {
+                       if (testHist[i] != 0)
+                               printf("testHist[%d]=%d\n", i, testHist[i]);
+               }
+#endif  //DEBUG_RADIXSORT
+               b3Swap(src, dst);
+               b3Swap(srcHisto, destHisto);
+
+#ifdef DEBUG_RADIXSORT2
+               keyValuesInOut.copyToHost(test2);
+               printf("numElem = %d\n", test2.size());
+               for (int i = 0; i < test2.size(); i++)
+               {
+                       if (test2[i].m_key != test2[i].m_value)
+                       {
+                               printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
+                               printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
+                       }
+               }
+#endif  //DEBUG_RADIXSORT2
+
+               count++;
+       }
+
+       if (count & 1)
+       {
+               b3Assert(0);  //need to copy from workbuffer to keyValuesInOut
+       }
+
+       if (m_workBuffer4->size())
+       {
+               m_workBuffer4->resize(originalSize);
+               keyValuesInOut.copyFromOpenCLArray(*m_workBuffer4);
+       }
+
+#ifdef DEBUG_RADIXSORT
+       keyValuesInOut.copyToHost(test2);
+
+       printf("numElem = %d\n", test2.size());
+       for (int i = 0; i < test2.size(); i++)
+       {
+               printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
+               printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
+       }
+#endif
+}
+
+void b3RadixSort32CL::execute(b3OpenCLArray<unsigned int>& keysInOut, int sortBits /* = 32 */)
+{
+       int originalSize = keysInOut.size();
+       int workingSize = originalSize;
+
+       int dataAlignment = DATA_ALIGNMENT;
+
+       b3OpenCLArray<unsigned int>* src = 0;
+
+       if (workingSize % dataAlignment)
+       {
+               workingSize += dataAlignment - (workingSize % dataAlignment);
+               m_workBuffer4a->copyFromOpenCLArray(keysInOut);
+               m_workBuffer4a->resize(workingSize);
+               unsigned int fillValue = 0xffffffff;
+
+               m_fill->execute(*m_workBuffer4a, fillValue, workingSize - originalSize, originalSize);
+
+               src = m_workBuffer4a;
+       }
+       else
+       {
+               src = &keysInOut;
+               m_workBuffer4a->resize(0);
+       }
+
+       b3Assert(workingSize % DATA_ALIGNMENT == 0);
+       int minCap = NUM_BUCKET * NUM_WGS;
+
+       int n = workingSize;
+
+       m_workBuffer1->resize(minCap);
+       m_workBuffer3->resize(workingSize);
+       m_workBuffer3a->resize(workingSize);
+
+       //      ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 );
+       b3Assert(BITS_PER_PASS == 4);
+       b3Assert(WG_SIZE == 64);
+       b3Assert((sortBits & 0x3) == 0);
+
+       b3OpenCLArray<unsigned int>* dst = m_workBuffer3a;
+
+       b3OpenCLArray<unsigned int>* srcHisto = m_workBuffer1;
+       b3OpenCLArray<unsigned int>* destHisto = m_workBuffer2;
+
+       int nWGs = NUM_WGS;
+       b3ConstData cdata;
+
+       {
+               int blockSize = ELEMENTS_PER_WORK_ITEM * WG_SIZE;  //set at 256
+               int nBlocks = (n + blockSize - 1) / (blockSize);
+               cdata.m_n = n;
+               cdata.m_nWGs = NUM_WGS;
+               cdata.m_startBit = 0;
+               cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1) / cdata.m_nWGs;
+               if (nBlocks < NUM_WGS)
+               {
+                       cdata.m_nBlocksPerWG = 1;
+                       nWGs = nBlocks;
+               }
+       }
+
+       int count = 0;
+       for (int ib = 0; ib < sortBits; ib += 4)
+       {
+               cdata.m_startBit = ib;
+
+               if (src->size())
+               {
+                       b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(srcHisto->getBufferCL())};
+                       b3LauncherCL launcher(m_commandQueue, m_streamCountKernel, "m_streamCountKernel");
+
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(cdata);
+
+                       int num = NUM_WGS * WG_SIZE;
+                       launcher.launch1D(num, WG_SIZE);
+               }
+
+//fast prefix scan is not working properly on Mac OSX yet
+#ifdef __APPLE__
+               bool fastScan = false;
+#else
+               bool fastScan = !m_deviceCPU;
+#endif
+
+               if (fastScan)
+               {  //   prefix scan group histogram
+                       b3BufferInfoCL bInfo[] = {b3BufferInfoCL(srcHisto->getBufferCL())};
+                       b3LauncherCL launcher(m_commandQueue, m_prefixScanKernel, "m_prefixScanKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(cdata);
+                       launcher.launch1D(128, 128);
+                       destHisto = srcHisto;
+               }
+               else
+               {
+                       //unsigned int sum; //for debugging
+                       m_scan->execute(*srcHisto, *destHisto, 1920, 0);  //,&sum);
+               }
+
+               if (src->size())
+               {  //   local sort and distribute
+                       b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(destHisto->getBufferCL(), true), b3BufferInfoCL(dst->getBufferCL())};
+                       b3LauncherCL launcher(m_commandQueue, m_sortAndScatterKernel, "m_sortAndScatterKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(cdata);
+                       launcher.launch1D(nWGs * WG_SIZE, WG_SIZE);
+               }
+
+               b3Swap(src, dst);
+               b3Swap(srcHisto, destHisto);
+
+               count++;
+       }
+
+       if (count & 1)
+       {
+               b3Assert(0);  //need to copy from workbuffer to keyValuesInOut
+       }
+
+       if (m_workBuffer4a->size())
+       {
+               m_workBuffer4a->resize(originalSize);
+               keysInOut.copyFromOpenCLArray(*m_workBuffer4a);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h
new file mode 100644 (file)
index 0000000..69caf18
--- /dev/null
@@ -0,0 +1,84 @@
+
+#ifndef B3_RADIXSORT32_H
+#define B3_RADIXSORT32_H
+
+#include "b3OpenCLArray.h"
+
+struct b3SortData
+{
+       union {
+               unsigned int m_key;
+               unsigned int x;
+       };
+
+       union {
+               unsigned int m_value;
+               unsigned int y;
+       };
+};
+#include "b3BufferInfoCL.h"
+
+class b3RadixSort32CL
+{
+       b3OpenCLArray<unsigned int>* m_workBuffer1;
+       b3OpenCLArray<unsigned int>* m_workBuffer2;
+
+       b3OpenCLArray<b3SortData>* m_workBuffer3;
+       b3OpenCLArray<b3SortData>* m_workBuffer4;
+
+       b3OpenCLArray<unsigned int>* m_workBuffer3a;
+       b3OpenCLArray<unsigned int>* m_workBuffer4a;
+
+       cl_command_queue m_commandQueue;
+
+       cl_kernel m_streamCountSortDataKernel;
+       cl_kernel m_streamCountKernel;
+
+       cl_kernel m_prefixScanKernel;
+       cl_kernel m_sortAndScatterSortDataKernel;
+       cl_kernel m_sortAndScatterKernel;
+
+       bool m_deviceCPU;
+
+       class b3PrefixScanCL* m_scan;
+       class b3FillCL* m_fill;
+
+public:
+       struct b3ConstData
+       {
+               int m_n;
+               int m_nWGs;
+               int m_startBit;
+               int m_nBlocksPerWG;
+       };
+       enum
+       {
+               DATA_ALIGNMENT = 256,
+               WG_SIZE = 64,
+               BLOCK_SIZE = 256,
+               ELEMENTS_PER_WORK_ITEM = (BLOCK_SIZE / WG_SIZE),
+               BITS_PER_PASS = 4,
+               NUM_BUCKET = (1 << BITS_PER_PASS),
+               //      if you change this, change nPerWI in kernel as well
+               NUM_WGS = 20 * 6,  //   cypress
+                                                  //                   NUM_WGS = 24*6, //      cayman
+                                                  //                   NUM_WGS = 32*4, //      nv
+       };
+
+private:
+public:
+       b3RadixSort32CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int initialCapacity = 0);
+
+       virtual ~b3RadixSort32CL();
+
+       void execute(b3OpenCLArray<unsigned int>& keysIn, b3OpenCLArray<unsigned int>& keysOut, b3OpenCLArray<unsigned int>& valuesIn,
+                                b3OpenCLArray<unsigned int>& valuesOut, int n, int sortBits = 32);
+
+       ///keys only
+       void execute(b3OpenCLArray<unsigned int>& keysInOut, int sortBits = 32);
+
+       void execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits = 32);
+       void executeHost(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits = 32);
+       void executeHost(b3AlignedObjectArray<b3SortData>& keyValuesInOut, int sortBits = 32);
+};
+#endif  //B3_RADIXSORT32_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl
new file mode 100644 (file)
index 0000000..f3b4a1e
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+
+typedef struct
+{
+       u32 m_key; 
+       u32 m_value;
+}SortData;
+
+
+
+typedef struct
+{
+       u32 m_nSrc;
+       u32 m_nDst;
+       u32 m_padding[2];
+} ConstBuffer;
+
+
+
+__attribute__((reqd_work_group_size(64,1,1)))
+__kernel
+void SearchSortDataLowerKernel(__global SortData* src, __global u32 *dst, 
+                                       unsigned int nSrc, unsigned int nDst)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < nSrc )
+       {
+               SortData first; first.m_key = (u32)(-1); first.m_value = (u32)(-1);
+               SortData end; end.m_key = nDst; end.m_value = nDst;
+
+               SortData iData = (gIdx==0)? first: src[gIdx-1];
+               SortData jData = (gIdx==nSrc)? end: src[gIdx];
+
+               if( iData.m_key != jData.m_key )
+               {
+//                     for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++)
+                       u32 k = jData.m_key;
+                       {
+                               dst[k] = gIdx;
+                       }
+               }
+       }
+}
+
+
+__attribute__((reqd_work_group_size(64,1,1)))
+__kernel
+void SearchSortDataUpperKernel(__global SortData* src, __global u32 *dst, 
+                                       unsigned int nSrc, unsigned int nDst)
+{
+       int gIdx = GET_GLOBAL_IDX+1;
+
+       if( gIdx < nSrc+1 )
+       {
+               SortData first; first.m_key = 0; first.m_value = 0;
+               SortData end; end.m_key = nDst; end.m_value = nDst;
+
+               SortData iData = src[gIdx-1];
+               SortData jData = (gIdx==nSrc)? end: src[gIdx];
+
+               if( iData.m_key != jData.m_key )
+               {
+                       u32 k = iData.m_key;
+                       {
+                               dst[k] = gIdx;
+                       }
+               }
+       }
+}
+
+__attribute__((reqd_work_group_size(64,1,1)))
+__kernel
+void SubtractKernel(__global u32* A, __global u32 *B, __global u32 *C, 
+                                       unsigned int nSrc, unsigned int nDst)
+{
+       int gIdx = GET_GLOBAL_IDX;
+       
+
+       if( gIdx < nDst )
+       {
+               C[gIdx] = A[gIdx] - B[gIdx];
+       }
+}
+
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h
new file mode 100644 (file)
index 0000000..1758dd4
--- /dev/null
@@ -0,0 +1,86 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* boundSearchKernelsCL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Takahiro Harada\n"
+       "typedef unsigned int u32;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "typedef struct\n"
+       "{\n"
+       "       u32 m_key; \n"
+       "       u32 m_value;\n"
+       "}SortData;\n"
+       "typedef struct\n"
+       "{\n"
+       "       u32 m_nSrc;\n"
+       "       u32 m_nDst;\n"
+       "       u32 m_padding[2];\n"
+       "} ConstBuffer;\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "__kernel\n"
+       "void SearchSortDataLowerKernel(__global SortData* src, __global u32 *dst, \n"
+       "                                       unsigned int nSrc, unsigned int nDst)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < nSrc )\n"
+       "       {\n"
+       "               SortData first; first.m_key = (u32)(-1); first.m_value = (u32)(-1);\n"
+       "               SortData end; end.m_key = nDst; end.m_value = nDst;\n"
+       "               SortData iData = (gIdx==0)? first: src[gIdx-1];\n"
+       "               SortData jData = (gIdx==nSrc)? end: src[gIdx];\n"
+       "               if( iData.m_key != jData.m_key )\n"
+       "               {\n"
+       "//                     for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++)\n"
+       "                       u32 k = jData.m_key;\n"
+       "                       {\n"
+       "                               dst[k] = gIdx;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "__kernel\n"
+       "void SearchSortDataUpperKernel(__global SortData* src, __global u32 *dst, \n"
+       "                                       unsigned int nSrc, unsigned int nDst)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX+1;\n"
+       "       if( gIdx < nSrc+1 )\n"
+       "       {\n"
+       "               SortData first; first.m_key = 0; first.m_value = 0;\n"
+       "               SortData end; end.m_key = nDst; end.m_value = nDst;\n"
+       "               SortData iData = src[gIdx-1];\n"
+       "               SortData jData = (gIdx==nSrc)? end: src[gIdx];\n"
+       "               if( iData.m_key != jData.m_key )\n"
+       "               {\n"
+       "                       u32 k = iData.m_key;\n"
+       "                       {\n"
+       "                               dst[k] = gIdx;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "__kernel\n"
+       "void SubtractKernel(__global u32* A, __global u32 *B, __global u32 *C, \n"
+       "                                       unsigned int nSrc, unsigned int nDst)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       \n"
+       "       if( gIdx < nDst )\n"
+       "       {\n"
+       "               C[gIdx] = A[gIdx] - B[gIdx];\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl
new file mode 100644 (file)
index 0000000..2eee575
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+
+#define make_uint4 (uint4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+typedef struct
+{
+       int m_n;
+       int m_padding[3];
+} ConstBuffer;
+
+
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void Copy1F4Kernel(__global float4* dst, __global float4* src, 
+                                       ConstBuffer cb)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < cb.m_n )
+       {
+               float4 a0 = src[gIdx];
+
+               dst[ gIdx ] = a0;
+       }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void Copy2F4Kernel(__global float4* dst, __global float4* src, 
+                                       ConstBuffer cb)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( 2*gIdx <= cb.m_n )
+       {
+               float4 a0 = src[gIdx*2+0];
+               float4 a1 = src[gIdx*2+1];
+
+               dst[ gIdx*2+0 ] = a0;
+               dst[ gIdx*2+1 ] = a1;
+       }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void Copy4F4Kernel(__global float4* dst, __global float4* src, 
+                                       ConstBuffer cb)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( 4*gIdx <= cb.m_n )
+       {
+               int idx0 = gIdx*4+0;
+               int idx1 = gIdx*4+1;
+               int idx2 = gIdx*4+2;
+               int idx3 = gIdx*4+3;
+
+               float4 a0 = src[idx0];
+               float4 a1 = src[idx1];
+               float4 a2 = src[idx2];
+               float4 a3 = src[idx3];
+
+               dst[ idx0 ] = a0;
+               dst[ idx1 ] = a1;
+               dst[ idx2 ] = a2;
+               dst[ idx3 ] = a3;
+       }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void CopyF1Kernel(__global float* dstF1, __global float* srcF1, 
+                                       ConstBuffer cb)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < cb.m_n )
+       {
+               float a0 = srcF1[gIdx];
+
+               dstF1[ gIdx ] = a0;
+       }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void CopyF2Kernel(__global float2* dstF2, __global float2* srcF2, 
+                                       ConstBuffer cb)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < cb.m_n )
+       {
+               float2 a0 = srcF2[gIdx];
+
+               dstF2[ gIdx ] = a0;
+       }
+}
+
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h
new file mode 100644 (file)
index 0000000..33c9279
--- /dev/null
@@ -0,0 +1,131 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* copyKernelsCL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "\n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Takahiro Harada\n"
+       "\n"
+       "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "\n"
+       "typedef unsigned int u32;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "\n"
+       "#define make_uint4 (uint4)\n"
+       "#define make_uint2 (uint2)\n"
+       "#define make_int2 (int2)\n"
+       "\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_n;\n"
+       "       int m_padding[3];\n"
+       "} ConstBuffer;\n"
+       "\n"
+       "\n"
+       "\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "void Copy1F4Kernel(__global float4* dst, __global float4* src, \n"
+       "                                       ConstBuffer cb)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "\n"
+       "       if( gIdx < cb.m_n )\n"
+       "       {\n"
+       "               float4 a0 = src[gIdx];\n"
+       "\n"
+       "               dst[ gIdx ] = a0;\n"
+       "       }\n"
+       "}\n"
+       "\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "void Copy2F4Kernel(__global float4* dst, __global float4* src, \n"
+       "                                       ConstBuffer cb)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "\n"
+       "       if( 2*gIdx <= cb.m_n )\n"
+       "       {\n"
+       "               float4 a0 = src[gIdx*2+0];\n"
+       "               float4 a1 = src[gIdx*2+1];\n"
+       "\n"
+       "               dst[ gIdx*2+0 ] = a0;\n"
+       "               dst[ gIdx*2+1 ] = a1;\n"
+       "       }\n"
+       "}\n"
+       "\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "void Copy4F4Kernel(__global float4* dst, __global float4* src, \n"
+       "                                       ConstBuffer cb)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "\n"
+       "       if( 4*gIdx <= cb.m_n )\n"
+       "       {\n"
+       "               int idx0 = gIdx*4+0;\n"
+       "               int idx1 = gIdx*4+1;\n"
+       "               int idx2 = gIdx*4+2;\n"
+       "               int idx3 = gIdx*4+3;\n"
+       "\n"
+       "               float4 a0 = src[idx0];\n"
+       "               float4 a1 = src[idx1];\n"
+       "               float4 a2 = src[idx2];\n"
+       "               float4 a3 = src[idx3];\n"
+       "\n"
+       "               dst[ idx0 ] = a0;\n"
+       "               dst[ idx1 ] = a1;\n"
+       "               dst[ idx2 ] = a2;\n"
+       "               dst[ idx3 ] = a3;\n"
+       "       }\n"
+       "}\n"
+       "\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "void CopyF1Kernel(__global float* dstF1, __global float* srcF1, \n"
+       "                                       ConstBuffer cb)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "\n"
+       "       if( gIdx < cb.m_n )\n"
+       "       {\n"
+       "               float a0 = srcF1[gIdx];\n"
+       "\n"
+       "               dstF1[ gIdx ] = a0;\n"
+       "       }\n"
+       "}\n"
+       "\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "void CopyF2Kernel(__global float2* dstF2, __global float2* srcF2, \n"
+       "                                       ConstBuffer cb)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "\n"
+       "       if( gIdx < cb.m_n )\n"
+       "       {\n"
+       "               float2 a0 = srcF2[gIdx];\n"
+       "\n"
+       "               dstF2[ gIdx ] = a0;\n"
+       "       }\n"
+       "}\n"
+       "\n"
+       "\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl
new file mode 100644 (file)
index 0000000..71c3107
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+
+#define make_uint4 (uint4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+typedef struct
+{
+       union
+       {
+               int4 m_data;
+               uint4 m_unsignedData;
+               float   m_floatData;
+       };
+       int m_offset;
+       int m_n;
+       int m_padding[2];
+} ConstBuffer;
+
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void FillIntKernel(__global int* dstInt,                       int num_elements, int value, const int offset)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < num_elements )
+       {
+               dstInt[ offset+gIdx ] = value;
+       }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void FillFloatKernel(__global float* dstFloat,         int num_elements, float value, const int offset)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < num_elements )
+       {
+               dstFloat[ offset+gIdx ] = value;
+       }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void FillUnsignedIntKernel(__global unsigned int* dstInt, const int num, const unsigned int value, const int offset)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < num )
+       {
+               dstInt[ offset+gIdx ] = value;
+       }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void FillInt2Kernel(__global int2* dstInt2,    const int num, const int2 value, const int offset)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < num )
+       {
+               dstInt2[ gIdx + offset] = make_int2( value.x, value.y );
+       }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(64,1,1)))
+void FillInt4Kernel(__global int4* dstInt4,            const int num, const int4 value, const int offset)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < num )
+       {
+               dstInt4[ offset+gIdx ] = value;
+       }
+}
+
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h
new file mode 100644 (file)
index 0000000..983e652
--- /dev/null
@@ -0,0 +1,90 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* fillKernelsCL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Takahiro Harada\n"
+       "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "typedef unsigned int u32;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define make_uint4 (uint4)\n"
+       "#define make_uint2 (uint2)\n"
+       "#define make_int2 (int2)\n"
+       "typedef struct\n"
+       "{\n"
+       "       union\n"
+       "       {\n"
+       "               int4 m_data;\n"
+       "               uint4 m_unsignedData;\n"
+       "               float   m_floatData;\n"
+       "       };\n"
+       "       int m_offset;\n"
+       "       int m_n;\n"
+       "       int m_padding[2];\n"
+       "} ConstBuffer;\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "void FillIntKernel(__global int* dstInt,                       int num_elements, int value, const int offset)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < num_elements )\n"
+       "       {\n"
+       "               dstInt[ offset+gIdx ] = value;\n"
+       "       }\n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "void FillFloatKernel(__global float* dstFloat,         int num_elements, float value, const int offset)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < num_elements )\n"
+       "       {\n"
+       "               dstFloat[ offset+gIdx ] = value;\n"
+       "       }\n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "void FillUnsignedIntKernel(__global unsigned int* dstInt, const int num, const unsigned int value, const int offset)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < num )\n"
+       "       {\n"
+       "               dstInt[ offset+gIdx ] = value;\n"
+       "       }\n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "void FillInt2Kernel(__global int2* dstInt2,    const int num, const int2 value, const int offset)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < num )\n"
+       "       {\n"
+       "               dstInt2[ gIdx + offset] = make_int2( value.x, value.y );\n"
+       "       }\n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "void FillInt4Kernel(__global int4* dstInt4,            const int num, const int4 value, const int offset)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < num )\n"
+       "       {\n"
+       "               dstInt4[ offset+gIdx ] = value;\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl
new file mode 100644 (file)
index 0000000..c9da798
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+
+// takahiro end
+#define WG_SIZE 128 
+#define m_numElems x
+#define m_numBlocks y
+#define m_numScanBlocks z
+
+/*typedef struct
+{
+       uint m_numElems;
+       uint m_numBlocks;
+       uint m_numScanBlocks;
+       uint m_padding[1];
+} ConstBuffer;
+*/
+
+float4 ScanExclusiveFloat4(__local float4* data, u32 n, int lIdx, int lSize)
+{
+       float4 blocksum;
+    int offset = 1;
+    for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)
+    {
+        GROUP_LDS_BARRIER;
+        for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)
+        {
+            int ai = offset*(2*iIdx+1)-1;
+            int bi = offset*(2*iIdx+2)-1;
+            data[bi] += data[ai];
+        }
+       }
+
+    GROUP_LDS_BARRIER;
+
+    if( lIdx == 0 )
+       {
+               blocksum = data[ n-1 ];
+    data[ n-1 ] = 0;
+       }
+
+       GROUP_LDS_BARRIER;
+
+       offset >>= 1;
+    for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )
+    {
+        GROUP_LDS_BARRIER;
+        for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )
+        {
+            int ai = offset*(2*iIdx+1)-1;
+            int bi = offset*(2*iIdx+2)-1;
+            float4 temp = data[ai];
+            data[ai] = data[bi];
+            data[bi] += temp;
+        }
+       }
+       GROUP_LDS_BARRIER;
+
+       return blocksum;
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void LocalScanKernel(__global float4* dst, __global float4* src, __global float4* sumBuffer,   uint4 cb)
+{
+       __local float4 ldsData[WG_SIZE*2];
+
+       int gIdx = GET_GLOBAL_IDX;
+       int lIdx = GET_LOCAL_IDX;
+
+       ldsData[2*lIdx]     = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;
+       ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;
+
+       float4 sum = ScanExclusiveFloat4(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);
+
+       if( lIdx == 0 ) 
+               sumBuffer[GET_GROUP_IDX] = sum;
+
+       if( (2*gIdx) < cb.m_numElems )
+    {
+        dst[2*gIdx]     = ldsData[2*lIdx];
+       }
+       if( (2*gIdx + 1) < cb.m_numElems )
+       {
+        dst[2*gIdx + 1] = ldsData[2*lIdx + 1];
+    }
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void AddOffsetKernel(__global float4* dst, __global float4* blockSum, uint4 cb)
+{
+       const u32 blockSize = WG_SIZE*2;
+
+       int myIdx = GET_GROUP_IDX+1;
+       int lIdx = GET_LOCAL_IDX;
+
+       float4 iBlockSum = blockSum[myIdx];
+
+       int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);
+       for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)
+       {
+               dst[i] += iBlockSum;
+       }
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void TopLevelScanKernel(__global float4* dst, uint4 cb)
+{
+       __local float4 ldsData[2048];
+       int gIdx = GET_GLOBAL_IDX;
+       int lIdx = GET_LOCAL_IDX;
+       int lSize = GET_GROUP_SIZE;
+
+       for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )
+       {
+               ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;
+       }
+
+       GROUP_LDS_BARRIER;
+
+       float4 sum = ScanExclusiveFloat4(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);
+
+       for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )
+       {
+               dst[i] = ldsData[i];
+       }
+
+       if( gIdx == 0 )
+       {
+               dst[cb.m_numBlocks] = sum;
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl
new file mode 100644 (file)
index 0000000..963cc1e
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+
+// takahiro end
+#define WG_SIZE 128 
+#define m_numElems x
+#define m_numBlocks y
+#define m_numScanBlocks z
+
+/*typedef struct
+{
+       uint m_numElems;
+       uint m_numBlocks;
+       uint m_numScanBlocks;
+       uint m_padding[1];
+} ConstBuffer;
+*/
+
+u32 ScanExclusive(__local u32* data, u32 n, int lIdx, int lSize)
+{
+       u32 blocksum;
+    int offset = 1;
+    for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)
+    {
+        GROUP_LDS_BARRIER;
+        for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)
+        {
+            int ai = offset*(2*iIdx+1)-1;
+            int bi = offset*(2*iIdx+2)-1;
+            data[bi] += data[ai];
+        }
+       }
+
+    GROUP_LDS_BARRIER;
+
+    if( lIdx == 0 )
+       {
+               blocksum = data[ n-1 ];
+        data[ n-1 ] = 0;
+       }
+
+       GROUP_LDS_BARRIER;
+
+       offset >>= 1;
+    for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )
+    {
+        GROUP_LDS_BARRIER;
+        for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )
+        {
+            int ai = offset*(2*iIdx+1)-1;
+            int bi = offset*(2*iIdx+2)-1;
+            u32 temp = data[ai];
+            data[ai] = data[bi];
+            data[bi] += temp;
+        }
+       }
+       GROUP_LDS_BARRIER;
+
+       return blocksum;
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void LocalScanKernel(__global u32* dst, __global u32 *src, __global u32 *sumBuffer,
+               uint4 cb)
+{
+       __local u32 ldsData[WG_SIZE*2];
+
+       int gIdx = GET_GLOBAL_IDX;
+       int lIdx = GET_LOCAL_IDX;
+
+       ldsData[2*lIdx]     = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;
+       ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;
+
+       u32 sum = ScanExclusive(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);
+
+       if( lIdx == 0 ) sumBuffer[GET_GROUP_IDX] = sum;
+
+       if( (2*gIdx) < cb.m_numElems )
+    {
+        dst[2*gIdx]     = ldsData[2*lIdx];
+       }
+       if( (2*gIdx + 1) < cb.m_numElems )
+       {
+        dst[2*gIdx + 1] = ldsData[2*lIdx + 1];
+    }
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void AddOffsetKernel(__global u32 *dst, __global u32 *blockSum, uint4 cb)
+{
+       const u32 blockSize = WG_SIZE*2;
+
+       int myIdx = GET_GROUP_IDX+1;
+       int lIdx = GET_LOCAL_IDX;
+
+       u32 iBlockSum = blockSum[myIdx];
+
+       int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);
+       for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)
+       {
+               dst[i] += iBlockSum;
+       }
+}
+
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+__kernel
+void TopLevelScanKernel(__global u32* dst, uint4 cb)
+{
+       __local u32 ldsData[2048];
+       int gIdx = GET_GLOBAL_IDX;
+       int lIdx = GET_LOCAL_IDX;
+       int lSize = GET_GROUP_SIZE;
+
+       for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )
+       {
+               ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;
+       }
+
+       GROUP_LDS_BARRIER;
+
+       u32 sum = ScanExclusive(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);
+
+       for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )
+       {
+               dst[i] = ldsData[i];
+       }
+
+       if( gIdx == 0 )
+       {
+               dst[cb.m_numBlocks] = sum;
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h
new file mode 100644 (file)
index 0000000..fc5e7b8
--- /dev/null
@@ -0,0 +1,128 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* prefixScanKernelsCL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Takahiro Harada\n"
+       "typedef unsigned int u32;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "// takahiro end\n"
+       "#define WG_SIZE 128 \n"
+       "#define m_numElems x\n"
+       "#define m_numBlocks y\n"
+       "#define m_numScanBlocks z\n"
+       "/*typedef struct\n"
+       "{\n"
+       "       uint m_numElems;\n"
+       "       uint m_numBlocks;\n"
+       "       uint m_numScanBlocks;\n"
+       "       uint m_padding[1];\n"
+       "} ConstBuffer;\n"
+       "*/\n"
+       "u32 ScanExclusive(__local u32* data, u32 n, int lIdx, int lSize)\n"
+       "{\n"
+       "       u32 blocksum;\n"
+       "    int offset = 1;\n"
+       "    for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n"
+       "    {\n"
+       "        GROUP_LDS_BARRIER;\n"
+       "        for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)\n"
+       "        {\n"
+       "            int ai = offset*(2*iIdx+1)-1;\n"
+       "            int bi = offset*(2*iIdx+2)-1;\n"
+       "            data[bi] += data[ai];\n"
+       "        }\n"
+       "       }\n"
+       "    GROUP_LDS_BARRIER;\n"
+       "    if( lIdx == 0 )\n"
+       "       {\n"
+       "               blocksum = data[ n-1 ];\n"
+       "        data[ n-1 ] = 0;\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       offset >>= 1;\n"
+       "    for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )\n"
+       "    {\n"
+       "        GROUP_LDS_BARRIER;\n"
+       "        for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )\n"
+       "        {\n"
+       "            int ai = offset*(2*iIdx+1)-1;\n"
+       "            int bi = offset*(2*iIdx+2)-1;\n"
+       "            u32 temp = data[ai];\n"
+       "            data[ai] = data[bi];\n"
+       "            data[bi] += temp;\n"
+       "        }\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       return blocksum;\n"
+       "}\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "__kernel\n"
+       "void LocalScanKernel(__global u32* dst, __global u32 *src, __global u32 *sumBuffer,\n"
+       "               uint4 cb)\n"
+       "{\n"
+       "       __local u32 ldsData[WG_SIZE*2];\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       ldsData[2*lIdx]     = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;\n"
+       "       ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;\n"
+       "       u32 sum = ScanExclusive(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+       "       if( lIdx == 0 ) sumBuffer[GET_GROUP_IDX] = sum;\n"
+       "       if( (2*gIdx) < cb.m_numElems )\n"
+       "    {\n"
+       "        dst[2*gIdx]     = ldsData[2*lIdx];\n"
+       "       }\n"
+       "       if( (2*gIdx + 1) < cb.m_numElems )\n"
+       "       {\n"
+       "        dst[2*gIdx + 1] = ldsData[2*lIdx + 1];\n"
+       "    }\n"
+       "}\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "__kernel\n"
+       "void AddOffsetKernel(__global u32 *dst, __global u32 *blockSum, uint4 cb)\n"
+       "{\n"
+       "       const u32 blockSize = WG_SIZE*2;\n"
+       "       int myIdx = GET_GROUP_IDX+1;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       u32 iBlockSum = blockSum[myIdx];\n"
+       "       int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);\n"
+       "       for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)\n"
+       "       {\n"
+       "               dst[i] += iBlockSum;\n"
+       "       }\n"
+       "}\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "__kernel\n"
+       "void TopLevelScanKernel(__global u32* dst, uint4 cb)\n"
+       "{\n"
+       "       __local u32 ldsData[2048];\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       int lSize = GET_GROUP_SIZE;\n"
+       "       for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )\n"
+       "       {\n"
+       "               ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       u32 sum = ScanExclusive(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+       "       for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )\n"
+       "       {\n"
+       "               dst[i] = ldsData[i];\n"
+       "       }\n"
+       "       if( gIdx == 0 )\n"
+       "       {\n"
+       "               dst[cb.m_numBlocks] = sum;\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h
new file mode 100644 (file)
index 0000000..15d1bc5
--- /dev/null
@@ -0,0 +1,128 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* prefixScanKernelsFloat4CL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Takahiro Harada\n"
+       "typedef unsigned int u32;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "// takahiro end\n"
+       "#define WG_SIZE 128 \n"
+       "#define m_numElems x\n"
+       "#define m_numBlocks y\n"
+       "#define m_numScanBlocks z\n"
+       "/*typedef struct\n"
+       "{\n"
+       "       uint m_numElems;\n"
+       "       uint m_numBlocks;\n"
+       "       uint m_numScanBlocks;\n"
+       "       uint m_padding[1];\n"
+       "} ConstBuffer;\n"
+       "*/\n"
+       "float4 ScanExclusiveFloat4(__local float4* data, u32 n, int lIdx, int lSize)\n"
+       "{\n"
+       "       float4 blocksum;\n"
+       "    int offset = 1;\n"
+       "    for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n"
+       "    {\n"
+       "        GROUP_LDS_BARRIER;\n"
+       "        for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)\n"
+       "        {\n"
+       "            int ai = offset*(2*iIdx+1)-1;\n"
+       "            int bi = offset*(2*iIdx+2)-1;\n"
+       "            data[bi] += data[ai];\n"
+       "        }\n"
+       "       }\n"
+       "    GROUP_LDS_BARRIER;\n"
+       "    if( lIdx == 0 )\n"
+       "       {\n"
+       "               blocksum = data[ n-1 ];\n"
+       "    data[ n-1 ] = 0;\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       offset >>= 1;\n"
+       "    for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )\n"
+       "    {\n"
+       "        GROUP_LDS_BARRIER;\n"
+       "        for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )\n"
+       "        {\n"
+       "            int ai = offset*(2*iIdx+1)-1;\n"
+       "            int bi = offset*(2*iIdx+2)-1;\n"
+       "            float4 temp = data[ai];\n"
+       "            data[ai] = data[bi];\n"
+       "            data[bi] += temp;\n"
+       "        }\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       return blocksum;\n"
+       "}\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "__kernel\n"
+       "void LocalScanKernel(__global float4* dst, __global float4* src, __global float4* sumBuffer,   uint4 cb)\n"
+       "{\n"
+       "       __local float4 ldsData[WG_SIZE*2];\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       ldsData[2*lIdx]     = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;\n"
+       "       ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;\n"
+       "       float4 sum = ScanExclusiveFloat4(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+       "       if( lIdx == 0 ) \n"
+       "               sumBuffer[GET_GROUP_IDX] = sum;\n"
+       "       if( (2*gIdx) < cb.m_numElems )\n"
+       "    {\n"
+       "        dst[2*gIdx]     = ldsData[2*lIdx];\n"
+       "       }\n"
+       "       if( (2*gIdx + 1) < cb.m_numElems )\n"
+       "       {\n"
+       "        dst[2*gIdx + 1] = ldsData[2*lIdx + 1];\n"
+       "    }\n"
+       "}\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "__kernel\n"
+       "void AddOffsetKernel(__global float4* dst, __global float4* blockSum, uint4 cb)\n"
+       "{\n"
+       "       const u32 blockSize = WG_SIZE*2;\n"
+       "       int myIdx = GET_GROUP_IDX+1;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       float4 iBlockSum = blockSum[myIdx];\n"
+       "       int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);\n"
+       "       for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)\n"
+       "       {\n"
+       "               dst[i] += iBlockSum;\n"
+       "       }\n"
+       "}\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "__kernel\n"
+       "void TopLevelScanKernel(__global float4* dst, uint4 cb)\n"
+       "{\n"
+       "       __local float4 ldsData[2048];\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       int lSize = GET_GROUP_SIZE;\n"
+       "       for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )\n"
+       "       {\n"
+       "               ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       float4 sum = ScanExclusiveFloat4(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
+       "       for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )\n"
+       "       {\n"
+       "               dst[i] = ldsData[i];\n"
+       "       }\n"
+       "       if( gIdx == 0 )\n"
+       "       {\n"
+       "               dst[cb.m_numBlocks] = sum;\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl
new file mode 100644 (file)
index 0000000..7402e2f
--- /dev/null
@@ -0,0 +1,1071 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Author Takahiro Harada
+
+
+//#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+
+typedef unsigned int u32;
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AtomAdd(x, value) atom_add(&(x), value)
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+
+#define make_uint4 (uint4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+#define WG_SIZE 64
+#define ELEMENTS_PER_WORK_ITEM (256/WG_SIZE)
+#define BITS_PER_PASS 4
+#define NUM_BUCKET (1<<BITS_PER_PASS)
+typedef uchar u8;
+
+//     this isn't optimization for VLIW. But just reducing writes. 
+#define USE_2LEVEL_REDUCE 1
+
+//#define CHECK_BOUNDARY 1
+
+//#define NV_GPU 1
+
+
+//     Cypress
+#define nPerWI 16
+//     Cayman
+//#define nPerWI 20
+
+#define m_n x
+#define m_nWGs y
+#define m_startBit z
+#define m_nBlocksPerWG w
+
+/*
+typedef struct
+{
+       int m_n;
+       int m_nWGs;
+       int m_startBit;
+       int m_nBlocksPerWG;
+} ConstBuffer;
+*/
+
+typedef struct
+{
+       unsigned int m_key;
+       unsigned int m_value;
+} SortDataCL;
+
+
+uint prefixScanVectorEx( uint4* data )
+{
+       u32 sum = 0;
+       u32 tmp = data[0].x;
+       data[0].x = sum;
+       sum += tmp;
+       tmp = data[0].y;
+       data[0].y = sum;
+       sum += tmp;
+       tmp = data[0].z;
+       data[0].z = sum;
+       sum += tmp;
+       tmp = data[0].w;
+       data[0].w = sum;
+       sum += tmp;
+       return sum;
+}
+
+u32 localPrefixSum( u32 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory, int wgSize /*64 or 128*/ )
+{
+       {       //      Set data
+               sorterSharedMemory[lIdx] = 0;
+               sorterSharedMemory[lIdx+wgSize] = pData;
+       }
+
+       GROUP_LDS_BARRIER;
+
+       {       //      Prefix sum
+               int idx = 2*lIdx + (wgSize+1);
+#if defined(USE_2LEVEL_REDUCE)
+               if( lIdx < 64 )
+               {
+                       u32 u0, u1, u2;
+                       u0 = sorterSharedMemory[idx-3];
+                       u1 = sorterSharedMemory[idx-2];
+                       u2 = sorterSharedMemory[idx-1];
+                       AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );                   
+                       GROUP_MEM_FENCE;
+
+                       u0 = sorterSharedMemory[idx-12];
+                       u1 = sorterSharedMemory[idx-8];
+                       u2 = sorterSharedMemory[idx-4];
+                       AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );                   
+                       GROUP_MEM_FENCE;
+
+                       u0 = sorterSharedMemory[idx-48];
+                       u1 = sorterSharedMemory[idx-32];
+                       u2 = sorterSharedMemory[idx-16];
+                       AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );                   
+                       GROUP_MEM_FENCE;
+                       if( wgSize > 64 )
+                       {
+                               sorterSharedMemory[idx] += sorterSharedMemory[idx-64];
+                               GROUP_MEM_FENCE;
+                       }
+
+                       sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];
+                       GROUP_MEM_FENCE;
+               }
+#else
+               if( lIdx < 64 )
+               {
+                       sorterSharedMemory[idx] += sorterSharedMemory[idx-1];
+                       GROUP_MEM_FENCE;
+                       sorterSharedMemory[idx] += sorterSharedMemory[idx-2];                   
+                       GROUP_MEM_FENCE;
+                       sorterSharedMemory[idx] += sorterSharedMemory[idx-4];
+                       GROUP_MEM_FENCE;
+                       sorterSharedMemory[idx] += sorterSharedMemory[idx-8];
+                       GROUP_MEM_FENCE;
+                       sorterSharedMemory[idx] += sorterSharedMemory[idx-16];
+                       GROUP_MEM_FENCE;
+                       sorterSharedMemory[idx] += sorterSharedMemory[idx-32];
+                       GROUP_MEM_FENCE;
+                       if( wgSize > 64 )
+                       {
+                               sorterSharedMemory[idx] += sorterSharedMemory[idx-64];
+                               GROUP_MEM_FENCE;
+                       }
+
+                       sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];
+                       GROUP_MEM_FENCE;
+               }
+#endif
+       }
+
+       GROUP_LDS_BARRIER;
+
+       *totalSum = sorterSharedMemory[wgSize*2-1];
+       u32 addValue = sorterSharedMemory[lIdx+wgSize-1];
+       return addValue;
+}
+
+//__attribute__((reqd_work_group_size(128,1,1)))
+uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )
+{
+       u32 s4 = prefixScanVectorEx( &pData );
+       u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 128 );
+       return pData + make_uint4( rank, rank, rank, rank );
+}
+
+
+//__attribute__((reqd_work_group_size(64,1,1)))
+uint4 localPrefixSum64V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )
+{
+       u32 s4 = prefixScanVectorEx( &pData );
+       u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 64 );
+       return pData + make_uint4( rank, rank, rank, rank );
+}
+
+u32 unpack4Key( u32 key, int keyIdx ){ return (key>>(keyIdx*8)) & 0xff;}
+
+u32 bit8Scan(u32 v)
+{
+       return (v<<8) + (v<<16) + (v<<24);
+}
+
+//===
+
+
+
+
+#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx]
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void StreamCountKernel( __global u32* gSrc, __global u32* histogramOut, int4 cb )
+{
+       __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];
+
+       u32 gIdx = GET_GLOBAL_IDX;
+       u32 lIdx = GET_LOCAL_IDX;
+       u32 wgIdx = GET_GROUP_IDX;
+       u32 wgSize = GET_GROUP_SIZE;
+       const int startBit = cb.m_startBit;
+       const int n = cb.m_n;
+       const int nWGs = cb.m_nWGs;
+       const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+       for(int i=0; i<NUM_BUCKET; i++)
+       {
+               MY_HISTOGRAM(i) = 0;
+       }
+
+       GROUP_LDS_BARRIER;
+
+       const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+       u32 localKey;
+
+       int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
+
+       int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+       for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
+       {
+               //      MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
+               //      Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
+               //      AMD: AtomInc performs better while NV prefers ++
+               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+               {
+#if defined(CHECK_BOUNDARY)
+                       if( addr+i < n )
+#endif
+                       {
+                               localKey = (gSrc[addr+i]>>startBit) & 0xf;
+#if defined(NV_GPU)
+                               MY_HISTOGRAM( localKey )++;
+#else
+                               AtomInc( MY_HISTOGRAM( localKey ) );
+#endif
+                       }
+               }
+       }
+
+       GROUP_LDS_BARRIER;
+       
+       if( lIdx < NUM_BUCKET )
+       {
+               u32 sum = 0;
+               for(int i=0; i<GET_GROUP_SIZE; i++)
+               {
+                       sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];
+               }
+               histogramOut[lIdx*nWGs+wgIdx] = sum;
+       }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void StreamCountSortDataKernel( __global SortDataCL* gSrc, __global u32* histogramOut, int4  cb )
+{
+       __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];
+
+       u32 gIdx = GET_GLOBAL_IDX;
+       u32 lIdx = GET_LOCAL_IDX;
+       u32 wgIdx = GET_GROUP_IDX;
+       u32 wgSize = GET_GROUP_SIZE;
+       const int startBit = cb.m_startBit;
+       const int n = cb.m_n;
+       const int nWGs = cb.m_nWGs;
+       const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+       for(int i=0; i<NUM_BUCKET; i++)
+       {
+               MY_HISTOGRAM(i) = 0;
+       }
+
+       GROUP_LDS_BARRIER;
+
+       const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+       u32 localKey;
+
+       int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
+
+       int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+       for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
+       {
+               //      MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
+               //      Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
+               //      AMD: AtomInc performs better while NV prefers ++
+               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+               {
+#if defined(CHECK_BOUNDARY)
+                       if( addr+i < n )
+#endif
+                       {
+                               localKey = (gSrc[addr+i].m_key>>startBit) & 0xf;
+#if defined(NV_GPU)
+                               MY_HISTOGRAM( localKey )++;
+#else
+                               AtomInc( MY_HISTOGRAM( localKey ) );
+#endif
+                       }
+               }
+       }
+
+       GROUP_LDS_BARRIER;
+       
+       if( lIdx < NUM_BUCKET )
+       {
+               u32 sum = 0;
+               for(int i=0; i<GET_GROUP_SIZE; i++)
+               {
+                       sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];
+               }
+               histogramOut[lIdx*nWGs+wgIdx] = sum;
+       }
+}
+
+#define nPerLane (nPerWI/4)
+
+//     NUM_BUCKET*nWGs < 128*nPerWI
+__kernel
+__attribute__((reqd_work_group_size(128,1,1)))
+void PrefixScanKernel( __global u32* wHistogram1, int4  cb )
+{
+       __local u32 ldsTopScanData[128*2];
+
+       u32 lIdx = GET_LOCAL_IDX;
+       u32 wgIdx = GET_GROUP_IDX;
+       const int nWGs = cb.m_nWGs;
+
+       u32 data[nPerWI];
+       for(int i=0; i<nPerWI; i++)
+       {
+               data[i] = 0;
+               if( (nPerWI*lIdx+i) < NUM_BUCKET*nWGs )
+                       data[i] = wHistogram1[nPerWI*lIdx+i];
+       }
+
+       uint4 myData = make_uint4(0,0,0,0);
+
+       for(int i=0; i<nPerLane; i++)
+       {
+               myData.x += data[nPerLane*0+i];
+               myData.y += data[nPerLane*1+i];
+               myData.z += data[nPerLane*2+i];
+               myData.w += data[nPerLane*3+i];
+       }
+
+       uint totalSum;
+       uint4 scanned = localPrefixSum128V( myData, lIdx, &totalSum, ldsTopScanData );
+
+//     for(int j=0; j<4; j++) //       somehow it introduces a lot of branches
+       {       int j = 0;
+               u32 sum = 0;
+               for(int i=0; i<nPerLane; i++)
+               {
+                       u32 tmp = data[nPerLane*j+i];
+                       data[nPerLane*j+i] = sum;
+                       sum += tmp;
+               }
+       }
+       {       int j = 1;
+               u32 sum = 0;
+               for(int i=0; i<nPerLane; i++)
+               {
+                       u32 tmp = data[nPerLane*j+i];
+                       data[nPerLane*j+i] = sum;
+                       sum += tmp;
+               }
+       }
+       {       int j = 2;
+               u32 sum = 0;
+               for(int i=0; i<nPerLane; i++)
+               {
+                       u32 tmp = data[nPerLane*j+i];
+                       data[nPerLane*j+i] = sum;
+                       sum += tmp;
+               }
+       }
+       {       int j = 3;
+               u32 sum = 0;
+               for(int i=0; i<nPerLane; i++)
+               {
+                       u32 tmp = data[nPerLane*j+i];
+                       data[nPerLane*j+i] = sum;
+                       sum += tmp;
+               }
+       }
+
+       for(int i=0; i<nPerLane; i++)
+       {
+               data[nPerLane*0+i] += scanned.x;
+               data[nPerLane*1+i] += scanned.y;
+               data[nPerLane*2+i] += scanned.z;
+               data[nPerLane*3+i] += scanned.w;
+       }
+
+       for(int i=0; i<nPerWI; i++)
+       {
+               int index = nPerWI*lIdx+i;
+               if (index < NUM_BUCKET*nWGs)
+                       wHistogram1[nPerWI*lIdx+i] = data[i];
+       }
+}
+
+//     4 scan, 4 exchange
+void sort4Bits(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)
+{
+       for(int bitIdx=0; bitIdx<BITS_PER_PASS; bitIdx++)
+       {
+               u32 mask = (1<<bitIdx);
+               uint4 cmpResult = make_uint4( (sortData[0]>>startBit) & mask, (sortData[1]>>startBit) & mask, (sortData[2]>>startBit) & mask, (sortData[3]>>startBit) & mask );
+               uint4 prefixSum = SELECT_UINT4( make_uint4(1,1,1,1), make_uint4(0,0,0,0), cmpResult != make_uint4(0,0,0,0) );
+               u32 total;
+               prefixSum = localPrefixSum64V( prefixSum, lIdx, &total, ldsSortData );
+               {
+                       uint4 localAddr = make_uint4(lIdx*4+0,lIdx*4+1,lIdx*4+2,lIdx*4+3);
+                       uint4 dstAddr = localAddr - prefixSum + make_uint4( total, total, total, total );
+                       dstAddr = SELECT_UINT4( prefixSum, dstAddr, cmpResult != make_uint4(0, 0, 0, 0) );
+
+                       GROUP_LDS_BARRIER;
+
+                       ldsSortData[dstAddr.x] = sortData[0];
+                       ldsSortData[dstAddr.y] = sortData[1];
+                       ldsSortData[dstAddr.z] = sortData[2];
+                       ldsSortData[dstAddr.w] = sortData[3];
+
+                       GROUP_LDS_BARRIER;
+
+                       sortData[0] = ldsSortData[localAddr.x];
+                       sortData[1] = ldsSortData[localAddr.y];
+                       sortData[2] = ldsSortData[localAddr.z];
+                       sortData[3] = ldsSortData[localAddr.w];
+
+                       GROUP_LDS_BARRIER;
+               }
+       }
+}
+
+//     2 scan, 2 exchange
+void sort4Bits1(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)
+{
+       for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)
+       {
+               uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, 
+                       (sortData[1]>>(startBit+ibit)) & 0x3, 
+                       (sortData[2]>>(startBit+ibit)) & 0x3, 
+                       (sortData[3]>>(startBit+ibit)) & 0x3);
+
+               u32 key4;
+               u32 sKeyPacked[4] = { 0, 0, 0, 0 };
+               {
+                       sKeyPacked[0] |= 1<<(8*b.x);
+                       sKeyPacked[1] |= 1<<(8*b.y);
+                       sKeyPacked[2] |= 1<<(8*b.z);
+                       sKeyPacked[3] |= 1<<(8*b.w);
+
+                       key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];
+               }
+
+               u32 rankPacked;
+               u32 sumPacked;
+               {
+                       rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );
+               }
+
+               GROUP_LDS_BARRIER;
+
+               u32 newOffset[4] = { 0,0,0,0 };
+               {
+                       u32 sumScanned = bit8Scan( sumPacked );
+
+                       u32 scannedKeys[4];
+                       scannedKeys[0] = 1<<(8*b.x);
+                       scannedKeys[1] = 1<<(8*b.y);
+                       scannedKeys[2] = 1<<(8*b.z);
+                       scannedKeys[3] = 1<<(8*b.w);
+                       {       //      4 scans at once
+                               u32 sum4 = 0;
+                               for(int ie=0; ie<4; ie++)
+                               {
+                                       u32 tmp = scannedKeys[ie];
+                                       scannedKeys[ie] = sum4;
+                                       sum4 += tmp;
+                               }
+                       }
+
+                       {
+                               u32 sumPlusRank = sumScanned + rankPacked;
+                               {       u32 ie = b.x;
+                                       scannedKeys[0] += sumPlusRank;
+                                       newOffset[0] = unpack4Key( scannedKeys[0], ie );
+                               }
+                               {       u32 ie = b.y;
+                                       scannedKeys[1] += sumPlusRank;
+                                       newOffset[1] = unpack4Key( scannedKeys[1], ie );
+                               }
+                               {       u32 ie = b.z;
+                                       scannedKeys[2] += sumPlusRank;
+                                       newOffset[2] = unpack4Key( scannedKeys[2], ie );
+                               }
+                               {       u32 ie = b.w;
+                                       scannedKeys[3] += sumPlusRank;
+                                       newOffset[3] = unpack4Key( scannedKeys[3], ie );
+                               }
+                       }
+               }
+
+
+               GROUP_LDS_BARRIER;
+
+               {
+                       ldsSortData[newOffset[0]] = sortData[0];
+                       ldsSortData[newOffset[1]] = sortData[1];
+                       ldsSortData[newOffset[2]] = sortData[2];
+                       ldsSortData[newOffset[3]] = sortData[3];
+
+                       GROUP_LDS_BARRIER;
+
+                       u32 dstAddr = 4*lIdx;
+                       sortData[0] = ldsSortData[dstAddr+0];
+                       sortData[1] = ldsSortData[dstAddr+1];
+                       sortData[2] = ldsSortData[dstAddr+2];
+                       sortData[3] = ldsSortData[dstAddr+3];
+
+                       GROUP_LDS_BARRIER;
+               }
+       }
+}
+
+#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key]
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SortAndScatterKernel( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4  cb )
+{
+       __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];
+       __local u32 localHistogramToCarry[NUM_BUCKET];
+       __local u32 localHistogram[NUM_BUCKET*2];
+
+       u32 gIdx = GET_GLOBAL_IDX;
+       u32 lIdx = GET_LOCAL_IDX;
+       u32 wgIdx = GET_GROUP_IDX;
+       u32 wgSize = GET_GROUP_SIZE;
+
+       const int n = cb.m_n;
+       const int nWGs = cb.m_nWGs;
+       const int startBit = cb.m_startBit;
+       const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+       if( lIdx < (NUM_BUCKET) )
+       {
+               localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];
+       }
+
+       GROUP_LDS_BARRIER;
+
+       const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+
+       int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;
+
+       int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+       for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
+       {
+               u32 myHistogram = 0;
+
+               u32 sortData[ELEMENTS_PER_WORK_ITEM];
+               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+#if defined(CHECK_BOUNDARY)
+                       sortData[i] = ( addr+i < n )? gSrc[ addr+i ] : 0xffffffff;
+#else
+                       sortData[i] = gSrc[ addr+i ];
+#endif
+
+               sort4Bits(sortData, startBit, lIdx, ldsSortData);
+
+               u32 keys[ELEMENTS_PER_WORK_ITEM];
+               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+                       keys[i] = (sortData[i]>>startBit) & 0xf;
+
+               {       //      create histogram
+                       u32 setIdx = lIdx/16;
+                       if( lIdx < NUM_BUCKET )
+                       {
+                               localHistogram[lIdx] = 0;
+                       }
+                       ldsSortData[lIdx] = 0;
+                       GROUP_LDS_BARRIER;
+
+                       for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+#if defined(CHECK_BOUNDARY)
+                               if( addr+i < n )
+#endif
+
+#if defined(NV_GPU)
+                               SET_HISTOGRAM( setIdx, keys[i] )++;
+#else
+                               AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );
+#endif
+                       
+                       GROUP_LDS_BARRIER;
+                       
+                       uint hIdx = NUM_BUCKET+lIdx;
+                       if( lIdx < NUM_BUCKET )
+                       {
+                               u32 sum = 0;
+                               for(int i=0; i<WG_SIZE/16; i++)
+                               {
+                                       sum += SET_HISTOGRAM( i, lIdx );
+                               }
+                               myHistogram = sum;
+                               localHistogram[hIdx] = sum;
+                       }
+                       GROUP_LDS_BARRIER;
+
+#if defined(USE_2LEVEL_REDUCE)
+                       if( lIdx < NUM_BUCKET )
+                       {
+                               localHistogram[hIdx] = localHistogram[hIdx-1];
+                               GROUP_MEM_FENCE;
+
+                               u32 u0, u1, u2;
+                               u0 = localHistogram[hIdx-3];
+                               u1 = localHistogram[hIdx-2];
+                               u2 = localHistogram[hIdx-1];
+                               AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
+                               GROUP_MEM_FENCE;
+                               u0 = localHistogram[hIdx-12];
+                               u1 = localHistogram[hIdx-8];
+                               u2 = localHistogram[hIdx-4];
+                               AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
+                               GROUP_MEM_FENCE;
+                       }
+#else
+                       if( lIdx < NUM_BUCKET )
+                       {
+                               localHistogram[hIdx] = localHistogram[hIdx-1];
+                               GROUP_MEM_FENCE;
+                               localHistogram[hIdx] += localHistogram[hIdx-1];
+                               GROUP_MEM_FENCE;
+                               localHistogram[hIdx] += localHistogram[hIdx-2];
+                               GROUP_MEM_FENCE;
+                               localHistogram[hIdx] += localHistogram[hIdx-4];
+                               GROUP_MEM_FENCE;
+                               localHistogram[hIdx] += localHistogram[hIdx-8];
+                               GROUP_MEM_FENCE;
+                       }
+#endif
+                       GROUP_LDS_BARRIER;
+               }
+
+               {
+                       for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)
+                       {
+                               int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;
+                               int binIdx = keys[ie];
+                               int groupOffset = localHistogramToCarry[binIdx];
+                               int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];
+#if defined(CHECK_BOUNDARY)
+                               if( addr+ie < n )
+#endif
+                               gDst[ groupOffset + myIdx ] = sortData[ie];
+                       }
+               }
+
+               GROUP_LDS_BARRIER;
+
+               if( lIdx < NUM_BUCKET )
+               {
+                       localHistogramToCarry[lIdx] += myHistogram;
+               }
+               GROUP_LDS_BARRIER;
+       }
+}
+
+//     2 scan, 2 exchange
+void sort4Bits1KeyValue(u32 sortData[4], int sortVal[4], int startBit, int lIdx, __local u32* ldsSortData, __local int *ldsSortVal)
+{
+       for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)
+       {
+               uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, 
+                       (sortData[1]>>(startBit+ibit)) & 0x3, 
+                       (sortData[2]>>(startBit+ibit)) & 0x3, 
+                       (sortData[3]>>(startBit+ibit)) & 0x3);
+
+               u32 key4;
+               u32 sKeyPacked[4] = { 0, 0, 0, 0 };
+               {
+                       sKeyPacked[0] |= 1<<(8*b.x);
+                       sKeyPacked[1] |= 1<<(8*b.y);
+                       sKeyPacked[2] |= 1<<(8*b.z);
+                       sKeyPacked[3] |= 1<<(8*b.w);
+
+                       key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];
+               }
+
+               u32 rankPacked;
+               u32 sumPacked;
+               {
+                       rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );
+               }
+
+               GROUP_LDS_BARRIER;
+
+               u32 newOffset[4] = { 0,0,0,0 };
+               {
+                       u32 sumScanned = bit8Scan( sumPacked );
+
+                       u32 scannedKeys[4];
+                       scannedKeys[0] = 1<<(8*b.x);
+                       scannedKeys[1] = 1<<(8*b.y);
+                       scannedKeys[2] = 1<<(8*b.z);
+                       scannedKeys[3] = 1<<(8*b.w);
+                       {       //      4 scans at once
+                               u32 sum4 = 0;
+                               for(int ie=0; ie<4; ie++)
+                               {
+                                       u32 tmp = scannedKeys[ie];
+                                       scannedKeys[ie] = sum4;
+                                       sum4 += tmp;
+                               }
+                       }
+
+                       {
+                               u32 sumPlusRank = sumScanned + rankPacked;
+                               {       u32 ie = b.x;
+                                       scannedKeys[0] += sumPlusRank;
+                                       newOffset[0] = unpack4Key( scannedKeys[0], ie );
+                               }
+                               {       u32 ie = b.y;
+                                       scannedKeys[1] += sumPlusRank;
+                                       newOffset[1] = unpack4Key( scannedKeys[1], ie );
+                               }
+                               {       u32 ie = b.z;
+                                       scannedKeys[2] += sumPlusRank;
+                                       newOffset[2] = unpack4Key( scannedKeys[2], ie );
+                               }
+                               {       u32 ie = b.w;
+                                       scannedKeys[3] += sumPlusRank;
+                                       newOffset[3] = unpack4Key( scannedKeys[3], ie );
+                               }
+                       }
+               }
+
+
+               GROUP_LDS_BARRIER;
+
+               {
+                       ldsSortData[newOffset[0]] = sortData[0];
+                       ldsSortData[newOffset[1]] = sortData[1];
+                       ldsSortData[newOffset[2]] = sortData[2];
+                       ldsSortData[newOffset[3]] = sortData[3];
+
+                       ldsSortVal[newOffset[0]] = sortVal[0];
+                       ldsSortVal[newOffset[1]] = sortVal[1];
+                       ldsSortVal[newOffset[2]] = sortVal[2];
+                       ldsSortVal[newOffset[3]] = sortVal[3];
+
+                       GROUP_LDS_BARRIER;
+
+                       u32 dstAddr = 4*lIdx;
+                       sortData[0] = ldsSortData[dstAddr+0];
+                       sortData[1] = ldsSortData[dstAddr+1];
+                       sortData[2] = ldsSortData[dstAddr+2];
+                       sortData[3] = ldsSortData[dstAddr+3];
+
+                       sortVal[0] = ldsSortVal[dstAddr+0];
+                       sortVal[1] = ldsSortVal[dstAddr+1];
+                       sortVal[2] = ldsSortVal[dstAddr+2];
+                       sortVal[3] = ldsSortVal[dstAddr+3];
+
+                       GROUP_LDS_BARRIER;
+               }
+       }
+}
+
+
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SortAndScatterSortDataKernel( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)
+{
+       __local int ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];
+       __local int ldsSortVal[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];
+       __local u32 localHistogramToCarry[NUM_BUCKET];
+       __local u32 localHistogram[NUM_BUCKET*2];
+
+       u32 gIdx = GET_GLOBAL_IDX;
+       u32 lIdx = GET_LOCAL_IDX;
+       u32 wgIdx = GET_GROUP_IDX;
+       u32 wgSize = GET_GROUP_SIZE;
+
+       const int n = cb.m_n;
+       const int nWGs = cb.m_nWGs;
+       const int startBit = cb.m_startBit;
+       const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+       if( lIdx < (NUM_BUCKET) )
+       {
+               localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];
+       }
+
+       GROUP_LDS_BARRIER;
+    
+
+       const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+
+       int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;
+
+       int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+
+       for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
+       {
+
+               u32 myHistogram = 0;
+
+               int sortData[ELEMENTS_PER_WORK_ITEM];
+               int sortVal[ELEMENTS_PER_WORK_ITEM];
+
+               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+#if defined(CHECK_BOUNDARY)
+               {
+                       sortData[i] = ( addr+i < n )? gSrc[ addr+i ].m_key : 0xffffffff;
+                       sortVal[i] = ( addr+i < n )? gSrc[ addr+i ].m_value : 0xffffffff;
+               }
+#else
+               {
+                       sortData[i] = gSrc[ addr+i ].m_key;
+                       sortVal[i] = gSrc[ addr+i ].m_value;
+               }
+#endif
+
+               sort4Bits1KeyValue(sortData, sortVal, startBit, lIdx, ldsSortData, ldsSortVal);
+
+               u32 keys[ELEMENTS_PER_WORK_ITEM];
+               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+                       keys[i] = (sortData[i]>>startBit) & 0xf;
+
+               {       //      create histogram
+                       u32 setIdx = lIdx/16;
+                       if( lIdx < NUM_BUCKET )
+                       {
+                               localHistogram[lIdx] = 0;
+                       }
+                       ldsSortData[lIdx] = 0;
+                       GROUP_LDS_BARRIER;
+
+                       for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
+#if defined(CHECK_BOUNDARY)
+                               if( addr+i < n )
+#endif
+
+#if defined(NV_GPU)
+                               SET_HISTOGRAM( setIdx, keys[i] )++;
+#else
+                               AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );
+#endif
+                       
+                       GROUP_LDS_BARRIER;
+                       
+                       uint hIdx = NUM_BUCKET+lIdx;
+                       if( lIdx < NUM_BUCKET )
+                       {
+                               u32 sum = 0;
+                               for(int i=0; i<WG_SIZE/16; i++)
+                               {
+                                       sum += SET_HISTOGRAM( i, lIdx );
+                               }
+                               myHistogram = sum;
+                               localHistogram[hIdx] = sum;
+                       }
+                       GROUP_LDS_BARRIER;
+
+#if defined(USE_2LEVEL_REDUCE)
+                       if( lIdx < NUM_BUCKET )
+                       {
+                               localHistogram[hIdx] = localHistogram[hIdx-1];
+                               GROUP_MEM_FENCE;
+
+                               u32 u0, u1, u2;
+                               u0 = localHistogram[hIdx-3];
+                               u1 = localHistogram[hIdx-2];
+                               u2 = localHistogram[hIdx-1];
+                               AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
+                               GROUP_MEM_FENCE;
+                               u0 = localHistogram[hIdx-12];
+                               u1 = localHistogram[hIdx-8];
+                               u2 = localHistogram[hIdx-4];
+                               AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
+                               GROUP_MEM_FENCE;
+                       }
+#else
+                       if( lIdx < NUM_BUCKET )
+                       {
+                               localHistogram[hIdx] = localHistogram[hIdx-1];
+                               GROUP_MEM_FENCE;
+                               localHistogram[hIdx] += localHistogram[hIdx-1];
+                               GROUP_MEM_FENCE;
+                               localHistogram[hIdx] += localHistogram[hIdx-2];
+                               GROUP_MEM_FENCE;
+                               localHistogram[hIdx] += localHistogram[hIdx-4];
+                               GROUP_MEM_FENCE;
+                               localHistogram[hIdx] += localHistogram[hIdx-8];
+                               GROUP_MEM_FENCE;
+                       }
+#endif
+                       GROUP_LDS_BARRIER;
+               }
+
+       {
+                       for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)
+                       {
+                               int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;
+                               int binIdx = keys[ie];
+                               int groupOffset = localHistogramToCarry[binIdx];
+                               int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];
+#if defined(CHECK_BOUNDARY)
+                               if( addr+ie < n )
+                               {
+                    if ((groupOffset + myIdx)<n)
+                    {
+                        if (sortData[ie]==sortVal[ie])
+                        {
+                            
+                            SortDataCL tmp;
+                            tmp.m_key = sortData[ie];
+                            tmp.m_value = sortVal[ie];
+                            if (tmp.m_key == tmp.m_value)
+                                gDst[groupOffset + myIdx ] = tmp;
+                        }
+                        
+                    }
+                               }
+#else
+                if ((groupOffset + myIdx)<n)
+                {
+                    gDst[ groupOffset + myIdx ].m_key = sortData[ie];
+                    gDst[ groupOffset + myIdx ].m_value = sortVal[ie];
+                }
+#endif
+                       }
+               }
+
+               GROUP_LDS_BARRIER;
+
+               if( lIdx < NUM_BUCKET )
+               {
+                       localHistogramToCarry[lIdx] += myHistogram;
+               }
+               GROUP_LDS_BARRIER;
+       }
+}
+
+
+
+
+
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SortAndScatterSortDataKernelSerial( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)
+{
+    
+       u32 gIdx = GET_GLOBAL_IDX;
+       u32 realLocalIdx = GET_LOCAL_IDX;
+       u32 wgIdx = GET_GROUP_IDX;
+       u32 wgSize = GET_GROUP_SIZE;
+       const int startBit = cb.m_startBit;
+       const int n = cb.m_n;
+       const int nWGs = cb.m_nWGs;
+       const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+    int counter[NUM_BUCKET];
+    
+    if (realLocalIdx>0)
+        return;
+    
+    for (int c=0;c<NUM_BUCKET;c++)
+        counter[c]=0;
+
+    const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+       
+       int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
+
+   for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)
+  {
+     for (int lIdx=0;lIdx<WG_SIZE;lIdx++)
+       {
+        int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+        
+               for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)
+               {
+            int i = addr2+j;
+                       if( i < n )
+                       {
+                int tableIdx;
+                               tableIdx = (gSrc[i].m_key>>startBit) & 0xf;//0xf = NUM_TABLES-1
+                gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];
+                counter[tableIdx] ++;
+                       }
+               }
+       }
+  }
+    
+}
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SortAndScatterKernelSerial( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4  cb )
+{
+    
+       u32 gIdx = GET_GLOBAL_IDX;
+       u32 realLocalIdx = GET_LOCAL_IDX;
+       u32 wgIdx = GET_GROUP_IDX;
+       u32 wgSize = GET_GROUP_SIZE;
+       const int startBit = cb.m_startBit;
+       const int n = cb.m_n;
+       const int nWGs = cb.m_nWGs;
+       const int nBlocksPerWG = cb.m_nBlocksPerWG;
+
+    int counter[NUM_BUCKET];
+    
+    if (realLocalIdx>0)
+        return;
+    
+    for (int c=0;c<NUM_BUCKET;c++)
+        counter[c]=0;
+
+    const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
+       
+       int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
+
+   for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)
+  {
+     for (int lIdx=0;lIdx<WG_SIZE;lIdx++)
+       {
+        int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
+        
+               for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)
+               {
+            int i = addr2+j;
+                       if( i < n )
+                       {
+                int tableIdx;
+                               tableIdx = (gSrc[i]>>startBit) & 0xf;//0xf = NUM_TABLES-1
+                gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];
+                counter[tableIdx] ++;
+                       }
+               }
+       }
+  }
+    
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h
new file mode 100644 (file)
index 0000000..fb4bdda
--- /dev/null
@@ -0,0 +1,909 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* radixSort32KernelsCL =
+       "/*\n"
+       "Bullet Continuous Collision Detection and Physics Library\n"
+       "Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org\n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Author Takahiro Harada\n"
+       "//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+       "typedef unsigned int u32;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+       "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+       "#define make_uint4 (uint4)\n"
+       "#define make_uint2 (uint2)\n"
+       "#define make_int2 (int2)\n"
+       "#define WG_SIZE 64\n"
+       "#define ELEMENTS_PER_WORK_ITEM (256/WG_SIZE)\n"
+       "#define BITS_PER_PASS 4\n"
+       "#define NUM_BUCKET (1<<BITS_PER_PASS)\n"
+       "typedef uchar u8;\n"
+       "//     this isn't optimization for VLIW. But just reducing writes. \n"
+       "#define USE_2LEVEL_REDUCE 1\n"
+       "//#define CHECK_BOUNDARY 1\n"
+       "//#define NV_GPU 1\n"
+       "//     Cypress\n"
+       "#define nPerWI 16\n"
+       "//     Cayman\n"
+       "//#define nPerWI 20\n"
+       "#define m_n x\n"
+       "#define m_nWGs y\n"
+       "#define m_startBit z\n"
+       "#define m_nBlocksPerWG w\n"
+       "/*\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_n;\n"
+       "       int m_nWGs;\n"
+       "       int m_startBit;\n"
+       "       int m_nBlocksPerWG;\n"
+       "} ConstBuffer;\n"
+       "*/\n"
+       "typedef struct\n"
+       "{\n"
+       "       unsigned int m_key;\n"
+       "       unsigned int m_value;\n"
+       "} SortDataCL;\n"
+       "uint prefixScanVectorEx( uint4* data )\n"
+       "{\n"
+       "       u32 sum = 0;\n"
+       "       u32 tmp = data[0].x;\n"
+       "       data[0].x = sum;\n"
+       "       sum += tmp;\n"
+       "       tmp = data[0].y;\n"
+       "       data[0].y = sum;\n"
+       "       sum += tmp;\n"
+       "       tmp = data[0].z;\n"
+       "       data[0].z = sum;\n"
+       "       sum += tmp;\n"
+       "       tmp = data[0].w;\n"
+       "       data[0].w = sum;\n"
+       "       sum += tmp;\n"
+       "       return sum;\n"
+       "}\n"
+       "u32 localPrefixSum( u32 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory, int wgSize /*64 or 128*/ )\n"
+       "{\n"
+       "       {       //      Set data\n"
+       "               sorterSharedMemory[lIdx] = 0;\n"
+       "               sorterSharedMemory[lIdx+wgSize] = pData;\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       {       //      Prefix sum\n"
+       "               int idx = 2*lIdx + (wgSize+1);\n"
+       "#if defined(USE_2LEVEL_REDUCE)\n"
+       "               if( lIdx < 64 )\n"
+       "               {\n"
+       "                       u32 u0, u1, u2;\n"
+       "                       u0 = sorterSharedMemory[idx-3];\n"
+       "                       u1 = sorterSharedMemory[idx-2];\n"
+       "                       u2 = sorterSharedMemory[idx-1];\n"
+       "                       AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );                   \n"
+       "                       GROUP_MEM_FENCE;\n"
+       "                       u0 = sorterSharedMemory[idx-12];\n"
+       "                       u1 = sorterSharedMemory[idx-8];\n"
+       "                       u2 = sorterSharedMemory[idx-4];\n"
+       "                       AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );                   \n"
+       "                       GROUP_MEM_FENCE;\n"
+       "                       u0 = sorterSharedMemory[idx-48];\n"
+       "                       u1 = sorterSharedMemory[idx-32];\n"
+       "                       u2 = sorterSharedMemory[idx-16];\n"
+       "                       AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );                   \n"
+       "                       GROUP_MEM_FENCE;\n"
+       "                       if( wgSize > 64 )\n"
+       "                       {\n"
+       "                               sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                       }\n"
+       "                       sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n"
+       "                       GROUP_MEM_FENCE;\n"
+       "               }\n"
+       "#else\n"
+       "               if( lIdx < 64 )\n"
+       "               {\n"
+       "                       sorterSharedMemory[idx] += sorterSharedMemory[idx-1];\n"
+       "                       GROUP_MEM_FENCE;\n"
+       "                       sorterSharedMemory[idx] += sorterSharedMemory[idx-2];                   \n"
+       "                       GROUP_MEM_FENCE;\n"
+       "                       sorterSharedMemory[idx] += sorterSharedMemory[idx-4];\n"
+       "                       GROUP_MEM_FENCE;\n"
+       "                       sorterSharedMemory[idx] += sorterSharedMemory[idx-8];\n"
+       "                       GROUP_MEM_FENCE;\n"
+       "                       sorterSharedMemory[idx] += sorterSharedMemory[idx-16];\n"
+       "                       GROUP_MEM_FENCE;\n"
+       "                       sorterSharedMemory[idx] += sorterSharedMemory[idx-32];\n"
+       "                       GROUP_MEM_FENCE;\n"
+       "                       if( wgSize > 64 )\n"
+       "                       {\n"
+       "                               sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                       }\n"
+       "                       sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n"
+       "                       GROUP_MEM_FENCE;\n"
+       "               }\n"
+       "#endif\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       *totalSum = sorterSharedMemory[wgSize*2-1];\n"
+       "       u32 addValue = sorterSharedMemory[lIdx+wgSize-1];\n"
+       "       return addValue;\n"
+       "}\n"
+       "//__attribute__((reqd_work_group_size(128,1,1)))\n"
+       "uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )\n"
+       "{\n"
+       "       u32 s4 = prefixScanVectorEx( &pData );\n"
+       "       u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 128 );\n"
+       "       return pData + make_uint4( rank, rank, rank, rank );\n"
+       "}\n"
+       "//__attribute__((reqd_work_group_size(64,1,1)))\n"
+       "uint4 localPrefixSum64V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )\n"
+       "{\n"
+       "       u32 s4 = prefixScanVectorEx( &pData );\n"
+       "       u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 64 );\n"
+       "       return pData + make_uint4( rank, rank, rank, rank );\n"
+       "}\n"
+       "u32 unpack4Key( u32 key, int keyIdx ){ return (key>>(keyIdx*8)) & 0xff;}\n"
+       "u32 bit8Scan(u32 v)\n"
+       "{\n"
+       "       return (v<<8) + (v<<16) + (v<<24);\n"
+       "}\n"
+       "//===\n"
+       "#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx]\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void StreamCountKernel( __global u32* gSrc, __global u32* histogramOut, int4 cb )\n"
+       "{\n"
+       "       __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n"
+       "       u32 gIdx = GET_GLOBAL_IDX;\n"
+       "       u32 lIdx = GET_LOCAL_IDX;\n"
+       "       u32 wgIdx = GET_GROUP_IDX;\n"
+       "       u32 wgSize = GET_GROUP_SIZE;\n"
+       "       const int startBit = cb.m_startBit;\n"
+       "       const int n = cb.m_n;\n"
+       "       const int nWGs = cb.m_nWGs;\n"
+       "       const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+       "       for(int i=0; i<NUM_BUCKET; i++)\n"
+       "       {\n"
+       "               MY_HISTOGRAM(i) = 0;\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+       "       u32 localKey;\n"
+       "       int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+       "       int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+       "       for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+       "       {\n"
+       "               //      MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD\n"
+       "               //      Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops\n"
+       "               //      AMD: AtomInc performs better while NV prefers ++\n"
+       "               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+       "               {\n"
+       "#if defined(CHECK_BOUNDARY)\n"
+       "                       if( addr+i < n )\n"
+       "#endif\n"
+       "                       {\n"
+       "                               localKey = (gSrc[addr+i]>>startBit) & 0xf;\n"
+       "#if defined(NV_GPU)\n"
+       "                               MY_HISTOGRAM( localKey )++;\n"
+       "#else\n"
+       "                               AtomInc( MY_HISTOGRAM( localKey ) );\n"
+       "#endif\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       \n"
+       "       if( lIdx < NUM_BUCKET )\n"
+       "       {\n"
+       "               u32 sum = 0;\n"
+       "               for(int i=0; i<GET_GROUP_SIZE; i++)\n"
+       "               {\n"
+       "                       sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];\n"
+       "               }\n"
+       "               histogramOut[lIdx*nWGs+wgIdx] = sum;\n"
+       "       }\n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void StreamCountSortDataKernel( __global SortDataCL* gSrc, __global u32* histogramOut, int4  cb )\n"
+       "{\n"
+       "       __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n"
+       "       u32 gIdx = GET_GLOBAL_IDX;\n"
+       "       u32 lIdx = GET_LOCAL_IDX;\n"
+       "       u32 wgIdx = GET_GROUP_IDX;\n"
+       "       u32 wgSize = GET_GROUP_SIZE;\n"
+       "       const int startBit = cb.m_startBit;\n"
+       "       const int n = cb.m_n;\n"
+       "       const int nWGs = cb.m_nWGs;\n"
+       "       const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+       "       for(int i=0; i<NUM_BUCKET; i++)\n"
+       "       {\n"
+       "               MY_HISTOGRAM(i) = 0;\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+       "       u32 localKey;\n"
+       "       int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+       "       int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+       "       for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+       "       {\n"
+       "               //      MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD\n"
+       "               //      Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops\n"
+       "               //      AMD: AtomInc performs better while NV prefers ++\n"
+       "               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+       "               {\n"
+       "#if defined(CHECK_BOUNDARY)\n"
+       "                       if( addr+i < n )\n"
+       "#endif\n"
+       "                       {\n"
+       "                               localKey = (gSrc[addr+i].m_key>>startBit) & 0xf;\n"
+       "#if defined(NV_GPU)\n"
+       "                               MY_HISTOGRAM( localKey )++;\n"
+       "#else\n"
+       "                               AtomInc( MY_HISTOGRAM( localKey ) );\n"
+       "#endif\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       \n"
+       "       if( lIdx < NUM_BUCKET )\n"
+       "       {\n"
+       "               u32 sum = 0;\n"
+       "               for(int i=0; i<GET_GROUP_SIZE; i++)\n"
+       "               {\n"
+       "                       sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];\n"
+       "               }\n"
+       "               histogramOut[lIdx*nWGs+wgIdx] = sum;\n"
+       "       }\n"
+       "}\n"
+       "#define nPerLane (nPerWI/4)\n"
+       "//     NUM_BUCKET*nWGs < 128*nPerWI\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(128,1,1)))\n"
+       "void PrefixScanKernel( __global u32* wHistogram1, int4  cb )\n"
+       "{\n"
+       "       __local u32 ldsTopScanData[128*2];\n"
+       "       u32 lIdx = GET_LOCAL_IDX;\n"
+       "       u32 wgIdx = GET_GROUP_IDX;\n"
+       "       const int nWGs = cb.m_nWGs;\n"
+       "       u32 data[nPerWI];\n"
+       "       for(int i=0; i<nPerWI; i++)\n"
+       "       {\n"
+       "               data[i] = 0;\n"
+       "               if( (nPerWI*lIdx+i) < NUM_BUCKET*nWGs )\n"
+       "                       data[i] = wHistogram1[nPerWI*lIdx+i];\n"
+       "       }\n"
+       "       uint4 myData = make_uint4(0,0,0,0);\n"
+       "       for(int i=0; i<nPerLane; i++)\n"
+       "       {\n"
+       "               myData.x += data[nPerLane*0+i];\n"
+       "               myData.y += data[nPerLane*1+i];\n"
+       "               myData.z += data[nPerLane*2+i];\n"
+       "               myData.w += data[nPerLane*3+i];\n"
+       "       }\n"
+       "       uint totalSum;\n"
+       "       uint4 scanned = localPrefixSum128V( myData, lIdx, &totalSum, ldsTopScanData );\n"
+       "//     for(int j=0; j<4; j++) //       somehow it introduces a lot of branches\n"
+       "       {       int j = 0;\n"
+       "               u32 sum = 0;\n"
+       "               for(int i=0; i<nPerLane; i++)\n"
+       "               {\n"
+       "                       u32 tmp = data[nPerLane*j+i];\n"
+       "                       data[nPerLane*j+i] = sum;\n"
+       "                       sum += tmp;\n"
+       "               }\n"
+       "       }\n"
+       "       {       int j = 1;\n"
+       "               u32 sum = 0;\n"
+       "               for(int i=0; i<nPerLane; i++)\n"
+       "               {\n"
+       "                       u32 tmp = data[nPerLane*j+i];\n"
+       "                       data[nPerLane*j+i] = sum;\n"
+       "                       sum += tmp;\n"
+       "               }\n"
+       "       }\n"
+       "       {       int j = 2;\n"
+       "               u32 sum = 0;\n"
+       "               for(int i=0; i<nPerLane; i++)\n"
+       "               {\n"
+       "                       u32 tmp = data[nPerLane*j+i];\n"
+       "                       data[nPerLane*j+i] = sum;\n"
+       "                       sum += tmp;\n"
+       "               }\n"
+       "       }\n"
+       "       {       int j = 3;\n"
+       "               u32 sum = 0;\n"
+       "               for(int i=0; i<nPerLane; i++)\n"
+       "               {\n"
+       "                       u32 tmp = data[nPerLane*j+i];\n"
+       "                       data[nPerLane*j+i] = sum;\n"
+       "                       sum += tmp;\n"
+       "               }\n"
+       "       }\n"
+       "       for(int i=0; i<nPerLane; i++)\n"
+       "       {\n"
+       "               data[nPerLane*0+i] += scanned.x;\n"
+       "               data[nPerLane*1+i] += scanned.y;\n"
+       "               data[nPerLane*2+i] += scanned.z;\n"
+       "               data[nPerLane*3+i] += scanned.w;\n"
+       "       }\n"
+       "       for(int i=0; i<nPerWI; i++)\n"
+       "       {\n"
+       "               int index = nPerWI*lIdx+i;\n"
+       "               if (index < NUM_BUCKET*nWGs)\n"
+       "                       wHistogram1[nPerWI*lIdx+i] = data[i];\n"
+       "       }\n"
+       "}\n"
+       "//     4 scan, 4 exchange\n"
+       "void sort4Bits(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n"
+       "{\n"
+       "       for(int bitIdx=0; bitIdx<BITS_PER_PASS; bitIdx++)\n"
+       "       {\n"
+       "               u32 mask = (1<<bitIdx);\n"
+       "               uint4 cmpResult = make_uint4( (sortData[0]>>startBit) & mask, (sortData[1]>>startBit) & mask, (sortData[2]>>startBit) & mask, (sortData[3]>>startBit) & mask );\n"
+       "               uint4 prefixSum = SELECT_UINT4( make_uint4(1,1,1,1), make_uint4(0,0,0,0), cmpResult != make_uint4(0,0,0,0) );\n"
+       "               u32 total;\n"
+       "               prefixSum = localPrefixSum64V( prefixSum, lIdx, &total, ldsSortData );\n"
+       "               {\n"
+       "                       uint4 localAddr = make_uint4(lIdx*4+0,lIdx*4+1,lIdx*4+2,lIdx*4+3);\n"
+       "                       uint4 dstAddr = localAddr - prefixSum + make_uint4( total, total, total, total );\n"
+       "                       dstAddr = SELECT_UINT4( prefixSum, dstAddr, cmpResult != make_uint4(0, 0, 0, 0) );\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "                       ldsSortData[dstAddr.x] = sortData[0];\n"
+       "                       ldsSortData[dstAddr.y] = sortData[1];\n"
+       "                       ldsSortData[dstAddr.z] = sortData[2];\n"
+       "                       ldsSortData[dstAddr.w] = sortData[3];\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "                       sortData[0] = ldsSortData[localAddr.x];\n"
+       "                       sortData[1] = ldsSortData[localAddr.y];\n"
+       "                       sortData[2] = ldsSortData[localAddr.z];\n"
+       "                       sortData[3] = ldsSortData[localAddr.w];\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "//     2 scan, 2 exchange\n"
+       "void sort4Bits1(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n"
+       "{\n"
+       "       for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)\n"
+       "       {\n"
+       "               uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, \n"
+       "                       (sortData[1]>>(startBit+ibit)) & 0x3, \n"
+       "                       (sortData[2]>>(startBit+ibit)) & 0x3, \n"
+       "                       (sortData[3]>>(startBit+ibit)) & 0x3);\n"
+       "               u32 key4;\n"
+       "               u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n"
+       "               {\n"
+       "                       sKeyPacked[0] |= 1<<(8*b.x);\n"
+       "                       sKeyPacked[1] |= 1<<(8*b.y);\n"
+       "                       sKeyPacked[2] |= 1<<(8*b.z);\n"
+       "                       sKeyPacked[3] |= 1<<(8*b.w);\n"
+       "                       key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n"
+       "               }\n"
+       "               u32 rankPacked;\n"
+       "               u32 sumPacked;\n"
+       "               {\n"
+       "                       rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "               u32 newOffset[4] = { 0,0,0,0 };\n"
+       "               {\n"
+       "                       u32 sumScanned = bit8Scan( sumPacked );\n"
+       "                       u32 scannedKeys[4];\n"
+       "                       scannedKeys[0] = 1<<(8*b.x);\n"
+       "                       scannedKeys[1] = 1<<(8*b.y);\n"
+       "                       scannedKeys[2] = 1<<(8*b.z);\n"
+       "                       scannedKeys[3] = 1<<(8*b.w);\n"
+       "                       {       //      4 scans at once\n"
+       "                               u32 sum4 = 0;\n"
+       "                               for(int ie=0; ie<4; ie++)\n"
+       "                               {\n"
+       "                                       u32 tmp = scannedKeys[ie];\n"
+       "                                       scannedKeys[ie] = sum4;\n"
+       "                                       sum4 += tmp;\n"
+       "                               }\n"
+       "                       }\n"
+       "                       {\n"
+       "                               u32 sumPlusRank = sumScanned + rankPacked;\n"
+       "                               {       u32 ie = b.x;\n"
+       "                                       scannedKeys[0] += sumPlusRank;\n"
+       "                                       newOffset[0] = unpack4Key( scannedKeys[0], ie );\n"
+       "                               }\n"
+       "                               {       u32 ie = b.y;\n"
+       "                                       scannedKeys[1] += sumPlusRank;\n"
+       "                                       newOffset[1] = unpack4Key( scannedKeys[1], ie );\n"
+       "                               }\n"
+       "                               {       u32 ie = b.z;\n"
+       "                                       scannedKeys[2] += sumPlusRank;\n"
+       "                                       newOffset[2] = unpack4Key( scannedKeys[2], ie );\n"
+       "                               }\n"
+       "                               {       u32 ie = b.w;\n"
+       "                                       scannedKeys[3] += sumPlusRank;\n"
+       "                                       newOffset[3] = unpack4Key( scannedKeys[3], ie );\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "               {\n"
+       "                       ldsSortData[newOffset[0]] = sortData[0];\n"
+       "                       ldsSortData[newOffset[1]] = sortData[1];\n"
+       "                       ldsSortData[newOffset[2]] = sortData[2];\n"
+       "                       ldsSortData[newOffset[3]] = sortData[3];\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "                       u32 dstAddr = 4*lIdx;\n"
+       "                       sortData[0] = ldsSortData[dstAddr+0];\n"
+       "                       sortData[1] = ldsSortData[dstAddr+1];\n"
+       "                       sortData[2] = ldsSortData[dstAddr+2];\n"
+       "                       sortData[3] = ldsSortData[dstAddr+3];\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key]\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void SortAndScatterKernel( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4  cb )\n"
+       "{\n"
+       "       __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
+       "       __local u32 localHistogramToCarry[NUM_BUCKET];\n"
+       "       __local u32 localHistogram[NUM_BUCKET*2];\n"
+       "       u32 gIdx = GET_GLOBAL_IDX;\n"
+       "       u32 lIdx = GET_LOCAL_IDX;\n"
+       "       u32 wgIdx = GET_GROUP_IDX;\n"
+       "       u32 wgSize = GET_GROUP_SIZE;\n"
+       "       const int n = cb.m_n;\n"
+       "       const int nWGs = cb.m_nWGs;\n"
+       "       const int startBit = cb.m_startBit;\n"
+       "       const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+       "       if( lIdx < (NUM_BUCKET) )\n"
+       "       {\n"
+       "               localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+       "       int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n"
+       "       int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+       "       for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+       "       {\n"
+       "               u32 myHistogram = 0;\n"
+       "               u32 sortData[ELEMENTS_PER_WORK_ITEM];\n"
+       "               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+       "#if defined(CHECK_BOUNDARY)\n"
+       "                       sortData[i] = ( addr+i < n )? gSrc[ addr+i ] : 0xffffffff;\n"
+       "#else\n"
+       "                       sortData[i] = gSrc[ addr+i ];\n"
+       "#endif\n"
+       "               sort4Bits(sortData, startBit, lIdx, ldsSortData);\n"
+       "               u32 keys[ELEMENTS_PER_WORK_ITEM];\n"
+       "               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+       "                       keys[i] = (sortData[i]>>startBit) & 0xf;\n"
+       "               {       //      create histogram\n"
+       "                       u32 setIdx = lIdx/16;\n"
+       "                       if( lIdx < NUM_BUCKET )\n"
+       "                       {\n"
+       "                               localHistogram[lIdx] = 0;\n"
+       "                       }\n"
+       "                       ldsSortData[lIdx] = 0;\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "                       for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+       "#if defined(CHECK_BOUNDARY)\n"
+       "                               if( addr+i < n )\n"
+       "#endif\n"
+       "#if defined(NV_GPU)\n"
+       "                               SET_HISTOGRAM( setIdx, keys[i] )++;\n"
+       "#else\n"
+       "                               AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );\n"
+       "#endif\n"
+       "                       \n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "                       \n"
+       "                       uint hIdx = NUM_BUCKET+lIdx;\n"
+       "                       if( lIdx < NUM_BUCKET )\n"
+       "                       {\n"
+       "                               u32 sum = 0;\n"
+       "                               for(int i=0; i<WG_SIZE/16; i++)\n"
+       "                               {\n"
+       "                                       sum += SET_HISTOGRAM( i, lIdx );\n"
+       "                               }\n"
+       "                               myHistogram = sum;\n"
+       "                               localHistogram[hIdx] = sum;\n"
+       "                       }\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "#if defined(USE_2LEVEL_REDUCE)\n"
+       "                       if( lIdx < NUM_BUCKET )\n"
+       "                       {\n"
+       "                               localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               u32 u0, u1, u2;\n"
+       "                               u0 = localHistogram[hIdx-3];\n"
+       "                               u1 = localHistogram[hIdx-2];\n"
+       "                               u2 = localHistogram[hIdx-1];\n"
+       "                               AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               u0 = localHistogram[hIdx-12];\n"
+       "                               u1 = localHistogram[hIdx-8];\n"
+       "                               u2 = localHistogram[hIdx-4];\n"
+       "                               AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                       }\n"
+       "#else\n"
+       "                       if( lIdx < NUM_BUCKET )\n"
+       "                       {\n"
+       "                               localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               localHistogram[hIdx] += localHistogram[hIdx-1];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               localHistogram[hIdx] += localHistogram[hIdx-2];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               localHistogram[hIdx] += localHistogram[hIdx-4];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               localHistogram[hIdx] += localHistogram[hIdx-8];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                       }\n"
+       "#endif\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "               }\n"
+       "               {\n"
+       "                       for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)\n"
+       "                       {\n"
+       "                               int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;\n"
+       "                               int binIdx = keys[ie];\n"
+       "                               int groupOffset = localHistogramToCarry[binIdx];\n"
+       "                               int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n"
+       "#if defined(CHECK_BOUNDARY)\n"
+       "                               if( addr+ie < n )\n"
+       "#endif\n"
+       "                               gDst[ groupOffset + myIdx ] = sortData[ie];\n"
+       "                       }\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "               if( lIdx < NUM_BUCKET )\n"
+       "               {\n"
+       "                       localHistogramToCarry[lIdx] += myHistogram;\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "       }\n"
+       "}\n"
+       "//     2 scan, 2 exchange\n"
+       "void sort4Bits1KeyValue(u32 sortData[4], int sortVal[4], int startBit, int lIdx, __local u32* ldsSortData, __local int *ldsSortVal)\n"
+       "{\n"
+       "       for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)\n"
+       "       {\n"
+       "               uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, \n"
+       "                       (sortData[1]>>(startBit+ibit)) & 0x3, \n"
+       "                       (sortData[2]>>(startBit+ibit)) & 0x3, \n"
+       "                       (sortData[3]>>(startBit+ibit)) & 0x3);\n"
+       "               u32 key4;\n"
+       "               u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n"
+       "               {\n"
+       "                       sKeyPacked[0] |= 1<<(8*b.x);\n"
+       "                       sKeyPacked[1] |= 1<<(8*b.y);\n"
+       "                       sKeyPacked[2] |= 1<<(8*b.z);\n"
+       "                       sKeyPacked[3] |= 1<<(8*b.w);\n"
+       "                       key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n"
+       "               }\n"
+       "               u32 rankPacked;\n"
+       "               u32 sumPacked;\n"
+       "               {\n"
+       "                       rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "               u32 newOffset[4] = { 0,0,0,0 };\n"
+       "               {\n"
+       "                       u32 sumScanned = bit8Scan( sumPacked );\n"
+       "                       u32 scannedKeys[4];\n"
+       "                       scannedKeys[0] = 1<<(8*b.x);\n"
+       "                       scannedKeys[1] = 1<<(8*b.y);\n"
+       "                       scannedKeys[2] = 1<<(8*b.z);\n"
+       "                       scannedKeys[3] = 1<<(8*b.w);\n"
+       "                       {       //      4 scans at once\n"
+       "                               u32 sum4 = 0;\n"
+       "                               for(int ie=0; ie<4; ie++)\n"
+       "                               {\n"
+       "                                       u32 tmp = scannedKeys[ie];\n"
+       "                                       scannedKeys[ie] = sum4;\n"
+       "                                       sum4 += tmp;\n"
+       "                               }\n"
+       "                       }\n"
+       "                       {\n"
+       "                               u32 sumPlusRank = sumScanned + rankPacked;\n"
+       "                               {       u32 ie = b.x;\n"
+       "                                       scannedKeys[0] += sumPlusRank;\n"
+       "                                       newOffset[0] = unpack4Key( scannedKeys[0], ie );\n"
+       "                               }\n"
+       "                               {       u32 ie = b.y;\n"
+       "                                       scannedKeys[1] += sumPlusRank;\n"
+       "                                       newOffset[1] = unpack4Key( scannedKeys[1], ie );\n"
+       "                               }\n"
+       "                               {       u32 ie = b.z;\n"
+       "                                       scannedKeys[2] += sumPlusRank;\n"
+       "                                       newOffset[2] = unpack4Key( scannedKeys[2], ie );\n"
+       "                               }\n"
+       "                               {       u32 ie = b.w;\n"
+       "                                       scannedKeys[3] += sumPlusRank;\n"
+       "                                       newOffset[3] = unpack4Key( scannedKeys[3], ie );\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "               {\n"
+       "                       ldsSortData[newOffset[0]] = sortData[0];\n"
+       "                       ldsSortData[newOffset[1]] = sortData[1];\n"
+       "                       ldsSortData[newOffset[2]] = sortData[2];\n"
+       "                       ldsSortData[newOffset[3]] = sortData[3];\n"
+       "                       ldsSortVal[newOffset[0]] = sortVal[0];\n"
+       "                       ldsSortVal[newOffset[1]] = sortVal[1];\n"
+       "                       ldsSortVal[newOffset[2]] = sortVal[2];\n"
+       "                       ldsSortVal[newOffset[3]] = sortVal[3];\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "                       u32 dstAddr = 4*lIdx;\n"
+       "                       sortData[0] = ldsSortData[dstAddr+0];\n"
+       "                       sortData[1] = ldsSortData[dstAddr+1];\n"
+       "                       sortData[2] = ldsSortData[dstAddr+2];\n"
+       "                       sortData[3] = ldsSortData[dstAddr+3];\n"
+       "                       sortVal[0] = ldsSortVal[dstAddr+0];\n"
+       "                       sortVal[1] = ldsSortVal[dstAddr+1];\n"
+       "                       sortVal[2] = ldsSortVal[dstAddr+2];\n"
+       "                       sortVal[3] = ldsSortVal[dstAddr+3];\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void SortAndScatterSortDataKernel( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)\n"
+       "{\n"
+       "       __local int ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
+       "       __local int ldsSortVal[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
+       "       __local u32 localHistogramToCarry[NUM_BUCKET];\n"
+       "       __local u32 localHistogram[NUM_BUCKET*2];\n"
+       "       u32 gIdx = GET_GLOBAL_IDX;\n"
+       "       u32 lIdx = GET_LOCAL_IDX;\n"
+       "       u32 wgIdx = GET_GROUP_IDX;\n"
+       "       u32 wgSize = GET_GROUP_SIZE;\n"
+       "       const int n = cb.m_n;\n"
+       "       const int nWGs = cb.m_nWGs;\n"
+       "       const int startBit = cb.m_startBit;\n"
+       "       const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+       "       if( lIdx < (NUM_BUCKET) )\n"
+       "       {\n"
+       "               localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "    \n"
+       "       const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+       "       int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n"
+       "       int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+       "       for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
+       "       {\n"
+       "               u32 myHistogram = 0;\n"
+       "               int sortData[ELEMENTS_PER_WORK_ITEM];\n"
+       "               int sortVal[ELEMENTS_PER_WORK_ITEM];\n"
+       "               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+       "#if defined(CHECK_BOUNDARY)\n"
+       "               {\n"
+       "                       sortData[i] = ( addr+i < n )? gSrc[ addr+i ].m_key : 0xffffffff;\n"
+       "                       sortVal[i] = ( addr+i < n )? gSrc[ addr+i ].m_value : 0xffffffff;\n"
+       "               }\n"
+       "#else\n"
+       "               {\n"
+       "                       sortData[i] = gSrc[ addr+i ].m_key;\n"
+       "                       sortVal[i] = gSrc[ addr+i ].m_value;\n"
+       "               }\n"
+       "#endif\n"
+       "               sort4Bits1KeyValue(sortData, sortVal, startBit, lIdx, ldsSortData, ldsSortVal);\n"
+       "               u32 keys[ELEMENTS_PER_WORK_ITEM];\n"
+       "               for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+       "                       keys[i] = (sortData[i]>>startBit) & 0xf;\n"
+       "               {       //      create histogram\n"
+       "                       u32 setIdx = lIdx/16;\n"
+       "                       if( lIdx < NUM_BUCKET )\n"
+       "                       {\n"
+       "                               localHistogram[lIdx] = 0;\n"
+       "                       }\n"
+       "                       ldsSortData[lIdx] = 0;\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "                       for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
+       "#if defined(CHECK_BOUNDARY)\n"
+       "                               if( addr+i < n )\n"
+       "#endif\n"
+       "#if defined(NV_GPU)\n"
+       "                               SET_HISTOGRAM( setIdx, keys[i] )++;\n"
+       "#else\n"
+       "                               AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );\n"
+       "#endif\n"
+       "                       \n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "                       \n"
+       "                       uint hIdx = NUM_BUCKET+lIdx;\n"
+       "                       if( lIdx < NUM_BUCKET )\n"
+       "                       {\n"
+       "                               u32 sum = 0;\n"
+       "                               for(int i=0; i<WG_SIZE/16; i++)\n"
+       "                               {\n"
+       "                                       sum += SET_HISTOGRAM( i, lIdx );\n"
+       "                               }\n"
+       "                               myHistogram = sum;\n"
+       "                               localHistogram[hIdx] = sum;\n"
+       "                       }\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "#if defined(USE_2LEVEL_REDUCE)\n"
+       "                       if( lIdx < NUM_BUCKET )\n"
+       "                       {\n"
+       "                               localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               u32 u0, u1, u2;\n"
+       "                               u0 = localHistogram[hIdx-3];\n"
+       "                               u1 = localHistogram[hIdx-2];\n"
+       "                               u2 = localHistogram[hIdx-1];\n"
+       "                               AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               u0 = localHistogram[hIdx-12];\n"
+       "                               u1 = localHistogram[hIdx-8];\n"
+       "                               u2 = localHistogram[hIdx-4];\n"
+       "                               AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                       }\n"
+       "#else\n"
+       "                       if( lIdx < NUM_BUCKET )\n"
+       "                       {\n"
+       "                               localHistogram[hIdx] = localHistogram[hIdx-1];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               localHistogram[hIdx] += localHistogram[hIdx-1];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               localHistogram[hIdx] += localHistogram[hIdx-2];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               localHistogram[hIdx] += localHistogram[hIdx-4];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                               localHistogram[hIdx] += localHistogram[hIdx-8];\n"
+       "                               GROUP_MEM_FENCE;\n"
+       "                       }\n"
+       "#endif\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "               }\n"
+       "       {\n"
+       "                       for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)\n"
+       "                       {\n"
+       "                               int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;\n"
+       "                               int binIdx = keys[ie];\n"
+       "                               int groupOffset = localHistogramToCarry[binIdx];\n"
+       "                               int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n"
+       "#if defined(CHECK_BOUNDARY)\n"
+       "                               if( addr+ie < n )\n"
+       "                               {\n"
+       "                    if ((groupOffset + myIdx)<n)\n"
+       "                    {\n"
+       "                        if (sortData[ie]==sortVal[ie])\n"
+       "                        {\n"
+       "                            \n"
+       "                            SortDataCL tmp;\n"
+       "                            tmp.m_key = sortData[ie];\n"
+       "                            tmp.m_value = sortVal[ie];\n"
+       "                            if (tmp.m_key == tmp.m_value)\n"
+       "                                gDst[groupOffset + myIdx ] = tmp;\n"
+       "                        }\n"
+       "                        \n"
+       "                    }\n"
+       "                               }\n"
+       "#else\n"
+       "                if ((groupOffset + myIdx)<n)\n"
+       "                {\n"
+       "                    gDst[ groupOffset + myIdx ].m_key = sortData[ie];\n"
+       "                    gDst[ groupOffset + myIdx ].m_value = sortVal[ie];\n"
+       "                }\n"
+       "#endif\n"
+       "                       }\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "               if( lIdx < NUM_BUCKET )\n"
+       "               {\n"
+       "                       localHistogramToCarry[lIdx] += myHistogram;\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "       }\n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void SortAndScatterSortDataKernelSerial( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)\n"
+       "{\n"
+       "    \n"
+       "       u32 gIdx = GET_GLOBAL_IDX;\n"
+       "       u32 realLocalIdx = GET_LOCAL_IDX;\n"
+       "       u32 wgIdx = GET_GROUP_IDX;\n"
+       "       u32 wgSize = GET_GROUP_SIZE;\n"
+       "       const int startBit = cb.m_startBit;\n"
+       "       const int n = cb.m_n;\n"
+       "       const int nWGs = cb.m_nWGs;\n"
+       "       const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+       "    int counter[NUM_BUCKET];\n"
+       "    \n"
+       "    if (realLocalIdx>0)\n"
+       "        return;\n"
+       "    \n"
+       "    for (int c=0;c<NUM_BUCKET;c++)\n"
+       "        counter[c]=0;\n"
+       "    const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+       "       \n"
+       "       int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+       "   for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)\n"
+       "  {\n"
+       "     for (int lIdx=0;lIdx<WG_SIZE;lIdx++)\n"
+       "       {\n"
+       "        int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+       "        \n"
+       "               for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)\n"
+       "               {\n"
+       "            int i = addr2+j;\n"
+       "                       if( i < n )\n"
+       "                       {\n"
+       "                int tableIdx;\n"
+       "                               tableIdx = (gSrc[i].m_key>>startBit) & 0xf;//0xf = NUM_TABLES-1\n"
+       "                gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];\n"
+       "                counter[tableIdx] ++;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "  }\n"
+       "    \n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void SortAndScatterKernelSerial( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4  cb )\n"
+       "{\n"
+       "    \n"
+       "       u32 gIdx = GET_GLOBAL_IDX;\n"
+       "       u32 realLocalIdx = GET_LOCAL_IDX;\n"
+       "       u32 wgIdx = GET_GROUP_IDX;\n"
+       "       u32 wgSize = GET_GROUP_SIZE;\n"
+       "       const int startBit = cb.m_startBit;\n"
+       "       const int n = cb.m_n;\n"
+       "       const int nWGs = cb.m_nWGs;\n"
+       "       const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
+       "    int counter[NUM_BUCKET];\n"
+       "    \n"
+       "    if (realLocalIdx>0)\n"
+       "        return;\n"
+       "    \n"
+       "    for (int c=0;c<NUM_BUCKET;c++)\n"
+       "        counter[c]=0;\n"
+       "    const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
+       "       \n"
+       "       int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
+       "   for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)\n"
+       "  {\n"
+       "     for (int lIdx=0;lIdx<WG_SIZE;lIdx++)\n"
+       "       {\n"
+       "        int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
+       "        \n"
+       "               for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)\n"
+       "               {\n"
+       "            int i = addr2+j;\n"
+       "                       if( i < n )\n"
+       "                       {\n"
+       "                int tableIdx;\n"
+       "                               tableIdx = (gSrc[i]>>startBit) & 0xf;//0xf = NUM_TABLES-1\n"
+       "                gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];\n"
+       "                counter[tableIdx] ++;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "  }\n"
+       "    \n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp
new file mode 100644 (file)
index 0000000..6571f30
--- /dev/null
@@ -0,0 +1,374 @@
+
+#include "b3GpuRaycast.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h"
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h"
+
+#include "Bullet3OpenCL/Raycast/kernels/rayCastKernels.h"
+
+#define B3_RAYCAST_PATH "src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl"
+
+struct b3GpuRaycastInternalData
+{
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_q;
+       cl_kernel m_raytraceKernel;
+       cl_kernel m_raytracePairsKernel;
+       cl_kernel m_findRayRigidPairIndexRanges;
+
+       b3GpuParallelLinearBvh* m_plbvh;
+       b3RadixSort32CL* m_radixSorter;
+       b3FillCL* m_fill;
+
+       //1 element per ray
+       b3OpenCLArray<b3RayInfo>* m_gpuRays;
+       b3OpenCLArray<b3RayHit>* m_gpuHitResults;
+       b3OpenCLArray<int>* m_firstRayRigidPairIndexPerRay;
+       b3OpenCLArray<int>* m_numRayRigidPairsPerRay;
+
+       //1 element per (ray index, rigid index) pair, where the ray intersects with the rigid's AABB
+       b3OpenCLArray<int>* m_gpuNumRayRigidPairs;
+       b3OpenCLArray<b3Int2>* m_gpuRayRigidPairs;  //x == ray index, y == rigid index
+
+       int m_test;
+};
+
+b3GpuRaycast::b3GpuRaycast(cl_context ctx, cl_device_id device, cl_command_queue q)
+{
+       m_data = new b3GpuRaycastInternalData;
+       m_data->m_context = ctx;
+       m_data->m_device = device;
+       m_data->m_q = q;
+       m_data->m_raytraceKernel = 0;
+       m_data->m_raytracePairsKernel = 0;
+       m_data->m_findRayRigidPairIndexRanges = 0;
+
+       m_data->m_plbvh = new b3GpuParallelLinearBvh(ctx, device, q);
+       m_data->m_radixSorter = new b3RadixSort32CL(ctx, device, q);
+       m_data->m_fill = new b3FillCL(ctx, device, q);
+
+       m_data->m_gpuRays = new b3OpenCLArray<b3RayInfo>(ctx, q);
+       m_data->m_gpuHitResults = new b3OpenCLArray<b3RayHit>(ctx, q);
+       m_data->m_firstRayRigidPairIndexPerRay = new b3OpenCLArray<int>(ctx, q);
+       m_data->m_numRayRigidPairsPerRay = new b3OpenCLArray<int>(ctx, q);
+       m_data->m_gpuNumRayRigidPairs = new b3OpenCLArray<int>(ctx, q);
+       m_data->m_gpuRayRigidPairs = new b3OpenCLArray<b3Int2>(ctx, q);
+
+       {
+               cl_int errNum = 0;
+               cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, &errNum, "", B3_RAYCAST_PATH);
+               b3Assert(errNum == CL_SUCCESS);
+               m_data->m_raytraceKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, "rayCastKernel", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+               m_data->m_raytracePairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, "rayCastPairsKernel", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+               m_data->m_findRayRigidPairIndexRanges = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, "findRayRigidPairIndexRanges", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+               clReleaseProgram(prog);
+       }
+}
+
+b3GpuRaycast::~b3GpuRaycast()
+{
+       clReleaseKernel(m_data->m_raytraceKernel);
+       clReleaseKernel(m_data->m_raytracePairsKernel);
+       clReleaseKernel(m_data->m_findRayRigidPairIndexRanges);
+
+       delete m_data->m_plbvh;
+       delete m_data->m_radixSorter;
+       delete m_data->m_fill;
+
+       delete m_data->m_gpuRays;
+       delete m_data->m_gpuHitResults;
+       delete m_data->m_firstRayRigidPairIndexPerRay;
+       delete m_data->m_numRayRigidPairsPerRay;
+       delete m_data->m_gpuNumRayRigidPairs;
+       delete m_data->m_gpuRayRigidPairs;
+
+       delete m_data;
+}
+
+bool sphere_intersect(const b3Vector3& spherePos, b3Scalar radius, const b3Vector3& rayFrom, const b3Vector3& rayTo, float& hitFraction)
+{
+       b3Vector3 rs = rayFrom - spherePos;
+       b3Vector3 rayDir = rayTo - rayFrom;
+
+       float A = b3Dot(rayDir, rayDir);
+       float B = b3Dot(rs, rayDir);
+       float C = b3Dot(rs, rs) - (radius * radius);
+
+       float D = B * B - A * C;
+
+       if (D > 0.0)
+       {
+               float t = (-B - sqrt(D)) / A;
+
+               if ((t >= 0.0f) && (t < hitFraction))
+               {
+                       hitFraction = t;
+                       return true;
+               }
+       }
+       return false;
+}
+
+bool rayConvex(const b3Vector3& rayFromLocal, const b3Vector3& rayToLocal, const b3ConvexPolyhedronData& poly,
+                          const b3AlignedObjectArray<b3GpuFace>& faces, float& hitFraction, b3Vector3& hitNormal)
+{
+       float exitFraction = hitFraction;
+       float enterFraction = -0.1f;
+       b3Vector3 curHitNormal = b3MakeVector3(0, 0, 0);
+       for (int i = 0; i < poly.m_numFaces; i++)
+       {
+               const b3GpuFace& face = faces[poly.m_faceOffset + i];
+               float fromPlaneDist = b3Dot(rayFromLocal, face.m_plane) + face.m_plane.w;
+               float toPlaneDist = b3Dot(rayToLocal, face.m_plane) + face.m_plane.w;
+               if (fromPlaneDist < 0.f)
+               {
+                       if (toPlaneDist >= 0.f)
+                       {
+                               float fraction = fromPlaneDist / (fromPlaneDist - toPlaneDist);
+                               if (exitFraction > fraction)
+                               {
+                                       exitFraction = fraction;
+                               }
+                       }
+               }
+               else
+               {
+                       if (toPlaneDist < 0.f)
+                       {
+                               float fraction = fromPlaneDist / (fromPlaneDist - toPlaneDist);
+                               if (enterFraction <= fraction)
+                               {
+                                       enterFraction = fraction;
+                                       curHitNormal = face.m_plane;
+                                       curHitNormal.w = 0.f;
+                               }
+                       }
+                       else
+                       {
+                               return false;
+                       }
+               }
+               if (exitFraction <= enterFraction)
+                       return false;
+       }
+
+       if (enterFraction < 0.f)
+               return false;
+
+       hitFraction = enterFraction;
+       hitNormal = curHitNormal;
+       return true;
+}
+
+void b3GpuRaycast::castRaysHost(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
+                                                               int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables, const struct b3GpuNarrowPhaseInternalData* narrowphaseData)
+{
+       //      return castRays(rays,hitResults,numBodies,bodies,numCollidables,collidables);
+
+       B3_PROFILE("castRaysHost");
+       for (int r = 0; r < rays.size(); r++)
+       {
+               b3Vector3 rayFrom = rays[r].m_from;
+               b3Vector3 rayTo = rays[r].m_to;
+               float hitFraction = hitResults[r].m_hitFraction;
+
+               int hitBodyIndex = -1;
+               b3Vector3 hitNormal;
+
+               for (int b = 0; b < numBodies; b++)
+               {
+                       const b3Vector3& pos = bodies[b].m_pos;
+                       //const b3Quaternion& orn = bodies[b].m_quat;
+
+                       switch (collidables[bodies[b].m_collidableIdx].m_shapeType)
+                       {
+                               case SHAPE_SPHERE:
+                               {
+                                       b3Scalar radius = collidables[bodies[b].m_collidableIdx].m_radius;
+                                       if (sphere_intersect(pos, radius, rayFrom, rayTo, hitFraction))
+                                       {
+                                               hitBodyIndex = b;
+                                               b3Vector3 hitPoint;
+                                               hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to, hitFraction);
+                                               hitNormal = (hitPoint - bodies[b].m_pos).normalize();
+                                       }
+                               }
+                               case SHAPE_CONVEX_HULL:
+                               {
+                                       b3Transform convexWorldTransform;
+                                       convexWorldTransform.setIdentity();
+                                       convexWorldTransform.setOrigin(bodies[b].m_pos);
+                                       convexWorldTransform.setRotation(bodies[b].m_quat);
+                                       b3Transform convexWorld2Local = convexWorldTransform.inverse();
+
+                                       b3Vector3 rayFromLocal = convexWorld2Local(rayFrom);
+                                       b3Vector3 rayToLocal = convexWorld2Local(rayTo);
+
+                                       int shapeIndex = collidables[bodies[b].m_collidableIdx].m_shapeIndex;
+                                       const b3ConvexPolyhedronData& poly = narrowphaseData->m_convexPolyhedra[shapeIndex];
+                                       if (rayConvex(rayFromLocal, rayToLocal, poly, narrowphaseData->m_convexFaces, hitFraction, hitNormal))
+                                       {
+                                               hitBodyIndex = b;
+                                       }
+
+                                       break;
+                               }
+                               default:
+                               {
+                                       static bool once = true;
+                                       if (once)
+                                       {
+                                               once = false;
+                                               b3Warning("Raytest: unsupported shape type\n");
+                                       }
+                               }
+                       }
+               }
+               if (hitBodyIndex >= 0)
+               {
+                       hitResults[r].m_hitFraction = hitFraction;
+                       hitResults[r].m_hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to, hitFraction);
+                       hitResults[r].m_hitNormal = hitNormal;
+                       hitResults[r].m_hitBody = hitBodyIndex;
+               }
+       }
+}
+///todo: add some acceleration structure (AABBs, tree etc)
+void b3GpuRaycast::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
+                                                       int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
+                                                       const struct b3GpuNarrowPhaseInternalData* narrowphaseData, class b3GpuBroadphaseInterface* broadphase)
+{
+       //castRaysHost(rays,hitResults,numBodies,bodies,numCollidables,collidables,narrowphaseData);
+
+       B3_PROFILE("castRaysGPU");
+
+       {
+               B3_PROFILE("raycast copyFromHost");
+               m_data->m_gpuRays->copyFromHost(rays);
+               m_data->m_gpuHitResults->copyFromHost(hitResults);
+       }
+
+       int numRays = hitResults.size();
+       {
+               m_data->m_firstRayRigidPairIndexPerRay->resize(numRays);
+               m_data->m_numRayRigidPairsPerRay->resize(numRays);
+
+               m_data->m_gpuNumRayRigidPairs->resize(1);
+               m_data->m_gpuRayRigidPairs->resize(numRays * 16);
+       }
+
+       //run kernel
+       const bool USE_BRUTE_FORCE_RAYCAST = false;
+       if (USE_BRUTE_FORCE_RAYCAST)
+       {
+               B3_PROFILE("raycast launch1D");
+
+               b3LauncherCL launcher(m_data->m_q, m_data->m_raytraceKernel, "m_raytraceKernel");
+               int numRays = rays.size();
+               launcher.setConst(numRays);
+
+               launcher.setBuffer(m_data->m_gpuRays->getBufferCL());
+               launcher.setBuffer(m_data->m_gpuHitResults->getBufferCL());
+
+               launcher.setConst(numBodies);
+               launcher.setBuffer(narrowphaseData->m_bodyBufferGPU->getBufferCL());
+               launcher.setBuffer(narrowphaseData->m_collidablesGPU->getBufferCL());
+               launcher.setBuffer(narrowphaseData->m_convexFacesGPU->getBufferCL());
+               launcher.setBuffer(narrowphaseData->m_convexPolyhedraGPU->getBufferCL());
+
+               launcher.launch1D(numRays);
+               clFinish(m_data->m_q);
+       }
+       else
+       {
+               m_data->m_plbvh->build(broadphase->getAllAabbsGPU(), broadphase->getSmallAabbIndicesGPU(), broadphase->getLargeAabbIndicesGPU());
+
+               m_data->m_plbvh->testRaysAgainstBvhAabbs(*m_data->m_gpuRays, *m_data->m_gpuNumRayRigidPairs, *m_data->m_gpuRayRigidPairs);
+
+               int numRayRigidPairs = -1;
+               m_data->m_gpuNumRayRigidPairs->copyToHostPointer(&numRayRigidPairs, 1);
+               if (numRayRigidPairs > m_data->m_gpuRayRigidPairs->size())
+               {
+                       numRayRigidPairs = m_data->m_gpuRayRigidPairs->size();
+                       m_data->m_gpuNumRayRigidPairs->copyFromHostPointer(&numRayRigidPairs, 1);
+               }
+
+               m_data->m_gpuRayRigidPairs->resize(numRayRigidPairs);  //Radix sort needs b3OpenCLArray::size() to be correct
+
+               //Sort ray-rigid pairs by ray index
+               {
+                       B3_PROFILE("sort ray-rigid pairs");
+                       m_data->m_radixSorter->execute(*reinterpret_cast<b3OpenCLArray<b3SortData>*>(m_data->m_gpuRayRigidPairs));
+               }
+
+               //detect start,count of each ray pair
+               {
+                       B3_PROFILE("detect ray-rigid pair index ranges");
+
+                       {
+                               B3_PROFILE("reset ray-rigid pair index ranges");
+
+                               m_data->m_fill->execute(*m_data->m_firstRayRigidPairIndexPerRay, numRayRigidPairs, numRays);  //atomic_min used to find first index
+                               m_data->m_fill->execute(*m_data->m_numRayRigidPairsPerRay, 0, numRays);
+                               clFinish(m_data->m_q);
+                       }
+
+                       b3BufferInfoCL bufferInfo[] =
+                               {
+                                       b3BufferInfoCL(m_data->m_gpuRayRigidPairs->getBufferCL()),
+
+                                       b3BufferInfoCL(m_data->m_firstRayRigidPairIndexPerRay->getBufferCL()),
+                                       b3BufferInfoCL(m_data->m_numRayRigidPairsPerRay->getBufferCL())};
+
+                       b3LauncherCL launcher(m_data->m_q, m_data->m_findRayRigidPairIndexRanges, "m_findRayRigidPairIndexRanges");
+                       launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numRayRigidPairs);
+
+                       launcher.launch1D(numRayRigidPairs);
+                       clFinish(m_data->m_q);
+               }
+
+               {
+                       B3_PROFILE("ray-rigid intersection");
+
+                       b3BufferInfoCL bufferInfo[] =
+                               {
+                                       b3BufferInfoCL(m_data->m_gpuRays->getBufferCL()),
+                                       b3BufferInfoCL(m_data->m_gpuHitResults->getBufferCL()),
+                                       b3BufferInfoCL(m_data->m_firstRayRigidPairIndexPerRay->getBufferCL()),
+                                       b3BufferInfoCL(m_data->m_numRayRigidPairsPerRay->getBufferCL()),
+
+                                       b3BufferInfoCL(narrowphaseData->m_bodyBufferGPU->getBufferCL()),
+                                       b3BufferInfoCL(narrowphaseData->m_collidablesGPU->getBufferCL()),
+                                       b3BufferInfoCL(narrowphaseData->m_convexFacesGPU->getBufferCL()),
+                                       b3BufferInfoCL(narrowphaseData->m_convexPolyhedraGPU->getBufferCL()),
+
+                                       b3BufferInfoCL(m_data->m_gpuRayRigidPairs->getBufferCL())};
+
+                       b3LauncherCL launcher(m_data->m_q, m_data->m_raytracePairsKernel, "m_raytracePairsKernel");
+                       launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
+                       launcher.setConst(numRays);
+
+                       launcher.launch1D(numRays);
+                       clFinish(m_data->m_q);
+               }
+       }
+
+       //copy results
+       {
+               B3_PROFILE("raycast copyToHost");
+               m_data->m_gpuHitResults->copyToHost(hitResults);
+       }
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/b3GpuRaycast.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/b3GpuRaycast.h
new file mode 100644 (file)
index 0000000..f1f6ffd
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef B3_GPU_RAYCAST_H
+#define B3_GPU_RAYCAST_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
+
+class b3GpuRaycast
+{
+protected:
+       struct b3GpuRaycastInternalData* m_data;
+
+public:
+       b3GpuRaycast(cl_context ctx, cl_device_id device, cl_command_queue q);
+       virtual ~b3GpuRaycast();
+
+       void castRaysHost(const b3AlignedObjectArray<b3RayInfo>& raysIn, b3AlignedObjectArray<b3RayHit>& hitResults,
+                                         int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
+                                         const struct b3GpuNarrowPhaseInternalData* narrowphaseData);
+
+       void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
+                                 int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
+                                 const struct b3GpuNarrowPhaseInternalData* narrowphaseData, class b3GpuBroadphaseInterface* broadphase);
+};
+
+#endif  //B3_GPU_RAYCAST_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl
new file mode 100644 (file)
index 0000000..e72d968
--- /dev/null
@@ -0,0 +1,439 @@
+
+#define SHAPE_CONVEX_HULL 3
+#define SHAPE_PLANE 4
+#define SHAPE_CONCAVE_TRIMESH 5
+#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
+#define SHAPE_SPHERE 7
+
+
+typedef struct
+{
+       float4 m_from;
+       float4 m_to;
+} b3RayInfo;
+
+typedef struct
+{
+       float m_hitFraction;
+       int     m_hitResult0;
+       int     m_hitResult1;
+       int     m_hitResult2;
+       float4  m_hitPoint;
+       float4  m_hitNormal;
+} b3RayHit;
+
+typedef struct
+{
+       float4 m_pos;
+       float4 m_quat;
+       float4 m_linVel;
+       float4 m_angVel;
+
+       unsigned int m_collidableIdx;
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+} Body;
+
+typedef struct Collidable
+{
+       union {
+               int m_numChildShapes;
+               int m_bvhIndex;
+       };
+       float m_radius;
+       int m_shapeType;
+       int m_shapeIndex;
+} Collidable;
+
+
+typedef struct  
+{
+       float4          m_localCenter;
+       float4          m_extents;
+       float4          mC;
+       float4          mE;
+
+       float                   m_radius;
+       int     m_faceOffset;
+       int m_numFaces;
+       int     m_numVertices;
+
+       int m_vertexOffset;
+       int     m_uniqueEdgesOffset;
+       int     m_numUniqueEdges;
+       int m_unused;
+
+} ConvexPolyhedronCL;
+
+typedef struct
+{
+       float4 m_plane;
+       int m_indexOffset;
+       int m_numIndices;
+} b3GpuFace;
+
+
+
+///////////////////////////////////////
+//     Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+       Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+       Quaternion qtNormalize(Quaternion in);
+
+
+__inline
+       Quaternion qtInvert(Quaternion q);
+
+
+__inline
+       float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = (float4)(a.xyz,0.f);
+       float4 b1 = (float4)(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+
+__inline
+       Quaternion qtMul(Quaternion a, Quaternion b)
+{
+       Quaternion ans;
+       ans = cross( a, b );
+       ans += a.w*b+b.w*a;
+       //      ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+       ans.w = a.w*b.w - dot3F4(a, b);
+       return ans;
+}
+
+__inline
+       Quaternion qtNormalize(Quaternion in)
+{
+       return fast_normalize(in);
+       //      in /= length( in );
+       //      return in;
+}
+__inline
+       float4 qtRotate(Quaternion q, float4 vec)
+{
+       Quaternion qInv = qtInvert( q );
+       float4 vcpy = vec;
+       vcpy.w = 0.f;
+       float4 out = qtMul(q,vcpy);
+       out = qtMul(out,qInv);
+       return out;
+}
+
+__inline
+       Quaternion qtInvert(Quaternion q)
+{
+       return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+       float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+       return qtRotate( qtInvert( q ), vec );
+}
+
+
+
+void   trInverse(float4 translationIn, Quaternion orientationIn,
+       float4* translationOut, Quaternion* orientationOut)
+{
+       *orientationOut = qtInvert(orientationIn);
+       *translationOut = qtRotate(*orientationOut, -translationIn);
+}
+
+
+
+
+
+bool rayConvex(float4 rayFromLocal, float4 rayToLocal, int numFaces, int faceOffset,
+       __global const b3GpuFace* faces, float* hitFraction, float4* hitNormal)
+{
+       rayFromLocal.w = 0.f;
+       rayToLocal.w = 0.f;
+       bool result = true;
+
+       float exitFraction = hitFraction[0];
+       float enterFraction = -0.3f;
+       float4 curHitNormal = (float4)(0,0,0,0);
+       for (int i=0;i<numFaces && result;i++)
+       {
+               b3GpuFace face = faces[faceOffset+i];
+               float fromPlaneDist = dot(rayFromLocal,face.m_plane)+face.m_plane.w;
+               float toPlaneDist = dot(rayToLocal,face.m_plane)+face.m_plane.w;
+               if (fromPlaneDist<0.f)
+               {
+                       if (toPlaneDist >= 0.f)
+                       {
+                               float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);
+                               if (exitFraction>fraction)
+                               {
+                                       exitFraction = fraction;
+                               }
+                       }                       
+               } else
+               {
+                       if (toPlaneDist<0.f)
+                       {
+                               float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);
+                               if (enterFraction <= fraction)
+                               {
+                                       enterFraction = fraction;
+                                       curHitNormal = face.m_plane;
+                                       curHitNormal.w = 0.f;
+                               }
+                       } else
+                       {
+                               result = false;
+                       }
+               }
+               if (exitFraction <= enterFraction)
+                       result = false;
+       }
+
+       if (enterFraction < 0.f)
+       {
+               result = false;
+       }
+
+       if (result)
+       {       
+               hitFraction[0] = enterFraction;
+               hitNormal[0] = curHitNormal;
+       }
+       return result;
+}
+
+
+
+
+
+
+bool sphere_intersect(float4 spherePos,  float radius, float4 rayFrom, float4 rayTo, float* hitFraction)
+{
+       float4 rs = rayFrom - spherePos;
+       rs.w = 0.f;
+       float4 rayDir = rayTo-rayFrom;
+       rayDir.w = 0.f;
+       float A = dot(rayDir,rayDir);
+       float B = dot(rs, rayDir);
+       float C = dot(rs, rs) - (radius * radius);
+
+       float D = B * B - A*C;
+
+       if (D > 0.0f)
+       {
+               float t = (-B - sqrt(D))/A;
+
+               if ( (t >= 0.0f) && (t < (*hitFraction)) )
+               {
+                       *hitFraction = t;
+                       return true;
+               }
+       }
+       return false;
+}
+
+float4 setInterpolate3(float4 from, float4 to, float t)
+{
+       float s = 1.0f - t;
+       float4 result;
+       result = s * from + t * to;
+       result.w = 0.f; 
+       return result;  
+}
+
+__kernel void rayCastKernel(  
+       int numRays, 
+       const __global b3RayInfo* rays, 
+       __global b3RayHit* hitResults, 
+       const int numBodies, 
+       __global Body* bodies,
+       __global Collidable* collidables,
+       __global const b3GpuFace* faces,
+       __global const ConvexPolyhedronCL* convexShapes )
+{
+
+       int i = get_global_id(0);
+       if (i>=numRays)
+               return;
+
+       hitResults[i].m_hitFraction = 1.f;
+
+       float4 rayFrom = rays[i].m_from;
+       float4 rayTo = rays[i].m_to;
+       float hitFraction = 1.f;
+       float4 hitPoint;
+       float4 hitNormal;
+       int hitBodyIndex= -1;
+
+       int cachedCollidableIndex = -1;
+       Collidable cachedCollidable;
+
+       for (int b=0;b<numBodies;b++)
+       {
+               if (hitResults[i].m_hitResult2==b)
+                       continue;
+               Body body = bodies[b];
+               float4 pos = body.m_pos;
+               float4 orn = body.m_quat;
+               if (cachedCollidableIndex != body.m_collidableIdx)
+               {
+                       cachedCollidableIndex = body.m_collidableIdx;
+                       cachedCollidable = collidables[cachedCollidableIndex];
+               }
+               if (cachedCollidable.m_shapeType == SHAPE_CONVEX_HULL)
+               {
+
+                       float4 invPos = (float4)(0,0,0,0);
+                       float4 invOrn = (float4)(0,0,0,0);
+                       float4 rayFromLocal = (float4)(0,0,0,0);
+                       float4 rayToLocal = (float4)(0,0,0,0);
+                       invOrn = qtInvert(orn);
+                       invPos = qtRotate(invOrn, -pos);
+                       rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;
+                       rayToLocal = qtRotate( invOrn, rayTo) + invPos;
+                       rayFromLocal.w = 0.f;
+                       rayToLocal.w = 0.f;
+                       int numFaces = convexShapes[cachedCollidable.m_shapeIndex].m_numFaces;
+                       int faceOffset = convexShapes[cachedCollidable.m_shapeIndex].m_faceOffset;
+                       if (numFaces)
+                       {
+                               if (rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))
+                               {
+                                       hitBodyIndex = b;
+                                       
+                               }
+                       }
+               }
+               if (cachedCollidable.m_shapeType == SHAPE_SPHERE)
+               {
+                       float radius = cachedCollidable.m_radius;
+               
+                       if (sphere_intersect(pos,  radius, rayFrom, rayTo, &hitFraction))
+                       {
+                               hitBodyIndex = b;
+                               hitNormal = (float4) (hitPoint-bodies[b].m_pos);
+                       }
+               }
+       }
+
+       if (hitBodyIndex>=0)
+       {
+               hitPoint = setInterpolate3(rayFrom, rayTo,hitFraction);
+               hitResults[i].m_hitFraction = hitFraction;
+               hitResults[i].m_hitPoint = hitPoint;
+               hitResults[i].m_hitNormal = normalize(hitNormal);
+               hitResults[i].m_hitResult0 = hitBodyIndex;
+       }
+
+}
+
+
+__kernel void findRayRigidPairIndexRanges(__global int2* rayRigidPairs, 
+                                                                                       __global int* out_firstRayRigidPairIndexPerRay,
+                                                                                       __global int* out_numRayRigidPairsPerRay,
+                                                                                       int numRayRigidPairs)
+{
+       int rayRigidPairIndex = get_global_id(0);
+       if (rayRigidPairIndex >= numRayRigidPairs) return;
+       
+       int rayIndex = rayRigidPairs[rayRigidPairIndex].x;
+       
+       atomic_min(&out_firstRayRigidPairIndexPerRay[rayIndex], rayRigidPairIndex);
+       atomic_inc(&out_numRayRigidPairsPerRay[rayIndex]);
+}
+
+__kernel void rayCastPairsKernel(const __global b3RayInfo* rays, 
+                                                               __global b3RayHit* hitResults, 
+                                                               __global int* firstRayRigidPairIndexPerRay,
+                                                               __global int* numRayRigidPairsPerRay,
+                                                                       
+                                                               __global Body* bodies,
+                                                               __global Collidable* collidables,
+                                                               __global const b3GpuFace* faces,
+                                                               __global const ConvexPolyhedronCL* convexShapes,
+                                                               
+                                                               __global int2* rayRigidPairs,
+                                                               int numRays)
+{
+       int i = get_global_id(0);
+       if (i >= numRays) return;
+       
+       float4 rayFrom = rays[i].m_from;
+       float4 rayTo = rays[i].m_to;
+               
+       hitResults[i].m_hitFraction = 1.f;
+               
+       float hitFraction = 1.f;
+       float4 hitPoint;
+       float4 hitNormal;
+       int hitBodyIndex = -1;
+               
+       //
+       for(int pair = 0; pair < numRayRigidPairsPerRay[i]; ++pair)
+       {
+               int rayRigidPairIndex = pair + firstRayRigidPairIndexPerRay[i];
+               int b = rayRigidPairs[rayRigidPairIndex].y;
+               
+               if (hitResults[i].m_hitResult2 == b) continue;
+               
+               Body body = bodies[b];
+               Collidable rigidCollidable = collidables[body.m_collidableIdx];
+               
+               float4 pos = body.m_pos;
+               float4 orn = body.m_quat;
+               
+               if (rigidCollidable.m_shapeType == SHAPE_CONVEX_HULL)
+               {
+                       float4 invPos = (float4)(0,0,0,0);
+                       float4 invOrn = (float4)(0,0,0,0);
+                       float4 rayFromLocal = (float4)(0,0,0,0);
+                       float4 rayToLocal = (float4)(0,0,0,0);
+                       invOrn = qtInvert(orn);
+                       invPos = qtRotate(invOrn, -pos);
+                       rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;
+                       rayToLocal = qtRotate( invOrn, rayTo) + invPos;
+                       rayFromLocal.w = 0.f;
+                       rayToLocal.w = 0.f;
+                       int numFaces = convexShapes[rigidCollidable.m_shapeIndex].m_numFaces;
+                       int faceOffset = convexShapes[rigidCollidable.m_shapeIndex].m_faceOffset;
+                       
+                       if (numFaces && rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))
+                       {
+                               hitBodyIndex = b;
+                               hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);
+                       }
+               }
+               
+               if (rigidCollidable.m_shapeType == SHAPE_SPHERE)
+               {
+                       float radius = rigidCollidable.m_radius;
+               
+                       if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))
+                       {
+                               hitBodyIndex = b;
+                               hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);
+                               hitNormal = (float4) (hitPoint - bodies[b].m_pos);
+                       }
+               }
+       }
+       
+       if (hitBodyIndex >= 0)
+       {
+               hitResults[i].m_hitFraction = hitFraction;
+               hitResults[i].m_hitPoint = hitPoint;
+               hitResults[i].m_hitNormal = normalize(hitNormal);
+               hitResults[i].m_hitResult0 = hitBodyIndex;
+       }
+       
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h
new file mode 100644 (file)
index 0000000..94f6a8e
--- /dev/null
@@ -0,0 +1,380 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* rayCastKernelCL =
+       "#define SHAPE_CONVEX_HULL 3\n"
+       "#define SHAPE_PLANE 4\n"
+       "#define SHAPE_CONCAVE_TRIMESH 5\n"
+       "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
+       "#define SHAPE_SPHERE 7\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_from;\n"
+       "       float4 m_to;\n"
+       "} b3RayInfo;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float m_hitFraction;\n"
+       "       int     m_hitResult0;\n"
+       "       int     m_hitResult1;\n"
+       "       int     m_hitResult2;\n"
+       "       float4  m_hitPoint;\n"
+       "       float4  m_hitNormal;\n"
+       "} b3RayHit;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_pos;\n"
+       "       float4 m_quat;\n"
+       "       float4 m_linVel;\n"
+       "       float4 m_angVel;\n"
+       "       unsigned int m_collidableIdx;\n"
+       "       float m_invMass;\n"
+       "       float m_restituitionCoeff;\n"
+       "       float m_frictionCoeff;\n"
+       "} Body;\n"
+       "typedef struct Collidable\n"
+       "{\n"
+       "       union {\n"
+       "               int m_numChildShapes;\n"
+       "               int m_bvhIndex;\n"
+       "       };\n"
+       "       float m_radius;\n"
+       "       int m_shapeType;\n"
+       "       int m_shapeIndex;\n"
+       "} Collidable;\n"
+       "typedef struct  \n"
+       "{\n"
+       "       float4          m_localCenter;\n"
+       "       float4          m_extents;\n"
+       "       float4          mC;\n"
+       "       float4          mE;\n"
+       "       float                   m_radius;\n"
+       "       int     m_faceOffset;\n"
+       "       int m_numFaces;\n"
+       "       int     m_numVertices;\n"
+       "       int m_vertexOffset;\n"
+       "       int     m_uniqueEdgesOffset;\n"
+       "       int     m_numUniqueEdges;\n"
+       "       int m_unused;\n"
+       "} ConvexPolyhedronCL;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_plane;\n"
+       "       int m_indexOffset;\n"
+       "       int m_numIndices;\n"
+       "} b3GpuFace;\n"
+       "///////////////////////////////////////\n"
+       "//     Quaternion\n"
+       "///////////////////////////////////////\n"
+       "typedef float4 Quaternion;\n"
+       "__inline\n"
+       "       Quaternion qtMul(Quaternion a, Quaternion b);\n"
+       "__inline\n"
+       "       Quaternion qtNormalize(Quaternion in);\n"
+       "__inline\n"
+       "       Quaternion qtInvert(Quaternion q);\n"
+       "__inline\n"
+       "       float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = (float4)(a.xyz,0.f);\n"
+       "       float4 b1 = (float4)(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "       Quaternion qtMul(Quaternion a, Quaternion b)\n"
+       "{\n"
+       "       Quaternion ans;\n"
+       "       ans = cross( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "       //      ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "       Quaternion qtNormalize(Quaternion in)\n"
+       "{\n"
+       "       return fast_normalize(in);\n"
+       "       //      in /= length( in );\n"
+       "       //      return in;\n"
+       "}\n"
+       "__inline\n"
+       "       float4 qtRotate(Quaternion q, float4 vec)\n"
+       "{\n"
+       "       Quaternion qInv = qtInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = qtMul(q,vcpy);\n"
+       "       out = qtMul(out,qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "       Quaternion qtInvert(Quaternion q)\n"
+       "{\n"
+       "       return (Quaternion)(-q.xyz, q.w);\n"
+       "}\n"
+       "__inline\n"
+       "       float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+       "{\n"
+       "       return qtRotate( qtInvert( q ), vec );\n"
+       "}\n"
+       "void   trInverse(float4 translationIn, Quaternion orientationIn,\n"
+       "       float4* translationOut, Quaternion* orientationOut)\n"
+       "{\n"
+       "       *orientationOut = qtInvert(orientationIn);\n"
+       "       *translationOut = qtRotate(*orientationOut, -translationIn);\n"
+       "}\n"
+       "bool rayConvex(float4 rayFromLocal, float4 rayToLocal, int numFaces, int faceOffset,\n"
+       "       __global const b3GpuFace* faces, float* hitFraction, float4* hitNormal)\n"
+       "{\n"
+       "       rayFromLocal.w = 0.f;\n"
+       "       rayToLocal.w = 0.f;\n"
+       "       bool result = true;\n"
+       "       float exitFraction = hitFraction[0];\n"
+       "       float enterFraction = -0.3f;\n"
+       "       float4 curHitNormal = (float4)(0,0,0,0);\n"
+       "       for (int i=0;i<numFaces && result;i++)\n"
+       "       {\n"
+       "               b3GpuFace face = faces[faceOffset+i];\n"
+       "               float fromPlaneDist = dot(rayFromLocal,face.m_plane)+face.m_plane.w;\n"
+       "               float toPlaneDist = dot(rayToLocal,face.m_plane)+face.m_plane.w;\n"
+       "               if (fromPlaneDist<0.f)\n"
+       "               {\n"
+       "                       if (toPlaneDist >= 0.f)\n"
+       "                       {\n"
+       "                               float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);\n"
+       "                               if (exitFraction>fraction)\n"
+       "                               {\n"
+       "                                       exitFraction = fraction;\n"
+       "                               }\n"
+       "                       }                       \n"
+       "               } else\n"
+       "               {\n"
+       "                       if (toPlaneDist<0.f)\n"
+       "                       {\n"
+       "                               float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);\n"
+       "                               if (enterFraction <= fraction)\n"
+       "                               {\n"
+       "                                       enterFraction = fraction;\n"
+       "                                       curHitNormal = face.m_plane;\n"
+       "                                       curHitNormal.w = 0.f;\n"
+       "                               }\n"
+       "                       } else\n"
+       "                       {\n"
+       "                               result = false;\n"
+       "                       }\n"
+       "               }\n"
+       "               if (exitFraction <= enterFraction)\n"
+       "                       result = false;\n"
+       "       }\n"
+       "       if (enterFraction < 0.f)\n"
+       "       {\n"
+       "               result = false;\n"
+       "       }\n"
+       "       if (result)\n"
+       "       {       \n"
+       "               hitFraction[0] = enterFraction;\n"
+       "               hitNormal[0] = curHitNormal;\n"
+       "       }\n"
+       "       return result;\n"
+       "}\n"
+       "bool sphere_intersect(float4 spherePos,  float radius, float4 rayFrom, float4 rayTo, float* hitFraction)\n"
+       "{\n"
+       "       float4 rs = rayFrom - spherePos;\n"
+       "       rs.w = 0.f;\n"
+       "       float4 rayDir = rayTo-rayFrom;\n"
+       "       rayDir.w = 0.f;\n"
+       "       float A = dot(rayDir,rayDir);\n"
+       "       float B = dot(rs, rayDir);\n"
+       "       float C = dot(rs, rs) - (radius * radius);\n"
+       "       float D = B * B - A*C;\n"
+       "       if (D > 0.0f)\n"
+       "       {\n"
+       "               float t = (-B - sqrt(D))/A;\n"
+       "               if ( (t >= 0.0f) && (t < (*hitFraction)) )\n"
+       "               {\n"
+       "                       *hitFraction = t;\n"
+       "                       return true;\n"
+       "               }\n"
+       "       }\n"
+       "       return false;\n"
+       "}\n"
+       "float4 setInterpolate3(float4 from, float4 to, float t)\n"
+       "{\n"
+       "       float s = 1.0f - t;\n"
+       "       float4 result;\n"
+       "       result = s * from + t * to;\n"
+       "       result.w = 0.f; \n"
+       "       return result;  \n"
+       "}\n"
+       "__kernel void rayCastKernel(  \n"
+       "       int numRays, \n"
+       "       const __global b3RayInfo* rays, \n"
+       "       __global b3RayHit* hitResults, \n"
+       "       const int numBodies, \n"
+       "       __global Body* bodies,\n"
+       "       __global Collidable* collidables,\n"
+       "       __global const b3GpuFace* faces,\n"
+       "       __global const ConvexPolyhedronCL* convexShapes )\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numRays)\n"
+       "               return;\n"
+       "       hitResults[i].m_hitFraction = 1.f;\n"
+       "       float4 rayFrom = rays[i].m_from;\n"
+       "       float4 rayTo = rays[i].m_to;\n"
+       "       float hitFraction = 1.f;\n"
+       "       float4 hitPoint;\n"
+       "       float4 hitNormal;\n"
+       "       int hitBodyIndex= -1;\n"
+       "       int cachedCollidableIndex = -1;\n"
+       "       Collidable cachedCollidable;\n"
+       "       for (int b=0;b<numBodies;b++)\n"
+       "       {\n"
+       "               if (hitResults[i].m_hitResult2==b)\n"
+       "                       continue;\n"
+       "               Body body = bodies[b];\n"
+       "               float4 pos = body.m_pos;\n"
+       "               float4 orn = body.m_quat;\n"
+       "               if (cachedCollidableIndex != body.m_collidableIdx)\n"
+       "               {\n"
+       "                       cachedCollidableIndex = body.m_collidableIdx;\n"
+       "                       cachedCollidable = collidables[cachedCollidableIndex];\n"
+       "               }\n"
+       "               if (cachedCollidable.m_shapeType == SHAPE_CONVEX_HULL)\n"
+       "               {\n"
+       "                       float4 invPos = (float4)(0,0,0,0);\n"
+       "                       float4 invOrn = (float4)(0,0,0,0);\n"
+       "                       float4 rayFromLocal = (float4)(0,0,0,0);\n"
+       "                       float4 rayToLocal = (float4)(0,0,0,0);\n"
+       "                       invOrn = qtInvert(orn);\n"
+       "                       invPos = qtRotate(invOrn, -pos);\n"
+       "                       rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;\n"
+       "                       rayToLocal = qtRotate( invOrn, rayTo) + invPos;\n"
+       "                       rayFromLocal.w = 0.f;\n"
+       "                       rayToLocal.w = 0.f;\n"
+       "                       int numFaces = convexShapes[cachedCollidable.m_shapeIndex].m_numFaces;\n"
+       "                       int faceOffset = convexShapes[cachedCollidable.m_shapeIndex].m_faceOffset;\n"
+       "                       if (numFaces)\n"
+       "                       {\n"
+       "                               if (rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))\n"
+       "                               {\n"
+       "                                       hitBodyIndex = b;\n"
+       "                                       \n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               if (cachedCollidable.m_shapeType == SHAPE_SPHERE)\n"
+       "               {\n"
+       "                       float radius = cachedCollidable.m_radius;\n"
+       "               \n"
+       "                       if (sphere_intersect(pos,  radius, rayFrom, rayTo, &hitFraction))\n"
+       "                       {\n"
+       "                               hitBodyIndex = b;\n"
+       "                               hitNormal = (float4) (hitPoint-bodies[b].m_pos);\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       if (hitBodyIndex>=0)\n"
+       "       {\n"
+       "               hitPoint = setInterpolate3(rayFrom, rayTo,hitFraction);\n"
+       "               hitResults[i].m_hitFraction = hitFraction;\n"
+       "               hitResults[i].m_hitPoint = hitPoint;\n"
+       "               hitResults[i].m_hitNormal = normalize(hitNormal);\n"
+       "               hitResults[i].m_hitResult0 = hitBodyIndex;\n"
+       "       }\n"
+       "}\n"
+       "__kernel void findRayRigidPairIndexRanges(__global int2* rayRigidPairs, \n"
+       "                                                                                       __global int* out_firstRayRigidPairIndexPerRay,\n"
+       "                                                                                       __global int* out_numRayRigidPairsPerRay,\n"
+       "                                                                                       int numRayRigidPairs)\n"
+       "{\n"
+       "       int rayRigidPairIndex = get_global_id(0);\n"
+       "       if (rayRigidPairIndex >= numRayRigidPairs) return;\n"
+       "       \n"
+       "       int rayIndex = rayRigidPairs[rayRigidPairIndex].x;\n"
+       "       \n"
+       "       atomic_min(&out_firstRayRigidPairIndexPerRay[rayIndex], rayRigidPairIndex);\n"
+       "       atomic_inc(&out_numRayRigidPairsPerRay[rayIndex]);\n"
+       "}\n"
+       "__kernel void rayCastPairsKernel(const __global b3RayInfo* rays, \n"
+       "                                                               __global b3RayHit* hitResults, \n"
+       "                                                               __global int* firstRayRigidPairIndexPerRay,\n"
+       "                                                               __global int* numRayRigidPairsPerRay,\n"
+       "                                                                       \n"
+       "                                                               __global Body* bodies,\n"
+       "                                                               __global Collidable* collidables,\n"
+       "                                                               __global const b3GpuFace* faces,\n"
+       "                                                               __global const ConvexPolyhedronCL* convexShapes,\n"
+       "                                                               \n"
+       "                                                               __global int2* rayRigidPairs,\n"
+       "                                                               int numRays)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i >= numRays) return;\n"
+       "       \n"
+       "       float4 rayFrom = rays[i].m_from;\n"
+       "       float4 rayTo = rays[i].m_to;\n"
+       "               \n"
+       "       hitResults[i].m_hitFraction = 1.f;\n"
+       "               \n"
+       "       float hitFraction = 1.f;\n"
+       "       float4 hitPoint;\n"
+       "       float4 hitNormal;\n"
+       "       int hitBodyIndex = -1;\n"
+       "               \n"
+       "       //\n"
+       "       for(int pair = 0; pair < numRayRigidPairsPerRay[i]; ++pair)\n"
+       "       {\n"
+       "               int rayRigidPairIndex = pair + firstRayRigidPairIndexPerRay[i];\n"
+       "               int b = rayRigidPairs[rayRigidPairIndex].y;\n"
+       "               \n"
+       "               if (hitResults[i].m_hitResult2 == b) continue;\n"
+       "               \n"
+       "               Body body = bodies[b];\n"
+       "               Collidable rigidCollidable = collidables[body.m_collidableIdx];\n"
+       "               \n"
+       "               float4 pos = body.m_pos;\n"
+       "               float4 orn = body.m_quat;\n"
+       "               \n"
+       "               if (rigidCollidable.m_shapeType == SHAPE_CONVEX_HULL)\n"
+       "               {\n"
+       "                       float4 invPos = (float4)(0,0,0,0);\n"
+       "                       float4 invOrn = (float4)(0,0,0,0);\n"
+       "                       float4 rayFromLocal = (float4)(0,0,0,0);\n"
+       "                       float4 rayToLocal = (float4)(0,0,0,0);\n"
+       "                       invOrn = qtInvert(orn);\n"
+       "                       invPos = qtRotate(invOrn, -pos);\n"
+       "                       rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;\n"
+       "                       rayToLocal = qtRotate( invOrn, rayTo) + invPos;\n"
+       "                       rayFromLocal.w = 0.f;\n"
+       "                       rayToLocal.w = 0.f;\n"
+       "                       int numFaces = convexShapes[rigidCollidable.m_shapeIndex].m_numFaces;\n"
+       "                       int faceOffset = convexShapes[rigidCollidable.m_shapeIndex].m_faceOffset;\n"
+       "                       \n"
+       "                       if (numFaces && rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))\n"
+       "                       {\n"
+       "                               hitBodyIndex = b;\n"
+       "                               hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "               if (rigidCollidable.m_shapeType == SHAPE_SPHERE)\n"
+       "               {\n"
+       "                       float radius = rigidCollidable.m_radius;\n"
+       "               \n"
+       "                       if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))\n"
+       "                       {\n"
+       "                               hitBodyIndex = b;\n"
+       "                               hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);\n"
+       "                               hitNormal = (float4) (hitPoint - bodies[b].m_pos);\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "       \n"
+       "       if (hitBodyIndex >= 0)\n"
+       "       {\n"
+       "               hitResults[i].m_hitFraction = hitFraction;\n"
+       "               hitResults[i].m_hitPoint = hitPoint;\n"
+       "               hitResults[i].m_hitNormal = normalize(hitNormal);\n"
+       "               hitResults[i].m_hitResult0 = hitBodyIndex;\n"
+       "       }\n"
+       "       \n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h
new file mode 100644 (file)
index 0000000..89c0142
--- /dev/null
@@ -0,0 +1,17 @@
+
+#ifndef B3_CONSTRAINT4_h
+#define B3_CONSTRAINT4_h
+#include "Bullet3Common/b3Vector3.h"
+
+#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
+
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3GpuConstraint4 : public b3ContactConstraint4
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       inline void setFrictionCoeff(float value) { m_linear[3] = value; }
+       inline float getFrictionCoeff() const { return m_linear[3]; }
+};
+
+#endif  //B3_CONSTRAINT4_h
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp
new file mode 100644 (file)
index 0000000..a271090
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#include "b3GpuGenericConstraint.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include <new>
+#include "Bullet3Common/b3Transform.h"
+
+void b3GpuGenericConstraint::getInfo1(unsigned int* info, const b3RigidBodyData* bodies)
+{
+       switch (m_constraintType)
+       {
+               case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
+               {
+                       *info = 3;
+                       break;
+               };
+               default:
+               {
+                       b3Assert(0);
+               }
+       };
+}
+
+void getInfo2Point2Point(b3GpuGenericConstraint* constraint, b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies)
+{
+       b3Transform trA;
+       trA.setIdentity();
+       trA.setOrigin(bodies[constraint->m_rbA].m_pos);
+       trA.setRotation(bodies[constraint->m_rbA].m_quat);
+
+       b3Transform trB;
+       trB.setIdentity();
+       trB.setOrigin(bodies[constraint->m_rbB].m_pos);
+       trB.setRotation(bodies[constraint->m_rbB].m_quat);
+
+       // anchor points in global coordinates with respect to body PORs.
+
+       // set jacobian
+       info->m_J1linearAxis[0] = 1;
+       info->m_J1linearAxis[info->rowskip + 1] = 1;
+       info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
+
+       b3Vector3 a1 = trA.getBasis() * constraint->getPivotInA();
+       //b3Vector3 a1a = b3QuatRotate(trA.getRotation(),constraint->getPivotInA());
+
+       {
+               b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
+               b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis + info->rowskip);
+               b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis + 2 * info->rowskip);
+               b3Vector3 a1neg = -a1;
+               a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+
+       if (info->m_J2linearAxis)
+       {
+               info->m_J2linearAxis[0] = -1;
+               info->m_J2linearAxis[info->rowskip + 1] = -1;
+               info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
+       }
+
+       b3Vector3 a2 = trB.getBasis() * constraint->getPivotInB();
+
+       {
+               //      b3Vector3 a2n = -a2;
+               b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
+               b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis + info->rowskip);
+               b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis + 2 * info->rowskip);
+               a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+
+       // set right hand side
+       //      b3Scalar currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
+       b3Scalar currERP = info->erp;
+
+       b3Scalar k = info->fps * currERP;
+       int j;
+       for (j = 0; j < 3; j++)
+       {
+               info->m_constraintError[j * info->rowskip] = k * (a2[j] + trB.getOrigin()[j] - a1[j] - trA.getOrigin()[j]);
+               //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
+       }
+#if 0
+       if(m_flags & B3_P2P_FLAGS_CFM)
+       {
+               for (j=0; j<3; j++)
+               {
+                       info->cfm[j*info->rowskip] = m_cfm;
+               }
+       }
+#endif
+
+#if 0
+       b3Scalar impulseClamp = m_setting.m_impulseClamp;//
+       for (j=0; j<3; j++)
+    {
+               if (m_setting.m_impulseClamp > 0)
+               {
+                       info->m_lowerLimit[j*info->rowskip] = -impulseClamp;
+                       info->m_upperLimit[j*info->rowskip] = impulseClamp;
+               }
+       }
+       info->m_damping = m_setting.m_damping;
+#endif
+}
+
+void b3GpuGenericConstraint::getInfo2(b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies)
+{
+       switch (m_constraintType)
+       {
+               case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
+               {
+                       getInfo2Point2Point(this, info, bodies);
+                       break;
+               };
+               default:
+               {
+                       b3Assert(0);
+               }
+       };
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h
new file mode 100644 (file)
index 0000000..1f163ba
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_GPU_GENERIC_CONSTRAINT_H
+#define B3_GPU_GENERIC_CONSTRAINT_H
+
+#include "Bullet3Common/b3Quaternion.h"
+struct b3RigidBodyData;
+enum B3_CONSTRAINT_FLAGS
+{
+       B3_CONSTRAINT_FLAG_ENABLED = 1,
+};
+
+enum b3GpuGenericConstraintType
+{
+       B3_GPU_POINT2POINT_CONSTRAINT_TYPE = 3,
+       B3_GPU_FIXED_CONSTRAINT_TYPE = 4,
+       //      B3_HINGE_CONSTRAINT_TYPE,
+       //      B3_CONETWIST_CONSTRAINT_TYPE,
+       //      B3_D6_CONSTRAINT_TYPE,
+       //      B3_SLIDER_CONSTRAINT_TYPE,
+       //      B3_CONTACT_CONSTRAINT_TYPE,
+       //      B3_D6_SPRING_CONSTRAINT_TYPE,
+       //      B3_GEAR_CONSTRAINT_TYPE,
+
+       B3_GPU_MAX_CONSTRAINT_TYPE
+};
+
+struct b3GpuConstraintInfo2
+{
+       // integrator parameters: frames per second (1/stepsize), default error
+       // reduction parameter (0..1).
+       b3Scalar fps, erp;
+
+       // for the first and second body, pointers to two (linear and angular)
+       // n*3 jacobian sub matrices, stored by rows. these matrices will have
+       // been initialized to 0 on entry. if the second body is zero then the
+       // J2xx pointers may be 0.
+       b3Scalar *m_J1linearAxis, *m_J1angularAxis, *m_J2linearAxis, *m_J2angularAxis;
+
+       // elements to jump from one row to the next in J's
+       int rowskip;
+
+       // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+       // "constraint force mixing" vector. c is set to zero on entry, cfm is
+       // set to a constant value (typically very small or zero) value on entry.
+       b3Scalar *m_constraintError, *cfm;
+
+       // lo and hi limits for variables (set to -/+ infinity on entry).
+       b3Scalar *m_lowerLimit, *m_upperLimit;
+
+       // findex vector for variables. see the LCP solver interface for a
+       // description of what this does. this is set to -1 on entry.
+       // note that the returned indexes are relative to the first index of
+       // the constraint.
+       int* findex;
+       // number of solver iterations
+       int m_numIterations;
+
+       //damping of the velocity
+       b3Scalar m_damping;
+};
+
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3GpuGenericConstraint
+{
+       int m_constraintType;
+       int m_rbA;
+       int m_rbB;
+       float m_breakingImpulseThreshold;
+
+       b3Vector3 m_pivotInA;
+       b3Vector3 m_pivotInB;
+       b3Quaternion m_relTargetAB;
+
+       int m_flags;
+       int m_uid;
+       int m_padding[2];
+
+       int getRigidBodyA() const
+       {
+               return m_rbA;
+       }
+       int getRigidBodyB() const
+       {
+               return m_rbB;
+       }
+
+       const b3Vector3& getPivotInA() const
+       {
+               return m_pivotInA;
+       }
+
+       const b3Vector3& getPivotInB() const
+       {
+               return m_pivotInB;
+       }
+
+       int isEnabled() const
+       {
+               return m_flags & B3_CONSTRAINT_FLAG_ENABLED;
+       }
+
+       float getBreakingImpulseThreshold() const
+       {
+               return m_breakingImpulseThreshold;
+       }
+
+       ///internal method used by the constraint solver, don't use them directly
+       void getInfo1(unsigned int* info, const b3RigidBodyData* bodies);
+
+       ///internal method used by the constraint solver, don't use them directly
+       void getInfo2(b3GpuConstraintInfo2 * info, const b3RigidBodyData* bodies);
+};
+
+#endif  //B3_GPU_GENERIC_CONSTRAINT_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp
new file mode 100644 (file)
index 0000000..089fb1f
--- /dev/null
@@ -0,0 +1,1305 @@
+
+#include "b3GpuJacobiContactSolver.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h"  //b3Int2
+class b3Vector3;
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3OpenCL/RigidBody/kernels/solverUtils.h"
+#include "Bullet3Common/b3Logging.h"
+#include "b3GpuConstraint4.h"
+#include "Bullet3Common/shared/b3Int2.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#define SOLVER_UTILS_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl"
+
+struct b3GpuJacobiSolverInternalData
+{
+       //btRadixSort32CL*      m_sort32;
+       //btBoundSearchCL*      m_search;
+       b3PrefixScanCL* m_scan;
+
+       b3OpenCLArray<unsigned int>* m_bodyCount;
+       b3OpenCLArray<b3Int2>* m_contactConstraintOffsets;
+       b3OpenCLArray<unsigned int>* m_offsetSplitBodies;
+
+       b3OpenCLArray<b3Vector3>* m_deltaLinearVelocities;
+       b3OpenCLArray<b3Vector3>* m_deltaAngularVelocities;
+
+       b3AlignedObjectArray<b3Vector3> m_deltaLinearVelocitiesCPU;
+       b3AlignedObjectArray<b3Vector3> m_deltaAngularVelocitiesCPU;
+
+       b3OpenCLArray<b3GpuConstraint4>* m_contactConstraints;
+
+       b3FillCL* m_filler;
+
+       cl_kernel m_countBodiesKernel;
+       cl_kernel m_contactToConstraintSplitKernel;
+       cl_kernel m_clearVelocitiesKernel;
+       cl_kernel m_averageVelocitiesKernel;
+       cl_kernel m_updateBodyVelocitiesKernel;
+       cl_kernel m_solveContactKernel;
+       cl_kernel m_solveFrictionKernel;
+};
+
+b3GpuJacobiContactSolver::b3GpuJacobiContactSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity)
+       : m_context(ctx),
+         m_device(device),
+         m_queue(queue)
+{
+       m_data = new b3GpuJacobiSolverInternalData;
+       m_data->m_scan = new b3PrefixScanCL(m_context, m_device, m_queue);
+       m_data->m_bodyCount = new b3OpenCLArray<unsigned int>(m_context, m_queue);
+       m_data->m_filler = new b3FillCL(m_context, m_device, m_queue);
+       m_data->m_contactConstraintOffsets = new b3OpenCLArray<b3Int2>(m_context, m_queue);
+       m_data->m_offsetSplitBodies = new b3OpenCLArray<unsigned int>(m_context, m_queue);
+       m_data->m_contactConstraints = new b3OpenCLArray<b3GpuConstraint4>(m_context, m_queue);
+       m_data->m_deltaLinearVelocities = new b3OpenCLArray<b3Vector3>(m_context, m_queue);
+       m_data->m_deltaAngularVelocities = new b3OpenCLArray<b3Vector3>(m_context, m_queue);
+
+       cl_int pErrNum;
+       const char* additionalMacros = "";
+       const char* solverUtilsSource = solverUtilsCL;
+       {
+               cl_program solverUtilsProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverUtilsSource, &pErrNum, additionalMacros, SOLVER_UTILS_KERNEL_PATH);
+               b3Assert(solverUtilsProg);
+               m_data->m_countBodiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "CountBodiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
+               b3Assert(m_data->m_countBodiesKernel);
+
+               m_data->m_contactToConstraintSplitKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "ContactToConstraintSplitKernel", &pErrNum, solverUtilsProg, additionalMacros);
+               b3Assert(m_data->m_contactToConstraintSplitKernel);
+               m_data->m_clearVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "ClearVelocitiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
+               b3Assert(m_data->m_clearVelocitiesKernel);
+
+               m_data->m_averageVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "AverageVelocitiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
+               b3Assert(m_data->m_averageVelocitiesKernel);
+
+               m_data->m_updateBodyVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "UpdateBodyVelocitiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
+               b3Assert(m_data->m_updateBodyVelocitiesKernel);
+
+               m_data->m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "SolveContactJacobiKernel", &pErrNum, solverUtilsProg, additionalMacros);
+               b3Assert(m_data->m_solveContactKernel);
+
+               m_data->m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "SolveFrictionJacobiKernel", &pErrNum, solverUtilsProg, additionalMacros);
+               b3Assert(m_data->m_solveFrictionKernel);
+       }
+}
+
+b3GpuJacobiContactSolver::~b3GpuJacobiContactSolver()
+{
+       clReleaseKernel(m_data->m_solveContactKernel);
+       clReleaseKernel(m_data->m_solveFrictionKernel);
+       clReleaseKernel(m_data->m_countBodiesKernel);
+       clReleaseKernel(m_data->m_contactToConstraintSplitKernel);
+       clReleaseKernel(m_data->m_averageVelocitiesKernel);
+       clReleaseKernel(m_data->m_updateBodyVelocitiesKernel);
+       clReleaseKernel(m_data->m_clearVelocitiesKernel);
+
+       delete m_data->m_deltaLinearVelocities;
+       delete m_data->m_deltaAngularVelocities;
+       delete m_data->m_contactConstraints;
+       delete m_data->m_offsetSplitBodies;
+       delete m_data->m_contactConstraintOffsets;
+       delete m_data->m_bodyCount;
+       delete m_data->m_filler;
+       delete m_data->m_scan;
+       delete m_data;
+}
+
+b3Vector3 make_float4(float v)
+{
+       return b3MakeVector3(v, v, v);
+}
+
+b3Vector4 make_float4(float x, float y, float z, float w)
+{
+       return b3MakeVector4(x, y, z, w);
+}
+
+static inline float calcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
+                                                          const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
+{
+       return b3Dot(l0, linVel0) + b3Dot(a0, angVel0) + b3Dot(l1, linVel1) + b3Dot(a1, angVel1);
+}
+
+static inline void setLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
+                                                                          b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
+{
+       linear = n;
+       angular0 = b3Cross(r0, n);
+       angular1 = -b3Cross(r1, n);
+}
+
+static __inline void solveContact(b3GpuConstraint4& cs,
+                                                                 const b3Vector3& posA, const b3Vector3& linVelARO, const b3Vector3& angVelARO, float invMassA, const b3Matrix3x3& invInertiaA,
+                                                                 const b3Vector3& posB, const b3Vector3& linVelBRO, const b3Vector3& angVelBRO, float invMassB, const b3Matrix3x3& invInertiaB,
+                                                                 float maxRambdaDt[4], float minRambdaDt[4], b3Vector3& dLinVelA, b3Vector3& dAngVelA, b3Vector3& dLinVelB, b3Vector3& dAngVelB)
+{
+       for (int ic = 0; ic < 4; ic++)
+       {
+               //      dont necessary because this makes change to 0
+               if (cs.m_jacCoeffInv[ic] == 0.f) continue;
+
+               {
+                       b3Vector3 angular0, angular1, linear;
+                       b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
+                       b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
+                       setLinearAndAngular((const b3Vector3&)cs.m_linear, (const b3Vector3&)r0, (const b3Vector3&)r1, linear, angular0, angular1);
+
+                       float rambdaDt = calcRelVel((const b3Vector3&)cs.m_linear, (const b3Vector3&)-cs.m_linear, angular0, angular1,
+                                                                               linVelARO + dLinVelA, angVelARO + dAngVelA, linVelBRO + dLinVelB, angVelBRO + dAngVelB) +
+                                                        cs.m_b[ic];
+                       rambdaDt *= cs.m_jacCoeffInv[ic];
+
+                       {
+                               float prevSum = cs.m_appliedRambdaDt[ic];
+                               float updated = prevSum;
+                               updated += rambdaDt;
+                               updated = b3Max(updated, minRambdaDt[ic]);
+                               updated = b3Min(updated, maxRambdaDt[ic]);
+                               rambdaDt = updated - prevSum;
+                               cs.m_appliedRambdaDt[ic] = updated;
+                       }
+
+                       b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+                       b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+                       b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+                       b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
+#ifdef _WIN32
+                       b3Assert(_finite(linImp0.getX()));
+                       b3Assert(_finite(linImp1.getX()));
+#endif
+
+                       if (invMassA)
+                       {
+                               dLinVelA += linImp0;
+                               dAngVelA += angImp0;
+                       }
+                       if (invMassB)
+                       {
+                               dLinVelB += linImp1;
+                               dAngVelB += angImp1;
+                       }
+               }
+       }
+}
+
+void solveContact3(b3GpuConstraint4* cs,
+                                  b3Vector3* posAPtr, b3Vector3* linVelA, b3Vector3* angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+                                  b3Vector3* posBPtr, b3Vector3* linVelB, b3Vector3* angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+                                  b3Vector3* dLinVelA, b3Vector3* dAngVelA, b3Vector3* dLinVelB, b3Vector3* dAngVelB)
+{
+       float minRambdaDt = 0;
+       float maxRambdaDt = FLT_MAX;
+
+       for (int ic = 0; ic < 4; ic++)
+       {
+               if (cs->m_jacCoeffInv[ic] == 0.f) continue;
+
+               b3Vector3 angular0, angular1, linear;
+               b3Vector3 r0 = cs->m_worldPos[ic] - *posAPtr;
+               b3Vector3 r1 = cs->m_worldPos[ic] - *posBPtr;
+               setLinearAndAngular(cs->m_linear, r0, r1, linear, angular0, angular1);
+
+               float rambdaDt = calcRelVel(cs->m_linear, -cs->m_linear, angular0, angular1,
+                                                                       *linVelA + *dLinVelA, *angVelA + *dAngVelA, *linVelB + *dLinVelB, *angVelB + *dAngVelB) +
+                                                cs->m_b[ic];
+               rambdaDt *= cs->m_jacCoeffInv[ic];
+
+               {
+                       float prevSum = cs->m_appliedRambdaDt[ic];
+                       float updated = prevSum;
+                       updated += rambdaDt;
+                       updated = b3Max(updated, minRambdaDt);
+                       updated = b3Min(updated, maxRambdaDt);
+                       rambdaDt = updated - prevSum;
+                       cs->m_appliedRambdaDt[ic] = updated;
+               }
+
+               b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+               b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+               b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+               b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
+
+               if (invMassA)
+               {
+                       *dLinVelA += linImp0;
+                       *dAngVelA += angImp0;
+               }
+               if (invMassB)
+               {
+                       *dLinVelB += linImp1;
+                       *dAngVelB += angImp1;
+               }
+       }
+}
+
+static inline void solveFriction(b3GpuConstraint4& cs,
+                                                                const b3Vector3& posA, const b3Vector3& linVelARO, const b3Vector3& angVelARO, float invMassA, const b3Matrix3x3& invInertiaA,
+                                                                const b3Vector3& posB, const b3Vector3& linVelBRO, const b3Vector3& angVelBRO, float invMassB, const b3Matrix3x3& invInertiaB,
+                                                                float maxRambdaDt[4], float minRambdaDt[4], b3Vector3& dLinVelA, b3Vector3& dAngVelA, b3Vector3& dLinVelB, b3Vector3& dAngVelB)
+{
+       b3Vector3 linVelA = linVelARO + dLinVelA;
+       b3Vector3 linVelB = linVelBRO + dLinVelB;
+       b3Vector3 angVelA = angVelARO + dAngVelA;
+       b3Vector3 angVelB = angVelBRO + dAngVelB;
+
+       if (cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0) return;
+       const b3Vector3& center = (const b3Vector3&)cs.m_center;
+
+       b3Vector3 n = -(const b3Vector3&)cs.m_linear;
+
+       b3Vector3 tangent[2];
+#if 1
+       b3PlaneSpace1(n, tangent[0], tangent[1]);
+#else
+       b3Vector3 r = cs.m_worldPos[0] - center;
+       tangent[0] = cross3(n, r);
+       tangent[1] = cross3(tangent[0], n);
+       tangent[0] = normalize3(tangent[0]);
+       tangent[1] = normalize3(tangent[1]);
+#endif
+
+       b3Vector3 angular0, angular1, linear;
+       b3Vector3 r0 = center - posA;
+       b3Vector3 r1 = center - posB;
+       for (int i = 0; i < 2; i++)
+       {
+               setLinearAndAngular(tangent[i], r0, r1, linear, angular0, angular1);
+               float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
+                                                                       linVelA, angVelA, linVelB, angVelB);
+               rambdaDt *= cs.m_fJacCoeffInv[i];
+
+               {
+                       float prevSum = cs.m_fAppliedRambdaDt[i];
+                       float updated = prevSum;
+                       updated += rambdaDt;
+                       updated = b3Max(updated, minRambdaDt[i]);
+                       updated = b3Min(updated, maxRambdaDt[i]);
+                       rambdaDt = updated - prevSum;
+                       cs.m_fAppliedRambdaDt[i] = updated;
+               }
+
+               b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+               b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+               b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+               b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
+#ifdef _WIN32
+               b3Assert(_finite(linImp0.getX()));
+               b3Assert(_finite(linImp1.getX()));
+#endif
+               if (invMassA)
+               {
+                       dLinVelA += linImp0;
+                       dAngVelA += angImp0;
+               }
+               if (invMassB)
+               {
+                       dLinVelB += linImp1;
+                       dAngVelB += angImp1;
+               }
+       }
+
+       {  //   angular damping for point constraint
+               b3Vector3 ab = (posB - posA).normalized();
+               b3Vector3 ac = (center - posA).normalized();
+               if (b3Dot(ab, ac) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+               {
+                       float angNA = b3Dot(n, angVelA);
+                       float angNB = b3Dot(n, angVelB);
+
+                       if (invMassA)
+                               dAngVelA -= (angNA * 0.1f) * n;
+                       if (invMassB)
+                               dAngVelB -= (angNB * 0.1f) * n;
+               }
+       }
+}
+
+float calcJacCoeff(const b3Vector3& linear0, const b3Vector3& linear1, const b3Vector3& angular0, const b3Vector3& angular1,
+                                  float invMass0, const b3Matrix3x3* invInertia0, float invMass1, const b3Matrix3x3* invInertia1, float countA, float countB)
+{
+       //      linear0,1 are normlized
+       float jmj0 = invMass0;  //dot3F4(linear0, linear0)*invMass0;
+
+       float jmj1 = b3Dot(mtMul3(angular0, *invInertia0), angular0);
+       float jmj2 = invMass1;  //dot3F4(linear1, linear1)*invMass1;
+       float jmj3 = b3Dot(mtMul3(angular1, *invInertia1), angular1);
+       return -1.f / ((jmj0 + jmj1) * countA + (jmj2 + jmj3) * countB);
+       //      return -1.f/((jmj0+jmj1)+(jmj2+jmj3));
+}
+
+void setConstraint4(const b3Vector3& posA, const b3Vector3& linVelA, const b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+                                       const b3Vector3& posB, const b3Vector3& linVelB, const b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+                                       b3Contact4* src, float dt, float positionDrift, float positionConstraintCoeff, float countA, float countB,
+                                       b3GpuConstraint4* dstC)
+{
+       dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
+       dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
+
+       float dtInv = 1.f / dt;
+       for (int ic = 0; ic < 4; ic++)
+       {
+               dstC->m_appliedRambdaDt[ic] = 0.f;
+       }
+       dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
+
+       dstC->m_linear = src->m_worldNormalOnB;
+       dstC->m_linear[3] = 0.7f;  //src->getFrictionCoeff() );
+       for (int ic = 0; ic < 4; ic++)
+       {
+               b3Vector3 r0 = src->m_worldPosB[ic] - posA;
+               b3Vector3 r1 = src->m_worldPosB[ic] - posB;
+
+               if (ic >= src->m_worldNormalOnB[3])  //npoints
+               {
+                       dstC->m_jacCoeffInv[ic] = 0.f;
+                       continue;
+               }
+
+               float relVelN;
+               {
+                       b3Vector3 linear, angular0, angular1;
+                       setLinearAndAngular(src->m_worldNormalOnB, r0, r1, linear, angular0, angular1);
+
+                       dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
+                                                                                                  invMassA, &invInertiaA, invMassB, &invInertiaB, countA, countB);
+
+                       relVelN = calcRelVel(linear, -linear, angular0, angular1,
+                                                                linVelA, angVelA, linVelB, angVelB);
+
+                       float e = 0.f;  //src->getRestituitionCoeff();
+                       if (relVelN * relVelN < 0.004f)
+                       {
+                               e = 0.f;
+                       }
+
+                       dstC->m_b[ic] = e * relVelN;
+                       //float penetration = src->m_worldPos[ic].w;
+                       dstC->m_b[ic] += (src->m_worldPosB[ic][3] + positionDrift) * positionConstraintCoeff * dtInv;
+                       dstC->m_appliedRambdaDt[ic] = 0.f;
+               }
+       }
+
+       if (src->m_worldNormalOnB[3] > 0)  //npoints
+       {                                  //   prepare friction
+               b3Vector3 center = make_float4(0.f);
+               for (int i = 0; i < src->m_worldNormalOnB[3]; i++)
+                       center += src->m_worldPosB[i];
+               center /= (float)src->m_worldNormalOnB[3];
+
+               b3Vector3 tangent[2];
+               b3PlaneSpace1(src->m_worldNormalOnB, tangent[0], tangent[1]);
+
+               b3Vector3 r[2];
+               r[0] = center - posA;
+               r[1] = center - posB;
+
+               for (int i = 0; i < 2; i++)
+               {
+                       b3Vector3 linear, angular0, angular1;
+                       setLinearAndAngular(tangent[i], r[0], r[1], linear, angular0, angular1);
+
+                       dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
+                                                                                                  invMassA, &invInertiaA, invMassB, &invInertiaB, countA, countB);
+                       dstC->m_fAppliedRambdaDt[i] = 0.f;
+               }
+               dstC->m_center = center;
+       }
+
+       for (int i = 0; i < 4; i++)
+       {
+               if (i < src->m_worldNormalOnB[3])
+               {
+                       dstC->m_worldPos[i] = src->m_worldPosB[i];
+               }
+               else
+               {
+                       dstC->m_worldPos[i] = make_float4(0.f);
+               }
+       }
+}
+
+void ContactToConstraintKernel(b3Contact4* gContact, b3RigidBodyData* gBodies, b3InertiaData* gShapes, b3GpuConstraint4* gConstraintOut, int nContacts,
+                                                          float dt,
+                                                          float positionDrift,
+                                                          float positionConstraintCoeff, int gIdx, b3AlignedObjectArray<unsigned int>& bodyCount)
+{
+       //int gIdx = 0;//GET_GLOBAL_IDX;
+
+       if (gIdx < nContacts)
+       {
+               int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
+               int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
+
+               b3Vector3 posA = gBodies[aIdx].m_pos;
+               b3Vector3 linVelA = gBodies[aIdx].m_linVel;
+               b3Vector3 angVelA = gBodies[aIdx].m_angVel;
+               float invMassA = gBodies[aIdx].m_invMass;
+               b3Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertiaWorld;  //.m_invInertia;
+
+               b3Vector3 posB = gBodies[bIdx].m_pos;
+               b3Vector3 linVelB = gBodies[bIdx].m_linVel;
+               b3Vector3 angVelB = gBodies[bIdx].m_angVel;
+               float invMassB = gBodies[bIdx].m_invMass;
+               b3Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertiaWorld;  //m_invInertia;
+
+               b3GpuConstraint4 cs;
+               float countA = invMassA ? (float)(bodyCount[aIdx]) : 1;
+               float countB = invMassB ? (float)(bodyCount[bIdx]) : 1;
+               setConstraint4(posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
+                                          &gContact[gIdx], dt, positionDrift, positionConstraintCoeff, countA, countB,
+                                          &cs);
+
+               cs.m_batchIdx = gContact[gIdx].m_batchIdx;
+
+               gConstraintOut[gIdx] = cs;
+       }
+}
+
+void b3GpuJacobiContactSolver::solveGroupHost(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, const b3JacobiSolverInfo& solverInfo)
+{
+       B3_PROFILE("b3GpuJacobiContactSolver::solveGroup");
+
+       b3AlignedObjectArray<unsigned int> bodyCount;
+       bodyCount.resize(numBodies);
+       for (int i = 0; i < numBodies; i++)
+               bodyCount[i] = 0;
+
+       b3AlignedObjectArray<b3Int2> contactConstraintOffsets;
+       contactConstraintOffsets.resize(numManifolds);
+
+       for (int i = 0; i < numManifolds; i++)
+       {
+               int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;
+               int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;
+
+               bool isFixedA = (pa < 0) || (pa == solverInfo.m_fixedBodyIndex);
+               bool isFixedB = (pb < 0) || (pb == solverInfo.m_fixedBodyIndex);
+
+               int bodyIndexA = manifoldPtr[i].getBodyA();
+               int bodyIndexB = manifoldPtr[i].getBodyB();
+
+               if (!isFixedA)
+               {
+                       contactConstraintOffsets[i].x = bodyCount[bodyIndexA];
+                       bodyCount[bodyIndexA]++;
+               }
+               if (!isFixedB)
+               {
+                       contactConstraintOffsets[i].y = bodyCount[bodyIndexB];
+                       bodyCount[bodyIndexB]++;
+               }
+       }
+
+       b3AlignedObjectArray<unsigned int> offsetSplitBodies;
+       offsetSplitBodies.resize(numBodies);
+       unsigned int totalNumSplitBodies;
+       m_data->m_scan->executeHost(bodyCount, offsetSplitBodies, numBodies, &totalNumSplitBodies);
+       int numlastBody = bodyCount[numBodies - 1];
+       totalNumSplitBodies += numlastBody;
+       printf("totalNumSplitBodies = %d\n", totalNumSplitBodies);
+
+       b3AlignedObjectArray<b3GpuConstraint4> contactConstraints;
+       contactConstraints.resize(numManifolds);
+
+       for (int i = 0; i < numManifolds; i++)
+       {
+               ContactToConstraintKernel(&manifoldPtr[0], bodies, inertias, &contactConstraints[0], numManifolds,
+                                                                 solverInfo.m_deltaTime,
+                                                                 solverInfo.m_positionDrift,
+                                                                 solverInfo.m_positionConstraintCoeff,
+                                                                 i, bodyCount);
+       }
+       int maxIter = solverInfo.m_numIterations;
+
+       b3AlignedObjectArray<b3Vector3> deltaLinearVelocities;
+       b3AlignedObjectArray<b3Vector3> deltaAngularVelocities;
+       deltaLinearVelocities.resize(totalNumSplitBodies);
+       deltaAngularVelocities.resize(totalNumSplitBodies);
+       for (unsigned int i = 0; i < totalNumSplitBodies; i++)
+       {
+               deltaLinearVelocities[i].setZero();
+               deltaAngularVelocities[i].setZero();
+       }
+
+       for (int iter = 0; iter < maxIter; iter++)
+       {
+               int i = 0;
+               for (i = 0; i < numManifolds; i++)
+               {
+                       //float frictionCoeff = contactConstraints[i].getFrictionCoeff();
+                       int aIdx = (int)contactConstraints[i].m_bodyA;
+                       int bIdx = (int)contactConstraints[i].m_bodyB;
+                       b3RigidBodyData& bodyA = bodies[aIdx];
+                       b3RigidBodyData& bodyB = bodies[bIdx];
+
+                       b3Vector3 zero = b3MakeVector3(0, 0, 0);
+
+                       b3Vector3* dlvAPtr = &zero;
+                       b3Vector3* davAPtr = &zero;
+                       b3Vector3* dlvBPtr = &zero;
+                       b3Vector3* davBPtr = &zero;
+
+                       if (bodyA.m_invMass)
+                       {
+                               int bodyOffsetA = offsetSplitBodies[aIdx];
+                               int constraintOffsetA = contactConstraintOffsets[i].x;
+                               int splitIndexA = bodyOffsetA + constraintOffsetA;
+                               dlvAPtr = &deltaLinearVelocities[splitIndexA];
+                               davAPtr = &deltaAngularVelocities[splitIndexA];
+                       }
+
+                       if (bodyB.m_invMass)
+                       {
+                               int bodyOffsetB = offsetSplitBodies[bIdx];
+                               int constraintOffsetB = contactConstraintOffsets[i].y;
+                               int splitIndexB = bodyOffsetB + constraintOffsetB;
+                               dlvBPtr = &deltaLinearVelocities[splitIndexB];
+                               davBPtr = &deltaAngularVelocities[splitIndexB];
+                       }
+
+                       {
+                               float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+                               float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
+
+                               solveContact(contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertias[aIdx].m_invInertiaWorld,
+                                                        (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertias[bIdx].m_invInertiaWorld,
+                                                        maxRambdaDt, minRambdaDt, *dlvAPtr, *davAPtr, *dlvBPtr, *davBPtr);
+                       }
+               }
+
+               //easy
+               for (int i = 0; i < numBodies; i++)
+               {
+                       if (bodies[i].m_invMass)
+                       {
+                               int bodyOffset = offsetSplitBodies[i];
+                               int count = bodyCount[i];
+                               float factor = 1.f / float(count);
+                               b3Vector3 averageLinVel;
+                               averageLinVel.setZero();
+                               b3Vector3 averageAngVel;
+                               averageAngVel.setZero();
+                               for (int j = 0; j < count; j++)
+                               {
+                                       averageLinVel += deltaLinearVelocities[bodyOffset + j] * factor;
+                                       averageAngVel += deltaAngularVelocities[bodyOffset + j] * factor;
+                               }
+                               for (int j = 0; j < count; j++)
+                               {
+                                       deltaLinearVelocities[bodyOffset + j] = averageLinVel;
+                                       deltaAngularVelocities[bodyOffset + j] = averageAngVel;
+                               }
+                       }
+               }
+       }
+       for (int iter = 0; iter < maxIter; iter++)
+       {
+               //int i=0;
+
+               //solve friction
+
+               for (int i = 0; i < numManifolds; i++)
+               {
+                       float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+                       float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
+
+                       float sum = 0;
+                       for (int j = 0; j < 4; j++)
+                       {
+                               sum += contactConstraints[i].m_appliedRambdaDt[j];
+                       }
+                       float frictionCoeff = contactConstraints[i].getFrictionCoeff();
+                       int aIdx = (int)contactConstraints[i].m_bodyA;
+                       int bIdx = (int)contactConstraints[i].m_bodyB;
+                       b3RigidBodyData& bodyA = bodies[aIdx];
+                       b3RigidBodyData& bodyB = bodies[bIdx];
+
+                       b3Vector3 zero = b3MakeVector3(0, 0, 0);
+
+                       b3Vector3* dlvAPtr = &zero;
+                       b3Vector3* davAPtr = &zero;
+                       b3Vector3* dlvBPtr = &zero;
+                       b3Vector3* davBPtr = &zero;
+
+                       if (bodyA.m_invMass)
+                       {
+                               int bodyOffsetA = offsetSplitBodies[aIdx];
+                               int constraintOffsetA = contactConstraintOffsets[i].x;
+                               int splitIndexA = bodyOffsetA + constraintOffsetA;
+                               dlvAPtr = &deltaLinearVelocities[splitIndexA];
+                               davAPtr = &deltaAngularVelocities[splitIndexA];
+                       }
+
+                       if (bodyB.m_invMass)
+                       {
+                               int bodyOffsetB = offsetSplitBodies[bIdx];
+                               int constraintOffsetB = contactConstraintOffsets[i].y;
+                               int splitIndexB = bodyOffsetB + constraintOffsetB;
+                               dlvBPtr = &deltaLinearVelocities[splitIndexB];
+                               davBPtr = &deltaAngularVelocities[splitIndexB];
+                       }
+
+                       for (int j = 0; j < 4; j++)
+                       {
+                               maxRambdaDt[j] = frictionCoeff * sum;
+                               minRambdaDt[j] = -maxRambdaDt[j];
+                       }
+
+                       solveFriction(contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertias[aIdx].m_invInertiaWorld,
+                                                 (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertias[bIdx].m_invInertiaWorld,
+                                                 maxRambdaDt, minRambdaDt, *dlvAPtr, *davAPtr, *dlvBPtr, *davBPtr);
+               }
+
+               //easy
+               for (int i = 0; i < numBodies; i++)
+               {
+                       if (bodies[i].m_invMass)
+                       {
+                               int bodyOffset = offsetSplitBodies[i];
+                               int count = bodyCount[i];
+                               float factor = 1.f / float(count);
+                               b3Vector3 averageLinVel;
+                               averageLinVel.setZero();
+                               b3Vector3 averageAngVel;
+                               averageAngVel.setZero();
+                               for (int j = 0; j < count; j++)
+                               {
+                                       averageLinVel += deltaLinearVelocities[bodyOffset + j] * factor;
+                                       averageAngVel += deltaAngularVelocities[bodyOffset + j] * factor;
+                               }
+                               for (int j = 0; j < count; j++)
+                               {
+                                       deltaLinearVelocities[bodyOffset + j] = averageLinVel;
+                                       deltaAngularVelocities[bodyOffset + j] = averageAngVel;
+                               }
+                       }
+               }
+       }
+
+       //easy
+       for (int i = 0; i < numBodies; i++)
+       {
+               if (bodies[i].m_invMass)
+               {
+                       int bodyOffset = offsetSplitBodies[i];
+                       int count = bodyCount[i];
+                       if (count)
+                       {
+                               bodies[i].m_linVel += deltaLinearVelocities[bodyOffset];
+                               bodies[i].m_angVel += deltaAngularVelocities[bodyOffset];
+                       }
+               }
+       }
+}
+
+void b3GpuJacobiContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index)
+//
+//
+//void  b3GpuJacobiContactSolver::solveGroup(b3OpenCLArray<b3RigidBodyData>* bodies,b3OpenCLArray<b3InertiaData>* inertias,b3OpenCLArray<b3Contact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo)
+{
+       b3JacobiSolverInfo solverInfo;
+       solverInfo.m_fixedBodyIndex = static0Index;
+
+       B3_PROFILE("b3GpuJacobiContactSolver::solveGroup");
+
+       //int numBodies = bodies->size();
+       int numManifolds = numContacts;  //manifoldPtr->size();
+
+       {
+               B3_PROFILE("resize");
+               m_data->m_bodyCount->resize(numBodies);
+       }
+
+       unsigned int val = 0;
+       b3Int2 val2;
+       val2.x = 0;
+       val2.y = 0;
+
+       {
+               B3_PROFILE("m_filler");
+               m_data->m_contactConstraintOffsets->resize(numManifolds);
+               m_data->m_filler->execute(*m_data->m_bodyCount, val, numBodies);
+
+               m_data->m_filler->execute(*m_data->m_contactConstraintOffsets, val2, numManifolds);
+       }
+
+       {
+               B3_PROFILE("m_countBodiesKernel");
+               b3LauncherCL launcher(this->m_queue, m_data->m_countBodiesKernel, "m_countBodiesKernel");
+               launcher.setBuffer(contactBuf);  //manifoldPtr->getBufferCL());
+               launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+               launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+               launcher.setConst(numManifolds);
+               launcher.setConst(solverInfo.m_fixedBodyIndex);
+               launcher.launch1D(numManifolds);
+       }
+       unsigned int totalNumSplitBodies = 0;
+       {
+               B3_PROFILE("m_scan->execute");
+
+               m_data->m_offsetSplitBodies->resize(numBodies);
+               m_data->m_scan->execute(*m_data->m_bodyCount, *m_data->m_offsetSplitBodies, numBodies, &totalNumSplitBodies);
+               totalNumSplitBodies += m_data->m_bodyCount->at(numBodies - 1);
+       }
+
+       {
+               B3_PROFILE("m_data->m_contactConstraints->resize");
+               //int numContacts = manifoldPtr->size();
+               m_data->m_contactConstraints->resize(numContacts);
+       }
+
+       {
+               B3_PROFILE("contactToConstraintSplitKernel");
+               b3LauncherCL launcher(m_queue, m_data->m_contactToConstraintSplitKernel, "m_contactToConstraintSplitKernel");
+               launcher.setBuffer(contactBuf);
+               launcher.setBuffer(bodyBuf);
+               launcher.setBuffer(inertiaBuf);
+               launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+               launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+               launcher.setConst(numContacts);
+               launcher.setConst(solverInfo.m_deltaTime);
+               launcher.setConst(solverInfo.m_positionDrift);
+               launcher.setConst(solverInfo.m_positionConstraintCoeff);
+               launcher.launch1D(numContacts, 64);
+       }
+
+       {
+               B3_PROFILE("m_data->m_deltaLinearVelocities->resize");
+               m_data->m_deltaLinearVelocities->resize(totalNumSplitBodies);
+               m_data->m_deltaAngularVelocities->resize(totalNumSplitBodies);
+       }
+
+       {
+               B3_PROFILE("m_clearVelocitiesKernel");
+               b3LauncherCL launch(m_queue, m_data->m_clearVelocitiesKernel, "m_clearVelocitiesKernel");
+               launch.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+               launch.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+               launch.setConst(totalNumSplitBodies);
+               launch.launch1D(totalNumSplitBodies);
+               clFinish(m_queue);
+       }
+
+       int maxIter = solverInfo.m_numIterations;
+
+       for (int iter = 0; iter < maxIter; iter++)
+       {
+               {
+                       B3_PROFILE("m_solveContactKernel");
+                       b3LauncherCL launcher(m_queue, m_data->m_solveContactKernel, "m_solveContactKernel");
+                       launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+                       launcher.setBuffer(bodyBuf);
+                       launcher.setBuffer(inertiaBuf);
+                       launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+                       launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+                       launcher.setConst(solverInfo.m_deltaTime);
+                       launcher.setConst(solverInfo.m_positionDrift);
+                       launcher.setConst(solverInfo.m_positionConstraintCoeff);
+                       launcher.setConst(solverInfo.m_fixedBodyIndex);
+                       launcher.setConst(numManifolds);
+
+                       launcher.launch1D(numManifolds);
+                       clFinish(m_queue);
+               }
+
+               {
+                       B3_PROFILE("average velocities");
+                       b3LauncherCL launcher(m_queue, m_data->m_averageVelocitiesKernel, "m_averageVelocitiesKernel");
+                       launcher.setBuffer(bodyBuf);
+                       launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+                       launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+                       launcher.setConst(numBodies);
+                       launcher.launch1D(numBodies);
+                       clFinish(m_queue);
+               }
+
+               {
+                       B3_PROFILE("m_solveFrictionKernel");
+                       b3LauncherCL launcher(m_queue, m_data->m_solveFrictionKernel, "m_solveFrictionKernel");
+                       launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+                       launcher.setBuffer(bodyBuf);
+                       launcher.setBuffer(inertiaBuf);
+                       launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+                       launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+                       launcher.setConst(solverInfo.m_deltaTime);
+                       launcher.setConst(solverInfo.m_positionDrift);
+                       launcher.setConst(solverInfo.m_positionConstraintCoeff);
+                       launcher.setConst(solverInfo.m_fixedBodyIndex);
+                       launcher.setConst(numManifolds);
+
+                       launcher.launch1D(numManifolds);
+                       clFinish(m_queue);
+               }
+
+               {
+                       B3_PROFILE("average velocities");
+                       b3LauncherCL launcher(m_queue, m_data->m_averageVelocitiesKernel, "m_averageVelocitiesKernel");
+                       launcher.setBuffer(bodyBuf);
+                       launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+                       launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+                       launcher.setConst(numBodies);
+                       launcher.launch1D(numBodies);
+                       clFinish(m_queue);
+               }
+       }
+
+       {
+               B3_PROFILE("update body velocities");
+               b3LauncherCL launcher(m_queue, m_data->m_updateBodyVelocitiesKernel, "m_updateBodyVelocitiesKernel");
+               launcher.setBuffer(bodyBuf);
+               launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+               launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+               launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+               launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+               launcher.setConst(numBodies);
+               launcher.launch1D(numBodies);
+               clFinish(m_queue);
+       }
+}
+
+#if 0
+
+void  b3GpuJacobiContactSolver::solveGroupMixed(b3OpenCLArray<b3RigidBodyData>* bodiesGPU,b3OpenCLArray<b3InertiaData>* inertiasGPU,b3OpenCLArray<b3Contact4>* manifoldPtrGPU,const btJacobiSolverInfo& solverInfo)
+{
+
+       b3AlignedObjectArray<b3RigidBodyData> bodiesCPU;
+       bodiesGPU->copyToHost(bodiesCPU);
+       b3AlignedObjectArray<b3InertiaData> inertiasCPU;
+       inertiasGPU->copyToHost(inertiasCPU);
+       b3AlignedObjectArray<b3Contact4> manifoldPtrCPU;
+       manifoldPtrGPU->copyToHost(manifoldPtrCPU);
+       
+       int numBodiesCPU = bodiesGPU->size();
+       int numManifoldsCPU = manifoldPtrGPU->size();
+       B3_PROFILE("b3GpuJacobiContactSolver::solveGroupMixed");
+
+       b3AlignedObjectArray<unsigned int> bodyCount;
+       bodyCount.resize(numBodiesCPU);
+       for (int i=0;i<numBodiesCPU;i++)
+               bodyCount[i] = 0;
+
+       b3AlignedObjectArray<b3Int2> contactConstraintOffsets;
+       contactConstraintOffsets.resize(numManifoldsCPU);
+
+
+       for (int i=0;i<numManifoldsCPU;i++)
+       {
+               int pa = manifoldPtrCPU[i].m_bodyAPtrAndSignBit;
+               int pb = manifoldPtrCPU[i].m_bodyBPtrAndSignBit;
+
+               bool isFixedA = (pa <0) || (pa == solverInfo.m_fixedBodyIndex);
+               bool isFixedB = (pb <0) || (pb == solverInfo.m_fixedBodyIndex);
+
+               int bodyIndexA = manifoldPtrCPU[i].getBodyA();
+               int bodyIndexB = manifoldPtrCPU[i].getBodyB();
+
+               if (!isFixedA)
+               {
+                       contactConstraintOffsets[i].x = bodyCount[bodyIndexA];
+                       bodyCount[bodyIndexA]++;
+               }
+               if (!isFixedB)
+               {
+                       contactConstraintOffsets[i].y = bodyCount[bodyIndexB];
+                       bodyCount[bodyIndexB]++;
+               } 
+       }
+
+       b3AlignedObjectArray<unsigned int> offsetSplitBodies;
+       offsetSplitBodies.resize(numBodiesCPU);
+       unsigned int totalNumSplitBodiesCPU;
+       m_data->m_scan->executeHost(bodyCount,offsetSplitBodies,numBodiesCPU,&totalNumSplitBodiesCPU);
+       int numlastBody = bodyCount[numBodiesCPU-1];
+       totalNumSplitBodiesCPU += numlastBody;
+
+               int numBodies = bodiesGPU->size();
+       int numManifolds = manifoldPtrGPU->size();
+
+       m_data->m_bodyCount->resize(numBodies);
+       
+       unsigned int val=0;
+       b3Int2 val2;
+       val2.x=0;
+       val2.y=0;
+
+        {
+               B3_PROFILE("m_filler");
+               m_data->m_contactConstraintOffsets->resize(numManifolds);
+               m_data->m_filler->execute(*m_data->m_bodyCount,val,numBodies);
+               
+       
+               m_data->m_filler->execute(*m_data->m_contactConstraintOffsets,val2,numManifolds);
+       }
+
+       {
+               B3_PROFILE("m_countBodiesKernel");
+               b3LauncherCL launcher(this->m_queue,m_data->m_countBodiesKernel);
+               launcher.setBuffer(manifoldPtrGPU->getBufferCL());
+               launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+               launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+               launcher.setConst(numManifolds);
+               launcher.setConst(solverInfo.m_fixedBodyIndex);
+               launcher.launch1D(numManifolds);
+       }
+
+       unsigned int totalNumSplitBodies=0;
+       m_data->m_offsetSplitBodies->resize(numBodies);
+       m_data->m_scan->execute(*m_data->m_bodyCount,*m_data->m_offsetSplitBodies,numBodies,&totalNumSplitBodies);
+       totalNumSplitBodies+=m_data->m_bodyCount->at(numBodies-1);
+
+       if (totalNumSplitBodies != totalNumSplitBodiesCPU)
+       {
+               printf("error in totalNumSplitBodies!\n");
+       }
+
+       int numContacts = manifoldPtrGPU->size();
+       m_data->m_contactConstraints->resize(numContacts);
+
+       
+       {
+               B3_PROFILE("contactToConstraintSplitKernel");
+               b3LauncherCL launcher( m_queue, m_data->m_contactToConstraintSplitKernel);
+               launcher.setBuffer(manifoldPtrGPU->getBufferCL());
+               launcher.setBuffer(bodiesGPU->getBufferCL());
+               launcher.setBuffer(inertiasGPU->getBufferCL());
+               launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+               launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+        launcher.setConst(numContacts);
+               launcher.setConst(solverInfo.m_deltaTime);
+               launcher.setConst(solverInfo.m_positionDrift);
+               launcher.setConst(solverInfo.m_positionConstraintCoeff);
+               launcher.launch1D( numContacts, 64 );
+               clFinish(m_queue);
+       }
+
+
+
+       b3AlignedObjectArray<b3GpuConstraint4> contactConstraints;
+       contactConstraints.resize(numManifoldsCPU);
+
+       for (int i=0;i<numManifoldsCPU;i++)
+       {
+               ContactToConstraintKernel(&manifoldPtrCPU[0],&bodiesCPU[0],&inertiasCPU[0],&contactConstraints[0],numManifoldsCPU,
+                       solverInfo.m_deltaTime,
+                       solverInfo.m_positionDrift,
+                       solverInfo.m_positionConstraintCoeff,
+                       i, bodyCount);
+       }
+       int maxIter = solverInfo.m_numIterations;
+
+
+       b3AlignedObjectArray<b3Vector3> deltaLinearVelocities;
+       b3AlignedObjectArray<b3Vector3> deltaAngularVelocities;
+       deltaLinearVelocities.resize(totalNumSplitBodiesCPU);
+       deltaAngularVelocities.resize(totalNumSplitBodiesCPU);
+       for (int i=0;i<totalNumSplitBodiesCPU;i++)
+       {
+               deltaLinearVelocities[i].setZero();
+               deltaAngularVelocities[i].setZero();
+       }
+
+       m_data->m_deltaLinearVelocities->resize(totalNumSplitBodies);
+       m_data->m_deltaAngularVelocities->resize(totalNumSplitBodies);
+
+
+       
+       {
+               B3_PROFILE("m_clearVelocitiesKernel");
+               b3LauncherCL launch(m_queue,m_data->m_clearVelocitiesKernel);
+               launch.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+               launch.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+               launch.setConst(totalNumSplitBodies);
+               launch.launch1D(totalNumSplitBodies);
+       }
+       
+
+               ///!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+       m_data->m_contactConstraints->copyToHost(contactConstraints);
+       m_data->m_offsetSplitBodies->copyToHost(offsetSplitBodies);
+       m_data->m_contactConstraintOffsets->copyToHost(contactConstraintOffsets);
+       m_data->m_deltaLinearVelocities->copyToHost(deltaLinearVelocities);
+       m_data->m_deltaAngularVelocities->copyToHost(deltaAngularVelocities);
+
+       for (int iter = 0;iter<maxIter;iter++)
+       {
+
+                               {
+                       B3_PROFILE("m_solveContactKernel");
+                       b3LauncherCL launcher( m_queue, m_data->m_solveContactKernel );
+                       launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+                       launcher.setBuffer(bodiesGPU->getBufferCL());
+                       launcher.setBuffer(inertiasGPU->getBufferCL());
+                       launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+                       launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+                       launcher.setConst(solverInfo.m_deltaTime);
+                       launcher.setConst(solverInfo.m_positionDrift);
+                       launcher.setConst(solverInfo.m_positionConstraintCoeff);
+                       launcher.setConst(solverInfo.m_fixedBodyIndex);
+                       launcher.setConst(numManifolds);
+
+                       launcher.launch1D(numManifolds);
+                       clFinish(m_queue);
+               }
+
+
+               int i=0;
+               for( i=0; i<numManifoldsCPU; i++)
+               {
+
+                       float frictionCoeff = contactConstraints[i].getFrictionCoeff();
+                       int aIdx = (int)contactConstraints[i].m_bodyA;
+                       int bIdx = (int)contactConstraints[i].m_bodyB;
+                       b3RigidBodyData& bodyA = bodiesCPU[aIdx];
+                       b3RigidBodyData& bodyB = bodiesCPU[bIdx];
+
+                       b3Vector3 zero(0,0,0);
+                       
+                       b3Vector3* dlvAPtr=&zero;
+                       b3Vector3* davAPtr=&zero;
+                       b3Vector3* dlvBPtr=&zero;
+                       b3Vector3* davBPtr=&zero;
+                       
+                       if (bodyA.m_invMass)
+                       {
+                               int bodyOffsetA = offsetSplitBodies[aIdx];
+                               int constraintOffsetA = contactConstraintOffsets[i].x;
+                               int splitIndexA = bodyOffsetA+constraintOffsetA;
+                               dlvAPtr = &deltaLinearVelocities[splitIndexA];
+                               davAPtr = &deltaAngularVelocities[splitIndexA];
+                       }
+
+                       if (bodyB.m_invMass)
+                       {
+                               int bodyOffsetB = offsetSplitBodies[bIdx];
+                               int constraintOffsetB = contactConstraintOffsets[i].y;
+                               int splitIndexB= bodyOffsetB+constraintOffsetB;
+                               dlvBPtr =&deltaLinearVelocities[splitIndexB];
+                               davBPtr = &deltaAngularVelocities[splitIndexB];
+                       }
+
+
+
+                       {
+                               float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+                               float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+                               solveContact( contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertiasCPU[aIdx].m_invInertiaWorld, 
+                                       (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertiasCPU[bIdx].m_invInertiaWorld,
+                                       maxRambdaDt, minRambdaDt , *dlvAPtr,*davAPtr,*dlvBPtr,*davBPtr          );
+
+
+                       }
+               }
+
+               
+               {
+                       B3_PROFILE("average velocities");
+                       b3LauncherCL launcher( m_queue, m_data->m_averageVelocitiesKernel);
+                       launcher.setBuffer(bodiesGPU->getBufferCL());
+                       launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+                       launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+                       launcher.setConst(numBodies);
+                       launcher.launch1D(numBodies);
+                       clFinish(m_queue);
+               }
+
+               //easy
+               for (int i=0;i<numBodiesCPU;i++)
+               {
+                       if (bodiesCPU[i].m_invMass)
+                       {
+                               int bodyOffset = offsetSplitBodies[i];
+                               int count = bodyCount[i];
+                               float factor = 1.f/float(count);
+                               b3Vector3 averageLinVel;
+                               averageLinVel.setZero();
+                               b3Vector3 averageAngVel;
+                               averageAngVel.setZero();
+                               for (int j=0;j<count;j++)
+                               {
+                                       averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
+                                       averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
+                               }
+                               for (int j=0;j<count;j++)
+                               {
+                                       deltaLinearVelocities[bodyOffset+j] = averageLinVel;
+                                       deltaAngularVelocities[bodyOffset+j] = averageAngVel;
+                               }
+                       }
+               }
+//     m_data->m_deltaAngularVelocities->copyFromHost(deltaAngularVelocities);
+       //m_data->m_deltaLinearVelocities->copyFromHost(deltaLinearVelocities);
+       m_data->m_deltaAngularVelocities->copyToHost(deltaAngularVelocities);
+       m_data->m_deltaLinearVelocities->copyToHost(deltaLinearVelocities);
+
+#if 0
+
+               {
+                       B3_PROFILE("m_solveFrictionKernel");
+                       b3LauncherCL launcher( m_queue, m_data->m_solveFrictionKernel);
+                       launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
+                       launcher.setBuffer(bodiesGPU->getBufferCL());
+                       launcher.setBuffer(inertiasGPU->getBufferCL());
+                       launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
+                       launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+                       launcher.setConst(solverInfo.m_deltaTime);
+                       launcher.setConst(solverInfo.m_positionDrift);
+                       launcher.setConst(solverInfo.m_positionConstraintCoeff);
+                       launcher.setConst(solverInfo.m_fixedBodyIndex);
+                       launcher.setConst(numManifolds);
+
+                       launcher.launch1D(numManifolds);
+                       clFinish(m_queue);
+               }
+
+               //solve friction
+
+               for(int i=0; i<numManifoldsCPU; i++)
+               {
+                       float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+                       float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+                       float sum = 0;
+                       for(int j=0; j<4; j++)
+                       {
+                               sum +=contactConstraints[i].m_appliedRambdaDt[j];
+                       }
+                       float frictionCoeff = contactConstraints[i].getFrictionCoeff();
+                       int aIdx = (int)contactConstraints[i].m_bodyA;
+                       int bIdx = (int)contactConstraints[i].m_bodyB;
+                       b3RigidBodyData& bodyA = bodiesCPU[aIdx];
+                       b3RigidBodyData& bodyB = bodiesCPU[bIdx];
+
+                       b3Vector3 zero(0,0,0);
+                       
+                       b3Vector3* dlvAPtr=&zero;
+                       b3Vector3* davAPtr=&zero;
+                       b3Vector3* dlvBPtr=&zero;
+                       b3Vector3* davBPtr=&zero;
+                       
+                       if (bodyA.m_invMass)
+                       {
+                               int bodyOffsetA = offsetSplitBodies[aIdx];
+                               int constraintOffsetA = contactConstraintOffsets[i].x;
+                               int splitIndexA = bodyOffsetA+constraintOffsetA;
+                               dlvAPtr = &deltaLinearVelocities[splitIndexA];
+                               davAPtr = &deltaAngularVelocities[splitIndexA];
+                       }
+
+                       if (bodyB.m_invMass)
+                       {
+                               int bodyOffsetB = offsetSplitBodies[bIdx];
+                               int constraintOffsetB = contactConstraintOffsets[i].y;
+                               int splitIndexB= bodyOffsetB+constraintOffsetB;
+                               dlvBPtr =&deltaLinearVelocities[splitIndexB];
+                               davBPtr = &deltaAngularVelocities[splitIndexB];
+                       }
+
+                       for(int j=0; j<4; j++)
+                       {
+                               maxRambdaDt[j] = frictionCoeff*sum;
+                               minRambdaDt[j] = -maxRambdaDt[j];
+                       }
+
+                       solveFriction( contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,inertiasCPU[aIdx].m_invInertiaWorld, 
+                               (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertiasCPU[bIdx].m_invInertiaWorld,
+                               maxRambdaDt, minRambdaDt , *dlvAPtr,*davAPtr,*dlvBPtr,*davBPtr);
+
+               }
+
+               {
+                       B3_PROFILE("average velocities");
+                       b3LauncherCL launcher( m_queue, m_data->m_averageVelocitiesKernel);
+                       launcher.setBuffer(bodiesGPU->getBufferCL());
+                       launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+                       launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+                       launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+                       launcher.setConst(numBodies);
+                       launcher.launch1D(numBodies);
+                       clFinish(m_queue);
+               }
+
+               //easy
+               for (int i=0;i<numBodiesCPU;i++)
+               {
+                       if (bodiesCPU[i].m_invMass)
+                       {
+                               int bodyOffset = offsetSplitBodies[i];
+                               int count = bodyCount[i];
+                               float factor = 1.f/float(count);
+                               b3Vector3 averageLinVel;
+                               averageLinVel.setZero();
+                               b3Vector3 averageAngVel;
+                               averageAngVel.setZero();
+                               for (int j=0;j<count;j++)
+                               {
+                                       averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
+                                       averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
+                               }
+                               for (int j=0;j<count;j++)
+                               {
+                                       deltaLinearVelocities[bodyOffset+j] = averageLinVel;
+                                       deltaAngularVelocities[bodyOffset+j] = averageAngVel;
+                               }
+                       }
+               }
+
+#endif
+
+       }
+
+       {
+               B3_PROFILE("update body velocities");
+               b3LauncherCL launcher( m_queue, m_data->m_updateBodyVelocitiesKernel);
+               launcher.setBuffer(bodiesGPU->getBufferCL());
+               launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
+               launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
+               launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
+               launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
+               launcher.setConst(numBodies);
+               launcher.launch1D(numBodies);
+               clFinish(m_queue);
+       }
+
+
+       //easy
+       for (int i=0;i<numBodiesCPU;i++)
+       {
+               if (bodiesCPU[i].m_invMass)
+               {
+                       int bodyOffset = offsetSplitBodies[i];
+                       int count = bodyCount[i];
+                       if (count)
+                       {
+                               bodiesCPU[i].m_linVel += deltaLinearVelocities[bodyOffset];
+                               bodiesCPU[i].m_angVel += deltaAngularVelocities[bodyOffset];
+                       }
+               }
+       }
+
+
+//     bodiesGPU->copyFromHost(bodiesCPU);
+
+
+}
+#endif
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h
new file mode 100644 (file)
index 0000000..8281aee
--- /dev/null
@@ -0,0 +1,56 @@
+
+#ifndef B3_GPU_JACOBI_CONTACT_SOLVER_H
+#define B3_GPU_JACOBI_CONTACT_SOLVER_H
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+//#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+
+//struct b3InertiaData;
+//b3InertiaData
+
+class b3TypedConstraint;
+
+struct b3JacobiSolverInfo
+{
+       int m_fixedBodyIndex;
+
+       float m_deltaTime;
+       float m_positionDrift;
+       float m_positionConstraintCoeff;
+       int m_numIterations;
+
+       b3JacobiSolverInfo()
+               : m_fixedBodyIndex(0),
+                 m_deltaTime(1. / 60.f),
+                 m_positionDrift(0.005f),
+                 m_positionConstraintCoeff(0.99f),
+                 m_numIterations(7)
+       {
+       }
+};
+class b3GpuJacobiContactSolver
+{
+protected:
+       struct b3GpuJacobiSolverInternalData* m_data;
+
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_queue;
+
+public:
+       b3GpuJacobiContactSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity);
+       virtual ~b3GpuJacobiContactSolver();
+
+       void solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index);
+       void solveGroupHost(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, struct b3Contact4* manifoldPtr, int numManifolds, const b3JacobiSolverInfo& solverInfo);
+       //void  solveGroupHost(btRigidBodyCL* bodies,b3InertiaData* inertias,int numBodies,btContact4* manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btJacobiSolverInfo& solverInfo);
+
+       //b3Scalar solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies,b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
+
+       //void  solveGroup(btOpenCLArray<btRigidBodyCL>* bodies,btOpenCLArray<btInertiaCL>* inertias,btOpenCLArray<btContact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo);
+       //void  solveGroupMixed(btOpenCLArray<btRigidBodyCL>* bodies,btOpenCLArray<btInertiaCL>* inertias,btOpenCLArray<btContact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo);
+};
+#endif  //B3_GPU_JACOBI_CONTACT_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp
new file mode 100644 (file)
index 0000000..2e4f6c1
--- /dev/null
@@ -0,0 +1,1013 @@
+#include "b3GpuNarrowPhase.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
+#include <string.h>
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h"
+
+#include "b3GpuNarrowPhaseInternalData.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h"
+
+b3GpuNarrowPhase::b3GpuNarrowPhase(cl_context ctx, cl_device_id device, cl_command_queue queue, const b3Config& config)
+       : m_data(0), m_planeBodyIndex(-1), m_static0Index(-1), m_context(ctx), m_device(device), m_queue(queue)
+{
+       m_data = new b3GpuNarrowPhaseInternalData();
+       m_data->m_currentContactBuffer = 0;
+
+       memset(m_data, 0, sizeof(b3GpuNarrowPhaseInternalData));
+
+       m_data->m_config = config;
+
+       m_data->m_gpuSatCollision = new GpuSatCollision(ctx, device, queue);
+
+       m_data->m_triangleConvexPairs = new b3OpenCLArray<b3Int4>(m_context, m_queue, config.m_maxTriConvexPairCapacity);
+
+       //m_data->m_convexPairsOutGPU = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
+       //m_data->m_planePairs = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
+
+       m_data->m_pBufContactOutCPU = new b3AlignedObjectArray<b3Contact4>();
+       m_data->m_pBufContactOutCPU->resize(config.m_maxBroadphasePairs);
+       m_data->m_bodyBufferCPU = new b3AlignedObjectArray<b3RigidBodyData>();
+       m_data->m_bodyBufferCPU->resize(config.m_maxConvexBodies);
+
+       m_data->m_inertiaBufferCPU = new b3AlignedObjectArray<b3InertiaData>();
+       m_data->m_inertiaBufferCPU->resize(config.m_maxConvexBodies);
+
+       m_data->m_pBufContactBuffersGPU[0] = new b3OpenCLArray<b3Contact4>(ctx, queue, config.m_maxContactCapacity, true);
+       m_data->m_pBufContactBuffersGPU[1] = new b3OpenCLArray<b3Contact4>(ctx, queue, config.m_maxContactCapacity, true);
+
+       m_data->m_inertiaBufferGPU = new b3OpenCLArray<b3InertiaData>(ctx, queue, config.m_maxConvexBodies, false);
+       m_data->m_collidablesGPU = new b3OpenCLArray<b3Collidable>(ctx, queue, config.m_maxConvexShapes);
+       m_data->m_collidablesCPU.reserve(config.m_maxConvexShapes);
+
+       m_data->m_localShapeAABBCPU = new b3AlignedObjectArray<b3SapAabb>;
+       m_data->m_localShapeAABBGPU = new b3OpenCLArray<b3SapAabb>(ctx, queue, config.m_maxConvexShapes);
+
+       //m_data->m_solverDataGPU = adl::Solver<adl::TYPE_CL>::allocate(ctx,queue, config.m_maxBroadphasePairs,false);
+       m_data->m_bodyBufferGPU = new b3OpenCLArray<b3RigidBodyData>(ctx, queue, config.m_maxConvexBodies, false);
+
+       m_data->m_convexFacesGPU = new b3OpenCLArray<b3GpuFace>(ctx, queue, config.m_maxConvexShapes * config.m_maxFacesPerShape, false);
+       m_data->m_convexFaces.reserve(config.m_maxConvexShapes * config.m_maxFacesPerShape);
+
+       m_data->m_gpuChildShapes = new b3OpenCLArray<b3GpuChildShape>(ctx, queue, config.m_maxCompoundChildShapes, false);
+
+       m_data->m_convexPolyhedraGPU = new b3OpenCLArray<b3ConvexPolyhedronData>(ctx, queue, config.m_maxConvexShapes, false);
+       m_data->m_convexPolyhedra.reserve(config.m_maxConvexShapes);
+
+       m_data->m_uniqueEdgesGPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexUniqueEdges, true);
+       m_data->m_uniqueEdges.reserve(config.m_maxConvexUniqueEdges);
+
+       m_data->m_convexVerticesGPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexVertices, true);
+       m_data->m_convexVertices.reserve(config.m_maxConvexVertices);
+
+       m_data->m_convexIndicesGPU = new b3OpenCLArray<int>(ctx, queue, config.m_maxConvexIndices, true);
+       m_data->m_convexIndices.reserve(config.m_maxConvexIndices);
+
+       m_data->m_worldVertsB1GPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies * config.m_maxVerticesPerFace);
+       m_data->m_clippingFacesOutGPU = new b3OpenCLArray<b3Int4>(ctx, queue, config.m_maxConvexBodies);
+       m_data->m_worldNormalsAGPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies);
+       m_data->m_worldVertsA1GPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies * config.m_maxVerticesPerFace);
+       m_data->m_worldVertsB2GPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies * config.m_maxVerticesPerFace);
+
+       m_data->m_convexData = new b3AlignedObjectArray<b3ConvexUtility*>();
+
+       m_data->m_convexData->resize(config.m_maxConvexShapes);
+       m_data->m_convexPolyhedra.resize(config.m_maxConvexShapes);
+
+       m_data->m_numAcceleratedShapes = 0;
+       m_data->m_numAcceleratedRigidBodies = 0;
+
+       m_data->m_subTreesGPU = new b3OpenCLArray<b3BvhSubtreeInfo>(this->m_context, this->m_queue);
+       m_data->m_treeNodesGPU = new b3OpenCLArray<b3QuantizedBvhNode>(this->m_context, this->m_queue);
+       m_data->m_bvhInfoGPU = new b3OpenCLArray<b3BvhInfo>(this->m_context, this->m_queue);
+
+       //m_data->m_contactCGPU = new b3OpenCLArray<Constraint4>(ctx,queue,config.m_maxBroadphasePairs,false);
+       //m_data->m_frictionCGPU = new b3OpenCLArray<adl::Solver<adl::TYPE_CL>::allocateFrictionConstraint( m_data->m_deviceCL, config.m_maxBroadphasePairs);
+}
+
+b3GpuNarrowPhase::~b3GpuNarrowPhase()
+{
+       delete m_data->m_gpuSatCollision;
+
+       delete m_data->m_triangleConvexPairs;
+       //delete m_data->m_convexPairsOutGPU;
+       //delete m_data->m_planePairs;
+       delete m_data->m_pBufContactOutCPU;
+       delete m_data->m_bodyBufferCPU;
+       delete m_data->m_inertiaBufferCPU;
+       delete m_data->m_pBufContactBuffersGPU[0];
+       delete m_data->m_pBufContactBuffersGPU[1];
+
+       delete m_data->m_inertiaBufferGPU;
+       delete m_data->m_collidablesGPU;
+       delete m_data->m_localShapeAABBCPU;
+       delete m_data->m_localShapeAABBGPU;
+       delete m_data->m_bodyBufferGPU;
+       delete m_data->m_convexFacesGPU;
+       delete m_data->m_gpuChildShapes;
+       delete m_data->m_convexPolyhedraGPU;
+       delete m_data->m_uniqueEdgesGPU;
+       delete m_data->m_convexVerticesGPU;
+       delete m_data->m_convexIndicesGPU;
+       delete m_data->m_worldVertsB1GPU;
+       delete m_data->m_clippingFacesOutGPU;
+       delete m_data->m_worldNormalsAGPU;
+       delete m_data->m_worldVertsA1GPU;
+       delete m_data->m_worldVertsB2GPU;
+
+       delete m_data->m_bvhInfoGPU;
+
+       for (int i = 0; i < m_data->m_bvhData.size(); i++)
+       {
+               delete m_data->m_bvhData[i];
+       }
+       for (int i = 0; i < m_data->m_meshInterfaces.size(); i++)
+       {
+               delete m_data->m_meshInterfaces[i];
+       }
+       m_data->m_meshInterfaces.clear();
+       m_data->m_bvhData.clear();
+       delete m_data->m_treeNodesGPU;
+       delete m_data->m_subTreesGPU;
+
+       delete m_data->m_convexData;
+       delete m_data;
+}
+
+int b3GpuNarrowPhase::allocateCollidable()
+{
+       int curSize = m_data->m_collidablesCPU.size();
+       if (curSize < m_data->m_config.m_maxConvexShapes)
+       {
+               m_data->m_collidablesCPU.expand();
+               return curSize;
+       }
+       else
+       {
+               b3Error("allocateCollidable out-of-range %d\n", m_data->m_config.m_maxConvexShapes);
+       }
+       return -1;
+}
+
+int b3GpuNarrowPhase::registerSphereShape(float radius)
+{
+       int collidableIndex = allocateCollidable();
+       if (collidableIndex < 0)
+               return collidableIndex;
+
+       b3Collidable& col = getCollidableCpu(collidableIndex);
+       col.m_shapeType = SHAPE_SPHERE;
+       col.m_shapeIndex = 0;
+       col.m_radius = radius;
+
+       if (col.m_shapeIndex >= 0)
+       {
+               b3SapAabb aabb;
+               b3Vector3 myAabbMin = b3MakeVector3(-radius, -radius, -radius);
+               b3Vector3 myAabbMax = b3MakeVector3(radius, radius, radius);
+
+               aabb.m_min[0] = myAabbMin[0];  //s_convexHeightField->m_aabb.m_min.x;
+               aabb.m_min[1] = myAabbMin[1];  //s_convexHeightField->m_aabb.m_min.y;
+               aabb.m_min[2] = myAabbMin[2];  //s_convexHeightField->m_aabb.m_min.z;
+               aabb.m_minIndices[3] = 0;
+
+               aabb.m_max[0] = myAabbMax[0];  //s_convexHeightField->m_aabb.m_max.x;
+               aabb.m_max[1] = myAabbMax[1];  //s_convexHeightField->m_aabb.m_max.y;
+               aabb.m_max[2] = myAabbMax[2];  //s_convexHeightField->m_aabb.m_max.z;
+               aabb.m_signedMaxIndices[3] = 0;
+
+               m_data->m_localShapeAABBCPU->push_back(aabb);
+               //              m_data->m_localShapeAABBGPU->push_back(aabb);
+               clFinish(m_queue);
+       }
+
+       return collidableIndex;
+}
+
+int b3GpuNarrowPhase::registerFace(const b3Vector3& faceNormal, float faceConstant)
+{
+       int faceOffset = m_data->m_convexFaces.size();
+       b3GpuFace& face = m_data->m_convexFaces.expand();
+       face.m_plane = b3MakeVector3(faceNormal.x, faceNormal.y, faceNormal.z, faceConstant);
+       return faceOffset;
+}
+
+int b3GpuNarrowPhase::registerPlaneShape(const b3Vector3& planeNormal, float planeConstant)
+{
+       int collidableIndex = allocateCollidable();
+       if (collidableIndex < 0)
+               return collidableIndex;
+
+       b3Collidable& col = getCollidableCpu(collidableIndex);
+       col.m_shapeType = SHAPE_PLANE;
+       col.m_shapeIndex = registerFace(planeNormal, planeConstant);
+       col.m_radius = planeConstant;
+
+       if (col.m_shapeIndex >= 0)
+       {
+               b3SapAabb aabb;
+               aabb.m_min[0] = -1e30f;
+               aabb.m_min[1] = -1e30f;
+               aabb.m_min[2] = -1e30f;
+               aabb.m_minIndices[3] = 0;
+
+               aabb.m_max[0] = 1e30f;
+               aabb.m_max[1] = 1e30f;
+               aabb.m_max[2] = 1e30f;
+               aabb.m_signedMaxIndices[3] = 0;
+
+               m_data->m_localShapeAABBCPU->push_back(aabb);
+               //              m_data->m_localShapeAABBGPU->push_back(aabb);
+               clFinish(m_queue);
+       }
+
+       return collidableIndex;
+}
+
+int b3GpuNarrowPhase::registerConvexHullShapeInternal(b3ConvexUtility* convexPtr, b3Collidable& col)
+{
+       m_data->m_convexData->resize(m_data->m_numAcceleratedShapes + 1);
+       m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes + 1);
+
+       b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size() - 1);
+       convex.mC = convexPtr->mC;
+       convex.mE = convexPtr->mE;
+       convex.m_extents = convexPtr->m_extents;
+       convex.m_localCenter = convexPtr->m_localCenter;
+       convex.m_radius = convexPtr->m_radius;
+
+       convex.m_numUniqueEdges = convexPtr->m_uniqueEdges.size();
+       int edgeOffset = m_data->m_uniqueEdges.size();
+       convex.m_uniqueEdgesOffset = edgeOffset;
+
+       m_data->m_uniqueEdges.resize(edgeOffset + convex.m_numUniqueEdges);
+
+       //convex data here
+       int i;
+       for (i = 0; i < convexPtr->m_uniqueEdges.size(); i++)
+       {
+               m_data->m_uniqueEdges[edgeOffset + i] = convexPtr->m_uniqueEdges[i];
+       }
+
+       int faceOffset = m_data->m_convexFaces.size();
+       convex.m_faceOffset = faceOffset;
+       convex.m_numFaces = convexPtr->m_faces.size();
+
+       m_data->m_convexFaces.resize(faceOffset + convex.m_numFaces);
+
+       for (i = 0; i < convexPtr->m_faces.size(); i++)
+       {
+               m_data->m_convexFaces[convex.m_faceOffset + i].m_plane = b3MakeVector3(convexPtr->m_faces[i].m_plane[0],
+                                                                                                                                                          convexPtr->m_faces[i].m_plane[1],
+                                                                                                                                                          convexPtr->m_faces[i].m_plane[2],
+                                                                                                                                                          convexPtr->m_faces[i].m_plane[3]);
+
+               int indexOffset = m_data->m_convexIndices.size();
+               int numIndices = convexPtr->m_faces[i].m_indices.size();
+               m_data->m_convexFaces[convex.m_faceOffset + i].m_numIndices = numIndices;
+               m_data->m_convexFaces[convex.m_faceOffset + i].m_indexOffset = indexOffset;
+               m_data->m_convexIndices.resize(indexOffset + numIndices);
+               for (int p = 0; p < numIndices; p++)
+               {
+                       m_data->m_convexIndices[indexOffset + p] = convexPtr->m_faces[i].m_indices[p];
+               }
+       }
+
+       convex.m_numVertices = convexPtr->m_vertices.size();
+       int vertexOffset = m_data->m_convexVertices.size();
+       convex.m_vertexOffset = vertexOffset;
+
+       m_data->m_convexVertices.resize(vertexOffset + convex.m_numVertices);
+       for (int i = 0; i < convexPtr->m_vertices.size(); i++)
+       {
+               m_data->m_convexVertices[vertexOffset + i] = convexPtr->m_vertices[i];
+       }
+
+       (*m_data->m_convexData)[m_data->m_numAcceleratedShapes] = convexPtr;
+
+       return m_data->m_numAcceleratedShapes++;
+}
+
+int b3GpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
+{
+       b3AlignedObjectArray<b3Vector3> verts;
+
+       unsigned char* vts = (unsigned char*)vertices;
+       for (int i = 0; i < numVertices; i++)
+       {
+               float* vertex = (float*)&vts[i * strideInBytes];
+               verts.push_back(b3MakeVector3(vertex[0] * scaling[0], vertex[1] * scaling[1], vertex[2] * scaling[2]));
+       }
+
+       b3ConvexUtility* utilPtr = new b3ConvexUtility();
+       bool merge = true;
+       if (numVertices)
+       {
+               utilPtr->initializePolyhedralFeatures(&verts[0], verts.size(), merge);
+       }
+
+       int collidableIndex = registerConvexHullShape(utilPtr);
+       delete utilPtr;
+       return collidableIndex;
+}
+
+int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
+{
+       int collidableIndex = allocateCollidable();
+       if (collidableIndex < 0)
+               return collidableIndex;
+
+       b3Collidable& col = getCollidableCpu(collidableIndex);
+       col.m_shapeType = SHAPE_CONVEX_HULL;
+       col.m_shapeIndex = -1;
+
+       {
+               b3Vector3 localCenter = b3MakeVector3(0, 0, 0);
+               for (int i = 0; i < utilPtr->m_vertices.size(); i++)
+                       localCenter += utilPtr->m_vertices[i];
+               localCenter *= (1.f / utilPtr->m_vertices.size());
+               utilPtr->m_localCenter = localCenter;
+
+               col.m_shapeIndex = registerConvexHullShapeInternal(utilPtr, col);
+       }
+
+       if (col.m_shapeIndex >= 0)
+       {
+               b3SapAabb aabb;
+
+               b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
+               b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
+
+               for (int i = 0; i < utilPtr->m_vertices.size(); i++)
+               {
+                       myAabbMin.setMin(utilPtr->m_vertices[i]);
+                       myAabbMax.setMax(utilPtr->m_vertices[i]);
+               }
+               aabb.m_min[0] = myAabbMin[0];
+               aabb.m_min[1] = myAabbMin[1];
+               aabb.m_min[2] = myAabbMin[2];
+               aabb.m_minIndices[3] = 0;
+
+               aabb.m_max[0] = myAabbMax[0];
+               aabb.m_max[1] = myAabbMax[1];
+               aabb.m_max[2] = myAabbMax[2];
+               aabb.m_signedMaxIndices[3] = 0;
+
+               m_data->m_localShapeAABBCPU->push_back(aabb);
+               //              m_data->m_localShapeAABBGPU->push_back(aabb);
+       }
+
+       return collidableIndex;
+}
+
+int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes)
+{
+       int collidableIndex = allocateCollidable();
+       if (collidableIndex < 0)
+               return collidableIndex;
+
+       b3Collidable& col = getCollidableCpu(collidableIndex);
+       col.m_shapeType = SHAPE_COMPOUND_OF_CONVEX_HULLS;
+       col.m_shapeIndex = m_data->m_cpuChildShapes.size();
+       col.m_compoundBvhIndex = m_data->m_bvhInfoCPU.size();
+
+       {
+               b3Assert(col.m_shapeIndex + childShapes->size() < m_data->m_config.m_maxCompoundChildShapes);
+               for (int i = 0; i < childShapes->size(); i++)
+               {
+                       m_data->m_cpuChildShapes.push_back(childShapes->at(i));
+               }
+       }
+
+       col.m_numChildShapes = childShapes->size();
+
+       b3SapAabb aabbLocalSpace;
+       b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
+       b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
+
+       b3AlignedObjectArray<b3Aabb> childLocalAabbs;
+       childLocalAabbs.resize(childShapes->size());
+
+       //compute local AABB of the compound of all children
+       for (int i = 0; i < childShapes->size(); i++)
+       {
+               int childColIndex = childShapes->at(i).m_shapeIndex;
+               //b3Collidable& childCol = getCollidableCpu(childColIndex);
+               b3SapAabb aabbLoc = m_data->m_localShapeAABBCPU->at(childColIndex);
+
+               b3Vector3 childLocalAabbMin = b3MakeVector3(aabbLoc.m_min[0], aabbLoc.m_min[1], aabbLoc.m_min[2]);
+               b3Vector3 childLocalAabbMax = b3MakeVector3(aabbLoc.m_max[0], aabbLoc.m_max[1], aabbLoc.m_max[2]);
+               b3Vector3 aMin, aMax;
+               b3Scalar margin(0.f);
+               b3Transform childTr;
+               childTr.setIdentity();
+
+               childTr.setOrigin(childShapes->at(i).m_childPosition);
+               childTr.setRotation(b3Quaternion(childShapes->at(i).m_childOrientation));
+               b3TransformAabb(childLocalAabbMin, childLocalAabbMax, margin, childTr, aMin, aMax);
+               myAabbMin.setMin(aMin);
+               myAabbMax.setMax(aMax);
+               childLocalAabbs[i].m_min[0] = aMin[0];
+               childLocalAabbs[i].m_min[1] = aMin[1];
+               childLocalAabbs[i].m_min[2] = aMin[2];
+               childLocalAabbs[i].m_min[3] = 0;
+               childLocalAabbs[i].m_max[0] = aMax[0];
+               childLocalAabbs[i].m_max[1] = aMax[1];
+               childLocalAabbs[i].m_max[2] = aMax[2];
+               childLocalAabbs[i].m_max[3] = 0;
+       }
+
+       aabbLocalSpace.m_min[0] = myAabbMin[0];  //s_convexHeightField->m_aabb.m_min.x;
+       aabbLocalSpace.m_min[1] = myAabbMin[1];  //s_convexHeightField->m_aabb.m_min.y;
+       aabbLocalSpace.m_min[2] = myAabbMin[2];  //s_convexHeightField->m_aabb.m_min.z;
+       aabbLocalSpace.m_minIndices[3] = 0;
+
+       aabbLocalSpace.m_max[0] = myAabbMax[0];  //s_convexHeightField->m_aabb.m_max.x;
+       aabbLocalSpace.m_max[1] = myAabbMax[1];  //s_convexHeightField->m_aabb.m_max.y;
+       aabbLocalSpace.m_max[2] = myAabbMax[2];  //s_convexHeightField->m_aabb.m_max.z;
+       aabbLocalSpace.m_signedMaxIndices[3] = 0;
+
+       m_data->m_localShapeAABBCPU->push_back(aabbLocalSpace);
+
+       b3QuantizedBvh* bvh = new b3QuantizedBvh;
+       bvh->setQuantizationValues(myAabbMin, myAabbMax);
+       QuantizedNodeArray& nodes = bvh->getLeafNodeArray();
+       int numNodes = childShapes->size();
+
+       for (int i = 0; i < numNodes; i++)
+       {
+               b3QuantizedBvhNode node;
+               b3Vector3 aabbMin, aabbMax;
+               aabbMin = (b3Vector3&)childLocalAabbs[i].m_min;
+               aabbMax = (b3Vector3&)childLocalAabbs[i].m_max;
+
+               bvh->quantize(&node.m_quantizedAabbMin[0], aabbMin, 0);
+               bvh->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);
+       }
+       bvh->buildInternal();
+
+       int numSubTrees = bvh->getSubtreeInfoArray().size();
+
+       //void  setQuantizationValues(const b3Vector3& bvhAabbMin,const b3Vector3& bvhAabbMax,b3Scalar quantizationMargin=b3Scalar(1.0));
+       //QuantizedNodeArray&   getLeafNodeArray() {                    return  m_quantizedLeafNodes;   }
+       ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
+       //void  buildInternal();
+
+       b3BvhInfo bvhInfo;
+
+       bvhInfo.m_aabbMin = bvh->m_bvhAabbMin;
+       bvhInfo.m_aabbMax = bvh->m_bvhAabbMax;
+       bvhInfo.m_quantization = bvh->m_bvhQuantization;
+       bvhInfo.m_numNodes = numNodes;
+       bvhInfo.m_numSubTrees = numSubTrees;
+       bvhInfo.m_nodeOffset = m_data->m_treeNodesCPU.size();
+       bvhInfo.m_subTreeOffset = m_data->m_subTreesCPU.size();
+
+       int numNewNodes = bvh->getQuantizedNodeArray().size();
+
+       for (int i = 0; i < numNewNodes - 1; i++)
+       {
+               if (bvh->getQuantizedNodeArray()[i].isLeafNode())
+               {
+                       int orgIndex = bvh->getQuantizedNodeArray()[i].getTriangleIndex();
+
+                       b3Vector3 nodeMinVec = bvh->unQuantize(bvh->getQuantizedNodeArray()[i].m_quantizedAabbMin);
+                       b3Vector3 nodeMaxVec = bvh->unQuantize(bvh->getQuantizedNodeArray()[i].m_quantizedAabbMax);
+
+                       for (int c = 0; c < 3; c++)
+                       {
+                               if (childLocalAabbs[orgIndex].m_min[c] < nodeMinVec[c])
+                               {
+                                       printf("min org (%f) and new (%f) ? at i:%d,c:%d\n", childLocalAabbs[i].m_min[c], nodeMinVec[c], i, c);
+                               }
+                               if (childLocalAabbs[orgIndex].m_max[c] > nodeMaxVec[c])
+                               {
+                                       printf("max org (%f) and new (%f) ? at i:%d,c:%d\n", childLocalAabbs[i].m_max[c], nodeMaxVec[c], i, c);
+                               }
+                       }
+               }
+       }
+
+       m_data->m_bvhInfoCPU.push_back(bvhInfo);
+
+       int numNewSubtrees = bvh->getSubtreeInfoArray().size();
+       m_data->m_subTreesCPU.reserve(m_data->m_subTreesCPU.size() + numNewSubtrees);
+       for (int i = 0; i < numNewSubtrees; i++)
+       {
+               m_data->m_subTreesCPU.push_back(bvh->getSubtreeInfoArray()[i]);
+       }
+       int numNewTreeNodes = bvh->getQuantizedNodeArray().size();
+
+       for (int i = 0; i < numNewTreeNodes; i++)
+       {
+               m_data->m_treeNodesCPU.push_back(bvh->getQuantizedNodeArray()[i]);
+       }
+
+       //      m_data->m_localShapeAABBGPU->push_back(aabbWS);
+       clFinish(m_queue);
+       return collidableIndex;
+}
+
+int b3GpuNarrowPhase::registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling1)
+{
+       b3Vector3 scaling = b3MakeVector3(scaling1[0], scaling1[1], scaling1[2]);
+
+       int collidableIndex = allocateCollidable();
+       if (collidableIndex < 0)
+               return collidableIndex;
+
+       b3Collidable& col = getCollidableCpu(collidableIndex);
+
+       col.m_shapeType = SHAPE_CONCAVE_TRIMESH;
+       col.m_shapeIndex = registerConcaveMeshShape(vertices, indices, col, scaling);
+       col.m_bvhIndex = m_data->m_bvhInfoCPU.size();
+
+       b3SapAabb aabb;
+       b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
+       b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
+
+       for (int i = 0; i < vertices->size(); i++)
+       {
+               b3Vector3 vtx(vertices->at(i) * scaling);
+               myAabbMin.setMin(vtx);
+               myAabbMax.setMax(vtx);
+       }
+       aabb.m_min[0] = myAabbMin[0];
+       aabb.m_min[1] = myAabbMin[1];
+       aabb.m_min[2] = myAabbMin[2];
+       aabb.m_minIndices[3] = 0;
+
+       aabb.m_max[0] = myAabbMax[0];
+       aabb.m_max[1] = myAabbMax[1];
+       aabb.m_max[2] = myAabbMax[2];
+       aabb.m_signedMaxIndices[3] = 0;
+
+       m_data->m_localShapeAABBCPU->push_back(aabb);
+       //      m_data->m_localShapeAABBGPU->push_back(aabb);
+
+       b3OptimizedBvh* bvh = new b3OptimizedBvh();
+       //void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax)
+
+       bool useQuantizedAabbCompression = true;
+       b3TriangleIndexVertexArray* meshInterface = new b3TriangleIndexVertexArray();
+       m_data->m_meshInterfaces.push_back(meshInterface);
+       b3IndexedMesh mesh;
+       mesh.m_numTriangles = indices->size() / 3;
+       mesh.m_numVertices = vertices->size();
+       mesh.m_vertexBase = (const unsigned char*)&vertices->at(0).x;
+       mesh.m_vertexStride = sizeof(b3Vector3);
+       mesh.m_triangleIndexStride = 3 * sizeof(int);  // or sizeof(int)
+       mesh.m_triangleIndexBase = (const unsigned char*)&indices->at(0);
+
+       meshInterface->addIndexedMesh(mesh);
+       bvh->build(meshInterface, useQuantizedAabbCompression, (b3Vector3&)aabb.m_min, (b3Vector3&)aabb.m_max);
+       m_data->m_bvhData.push_back(bvh);
+       int numNodes = bvh->getQuantizedNodeArray().size();
+       //b3OpenCLArray<b3QuantizedBvhNode>*    treeNodesGPU = new b3OpenCLArray<b3QuantizedBvhNode>(this->m_context,this->m_queue,numNodes);
+       int numSubTrees = bvh->getSubtreeInfoArray().size();
+
+       b3BvhInfo bvhInfo;
+
+       bvhInfo.m_aabbMin = bvh->m_bvhAabbMin;
+       bvhInfo.m_aabbMax = bvh->m_bvhAabbMax;
+       bvhInfo.m_quantization = bvh->m_bvhQuantization;
+       bvhInfo.m_numNodes = numNodes;
+       bvhInfo.m_numSubTrees = numSubTrees;
+       bvhInfo.m_nodeOffset = m_data->m_treeNodesCPU.size();
+       bvhInfo.m_subTreeOffset = m_data->m_subTreesCPU.size();
+
+       m_data->m_bvhInfoCPU.push_back(bvhInfo);
+
+       int numNewSubtrees = bvh->getSubtreeInfoArray().size();
+       m_data->m_subTreesCPU.reserve(m_data->m_subTreesCPU.size() + numNewSubtrees);
+       for (int i = 0; i < numNewSubtrees; i++)
+       {
+               m_data->m_subTreesCPU.push_back(bvh->getSubtreeInfoArray()[i]);
+       }
+       int numNewTreeNodes = bvh->getQuantizedNodeArray().size();
+
+       for (int i = 0; i < numNewTreeNodes; i++)
+       {
+               m_data->m_treeNodesCPU.push_back(bvh->getQuantizedNodeArray()[i]);
+       }
+
+       return collidableIndex;
+}
+
+int b3GpuNarrowPhase::registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling1)
+{
+       b3Vector3 scaling = b3MakeVector3(scaling1[0], scaling1[1], scaling1[2]);
+
+       m_data->m_convexData->resize(m_data->m_numAcceleratedShapes + 1);
+       m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes + 1);
+
+       b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size() - 1);
+       convex.mC = b3MakeVector3(0, 0, 0);
+       convex.mE = b3MakeVector3(0, 0, 0);
+       convex.m_extents = b3MakeVector3(0, 0, 0);
+       convex.m_localCenter = b3MakeVector3(0, 0, 0);
+       convex.m_radius = 0.f;
+
+       convex.m_numUniqueEdges = 0;
+       int edgeOffset = m_data->m_uniqueEdges.size();
+       convex.m_uniqueEdgesOffset = edgeOffset;
+
+       int faceOffset = m_data->m_convexFaces.size();
+       convex.m_faceOffset = faceOffset;
+
+       convex.m_numFaces = indices->size() / 3;
+       m_data->m_convexFaces.resize(faceOffset + convex.m_numFaces);
+       m_data->m_convexIndices.reserve(convex.m_numFaces * 3);
+       for (int i = 0; i < convex.m_numFaces; i++)
+       {
+               if (i % 256 == 0)
+               {
+                       //printf("i=%d out of %d", i,convex.m_numFaces);
+               }
+               b3Vector3 vert0(vertices->at(indices->at(i * 3)) * scaling);
+               b3Vector3 vert1(vertices->at(indices->at(i * 3 + 1)) * scaling);
+               b3Vector3 vert2(vertices->at(indices->at(i * 3 + 2)) * scaling);
+
+               b3Vector3 normal = ((vert1 - vert0).cross(vert2 - vert0)).normalize();
+               b3Scalar c = -(normal.dot(vert0));
+
+               m_data->m_convexFaces[convex.m_faceOffset + i].m_plane = b3MakeVector4(normal.x, normal.y, normal.z, c);
+               int indexOffset = m_data->m_convexIndices.size();
+               int numIndices = 3;
+               m_data->m_convexFaces[convex.m_faceOffset + i].m_numIndices = numIndices;
+               m_data->m_convexFaces[convex.m_faceOffset + i].m_indexOffset = indexOffset;
+               m_data->m_convexIndices.resize(indexOffset + numIndices);
+               for (int p = 0; p < numIndices; p++)
+               {
+                       int vi = indices->at(i * 3 + p);
+                       m_data->m_convexIndices[indexOffset + p] = vi;  //convexPtr->m_faces[i].m_indices[p];
+               }
+       }
+
+       convex.m_numVertices = vertices->size();
+       int vertexOffset = m_data->m_convexVertices.size();
+       convex.m_vertexOffset = vertexOffset;
+       m_data->m_convexVertices.resize(vertexOffset + convex.m_numVertices);
+       for (int i = 0; i < vertices->size(); i++)
+       {
+               m_data->m_convexVertices[vertexOffset + i] = vertices->at(i) * scaling;
+       }
+
+       (*m_data->m_convexData)[m_data->m_numAcceleratedShapes] = 0;
+
+       return m_data->m_numAcceleratedShapes++;
+}
+
+cl_mem b3GpuNarrowPhase::getBodiesGpu()
+{
+       return (cl_mem)m_data->m_bodyBufferGPU->getBufferCL();
+}
+
+const struct b3RigidBodyData* b3GpuNarrowPhase::getBodiesCpu() const
+{
+       return &m_data->m_bodyBufferCPU->at(0);
+};
+
+int b3GpuNarrowPhase::getNumBodiesGpu() const
+{
+       return m_data->m_bodyBufferGPU->size();
+}
+
+cl_mem b3GpuNarrowPhase::getBodyInertiasGpu()
+{
+       return (cl_mem)m_data->m_inertiaBufferGPU->getBufferCL();
+}
+
+int b3GpuNarrowPhase::getNumBodyInertiasGpu() const
+{
+       return m_data->m_inertiaBufferGPU->size();
+}
+
+b3Collidable& b3GpuNarrowPhase::getCollidableCpu(int collidableIndex)
+{
+       return m_data->m_collidablesCPU[collidableIndex];
+}
+
+const b3Collidable& b3GpuNarrowPhase::getCollidableCpu(int collidableIndex) const
+{
+       return m_data->m_collidablesCPU[collidableIndex];
+}
+
+cl_mem b3GpuNarrowPhase::getCollidablesGpu()
+{
+       return m_data->m_collidablesGPU->getBufferCL();
+}
+
+const struct b3Collidable* b3GpuNarrowPhase::getCollidablesCpu() const
+{
+       if (m_data->m_collidablesCPU.size())
+               return &m_data->m_collidablesCPU[0];
+       return 0;
+}
+
+const struct b3SapAabb* b3GpuNarrowPhase::getLocalSpaceAabbsCpu() const
+{
+       if (m_data->m_localShapeAABBCPU->size())
+       {
+               return &m_data->m_localShapeAABBCPU->at(0);
+       }
+       return 0;
+}
+
+cl_mem b3GpuNarrowPhase::getAabbLocalSpaceBufferGpu()
+{
+       return m_data->m_localShapeAABBGPU->getBufferCL();
+}
+int b3GpuNarrowPhase::getNumCollidablesGpu() const
+{
+       return m_data->m_collidablesGPU->size();
+}
+
+int b3GpuNarrowPhase::getNumContactsGpu() const
+{
+       return m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->size();
+}
+cl_mem b3GpuNarrowPhase::getContactsGpu()
+{
+       return m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->getBufferCL();
+}
+
+const b3Contact4* b3GpuNarrowPhase::getContactsCPU() const
+{
+       m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->copyToHost(*m_data->m_pBufContactOutCPU);
+       return &m_data->m_pBufContactOutCPU->at(0);
+}
+
+void b3GpuNarrowPhase::computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects)
+{
+       cl_mem aabbsLocalSpace = m_data->m_localShapeAABBGPU->getBufferCL();
+
+       int nContactOut = 0;
+
+       //swap buffer
+       m_data->m_currentContactBuffer = 1 - m_data->m_currentContactBuffer;
+
+       //int curSize = m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->size();
+
+       int maxTriConvexPairCapacity = m_data->m_config.m_maxTriConvexPairCapacity;
+       int numTriConvexPairsOut = 0;
+
+       b3OpenCLArray<b3Int4> broadphasePairsGPU(m_context, m_queue);
+       broadphasePairsGPU.setFromOpenCLBuffer(broadphasePairs, numBroadphasePairs);
+
+       b3OpenCLArray<b3Aabb> clAabbArrayWorldSpace(this->m_context, this->m_queue);
+       clAabbArrayWorldSpace.setFromOpenCLBuffer(aabbsWorldSpace, numObjects);
+
+       b3OpenCLArray<b3Aabb> clAabbArrayLocalSpace(this->m_context, this->m_queue);
+       clAabbArrayLocalSpace.setFromOpenCLBuffer(aabbsLocalSpace, numObjects);
+
+       m_data->m_gpuSatCollision->computeConvexConvexContactsGPUSAT(
+               &broadphasePairsGPU, numBroadphasePairs,
+               m_data->m_bodyBufferGPU,
+               m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer],
+               nContactOut,
+               m_data->m_pBufContactBuffersGPU[1 - m_data->m_currentContactBuffer],
+               m_data->m_config.m_maxContactCapacity,
+               m_data->m_config.m_compoundPairCapacity,
+               *m_data->m_convexPolyhedraGPU,
+               *m_data->m_convexVerticesGPU,
+               *m_data->m_uniqueEdgesGPU,
+               *m_data->m_convexFacesGPU,
+               *m_data->m_convexIndicesGPU,
+               *m_data->m_collidablesGPU,
+               *m_data->m_gpuChildShapes,
+               clAabbArrayWorldSpace,
+               clAabbArrayLocalSpace,
+               *m_data->m_worldVertsB1GPU,
+               *m_data->m_clippingFacesOutGPU,
+               *m_data->m_worldNormalsAGPU,
+               *m_data->m_worldVertsA1GPU,
+               *m_data->m_worldVertsB2GPU,
+               m_data->m_bvhData,
+               m_data->m_treeNodesGPU,
+               m_data->m_subTreesGPU,
+               m_data->m_bvhInfoGPU,
+               numObjects,
+               maxTriConvexPairCapacity,
+               *m_data->m_triangleConvexPairs,
+               numTriConvexPairsOut);
+
+       /*b3AlignedObjectArray<b3Int4> broadphasePairsCPU;
+       broadphasePairsGPU.copyToHost(broadphasePairsCPU);
+       printf("checking pairs\n");
+       */
+}
+
+const b3SapAabb& b3GpuNarrowPhase::getLocalSpaceAabb(int collidableIndex) const
+{
+       return m_data->m_localShapeAABBCPU->at(collidableIndex);
+}
+
+int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMinPtr, const float* aabbMaxPtr, bool writeToGpu)
+{
+       b3Vector3 aabbMin = b3MakeVector3(aabbMinPtr[0], aabbMinPtr[1], aabbMinPtr[2]);
+       b3Vector3 aabbMax = b3MakeVector3(aabbMaxPtr[0], aabbMaxPtr[1], aabbMaxPtr[2]);
+
+       if (m_data->m_numAcceleratedRigidBodies >= (m_data->m_config.m_maxConvexBodies))
+       {
+               b3Error("registerRigidBody: exceeding the number of rigid bodies, %d > %d \n", m_data->m_numAcceleratedRigidBodies, m_data->m_config.m_maxConvexBodies);
+               return -1;
+       }
+
+       m_data->m_bodyBufferCPU->resize(m_data->m_numAcceleratedRigidBodies + 1);
+
+       b3RigidBodyData& body = m_data->m_bodyBufferCPU->at(m_data->m_numAcceleratedRigidBodies);
+
+       float friction = 1.f;
+       float restitution = 0.f;
+
+       body.m_frictionCoeff = friction;
+       body.m_restituitionCoeff = restitution;
+       body.m_angVel = b3MakeVector3(0, 0, 0);
+       body.m_linVel = b3MakeVector3(0, 0, 0);  //.setZero();
+       body.m_pos = b3MakeVector3(position[0], position[1], position[2]);
+       body.m_quat.setValue(orientation[0], orientation[1], orientation[2], orientation[3]);
+       body.m_collidableIdx = collidableIndex;
+       if (collidableIndex >= 0)
+       {
+               //              body.m_shapeType = m_data->m_collidablesCPU.at(collidableIndex).m_shapeType;
+       }
+       else
+       {
+               //      body.m_shapeType = CollisionShape::SHAPE_PLANE;
+               m_planeBodyIndex = m_data->m_numAcceleratedRigidBodies;
+       }
+       //body.m_shapeType = shapeType;
+
+       body.m_invMass = mass ? 1.f / mass : 0.f;
+
+       if (writeToGpu)
+       {
+               m_data->m_bodyBufferGPU->copyFromHostPointer(&body, 1, m_data->m_numAcceleratedRigidBodies);
+       }
+
+       b3InertiaData& shapeInfo = m_data->m_inertiaBufferCPU->at(m_data->m_numAcceleratedRigidBodies);
+
+       if (mass == 0.f)
+       {
+               if (m_data->m_numAcceleratedRigidBodies == 0)
+                       m_static0Index = 0;
+
+               shapeInfo.m_initInvInertia.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+               shapeInfo.m_invInertiaWorld.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+       }
+       else
+       {
+               b3Assert(body.m_collidableIdx >= 0);
+
+               //approximate using the aabb of the shape
+
+               //Aabb aabb = (*m_data->m_shapePointers)[shapeIndex]->m_aabb;
+               b3Vector3 halfExtents = (aabbMax - aabbMin);  //*0.5f;//fake larger inertia makes demos more stable ;-)
+
+               b3Vector3 localInertia;
+
+               float lx = 2.f * halfExtents[0];
+               float ly = 2.f * halfExtents[1];
+               float lz = 2.f * halfExtents[2];
+
+               localInertia.setValue((mass / 12.0f) * (ly * ly + lz * lz),
+                                                         (mass / 12.0f) * (lx * lx + lz * lz),
+                                                         (mass / 12.0f) * (lx * lx + ly * ly));
+
+               b3Vector3 invLocalInertia;
+               invLocalInertia[0] = 1.f / localInertia[0];
+               invLocalInertia[1] = 1.f / localInertia[1];
+               invLocalInertia[2] = 1.f / localInertia[2];
+               invLocalInertia[3] = 0.f;
+
+               shapeInfo.m_initInvInertia.setValue(
+                       invLocalInertia[0], 0, 0,
+                       0, invLocalInertia[1], 0,
+                       0, 0, invLocalInertia[2]);
+
+               b3Matrix3x3 m(body.m_quat);
+
+               shapeInfo.m_invInertiaWorld = m.scaled(invLocalInertia) * m.transpose();
+       }
+
+       if (writeToGpu)
+               m_data->m_inertiaBufferGPU->copyFromHostPointer(&shapeInfo, 1, m_data->m_numAcceleratedRigidBodies);
+
+       return m_data->m_numAcceleratedRigidBodies++;
+}
+
+int b3GpuNarrowPhase::getNumRigidBodies() const
+{
+       return m_data->m_numAcceleratedRigidBodies;
+}
+
+void b3GpuNarrowPhase::writeAllBodiesToGpu()
+{
+       if (m_data->m_localShapeAABBCPU->size())
+       {
+               m_data->m_localShapeAABBGPU->copyFromHost(*m_data->m_localShapeAABBCPU);
+       }
+
+       m_data->m_gpuChildShapes->copyFromHost(m_data->m_cpuChildShapes);
+       m_data->m_convexFacesGPU->copyFromHost(m_data->m_convexFaces);
+       m_data->m_convexPolyhedraGPU->copyFromHost(m_data->m_convexPolyhedra);
+       m_data->m_uniqueEdgesGPU->copyFromHost(m_data->m_uniqueEdges);
+       m_data->m_convexVerticesGPU->copyFromHost(m_data->m_convexVertices);
+       m_data->m_convexIndicesGPU->copyFromHost(m_data->m_convexIndices);
+       m_data->m_bvhInfoGPU->copyFromHost(m_data->m_bvhInfoCPU);
+       m_data->m_treeNodesGPU->copyFromHost(m_data->m_treeNodesCPU);
+       m_data->m_subTreesGPU->copyFromHost(m_data->m_subTreesCPU);
+
+       m_data->m_bodyBufferGPU->resize(m_data->m_numAcceleratedRigidBodies);
+       m_data->m_inertiaBufferGPU->resize(m_data->m_numAcceleratedRigidBodies);
+
+       if (m_data->m_numAcceleratedRigidBodies)
+       {
+               m_data->m_bodyBufferGPU->copyFromHostPointer(&m_data->m_bodyBufferCPU->at(0), m_data->m_numAcceleratedRigidBodies);
+               m_data->m_inertiaBufferGPU->copyFromHostPointer(&m_data->m_inertiaBufferCPU->at(0), m_data->m_numAcceleratedRigidBodies);
+       }
+       if (m_data->m_collidablesCPU.size())
+       {
+               m_data->m_collidablesGPU->copyFromHost(m_data->m_collidablesCPU);
+       }
+}
+
+void b3GpuNarrowPhase::reset()
+{
+       m_data->m_numAcceleratedShapes = 0;
+       m_data->m_numAcceleratedRigidBodies = 0;
+       this->m_static0Index = -1;
+       m_data->m_uniqueEdges.resize(0);
+       m_data->m_convexVertices.resize(0);
+       m_data->m_convexPolyhedra.resize(0);
+       m_data->m_convexIndices.resize(0);
+       m_data->m_cpuChildShapes.resize(0);
+       m_data->m_convexFaces.resize(0);
+       m_data->m_collidablesCPU.resize(0);
+       m_data->m_localShapeAABBCPU->resize(0);
+       m_data->m_bvhData.resize(0);
+       m_data->m_treeNodesCPU.resize(0);
+       m_data->m_subTreesCPU.resize(0);
+       m_data->m_bvhInfoCPU.resize(0);
+}
+
+void b3GpuNarrowPhase::readbackAllBodiesToCpu()
+{
+       m_data->m_bodyBufferGPU->copyToHostPointer(&m_data->m_bodyBufferCPU->at(0), m_data->m_numAcceleratedRigidBodies);
+}
+
+void b3GpuNarrowPhase::setObjectTransformCpu(float* position, float* orientation, int bodyIndex)
+{
+       if (bodyIndex >= 0 && bodyIndex < m_data->m_bodyBufferCPU->size())
+       {
+               m_data->m_bodyBufferCPU->at(bodyIndex).m_pos = b3MakeVector3(position[0], position[1], position[2]);
+               m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.setValue(orientation[0], orientation[1], orientation[2], orientation[3]);
+       }
+       else
+       {
+               b3Warning("setObjectVelocityCpu out of range.\n");
+       }
+}
+void b3GpuNarrowPhase::setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex)
+{
+       if (bodyIndex >= 0 && bodyIndex < m_data->m_bodyBufferCPU->size())
+       {
+               m_data->m_bodyBufferCPU->at(bodyIndex).m_linVel = b3MakeVector3(linVel[0], linVel[1], linVel[2]);
+               m_data->m_bodyBufferCPU->at(bodyIndex).m_angVel = b3MakeVector3(angVel[0], angVel[1], angVel[2]);
+       }
+       else
+       {
+               b3Warning("setObjectVelocityCpu out of range.\n");
+       }
+}
+
+bool b3GpuNarrowPhase::getObjectTransformFromCpu(float* position, float* orientation, int bodyIndex) const
+{
+       if (bodyIndex >= 0 && bodyIndex < m_data->m_bodyBufferCPU->size())
+       {
+               position[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.x;
+               position[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.y;
+               position[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.z;
+               position[3] = 1.f;  //or 1
+
+               orientation[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.x;
+               orientation[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.y;
+               orientation[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.z;
+               orientation[3] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.w;
+               return true;
+       }
+
+       b3Warning("getObjectTransformFromCpu out of range.\n");
+       return false;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h
new file mode 100644 (file)
index 0000000..21a68de
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef B3_GPU_NARROWPHASE_H
+#define B3_GPU_NARROWPHASE_H
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Vector3.h"
+
+class b3GpuNarrowPhase
+{
+protected:
+       struct b3GpuNarrowPhaseInternalData* m_data;
+       int m_acceleratedCompanionShapeIndex;
+       int m_planeBodyIndex;
+       int m_static0Index;
+
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_queue;
+
+       int registerConvexHullShapeInternal(class b3ConvexUtility* convexPtr, b3Collidable& col);
+       int registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling);
+
+public:
+       b3GpuNarrowPhase(cl_context vtx, cl_device_id dev, cl_command_queue q, const struct b3Config& config);
+
+       virtual ~b3GpuNarrowPhase(void);
+
+       int registerSphereShape(float radius);
+       int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
+
+       int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
+       int registerFace(const b3Vector3& faceNormal, float faceConstant);
+
+       int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
+
+       //do they need to be merged?
+
+       int registerConvexHullShape(b3ConvexUtility* utilPtr);
+       int registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
+
+       int registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMin, const float* aabbMax, bool writeToGpu);
+       void setObjectTransform(const float* position, const float* orientation, int bodyIndex);
+
+       void writeAllBodiesToGpu();
+       void reset();
+       void readbackAllBodiesToCpu();
+       bool getObjectTransformFromCpu(float* position, float* orientation, int bodyIndex) const;
+
+       void setObjectTransformCpu(float* position, float* orientation, int bodyIndex);
+       void setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex);
+
+       virtual void computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects);
+
+       cl_mem getBodiesGpu();
+       const struct b3RigidBodyData* getBodiesCpu() const;
+       //struct b3RigidBodyData* getBodiesCpu();
+
+       int getNumBodiesGpu() const;
+
+       cl_mem getBodyInertiasGpu();
+       int getNumBodyInertiasGpu() const;
+
+       cl_mem getCollidablesGpu();
+       const struct b3Collidable* getCollidablesCpu() const;
+       int getNumCollidablesGpu() const;
+
+       const struct b3SapAabb* getLocalSpaceAabbsCpu() const;
+
+       const struct b3Contact4* getContactsCPU() const;
+
+       cl_mem getContactsGpu();
+       int getNumContactsGpu() const;
+
+       cl_mem getAabbLocalSpaceBufferGpu();
+
+       int getNumRigidBodies() const;
+
+       int allocateCollidable();
+
+       int getStatic0Index() const
+       {
+               return m_static0Index;
+       }
+       b3Collidable& getCollidableCpu(int collidableIndex);
+       const b3Collidable& getCollidableCpu(int collidableIndex) const;
+
+       const b3GpuNarrowPhaseInternalData* getInternalData() const
+       {
+               return m_data;
+       }
+
+       b3GpuNarrowPhaseInternalData* getInternalData()
+       {
+               return m_data;
+       }
+
+       const struct b3SapAabb& getLocalSpaceAabb(int collidableIndex) const;
+};
+
+#endif  //B3_GPU_NARROWPHASE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h
new file mode 100644 (file)
index 0000000..716a5ea
--- /dev/null
@@ -0,0 +1,89 @@
+
+#ifndef B3_GPU_NARROWPHASE_INTERNAL_DATA_H
+#define B3_GPU_NARROWPHASE_INTERNAL_DATA_H
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3Vector3.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
+
+#include "Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h"
+#include "Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h"
+#include "Bullet3Common/shared/b3Int4.h"
+#include "Bullet3Common/shared/b3Int2.h"
+
+class b3ConvexUtility;
+
+struct b3GpuNarrowPhaseInternalData
+{
+       b3AlignedObjectArray<b3ConvexUtility*>* m_convexData;
+
+       b3AlignedObjectArray<b3ConvexPolyhedronData> m_convexPolyhedra;
+       b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
+       b3AlignedObjectArray<b3Vector3> m_convexVertices;
+       b3AlignedObjectArray<int> m_convexIndices;
+
+       b3OpenCLArray<b3ConvexPolyhedronData>* m_convexPolyhedraGPU;
+       b3OpenCLArray<b3Vector3>* m_uniqueEdgesGPU;
+       b3OpenCLArray<b3Vector3>* m_convexVerticesGPU;
+       b3OpenCLArray<int>* m_convexIndicesGPU;
+
+       b3OpenCLArray<b3Vector3>* m_worldVertsB1GPU;
+       b3OpenCLArray<b3Int4>* m_clippingFacesOutGPU;
+       b3OpenCLArray<b3Vector3>* m_worldNormalsAGPU;
+       b3OpenCLArray<b3Vector3>* m_worldVertsA1GPU;
+       b3OpenCLArray<b3Vector3>* m_worldVertsB2GPU;
+
+       b3AlignedObjectArray<b3GpuChildShape> m_cpuChildShapes;
+       b3OpenCLArray<b3GpuChildShape>* m_gpuChildShapes;
+
+       b3AlignedObjectArray<b3GpuFace> m_convexFaces;
+       b3OpenCLArray<b3GpuFace>* m_convexFacesGPU;
+
+       struct GpuSatCollision* m_gpuSatCollision;
+
+       b3OpenCLArray<b3Int4>* m_triangleConvexPairs;
+
+       b3OpenCLArray<b3Contact4>* m_pBufContactBuffersGPU[2];
+       int m_currentContactBuffer;
+       b3AlignedObjectArray<b3Contact4>* m_pBufContactOutCPU;
+
+       b3AlignedObjectArray<b3RigidBodyData>* m_bodyBufferCPU;
+       b3OpenCLArray<b3RigidBodyData>* m_bodyBufferGPU;
+
+       b3AlignedObjectArray<b3InertiaData>* m_inertiaBufferCPU;
+       b3OpenCLArray<b3InertiaData>* m_inertiaBufferGPU;
+
+       int m_numAcceleratedShapes;
+       int m_numAcceleratedRigidBodies;
+
+       b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
+       b3OpenCLArray<b3Collidable>* m_collidablesGPU;
+
+       b3OpenCLArray<b3SapAabb>* m_localShapeAABBGPU;
+       b3AlignedObjectArray<b3SapAabb>* m_localShapeAABBCPU;
+
+       b3AlignedObjectArray<class b3OptimizedBvh*> m_bvhData;
+       b3AlignedObjectArray<class b3TriangleIndexVertexArray*> m_meshInterfaces;
+
+       b3AlignedObjectArray<b3QuantizedBvhNode> m_treeNodesCPU;
+       b3AlignedObjectArray<b3BvhSubtreeInfo> m_subTreesCPU;
+
+       b3AlignedObjectArray<b3BvhInfo> m_bvhInfoCPU;
+       b3OpenCLArray<b3BvhInfo>* m_bvhInfoGPU;
+
+       b3OpenCLArray<b3QuantizedBvhNode>* m_treeNodesGPU;
+       b3OpenCLArray<b3BvhSubtreeInfo>* m_subTreesGPU;
+
+       b3Config m_config;
+};
+
+#endif  //B3_GPU_NARROWPHASE_INTERNAL_DATA_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp
new file mode 100644 (file)
index 0000000..bd9d6bb
--- /dev/null
@@ -0,0 +1,1068 @@
+
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+bool useGpuInitSolverBodies = true;
+bool useGpuInfo1 = true;
+bool useGpuInfo2 = true;
+bool useGpuSolveJointConstraintRows = true;
+bool useGpuWriteBackVelocities = true;
+bool gpuBreakConstraints = true;
+
+#include "b3GpuPgsConstraintSolver.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
+#include <new>
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include <string.h>  //for memset
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
+
+#include "Bullet3OpenCL/RigidBody/kernels/jointSolver.h"  //solveConstraintRowsCL
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+
+#define B3_JOINT_SOLVER_PATH "src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl"
+
+struct b3GpuPgsJacobiSolverInternalData
+{
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_queue;
+
+       b3PrefixScanCL* m_prefixScan;
+
+       cl_kernel m_solveJointConstraintRowsKernels;
+       cl_kernel m_initSolverBodiesKernel;
+       cl_kernel m_getInfo1Kernel;
+       cl_kernel m_initBatchConstraintsKernel;
+       cl_kernel m_getInfo2Kernel;
+       cl_kernel m_writeBackVelocitiesKernel;
+       cl_kernel m_breakViolatedConstraintsKernel;
+
+       b3OpenCLArray<unsigned int>* m_gpuConstraintRowOffsets;
+
+       b3OpenCLArray<b3GpuSolverBody>* m_gpuSolverBodies;
+       b3OpenCLArray<b3BatchConstraint>* m_gpuBatchConstraints;
+       b3OpenCLArray<b3GpuSolverConstraint>* m_gpuConstraintRows;
+       b3OpenCLArray<unsigned int>* m_gpuConstraintInfo1;
+
+       //      b3AlignedObjectArray<b3GpuSolverBody>           m_cpuSolverBodies;
+       b3AlignedObjectArray<b3BatchConstraint> m_cpuBatchConstraints;
+       b3AlignedObjectArray<b3GpuSolverConstraint> m_cpuConstraintRows;
+       b3AlignedObjectArray<unsigned int> m_cpuConstraintInfo1;
+       b3AlignedObjectArray<unsigned int> m_cpuConstraintRowOffsets;
+
+       b3AlignedObjectArray<b3RigidBodyData> m_cpuBodies;
+       b3AlignedObjectArray<b3InertiaData> m_cpuInertias;
+
+       b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
+
+       b3AlignedObjectArray<int> m_batchSizes;
+};
+
+/*
+static b3Transform     getWorldTransform(b3RigidBodyData* rb)
+{
+       b3Transform newTrans;
+       newTrans.setOrigin(rb->m_pos);
+       newTrans.setRotation(rb->m_quat);
+       return newTrans;
+}
+
+static const b3Matrix3x3&      getInvInertiaTensorWorld(b3InertiaData* inertia)
+{
+       return inertia->m_invInertiaWorld;
+}
+
+*/
+
+static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
+{
+       return rb->m_linVel;
+}
+
+static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
+{
+       return rb->m_angVel;
+}
+
+b3Vector3 getVelocityInLocalPoint(b3RigidBodyData* rb, const b3Vector3& rel_pos)
+{
+       //we also calculate lin/ang velocity for kinematic objects
+       return getLinearVelocity(rb) + getAngularVelocity(rb).cross(rel_pos);
+}
+
+b3GpuPgsConstraintSolver::b3GpuPgsConstraintSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, bool usePgs)
+{
+       m_usePgs = usePgs;
+       m_gpuData = new b3GpuPgsJacobiSolverInternalData();
+       m_gpuData->m_context = ctx;
+       m_gpuData->m_device = device;
+       m_gpuData->m_queue = queue;
+
+       m_gpuData->m_prefixScan = new b3PrefixScanCL(ctx, device, queue);
+
+       m_gpuData->m_gpuConstraintRowOffsets = new b3OpenCLArray<unsigned int>(m_gpuData->m_context, m_gpuData->m_queue);
+
+       m_gpuData->m_gpuSolverBodies = new b3OpenCLArray<b3GpuSolverBody>(m_gpuData->m_context, m_gpuData->m_queue);
+       m_gpuData->m_gpuBatchConstraints = new b3OpenCLArray<b3BatchConstraint>(m_gpuData->m_context, m_gpuData->m_queue);
+       m_gpuData->m_gpuConstraintRows = new b3OpenCLArray<b3GpuSolverConstraint>(m_gpuData->m_context, m_gpuData->m_queue);
+       m_gpuData->m_gpuConstraintInfo1 = new b3OpenCLArray<unsigned int>(m_gpuData->m_context, m_gpuData->m_queue);
+       cl_int errNum = 0;
+
+       {
+               cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, &errNum, "", B3_JOINT_SOLVER_PATH);
+               //cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context,m_gpuData->m_device,0,&errNum,"",B3_JOINT_SOLVER_PATH,true);
+               b3Assert(errNum == CL_SUCCESS);
+               m_gpuData->m_solveJointConstraintRowsKernels = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "solveJointConstraintRows", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+               m_gpuData->m_initSolverBodiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "initSolverBodies", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+               m_gpuData->m_getInfo1Kernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "getInfo1Kernel", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+               m_gpuData->m_initBatchConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "initBatchConstraintsKernel", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+               m_gpuData->m_getInfo2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "getInfo2Kernel", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+               m_gpuData->m_writeBackVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "writeBackVelocitiesKernel", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+               m_gpuData->m_breakViolatedConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "breakViolatedConstraintsKernel", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+
+               clReleaseProgram(prog);
+       }
+}
+
+b3GpuPgsConstraintSolver::~b3GpuPgsConstraintSolver()
+{
+       clReleaseKernel(m_gpuData->m_solveJointConstraintRowsKernels);
+       clReleaseKernel(m_gpuData->m_initSolverBodiesKernel);
+       clReleaseKernel(m_gpuData->m_getInfo1Kernel);
+       clReleaseKernel(m_gpuData->m_initBatchConstraintsKernel);
+       clReleaseKernel(m_gpuData->m_getInfo2Kernel);
+       clReleaseKernel(m_gpuData->m_writeBackVelocitiesKernel);
+       clReleaseKernel(m_gpuData->m_breakViolatedConstraintsKernel);
+
+       delete m_gpuData->m_prefixScan;
+       delete m_gpuData->m_gpuConstraintRowOffsets;
+       delete m_gpuData->m_gpuSolverBodies;
+       delete m_gpuData->m_gpuBatchConstraints;
+       delete m_gpuData->m_gpuConstraintRows;
+       delete m_gpuData->m_gpuConstraintInfo1;
+
+       delete m_gpuData;
+}
+
+struct b3BatchConstraint
+{
+       int m_bodyAPtrAndSignBit;
+       int m_bodyBPtrAndSignBit;
+       int m_originalConstraintIndex;
+       int m_batchId;
+};
+
+static b3AlignedObjectArray<b3BatchConstraint> batchConstraints;
+
+void b3GpuPgsConstraintSolver::recomputeBatches()
+{
+       m_gpuData->m_batchSizes.clear();
+}
+
+b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
+{
+       B3_PROFILE("GPU solveGroupCacheFriendlySetup");
+       batchConstraints.resize(numConstraints);
+       m_gpuData->m_gpuBatchConstraints->resize(numConstraints);
+       m_staticIdx = -1;
+       m_maxOverrideNumSolverIterations = 0;
+
+       /*      m_gpuData->m_gpuBodies->resize(numBodies);
+       m_gpuData->m_gpuBodies->copyFromHostPointer(bodies,numBodies);
+
+       b3OpenCLArray<b3InertiaData> gpuInertias(m_gpuData->m_context,m_gpuData->m_queue);
+       gpuInertias.resize(numBodies);
+       gpuInertias.copyFromHostPointer(inertias,numBodies);
+       */
+
+       m_gpuData->m_gpuSolverBodies->resize(numBodies);
+
+       m_tmpSolverBodyPool.resize(numBodies);
+       {
+               if (useGpuInitSolverBodies)
+               {
+                       B3_PROFILE("m_initSolverBodiesKernel");
+
+                       b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_initSolverBodiesKernel, "m_initSolverBodiesKernel");
+                       launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
+                       launcher.setBuffer(gpuBodies->getBufferCL());
+                       launcher.setConst(numBodies);
+                       launcher.launch1D(numBodies);
+                       clFinish(m_gpuData->m_queue);
+
+                       //                      m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+               }
+               else
+               {
+                       gpuBodies->copyToHost(m_gpuData->m_cpuBodies);
+                       for (int i = 0; i < numBodies; i++)
+                       {
+                               b3RigidBodyData& body = m_gpuData->m_cpuBodies[i];
+                               b3GpuSolverBody& solverBody = m_tmpSolverBodyPool[i];
+                               initSolverBody(i, &solverBody, &body);
+                               solverBody.m_originalBodyIndex = i;
+                       }
+                       m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
+               }
+       }
+
+       //      int totalBodies = 0;
+       int totalNumRows = 0;
+       //b3RigidBody* rb0=0,*rb1=0;
+       //if (1)
+       {
+               {
+                       //                      int i;
+
+                       m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
+
+                       //                      b3OpenCLArray<b3GpuGenericConstraint> gpuConstraints(m_gpuData->m_context,m_gpuData->m_queue);
+
+                       if (useGpuInfo1)
+                       {
+                               B3_PROFILE("info1 and init batchConstraint");
+
+                               m_gpuData->m_gpuConstraintInfo1->resize(numConstraints);
+
+                               if (1)
+                               {
+                                       B3_PROFILE("getInfo1Kernel");
+
+                                       b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_getInfo1Kernel, "m_getInfo1Kernel");
+                                       launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+                                       launcher.setBuffer(gpuConstraints->getBufferCL());
+                                       launcher.setConst(numConstraints);
+                                       launcher.launch1D(numConstraints);
+                                       clFinish(m_gpuData->m_queue);
+                               }
+
+                               if (m_gpuData->m_batchSizes.size() == 0)
+                               {
+                                       B3_PROFILE("initBatchConstraintsKernel");
+
+                                       m_gpuData->m_gpuConstraintRowOffsets->resize(numConstraints);
+                                       unsigned int total = 0;
+                                       m_gpuData->m_prefixScan->execute(*m_gpuData->m_gpuConstraintInfo1, *m_gpuData->m_gpuConstraintRowOffsets, numConstraints, &total);
+                                       unsigned int lastElem = m_gpuData->m_gpuConstraintInfo1->at(numConstraints - 1);
+                                       totalNumRows = total + lastElem;
+
+                                       {
+                                               B3_PROFILE("init batch constraints");
+                                               b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_initBatchConstraintsKernel, "m_initBatchConstraintsKernel");
+                                               launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+                                               launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
+                                               launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
+                                               launcher.setBuffer(gpuConstraints->getBufferCL());
+                                               launcher.setBuffer(gpuBodies->getBufferCL());
+                                               launcher.setConst(numConstraints);
+                                               launcher.launch1D(numConstraints);
+                                               clFinish(m_gpuData->m_queue);
+                                       }
+                                       //assume the batching happens on CPU, so copy the data
+                                       m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+                               }
+                       }
+                       else
+                       {
+                               totalNumRows = 0;
+                               gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
+                               //calculate the total number of contraint rows
+                               for (int i = 0; i < numConstraints; i++)
+                               {
+                                       unsigned int& info1 = m_tmpConstraintSizesPool[i];
+                                       //                                      unsigned int info1;
+                                       if (m_gpuData->m_cpuConstraints[i].isEnabled())
+                                       {
+                                               m_gpuData->m_cpuConstraints[i].getInfo1(&info1, &m_gpuData->m_cpuBodies[0]);
+                                       }
+                                       else
+                                       {
+                                               info1 = 0;
+                                       }
+
+                                       totalNumRows += info1;
+                               }
+
+                               m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
+                               m_gpuData->m_gpuConstraintInfo1->copyFromHost(m_tmpConstraintSizesPool);
+                       }
+                       m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
+                       m_gpuData->m_gpuConstraintRows->resize(totalNumRows);
+
+                       //                      b3GpuConstraintArray            verify;
+
+                       if (useGpuInfo2)
+                       {
+                               {
+                                       B3_PROFILE("getInfo2Kernel");
+                                       b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_getInfo2Kernel, "m_getInfo2Kernel");
+                                       launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
+                                       launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+                                       launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
+                                       launcher.setBuffer(gpuConstraints->getBufferCL());
+                                       launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
+                                       launcher.setBuffer(gpuBodies->getBufferCL());
+                                       launcher.setBuffer(gpuInertias->getBufferCL());
+                                       launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
+                                       launcher.setConst(infoGlobal.m_timeStep);
+                                       launcher.setConst(infoGlobal.m_erp);
+                                       launcher.setConst(infoGlobal.m_globalCfm);
+                                       launcher.setConst(infoGlobal.m_damping);
+                                       launcher.setConst(infoGlobal.m_numIterations);
+                                       launcher.setConst(numConstraints);
+                                       launcher.launch1D(numConstraints);
+                                       clFinish(m_gpuData->m_queue);
+
+                                       if (m_gpuData->m_batchSizes.size() == 0)
+                                               m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+                                       //m_gpuData->m_gpuConstraintRows->copyToHost(verify);
+                                       //m_gpuData->m_gpuConstraintRows->copyToHost(m_tmpSolverNonContactConstraintPool);
+                               }
+                       }
+                       else
+                       {
+                               gpuInertias->copyToHost(m_gpuData->m_cpuInertias);
+
+                               ///setup the b3SolverConstraints
+
+                               for (int i = 0; i < numConstraints; i++)
+                               {
+                                       const int& info1 = m_tmpConstraintSizesPool[i];
+
+                                       if (info1)
+                                       {
+                                               int constraintIndex = batchConstraints[i].m_originalConstraintIndex;
+                                               int constraintRowOffset = m_gpuData->m_cpuConstraintRowOffsets[constraintIndex];
+
+                                               b3GpuSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[constraintRowOffset];
+                                               b3GpuGenericConstraint& constraint = m_gpuData->m_cpuConstraints[i];
+
+                                               b3RigidBodyData& rbA = m_gpuData->m_cpuBodies[constraint.getRigidBodyA()];
+                                               //b3RigidBody& rbA = constraint.getRigidBodyA();
+                                               //                              b3RigidBody& rbB = constraint.getRigidBodyB();
+                                               b3RigidBodyData& rbB = m_gpuData->m_cpuBodies[constraint.getRigidBodyB()];
+
+                                               int solverBodyIdA = constraint.getRigidBodyA();  //getOrInitSolverBody(constraint.getRigidBodyA(),bodies,inertias);
+                                               int solverBodyIdB = constraint.getRigidBodyB();  //getOrInitSolverBody(constraint.getRigidBodyB(),bodies,inertias);
+
+                                               b3GpuSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+                                               b3GpuSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
+
+                                               if (rbA.m_invMass)
+                                               {
+                                                       batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;
+                                               }
+                                               else
+                                               {
+                                                       if (!solverBodyIdA)
+                                                               m_staticIdx = 0;
+                                                       batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;
+                                               }
+
+                                               if (rbB.m_invMass)
+                                               {
+                                                       batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;
+                                               }
+                                               else
+                                               {
+                                                       if (!solverBodyIdB)
+                                                               m_staticIdx = 0;
+                                                       batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;
+                                               }
+
+                                               int overrideNumSolverIterations = 0;  //constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
+                                               if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
+                                                       m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
+
+                                               int j;
+                                               for (j = 0; j < info1; j++)
+                                               {
+                                                       memset(&currentConstraintRow[j], 0, sizeof(b3GpuSolverConstraint));
+                                                       currentConstraintRow[j].m_angularComponentA.setValue(0, 0, 0);
+                                                       currentConstraintRow[j].m_angularComponentB.setValue(0, 0, 0);
+                                                       currentConstraintRow[j].m_appliedImpulse = 0.f;
+                                                       currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+                                                       currentConstraintRow[j].m_cfm = 0.f;
+                                                       currentConstraintRow[j].m_contactNormal.setValue(0, 0, 0);
+                                                       currentConstraintRow[j].m_friction = 0.f;
+                                                       currentConstraintRow[j].m_frictionIndex = 0;
+                                                       currentConstraintRow[j].m_jacDiagABInv = 0.f;
+                                                       currentConstraintRow[j].m_lowerLimit = 0.f;
+                                                       currentConstraintRow[j].m_upperLimit = 0.f;
+
+                                                       currentConstraintRow[j].m_originalContactPoint = 0;
+                                                       currentConstraintRow[j].m_overrideNumSolverIterations = 0;
+                                                       currentConstraintRow[j].m_relpos1CrossNormal.setValue(0, 0, 0);
+                                                       currentConstraintRow[j].m_relpos2CrossNormal.setValue(0, 0, 0);
+                                                       currentConstraintRow[j].m_rhs = 0.f;
+                                                       currentConstraintRow[j].m_rhsPenetration = 0.f;
+                                                       currentConstraintRow[j].m_solverBodyIdA = 0;
+                                                       currentConstraintRow[j].m_solverBodyIdB = 0;
+
+                                                       currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
+                                                       currentConstraintRow[j].m_upperLimit = B3_INFINITY;
+                                                       currentConstraintRow[j].m_appliedImpulse = 0.f;
+                                                       currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+                                                       currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
+                                                       currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
+                                                       currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
+                                               }
+
+                                               bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+                                               bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+                                               bodyAPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+                                               bodyAPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+                                               bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+                                               bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+                                               bodyBPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+                                               bodyBPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+
+                                               b3GpuConstraintInfo2 info2;
+                                               info2.fps = 1.f / infoGlobal.m_timeStep;
+                                               info2.erp = infoGlobal.m_erp;
+                                               info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
+                                               info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
+                                               info2.m_J2linearAxis = 0;
+                                               info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
+                                               info2.rowskip = sizeof(b3GpuSolverConstraint) / sizeof(b3Scalar);  //check this
+                                               ///the size of b3GpuSolverConstraint needs be a multiple of b3Scalar
+                                               b3Assert(info2.rowskip * sizeof(b3Scalar) == sizeof(b3GpuSolverConstraint));
+                                               info2.m_constraintError = &currentConstraintRow->m_rhs;
+                                               currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
+                                               info2.m_damping = infoGlobal.m_damping;
+                                               info2.cfm = &currentConstraintRow->m_cfm;
+                                               info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
+                                               info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
+                                               info2.m_numIterations = infoGlobal.m_numIterations;
+                                               m_gpuData->m_cpuConstraints[i].getInfo2(&info2, &m_gpuData->m_cpuBodies[0]);
+
+                                               ///finalize the constraint setup
+                                               for (j = 0; j < info1; j++)
+                                               {
+                                                       b3GpuSolverConstraint& solverConstraint = currentConstraintRow[j];
+
+                                                       if (solverConstraint.m_upperLimit >= m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
+                                                       {
+                                                               solverConstraint.m_upperLimit = m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold();
+                                                       }
+
+                                                       if (solverConstraint.m_lowerLimit <= -m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
+                                                       {
+                                                               solverConstraint.m_lowerLimit = -m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold();
+                                                       }
+
+                                                       //                                              solverConstraint.m_originalContactPoint = constraint;
+
+                                                       b3Matrix3x3& invInertiaWorldA = m_gpuData->m_cpuInertias[constraint.getRigidBodyA()].m_invInertiaWorld;
+                                                       {
+                                                               //b3Vector3 angularFactorA(1,1,1);
+                                                               const b3Vector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
+                                                               solverConstraint.m_angularComponentA = invInertiaWorldA * ftorqueAxis1;  //*angularFactorA;
+                                                       }
+
+                                                       b3Matrix3x3& invInertiaWorldB = m_gpuData->m_cpuInertias[constraint.getRigidBodyB()].m_invInertiaWorld;
+                                                       {
+                                                               const b3Vector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
+                                                               solverConstraint.m_angularComponentB = invInertiaWorldB * ftorqueAxis2;  //*constraint.getRigidBodyB().getAngularFactor();
+                                                       }
+
+                                                       {
+                                                               //it is ok to use solverConstraint.m_contactNormal instead of -solverConstraint.m_contactNormal
+                                                               //because it gets multiplied iMJlB
+                                                               b3Vector3 iMJlA = solverConstraint.m_contactNormal * rbA.m_invMass;
+                                                               b3Vector3 iMJaA = invInertiaWorldA * solverConstraint.m_relpos1CrossNormal;
+                                                               b3Vector3 iMJlB = solverConstraint.m_contactNormal * rbB.m_invMass;  //sign of normal?
+                                                               b3Vector3 iMJaB = invInertiaWorldB * solverConstraint.m_relpos2CrossNormal;
+
+                                                               b3Scalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
+                                                               sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+                                                               sum += iMJlB.dot(solverConstraint.m_contactNormal);
+                                                               sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+                                                               b3Scalar fsum = b3Fabs(sum);
+                                                               b3Assert(fsum > B3_EPSILON);
+                                                               solverConstraint.m_jacDiagABInv = fsum > B3_EPSILON ? b3Scalar(1.) / sum : 0.f;
+                                                       }
+
+                                                       ///fix rhs
+                                                       ///todo: add force/torque accelerators
+                                                       {
+                                                               b3Scalar rel_vel;
+                                                               b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.m_linVel) + solverConstraint.m_relpos1CrossNormal.dot(rbA.m_angVel);
+                                                               b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.m_linVel) + solverConstraint.m_relpos2CrossNormal.dot(rbB.m_angVel);
+
+                                                               rel_vel = vel1Dotn + vel2Dotn;
+
+                                                               b3Scalar restitution = 0.f;
+                                                               b3Scalar positionalError = solverConstraint.m_rhs;  //already filled in by getConstraintInfo2
+                                                               b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
+                                                               b3Scalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+                                                               b3Scalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+                                                               solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+                                                               solverConstraint.m_appliedImpulse = 0.f;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               m_gpuData->m_gpuConstraintRows->copyFromHost(m_tmpSolverNonContactConstraintPool);
+                               m_gpuData->m_gpuConstraintInfo1->copyFromHost(m_tmpConstraintSizesPool);
+
+                               if (m_gpuData->m_batchSizes.size() == 0)
+                                       m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
+                               else
+                                       m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+
+                               m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
+
+                       }  //end useGpuInfo2
+               }
+
+#ifdef B3_SUPPORT_CONTACT_CONSTRAINTS
+               {
+                       int i;
+
+                       for (i = 0; i < numManifolds; i++)
+                       {
+                               b3Contact4& manifold = manifoldPtr[i];
+                               convertContact(bodies, inertias, &manifold, infoGlobal);
+                       }
+               }
+#endif  //B3_SUPPORT_CONTACT_CONSTRAINTS
+       }
+
+       //      b3ContactSolverInfo info = infoGlobal;
+
+       //      int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+       //      int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+       //      int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+       return 0.f;
+}
+
+///a straight copy from GPU/OpenCL kernel, for debugging
+__inline void internalApplyImpulse(b3GpuSolverBody* body, const b3Vector3& linearComponent, const b3Vector3& angularComponent, float impulseMagnitude)
+{
+       body->m_deltaLinearVelocity += linearComponent * impulseMagnitude * body->m_linearFactor;
+       body->m_deltaAngularVelocity += angularComponent * (impulseMagnitude * body->m_angularFactor);
+}
+
+void resolveSingleConstraintRowGeneric2(b3GpuSolverBody* body1, b3GpuSolverBody* body2, b3GpuSolverConstraint* c)
+{
+       float deltaImpulse = c->m_rhs - b3Scalar(c->m_appliedImpulse) * c->m_cfm;
+       float deltaVel1Dotn = b3Dot(c->m_contactNormal, body1->m_deltaLinearVelocity) + b3Dot(c->m_relpos1CrossNormal, body1->m_deltaAngularVelocity);
+       float deltaVel2Dotn = -b3Dot(c->m_contactNormal, body2->m_deltaLinearVelocity) + b3Dot(c->m_relpos2CrossNormal, body2->m_deltaAngularVelocity);
+
+       deltaImpulse -= deltaVel1Dotn * c->m_jacDiagABInv;
+       deltaImpulse -= deltaVel2Dotn * c->m_jacDiagABInv;
+
+       float sum = b3Scalar(c->m_appliedImpulse) + deltaImpulse;
+       if (sum < c->m_lowerLimit)
+       {
+               deltaImpulse = c->m_lowerLimit - b3Scalar(c->m_appliedImpulse);
+               c->m_appliedImpulse = c->m_lowerLimit;
+       }
+       else if (sum > c->m_upperLimit)
+       {
+               deltaImpulse = c->m_upperLimit - b3Scalar(c->m_appliedImpulse);
+               c->m_appliedImpulse = c->m_upperLimit;
+       }
+       else
+       {
+               c->m_appliedImpulse = sum;
+       }
+
+       internalApplyImpulse(body1, c->m_contactNormal * body1->m_invMass, c->m_angularComponentA, deltaImpulse);
+       internalApplyImpulse(body2, -c->m_contactNormal * body2->m_invMass, c->m_angularComponentB, deltaImpulse);
+}
+
+void b3GpuPgsConstraintSolver::initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb)
+{
+       solverBody->m_deltaLinearVelocity.setValue(0.f, 0.f, 0.f);
+       solverBody->m_deltaAngularVelocity.setValue(0.f, 0.f, 0.f);
+       solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+       solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+
+       b3Assert(rb);
+       //      solverBody->m_worldTransform = getWorldTransform(rb);
+       solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass, rb->m_invMass, rb->m_invMass));
+       solverBody->m_originalBodyIndex = bodyIndex;
+       solverBody->m_angularFactor = b3MakeVector3(1, 1, 1);
+       solverBody->m_linearFactor = b3MakeVector3(1, 1, 1);
+       solverBody->m_linearVelocity = getLinearVelocity(rb);
+       solverBody->m_angularVelocity = getAngularVelocity(rb);
+}
+
+void b3GpuPgsConstraintSolver::averageVelocities()
+{
+}
+
+b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1, int numConstraints, const b3ContactSolverInfo& infoGlobal)
+{
+       //only create the batches once.
+       //@todo: incrementally update batches when constraints are added/activated and/or removed/deactivated
+       B3_PROFILE("GpuSolveGroupCacheFriendlyIterations");
+
+       bool createBatches = m_gpuData->m_batchSizes.size() == 0;
+       {
+               if (createBatches)
+               {
+                       m_gpuData->m_batchSizes.resize(0);
+
+                       {
+                               m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+
+                               B3_PROFILE("batch joints");
+                               b3Assert(batchConstraints.size() == numConstraints);
+                               int simdWidth = numConstraints + 1;
+                               int numBodies = m_tmpSolverBodyPool.size();
+                               sortConstraintByBatch3(&batchConstraints[0], numConstraints, simdWidth, m_staticIdx, numBodies);
+
+                               m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
+                       }
+               }
+               else
+               {
+                       /*b3AlignedObjectArray<b3BatchConstraint> cpuCheckBatches;
+                       m_gpuData->m_gpuBatchConstraints->copyToHost(cpuCheckBatches);
+                       b3Assert(cpuCheckBatches.size()==batchConstraints.size());
+                       printf(".\n");
+                       */
+                       //>copyFromHost(batchConstraints);
+               }
+               int maxIterations = infoGlobal.m_numIterations;
+
+               bool useBatching = true;
+
+               if (useBatching)
+               {
+                       if (!useGpuSolveJointConstraintRows)
+                       {
+                               B3_PROFILE("copy to host");
+                               m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+                               m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
+                               m_gpuData->m_gpuConstraintRows->copyToHost(m_tmpSolverNonContactConstraintPool);
+                               m_gpuData->m_gpuConstraintInfo1->copyToHost(m_gpuData->m_cpuConstraintInfo1);
+                               m_gpuData->m_gpuConstraintRowOffsets->copyToHost(m_gpuData->m_cpuConstraintRowOffsets);
+                               gpuConstraints1->copyToHost(m_gpuData->m_cpuConstraints);
+                       }
+
+                       for (int iteration = 0; iteration < maxIterations; iteration++)
+                       {
+                               int batchOffset = 0;
+                               int constraintOffset = 0;
+                               int numBatches = m_gpuData->m_batchSizes.size();
+                               for (int bb = 0; bb < numBatches; bb++)
+                               {
+                                       int numConstraintsInBatch = m_gpuData->m_batchSizes[bb];
+
+                                       if (useGpuSolveJointConstraintRows)
+                                       {
+                                               B3_PROFILE("solveJointConstraintRowsKernels");
+
+                                               /*
+                                               __kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,
+                                         __global b3BatchConstraint* batchConstraints,
+                                               __global b3SolverConstraint* rows,
+                                               __global unsigned int* numConstraintRowsInfo1, 
+                                               __global unsigned int* rowOffsets,
+                                               __global b3GpuGenericConstraint* constraints,
+                                               int batchOffset,
+                                               int numConstraintsInBatch*/
+
+                                               b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_solveJointConstraintRowsKernels, "m_solveJointConstraintRowsKernels");
+                                               launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
+                                               launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
+                                               launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
+                                               launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+                                               launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
+                                               launcher.setBuffer(gpuConstraints1->getBufferCL());  //to detect disabled constraints
+                                               launcher.setConst(batchOffset);
+                                               launcher.setConst(numConstraintsInBatch);
+
+                                               launcher.launch1D(numConstraintsInBatch);
+                                       }
+                                       else  //useGpu
+                                       {
+                                               for (int b = 0; b < numConstraintsInBatch; b++)
+                                               {
+                                                       const b3BatchConstraint& c = batchConstraints[batchOffset + b];
+                                                       /*printf("-----------\n");
+                                                       printf("bb=%d\n",bb);
+                                                       printf("c.batchId = %d\n", c.m_batchId);
+                                                       */
+                                                       b3Assert(c.m_batchId == bb);
+                                                       b3GpuGenericConstraint* constraint = &m_gpuData->m_cpuConstraints[c.m_originalConstraintIndex];
+                                                       if (constraint->m_flags & B3_CONSTRAINT_FLAG_ENABLED)
+                                                       {
+                                                               int numConstraintRows = m_gpuData->m_cpuConstraintInfo1[c.m_originalConstraintIndex];
+                                                               int constraintOffset = m_gpuData->m_cpuConstraintRowOffsets[c.m_originalConstraintIndex];
+
+                                                               for (int jj = 0; jj < numConstraintRows; jj++)
+                                                               {
+                                                                       //
+                                                                       b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[constraintOffset + jj];
+                                                                       //resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
+                                                                       resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA], &m_tmpSolverBodyPool[constraint.m_solverBodyIdB], &constraint);
+                                                               }
+                                                       }
+                                               }
+                                       }  //useGpu
+                                       batchOffset += numConstraintsInBatch;
+                                       constraintOffset += numConstraintsInBatch;
+                               }
+                       }  //for (int iteration...
+
+                       if (!useGpuSolveJointConstraintRows)
+                       {
+                               {
+                                       B3_PROFILE("copy from host");
+                                       m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
+                                       m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
+                                       m_gpuData->m_gpuConstraintRows->copyFromHost(m_tmpSolverNonContactConstraintPool);
+                               }
+
+                               //B3_PROFILE("copy to host");
+                               //m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+                       }
+                       //int sz = sizeof(b3GpuSolverBody);
+                       //printf("cpu sizeof(b3GpuSolverBody)=%d\n",sz);
+               }
+               else
+               {
+                       for (int iteration = 0; iteration < maxIterations; iteration++)
+                       {
+                               int numJoints = m_tmpSolverNonContactConstraintPool.size();
+                               for (int j = 0; j < numJoints; j++)
+                               {
+                                       b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[j];
+                                       resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA], &m_tmpSolverBodyPool[constraint.m_solverBodyIdB], &constraint);
+                               }
+
+                               if (!m_usePgs)
+                               {
+                                       averageVelocities();
+                               }
+                       }
+               }
+       }
+       clFinish(m_gpuData->m_queue);
+       return 0.f;
+}
+
+static b3AlignedObjectArray<int> bodyUsed;
+static b3AlignedObjectArray<int> curUsed;
+
+inline int b3GpuPgsConstraintSolver::sortConstraintByBatch3(b3BatchConstraint* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies)
+{
+       //int sz = sizeof(b3BatchConstraint);
+
+       B3_PROFILE("sortConstraintByBatch3");
+
+       static int maxSwaps = 0;
+       int numSwaps = 0;
+
+       curUsed.resize(2 * simdWidth);
+
+       static int maxNumConstraints = 0;
+       if (maxNumConstraints < numConstraints)
+       {
+               maxNumConstraints = numConstraints;
+               //printf("maxNumConstraints  = %d\n",maxNumConstraints );
+       }
+
+       int numUsedArray = numBodies / 32 + 1;
+       bodyUsed.resize(numUsedArray);
+
+       for (int q = 0; q < numUsedArray; q++)
+               bodyUsed[q] = 0;
+
+       int curBodyUsed = 0;
+
+       int numIter = 0;
+
+#if defined(_DEBUG)
+       for (int i = 0; i < numConstraints; i++)
+               cs[i].m_batchId = -1;
+#endif
+
+       int numValidConstraints = 0;
+       //      int unprocessedConstraintIndex = 0;
+
+       int batchIdx = 0;
+
+       {
+               B3_PROFILE("cpu batch innerloop");
+
+               while (numValidConstraints < numConstraints)
+               {
+                       numIter++;
+                       int nCurrentBatch = 0;
+                       //      clear flag
+                       for (int i = 0; i < curBodyUsed; i++)
+                               bodyUsed[curUsed[i] / 32] = 0;
+
+                       curBodyUsed = 0;
+
+                       for (int i = numValidConstraints; i < numConstraints; i++)
+                       {
+                               int idx = i;
+                               b3Assert(idx < numConstraints);
+                               //      check if it can go
+                               int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
+                               int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
+                               int bodyA = abs(bodyAS);
+                               int bodyB = abs(bodyBS);
+                               bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
+                               bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
+                               int aUnavailable = 0;
+                               int bUnavailable = 0;
+                               if (!aIsStatic)
+                               {
+                                       aUnavailable = bodyUsed[bodyA / 32] & (1 << (bodyA & 31));
+                               }
+                               if (!aUnavailable)
+                                       if (!bIsStatic)
+                                       {
+                                               bUnavailable = bodyUsed[bodyB / 32] & (1 << (bodyB & 31));
+                                       }
+
+                               if (aUnavailable == 0 && bUnavailable == 0)  // ok
+                               {
+                                       if (!aIsStatic)
+                                       {
+                                               bodyUsed[bodyA / 32] |= (1 << (bodyA & 31));
+                                               curUsed[curBodyUsed++] = bodyA;
+                                       }
+                                       if (!bIsStatic)
+                                       {
+                                               bodyUsed[bodyB / 32] |= (1 << (bodyB & 31));
+                                               curUsed[curBodyUsed++] = bodyB;
+                                       }
+
+                                       cs[idx].m_batchId = batchIdx;
+
+                                       if (i != numValidConstraints)
+                                       {
+                                               b3Swap(cs[i], cs[numValidConstraints]);
+                                               numSwaps++;
+                                       }
+
+                                       numValidConstraints++;
+                                       {
+                                               nCurrentBatch++;
+                                               if (nCurrentBatch == simdWidth)
+                                               {
+                                                       nCurrentBatch = 0;
+                                                       for (int i = 0; i < curBodyUsed; i++)
+                                                               bodyUsed[curUsed[i] / 32] = 0;
+                                                       curBodyUsed = 0;
+                                               }
+                                       }
+                               }
+                       }
+                       m_gpuData->m_batchSizes.push_back(nCurrentBatch);
+                       batchIdx++;
+               }
+       }
+
+#if defined(_DEBUG)
+       //              debugPrintf( "nBatches: %d\n", batchIdx );
+       for (int i = 0; i < numConstraints; i++)
+       {
+               b3Assert(cs[i].m_batchId != -1);
+       }
+#endif
+
+       if (maxSwaps < numSwaps)
+       {
+               maxSwaps = numSwaps;
+               //printf("maxSwaps = %d\n", maxSwaps);
+       }
+
+       return batchIdx;
+}
+
+/// b3PgsJacobiSolver Sequentially applies impulses
+b3Scalar b3GpuPgsConstraintSolver::solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
+                                                                                         int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
+{
+       B3_PROFILE("solveJoints");
+       //you need to provide at least some bodies
+
+       solveGroupCacheFriendlySetup(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
+
+       solveGroupCacheFriendlyIterations(gpuConstraints, numConstraints, infoGlobal);
+
+       solveGroupCacheFriendlyFinish(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
+
+       return 0.f;
+}
+
+void b3GpuPgsConstraintSolver::solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
+                                                                                  int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints)
+{
+       b3ContactSolverInfo infoGlobal;
+       infoGlobal.m_splitImpulse = false;
+       infoGlobal.m_timeStep = 1.f / 60.f;
+       infoGlobal.m_numIterations = 4;  //4;
+                                                                        //     infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
+       //infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS;
+       infoGlobal.m_solverMode |= B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
+
+       //if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+       //if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+
+       solveGroup(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
+}
+
+//b3AlignedObjectArray<b3RigidBodyData> testBodies;
+
+b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
+{
+       B3_PROFILE("solveGroupCacheFriendlyFinish");
+       //      int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+       //      int i,j;
+
+       {
+               if (gpuBreakConstraints)
+               {
+                       B3_PROFILE("breakViolatedConstraintsKernel");
+                       b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_breakViolatedConstraintsKernel, "m_breakViolatedConstraintsKernel");
+                       launcher.setBuffer(gpuConstraints->getBufferCL());
+                       launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
+                       launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
+                       launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
+                       launcher.setConst(numConstraints);
+                       launcher.launch1D(numConstraints);
+               }
+               else
+               {
+                       gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
+                       m_gpuData->m_gpuBatchConstraints->copyToHost(m_gpuData->m_cpuBatchConstraints);
+                       m_gpuData->m_gpuConstraintRows->copyToHost(m_gpuData->m_cpuConstraintRows);
+                       gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
+                       m_gpuData->m_gpuConstraintInfo1->copyToHost(m_gpuData->m_cpuConstraintInfo1);
+                       m_gpuData->m_gpuConstraintRowOffsets->copyToHost(m_gpuData->m_cpuConstraintRowOffsets);
+
+                       for (int cid = 0; cid < numConstraints; cid++)
+                       {
+                               int originalConstraintIndex = batchConstraints[cid].m_originalConstraintIndex;
+                               int constraintRowOffset = m_gpuData->m_cpuConstraintRowOffsets[originalConstraintIndex];
+                               int numRows = m_gpuData->m_cpuConstraintInfo1[originalConstraintIndex];
+                               if (numRows)
+                               {
+                                       //      printf("cid=%d, breakingThreshold =%f\n",cid,breakingThreshold);
+                                       for (int i = 0; i < numRows; i++)
+                                       {
+                                               int rowIndex = constraintRowOffset + i;
+                                               int orgConstraintIndex = m_gpuData->m_cpuConstraintRows[rowIndex].m_originalConstraintIndex;
+                                               float breakingThreshold = m_gpuData->m_cpuConstraints[orgConstraintIndex].m_breakingImpulseThreshold;
+                                               //      printf("rows[%d].m_appliedImpulse=%f\n",rowIndex,rows[rowIndex].m_appliedImpulse);
+                                               if (b3Fabs(m_gpuData->m_cpuConstraintRows[rowIndex].m_appliedImpulse) >= breakingThreshold)
+                                               {
+                                                       m_gpuData->m_cpuConstraints[orgConstraintIndex].m_flags = 0;  //&= ~B3_CONSTRAINT_FLAG_ENABLED;
+                                               }
+                                       }
+                               }
+                       }
+
+                       gpuConstraints->copyFromHost(m_gpuData->m_cpuConstraints);
+               }
+       }
+
+       {
+               if (useGpuWriteBackVelocities)
+               {
+                       B3_PROFILE("GPU write back velocities and transforms");
+
+                       b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_writeBackVelocitiesKernel, "m_writeBackVelocitiesKernel");
+                       launcher.setBuffer(gpuBodies->getBufferCL());
+                       launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
+                       launcher.setConst(numBodies);
+                       launcher.launch1D(numBodies);
+                       clFinish(m_gpuData->m_queue);
+                       //                      m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+                       //                      m_gpuData->m_gpuBodies->copyToHostPointer(bodies,numBodies);
+                       //m_gpuData->m_gpuBodies->copyToHost(testBodies);
+               }
+               else
+               {
+                       B3_PROFILE("CPU write back velocities and transforms");
+
+                       m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
+                       gpuBodies->copyToHost(m_gpuData->m_cpuBodies);
+                       for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
+                       {
+                               int bodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
+                               //printf("bodyIndex=%d\n",bodyIndex);
+                               b3Assert(i == bodyIndex);
+
+                               b3RigidBodyData* body = &m_gpuData->m_cpuBodies[bodyIndex];
+                               if (body->m_invMass)
+                               {
+                                       if (infoGlobal.m_splitImpulse)
+                                               m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
+                                       else
+                                               m_tmpSolverBodyPool[i].writebackVelocity();
+
+                                       if (m_usePgs)
+                                       {
+                                               body->m_linVel = m_tmpSolverBodyPool[i].m_linearVelocity;
+                                               body->m_angVel = m_tmpSolverBodyPool[i].m_angularVelocity;
+                                       }
+                                       else
+                                       {
+                                               b3Assert(0);
+                                       }
+                                       /*                      
+                                       if (infoGlobal.m_splitImpulse)
+                                       {
+                                               body->m_pos = m_tmpSolverBodyPool[i].m_worldTransform.getOrigin();
+                                               b3Quaternion orn;
+                                               orn = m_tmpSolverBodyPool[i].m_worldTransform.getRotation();
+                                               body->m_quat = orn;
+                                       }
+                                       */
+                               }
+                       }  //for
+
+                       gpuBodies->copyFromHost(m_gpuData->m_cpuBodies);
+               }
+       }
+
+       clFinish(m_gpuData->m_queue);
+
+       m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
+
+       m_tmpSolverBodyPool.resizeNoInitialize(0);
+       return 0.f;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h
new file mode 100644 (file)
index 0000000..00bc544
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_GPU_PGS_CONSTRAINT_SOLVER_H
+#define B3_GPU_PGS_CONSTRAINT_SOLVER_H
+
+struct b3Contact4;
+struct b3ContactPoint;
+
+class b3Dispatcher;
+
+#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
+#include "Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h"
+#include "b3GpuSolverBody.h"
+#include "b3GpuSolverConstraint.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+struct b3RigidBodyData;
+struct b3InertiaData;
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "b3GpuGenericConstraint.h"
+
+class b3GpuPgsConstraintSolver
+{
+protected:
+       int m_staticIdx;
+       struct b3GpuPgsJacobiSolverInternalData* m_gpuData;
+
+protected:
+       b3AlignedObjectArray<b3GpuSolverBody> m_tmpSolverBodyPool;
+       b3GpuConstraintArray m_tmpSolverContactConstraintPool;
+       b3GpuConstraintArray m_tmpSolverNonContactConstraintPool;
+       b3GpuConstraintArray m_tmpSolverContactFrictionConstraintPool;
+       b3GpuConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
+
+       b3AlignedObjectArray<unsigned int> m_tmpConstraintSizesPool;
+
+       bool m_usePgs;
+       void averageVelocities();
+
+       int m_maxOverrideNumSolverIterations;
+
+       int m_numSplitImpulseRecoveries;
+
+       //      int     getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies,b3InertiaData* inertias);
+       void initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb);
+
+public:
+       b3GpuPgsConstraintSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, bool usePgs);
+       virtual ~b3GpuPgsConstraintSolver();
+
+       virtual b3Scalar solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+       virtual b3Scalar solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+       b3Scalar solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+
+       b3Scalar solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
+       void solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
+                                        int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints);
+
+       int sortConstraintByBatch3(struct b3BatchConstraint* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies);
+       void recomputeBatches();
+};
+
+#endif  //B3_GPU_PGS_CONSTRAINT_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp
new file mode 100644 (file)
index 0000000..e3d235a
--- /dev/null
@@ -0,0 +1,1529 @@
+
+bool gUseLargeBatches = false;
+bool gCpuBatchContacts = false;
+bool gCpuSolveConstraint = false;
+bool gCpuRadixSort = false;
+bool gCpuSetSortData = false;
+bool gCpuSortContactsDeterminism = false;
+bool gUseCpuCopyConstraints = false;
+bool gUseScanHost = false;
+bool gReorderContactsOnCpu = false;
+
+bool optionalSortContactsDeterminism = true;
+
+#include "b3GpuPgsContactSolver.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
+#include <string.h>
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+#include "b3Solver.h"
+
+#define B3_SOLVER_SETUP_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl"
+#define B3_SOLVER_SETUP2_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl"
+#define B3_SOLVER_CONTACT_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl"
+#define B3_SOLVER_FRICTION_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl"
+#define B3_BATCHING_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl"
+#define B3_BATCHING_NEW_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl"
+
+#include "kernels/solverSetup.h"
+#include "kernels/solverSetup2.h"
+#include "kernels/solveContact.h"
+#include "kernels/solveFriction.h"
+#include "kernels/batchingKernels.h"
+#include "kernels/batchingKernelsNew.h"
+
+struct b3GpuBatchingPgsSolverInternalData
+{
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_queue;
+       int m_pairCapacity;
+       int m_nIterations;
+
+       b3OpenCLArray<b3GpuConstraint4>* m_contactCGPU;
+       b3OpenCLArray<unsigned int>* m_numConstraints;
+       b3OpenCLArray<unsigned int>* m_offsets;
+
+       b3Solver* m_solverGPU;
+
+       cl_kernel m_batchingKernel;
+       cl_kernel m_batchingKernelNew;
+       cl_kernel m_solveContactKernel;
+       cl_kernel m_solveSingleContactKernel;
+       cl_kernel m_solveSingleFrictionKernel;
+       cl_kernel m_solveFrictionKernel;
+       cl_kernel m_contactToConstraintKernel;
+       cl_kernel m_setSortDataKernel;
+       cl_kernel m_reorderContactKernel;
+       cl_kernel m_copyConstraintKernel;
+
+       cl_kernel m_setDeterminismSortDataBodyAKernel;
+       cl_kernel m_setDeterminismSortDataBodyBKernel;
+       cl_kernel m_setDeterminismSortDataChildShapeAKernel;
+       cl_kernel m_setDeterminismSortDataChildShapeBKernel;
+
+       class b3RadixSort32CL* m_sort32;
+       class b3BoundSearchCL* m_search;
+       class b3PrefixScanCL* m_scan;
+
+       b3OpenCLArray<b3SortData>* m_sortDataBuffer;
+       b3OpenCLArray<b3Contact4>* m_contactBuffer;
+
+       b3OpenCLArray<b3RigidBodyData>* m_bodyBufferGPU;
+       b3OpenCLArray<b3InertiaData>* m_inertiaBufferGPU;
+       b3OpenCLArray<b3Contact4>* m_pBufContactOutGPU;
+
+       b3OpenCLArray<b3Contact4>* m_pBufContactOutGPUCopy;
+       b3OpenCLArray<b3SortData>* m_contactKeyValues;
+
+       b3AlignedObjectArray<unsigned int> m_idxBuffer;
+       b3AlignedObjectArray<b3SortData> m_sortData;
+       b3AlignedObjectArray<b3Contact4> m_old;
+
+       b3AlignedObjectArray<int> m_batchSizes;
+       b3OpenCLArray<int>* m_batchSizesGpu;
+};
+
+b3GpuPgsContactSolver::b3GpuPgsContactSolver(cl_context ctx, cl_device_id device, cl_command_queue q, int pairCapacity)
+{
+       m_debugOutput = 0;
+       m_data = new b3GpuBatchingPgsSolverInternalData;
+       m_data->m_context = ctx;
+       m_data->m_device = device;
+       m_data->m_queue = q;
+       m_data->m_pairCapacity = pairCapacity;
+       m_data->m_nIterations = 4;
+       m_data->m_batchSizesGpu = new b3OpenCLArray<int>(ctx, q);
+       m_data->m_bodyBufferGPU = new b3OpenCLArray<b3RigidBodyData>(ctx, q);
+       m_data->m_inertiaBufferGPU = new b3OpenCLArray<b3InertiaData>(ctx, q);
+       m_data->m_pBufContactOutGPU = new b3OpenCLArray<b3Contact4>(ctx, q);
+
+       m_data->m_pBufContactOutGPUCopy = new b3OpenCLArray<b3Contact4>(ctx, q);
+       m_data->m_contactKeyValues = new b3OpenCLArray<b3SortData>(ctx, q);
+
+       m_data->m_solverGPU = new b3Solver(ctx, device, q, 512 * 1024);
+
+       m_data->m_sort32 = new b3RadixSort32CL(ctx, device, m_data->m_queue);
+       m_data->m_scan = new b3PrefixScanCL(ctx, device, m_data->m_queue, B3_SOLVER_N_CELLS);
+       m_data->m_search = new b3BoundSearchCL(ctx, device, m_data->m_queue, B3_SOLVER_N_CELLS);
+
+       const int sortSize = B3NEXTMULTIPLEOF(pairCapacity, 512);
+
+       m_data->m_sortDataBuffer = new b3OpenCLArray<b3SortData>(ctx, m_data->m_queue, sortSize);
+       m_data->m_contactBuffer = new b3OpenCLArray<b3Contact4>(ctx, m_data->m_queue);
+
+       m_data->m_numConstraints = new b3OpenCLArray<unsigned int>(ctx, m_data->m_queue, B3_SOLVER_N_CELLS);
+       m_data->m_numConstraints->resize(B3_SOLVER_N_CELLS);
+
+       m_data->m_contactCGPU = new b3OpenCLArray<b3GpuConstraint4>(ctx, q, pairCapacity);
+
+       m_data->m_offsets = new b3OpenCLArray<unsigned int>(ctx, m_data->m_queue, B3_SOLVER_N_CELLS);
+       m_data->m_offsets->resize(B3_SOLVER_N_CELLS);
+       const char* additionalMacros = "";
+       //const char* srcFileNameForCaching="";
+
+       cl_int pErrNum;
+       const char* batchKernelSource = batchingKernelsCL;
+       const char* batchKernelNewSource = batchingKernelsNewCL;
+       const char* solverSetupSource = solverSetupCL;
+       const char* solverSetup2Source = solverSetup2CL;
+       const char* solveContactSource = solveContactCL;
+       const char* solveFrictionSource = solveFrictionCL;
+
+       {
+               cl_program solveContactProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveContactSource, &pErrNum, additionalMacros, B3_SOLVER_CONTACT_KERNEL_PATH);
+               b3Assert(solveContactProg);
+
+               cl_program solveFrictionProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveFrictionSource, &pErrNum, additionalMacros, B3_SOLVER_FRICTION_KERNEL_PATH);
+               b3Assert(solveFrictionProg);
+
+               cl_program solverSetup2Prog = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetup2Source, &pErrNum, additionalMacros, B3_SOLVER_SETUP2_KERNEL_PATH);
+
+               b3Assert(solverSetup2Prog);
+
+               cl_program solverSetupProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetupSource, &pErrNum, additionalMacros, B3_SOLVER_SETUP_KERNEL_PATH);
+               b3Assert(solverSetupProg);
+
+               m_data->m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg, additionalMacros);
+               b3Assert(m_data->m_solveFrictionKernel);
+
+               m_data->m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg, additionalMacros);
+               b3Assert(m_data->m_solveContactKernel);
+
+               m_data->m_solveSingleContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveContactSource, "solveSingleContactKernel", &pErrNum, solveContactProg, additionalMacros);
+               b3Assert(m_data->m_solveSingleContactKernel);
+
+               m_data->m_solveSingleFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveFrictionSource, "solveSingleFrictionKernel", &pErrNum, solveFrictionProg, additionalMacros);
+               b3Assert(m_data->m_solveSingleFrictionKernel);
+
+               m_data->m_contactToConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg, additionalMacros);
+               b3Assert(m_data->m_contactToConstraintKernel);
+
+               m_data->m_setSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog, additionalMacros);
+               b3Assert(m_data->m_setSortDataKernel);
+
+               m_data->m_setDeterminismSortDataBodyAKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataBodyA", &pErrNum, solverSetup2Prog, additionalMacros);
+               b3Assert(m_data->m_setDeterminismSortDataBodyAKernel);
+
+               m_data->m_setDeterminismSortDataBodyBKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataBodyB", &pErrNum, solverSetup2Prog, additionalMacros);
+               b3Assert(m_data->m_setDeterminismSortDataBodyBKernel);
+
+               m_data->m_setDeterminismSortDataChildShapeAKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataChildShapeA", &pErrNum, solverSetup2Prog, additionalMacros);
+               b3Assert(m_data->m_setDeterminismSortDataChildShapeAKernel);
+
+               m_data->m_setDeterminismSortDataChildShapeBKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataChildShapeB", &pErrNum, solverSetup2Prog, additionalMacros);
+               b3Assert(m_data->m_setDeterminismSortDataChildShapeBKernel);
+
+               m_data->m_reorderContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog, additionalMacros);
+               b3Assert(m_data->m_reorderContactKernel);
+
+               m_data->m_copyConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog, additionalMacros);
+               b3Assert(m_data->m_copyConstraintKernel);
+       }
+
+       {
+               cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelSource, &pErrNum, additionalMacros, B3_BATCHING_PATH);
+               b3Assert(batchingProg);
+
+               m_data->m_batchingKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg, additionalMacros);
+               b3Assert(m_data->m_batchingKernel);
+       }
+
+       {
+               cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelNewSource, &pErrNum, additionalMacros, B3_BATCHING_NEW_PATH);
+               b3Assert(batchingNewProg);
+
+               m_data->m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg, additionalMacros);
+               b3Assert(m_data->m_batchingKernelNew);
+       }
+}
+
+b3GpuPgsContactSolver::~b3GpuPgsContactSolver()
+{
+       delete m_data->m_batchSizesGpu;
+       delete m_data->m_bodyBufferGPU;
+       delete m_data->m_inertiaBufferGPU;
+       delete m_data->m_pBufContactOutGPU;
+       delete m_data->m_pBufContactOutGPUCopy;
+       delete m_data->m_contactKeyValues;
+
+       delete m_data->m_contactCGPU;
+       delete m_data->m_numConstraints;
+       delete m_data->m_offsets;
+       delete m_data->m_sortDataBuffer;
+       delete m_data->m_contactBuffer;
+
+       delete m_data->m_sort32;
+       delete m_data->m_scan;
+       delete m_data->m_search;
+       delete m_data->m_solverGPU;
+
+       clReleaseKernel(m_data->m_batchingKernel);
+       clReleaseKernel(m_data->m_batchingKernelNew);
+       clReleaseKernel(m_data->m_solveSingleContactKernel);
+       clReleaseKernel(m_data->m_solveSingleFrictionKernel);
+       clReleaseKernel(m_data->m_solveContactKernel);
+       clReleaseKernel(m_data->m_solveFrictionKernel);
+
+       clReleaseKernel(m_data->m_contactToConstraintKernel);
+       clReleaseKernel(m_data->m_setSortDataKernel);
+       clReleaseKernel(m_data->m_reorderContactKernel);
+       clReleaseKernel(m_data->m_copyConstraintKernel);
+
+       clReleaseKernel(m_data->m_setDeterminismSortDataBodyAKernel);
+       clReleaseKernel(m_data->m_setDeterminismSortDataBodyBKernel);
+       clReleaseKernel(m_data->m_setDeterminismSortDataChildShapeAKernel);
+       clReleaseKernel(m_data->m_setDeterminismSortDataChildShapeBKernel);
+
+       delete m_data;
+}
+
+struct b3ConstraintCfg
+{
+       b3ConstraintCfg(float dt = 0.f) : m_positionDrift(0.005f), m_positionConstraintCoeff(0.2f), m_dt(dt), m_staticIdx(0) {}
+
+       float m_positionDrift;
+       float m_positionConstraintCoeff;
+       float m_dt;
+       bool m_enableParallelSolve;
+       float m_batchCellSize;
+       int m_staticIdx;
+};
+
+void b3GpuPgsContactSolver::solveContactConstraintBatchSizes(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+                                                                                                                        b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes)  //const b3OpenCLArray<int>* gpuBatchSizes)
+{
+       B3_PROFILE("solveContactConstraintBatchSizes");
+       int numBatches = batchSizes->size() / B3_MAX_NUM_BATCHES;
+       for (int iter = 0; iter < numIterations; iter++)
+       {
+               for (int cellId = 0; cellId < numBatches; cellId++)
+               {
+                       int offset = 0;
+                       for (int ii = 0; ii < B3_MAX_NUM_BATCHES; ii++)
+                       {
+                               int numInBatch = batchSizes->at(cellId * B3_MAX_NUM_BATCHES + ii);
+                               if (!numInBatch)
+                                       break;
+
+                               {
+                                       b3LauncherCL launcher(m_data->m_queue, m_data->m_solveSingleContactKernel, "m_solveSingleContactKernel");
+                                       launcher.setBuffer(bodyBuf->getBufferCL());
+                                       launcher.setBuffer(shapeBuf->getBufferCL());
+                                       launcher.setBuffer(constraint->getBufferCL());
+                                       launcher.setConst(cellId);
+                                       launcher.setConst(offset);
+                                       launcher.setConst(numInBatch);
+                                       launcher.launch1D(numInBatch);
+                                       offset += numInBatch;
+                               }
+                       }
+               }
+       }
+
+       for (int iter = 0; iter < numIterations; iter++)
+       {
+               for (int cellId = 0; cellId < numBatches; cellId++)
+               {
+                       int offset = 0;
+                       for (int ii = 0; ii < B3_MAX_NUM_BATCHES; ii++)
+                       {
+                               int numInBatch = batchSizes->at(cellId * B3_MAX_NUM_BATCHES + ii);
+                               if (!numInBatch)
+                                       break;
+
+                               {
+                                       b3LauncherCL launcher(m_data->m_queue, m_data->m_solveSingleFrictionKernel, "m_solveSingleFrictionKernel");
+                                       launcher.setBuffer(bodyBuf->getBufferCL());
+                                       launcher.setBuffer(shapeBuf->getBufferCL());
+                                       launcher.setBuffer(constraint->getBufferCL());
+                                       launcher.setConst(cellId);
+                                       launcher.setConst(offset);
+                                       launcher.setConst(numInBatch);
+                                       launcher.launch1D(numInBatch);
+                                       offset += numInBatch;
+                               }
+                       }
+               }
+       }
+}
+
+void b3GpuPgsContactSolver::solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+                                                                                                  b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes)  //,const b3OpenCLArray<int>* gpuBatchSizes)
+{
+       //sort the contacts
+
+       b3Int4 cdata = b3MakeInt4(n, 0, 0, 0);
+       {
+               const int nn = B3_SOLVER_N_CELLS;
+
+               cdata.x = 0;
+               cdata.y = maxNumBatches;  //250;
+
+               int numWorkItems = 64 * nn / B3_SOLVER_N_BATCHES;
+#ifdef DEBUG_ME
+               SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
+               adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device, numWorkItems);
+#endif
+
+               {
+                       B3_PROFILE("m_batchSolveKernel iterations");
+                       for (int iter = 0; iter < numIterations; iter++)
+                       {
+                               for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
+                               {
+#ifdef DEBUG_ME
+                                       memset(debugInfo, 0, sizeof(SolverDebugInfo) * numWorkItems);
+                                       gpuDebugInfo.write(debugInfo, numWorkItems);
+#endif
+
+                                       cdata.z = ib;
+
+                                       b3LauncherCL launcher(m_data->m_queue, m_data->m_solveContactKernel, "m_solveContactKernel");
+#if 1
+
+                                       b3BufferInfoCL bInfo[] = {
+
+                                               b3BufferInfoCL(bodyBuf->getBufferCL()),
+                                               b3BufferInfoCL(shapeBuf->getBufferCL()),
+                                               b3BufferInfoCL(constraint->getBufferCL()),
+                                               b3BufferInfoCL(m_data->m_solverGPU->m_numConstraints->getBufferCL()),
+                                               b3BufferInfoCL(m_data->m_solverGPU->m_offsets->getBufferCL())
+#ifdef DEBUG_ME
+                                                       ,
+                                               b3BufferInfoCL(&gpuDebugInfo)
+#endif
+                                       };
+
+                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                       launcher.setBuffer(m_data->m_solverGPU->m_batchSizes.getBufferCL());
+                                       //launcher.setConst(  cdata.x );
+                                       launcher.setConst(cdata.y);
+                                       launcher.setConst(cdata.z);
+                                       b3Int4 nSplit;
+                                       nSplit.x = B3_SOLVER_N_SPLIT_X;
+                                       nSplit.y = B3_SOLVER_N_SPLIT_Y;
+                                       nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+                                       launcher.setConst(nSplit);
+                                       launcher.launch1D(numWorkItems, 64);
+
+#else
+                                       const char* fileName = "m_batchSolveKernel.bin";
+                                       FILE* f = fopen(fileName, "rb");
+                                       if (f)
+                                       {
+                                               int sizeInBytes = 0;
+                                               if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
+                                               {
+                                                       printf("error, cannot get file size\n");
+                                                       exit(0);
+                                               }
+
+                                               unsigned char* buf = (unsigned char*)malloc(sizeInBytes);
+                                               fread(buf, sizeInBytes, 1, f);
+                                               int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes, m_context);
+                                               int num = *(int*)&buf[serializedBytes];
+
+                                               launcher.launch1D(num);
+
+                                               //this clFinish is for testing on errors
+                                               clFinish(m_queue);
+                                       }
+
+#endif
+
+#ifdef DEBUG_ME
+                                       clFinish(m_queue);
+                                       gpuDebugInfo.read(debugInfo, numWorkItems);
+                                       clFinish(m_queue);
+                                       for (int i = 0; i < numWorkItems; i++)
+                                       {
+                                               if (debugInfo[i].m_valInt2 > 0)
+                                               {
+                                                       printf("debugInfo[i].m_valInt2 = %d\n", i, debugInfo[i].m_valInt2);
+                                               }
+
+                                               if (debugInfo[i].m_valInt3 > 0)
+                                               {
+                                                       printf("debugInfo[i].m_valInt3 = %d\n", i, debugInfo[i].m_valInt3);
+                                               }
+                                       }
+#endif  //DEBUG_ME
+                               }
+                       }
+
+                       clFinish(m_data->m_queue);
+               }
+
+               cdata.x = 1;
+               bool applyFriction = true;
+               if (applyFriction)
+               {
+                       B3_PROFILE("m_batchSolveKernel iterations2");
+                       for (int iter = 0; iter < numIterations; iter++)
+                       {
+                               for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
+                               {
+                                       cdata.z = ib;
+
+                                       b3BufferInfoCL bInfo[] = {
+                                               b3BufferInfoCL(bodyBuf->getBufferCL()),
+                                               b3BufferInfoCL(shapeBuf->getBufferCL()),
+                                               b3BufferInfoCL(constraint->getBufferCL()),
+                                               b3BufferInfoCL(m_data->m_solverGPU->m_numConstraints->getBufferCL()),
+                                               b3BufferInfoCL(m_data->m_solverGPU->m_offsets->getBufferCL())
+#ifdef DEBUG_ME
+                                                       ,
+                                               b3BufferInfoCL(&gpuDebugInfo)
+#endif  //DEBUG_ME
+                                       };
+                                       b3LauncherCL launcher(m_data->m_queue, m_data->m_solveFrictionKernel, "m_solveFrictionKernel");
+                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                       launcher.setBuffer(m_data->m_solverGPU->m_batchSizes.getBufferCL());
+                                       //launcher.setConst(  cdata.x );
+                                       launcher.setConst(cdata.y);
+                                       launcher.setConst(cdata.z);
+
+                                       b3Int4 nSplit;
+                                       nSplit.x = B3_SOLVER_N_SPLIT_X;
+                                       nSplit.y = B3_SOLVER_N_SPLIT_Y;
+                                       nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+                                       launcher.setConst(nSplit);
+
+                                       launcher.launch1D(64 * nn / B3_SOLVER_N_BATCHES, 64);
+                               }
+                       }
+                       clFinish(m_data->m_queue);
+               }
+#ifdef DEBUG_ME
+               delete[] debugInfo;
+#endif  //DEBUG_ME
+       }
+}
+
+static bool sortfnc(const b3SortData& a, const b3SortData& b)
+{
+       return (a.m_key < b.m_key);
+}
+
+static bool b3ContactCmp(const b3Contact4& p, const b3Contact4& q)
+{
+       return ((p.m_bodyAPtrAndSignBit < q.m_bodyAPtrAndSignBit) ||
+                       ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit < q.m_bodyBPtrAndSignBit)) ||
+                       ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit == q.m_bodyBPtrAndSignBit) && p.m_childIndexA < q.m_childIndexA) ||
+                       ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit == q.m_bodyBPtrAndSignBit) && p.m_childIndexA < q.m_childIndexA) ||
+                       ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit == q.m_bodyBPtrAndSignBit) && p.m_childIndexA == q.m_childIndexA && p.m_childIndexB < q.m_childIndexB));
+}
+
+#define USE_SPATIAL_BATCHING 1
+#define USE_4x4_GRID 1
+
+#ifndef USE_SPATIAL_BATCHING
+static const int gridTable4x4[] =
+       {
+               0, 1, 17, 16,
+               1, 2, 18, 19,
+               17, 18, 32, 3,
+               16, 19, 3, 34};
+static const int gridTable8x8[] =
+       {
+               0, 2, 3, 16, 17, 18, 19, 1,
+               66, 64, 80, 67, 82, 81, 65, 83,
+               131, 144, 128, 130, 147, 129, 145, 146,
+               208, 195, 194, 192, 193, 211, 210, 209,
+               21, 22, 23, 5, 4, 6, 7, 20,
+               86, 85, 69, 87, 70, 68, 84, 71,
+               151, 133, 149, 150, 135, 148, 132, 134,
+               197, 27, 214, 213, 212, 199, 198, 196
+
+};
+
+#endif
+
+void SetSortDataCPU(b3Contact4* gContact, b3RigidBodyData* gBodies, b3SortData* gSortDataOut, int nContacts, float scale, const b3Int4& nSplit, int staticIdx)
+{
+       for (int gIdx = 0; gIdx < nContacts; gIdx++)
+       {
+               if (gIdx < nContacts)
+               {
+                       int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;
+                       int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;
+
+                       int aIdx = abs(aPtrAndSignBit);
+                       int bIdx = abs(bPtrAndSignBit);
+
+                       bool aStatic = (aPtrAndSignBit < 0) || (aPtrAndSignBit == staticIdx);
+
+#if USE_SPATIAL_BATCHING
+                       int idx = (aStatic) ? bIdx : aIdx;
+                       b3Vector3 p = gBodies[idx].m_pos;
+                       int xIdx = (int)((p.x - ((p.x < 0.f) ? 1.f : 0.f)) * scale) & (nSplit.x - 1);
+                       int yIdx = (int)((p.y - ((p.y < 0.f) ? 1.f : 0.f)) * scale) & (nSplit.y - 1);
+                       int zIdx = (int)((p.z - ((p.z < 0.f) ? 1.f : 0.f)) * scale) & (nSplit.z - 1);
+
+                       int newIndex = (xIdx + yIdx * nSplit.x + zIdx * nSplit.x * nSplit.y);
+
+#else  //USE_SPATIAL_BATCHING
+                       bool bStatic = (bPtrAndSignBit < 0) || (bPtrAndSignBit == staticIdx);
+
+#if USE_4x4_GRID
+                       int aa = aIdx & 3;
+                       int bb = bIdx & 3;
+                       if (aStatic)
+                               aa = bb;
+                       if (bStatic)
+                               bb = aa;
+
+                       int gridIndex = aa + bb * 4;
+                       int newIndex = gridTable4x4[gridIndex];
+#else   //USE_4x4_GRID
+                       int aa = aIdx & 7;
+                       int bb = bIdx & 7;
+                       if (aStatic)
+                               aa = bb;
+                       if (bStatic)
+                               bb = aa;
+
+                       int gridIndex = aa + bb * 8;
+                       int newIndex = gridTable8x8[gridIndex];
+#endif  //USE_4x4_GRID
+#endif  //USE_SPATIAL_BATCHING
+
+                       gSortDataOut[gIdx].x = newIndex;
+                       gSortDataOut[gIdx].y = gIdx;
+               }
+               else
+               {
+                       gSortDataOut[gIdx].x = 0xffffffff;
+               }
+       }
+}
+
+void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const b3Config& config, int static0Index)
+{
+       B3_PROFILE("solveContacts");
+       m_data->m_bodyBufferGPU->setFromOpenCLBuffer(bodyBuf, numBodies);
+       m_data->m_inertiaBufferGPU->setFromOpenCLBuffer(inertiaBuf, numBodies);
+       m_data->m_pBufContactOutGPU->setFromOpenCLBuffer(contactBuf, numContacts);
+
+       if (optionalSortContactsDeterminism)
+       {
+               if (!gCpuSortContactsDeterminism)
+               {
+                       B3_PROFILE("GPU Sort contact constraints (determinism)");
+
+                       m_data->m_pBufContactOutGPUCopy->resize(numContacts);
+                       m_data->m_contactKeyValues->resize(numContacts);
+
+                       m_data->m_pBufContactOutGPU->copyToCL(m_data->m_pBufContactOutGPUCopy->getBufferCL(), numContacts, 0, 0);
+
+                       {
+                               b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataChildShapeBKernel, "m_setDeterminismSortDataChildShapeBKernel");
+                               launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
+                               launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
+                               launcher.setConst(numContacts);
+                               launcher.launch1D(numContacts, 64);
+                       }
+                       m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
+                       {
+                               b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataChildShapeAKernel, "m_setDeterminismSortDataChildShapeAKernel");
+                               launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
+                               launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
+                               launcher.setConst(numContacts);
+                               launcher.launch1D(numContacts, 64);
+                       }
+                       m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
+                       {
+                               b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataBodyBKernel, "m_setDeterminismSortDataBodyBKernel");
+                               launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
+                               launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
+                               launcher.setConst(numContacts);
+                               launcher.launch1D(numContacts, 64);
+                       }
+
+                       m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
+
+                       {
+                               b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataBodyAKernel, "m_setDeterminismSortDataBodyAKernel");
+                               launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
+                               launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
+                               launcher.setConst(numContacts);
+                               launcher.launch1D(numContacts, 64);
+                       }
+
+                       m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
+
+                       {
+                               B3_PROFILE("gpu reorderContactKernel (determinism)");
+
+                               b3Int4 cdata;
+                               cdata.x = numContacts;
+
+                               //b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_data->m_pBufContactOutGPU->getBufferCL() ), b3BufferInfoCL( m_data->m_solverGPU->m_contactBuffer2->getBufferCL())
+                               //      , b3BufferInfoCL( m_data->m_solverGPU->m_sortDataBuffer->getBufferCL()) };
+                               b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_reorderContactKernel, "m_reorderContactKernel");
+                               launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
+                               launcher.setBuffer(m_data->m_pBufContactOutGPU->getBufferCL());
+                               launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
+                               launcher.setConst(cdata);
+                               launcher.launch1D(numContacts, 64);
+                       }
+               }
+               else
+               {
+                       B3_PROFILE("CPU Sort contact constraints (determinism)");
+                       b3AlignedObjectArray<b3Contact4> cpuConstraints;
+                       m_data->m_pBufContactOutGPU->copyToHost(cpuConstraints);
+                       bool sort = true;
+                       if (sort)
+                       {
+                               cpuConstraints.quickSort(b3ContactCmp);
+
+                               for (int i = 0; i < cpuConstraints.size(); i++)
+                               {
+                                       cpuConstraints[i].m_batchIdx = i;
+                               }
+                       }
+                       m_data->m_pBufContactOutGPU->copyFromHost(cpuConstraints);
+                       if (m_debugOutput == 100)
+                       {
+                               for (int i = 0; i < cpuConstraints.size(); i++)
+                               {
+                                       printf("c[%d].m_bodyA = %d, m_bodyB = %d, batchId = %d\n", i, cpuConstraints[i].m_bodyAPtrAndSignBit, cpuConstraints[i].m_bodyBPtrAndSignBit, cpuConstraints[i].m_batchIdx);
+                               }
+                       }
+
+                       m_debugOutput++;
+               }
+       }
+
+       int nContactOut = m_data->m_pBufContactOutGPU->size();
+
+       bool useSolver = true;
+
+       if (useSolver)
+       {
+               float dt = 1. / 60.;
+               b3ConstraintCfg csCfg(dt);
+               csCfg.m_enableParallelSolve = true;
+               csCfg.m_batchCellSize = 6;
+               csCfg.m_staticIdx = static0Index;
+
+               b3OpenCLArray<b3RigidBodyData>* bodyBuf = m_data->m_bodyBufferGPU;
+
+               void* additionalData = 0;  //m_data->m_frictionCGPU;
+               const b3OpenCLArray<b3InertiaData>* shapeBuf = m_data->m_inertiaBufferGPU;
+               b3OpenCLArray<b3GpuConstraint4>* contactConstraintOut = m_data->m_contactCGPU;
+               int nContacts = nContactOut;
+
+               int maxNumBatches = 0;
+
+               if (!gUseLargeBatches)
+               {
+                       if (m_data->m_solverGPU->m_contactBuffer2)
+                       {
+                               m_data->m_solverGPU->m_contactBuffer2->resize(nContacts);
+                       }
+
+                       if (m_data->m_solverGPU->m_contactBuffer2 == 0)
+                       {
+                               m_data->m_solverGPU->m_contactBuffer2 = new b3OpenCLArray<b3Contact4>(m_data->m_context, m_data->m_queue, nContacts);
+                               m_data->m_solverGPU->m_contactBuffer2->resize(nContacts);
+                       }
+
+                       //clFinish(m_data->m_queue);
+
+                       {
+                               B3_PROFILE("batching");
+                               //@todo: just reserve it, without copy of original contact (unless we use warmstarting)
+
+                               //const b3OpenCLArray<b3RigidBodyData>* bodyNative = bodyBuf;
+
+                               {
+                                       //b3OpenCLArray<b3RigidBodyData>* bodyNative = b3OpenCLArrayUtils::map<adl::TYPE_CL, true>( data->m_device, bodyBuf );
+                                       //b3OpenCLArray<b3Contact4>* contactNative = b3OpenCLArrayUtils::map<adl::TYPE_CL, true>( data->m_device, contactsIn );
+
+                                       const int sortAlignment = 512;  // todo. get this out of sort
+                                       if (csCfg.m_enableParallelSolve)
+                                       {
+                                               int sortSize = B3NEXTMULTIPLEOF(nContacts, sortAlignment);
+
+                                               b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
+                                               b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
+
+                                               if (!gCpuSetSortData)
+                                               {  //   2. set cell idx
+                                                       B3_PROFILE("GPU set cell idx");
+                                                       struct CB
+                                                       {
+                                                               int m_nContacts;
+                                                               int m_staticIdx;
+                                                               float m_scale;
+                                                               b3Int4 m_nSplit;
+                                                       };
+
+                                                       b3Assert(sortSize % 64 == 0);
+                                                       CB cdata;
+                                                       cdata.m_nContacts = nContacts;
+                                                       cdata.m_staticIdx = csCfg.m_staticIdx;
+                                                       cdata.m_scale = 1.f / csCfg.m_batchCellSize;
+                                                       cdata.m_nSplit.x = B3_SOLVER_N_SPLIT_X;
+                                                       cdata.m_nSplit.y = B3_SOLVER_N_SPLIT_Y;
+                                                       cdata.m_nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+                                                       m_data->m_solverGPU->m_sortDataBuffer->resize(nContacts);
+
+                                                       b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_data->m_pBufContactOutGPU->getBufferCL()), b3BufferInfoCL(bodyBuf->getBufferCL()), b3BufferInfoCL(m_data->m_solverGPU->m_sortDataBuffer->getBufferCL())};
+                                                       b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_setSortDataKernel, "m_setSortDataKernel");
+                                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                                       launcher.setConst(cdata.m_nContacts);
+                                                       launcher.setConst(cdata.m_scale);
+                                                       launcher.setConst(cdata.m_nSplit);
+                                                       launcher.setConst(cdata.m_staticIdx);
+
+                                                       launcher.launch1D(sortSize, 64);
+                                               }
+                                               else
+                                               {
+                                                       m_data->m_solverGPU->m_sortDataBuffer->resize(nContacts);
+                                                       b3AlignedObjectArray<b3SortData> sortDataCPU;
+                                                       m_data->m_solverGPU->m_sortDataBuffer->copyToHost(sortDataCPU);
+
+                                                       b3AlignedObjectArray<b3Contact4> contactCPU;
+                                                       m_data->m_pBufContactOutGPU->copyToHost(contactCPU);
+                                                       b3AlignedObjectArray<b3RigidBodyData> bodiesCPU;
+                                                       bodyBuf->copyToHost(bodiesCPU);
+                                                       float scale = 1.f / csCfg.m_batchCellSize;
+                                                       b3Int4 nSplit;
+                                                       nSplit.x = B3_SOLVER_N_SPLIT_X;
+                                                       nSplit.y = B3_SOLVER_N_SPLIT_Y;
+                                                       nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+                                                       SetSortDataCPU(&contactCPU[0], &bodiesCPU[0], &sortDataCPU[0], nContacts, scale, nSplit, csCfg.m_staticIdx);
+
+                                                       m_data->m_solverGPU->m_sortDataBuffer->copyFromHost(sortDataCPU);
+                                               }
+
+                                               if (!gCpuRadixSort)
+                                               {  //   3. sort by cell idx
+                                                       B3_PROFILE("gpuRadixSort");
+                                                       //int n = B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT;
+                                                       //int sortBit = 32;
+                                                       //if( n <= 0xffff ) sortBit = 16;
+                                                       //if( n <= 0xff ) sortBit = 8;
+                                                       //adl::RadixSort<adl::TYPE_CL>::execute( data->m_sort, *data->m_sortDataBuffer, sortSize );
+                                                       //adl::RadixSort32<adl::TYPE_CL>::execute( data->m_sort32, *data->m_sortDataBuffer, sortSize );
+                                                       b3OpenCLArray<b3SortData>& keyValuesInOut = *(m_data->m_solverGPU->m_sortDataBuffer);
+                                                       this->m_data->m_solverGPU->m_sort32->execute(keyValuesInOut);
+                                               }
+                                               else
+                                               {
+                                                       b3OpenCLArray<b3SortData>& keyValuesInOut = *(m_data->m_solverGPU->m_sortDataBuffer);
+                                                       b3AlignedObjectArray<b3SortData> hostValues;
+                                                       keyValuesInOut.copyToHost(hostValues);
+                                                       hostValues.quickSort(sortfnc);
+                                                       keyValuesInOut.copyFromHost(hostValues);
+                                               }
+
+                                               if (gUseScanHost)
+                                               {
+                                                       //      4. find entries
+                                                       B3_PROFILE("cpuBoundSearch");
+                                                       b3AlignedObjectArray<unsigned int> countsHost;
+                                                       countsNative->copyToHost(countsHost);
+
+                                                       b3AlignedObjectArray<b3SortData> sortDataHost;
+                                                       m_data->m_solverGPU->m_sortDataBuffer->copyToHost(sortDataHost);
+
+                                                       //m_data->m_solverGPU->m_search->executeHost(*m_data->m_solverGPU->m_sortDataBuffer,nContacts,*countsNative,B3_SOLVER_N_CELLS,b3BoundSearchCL::COUNT);
+                                                       m_data->m_solverGPU->m_search->executeHost(sortDataHost, nContacts, countsHost, B3_SOLVER_N_CELLS, b3BoundSearchCL::COUNT);
+
+                                                       countsNative->copyFromHost(countsHost);
+
+                                                       //adl::BoundSearch<adl::TYPE_CL>::execute( data->m_search, *data->m_sortDataBuffer, nContacts, *countsNative,
+                                                       //      B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT, adl::BoundSearchBase::COUNT );
+
+                                                       //unsigned int sum;
+                                                       //m_data->m_solverGPU->m_scan->execute(*countsNative,*offsetsNative, B3_SOLVER_N_CELLS);//,&sum );
+                                                       b3AlignedObjectArray<unsigned int> offsetsHost;
+                                                       offsetsHost.resize(offsetsNative->size());
+
+                                                       m_data->m_solverGPU->m_scan->executeHost(countsHost, offsetsHost, B3_SOLVER_N_CELLS);  //,&sum );
+                                                       offsetsNative->copyFromHost(offsetsHost);
+
+                                                       //printf("sum = %d\n",sum);
+                                               }
+                                               else
+                                               {
+                                                       //      4. find entries
+                                                       B3_PROFILE("gpuBoundSearch");
+                                                       m_data->m_solverGPU->m_search->execute(*m_data->m_solverGPU->m_sortDataBuffer, nContacts, *countsNative, B3_SOLVER_N_CELLS, b3BoundSearchCL::COUNT);
+                                                       m_data->m_solverGPU->m_scan->execute(*countsNative, *offsetsNative, B3_SOLVER_N_CELLS);  //,&sum );
+                                               }
+
+                                               if (nContacts)
+                                               {  //   5. sort constraints by cellIdx
+                                                       if (gReorderContactsOnCpu)
+                                                       {
+                                                               B3_PROFILE("cpu m_reorderContactKernel");
+                                                               b3AlignedObjectArray<b3SortData> sortDataHost;
+                                                               m_data->m_solverGPU->m_sortDataBuffer->copyToHost(sortDataHost);
+                                                               b3AlignedObjectArray<b3Contact4> inContacts;
+                                                               b3AlignedObjectArray<b3Contact4> outContacts;
+                                                               m_data->m_pBufContactOutGPU->copyToHost(inContacts);
+                                                               outContacts.resize(inContacts.size());
+                                                               for (int i = 0; i < nContacts; i++)
+                                                               {
+                                                                       int srcIdx = sortDataHost[i].y;
+                                                                       outContacts[i] = inContacts[srcIdx];
+                                                               }
+                                                               m_data->m_solverGPU->m_contactBuffer2->copyFromHost(outContacts);
+
+                                                               /*                                                              "void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )\n"
+                                                               "{\n"
+                                                               "       int nContacts = cb.x;\n"
+                                                               "       int gIdx = GET_GLOBAL_IDX;\n"
+                                                               "       if( gIdx < nContacts )\n"
+                                                               "       {\n"
+                                                               "               int srcIdx = sortData[gIdx].y;\n"
+                                                               "               out[gIdx] = in[srcIdx];\n"
+                                                               "       }\n"
+                                                               "}\n"
+                                                               */
+                                                       }
+                                                       else
+                                                       {
+                                                               B3_PROFILE("gpu m_reorderContactKernel");
+
+                                                               b3Int4 cdata;
+                                                               cdata.x = nContacts;
+
+                                                               b3BufferInfoCL bInfo[] = {
+                                                                       b3BufferInfoCL(m_data->m_pBufContactOutGPU->getBufferCL()),
+                                                                       b3BufferInfoCL(m_data->m_solverGPU->m_contactBuffer2->getBufferCL()), b3BufferInfoCL(m_data->m_solverGPU->m_sortDataBuffer->getBufferCL())};
+
+                                                               b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_reorderContactKernel, "m_reorderContactKernel");
+                                                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                                               launcher.setConst(cdata);
+                                                               launcher.launch1D(nContacts, 64);
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               //clFinish(m_data->m_queue);
+
+                               //                              {
+                               //                              b3AlignedObjectArray<unsigned int> histogram;
+                               //                              m_data->m_solverGPU->m_numConstraints->copyToHost(histogram);
+                               //                              printf(",,,\n");
+                               //                              }
+
+                               if (nContacts)
+                               {
+                                       if (gUseCpuCopyConstraints)
+                                       {
+                                               for (int i = 0; i < nContacts; i++)
+                                               {
+                                                       m_data->m_pBufContactOutGPU->copyFromOpenCLArray(*m_data->m_solverGPU->m_contactBuffer2);
+                                                       //                                                      m_data->m_solverGPU->m_contactBuffer2->getBufferCL();
+                                                       //                                              m_data->m_pBufContactOutGPU->getBufferCL()
+                                               }
+                                       }
+                                       else
+                                       {
+                                               B3_PROFILE("gpu m_copyConstraintKernel");
+                                               b3Int4 cdata;
+                                               cdata.x = nContacts;
+                                               b3BufferInfoCL bInfo[] = {
+                                                       b3BufferInfoCL(m_data->m_solverGPU->m_contactBuffer2->getBufferCL()),
+                                                       b3BufferInfoCL(m_data->m_pBufContactOutGPU->getBufferCL())};
+
+                                               b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_copyConstraintKernel, "m_copyConstraintKernel");
+                                               launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                               launcher.setConst(cdata);
+                                               launcher.launch1D(nContacts, 64);
+                                               //we use the clFinish for proper benchmark/profile
+                                               clFinish(m_data->m_queue);
+                                       }
+                               }
+
+                               //                              bool compareGPU = false;
+                               if (nContacts)
+                               {
+                                       if (!gCpuBatchContacts)
+                                       {
+                                               B3_PROFILE("gpu batchContacts");
+                                               maxNumBatches = 250;  //250;
+                                               m_data->m_solverGPU->batchContacts(m_data->m_pBufContactOutGPU, nContacts, m_data->m_solverGPU->m_numConstraints, m_data->m_solverGPU->m_offsets, csCfg.m_staticIdx);
+                                               clFinish(m_data->m_queue);
+                                       }
+                                       else
+                                       {
+                                               B3_PROFILE("cpu batchContacts");
+                                               static b3AlignedObjectArray<b3Contact4> cpuContacts;
+                                               b3OpenCLArray<b3Contact4>* contactsIn = m_data->m_solverGPU->m_contactBuffer2;
+                                               {
+                                                       B3_PROFILE("copyToHost");
+                                                       contactsIn->copyToHost(cpuContacts);
+                                               }
+                                               b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
+                                               b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
+
+                                               b3AlignedObjectArray<unsigned int> nNativeHost;
+                                               b3AlignedObjectArray<unsigned int> offsetsNativeHost;
+
+                                               {
+                                                       B3_PROFILE("countsNative/offsetsNative copyToHost");
+                                                       countsNative->copyToHost(nNativeHost);
+                                                       offsetsNative->copyToHost(offsetsNativeHost);
+                                               }
+
+                                               int numNonzeroGrid = 0;
+
+                                               if (gUseLargeBatches)
+                                               {
+                                                       m_data->m_batchSizes.resize(B3_MAX_NUM_BATCHES);
+                                                       int totalNumConstraints = cpuContacts.size();
+                                                       //int simdWidth =numBodies+1;//-1;//64;//-1;//32;
+                                                       int numBatches = sortConstraintByBatch3(&cpuContacts[0], totalNumConstraints, totalNumConstraints + 1, csCfg.m_staticIdx, numBodies, &m_data->m_batchSizes[0]);  //     on GPU
+                                                       maxNumBatches = b3Max(numBatches, maxNumBatches);
+                                                       static int globalMaxBatch = 0;
+                                                       if (maxNumBatches > globalMaxBatch)
+                                                       {
+                                                               globalMaxBatch = maxNumBatches;
+                                                               b3Printf("maxNumBatches = %d\n", maxNumBatches);
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       m_data->m_batchSizes.resize(B3_SOLVER_N_CELLS * B3_MAX_NUM_BATCHES);
+                                                       B3_PROFILE("cpu batch grid");
+                                                       for (int i = 0; i < B3_SOLVER_N_CELLS; i++)
+                                                       {
+                                                               int n = (nNativeHost)[i];
+                                                               int offset = (offsetsNativeHost)[i];
+                                                               if (n)
+                                                               {
+                                                                       numNonzeroGrid++;
+                                                                       int simdWidth = numBodies + 1;                                                                                                                                 //-1;//64;//-1;//32;
+                                                                       int numBatches = sortConstraintByBatch3(&cpuContacts[0] + offset, n, simdWidth, csCfg.m_staticIdx, numBodies, &m_data->m_batchSizes[i * B3_MAX_NUM_BATCHES]);  //       on GPU
+                                                                       maxNumBatches = b3Max(numBatches, maxNumBatches);
+                                                                       static int globalMaxBatch = 0;
+                                                                       if (maxNumBatches > globalMaxBatch)
+                                                                       {
+                                                                               globalMaxBatch = maxNumBatches;
+                                                                               b3Printf("maxNumBatches = %d\n", maxNumBatches);
+                                                                       }
+                                                                       //we use the clFinish for proper benchmark/profile
+                                                               }
+                                                       }
+                                                       //clFinish(m_data->m_queue);
+                                               }
+                                               {
+                                                       B3_PROFILE("m_contactBuffer->copyFromHost");
+                                                       m_data->m_solverGPU->m_contactBuffer2->copyFromHost((b3AlignedObjectArray<b3Contact4>&)cpuContacts);
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               //printf("maxNumBatches = %d\n", maxNumBatches);
+
+               if (gUseLargeBatches)
+               {
+                       if (nContacts)
+                       {
+                               B3_PROFILE("cpu batchContacts");
+                               static b3AlignedObjectArray<b3Contact4> cpuContacts;
+                               //                              b3OpenCLArray<b3Contact4>* contactsIn = m_data->m_solverGPU->m_contactBuffer2;
+                               {
+                                       B3_PROFILE("copyToHost");
+                                       m_data->m_pBufContactOutGPU->copyToHost(cpuContacts);
+                               }
+                               //                              b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
+                               //                              b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
+
+                               //                              int numNonzeroGrid=0;
+
+                               {
+                                       m_data->m_batchSizes.resize(B3_MAX_NUM_BATCHES);
+                                       int totalNumConstraints = cpuContacts.size();
+                                       //                              int simdWidth =numBodies+1;//-1;//64;//-1;//32;
+                                       int numBatches = sortConstraintByBatch3(&cpuContacts[0], totalNumConstraints, totalNumConstraints + 1, csCfg.m_staticIdx, numBodies, &m_data->m_batchSizes[0]);  //     on GPU
+                                       maxNumBatches = b3Max(numBatches, maxNumBatches);
+                                       static int globalMaxBatch = 0;
+                                       if (maxNumBatches > globalMaxBatch)
+                                       {
+                                               globalMaxBatch = maxNumBatches;
+                                               b3Printf("maxNumBatches = %d\n", maxNumBatches);
+                                       }
+                               }
+                               {
+                                       B3_PROFILE("m_contactBuffer->copyFromHost");
+                                       m_data->m_solverGPU->m_contactBuffer2->copyFromHost((b3AlignedObjectArray<b3Contact4>&)cpuContacts);
+                               }
+                       }
+               }
+
+               if (nContacts)
+               {
+                       B3_PROFILE("gpu convertToConstraints");
+                       m_data->m_solverGPU->convertToConstraints(bodyBuf,
+                                                                                                         shapeBuf, m_data->m_solverGPU->m_contactBuffer2,
+                                                                                                         contactConstraintOut,
+                                                                                                         additionalData, nContacts,
+                                                                                                         (b3SolverBase::ConstraintCfg&)csCfg);
+                       clFinish(m_data->m_queue);
+               }
+
+               if (1)
+               {
+                       int numIter = 4;
+
+                       m_data->m_solverGPU->m_nIterations = numIter;  //10
+                       if (!gCpuSolveConstraint)
+                       {
+                               B3_PROFILE("GPU solveContactConstraint");
+
+                               /*m_data->m_solverGPU->solveContactConstraint(
+                               m_data->m_bodyBufferGPU, 
+                               m_data->m_inertiaBufferGPU,
+                               m_data->m_contactCGPU,0,
+                               nContactOut ,
+                               maxNumBatches);
+                               */
+
+                               //m_data->m_batchSizesGpu->copyFromHost(m_data->m_batchSizes);
+
+                               if (gUseLargeBatches)
+                               {
+                                       solveContactConstraintBatchSizes(m_data->m_bodyBufferGPU,
+                                                                                                        m_data->m_inertiaBufferGPU,
+                                                                                                        m_data->m_contactCGPU, 0,
+                                                                                                        nContactOut,
+                                                                                                        maxNumBatches, numIter, &m_data->m_batchSizes);
+                               }
+                               else
+                               {
+                                       solveContactConstraint(
+                                               m_data->m_bodyBufferGPU,
+                                               m_data->m_inertiaBufferGPU,
+                                               m_data->m_contactCGPU, 0,
+                                               nContactOut,
+                                               maxNumBatches, numIter, &m_data->m_batchSizes);  //m_data->m_batchSizesGpu);
+                               }
+                       }
+                       else
+                       {
+                               B3_PROFILE("Host solveContactConstraint");
+
+                               m_data->m_solverGPU->solveContactConstraintHost(m_data->m_bodyBufferGPU, m_data->m_inertiaBufferGPU, m_data->m_contactCGPU, 0, nContactOut, maxNumBatches, &m_data->m_batchSizes);
+                       }
+               }
+
+#if 0
+        if (0)
+        {
+            B3_PROFILE("read body velocities back to CPU");
+            //read body updated linear/angular velocities back to CPU
+            m_data->m_bodyBufferGPU->read(
+                                                  m_data->m_bodyBufferCPU->m_ptr,numOfConvexRBodies);
+            adl::DeviceUtils::waitForCompletion( m_data->m_deviceCL );
+        }
+#endif
+       }
+}
+
+void b3GpuPgsContactSolver::batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx)
+{
+}
+
+b3AlignedObjectArray<unsigned int> idxBuffer;
+b3AlignedObjectArray<b3SortData> sortData;
+b3AlignedObjectArray<b3Contact4> old;
+
+inline int b3GpuPgsContactSolver::sortConstraintByBatch(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies)
+{
+       B3_PROFILE("sortConstraintByBatch");
+       int numIter = 0;
+
+       sortData.resize(n);
+       idxBuffer.resize(n);
+       old.resize(n);
+
+       unsigned int* idxSrc = &idxBuffer[0];
+       unsigned int* idxDst = &idxBuffer[0];
+       int nIdxSrc, nIdxDst;
+
+       const int N_FLG = 256;
+       const int FLG_MASK = N_FLG - 1;
+       unsigned int flg[N_FLG / 32];
+#if defined(_DEBUG)
+       for (int i = 0; i < n; i++)
+               cs[i].getBatchIdx() = -1;
+#endif
+       for (int i = 0; i < n; i++)
+               idxSrc[i] = i;
+       nIdxSrc = n;
+
+       int batchIdx = 0;
+
+       {
+               B3_PROFILE("cpu batch innerloop");
+               while (nIdxSrc)
+               {
+                       numIter++;
+                       nIdxDst = 0;
+                       int nCurrentBatch = 0;
+
+                       //      clear flag
+                       for (int i = 0; i < N_FLG / 32; i++) flg[i] = 0;
+
+                       for (int i = 0; i < nIdxSrc; i++)
+                       {
+                               int idx = idxSrc[i];
+
+                               b3Assert(idx < n);
+                               //      check if it can go
+                               int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
+                               int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
+
+                               int bodyA = abs(bodyAS);
+                               int bodyB = abs(bodyBS);
+
+                               int aIdx = bodyA & FLG_MASK;
+                               int bIdx = bodyB & FLG_MASK;
+
+                               unsigned int aUnavailable = flg[aIdx / 32] & (1 << (aIdx & 31));
+                               unsigned int bUnavailable = flg[bIdx / 32] & (1 << (bIdx & 31));
+
+                               bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
+                               bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
+
+                               //use inv_mass!
+                               aUnavailable = !aIsStatic ? aUnavailable : 0;  //
+                               bUnavailable = !bIsStatic ? bUnavailable : 0;
+
+                               if (aUnavailable == 0 && bUnavailable == 0)  // ok
+                               {
+                                       if (!aIsStatic)
+                                               flg[aIdx / 32] |= (1 << (aIdx & 31));
+                                       if (!bIsStatic)
+                                               flg[bIdx / 32] |= (1 << (bIdx & 31));
+
+                                       cs[idx].getBatchIdx() = batchIdx;
+                                       sortData[idx].m_key = batchIdx;
+                                       sortData[idx].m_value = idx;
+
+                                       {
+                                               nCurrentBatch++;
+                                               if (nCurrentBatch == simdWidth)
+                                               {
+                                                       nCurrentBatch = 0;
+                                                       for (int i = 0; i < N_FLG / 32; i++) flg[i] = 0;
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       idxDst[nIdxDst++] = idx;
+                               }
+                       }
+                       b3Swap(idxSrc, idxDst);
+                       b3Swap(nIdxSrc, nIdxDst);
+                       batchIdx++;
+               }
+       }
+       {
+               B3_PROFILE("quickSort");
+               sortData.quickSort(sortfnc);
+       }
+
+       {
+               B3_PROFILE("reorder");
+               //      reorder
+
+               memcpy(&old[0], cs, sizeof(b3Contact4) * n);
+               for (int i = 0; i < n; i++)
+               {
+                       int idx = sortData[i].m_value;
+                       cs[i] = old[idx];
+               }
+       }
+
+#if defined(_DEBUG)
+       //              debugPrintf( "nBatches: %d\n", batchIdx );
+       for (int i = 0; i < n; i++)
+       {
+               b3Assert(cs[i].getBatchIdx() != -1);
+       }
+#endif
+       return batchIdx;
+}
+
+b3AlignedObjectArray<int> bodyUsed2;
+
+inline int b3GpuPgsContactSolver::sortConstraintByBatch2(b3Contact4* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies)
+{
+       B3_PROFILE("sortConstraintByBatch2");
+
+       bodyUsed2.resize(2 * simdWidth);
+
+       for (int q = 0; q < 2 * simdWidth; q++)
+               bodyUsed2[q] = 0;
+
+       int curBodyUsed = 0;
+
+       int numIter = 0;
+
+       m_data->m_sortData.resize(numConstraints);
+       m_data->m_idxBuffer.resize(numConstraints);
+       m_data->m_old.resize(numConstraints);
+
+       unsigned int* idxSrc = &m_data->m_idxBuffer[0];
+
+#if defined(_DEBUG)
+       for (int i = 0; i < numConstraints; i++)
+               cs[i].getBatchIdx() = -1;
+#endif
+       for (int i = 0; i < numConstraints; i++)
+               idxSrc[i] = i;
+
+       int numValidConstraints = 0;
+       //      int unprocessedConstraintIndex = 0;
+
+       int batchIdx = 0;
+
+       {
+               B3_PROFILE("cpu batch innerloop");
+
+               while (numValidConstraints < numConstraints)
+               {
+                       numIter++;
+                       int nCurrentBatch = 0;
+                       //      clear flag
+                       for (int i = 0; i < curBodyUsed; i++)
+                               bodyUsed2[i] = 0;
+                       curBodyUsed = 0;
+
+                       for (int i = numValidConstraints; i < numConstraints; i++)
+                       {
+                               int idx = idxSrc[i];
+                               b3Assert(idx < numConstraints);
+                               //      check if it can go
+                               int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
+                               int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
+                               int bodyA = abs(bodyAS);
+                               int bodyB = abs(bodyBS);
+                               bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
+                               bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
+                               int aUnavailable = 0;
+                               int bUnavailable = 0;
+                               if (!aIsStatic)
+                               {
+                                       for (int j = 0; j < curBodyUsed; j++)
+                                       {
+                                               if (bodyA == bodyUsed2[j])
+                                               {
+                                                       aUnavailable = 1;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if (!aUnavailable)
+                                       if (!bIsStatic)
+                                       {
+                                               for (int j = 0; j < curBodyUsed; j++)
+                                               {
+                                                       if (bodyB == bodyUsed2[j])
+                                                       {
+                                                               bUnavailable = 1;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+
+                               if (aUnavailable == 0 && bUnavailable == 0)  // ok
+                               {
+                                       if (!aIsStatic)
+                                       {
+                                               bodyUsed2[curBodyUsed++] = bodyA;
+                                       }
+                                       if (!bIsStatic)
+                                       {
+                                               bodyUsed2[curBodyUsed++] = bodyB;
+                                       }
+
+                                       cs[idx].getBatchIdx() = batchIdx;
+                                       m_data->m_sortData[idx].m_key = batchIdx;
+                                       m_data->m_sortData[idx].m_value = idx;
+
+                                       if (i != numValidConstraints)
+                                       {
+                                               b3Swap(idxSrc[i], idxSrc[numValidConstraints]);
+                                       }
+
+                                       numValidConstraints++;
+                                       {
+                                               nCurrentBatch++;
+                                               if (nCurrentBatch == simdWidth)
+                                               {
+                                                       nCurrentBatch = 0;
+                                                       for (int i = 0; i < curBodyUsed; i++)
+                                                               bodyUsed2[i] = 0;
+
+                                                       curBodyUsed = 0;
+                                               }
+                                       }
+                               }
+                       }
+
+                       batchIdx++;
+               }
+       }
+       {
+               B3_PROFILE("quickSort");
+               //m_data->m_sortData.quickSort(sortfnc);
+       }
+
+       {
+               B3_PROFILE("reorder");
+               //      reorder
+
+               memcpy(&m_data->m_old[0], cs, sizeof(b3Contact4) * numConstraints);
+
+               for (int i = 0; i < numConstraints; i++)
+               {
+                       b3Assert(m_data->m_sortData[idxSrc[i]].m_value == idxSrc[i]);
+                       int idx = m_data->m_sortData[idxSrc[i]].m_value;
+                       cs[i] = m_data->m_old[idx];
+               }
+       }
+
+#if defined(_DEBUG)
+       //              debugPrintf( "nBatches: %d\n", batchIdx );
+       for (int i = 0; i < numConstraints; i++)
+       {
+               b3Assert(cs[i].getBatchIdx() != -1);
+       }
+#endif
+
+       return batchIdx;
+}
+
+b3AlignedObjectArray<int> bodyUsed;
+b3AlignedObjectArray<int> curUsed;
+
+inline int b3GpuPgsContactSolver::sortConstraintByBatch3(b3Contact4* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies, int* batchSizes)
+{
+       B3_PROFILE("sortConstraintByBatch3");
+
+       static int maxSwaps = 0;
+       int numSwaps = 0;
+
+       curUsed.resize(2 * simdWidth);
+
+       static int maxNumConstraints = 0;
+       if (maxNumConstraints < numConstraints)
+       {
+               maxNumConstraints = numConstraints;
+               //printf("maxNumConstraints  = %d\n",maxNumConstraints );
+       }
+
+       int numUsedArray = numBodies / 32 + 1;
+       bodyUsed.resize(numUsedArray);
+
+       for (int q = 0; q < numUsedArray; q++)
+               bodyUsed[q] = 0;
+
+       int curBodyUsed = 0;
+
+       int numIter = 0;
+
+       m_data->m_sortData.resize(0);
+       m_data->m_idxBuffer.resize(0);
+       m_data->m_old.resize(0);
+
+#if defined(_DEBUG)
+       for (int i = 0; i < numConstraints; i++)
+               cs[i].getBatchIdx() = -1;
+#endif
+
+       int numValidConstraints = 0;
+       //      int unprocessedConstraintIndex = 0;
+
+       int batchIdx = 0;
+
+       {
+               B3_PROFILE("cpu batch innerloop");
+
+               while (numValidConstraints < numConstraints)
+               {
+                       numIter++;
+                       int nCurrentBatch = 0;
+                       batchSizes[batchIdx] = 0;
+
+                       //      clear flag
+                       for (int i = 0; i < curBodyUsed; i++)
+                               bodyUsed[curUsed[i] / 32] = 0;
+
+                       curBodyUsed = 0;
+
+                       for (int i = numValidConstraints; i < numConstraints; i++)
+                       {
+                               int idx = i;
+                               b3Assert(idx < numConstraints);
+                               //      check if it can go
+                               int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
+                               int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
+                               int bodyA = abs(bodyAS);
+                               int bodyB = abs(bodyBS);
+                               bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
+                               bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
+                               int aUnavailable = 0;
+                               int bUnavailable = 0;
+                               if (!aIsStatic)
+                               {
+                                       aUnavailable = bodyUsed[bodyA / 32] & (1 << (bodyA & 31));
+                               }
+                               if (!aUnavailable)
+                                       if (!bIsStatic)
+                                       {
+                                               bUnavailable = bodyUsed[bodyB / 32] & (1 << (bodyB & 31));
+                                       }
+
+                               if (aUnavailable == 0 && bUnavailable == 0)  // ok
+                               {
+                                       if (!aIsStatic)
+                                       {
+                                               bodyUsed[bodyA / 32] |= (1 << (bodyA & 31));
+                                               curUsed[curBodyUsed++] = bodyA;
+                                       }
+                                       if (!bIsStatic)
+                                       {
+                                               bodyUsed[bodyB / 32] |= (1 << (bodyB & 31));
+                                               curUsed[curBodyUsed++] = bodyB;
+                                       }
+
+                                       cs[idx].getBatchIdx() = batchIdx;
+
+                                       if (i != numValidConstraints)
+                                       {
+                                               b3Swap(cs[i], cs[numValidConstraints]);
+                                               numSwaps++;
+                                       }
+
+                                       numValidConstraints++;
+                                       {
+                                               nCurrentBatch++;
+                                               if (nCurrentBatch == simdWidth)
+                                               {
+                                                       batchSizes[batchIdx] += simdWidth;
+                                                       nCurrentBatch = 0;
+                                                       for (int i = 0; i < curBodyUsed; i++)
+                                                               bodyUsed[curUsed[i] / 32] = 0;
+                                                       curBodyUsed = 0;
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (batchIdx >= B3_MAX_NUM_BATCHES)
+                       {
+                               b3Error("batchIdx>=B3_MAX_NUM_BATCHES");
+                               b3Assert(0);
+                               break;
+                       }
+
+                       batchSizes[batchIdx] += nCurrentBatch;
+
+                       batchIdx++;
+               }
+       }
+
+#if defined(_DEBUG)
+       //              debugPrintf( "nBatches: %d\n", batchIdx );
+       for (int i = 0; i < numConstraints; i++)
+       {
+               b3Assert(cs[i].getBatchIdx() != -1);
+       }
+#endif
+
+       batchSizes[batchIdx] = 0;
+
+       if (maxSwaps < numSwaps)
+       {
+               maxSwaps = numSwaps;
+               //printf("maxSwaps = %d\n", maxSwaps);
+       }
+
+       return batchIdx;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h
new file mode 100644 (file)
index 0000000..6ab7502
--- /dev/null
@@ -0,0 +1,37 @@
+
+#ifndef B3_GPU_BATCHING_PGS_SOLVER_H
+#define B3_GPU_BATCHING_PGS_SOLVER_H
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "b3GpuConstraint4.h"
+
+class b3GpuPgsContactSolver
+{
+protected:
+       int m_debugOutput;
+
+       struct b3GpuBatchingPgsSolverInternalData* m_data;
+
+       void batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx);
+
+       inline int sortConstraintByBatch(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies);
+       inline int sortConstraintByBatch2(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies);
+       inline int sortConstraintByBatch3(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies, int* batchSizes);
+
+       void solveContactConstraintBatchSizes(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+                                                                                 b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes);  //const b3OpenCLArray<int>* gpuBatchSizes);
+
+       void solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+                                                               b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes);  //const b3OpenCLArray<int>* gpuBatchSizes);
+
+public:
+       b3GpuPgsContactSolver(cl_context ctx, cl_device_id device, cl_command_queue q, int pairCapacity);
+       virtual ~b3GpuPgsContactSolver();
+
+       void solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index);
+};
+
+#endif  //B3_GPU_BATCHING_PGS_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp
new file mode 100644 (file)
index 0000000..fef33ad
--- /dev/null
@@ -0,0 +1,677 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#include "b3GpuRigidBodyPipeline.h"
+#include "b3GpuRigidBodyPipelineInternalData.h"
+#include "kernels/integrateKernel.h"
+#include "kernels/updateAabbsKernel.h"
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+#include "b3GpuNarrowPhase.h"
+#include "Bullet3Geometry/b3AabbUtil.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
+#include "Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h"
+#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
+
+//#define TEST_OTHER_GPU_SOLVER
+
+#define B3_RIGIDBODY_INTEGRATE_PATH "src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl"
+#define B3_RIGIDBODY_UPDATEAABB_PATH "src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl"
+
+bool useBullet2CpuSolver = true;
+
+//choice of contact solver
+bool gUseJacobi = false;
+bool gUseDbvt = false;
+bool gDumpContactStats = false;
+bool gCalcWorldSpaceAabbOnCpu = false;
+bool gUseCalculateOverlappingPairsHost = false;
+bool gIntegrateOnCpu = false;
+bool gClearPairsOnGpu = true;
+
+#define TEST_OTHER_GPU_SOLVER 1
+#ifdef TEST_OTHER_GPU_SOLVER
+#include "b3GpuJacobiContactSolver.h"
+#endif  //TEST_OTHER_GPU_SOLVER
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+#include "Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h"
+
+#include "b3GpuPgsContactSolver.h"
+#include "b3Solver.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+#include "Bullet3OpenCL/Raycast/b3GpuRaycast.h"
+
+#include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
+#include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h"
+
+b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx, cl_device_id device, cl_command_queue q, class b3GpuNarrowPhase* narrowphase, class b3GpuBroadphaseInterface* broadphaseSap, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
+{
+       m_data = new b3GpuRigidBodyPipelineInternalData;
+       m_data->m_constraintUid = 0;
+       m_data->m_config = config;
+       m_data->m_context = ctx;
+       m_data->m_device = device;
+       m_data->m_queue = q;
+
+       m_data->m_solver = new b3PgsJacobiSolver(true);                            //new b3PgsJacobiSolver(true);
+       m_data->m_gpuSolver = new b3GpuPgsConstraintSolver(ctx, device, q, true);  //new b3PgsJacobiSolver(true);
+
+       m_data->m_allAabbsGPU = new b3OpenCLArray<b3SapAabb>(ctx, q, config.m_maxConvexBodies);
+       m_data->m_overlappingPairsGPU = new b3OpenCLArray<b3BroadphasePair>(ctx, q, config.m_maxBroadphasePairs);
+
+       m_data->m_gpuConstraints = new b3OpenCLArray<b3GpuGenericConstraint>(ctx, q);
+#ifdef TEST_OTHER_GPU_SOLVER
+       m_data->m_solver3 = new b3GpuJacobiContactSolver(ctx, device, q, config.m_maxBroadphasePairs);
+#endif  //     TEST_OTHER_GPU_SOLVER
+
+       m_data->m_solver2 = new b3GpuPgsContactSolver(ctx, device, q, config.m_maxBroadphasePairs);
+
+       m_data->m_raycaster = new b3GpuRaycast(ctx, device, q);
+
+       m_data->m_broadphaseDbvt = broadphaseDbvt;
+       m_data->m_broadphaseSap = broadphaseSap;
+       m_data->m_narrowphase = narrowphase;
+       m_data->m_gravity.setValue(0.f, -9.8f, 0.f);
+
+       cl_int errNum = 0;
+
+       {
+               cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context, m_data->m_device, integrateKernelCL, &errNum, "", B3_RIGIDBODY_INTEGRATE_PATH);
+               b3Assert(errNum == CL_SUCCESS);
+               m_data->m_integrateTransformsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, integrateKernelCL, "integrateTransformsKernel", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+               clReleaseProgram(prog);
+       }
+       {
+               cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context, m_data->m_device, updateAabbsKernelCL, &errNum, "", B3_RIGIDBODY_UPDATEAABB_PATH);
+               b3Assert(errNum == CL_SUCCESS);
+               m_data->m_updateAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, updateAabbsKernelCL, "initializeGpuAabbsFull", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+
+               m_data->m_clearOverlappingPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, updateAabbsKernelCL, "clearOverlappingPairsKernel", &errNum, prog);
+               b3Assert(errNum == CL_SUCCESS);
+
+               clReleaseProgram(prog);
+       }
+}
+
+b3GpuRigidBodyPipeline::~b3GpuRigidBodyPipeline()
+{
+       if (m_data->m_integrateTransformsKernel)
+               clReleaseKernel(m_data->m_integrateTransformsKernel);
+
+       if (m_data->m_updateAabbsKernel)
+               clReleaseKernel(m_data->m_updateAabbsKernel);
+
+       if (m_data->m_clearOverlappingPairsKernel)
+               clReleaseKernel(m_data->m_clearOverlappingPairsKernel);
+       delete m_data->m_raycaster;
+       delete m_data->m_solver;
+       delete m_data->m_allAabbsGPU;
+       delete m_data->m_gpuConstraints;
+       delete m_data->m_overlappingPairsGPU;
+
+#ifdef TEST_OTHER_GPU_SOLVER
+       delete m_data->m_solver3;
+#endif  //TEST_OTHER_GPU_SOLVER
+
+       delete m_data->m_solver2;
+
+       delete m_data;
+}
+
+void b3GpuRigidBodyPipeline::reset()
+{
+       m_data->m_gpuConstraints->resize(0);
+       m_data->m_cpuConstraints.resize(0);
+       m_data->m_allAabbsGPU->resize(0);
+       m_data->m_allAabbsCPU.resize(0);
+}
+
+void b3GpuRigidBodyPipeline::addConstraint(b3TypedConstraint* constraint)
+{
+       m_data->m_joints.push_back(constraint);
+}
+
+void b3GpuRigidBodyPipeline::removeConstraint(b3TypedConstraint* constraint)
+{
+       m_data->m_joints.remove(constraint);
+}
+
+void b3GpuRigidBodyPipeline::removeConstraintByUid(int uid)
+{
+       m_data->m_gpuSolver->recomputeBatches();
+       //slow linear search
+       m_data->m_gpuConstraints->copyToHost(m_data->m_cpuConstraints);
+       //remove
+       for (int i = 0; i < m_data->m_cpuConstraints.size(); i++)
+       {
+               if (m_data->m_cpuConstraints[i].m_uid == uid)
+               {
+                       //m_data->m_cpuConstraints.remove(m_data->m_cpuConstraints[i]);
+                       m_data->m_cpuConstraints.swap(i, m_data->m_cpuConstraints.size() - 1);
+                       m_data->m_cpuConstraints.pop_back();
+
+                       break;
+               }
+       }
+
+       if (m_data->m_cpuConstraints.size())
+       {
+               m_data->m_gpuConstraints->copyFromHost(m_data->m_cpuConstraints);
+       }
+       else
+       {
+               m_data->m_gpuConstraints->resize(0);
+       }
+}
+int b3GpuRigidBodyPipeline::createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, float breakingThreshold)
+{
+       m_data->m_gpuSolver->recomputeBatches();
+       b3GpuGenericConstraint c;
+       c.m_uid = m_data->m_constraintUid;
+       m_data->m_constraintUid++;
+       c.m_flags = B3_CONSTRAINT_FLAG_ENABLED;
+       c.m_rbA = bodyA;
+       c.m_rbB = bodyB;
+       c.m_pivotInA.setValue(pivotInA[0], pivotInA[1], pivotInA[2]);
+       c.m_pivotInB.setValue(pivotInB[0], pivotInB[1], pivotInB[2]);
+       c.m_breakingImpulseThreshold = breakingThreshold;
+       c.m_constraintType = B3_GPU_POINT2POINT_CONSTRAINT_TYPE;
+       m_data->m_cpuConstraints.push_back(c);
+       return c.m_uid;
+}
+int b3GpuRigidBodyPipeline::createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold)
+{
+       m_data->m_gpuSolver->recomputeBatches();
+       b3GpuGenericConstraint c;
+       c.m_uid = m_data->m_constraintUid;
+       m_data->m_constraintUid++;
+       c.m_flags = B3_CONSTRAINT_FLAG_ENABLED;
+       c.m_rbA = bodyA;
+       c.m_rbB = bodyB;
+       c.m_pivotInA.setValue(pivotInA[0], pivotInA[1], pivotInA[2]);
+       c.m_pivotInB.setValue(pivotInB[0], pivotInB[1], pivotInB[2]);
+       c.m_relTargetAB.setValue(relTargetAB[0], relTargetAB[1], relTargetAB[2], relTargetAB[3]);
+       c.m_breakingImpulseThreshold = breakingThreshold;
+       c.m_constraintType = B3_GPU_FIXED_CONSTRAINT_TYPE;
+
+       m_data->m_cpuConstraints.push_back(c);
+       return c.m_uid;
+}
+
+void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
+{
+       //update worldspace AABBs from local AABB/worldtransform
+       {
+               B3_PROFILE("setupGpuAabbs");
+               setupGpuAabbsFull();
+       }
+
+       int numPairs = 0;
+
+       //compute overlapping pairs
+       {
+               if (gUseDbvt)
+               {
+                       {
+                               B3_PROFILE("setAabb");
+                               m_data->m_allAabbsGPU->copyToHost(m_data->m_allAabbsCPU);
+                               for (int i = 0; i < m_data->m_allAabbsCPU.size(); i++)
+                               {
+                                       b3Vector3 aabbMin = b3MakeVector3(m_data->m_allAabbsCPU[i].m_min[0], m_data->m_allAabbsCPU[i].m_min[1], m_data->m_allAabbsCPU[i].m_min[2]);
+                                       b3Vector3 aabbMax = b3MakeVector3(m_data->m_allAabbsCPU[i].m_max[0], m_data->m_allAabbsCPU[i].m_max[1], m_data->m_allAabbsCPU[i].m_max[2]);
+                                       m_data->m_broadphaseDbvt->setAabb(i, aabbMin, aabbMax, 0);
+                               }
+                       }
+
+                       {
+                               B3_PROFILE("calculateOverlappingPairs");
+                               m_data->m_broadphaseDbvt->calculateOverlappingPairs();
+                       }
+                       numPairs = m_data->m_broadphaseDbvt->getOverlappingPairCache()->getNumOverlappingPairs();
+               }
+               else
+               {
+                       if (gUseCalculateOverlappingPairsHost)
+                       {
+                               m_data->m_broadphaseSap->calculateOverlappingPairsHost(m_data->m_config.m_maxBroadphasePairs);
+                       }
+                       else
+                       {
+                               m_data->m_broadphaseSap->calculateOverlappingPairs(m_data->m_config.m_maxBroadphasePairs);
+                       }
+                       numPairs = m_data->m_broadphaseSap->getNumOverlap();
+               }
+       }
+
+       //compute contact points
+       //      printf("numPairs=%d\n",numPairs);
+
+       int numContacts = 0;
+
+       int numBodies = m_data->m_narrowphase->getNumRigidBodies();
+
+       if (numPairs)
+       {
+               cl_mem pairs = 0;
+               cl_mem aabbsWS = 0;
+               if (gUseDbvt)
+               {
+                       B3_PROFILE("m_overlappingPairsGPU->copyFromHost");
+                       m_data->m_overlappingPairsGPU->copyFromHost(m_data->m_broadphaseDbvt->getOverlappingPairCache()->getOverlappingPairArray());
+                       pairs = m_data->m_overlappingPairsGPU->getBufferCL();
+                       aabbsWS = m_data->m_allAabbsGPU->getBufferCL();
+               }
+               else
+               {
+                       pairs = m_data->m_broadphaseSap->getOverlappingPairBuffer();
+                       aabbsWS = m_data->m_broadphaseSap->getAabbBufferWS();
+               }
+
+               m_data->m_overlappingPairsGPU->resize(numPairs);
+
+               //mark the contacts for each pair as 'unused'
+               if (numPairs)
+               {
+                       b3OpenCLArray<b3BroadphasePair> gpuPairs(this->m_data->m_context, m_data->m_queue);
+                       gpuPairs.setFromOpenCLBuffer(pairs, numPairs);
+
+                       if (gClearPairsOnGpu)
+                       {
+                               //b3AlignedObjectArray<b3BroadphasePair> hostPairs;//just for debugging
+                               //gpuPairs.copyToHost(hostPairs);
+
+                               b3LauncherCL launcher(m_data->m_queue, m_data->m_clearOverlappingPairsKernel, "clearOverlappingPairsKernel");
+                               launcher.setBuffer(pairs);
+                               launcher.setConst(numPairs);
+                               launcher.launch1D(numPairs);
+
+                               //gpuPairs.copyToHost(hostPairs);
+                       }
+                       else
+                       {
+                               b3AlignedObjectArray<b3BroadphasePair> hostPairs;
+                               gpuPairs.copyToHost(hostPairs);
+
+                               for (int i = 0; i < hostPairs.size(); i++)
+                               {
+                                       hostPairs[i].z = 0xffffffff;
+                               }
+
+                               gpuPairs.copyFromHost(hostPairs);
+                       }
+               }
+
+               m_data->m_narrowphase->computeContacts(pairs, numPairs, aabbsWS, numBodies);
+               numContacts = m_data->m_narrowphase->getNumContactsGpu();
+
+               if (gUseDbvt)
+               {
+                       ///store the cached information (contact locations in the 'z' component)
+                       B3_PROFILE("m_overlappingPairsGPU->copyToHost");
+                       m_data->m_overlappingPairsGPU->copyToHost(m_data->m_broadphaseDbvt->getOverlappingPairCache()->getOverlappingPairArray());
+               }
+               if (gDumpContactStats && numContacts)
+               {
+                       m_data->m_narrowphase->getContactsGpu();
+
+                       printf("numContacts = %d\n", numContacts);
+
+                       int totalPoints = 0;
+                       const b3Contact4* contacts = m_data->m_narrowphase->getContactsCPU();
+
+                       for (int i = 0; i < numContacts; i++)
+                       {
+                               totalPoints += contacts->getNPoints();
+                       }
+                       printf("totalPoints=%d\n", totalPoints);
+               }
+       }
+
+       //convert contact points to contact constraints
+
+       //solve constraints
+
+       b3OpenCLArray<b3RigidBodyData> gpuBodies(m_data->m_context, m_data->m_queue, 0, true);
+       gpuBodies.setFromOpenCLBuffer(m_data->m_narrowphase->getBodiesGpu(), m_data->m_narrowphase->getNumRigidBodies());
+       b3OpenCLArray<b3InertiaData> gpuInertias(m_data->m_context, m_data->m_queue, 0, true);
+       gpuInertias.setFromOpenCLBuffer(m_data->m_narrowphase->getBodyInertiasGpu(), m_data->m_narrowphase->getNumRigidBodies());
+       b3OpenCLArray<b3Contact4> gpuContacts(m_data->m_context, m_data->m_queue, 0, true);
+       gpuContacts.setFromOpenCLBuffer(m_data->m_narrowphase->getContactsGpu(), m_data->m_narrowphase->getNumContactsGpu());
+
+       int numJoints = m_data->m_joints.size() ? m_data->m_joints.size() : m_data->m_cpuConstraints.size();
+       if (useBullet2CpuSolver && numJoints)
+       {
+               //      b3AlignedObjectArray<b3Contact4> hostContacts;
+               //gpuContacts.copyToHost(hostContacts);
+               {
+                       bool useGpu = m_data->m_joints.size() == 0;
+
+                       //                      b3Contact4* contacts = numContacts? &hostContacts[0]: 0;
+                       //m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,contacts,numJoints, joints);
+                       if (useGpu)
+                       {
+                               m_data->m_gpuSolver->solveJoints(m_data->m_narrowphase->getNumRigidBodies(), &gpuBodies, &gpuInertias, numJoints, m_data->m_gpuConstraints);
+                       }
+                       else
+                       {
+                               b3AlignedObjectArray<b3RigidBodyData> hostBodies;
+                               gpuBodies.copyToHost(hostBodies);
+                               b3AlignedObjectArray<b3InertiaData> hostInertias;
+                               gpuInertias.copyToHost(hostInertias);
+
+                               b3TypedConstraint** joints = numJoints ? &m_data->m_joints[0] : 0;
+                               m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumRigidBodies(), &hostBodies[0], &hostInertias[0], 0, 0, numJoints, joints);
+                               gpuBodies.copyFromHost(hostBodies);
+                       }
+               }
+       }
+
+       if (numContacts)
+       {
+#ifdef TEST_OTHER_GPU_SOLVER
+
+               if (gUseJacobi)
+               {
+                       bool useGpu = true;
+                       if (useGpu)
+                       {
+                               bool forceHost = false;
+                               if (forceHost)
+                               {
+                                       b3AlignedObjectArray<b3RigidBodyData> hostBodies;
+                                       b3AlignedObjectArray<b3InertiaData> hostInertias;
+                                       b3AlignedObjectArray<b3Contact4> hostContacts;
+
+                                       {
+                                               B3_PROFILE("copyToHost");
+                                               gpuBodies.copyToHost(hostBodies);
+                                               gpuInertias.copyToHost(hostInertias);
+                                               gpuContacts.copyToHost(hostContacts);
+                                       }
+
+                                       {
+                                               b3JacobiSolverInfo solverInfo;
+                                               m_data->m_solver3->solveGroupHost(&hostBodies[0], &hostInertias[0], hostBodies.size(), &hostContacts[0], hostContacts.size(), solverInfo);
+                                       }
+                                       {
+                                               B3_PROFILE("copyFromHost");
+                                               gpuBodies.copyFromHost(hostBodies);
+                                       }
+                               }
+                               else
+
+                               {
+                                       int static0Index = m_data->m_narrowphase->getStatic0Index();
+                                       b3JacobiSolverInfo solverInfo;
+                                       //m_data->m_solver3->solveContacts(    >solveGroup(&gpuBodies, &gpuInertias, &gpuContacts,solverInfo);
+                                       //m_data->m_solver3->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,&hostContacts[0]);
+                                       m_data->m_solver3->solveContacts(numBodies, gpuBodies.getBufferCL(), gpuInertias.getBufferCL(), numContacts, gpuContacts.getBufferCL(), m_data->m_config, static0Index);
+                               }
+                       }
+                       else
+                       {
+                               b3AlignedObjectArray<b3RigidBodyData> hostBodies;
+                               gpuBodies.copyToHost(hostBodies);
+                               b3AlignedObjectArray<b3InertiaData> hostInertias;
+                               gpuInertias.copyToHost(hostInertias);
+                               b3AlignedObjectArray<b3Contact4> hostContacts;
+                               gpuContacts.copyToHost(hostContacts);
+                               {
+                                       //m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,&hostContacts[0]);
+                               }
+                               gpuBodies.copyFromHost(hostBodies);
+                       }
+               }
+               else
+#endif  //TEST_OTHER_GPU_SOLVER
+               {
+                       int static0Index = m_data->m_narrowphase->getStatic0Index();
+                       m_data->m_solver2->solveContacts(numBodies, gpuBodies.getBufferCL(), gpuInertias.getBufferCL(), numContacts, gpuContacts.getBufferCL(), m_data->m_config, static0Index);
+
+                       //m_data->m_solver4->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(), gpuBodies.getBufferCL(), gpuInertias.getBufferCL(), numContacts, gpuContacts.getBufferCL());
+
+                       /*m_data->m_solver3->solveContactConstraintHost(
+                       (b3OpenCLArray<RigidBodyBase::Body>*)&gpuBodies,
+                       (b3OpenCLArray<RigidBodyBase::Inertia>*)&gpuInertias,
+                       (b3OpenCLArray<Constraint4>*) &gpuContacts,
+                       0,numContacts,256);
+                       */
+               }
+       }
+
+       integrate(deltaTime);
+}
+
+void b3GpuRigidBodyPipeline::integrate(float timeStep)
+{
+       //integrate
+       int numBodies = m_data->m_narrowphase->getNumRigidBodies();
+       float angularDamp = 0.99f;
+
+       if (gIntegrateOnCpu)
+       {
+               if (numBodies)
+               {
+                       b3GpuNarrowPhaseInternalData* npData = m_data->m_narrowphase->getInternalData();
+                       npData->m_bodyBufferGPU->copyToHost(*npData->m_bodyBufferCPU);
+
+                       b3RigidBodyData_t* bodies = &npData->m_bodyBufferCPU->at(0);
+
+                       for (int nodeID = 0; nodeID < numBodies; nodeID++)
+                       {
+                               integrateSingleTransform(bodies, nodeID, timeStep, angularDamp, m_data->m_gravity);
+                       }
+                       npData->m_bodyBufferGPU->copyFromHost(*npData->m_bodyBufferCPU);
+               }
+       }
+       else
+       {
+               b3LauncherCL launcher(m_data->m_queue, m_data->m_integrateTransformsKernel, "m_integrateTransformsKernel");
+               launcher.setBuffer(m_data->m_narrowphase->getBodiesGpu());
+
+               launcher.setConst(numBodies);
+               launcher.setConst(timeStep);
+               launcher.setConst(angularDamp);
+               launcher.setConst(m_data->m_gravity);
+               launcher.launch1D(numBodies);
+       }
+}
+
+void b3GpuRigidBodyPipeline::setupGpuAabbsFull()
+{
+       cl_int ciErrNum = 0;
+
+       int numBodies = m_data->m_narrowphase->getNumRigidBodies();
+       if (!numBodies)
+               return;
+
+       if (gCalcWorldSpaceAabbOnCpu)
+       {
+               if (numBodies)
+               {
+                       if (gUseDbvt)
+                       {
+                               m_data->m_allAabbsCPU.resize(numBodies);
+                               m_data->m_narrowphase->readbackAllBodiesToCpu();
+                               for (int i = 0; i < numBodies; i++)
+                               {
+                                       b3ComputeWorldAabb(i, m_data->m_narrowphase->getBodiesCpu(), m_data->m_narrowphase->getCollidablesCpu(), m_data->m_narrowphase->getLocalSpaceAabbsCpu(), &m_data->m_allAabbsCPU[0]);
+                               }
+                               m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
+                       }
+                       else
+                       {
+                               m_data->m_broadphaseSap->getAllAabbsCPU().resize(numBodies);
+                               m_data->m_narrowphase->readbackAllBodiesToCpu();
+                               for (int i = 0; i < numBodies; i++)
+                               {
+                                       b3ComputeWorldAabb(i, m_data->m_narrowphase->getBodiesCpu(), m_data->m_narrowphase->getCollidablesCpu(), m_data->m_narrowphase->getLocalSpaceAabbsCpu(), &m_data->m_broadphaseSap->getAllAabbsCPU()[0]);
+                               }
+                               m_data->m_broadphaseSap->getAllAabbsGPU().copyFromHost(m_data->m_broadphaseSap->getAllAabbsCPU());
+                               //m_data->m_broadphaseSap->writeAabbsToGpu();
+                       }
+               }
+       }
+       else
+       {
+               //__kernel void initializeGpuAabbsFull(  const int numNodes, __global Body* gBodies,__global Collidable* collidables, __global b3AABBCL* plocalShapeAABB, __global b3AABBCL* pAABB)
+               b3LauncherCL launcher(m_data->m_queue, m_data->m_updateAabbsKernel, "m_updateAabbsKernel");
+               launcher.setConst(numBodies);
+               cl_mem bodies = m_data->m_narrowphase->getBodiesGpu();
+               launcher.setBuffer(bodies);
+               cl_mem collidables = m_data->m_narrowphase->getCollidablesGpu();
+               launcher.setBuffer(collidables);
+               cl_mem localAabbs = m_data->m_narrowphase->getAabbLocalSpaceBufferGpu();
+               launcher.setBuffer(localAabbs);
+
+               cl_mem worldAabbs = 0;
+               if (gUseDbvt)
+               {
+                       worldAabbs = m_data->m_allAabbsGPU->getBufferCL();
+               }
+               else
+               {
+                       worldAabbs = m_data->m_broadphaseSap->getAabbBufferWS();
+               }
+               launcher.setBuffer(worldAabbs);
+               launcher.launch1D(numBodies);
+
+               oclCHECKERROR(ciErrNum, CL_SUCCESS);
+       }
+
+       /*
+       b3AlignedObjectArray<b3SapAabb> aabbs;
+       m_data->m_broadphaseSap->m_allAabbsGPU.copyToHost(aabbs);
+
+       printf("numAabbs = %d\n",  aabbs.size());
+
+       for (int i=0;i<aabbs.size();i++)
+       {
+               printf("aabb[%d].m_min=%f,%f,%f,%d\n",i,aabbs[i].m_minVec[0],aabbs[i].m_minVec[1],aabbs[i].m_minVec[2],aabbs[i].m_minIndices[3]);
+               printf("aabb[%d].m_max=%f,%f,%f,%d\n",i,aabbs[i].m_maxVec[0],aabbs[i].m_maxVec[1],aabbs[i].m_maxVec[2],aabbs[i].m_signedMaxIndices[3]);
+
+       };
+       */
+}
+
+cl_mem b3GpuRigidBodyPipeline::getBodyBuffer()
+{
+       return m_data->m_narrowphase->getBodiesGpu();
+}
+
+int b3GpuRigidBodyPipeline::getNumBodies() const
+{
+       return m_data->m_narrowphase->getNumRigidBodies();
+}
+
+void b3GpuRigidBodyPipeline::setGravity(const float* grav)
+{
+       m_data->m_gravity.setValue(grav[0], grav[1], grav[2]);
+}
+
+void b3GpuRigidBodyPipeline::copyConstraintsToHost()
+{
+       m_data->m_gpuConstraints->copyToHost(m_data->m_cpuConstraints);
+}
+
+void b3GpuRigidBodyPipeline::writeAllInstancesToGpu()
+{
+       m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
+       m_data->m_gpuConstraints->copyFromHost(m_data->m_cpuConstraints);
+}
+
+int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userIndex, bool writeInstanceToGpu)
+{
+       b3Vector3 aabbMin = b3MakeVector3(0, 0, 0), aabbMax = b3MakeVector3(0, 0, 0);
+
+       if (collidableIndex >= 0)
+       {
+               b3SapAabb localAabb = m_data->m_narrowphase->getLocalSpaceAabb(collidableIndex);
+               b3Vector3 localAabbMin = b3MakeVector3(localAabb.m_min[0], localAabb.m_min[1], localAabb.m_min[2]);
+               b3Vector3 localAabbMax = b3MakeVector3(localAabb.m_max[0], localAabb.m_max[1], localAabb.m_max[2]);
+
+               b3Scalar margin = 0.01f;
+               b3Transform t;
+               t.setIdentity();
+               t.setOrigin(b3MakeVector3(position[0], position[1], position[2]));
+               t.setRotation(b3Quaternion(orientation[0], orientation[1], orientation[2], orientation[3]));
+               b3TransformAabb(localAabbMin, localAabbMax, margin, t, aabbMin, aabbMax);
+       }
+       else
+       {
+               b3Error("registerPhysicsInstance using invalid collidableIndex\n");
+               return -1;
+       }
+
+       bool writeToGpu = false;
+       int bodyIndex = m_data->m_narrowphase->getNumRigidBodies();
+       bodyIndex = m_data->m_narrowphase->registerRigidBody(collidableIndex, mass, position, orientation, &aabbMin.getX(), &aabbMax.getX(), writeToGpu);
+
+       if (bodyIndex >= 0)
+       {
+               if (gUseDbvt)
+               {
+                       m_data->m_broadphaseDbvt->createProxy(aabbMin, aabbMax, bodyIndex, 0, 1, 1);
+                       b3SapAabb aabb;
+                       for (int i = 0; i < 3; i++)
+                       {
+                               aabb.m_min[i] = aabbMin[i];
+                               aabb.m_max[i] = aabbMax[i];
+                               aabb.m_minIndices[3] = bodyIndex;
+                       }
+                       m_data->m_allAabbsCPU.push_back(aabb);
+                       if (writeInstanceToGpu)
+                       {
+                               m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
+                       }
+               }
+               else
+               {
+                       if (mass)
+                       {
+                               m_data->m_broadphaseSap->createProxy(aabbMin, aabbMax, bodyIndex, 1, 1);  //m_dispatcher);
+                       }
+                       else
+                       {
+                               m_data->m_broadphaseSap->createLargeProxy(aabbMin, aabbMax, bodyIndex, 1, 1);  //m_dispatcher);
+                       }
+               }
+       }
+
+       /*
+       if (mass>0.f)
+               m_numDynamicPhysicsInstances++;
+
+       m_numPhysicsInstances++;
+       */
+
+       return bodyIndex;
+}
+
+void b3GpuRigidBodyPipeline::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults)
+{
+       this->m_data->m_raycaster->castRays(rays, hitResults,
+                                                                               getNumBodies(), this->m_data->m_narrowphase->getBodiesCpu(),
+                                                                               m_data->m_narrowphase->getNumCollidablesGpu(), m_data->m_narrowphase->getCollidablesCpu(),
+                                                                               m_data->m_narrowphase->getInternalData(), m_data->m_broadphaseSap);
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h
new file mode 100644 (file)
index 0000000..0e5c6fe
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_GPU_RIGIDBODY_PIPELINE_H
+#define B3_GPU_RIGIDBODY_PIPELINE_H
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
+
+class b3GpuRigidBodyPipeline
+{
+protected:
+       struct b3GpuRigidBodyPipelineInternalData* m_data;
+
+       int allocateCollidable();
+
+public:
+       b3GpuRigidBodyPipeline(cl_context ctx, cl_device_id device, cl_command_queue q, class b3GpuNarrowPhase* narrowphase, class b3GpuBroadphaseInterface* broadphaseSap, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config);
+       virtual ~b3GpuRigidBodyPipeline();
+
+       void stepSimulation(float deltaTime);
+       void integrate(float timeStep);
+       void setupGpuAabbsFull();
+
+       int registerConvexPolyhedron(class b3ConvexUtility* convex);
+
+       //int           registerConvexPolyhedron(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
+       //int           registerSphereShape(float radius);
+       //int           registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
+
+       //int           registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
+       //int           registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
+
+       int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData, bool writeInstanceToGpu);
+       //if you passed "writeInstanceToGpu" false in the registerPhysicsInstance method (for performance) you need to call writeAllInstancesToGpu after all instances are registered
+       void writeAllInstancesToGpu();
+       void copyConstraintsToHost();
+       void setGravity(const float* grav);
+       void reset();
+
+       int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, float breakingThreshold);
+       int createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold);
+       void removeConstraintByUid(int uid);
+
+       void addConstraint(class b3TypedConstraint* constraint);
+       void removeConstraint(b3TypedConstraint* constraint);
+
+       void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults);
+
+       cl_mem getBodyBuffer();
+
+       int getNumBodies() const;
+};
+
+#endif  //B3_GPU_RIGIDBODY_PIPELINE_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h
new file mode 100644 (file)
index 0000000..e0a26fd
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
+#define B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
+
+#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
+#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
+
+#include "Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h"
+#include "Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h"
+
+struct b3GpuRigidBodyPipelineInternalData
+{
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_queue;
+
+       cl_kernel m_integrateTransformsKernel;
+       cl_kernel m_updateAabbsKernel;
+       cl_kernel m_clearOverlappingPairsKernel;
+
+       class b3PgsJacobiSolver* m_solver;
+
+       class b3GpuPgsConstraintSolver* m_gpuSolver;
+
+       class b3GpuPgsContactSolver* m_solver2;
+       class b3GpuJacobiContactSolver* m_solver3;
+       class b3GpuRaycast* m_raycaster;
+
+       class b3GpuBroadphaseInterface* m_broadphaseSap;
+
+       struct b3DynamicBvhBroadphase* m_broadphaseDbvt;
+       b3OpenCLArray<b3SapAabb>* m_allAabbsGPU;
+       b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
+       b3OpenCLArray<b3BroadphasePair>* m_overlappingPairsGPU;
+
+       b3OpenCLArray<b3GpuGenericConstraint>* m_gpuConstraints;
+       b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
+
+       b3AlignedObjectArray<b3TypedConstraint*> m_joints;
+       int m_constraintUid;
+       class b3GpuNarrowPhase* m_narrowphase;
+       b3Vector3 m_gravity;
+
+       b3Config m_config;
+};
+
+#endif  //B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h
new file mode 100644 (file)
index 0000000..db815d9
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#ifndef B3_GPU_SOLVER_BODY_H
+#define B3_GPU_SOLVER_BODY_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Matrix3x3.h"
+
+#include "Bullet3Common/b3AlignedAllocator.h"
+#include "Bullet3Common/b3TransformUtil.h"
+
+///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
+#ifdef B3_USE_SSE
+#define USE_SIMD 1
+#endif  //
+
+///The b3SolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3GpuSolverBody
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+       //      b3Transform             m_worldTransformUnused;
+       b3Vector3 m_deltaLinearVelocity;
+       b3Vector3 m_deltaAngularVelocity;
+       b3Vector3 m_angularFactor;
+       b3Vector3 m_linearFactor;
+       b3Vector3 m_invMass;
+       b3Vector3 m_pushVelocity;
+       b3Vector3 m_turnVelocity;
+       b3Vector3 m_linearVelocity;
+       b3Vector3 m_angularVelocity;
+
+       union {
+               void* m_originalBody;
+               int m_originalBodyIndex;
+       };
+
+       int padding[3];
+
+       /*
+       void    setWorldTransform(const b3Transform& worldTransform)
+       {
+               m_worldTransform = worldTransform;
+       }
+
+       const b3Transform& getWorldTransform() const
+       {
+               return m_worldTransform;
+       }
+       */
+       B3_FORCE_INLINE void getVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
+       {
+               if (m_originalBody)
+                       velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
+               else
+                       velocity.setValue(0, 0, 0);
+       }
+
+       B3_FORCE_INLINE void getAngularVelocity(b3Vector3 & angVel) const
+       {
+               if (m_originalBody)
+                       angVel = m_angularVelocity + m_deltaAngularVelocity;
+               else
+                       angVel.setValue(0, 0, 0);
+       }
+
+       //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+       B3_FORCE_INLINE void applyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
+       {
+               if (m_originalBody)
+               {
+                       m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+                       m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
+               }
+       }
+
+       B3_FORCE_INLINE void internalApplyPushImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, b3Scalar impulseMagnitude)
+       {
+               if (m_originalBody)
+               {
+                       m_pushVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+                       m_turnVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
+               }
+       }
+
+       const b3Vector3& getDeltaLinearVelocity() const
+       {
+               return m_deltaLinearVelocity;
+       }
+
+       const b3Vector3& getDeltaAngularVelocity() const
+       {
+               return m_deltaAngularVelocity;
+       }
+
+       const b3Vector3& getPushVelocity() const
+       {
+               return m_pushVelocity;
+       }
+
+       const b3Vector3& getTurnVelocity() const
+       {
+               return m_turnVelocity;
+       }
+
+       ////////////////////////////////////////////////
+       ///some internal methods, don't use them
+
+       b3Vector3& internalGetDeltaLinearVelocity()
+       {
+               return m_deltaLinearVelocity;
+       }
+
+       b3Vector3& internalGetDeltaAngularVelocity()
+       {
+               return m_deltaAngularVelocity;
+       }
+
+       const b3Vector3& internalGetAngularFactor() const
+       {
+               return m_angularFactor;
+       }
+
+       const b3Vector3& internalGetInvMass() const
+       {
+               return m_invMass;
+       }
+
+       void internalSetInvMass(const b3Vector3& invMass)
+       {
+               m_invMass = invMass;
+       }
+
+       b3Vector3& internalGetPushVelocity()
+       {
+               return m_pushVelocity;
+       }
+
+       b3Vector3& internalGetTurnVelocity()
+       {
+               return m_turnVelocity;
+       }
+
+       B3_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
+       {
+               velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
+       }
+
+       B3_FORCE_INLINE void internalGetAngularVelocity(b3Vector3 & angVel) const
+       {
+               angVel = m_angularVelocity + m_deltaAngularVelocity;
+       }
+
+       //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+       B3_FORCE_INLINE void internalApplyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
+       {
+               //if (m_originalBody)
+               {
+                       m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+                       m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
+               }
+       }
+
+       void writebackVelocity()
+       {
+               //if (m_originalBody>=0)
+               {
+                       m_linearVelocity += m_deltaLinearVelocity;
+                       m_angularVelocity += m_deltaAngularVelocity;
+
+                       //m_originalBody->setCompanionId(-1);
+               }
+       }
+
+       void writebackVelocityAndTransform(b3Scalar timeStep, b3Scalar splitImpulseTurnErp)
+       {
+               (void)timeStep;
+               if (m_originalBody)
+               {
+                       m_linearVelocity += m_deltaLinearVelocity;
+                       m_angularVelocity += m_deltaAngularVelocity;
+
+                       //correct the position/orientation based on push/turn recovery
+                       b3Transform newTransform;
+                       if (m_pushVelocity[0] != 0.f || m_pushVelocity[1] != 0 || m_pushVelocity[2] != 0 || m_turnVelocity[0] != 0.f || m_turnVelocity[1] != 0 || m_turnVelocity[2] != 0)
+                       {
+                               //      b3Quaternion orn = m_worldTransform.getRotation();
+                               //                              b3TransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform);
+                               //                              m_worldTransform = newTransform;
+                       }
+                       //m_worldTransform.setRotation(orn);
+                       //m_originalBody->setCompanionId(-1);
+               }
+       }
+};
+
+#endif  //B3_SOLVER_BODY_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h
new file mode 100644 (file)
index 0000000..7d9eea2
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans http://github.com/erwincoumans/bullet3
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_GPU_SOLVER_CONSTRAINT_H
+#define B3_GPU_SOLVER_CONSTRAINT_H
+
+#include "Bullet3Common/b3Vector3.h"
+#include "Bullet3Common/b3Matrix3x3.h"
+//#include "b3JacobianEntry.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+
+//#define NO_FRICTION_TANGENTIALS 1
+
+///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
+B3_ATTRIBUTE_ALIGNED16(struct)
+b3GpuSolverConstraint
+{
+       B3_DECLARE_ALIGNED_ALLOCATOR();
+
+       b3Vector3 m_relpos1CrossNormal;
+       b3Vector3 m_contactNormal;
+
+       b3Vector3 m_relpos2CrossNormal;
+       //b3Vector3             m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
+
+       b3Vector3 m_angularComponentA;
+       b3Vector3 m_angularComponentB;
+
+       mutable b3Scalar m_appliedPushImpulse;
+       mutable b3Scalar m_appliedImpulse;
+       int m_padding1;
+       int m_padding2;
+       b3Scalar m_friction;
+       b3Scalar m_jacDiagABInv;
+       b3Scalar m_rhs;
+       b3Scalar m_cfm;
+
+       b3Scalar m_lowerLimit;
+       b3Scalar m_upperLimit;
+       b3Scalar m_rhsPenetration;
+       union {
+               void* m_originalContactPoint;
+               int m_originalConstraintIndex;
+               b3Scalar m_unusedPadding4;
+       };
+
+       int m_overrideNumSolverIterations;
+       int m_frictionIndex;
+       int m_solverBodyIdA;
+       int m_solverBodyIdB;
+
+       enum b3SolverConstraintType
+       {
+               B3_SOLVER_CONTACT_1D = 0,
+               B3_SOLVER_FRICTION_1D
+       };
+};
+
+typedef b3AlignedObjectArray<b3GpuSolverConstraint> b3GpuConstraintArray;
+
+#endif  //B3_GPU_SOLVER_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3Solver.cpp b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3Solver.cpp
new file mode 100644 (file)
index 0000000..ccf67da
--- /dev/null
@@ -0,0 +1,1128 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+#include "b3Solver.h"
+
+///useNewBatchingKernel  is a rewritten kernel using just a single thread of the warp, for experiments
+bool useNewBatchingKernel = true;
+bool gConvertConstraintOnCpu = false;
+
+#define B3_SOLVER_SETUP_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl"
+#define B3_SOLVER_SETUP2_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl"
+#define B3_SOLVER_CONTACT_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl"
+#define B3_SOLVER_FRICTION_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl"
+#define B3_BATCHING_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl"
+#define B3_BATCHING_NEW_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl"
+
+#include "Bullet3Dynamics/shared/b3ConvertConstraint4.h"
+
+#include "kernels/solverSetup.h"
+#include "kernels/solverSetup2.h"
+
+#include "kernels/solveContact.h"
+#include "kernels/solveFriction.h"
+
+#include "kernels/batchingKernels.h"
+#include "kernels/batchingKernelsNew.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
+#include "Bullet3Common/b3Vector3.h"
+
+struct SolverDebugInfo
+{
+       int m_valInt0;
+       int m_valInt1;
+       int m_valInt2;
+       int m_valInt3;
+
+       int m_valInt4;
+       int m_valInt5;
+       int m_valInt6;
+       int m_valInt7;
+
+       int m_valInt8;
+       int m_valInt9;
+       int m_valInt10;
+       int m_valInt11;
+
+       int m_valInt12;
+       int m_valInt13;
+       int m_valInt14;
+       int m_valInt15;
+
+       float m_val0;
+       float m_val1;
+       float m_val2;
+       float m_val3;
+};
+
+class SolverDeviceInl
+{
+public:
+       struct ParallelSolveData
+       {
+               b3OpenCLArray<unsigned int>* m_numConstraints;
+               b3OpenCLArray<unsigned int>* m_offsets;
+       };
+};
+
+b3Solver::b3Solver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity)
+       : m_context(ctx),
+         m_device(device),
+         m_queue(queue),
+         m_batchSizes(ctx, queue),
+         m_nIterations(4)
+{
+       m_sort32 = new b3RadixSort32CL(ctx, device, queue);
+       m_scan = new b3PrefixScanCL(ctx, device, queue, B3_SOLVER_N_CELLS);
+       m_search = new b3BoundSearchCL(ctx, device, queue, B3_SOLVER_N_CELLS);
+
+       const int sortSize = B3NEXTMULTIPLEOF(pairCapacity, 512);
+
+       m_sortDataBuffer = new b3OpenCLArray<b3SortData>(ctx, queue, sortSize);
+       m_contactBuffer2 = new b3OpenCLArray<b3Contact4>(ctx, queue);
+
+       m_numConstraints = new b3OpenCLArray<unsigned int>(ctx, queue, B3_SOLVER_N_CELLS);
+       m_numConstraints->resize(B3_SOLVER_N_CELLS);
+
+       m_offsets = new b3OpenCLArray<unsigned int>(ctx, queue, B3_SOLVER_N_CELLS);
+       m_offsets->resize(B3_SOLVER_N_CELLS);
+       const char* additionalMacros = "";
+       //      const char* srcFileNameForCaching="";
+
+       cl_int pErrNum;
+       const char* batchKernelSource = batchingKernelsCL;
+       const char* batchKernelNewSource = batchingKernelsNewCL;
+
+       const char* solverSetupSource = solverSetupCL;
+       const char* solverSetup2Source = solverSetup2CL;
+       const char* solveContactSource = solveContactCL;
+       const char* solveFrictionSource = solveFrictionCL;
+
+       {
+               cl_program solveContactProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveContactSource, &pErrNum, additionalMacros, B3_SOLVER_CONTACT_KERNEL_PATH);
+               b3Assert(solveContactProg);
+
+               cl_program solveFrictionProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveFrictionSource, &pErrNum, additionalMacros, B3_SOLVER_FRICTION_KERNEL_PATH);
+               b3Assert(solveFrictionProg);
+
+               cl_program solverSetup2Prog = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetup2Source, &pErrNum, additionalMacros, B3_SOLVER_SETUP2_KERNEL_PATH);
+               b3Assert(solverSetup2Prog);
+
+               cl_program solverSetupProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetupSource, &pErrNum, additionalMacros, B3_SOLVER_SETUP_KERNEL_PATH);
+               b3Assert(solverSetupProg);
+
+               m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg, additionalMacros);
+               b3Assert(m_solveFrictionKernel);
+
+               m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg, additionalMacros);
+               b3Assert(m_solveContactKernel);
+
+               m_contactToConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg, additionalMacros);
+               b3Assert(m_contactToConstraintKernel);
+
+               m_setSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog, additionalMacros);
+               b3Assert(m_setSortDataKernel);
+
+               m_reorderContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog, additionalMacros);
+               b3Assert(m_reorderContactKernel);
+
+               m_copyConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog, additionalMacros);
+               b3Assert(m_copyConstraintKernel);
+       }
+
+       {
+               cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelSource, &pErrNum, additionalMacros, B3_BATCHING_PATH);
+               //cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, 0, &pErrNum,additionalMacros, B3_BATCHING_PATH,true);
+               b3Assert(batchingProg);
+
+               m_batchingKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg, additionalMacros);
+               b3Assert(m_batchingKernel);
+       }
+       {
+               cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelNewSource, &pErrNum, additionalMacros, B3_BATCHING_NEW_PATH);
+               b3Assert(batchingNewProg);
+
+               m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg, additionalMacros);
+               //m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelNewSource, "CreateBatchesBruteForce", &pErrNum, batchingNewProg,additionalMacros );
+               b3Assert(m_batchingKernelNew);
+       }
+}
+
+b3Solver::~b3Solver()
+{
+       delete m_offsets;
+       delete m_numConstraints;
+       delete m_sortDataBuffer;
+       delete m_contactBuffer2;
+
+       delete m_sort32;
+       delete m_scan;
+       delete m_search;
+
+       clReleaseKernel(m_batchingKernel);
+       clReleaseKernel(m_batchingKernelNew);
+
+       clReleaseKernel(m_solveContactKernel);
+       clReleaseKernel(m_solveFrictionKernel);
+
+       clReleaseKernel(m_contactToConstraintKernel);
+       clReleaseKernel(m_setSortDataKernel);
+       clReleaseKernel(m_reorderContactKernel);
+       clReleaseKernel(m_copyConstraintKernel);
+}
+
+template <bool JACOBI>
+static __inline void solveContact(b3GpuConstraint4& cs,
+                                                                 const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+                                                                 const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+                                                                 float maxRambdaDt[4], float minRambdaDt[4])
+{
+       b3Vector3 dLinVelA;
+       dLinVelA.setZero();
+       b3Vector3 dAngVelA;
+       dAngVelA.setZero();
+       b3Vector3 dLinVelB;
+       dLinVelB.setZero();
+       b3Vector3 dAngVelB;
+       dAngVelB.setZero();
+
+       for (int ic = 0; ic < 4; ic++)
+       {
+               //      dont necessary because this makes change to 0
+               if (cs.m_jacCoeffInv[ic] == 0.f) continue;
+
+               {
+                       b3Vector3 angular0, angular1, linear;
+                       b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
+                       b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
+                       setLinearAndAngular((const b3Vector3&)cs.m_linear, (const b3Vector3&)r0, (const b3Vector3&)r1, &linear, &angular0, &angular1);
+
+                       float rambdaDt = calcRelVel((const b3Vector3&)cs.m_linear, (const b3Vector3&)-cs.m_linear, angular0, angular1,
+                                                                               linVelA, angVelA, linVelB, angVelB) +
+                                                        cs.m_b[ic];
+                       rambdaDt *= cs.m_jacCoeffInv[ic];
+
+                       {
+                               float prevSum = cs.m_appliedRambdaDt[ic];
+                               float updated = prevSum;
+                               updated += rambdaDt;
+                               updated = b3Max(updated, minRambdaDt[ic]);
+                               updated = b3Min(updated, maxRambdaDt[ic]);
+                               rambdaDt = updated - prevSum;
+                               cs.m_appliedRambdaDt[ic] = updated;
+                       }
+
+                       b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+                       b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+                       b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+                       b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
+#ifdef _WIN32
+                       b3Assert(_finite(linImp0.getX()));
+                       b3Assert(_finite(linImp1.getX()));
+#endif
+                       if (JACOBI)
+                       {
+                               dLinVelA += linImp0;
+                               dAngVelA += angImp0;
+                               dLinVelB += linImp1;
+                               dAngVelB += angImp1;
+                       }
+                       else
+                       {
+                               linVelA += linImp0;
+                               angVelA += angImp0;
+                               linVelB += linImp1;
+                               angVelB += angImp1;
+                       }
+               }
+       }
+
+       if (JACOBI)
+       {
+               linVelA += dLinVelA;
+               angVelA += dAngVelA;
+               linVelB += dLinVelB;
+               angVelB += dAngVelB;
+       }
+}
+
+static __inline void solveFriction(b3GpuConstraint4& cs,
+                                                                  const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
+                                                                  const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
+                                                                  float maxRambdaDt[4], float minRambdaDt[4])
+{
+       if (cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0) return;
+       const b3Vector3& center = (const b3Vector3&)cs.m_center;
+
+       b3Vector3 n = -(const b3Vector3&)cs.m_linear;
+
+       b3Vector3 tangent[2];
+#if 1
+       b3PlaneSpace1(n, tangent[0], tangent[1]);
+#else
+       b3Vector3 r = cs.m_worldPos[0] - center;
+       tangent[0] = cross3(n, r);
+       tangent[1] = cross3(tangent[0], n);
+       tangent[0] = normalize3(tangent[0]);
+       tangent[1] = normalize3(tangent[1]);
+#endif
+
+       b3Vector3 angular0, angular1, linear;
+       b3Vector3 r0 = center - posA;
+       b3Vector3 r1 = center - posB;
+       for (int i = 0; i < 2; i++)
+       {
+               setLinearAndAngular(tangent[i], r0, r1, &linear, &angular0, &angular1);
+               float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
+                                                                       linVelA, angVelA, linVelB, angVelB);
+               rambdaDt *= cs.m_fJacCoeffInv[i];
+
+               {
+                       float prevSum = cs.m_fAppliedRambdaDt[i];
+                       float updated = prevSum;
+                       updated += rambdaDt;
+                       updated = b3Max(updated, minRambdaDt[i]);
+                       updated = b3Min(updated, maxRambdaDt[i]);
+                       rambdaDt = updated - prevSum;
+                       cs.m_fAppliedRambdaDt[i] = updated;
+               }
+
+               b3Vector3 linImp0 = invMassA * linear * rambdaDt;
+               b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
+               b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
+               b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
+#ifdef _WIN32
+               b3Assert(_finite(linImp0.getX()));
+               b3Assert(_finite(linImp1.getX()));
+#endif
+               linVelA += linImp0;
+               angVelA += angImp0;
+               linVelB += linImp1;
+               angVelB += angImp1;
+       }
+
+       {  //   angular damping for point constraint
+               b3Vector3 ab = (posB - posA).normalized();
+               b3Vector3 ac = (center - posA).normalized();
+               if (b3Dot(ab, ac) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
+               {
+                       float angNA = b3Dot(n, angVelA);
+                       float angNB = b3Dot(n, angVelB);
+
+                       angVelA -= (angNA * 0.1f) * n;
+                       angVelB -= (angNB * 0.1f) * n;
+               }
+       }
+}
+/*
+ b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
+       b3AlignedObjectArray<b3InertiaData>& m_shapes;
+       b3AlignedObjectArray<b3GpuConstraint4>& m_constraints;
+       b3AlignedObjectArray<int>* m_batchSizes;
+       int m_cellIndex;
+       int m_curWgidx;
+       int m_start;
+       int m_nConstraints;
+       bool m_solveFriction;
+       int m_maxNumBatches;
+ */
+
+struct SolveTask  // : public ThreadPool::Task
+{
+       SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies, b3AlignedObjectArray<b3InertiaData>& shapes, b3AlignedObjectArray<b3GpuConstraint4>& constraints,
+                         int start, int nConstraints, int maxNumBatches, b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx, b3AlignedObjectArray<int>* batchSizes, int cellIndex)
+               : m_bodies(bodies), m_shapes(shapes), m_constraints(constraints), m_batchSizes(batchSizes), m_cellIndex(cellIndex), m_curWgidx(curWgidx), m_start(start), m_nConstraints(nConstraints), m_solveFriction(true), m_maxNumBatches(maxNumBatches)
+       {
+       }
+
+       unsigned short int getType() { return 0; }
+
+       void run(int tIdx)
+       {
+               int offset = 0;
+               for (int ii = 0; ii < B3_MAX_NUM_BATCHES; ii++)
+               {
+                       int numInBatch = m_batchSizes->at(m_cellIndex * B3_MAX_NUM_BATCHES + ii);
+                       if (!numInBatch)
+                               break;
+
+                       for (int jj = 0; jj < numInBatch; jj++)
+                       {
+                               int i = m_start + offset + jj;
+                               int batchId = m_constraints[i].m_batchIdx;
+                               b3Assert(batchId == ii);
+                               float frictionCoeff = m_constraints[i].getFrictionCoeff();
+                               int aIdx = (int)m_constraints[i].m_bodyA;
+                               int bIdx = (int)m_constraints[i].m_bodyB;
+                               //                              int localBatch = m_constraints[i].m_batchIdx;
+                               b3RigidBodyData& bodyA = m_bodies[aIdx];
+                               b3RigidBodyData& bodyB = m_bodies[bIdx];
+
+                               if (!m_solveFriction)
+                               {
+                                       float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+                                       float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
+
+                                       solveContact<false>(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
+                                                                               (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
+                                                                               maxRambdaDt, minRambdaDt);
+                               }
+                               else
+                               {
+                                       float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
+                                       float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
+                                       float sum = 0;
+                                       for (int j = 0; j < 4; j++)
+                                       {
+                                               sum += m_constraints[i].m_appliedRambdaDt[j];
+                                       }
+                                       frictionCoeff = 0.7f;
+                                       for (int j = 0; j < 4; j++)
+                                       {
+                                               maxRambdaDt[j] = frictionCoeff * sum;
+                                               minRambdaDt[j] = -maxRambdaDt[j];
+                                       }
+                                       solveFriction(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
+                                                                 (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
+                                                                 maxRambdaDt, minRambdaDt);
+                               }
+                       }
+                       offset += numInBatch;
+               }
+               /*              for (int bb=0;bb<m_maxNumBatches;bb++)
+               {
+                       //for(int ic=m_nConstraints-1; ic>=0; ic--)
+                       for(int ic=0; ic<m_nConstraints; ic++)
+                       {
+                               
+                               int i = m_start + ic;
+                               if (m_constraints[i].m_batchIdx != bb)
+                                       continue;
+
+                               float frictionCoeff = m_constraints[i].getFrictionCoeff();
+                               int aIdx = (int)m_constraints[i].m_bodyA;
+                               int bIdx = (int)m_constraints[i].m_bodyB;
+                               int localBatch = m_constraints[i].m_batchIdx;
+                               b3RigidBodyData& bodyA = m_bodies[aIdx];
+                               b3RigidBodyData& bodyB = m_bodies[bIdx];
+
+                               if( !m_solveFriction )
+                               {
+                                       float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+                                       float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+                                       solveContact<false>( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3 &)m_shapes[aIdx].m_invInertiaWorld, 
+                                                       (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3 &)m_shapes[bIdx].m_invInertiaWorld,
+                                               maxRambdaDt, minRambdaDt );
+                               }
+                               else
+                               {
+                                       float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+                                       float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+                                       float sum = 0;
+                                       for(int j=0; j<4; j++)
+                                       {
+                                               sum +=m_constraints[i].m_appliedRambdaDt[j];
+                                       }
+                                       frictionCoeff = 0.7f;
+                                       for(int j=0; j<4; j++)
+                                       {
+                                               maxRambdaDt[j] = frictionCoeff*sum;
+                                               minRambdaDt[j] = -maxRambdaDt[j];
+                                       }
+                                       solveFriction( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,(const b3Matrix3x3 &) m_shapes[aIdx].m_invInertiaWorld, 
+                                               (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass,(const b3Matrix3x3 &) m_shapes[bIdx].m_invInertiaWorld,
+                                               maxRambdaDt, minRambdaDt );
+                       
+                               }
+                       }
+               }
+               */
+       }
+
+       b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
+       b3AlignedObjectArray<b3InertiaData>& m_shapes;
+       b3AlignedObjectArray<b3GpuConstraint4>& m_constraints;
+       b3AlignedObjectArray<int>* m_batchSizes;
+       int m_cellIndex;
+       int m_curWgidx;
+       int m_start;
+       int m_nConstraints;
+       bool m_solveFriction;
+       int m_maxNumBatches;
+};
+
+void b3Solver::solveContactConstraintHost(b3OpenCLArray<b3RigidBodyData>* bodyBuf, b3OpenCLArray<b3InertiaData>* shapeBuf,
+                                                                                 b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, b3AlignedObjectArray<int>* batchSizes)
+{
+#if 0
+       {       
+               int nSplitX = B3_SOLVER_N_SPLIT_X;
+               int nSplitY = B3_SOLVER_N_SPLIT_Y;
+               int numWorkgroups = B3_SOLVER_N_CELLS/B3_SOLVER_N_BATCHES;
+               for (int z=0;z<4;z++)
+               {
+                       for (int y=0;y<4;y++)
+                       {
+                               for (int x=0;x<4;x++)
+                               {
+                                       int newIndex = (x+y*nSplitX+z*nSplitX*nSplitY);
+                               //      printf("newIndex=%d\n",newIndex);
+
+                                       int zIdx = newIndex/(nSplitX*nSplitY);
+                                       int remain = newIndex%(nSplitX*nSplitY);
+                                       int yIdx = remain/nSplitX;
+                                       int xIdx = remain%nSplitX;
+                               //      printf("newIndex=%d\n",newIndex);
+                               }
+                       }
+               }
+
+               //for (int wgIdx=numWorkgroups-1;wgIdx>=0;wgIdx--)
+               for (int cellBatch=0;cellBatch<B3_SOLVER_N_BATCHES;cellBatch++)
+               {
+                       for (int wgIdx=0;wgIdx<numWorkgroups;wgIdx++)
+                       {
+                               int zIdx = (wgIdx/((nSplitX*nSplitY)/4))*2+((cellBatch&4)>>2);
+                               int remain= (wgIdx%((nSplitX*nSplitY)/4));
+                               int yIdx = (remain/(nSplitX/2))*2 + ((cellBatch&2)>>1);
+                               int xIdx = (remain%(nSplitX/2))*2 + (cellBatch&1);
+                               
+                               /*int zIdx = newIndex/(nSplitX*nSplitY);
+                               int remain = newIndex%(nSplitX*nSplitY);
+                               int yIdx = remain/nSplitX;
+                               int xIdx = remain%nSplitX;
+                               */
+                               int cellIdx = xIdx+yIdx*nSplitX+zIdx*(nSplitX*nSplitY);
+                       //      printf("wgIdx %d: xIdx=%d, yIdx=%d, zIdx=%d, cellIdx=%d, cell Batch %d\n",wgIdx,xIdx,yIdx,zIdx,cellIdx,cellBatch);
+                       }
+               }
+       }
+#endif
+
+       b3AlignedObjectArray<b3RigidBodyData> bodyNative;
+       bodyBuf->copyToHost(bodyNative);
+       b3AlignedObjectArray<b3InertiaData> shapeNative;
+       shapeBuf->copyToHost(shapeNative);
+       b3AlignedObjectArray<b3GpuConstraint4> constraintNative;
+       constraint->copyToHost(constraintNative);
+
+       b3AlignedObjectArray<unsigned int> numConstraintsHost;
+       m_numConstraints->copyToHost(numConstraintsHost);
+
+       //printf("------------------------\n");
+       b3AlignedObjectArray<unsigned int> offsetsHost;
+       m_offsets->copyToHost(offsetsHost);
+       static int frame = 0;
+       bool useBatches = true;
+       if (useBatches)
+       {
+               for (int iter = 0; iter < m_nIterations; iter++)
+               {
+                       for (int cellBatch = 0; cellBatch < B3_SOLVER_N_BATCHES; cellBatch++)
+                       {
+                               int nSplitX = B3_SOLVER_N_SPLIT_X;
+                               int nSplitY = B3_SOLVER_N_SPLIT_Y;
+                               int numWorkgroups = B3_SOLVER_N_CELLS / B3_SOLVER_N_BATCHES;
+                               //printf("cell Batch %d\n",cellBatch);
+                               b3AlignedObjectArray<int> usedBodies[B3_SOLVER_N_CELLS];
+                               for (int i = 0; i < B3_SOLVER_N_CELLS; i++)
+                               {
+                                       usedBodies[i].resize(0);
+                               }
+
+                               //for (int wgIdx=numWorkgroups-1;wgIdx>=0;wgIdx--)
+                               for (int wgIdx = 0; wgIdx < numWorkgroups; wgIdx++)
+                               {
+                                       int zIdx = (wgIdx / ((nSplitX * nSplitY) / 4)) * 2 + ((cellBatch & 4) >> 2);
+                                       int remain = (wgIdx % ((nSplitX * nSplitY) / 4));
+                                       int yIdx = (remain / (nSplitX / 2)) * 2 + ((cellBatch & 2) >> 1);
+                                       int xIdx = (remain % (nSplitX / 2)) * 2 + (cellBatch & 1);
+                                       int cellIdx = xIdx + yIdx * nSplitX + zIdx * (nSplitX * nSplitY);
+
+                                       if (numConstraintsHost[cellIdx] == 0)
+                                               continue;
+
+                                       //printf("wgIdx %d: xIdx=%d, yIdx=%d, zIdx=%d, cellIdx=%d, cell Batch %d\n",wgIdx,xIdx,yIdx,zIdx,cellIdx,cellBatch);
+                                       //printf("cell %d has %d constraints\n", cellIdx,numConstraintsHost[cellIdx]);
+                                       if (zIdx)
+                                       {
+                                               //printf("?\n");
+                                       }
+
+                                       if (iter == 0)
+                                       {
+                                               //printf("frame=%d, Cell xIdx=%x, yIdx=%d ",frame, xIdx,yIdx);
+                                               //printf("cellBatch=%d, wgIdx=%d, #constraints in cell=%d\n",cellBatch,wgIdx,numConstraintsHost[cellIdx]);
+                                       }
+                                       const int start = offsetsHost[cellIdx];
+                                       int numConstraintsInCell = numConstraintsHost[cellIdx];
+                                       //                              const int end = start + numConstraintsInCell;
+
+                                       SolveTask task(bodyNative, shapeNative, constraintNative, start, numConstraintsInCell, maxNumBatches, usedBodies, wgIdx, batchSizes, cellIdx);
+                                       task.m_solveFriction = false;
+                                       task.run(0);
+                               }
+                       }
+               }
+
+               for (int iter = 0; iter < m_nIterations; iter++)
+               {
+                       for (int cellBatch = 0; cellBatch < B3_SOLVER_N_BATCHES; cellBatch++)
+                       {
+                               int nSplitX = B3_SOLVER_N_SPLIT_X;
+                               int nSplitY = B3_SOLVER_N_SPLIT_Y;
+
+                               int numWorkgroups = B3_SOLVER_N_CELLS / B3_SOLVER_N_BATCHES;
+
+                               for (int wgIdx = 0; wgIdx < numWorkgroups; wgIdx++)
+                               {
+                                       int zIdx = (wgIdx / ((nSplitX * nSplitY) / 4)) * 2 + ((cellBatch & 4) >> 2);
+                                       int remain = (wgIdx % ((nSplitX * nSplitY) / 4));
+                                       int yIdx = (remain / (nSplitX / 2)) * 2 + ((cellBatch & 2) >> 1);
+                                       int xIdx = (remain % (nSplitX / 2)) * 2 + (cellBatch & 1);
+
+                                       int cellIdx = xIdx + yIdx * nSplitX + zIdx * (nSplitX * nSplitY);
+
+                                       if (numConstraintsHost[cellIdx] == 0)
+                                               continue;
+
+                                       //printf("yIdx=%d\n",yIdx);
+
+                                       const int start = offsetsHost[cellIdx];
+                                       int numConstraintsInCell = numConstraintsHost[cellIdx];
+                                       //                              const int end = start + numConstraintsInCell;
+
+                                       SolveTask task(bodyNative, shapeNative, constraintNative, start, numConstraintsInCell, maxNumBatches, 0, 0, batchSizes, cellIdx);
+                                       task.m_solveFriction = true;
+                                       task.run(0);
+                               }
+                       }
+               }
+       }
+       else
+       {
+               for (int iter = 0; iter < m_nIterations; iter++)
+               {
+                       SolveTask task(bodyNative, shapeNative, constraintNative, 0, n, maxNumBatches, 0, 0, 0, 0);
+                       task.m_solveFriction = false;
+                       task.run(0);
+               }
+
+               for (int iter = 0; iter < m_nIterations; iter++)
+               {
+                       SolveTask task(bodyNative, shapeNative, constraintNative, 0, n, maxNumBatches, 0, 0, 0, 0);
+                       task.m_solveFriction = true;
+                       task.run(0);
+               }
+       }
+
+       bodyBuf->copyFromHost(bodyNative);
+       shapeBuf->copyFromHost(shapeNative);
+       constraint->copyFromHost(constraintNative);
+       frame++;
+}
+
+void checkConstraintBatch(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+                                                 const b3OpenCLArray<b3InertiaData>* shapeBuf,
+                                                 b3OpenCLArray<b3GpuConstraint4>* constraint,
+                                                 b3OpenCLArray<unsigned int>* m_numConstraints,
+                                                 b3OpenCLArray<unsigned int>* m_offsets,
+                                                 int batchId)
+{
+       //                                              b3BufferInfoCL( m_numConstraints->getBufferCL() ),
+       //                                              b3BufferInfoCL( m_offsets->getBufferCL() )
+
+       int cellBatch = batchId;
+       const int nn = B3_SOLVER_N_CELLS;
+       //      int numWorkItems = 64*nn/B3_SOLVER_N_BATCHES;
+
+       b3AlignedObjectArray<unsigned int> gN;
+       m_numConstraints->copyToHost(gN);
+       b3AlignedObjectArray<unsigned int> gOffsets;
+       m_offsets->copyToHost(gOffsets);
+       int nSplitX = B3_SOLVER_N_SPLIT_X;
+       int nSplitY = B3_SOLVER_N_SPLIT_Y;
+
+       //      int bIdx = batchId;
+
+       b3AlignedObjectArray<b3GpuConstraint4> cpuConstraints;
+       constraint->copyToHost(cpuConstraints);
+
+       printf("batch = %d\n", batchId);
+
+       int numWorkgroups = nn / B3_SOLVER_N_BATCHES;
+       b3AlignedObjectArray<int> usedBodies;
+
+       for (int wgIdx = 0; wgIdx < numWorkgroups; wgIdx++)
+       {
+               printf("wgIdx = %d           ", wgIdx);
+
+               int zIdx = (wgIdx / ((nSplitX * nSplitY)) / 2) * 2 + ((cellBatch & 4) >> 2);
+               int remain = wgIdx % ((nSplitX * nSplitY));
+               int yIdx = (remain % (nSplitX / 2)) * 2 + ((cellBatch & 2) >> 1);
+               int xIdx = (remain / (nSplitX / 2)) * 2 + (cellBatch & 1);
+
+               int cellIdx = xIdx + yIdx * nSplitX + zIdx * (nSplitX * nSplitY);
+               printf("cellIdx=%d\n", cellIdx);
+               if (gN[cellIdx] == 0)
+                       continue;
+
+               const int start = gOffsets[cellIdx];
+               const int end = start + gN[cellIdx];
+
+               for (int c = start; c < end; c++)
+               {
+                       b3GpuConstraint4& constraint = cpuConstraints[c];
+                       //printf("constraint (%d,%d)\n", constraint.m_bodyA,constraint.m_bodyB);
+                       if (usedBodies.findLinearSearch(constraint.m_bodyA) < usedBodies.size())
+                       {
+                               printf("error?\n");
+                       }
+                       if (usedBodies.findLinearSearch(constraint.m_bodyB) < usedBodies.size())
+                       {
+                               printf("error?\n");
+                       }
+               }
+
+               for (int c = start; c < end; c++)
+               {
+                       b3GpuConstraint4& constraint = cpuConstraints[c];
+                       usedBodies.push_back(constraint.m_bodyA);
+                       usedBodies.push_back(constraint.m_bodyB);
+               }
+       }
+}
+
+static bool verify = false;
+
+void b3Solver::solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
+                                                                         b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches)
+{
+       b3Int4 cdata = b3MakeInt4(n, 0, 0, 0);
+       {
+               const int nn = B3_SOLVER_N_CELLS;
+
+               cdata.x = 0;
+               cdata.y = maxNumBatches;  //250;
+
+               int numWorkItems = 64 * nn / B3_SOLVER_N_BATCHES;
+#ifdef DEBUG_ME
+               SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
+               adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device, numWorkItems);
+#endif
+
+               {
+                       B3_PROFILE("m_batchSolveKernel iterations");
+                       for (int iter = 0; iter < m_nIterations; iter++)
+                       {
+                               for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
+                               {
+                                       if (verify)
+                                       {
+                                               checkConstraintBatch(bodyBuf, shapeBuf, constraint, m_numConstraints, m_offsets, ib);
+                                       }
+
+#ifdef DEBUG_ME
+                                       memset(debugInfo, 0, sizeof(SolverDebugInfo) * numWorkItems);
+                                       gpuDebugInfo.write(debugInfo, numWorkItems);
+#endif
+
+                                       cdata.z = ib;
+
+                                       b3LauncherCL launcher(m_queue, m_solveContactKernel, "m_solveContactKernel");
+#if 1
+
+                                       b3BufferInfoCL bInfo[] = {
+
+                                               b3BufferInfoCL(bodyBuf->getBufferCL()),
+                                               b3BufferInfoCL(shapeBuf->getBufferCL()),
+                                               b3BufferInfoCL(constraint->getBufferCL()),
+                                               b3BufferInfoCL(m_numConstraints->getBufferCL()),
+                                               b3BufferInfoCL(m_offsets->getBufferCL())
+#ifdef DEBUG_ME
+                                                       ,
+                                               b3BufferInfoCL(&gpuDebugInfo)
+#endif
+                                       };
+
+                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                       //launcher.setConst(  cdata.x );
+                                       launcher.setConst(cdata.y);
+                                       launcher.setConst(cdata.z);
+                                       b3Int4 nSplit;
+                                       nSplit.x = B3_SOLVER_N_SPLIT_X;
+                                       nSplit.y = B3_SOLVER_N_SPLIT_Y;
+                                       nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+                                       launcher.setConst(nSplit);
+                                       launcher.launch1D(numWorkItems, 64);
+
+#else
+                                       const char* fileName = "m_batchSolveKernel.bin";
+                                       FILE* f = fopen(fileName, "rb");
+                                       if (f)
+                                       {
+                                               int sizeInBytes = 0;
+                                               if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
+                                               {
+                                                       printf("error, cannot get file size\n");
+                                                       exit(0);
+                                               }
+
+                                               unsigned char* buf = (unsigned char*)malloc(sizeInBytes);
+                                               fread(buf, sizeInBytes, 1, f);
+                                               int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes, m_context);
+                                               int num = *(int*)&buf[serializedBytes];
+
+                                               launcher.launch1D(num);
+
+                                               //this clFinish is for testing on errors
+                                               clFinish(m_queue);
+                                       }
+
+#endif
+
+#ifdef DEBUG_ME
+                                       clFinish(m_queue);
+                                       gpuDebugInfo.read(debugInfo, numWorkItems);
+                                       clFinish(m_queue);
+                                       for (int i = 0; i < numWorkItems; i++)
+                                       {
+                                               if (debugInfo[i].m_valInt2 > 0)
+                                               {
+                                                       printf("debugInfo[i].m_valInt2 = %d\n", i, debugInfo[i].m_valInt2);
+                                               }
+
+                                               if (debugInfo[i].m_valInt3 > 0)
+                                               {
+                                                       printf("debugInfo[i].m_valInt3 = %d\n", i, debugInfo[i].m_valInt3);
+                                               }
+                                       }
+#endif  //DEBUG_ME
+                               }
+                       }
+
+                       clFinish(m_queue);
+               }
+
+               cdata.x = 1;
+               bool applyFriction = true;
+               if (applyFriction)
+               {
+                       B3_PROFILE("m_batchSolveKernel iterations2");
+                       for (int iter = 0; iter < m_nIterations; iter++)
+                       {
+                               for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
+                               {
+                                       cdata.z = ib;
+
+                                       b3BufferInfoCL bInfo[] = {
+                                               b3BufferInfoCL(bodyBuf->getBufferCL()),
+                                               b3BufferInfoCL(shapeBuf->getBufferCL()),
+                                               b3BufferInfoCL(constraint->getBufferCL()),
+                                               b3BufferInfoCL(m_numConstraints->getBufferCL()),
+                                               b3BufferInfoCL(m_offsets->getBufferCL())
+#ifdef DEBUG_ME
+                                                       ,
+                                               b3BufferInfoCL(&gpuDebugInfo)
+#endif  //DEBUG_ME
+                                       };
+                                       b3LauncherCL launcher(m_queue, m_solveFrictionKernel, "m_solveFrictionKernel");
+                                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                                       //launcher.setConst(  cdata.x );
+                                       launcher.setConst(cdata.y);
+                                       launcher.setConst(cdata.z);
+                                       b3Int4 nSplit;
+                                       nSplit.x = B3_SOLVER_N_SPLIT_X;
+                                       nSplit.y = B3_SOLVER_N_SPLIT_Y;
+                                       nSplit.z = B3_SOLVER_N_SPLIT_Z;
+
+                                       launcher.setConst(nSplit);
+
+                                       launcher.launch1D(64 * nn / B3_SOLVER_N_BATCHES, 64);
+                               }
+                       }
+                       clFinish(m_queue);
+               }
+#ifdef DEBUG_ME
+               delete[] debugInfo;
+#endif  //DEBUG_ME
+       }
+}
+
+void b3Solver::convertToConstraints(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+                                                                       const b3OpenCLArray<b3InertiaData>* shapeBuf,
+                                                                       b3OpenCLArray<b3Contact4>* contactsIn, b3OpenCLArray<b3GpuConstraint4>* contactCOut, void* additionalData,
+                                                                       int nContacts, const ConstraintCfg& cfg)
+{
+       //      b3OpenCLArray<b3GpuConstraint4>* constraintNative =0;
+       contactCOut->resize(nContacts);
+       struct CB
+       {
+               int m_nContacts;
+               float m_dt;
+               float m_positionDrift;
+               float m_positionConstraintCoeff;
+       };
+
+       {
+               CB cdata;
+               cdata.m_nContacts = nContacts;
+               cdata.m_dt = cfg.m_dt;
+               cdata.m_positionDrift = cfg.m_positionDrift;
+               cdata.m_positionConstraintCoeff = cfg.m_positionConstraintCoeff;
+
+               if (gConvertConstraintOnCpu)
+               {
+                       b3AlignedObjectArray<b3RigidBodyData> gBodies;
+                       bodyBuf->copyToHost(gBodies);
+
+                       b3AlignedObjectArray<b3Contact4> gContact;
+                       contactsIn->copyToHost(gContact);
+
+                       b3AlignedObjectArray<b3InertiaData> gShapes;
+                       shapeBuf->copyToHost(gShapes);
+
+                       b3AlignedObjectArray<b3GpuConstraint4> gConstraintOut;
+                       gConstraintOut.resize(nContacts);
+
+                       B3_PROFILE("cpu contactToConstraintKernel");
+                       for (int gIdx = 0; gIdx < nContacts; gIdx++)
+                       {
+                               int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
+                               int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
+
+                               b3Float4 posA = gBodies[aIdx].m_pos;
+                               b3Float4 linVelA = gBodies[aIdx].m_linVel;
+                               b3Float4 angVelA = gBodies[aIdx].m_angVel;
+                               float invMassA = gBodies[aIdx].m_invMass;
+                               b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;
+
+                               b3Float4 posB = gBodies[bIdx].m_pos;
+                               b3Float4 linVelB = gBodies[bIdx].m_linVel;
+                               b3Float4 angVelB = gBodies[bIdx].m_angVel;
+                               float invMassB = gBodies[bIdx].m_invMass;
+                               b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;
+
+                               b3ContactConstraint4_t cs;
+
+                               setConstraint4(posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
+                                                          &gContact[gIdx], cdata.m_dt, cdata.m_positionDrift, cdata.m_positionConstraintCoeff,
+                                                          &cs);
+
+                               cs.m_batchIdx = gContact[gIdx].m_batchIdx;
+
+                               gConstraintOut[gIdx] = (b3GpuConstraint4&)cs;
+                       }
+
+                       contactCOut->copyFromHost(gConstraintOut);
+               }
+               else
+               {
+                       B3_PROFILE("gpu m_contactToConstraintKernel");
+
+                       b3BufferInfoCL bInfo[] = {b3BufferInfoCL(contactsIn->getBufferCL()), b3BufferInfoCL(bodyBuf->getBufferCL()), b3BufferInfoCL(shapeBuf->getBufferCL()),
+                                                                         b3BufferInfoCL(contactCOut->getBufferCL())};
+                       b3LauncherCL launcher(m_queue, m_contactToConstraintKernel, "m_contactToConstraintKernel");
+                       launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
+                       //launcher.setConst(  cdata );
+
+                       launcher.setConst(cdata.m_nContacts);
+                       launcher.setConst(cdata.m_dt);
+                       launcher.setConst(cdata.m_positionDrift);
+                       launcher.setConst(cdata.m_positionConstraintCoeff);
+
+                       launcher.launch1D(nContacts, 64);
+                       clFinish(m_queue);
+               }
+       }
+}
+
+/*
+void b3Solver::sortContacts(  const b3OpenCLArray<b3RigidBodyData>* bodyBuf, 
+                       b3OpenCLArray<b3Contact4>* contactsIn, void* additionalData, 
+                       int nContacts, const b3Solver::ConstraintCfg& cfg )
+{
+       
+       
+
+       const int sortAlignment = 512; // todo. get this out of sort
+       if( cfg.m_enableParallelSolve )
+       {
+               
+
+               int sortSize = NEXTMULTIPLEOF( nContacts, sortAlignment );
+
+               b3OpenCLArray<unsigned int>* countsNative = m_numConstraints;//BufferUtils::map<TYPE_CL, false>( data->m_device, &countsHost );
+               b3OpenCLArray<unsigned int>* offsetsNative = m_offsets;//BufferUtils::map<TYPE_CL, false>( data->m_device, &offsetsHost );
+
+               {       //      2. set cell idx
+                       struct CB
+                       {
+                               int m_nContacts;
+                               int m_staticIdx;
+                               float m_scale;
+                               int m_nSplit;
+                       };
+
+                       b3Assert( sortSize%64 == 0 );
+                       CB cdata;
+                       cdata.m_nContacts = nContacts;
+                       cdata.m_staticIdx = cfg.m_staticIdx;
+                       cdata.m_scale = 1.f/(N_OBJ_PER_SPLIT*cfg.m_averageExtent);
+                       cdata.m_nSplit = B3_SOLVER_N_SPLIT;
+
+                       
+                       b3BufferInfoCL bInfo[] = { b3BufferInfoCL( contactsIn->getBufferCL() ), b3BufferInfoCL( bodyBuf->getBufferCL() ), b3BufferInfoCL( m_sortDataBuffer->getBufferCL() ) };
+                       b3LauncherCL launcher( m_queue, m_setSortDataKernel );
+                       launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+                       launcher.setConst(  cdata );
+                       launcher.launch1D( sortSize, 64 );
+               }
+
+               {       //      3. sort by cell idx
+                       int n = B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT;
+                       int sortBit = 32;
+                       //if( n <= 0xffff ) sortBit = 16;
+                       //if( n <= 0xff ) sortBit = 8;
+                       m_sort32->execute(*m_sortDataBuffer,sortSize);
+               }
+               {       //      4. find entries
+                       m_search->execute( *m_sortDataBuffer, nContacts, *countsNative, B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT, b3BoundSearchCL::COUNT);
+
+                       m_scan->execute( *countsNative, *offsetsNative, B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT );
+               }
+
+               {       //      5. sort constraints by cellIdx
+                       //      todo. preallocate this
+//                     b3Assert( contactsIn->getType() == TYPE_HOST );
+//                     b3OpenCLArray<b3Contact4>* out = BufferUtils::map<TYPE_CL, false>( data->m_device, contactsIn );        //      copying contacts to this buffer
+
+                       {
+                               
+
+                               b3Int4 cdata; cdata.x = nContacts;
+                               b3BufferInfoCL bInfo[] = { b3BufferInfoCL( contactsIn->getBufferCL() ), b3BufferInfoCL( m_contactBuffer->getBufferCL() ), b3BufferInfoCL( m_sortDataBuffer->getBufferCL() ) };
+                               b3LauncherCL launcher( m_queue, m_reorderContactKernel );
+                               launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
+                               launcher.setConst(  cdata );
+                               launcher.launch1D( nContacts, 64 );
+                       }
+//                     BufferUtils::unmap<true>( out, contactsIn, nContacts );
+               }
+       }
+
+       
+}
+
+*/
+void b3Solver::batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* nNative, b3OpenCLArray<unsigned int>* offsetsNative, int staticIdx)
+{
+       int numWorkItems = 64 * B3_SOLVER_N_CELLS;
+       {
+               B3_PROFILE("batch generation");
+
+               b3Int4 cdata;
+               cdata.x = nContacts;
+               cdata.y = 0;
+               cdata.z = staticIdx;
+
+#ifdef BATCH_DEBUG
+               SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
+               adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device, numWorkItems);
+               memset(debugInfo, 0, sizeof(SolverDebugInfo) * numWorkItems);
+               gpuDebugInfo.write(debugInfo, numWorkItems);
+#endif
+
+#if 0
+               b3BufferInfoCL bInfo[] = { 
+                       b3BufferInfoCL( contacts->getBufferCL() ), 
+                       b3BufferInfoCL(  m_contactBuffer2->getBufferCL()),
+                       b3BufferInfoCL( nNative->getBufferCL() ), 
+                       b3BufferInfoCL( offsetsNative->getBufferCL() ),
+#ifdef BATCH_DEBUG
+                       ,       b3BufferInfoCL(&gpuDebugInfo)
+#endif
+               };
+#endif
+
+               {
+                       m_batchSizes.resize(nNative->size());
+                       B3_PROFILE("batchingKernel");
+                       //b3LauncherCL launcher( m_queue, m_batchingKernel);
+                       cl_kernel k = useNewBatchingKernel ? m_batchingKernelNew : m_batchingKernel;
+
+                       b3LauncherCL launcher(m_queue, k, "*batchingKernel");
+                       if (!useNewBatchingKernel)
+                       {
+                               launcher.setBuffer(contacts->getBufferCL());
+                       }
+                       launcher.setBuffer(m_contactBuffer2->getBufferCL());
+                       launcher.setBuffer(nNative->getBufferCL());
+                       launcher.setBuffer(offsetsNative->getBufferCL());
+
+                       launcher.setBuffer(m_batchSizes.getBufferCL());
+
+                       //launcher.setConst(  cdata );
+                       launcher.setConst(staticIdx);
+
+                       launcher.launch1D(numWorkItems, 64);
+                       //clFinish(m_queue);
+                       //b3AlignedObjectArray<int> batchSizesCPU;
+                       //m_batchSizes.copyToHost(batchSizesCPU);
+                       //printf(".\n");
+               }
+
+#ifdef BATCH_DEBUG
+               aaaa
+                       b3Contact4* hostContacts = new b3Contact4[nContacts];
+               m_contactBuffer->read(hostContacts, nContacts);
+               clFinish(m_queue);
+
+               gpuDebugInfo.read(debugInfo, numWorkItems);
+               clFinish(m_queue);
+
+               for (int i = 0; i < numWorkItems; i++)
+               {
+                       if (debugInfo[i].m_valInt1 > 0)
+                       {
+                               printf("catch\n");
+                       }
+                       if (debugInfo[i].m_valInt2 > 0)
+                       {
+                               printf("catch22\n");
+                       }
+
+                       if (debugInfo[i].m_valInt3 > 0)
+                       {
+                               printf("catch666\n");
+                       }
+
+                       if (debugInfo[i].m_valInt4 > 0)
+                       {
+                               printf("catch777\n");
+                       }
+               }
+               delete[] debugInfo;
+#endif  //BATCH_DEBUG
+       }
+
+       //      copy buffer to buffer
+       //b3Assert(m_contactBuffer->size()==nContacts);
+       //contacts->copyFromOpenCLArray( *m_contactBuffer);
+       //clFinish(m_queue);//needed?
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3Solver.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/b3Solver.h
new file mode 100644 (file)
index 0000000..ee63531
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+#ifndef __ADL_SOLVER_H
+#define __ADL_SOLVER_H
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
+#include "b3GpuConstraint4.h"
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
+
+#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
+#include "Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h"
+
+#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
+
+#define B3NEXTMULTIPLEOF(num, alignment) (((num) / (alignment) + (((num) % (alignment) == 0) ? 0 : 1)) * (alignment))
+
+enum
+{
+       B3_SOLVER_N_SPLIT_X = 8,  //16,//4,
+       B3_SOLVER_N_SPLIT_Y = 4,  //16,//4,
+       B3_SOLVER_N_SPLIT_Z = 8,  //,
+       B3_SOLVER_N_CELLS = B3_SOLVER_N_SPLIT_X * B3_SOLVER_N_SPLIT_Y * B3_SOLVER_N_SPLIT_Z,
+       B3_SOLVER_N_BATCHES = 8,  //4,//8,//4,
+       B3_MAX_NUM_BATCHES = 128,
+};
+
+class b3SolverBase
+{
+public:
+       struct ConstraintCfg
+       {
+               ConstraintCfg(float dt = 0.f) : m_positionDrift(0.005f), m_positionConstraintCoeff(0.2f), m_dt(dt), m_staticIdx(-1) {}
+
+               float m_positionDrift;
+               float m_positionConstraintCoeff;
+               float m_dt;
+               bool m_enableParallelSolve;
+               float m_batchCellSize;
+               int m_staticIdx;
+       };
+};
+
+class b3Solver : public b3SolverBase
+{
+public:
+       cl_context m_context;
+       cl_device_id m_device;
+       cl_command_queue m_queue;
+
+       b3OpenCLArray<unsigned int>* m_numConstraints;
+       b3OpenCLArray<unsigned int>* m_offsets;
+       b3OpenCLArray<int> m_batchSizes;
+
+       int m_nIterations;
+       cl_kernel m_batchingKernel;
+       cl_kernel m_batchingKernelNew;
+       cl_kernel m_solveContactKernel;
+       cl_kernel m_solveFrictionKernel;
+       cl_kernel m_contactToConstraintKernel;
+       cl_kernel m_setSortDataKernel;
+       cl_kernel m_reorderContactKernel;
+       cl_kernel m_copyConstraintKernel;
+
+       class b3RadixSort32CL* m_sort32;
+       class b3BoundSearchCL* m_search;
+       class b3PrefixScanCL* m_scan;
+
+       b3OpenCLArray<b3SortData>* m_sortDataBuffer;
+       b3OpenCLArray<b3Contact4>* m_contactBuffer2;
+
+       enum
+       {
+               DYNAMIC_CONTACT_ALLOCATION_THRESHOLD = 2000000,
+       };
+
+       b3Solver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity);
+
+       virtual ~b3Solver();
+
+       void solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* inertiaBuf,
+                                                               b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches);
+
+       void solveContactConstraintHost(b3OpenCLArray<b3RigidBodyData>* bodyBuf, b3OpenCLArray<b3InertiaData>* shapeBuf,
+                                                                       b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, b3AlignedObjectArray<int>* batchSizes);
+
+       void convertToConstraints(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
+                                                         const b3OpenCLArray<b3InertiaData>* shapeBuf,
+                                                         b3OpenCLArray<b3Contact4>* contactsIn, b3OpenCLArray<b3GpuConstraint4>* contactCOut, void* additionalData,
+                                                         int nContacts, const ConstraintCfg& cfg);
+
+       void batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx);
+};
+
+#endif  //__ADL_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl
new file mode 100644 (file)
index 0000000..3b891b8
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile __global int*
+#endif
+
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+#define WG_SIZE 64
+
+
+
+
+
+typedef struct 
+{
+       int m_n;
+       int m_start;
+       int m_staticIdx;
+       int m_paddings[1];
+} ConstBuffer;
+
+typedef struct 
+{
+       int m_a;
+       int m_b;
+       u32 m_idx;
+}Elem;
+
+#define STACK_SIZE (WG_SIZE*10)
+//#define STACK_SIZE (WG_SIZE)
+#define RING_SIZE 1024
+#define RING_SIZE_MASK (RING_SIZE-1)
+#define CHECK_SIZE (WG_SIZE)
+
+
+#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd)
+#define RING_END ldsTmp
+
+u32 readBuf(__local u32* buff, int idx)
+{
+       idx = idx % (32*CHECK_SIZE);
+       int bitIdx = idx%32;
+       int bufIdx = idx/32;
+       return buff[bufIdx] & (1<<bitIdx);
+}
+
+void writeBuf(__local u32* buff, int idx)
+{
+       idx = idx % (32*CHECK_SIZE);
+       int bitIdx = idx%32;
+       int bufIdx = idx/32;
+//     buff[bufIdx] |= (1<<bitIdx);
+       atom_or( &buff[bufIdx], (1<<bitIdx) );
+}
+
+u32 tryWrite(__local u32* buff, int idx)
+{
+       idx = idx % (32*CHECK_SIZE);
+       int bitIdx = idx%32;
+       int bufIdx = idx/32;
+       u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );
+       return ((ans >> bitIdx)&1) == 0;
+}
+
+//     batching on the GPU
+__kernel void CreateBatches( __global const struct b3Contact4Data* gConstraints, __global struct b3Contact4Data* gConstraintsOut,
+               __global const u32* gN, __global const u32* gStart, __global int* batchSizes, 
+               int m_staticIdx )
+{
+       __local u32 ldsStackIdx[STACK_SIZE];
+       __local u32 ldsStackEnd;
+       __local Elem ldsRingElem[RING_SIZE];
+       __local u32 ldsRingEnd;
+       __local u32 ldsTmp;
+       __local u32 ldsCheckBuffer[CHECK_SIZE];
+       __local u32 ldsFixedBuffer[CHECK_SIZE];
+       __local u32 ldsGEnd;
+       __local u32 ldsDstEnd;
+
+       int wgIdx = GET_GROUP_IDX;
+       int lIdx = GET_LOCAL_IDX;
+       
+       const int m_n = gN[wgIdx];
+       const int m_start = gStart[wgIdx];
+               
+       if( lIdx == 0 )
+       {
+               ldsRingEnd = 0;
+               ldsGEnd = 0;
+               ldsStackEnd = 0;
+               ldsDstEnd = m_start;
+       }
+       
+       
+       
+//     while(1)
+//was 250
+       int ie=0;
+       int maxBatch = 0;
+       for(ie=0; ie<50; ie++)
+       {
+               ldsFixedBuffer[lIdx] = 0;
+
+               for(int giter=0; giter<4; giter++)
+               {
+                       int ringCap = GET_RING_CAPACITY;
+               
+                       //      1. fill ring
+                       if( ldsGEnd < m_n )
+                       {
+                               while( ringCap > WG_SIZE )
+                               {
+                                       if( ldsGEnd >= m_n ) break;
+                                       if( lIdx < ringCap - WG_SIZE )
+                                       {
+                                               int srcIdx;
+                                               AtomInc1( ldsGEnd, srcIdx );
+                                               if( srcIdx < m_n )
+                                               {
+                                                       int dstIdx;
+                                                       AtomInc1( ldsRingEnd, dstIdx );
+                                                       
+                                                       int a = gConstraints[m_start+srcIdx].m_bodyAPtrAndSignBit;
+                                                       int b = gConstraints[m_start+srcIdx].m_bodyBPtrAndSignBit;
+                                                       ldsRingElem[dstIdx].m_a = (a>b)? b:a;
+                                                       ldsRingElem[dstIdx].m_b = (a>b)? a:b;
+                                                       ldsRingElem[dstIdx].m_idx = srcIdx;
+                                               }
+                                       }
+                                       ringCap = GET_RING_CAPACITY;
+                               }
+                       }
+
+                       GROUP_LDS_BARRIER;
+       
+                       //      2. fill stack
+                       __local Elem* dst = ldsRingElem;
+                       if( lIdx == 0 ) RING_END = 0;
+
+                       int srcIdx=lIdx;
+                       int end = ldsRingEnd;
+
+                       {
+                               for(int ii=0; ii<end; ii+=WG_SIZE, srcIdx+=WG_SIZE)
+                               {
+                                       Elem e;
+                                       if(srcIdx<end) e = ldsRingElem[srcIdx];
+                                       bool done = (srcIdx<end)?false:true;
+
+                                       for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) ldsCheckBuffer[lIdx] = 0;
+                                       
+                                       if( !done )
+                                       {
+                                               int aUsed = readBuf( ldsFixedBuffer, abs(e.m_a));
+                                               int bUsed = readBuf( ldsFixedBuffer, abs(e.m_b));
+
+                                               if( aUsed==0 && bUsed==0 )
+                                               {
+                                                       int aAvailable=1;
+                                                       int bAvailable=1;
+                                                       int ea = abs(e.m_a);
+                                                       int eb = abs(e.m_b);
+
+                                                       bool aStatic = (e.m_a<0) ||(ea==m_staticIdx);
+                                                       bool bStatic = (e.m_b<0) ||(eb==m_staticIdx);
+                                                       
+                                                       if (!aStatic)
+                                                               aAvailable = tryWrite( ldsCheckBuffer, ea );
+                                                       if (!bStatic)
+                                                               bAvailable = tryWrite( ldsCheckBuffer, eb );
+                                                       
+                                                       //aAvailable = aStatic? 1: aAvailable;
+                                                       //bAvailable = bStatic? 1: bAvailable;
+
+                                                       bool success = (aAvailable && bAvailable);
+                                                       if(success)
+                                                       {
+                                                       
+                                                               if (!aStatic)
+                                                                       writeBuf( ldsFixedBuffer, ea );
+                                                               if (!bStatic)
+                                                                       writeBuf( ldsFixedBuffer, eb );
+                                                       }
+                                                       done = success;
+                                               }
+                                       }
+
+                                       //      put it aside
+                                       if(srcIdx<end)
+                                       {
+                                               if( done )
+                                               {
+                                                       int dstIdx; AtomInc1( ldsStackEnd, dstIdx );
+                                                       if( dstIdx < STACK_SIZE )
+                                                               ldsStackIdx[dstIdx] = e.m_idx;
+                                                       else{
+                                                               done = false;
+                                                               AtomAdd( ldsStackEnd, -1 );
+                                                       }
+                                               }
+                                               if( !done )
+                                               {
+                                                       int dstIdx; AtomInc1( RING_END, dstIdx );
+                                                       dst[dstIdx] = e;
+                                               }
+                                       }
+
+                                       //      if filled, flush
+                                       if( ldsStackEnd == STACK_SIZE )
+                                       {
+                                               for(int i=lIdx; i<STACK_SIZE; i+=WG_SIZE)
+                                               {
+                                                       int idx = m_start + ldsStackIdx[i];
+                                                       int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
+                                                       gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
+                                                       gConstraintsOut[ dstIdx ].m_batchIdx = ie;
+                                               }
+                                               if( lIdx == 0 ) ldsStackEnd = 0;
+
+                                               //for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) 
+                                               ldsFixedBuffer[lIdx] = 0;
+                                       }
+                               }
+                       }
+
+                       if( lIdx == 0 ) ldsRingEnd = RING_END;
+               }
+
+               GROUP_LDS_BARRIER;
+
+               for(int i=lIdx; i<ldsStackEnd; i+=WG_SIZE)
+               {
+                       int idx = m_start + ldsStackIdx[i];
+                       int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
+                       gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
+                       gConstraintsOut[ dstIdx ].m_batchIdx = ie;
+               }
+
+               //      in case it couldn't consume any pair. Flush them
+               //      todo. Serial batch worth while?
+               if( ldsStackEnd == 0 )
+               {
+                       for(int i=lIdx; i<ldsRingEnd; i+=WG_SIZE)
+                       {
+                               int idx = m_start + ldsRingElem[i].m_idx;
+                               int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
+                               gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
+                               int curBatch = 100+i;
+                               if (maxBatch < curBatch)
+                                       maxBatch = curBatch;
+                               
+                               gConstraintsOut[ dstIdx ].m_batchIdx = curBatch;
+                               
+                       }
+                       GROUP_LDS_BARRIER;
+                       if( lIdx == 0 ) ldsRingEnd = 0;
+               }
+
+               if( lIdx == 0 ) ldsStackEnd = 0;
+
+               GROUP_LDS_BARRIER;
+
+               //      termination
+               if( ldsGEnd == m_n && ldsRingEnd == 0 )
+                       break;
+       }
+
+       if( lIdx == 0 )
+       {
+               if (maxBatch < ie)
+                       maxBatch=ie;
+               batchSizes[wgIdx]=maxBatch;
+       }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h
new file mode 100644 (file)
index 0000000..7c73c96
--- /dev/null
@@ -0,0 +1,387 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* batchingKernelsCL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Takahiro Harada\n"
+       "#ifndef B3_CONTACT4DATA_H\n"
+       "#define B3_CONTACT4DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "typedef  struct b3Contact4Data b3Contact4Data_t;\n"
+       "struct b3Contact4Data\n"
+       "{\n"
+       "       b3Float4        m_worldPosB[4];\n"
+       "//     b3Float4        m_localPosA[4];\n"
+       "//     b3Float4        m_localPosB[4];\n"
+       "       b3Float4        m_worldNormalOnB;       //      w: m_nPoints\n"
+       "       unsigned short  m_restituitionCoeffCmp;\n"
+       "       unsigned short  m_frictionCoeffCmp;\n"
+       "       int m_batchIdx;\n"
+       "       int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+       "       int m_bodyBPtrAndSignBit;\n"
+       "       int     m_childIndexA;\n"
+       "       int     m_childIndexB;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "};\n"
+       "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+       "{\n"
+       "       return (int)contact->m_worldNormalOnB.w;\n"
+       "};\n"
+       "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+       "{\n"
+       "       contact->m_worldNormalOnB.w = (float)numPoints;\n"
+       "};\n"
+       "#endif //B3_CONTACT4DATA_H\n"
+       "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+       "#ifdef cl_ext_atomic_counters_32\n"
+       "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+       "#else\n"
+       "#define counter32_t volatile __global int*\n"
+       "#endif\n"
+       "typedef unsigned int u32;\n"
+       "typedef unsigned short u16;\n"
+       "typedef unsigned char u8;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GET_NUM_GROUPS get_num_groups(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define AppendInc(x, out) out = atomic_inc(x)\n"
+       "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+       "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+       "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+       "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+       "#define make_float4 (float4)\n"
+       "#define make_float2 (float2)\n"
+       "#define make_uint4 (uint4)\n"
+       "#define make_int4 (int4)\n"
+       "#define make_uint2 (uint2)\n"
+       "#define make_int2 (int2)\n"
+       "#define max2 max\n"
+       "#define min2 min\n"
+       "#define WG_SIZE 64\n"
+       "typedef struct \n"
+       "{\n"
+       "       int m_n;\n"
+       "       int m_start;\n"
+       "       int m_staticIdx;\n"
+       "       int m_paddings[1];\n"
+       "} ConstBuffer;\n"
+       "typedef struct \n"
+       "{\n"
+       "       int m_a;\n"
+       "       int m_b;\n"
+       "       u32 m_idx;\n"
+       "}Elem;\n"
+       "#define STACK_SIZE (WG_SIZE*10)\n"
+       "//#define STACK_SIZE (WG_SIZE)\n"
+       "#define RING_SIZE 1024\n"
+       "#define RING_SIZE_MASK (RING_SIZE-1)\n"
+       "#define CHECK_SIZE (WG_SIZE)\n"
+       "#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd)\n"
+       "#define RING_END ldsTmp\n"
+       "u32 readBuf(__local u32* buff, int idx)\n"
+       "{\n"
+       "       idx = idx % (32*CHECK_SIZE);\n"
+       "       int bitIdx = idx%32;\n"
+       "       int bufIdx = idx/32;\n"
+       "       return buff[bufIdx] & (1<<bitIdx);\n"
+       "}\n"
+       "void writeBuf(__local u32* buff, int idx)\n"
+       "{\n"
+       "       idx = idx % (32*CHECK_SIZE);\n"
+       "       int bitIdx = idx%32;\n"
+       "       int bufIdx = idx/32;\n"
+       "//     buff[bufIdx] |= (1<<bitIdx);\n"
+       "       atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+       "}\n"
+       "u32 tryWrite(__local u32* buff, int idx)\n"
+       "{\n"
+       "       idx = idx % (32*CHECK_SIZE);\n"
+       "       int bitIdx = idx%32;\n"
+       "       int bufIdx = idx/32;\n"
+       "       u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+       "       return ((ans >> bitIdx)&1) == 0;\n"
+       "}\n"
+       "//     batching on the GPU\n"
+       "__kernel void CreateBatches( __global const struct b3Contact4Data* gConstraints, __global struct b3Contact4Data* gConstraintsOut,\n"
+       "               __global const u32* gN, __global const u32* gStart, __global int* batchSizes, \n"
+       "               int m_staticIdx )\n"
+       "{\n"
+       "       __local u32 ldsStackIdx[STACK_SIZE];\n"
+       "       __local u32 ldsStackEnd;\n"
+       "       __local Elem ldsRingElem[RING_SIZE];\n"
+       "       __local u32 ldsRingEnd;\n"
+       "       __local u32 ldsTmp;\n"
+       "       __local u32 ldsCheckBuffer[CHECK_SIZE];\n"
+       "       __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
+       "       __local u32 ldsGEnd;\n"
+       "       __local u32 ldsDstEnd;\n"
+       "       int wgIdx = GET_GROUP_IDX;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       \n"
+       "       const int m_n = gN[wgIdx];\n"
+       "       const int m_start = gStart[wgIdx];\n"
+       "               \n"
+       "       if( lIdx == 0 )\n"
+       "       {\n"
+       "               ldsRingEnd = 0;\n"
+       "               ldsGEnd = 0;\n"
+       "               ldsStackEnd = 0;\n"
+       "               ldsDstEnd = m_start;\n"
+       "       }\n"
+       "       \n"
+       "       \n"
+       "       \n"
+       "//     while(1)\n"
+       "//was 250\n"
+       "       int ie=0;\n"
+       "       int maxBatch = 0;\n"
+       "       for(ie=0; ie<50; ie++)\n"
+       "       {\n"
+       "               ldsFixedBuffer[lIdx] = 0;\n"
+       "               for(int giter=0; giter<4; giter++)\n"
+       "               {\n"
+       "                       int ringCap = GET_RING_CAPACITY;\n"
+       "               \n"
+       "                       //      1. fill ring\n"
+       "                       if( ldsGEnd < m_n )\n"
+       "                       {\n"
+       "                               while( ringCap > WG_SIZE )\n"
+       "                               {\n"
+       "                                       if( ldsGEnd >= m_n ) break;\n"
+       "                                       if( lIdx < ringCap - WG_SIZE )\n"
+       "                                       {\n"
+       "                                               int srcIdx;\n"
+       "                                               AtomInc1( ldsGEnd, srcIdx );\n"
+       "                                               if( srcIdx < m_n )\n"
+       "                                               {\n"
+       "                                                       int dstIdx;\n"
+       "                                                       AtomInc1( ldsRingEnd, dstIdx );\n"
+       "                                                       \n"
+       "                                                       int a = gConstraints[m_start+srcIdx].m_bodyAPtrAndSignBit;\n"
+       "                                                       int b = gConstraints[m_start+srcIdx].m_bodyBPtrAndSignBit;\n"
+       "                                                       ldsRingElem[dstIdx].m_a = (a>b)? b:a;\n"
+       "                                                       ldsRingElem[dstIdx].m_b = (a>b)? a:b;\n"
+       "                                                       ldsRingElem[dstIdx].m_idx = srcIdx;\n"
+       "                                               }\n"
+       "                                       }\n"
+       "                                       ringCap = GET_RING_CAPACITY;\n"
+       "                               }\n"
+       "                       }\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "       \n"
+       "                       //      2. fill stack\n"
+       "                       __local Elem* dst = ldsRingElem;\n"
+       "                       if( lIdx == 0 ) RING_END = 0;\n"
+       "                       int srcIdx=lIdx;\n"
+       "                       int end = ldsRingEnd;\n"
+       "                       {\n"
+       "                               for(int ii=0; ii<end; ii+=WG_SIZE, srcIdx+=WG_SIZE)\n"
+       "                               {\n"
+       "                                       Elem e;\n"
+       "                                       if(srcIdx<end) e = ldsRingElem[srcIdx];\n"
+       "                                       bool done = (srcIdx<end)?false:true;\n"
+       "                                       for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) ldsCheckBuffer[lIdx] = 0;\n"
+       "                                       \n"
+       "                                       if( !done )\n"
+       "                                       {\n"
+       "                                               int aUsed = readBuf( ldsFixedBuffer, abs(e.m_a));\n"
+       "                                               int bUsed = readBuf( ldsFixedBuffer, abs(e.m_b));\n"
+       "                                               if( aUsed==0 && bUsed==0 )\n"
+       "                                               {\n"
+       "                                                       int aAvailable=1;\n"
+       "                                                       int bAvailable=1;\n"
+       "                                                       int ea = abs(e.m_a);\n"
+       "                                                       int eb = abs(e.m_b);\n"
+       "                                                       bool aStatic = (e.m_a<0) ||(ea==m_staticIdx);\n"
+       "                                                       bool bStatic = (e.m_b<0) ||(eb==m_staticIdx);\n"
+       "                                                       \n"
+       "                                                       if (!aStatic)\n"
+       "                                                               aAvailable = tryWrite( ldsCheckBuffer, ea );\n"
+       "                                                       if (!bStatic)\n"
+       "                                                               bAvailable = tryWrite( ldsCheckBuffer, eb );\n"
+       "                                                       \n"
+       "                                                       //aAvailable = aStatic? 1: aAvailable;\n"
+       "                                                       //bAvailable = bStatic? 1: bAvailable;\n"
+       "                                                       bool success = (aAvailable && bAvailable);\n"
+       "                                                       if(success)\n"
+       "                                                       {\n"
+       "                                                       \n"
+       "                                                               if (!aStatic)\n"
+       "                                                                       writeBuf( ldsFixedBuffer, ea );\n"
+       "                                                               if (!bStatic)\n"
+       "                                                                       writeBuf( ldsFixedBuffer, eb );\n"
+       "                                                       }\n"
+       "                                                       done = success;\n"
+       "                                               }\n"
+       "                                       }\n"
+       "                                       //      put it aside\n"
+       "                                       if(srcIdx<end)\n"
+       "                                       {\n"
+       "                                               if( done )\n"
+       "                                               {\n"
+       "                                                       int dstIdx; AtomInc1( ldsStackEnd, dstIdx );\n"
+       "                                                       if( dstIdx < STACK_SIZE )\n"
+       "                                                               ldsStackIdx[dstIdx] = e.m_idx;\n"
+       "                                                       else{\n"
+       "                                                               done = false;\n"
+       "                                                               AtomAdd( ldsStackEnd, -1 );\n"
+       "                                                       }\n"
+       "                                               }\n"
+       "                                               if( !done )\n"
+       "                                               {\n"
+       "                                                       int dstIdx; AtomInc1( RING_END, dstIdx );\n"
+       "                                                       dst[dstIdx] = e;\n"
+       "                                               }\n"
+       "                                       }\n"
+       "                                       //      if filled, flush\n"
+       "                                       if( ldsStackEnd == STACK_SIZE )\n"
+       "                                       {\n"
+       "                                               for(int i=lIdx; i<STACK_SIZE; i+=WG_SIZE)\n"
+       "                                               {\n"
+       "                                                       int idx = m_start + ldsStackIdx[i];\n"
+       "                                                       int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
+       "                                                       gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
+       "                                                       gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
+       "                                               }\n"
+       "                                               if( lIdx == 0 ) ldsStackEnd = 0;\n"
+       "                                               //for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) \n"
+       "                                               ldsFixedBuffer[lIdx] = 0;\n"
+       "                                       }\n"
+       "                               }\n"
+       "                       }\n"
+       "                       if( lIdx == 0 ) ldsRingEnd = RING_END;\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "               for(int i=lIdx; i<ldsStackEnd; i+=WG_SIZE)\n"
+       "               {\n"
+       "                       int idx = m_start + ldsStackIdx[i];\n"
+       "                       int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
+       "                       gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
+       "                       gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
+       "               }\n"
+       "               //      in case it couldn't consume any pair. Flush them\n"
+       "               //      todo. Serial batch worth while?\n"
+       "               if( ldsStackEnd == 0 )\n"
+       "               {\n"
+       "                       for(int i=lIdx; i<ldsRingEnd; i+=WG_SIZE)\n"
+       "                       {\n"
+       "                               int idx = m_start + ldsRingElem[i].m_idx;\n"
+       "                               int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
+       "                               gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
+       "                               int curBatch = 100+i;\n"
+       "                               if (maxBatch < curBatch)\n"
+       "                                       maxBatch = curBatch;\n"
+       "                               \n"
+       "                               gConstraintsOut[ dstIdx ].m_batchIdx = curBatch;\n"
+       "                               \n"
+       "                       }\n"
+       "                       GROUP_LDS_BARRIER;\n"
+       "                       if( lIdx == 0 ) ldsRingEnd = 0;\n"
+       "               }\n"
+       "               if( lIdx == 0 ) ldsStackEnd = 0;\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "               //      termination\n"
+       "               if( ldsGEnd == m_n && ldsRingEnd == 0 )\n"
+       "                       break;\n"
+       "       }\n"
+       "       if( lIdx == 0 )\n"
+       "       {\n"
+       "               if (maxBatch < ie)\n"
+       "                       maxBatch=ie;\n"
+       "               batchSizes[wgIdx]=maxBatch;\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl
new file mode 100644 (file)
index 0000000..ba1b66d
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile __global int*
+#endif
+
+#define SIMD_WIDTH 64
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+#define WG_SIZE 64
+
+
+
+
+
+typedef struct 
+{
+       int m_n;
+       int m_start;
+       int m_staticIdx;
+       int m_paddings[1];
+} ConstBuffer;
+
+typedef struct 
+{
+       int m_a;
+       int m_b;
+       u32 m_idx;
+}Elem;
+
+
+
+
+
+//     batching on the GPU
+__kernel void CreateBatchesBruteForce( __global struct b3Contact4Data* gConstraints,   __global const u32* gN, __global const u32* gStart, int m_staticIdx )
+{
+       int wgIdx = GET_GROUP_IDX;
+       int lIdx = GET_LOCAL_IDX;
+       
+       const int m_n = gN[wgIdx];
+       const int m_start = gStart[wgIdx];
+               
+       if( lIdx == 0 )
+       {
+               for (int i=0;i<m_n;i++)
+               {
+                       int srcIdx = i+m_start;
+                       int batchIndex = i;
+                       gConstraints[ srcIdx ].m_batchIdx = batchIndex; 
+               }
+       }
+}
+
+
+#define CHECK_SIZE (WG_SIZE)
+
+
+
+
+u32 readBuf(__local u32* buff, int idx)
+{
+       idx = idx % (32*CHECK_SIZE);
+       int bitIdx = idx%32;
+       int bufIdx = idx/32;
+       return buff[bufIdx] & (1<<bitIdx);
+}
+
+void writeBuf(__local u32* buff, int idx)
+{
+       idx = idx % (32*CHECK_SIZE);
+       int bitIdx = idx%32;
+       int bufIdx = idx/32;
+       buff[bufIdx] |= (1<<bitIdx);
+       //atom_or( &buff[bufIdx], (1<<bitIdx) );
+}
+
+u32 tryWrite(__local u32* buff, int idx)
+{
+       idx = idx % (32*CHECK_SIZE);
+       int bitIdx = idx%32;
+       int bufIdx = idx/32;
+       u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );
+       return ((ans >> bitIdx)&1) == 0;
+}
+
+
+//     batching on the GPU
+__kernel void CreateBatchesNew( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, __global int* batchSizes, int staticIdx )
+{
+       int wgIdx = GET_GROUP_IDX;
+       int lIdx = GET_LOCAL_IDX;
+       const int numConstraints = gN[wgIdx];
+       const int m_start = gStart[wgIdx];
+       b3Contact4Data_t tmp;
+       
+       __local u32 ldsFixedBuffer[CHECK_SIZE];
+               
+       
+       
+       
+       
+       if( lIdx == 0 )
+       {
+       
+               
+               __global struct b3Contact4Data* cs = &gConstraints[m_start];    
+       
+               
+               int numValidConstraints = 0;
+               int batchIdx = 0;
+
+               while( numValidConstraints < numConstraints)
+               {
+                       int nCurrentBatch = 0;
+                       //      clear flag
+       
+                       for(int i=0; i<CHECK_SIZE; i++) 
+                               ldsFixedBuffer[i] = 0;          
+
+                       for(int i=numValidConstraints; i<numConstraints; i++)
+                       {
+
+                               int bodyAS = cs[i].m_bodyAPtrAndSignBit;
+                               int bodyBS = cs[i].m_bodyBPtrAndSignBit;
+                               int bodyA = abs(bodyAS);
+                               int bodyB = abs(bodyBS);
+                               bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
+                               bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
+                               int aUnavailable = aIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyA);
+                               int bUnavailable = bIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyB);
+                               
+                               if( aUnavailable==0 && bUnavailable==0 ) // ok
+                               {
+                                       if (!aIsStatic)
+                                       {
+                                               writeBuf( ldsFixedBuffer, bodyA );
+                                       }
+                                       if (!bIsStatic)
+                                       {
+                                               writeBuf( ldsFixedBuffer, bodyB );
+                                       }
+
+                                       cs[i].m_batchIdx = batchIdx;
+
+                                       if (i!=numValidConstraints)
+                                       {
+
+                                               tmp = cs[i];
+                                               cs[i] = cs[numValidConstraints];
+                                               cs[numValidConstraints]  = tmp;
+
+
+                                       }
+
+                                       numValidConstraints++;
+                                       
+                                       nCurrentBatch++;
+                                       if( nCurrentBatch == SIMD_WIDTH)
+                                       {
+                                               nCurrentBatch = 0;
+                                               for(int i=0; i<CHECK_SIZE; i++) 
+                                                       ldsFixedBuffer[i] = 0;
+                                               
+                                       }
+                               }
+                       }//for
+                       batchIdx ++;
+               }//while
+               
+               batchSizes[wgIdx] = batchIdx;
+
+       }//if( lIdx == 0 )
+       
+       //return batchIdx;
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h
new file mode 100644 (file)
index 0000000..0580065
--- /dev/null
@@ -0,0 +1,290 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* batchingKernelsNewCL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Erwin Coumans\n"
+       "#ifndef B3_CONTACT4DATA_H\n"
+       "#define B3_CONTACT4DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "typedef  struct b3Contact4Data b3Contact4Data_t;\n"
+       "struct b3Contact4Data\n"
+       "{\n"
+       "       b3Float4        m_worldPosB[4];\n"
+       "//     b3Float4        m_localPosA[4];\n"
+       "//     b3Float4        m_localPosB[4];\n"
+       "       b3Float4        m_worldNormalOnB;       //      w: m_nPoints\n"
+       "       unsigned short  m_restituitionCoeffCmp;\n"
+       "       unsigned short  m_frictionCoeffCmp;\n"
+       "       int m_batchIdx;\n"
+       "       int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+       "       int m_bodyBPtrAndSignBit;\n"
+       "       int     m_childIndexA;\n"
+       "       int     m_childIndexB;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "};\n"
+       "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+       "{\n"
+       "       return (int)contact->m_worldNormalOnB.w;\n"
+       "};\n"
+       "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+       "{\n"
+       "       contact->m_worldNormalOnB.w = (float)numPoints;\n"
+       "};\n"
+       "#endif //B3_CONTACT4DATA_H\n"
+       "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+       "#ifdef cl_ext_atomic_counters_32\n"
+       "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+       "#else\n"
+       "#define counter32_t volatile __global int*\n"
+       "#endif\n"
+       "#define SIMD_WIDTH 64\n"
+       "typedef unsigned int u32;\n"
+       "typedef unsigned short u16;\n"
+       "typedef unsigned char u8;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GET_NUM_GROUPS get_num_groups(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define AppendInc(x, out) out = atomic_inc(x)\n"
+       "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+       "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+       "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+       "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+       "#define make_float4 (float4)\n"
+       "#define make_float2 (float2)\n"
+       "#define make_uint4 (uint4)\n"
+       "#define make_int4 (int4)\n"
+       "#define make_uint2 (uint2)\n"
+       "#define make_int2 (int2)\n"
+       "#define max2 max\n"
+       "#define min2 min\n"
+       "#define WG_SIZE 64\n"
+       "typedef struct \n"
+       "{\n"
+       "       int m_n;\n"
+       "       int m_start;\n"
+       "       int m_staticIdx;\n"
+       "       int m_paddings[1];\n"
+       "} ConstBuffer;\n"
+       "typedef struct \n"
+       "{\n"
+       "       int m_a;\n"
+       "       int m_b;\n"
+       "       u32 m_idx;\n"
+       "}Elem;\n"
+       "//     batching on the GPU\n"
+       "__kernel void CreateBatchesBruteForce( __global struct b3Contact4Data* gConstraints,   __global const u32* gN, __global const u32* gStart, int m_staticIdx )\n"
+       "{\n"
+       "       int wgIdx = GET_GROUP_IDX;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       \n"
+       "       const int m_n = gN[wgIdx];\n"
+       "       const int m_start = gStart[wgIdx];\n"
+       "               \n"
+       "       if( lIdx == 0 )\n"
+       "       {\n"
+       "               for (int i=0;i<m_n;i++)\n"
+       "               {\n"
+       "                       int srcIdx = i+m_start;\n"
+       "                       int batchIndex = i;\n"
+       "                       gConstraints[ srcIdx ].m_batchIdx = batchIndex; \n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "#define CHECK_SIZE (WG_SIZE)\n"
+       "u32 readBuf(__local u32* buff, int idx)\n"
+       "{\n"
+       "       idx = idx % (32*CHECK_SIZE);\n"
+       "       int bitIdx = idx%32;\n"
+       "       int bufIdx = idx/32;\n"
+       "       return buff[bufIdx] & (1<<bitIdx);\n"
+       "}\n"
+       "void writeBuf(__local u32* buff, int idx)\n"
+       "{\n"
+       "       idx = idx % (32*CHECK_SIZE);\n"
+       "       int bitIdx = idx%32;\n"
+       "       int bufIdx = idx/32;\n"
+       "       buff[bufIdx] |= (1<<bitIdx);\n"
+       "       //atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+       "}\n"
+       "u32 tryWrite(__local u32* buff, int idx)\n"
+       "{\n"
+       "       idx = idx % (32*CHECK_SIZE);\n"
+       "       int bitIdx = idx%32;\n"
+       "       int bufIdx = idx/32;\n"
+       "       u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
+       "       return ((ans >> bitIdx)&1) == 0;\n"
+       "}\n"
+       "//     batching on the GPU\n"
+       "__kernel void CreateBatchesNew( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, __global int* batchSizes, int staticIdx )\n"
+       "{\n"
+       "       int wgIdx = GET_GROUP_IDX;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       const int numConstraints = gN[wgIdx];\n"
+       "       const int m_start = gStart[wgIdx];\n"
+       "       b3Contact4Data_t tmp;\n"
+       "       \n"
+       "       __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
+       "               \n"
+       "       \n"
+       "       \n"
+       "       \n"
+       "       \n"
+       "       if( lIdx == 0 )\n"
+       "       {\n"
+       "       \n"
+       "               \n"
+       "               __global struct b3Contact4Data* cs = &gConstraints[m_start];    \n"
+       "       \n"
+       "               \n"
+       "               int numValidConstraints = 0;\n"
+       "               int batchIdx = 0;\n"
+       "               while( numValidConstraints < numConstraints)\n"
+       "               {\n"
+       "                       int nCurrentBatch = 0;\n"
+       "                       //      clear flag\n"
+       "       \n"
+       "                       for(int i=0; i<CHECK_SIZE; i++) \n"
+       "                               ldsFixedBuffer[i] = 0;          \n"
+       "                       for(int i=numValidConstraints; i<numConstraints; i++)\n"
+       "                       {\n"
+       "                               int bodyAS = cs[i].m_bodyAPtrAndSignBit;\n"
+       "                               int bodyBS = cs[i].m_bodyBPtrAndSignBit;\n"
+       "                               int bodyA = abs(bodyAS);\n"
+       "                               int bodyB = abs(bodyBS);\n"
+       "                               bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;\n"
+       "                               bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;\n"
+       "                               int aUnavailable = aIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyA);\n"
+       "                               int bUnavailable = bIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyB);\n"
+       "                               \n"
+       "                               if( aUnavailable==0 && bUnavailable==0 ) // ok\n"
+       "                               {\n"
+       "                                       if (!aIsStatic)\n"
+       "                                       {\n"
+       "                                               writeBuf( ldsFixedBuffer, bodyA );\n"
+       "                                       }\n"
+       "                                       if (!bIsStatic)\n"
+       "                                       {\n"
+       "                                               writeBuf( ldsFixedBuffer, bodyB );\n"
+       "                                       }\n"
+       "                                       cs[i].m_batchIdx = batchIdx;\n"
+       "                                       if (i!=numValidConstraints)\n"
+       "                                       {\n"
+       "                                               tmp = cs[i];\n"
+       "                                               cs[i] = cs[numValidConstraints];\n"
+       "                                               cs[numValidConstraints]  = tmp;\n"
+       "                                       }\n"
+       "                                       numValidConstraints++;\n"
+       "                                       \n"
+       "                                       nCurrentBatch++;\n"
+       "                                       if( nCurrentBatch == SIMD_WIDTH)\n"
+       "                                       {\n"
+       "                                               nCurrentBatch = 0;\n"
+       "                                               for(int i=0; i<CHECK_SIZE; i++) \n"
+       "                                                       ldsFixedBuffer[i] = 0;\n"
+       "                                               \n"
+       "                                       }\n"
+       "                               }\n"
+       "                       }//for\n"
+       "                       batchIdx ++;\n"
+       "               }//while\n"
+       "               \n"
+       "               batchSizes[wgIdx] = batchIdx;\n"
+       "       }//if( lIdx == 0 )\n"
+       "       \n"
+       "       //return batchIdx;\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl
new file mode 100644 (file)
index 0000000..e22bc9b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
+
+#include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
+
+
+
+__kernel void 
+  integrateTransformsKernel( __global b3RigidBodyData_t* bodies,const int numNodes, float timeStep, float angularDamping, float4 gravityAcceleration)
+{
+       int nodeID = get_global_id(0);
+       
+       if( nodeID < numNodes)
+       {
+               integrateSingleTransform(bodies,nodeID, timeStep, angularDamping,gravityAcceleration);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h
new file mode 100644 (file)
index 0000000..6e9c53e
--- /dev/null
@@ -0,0 +1,432 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* integrateKernelCL =
+       "/*\n"
+       "Copyright (c) 2013 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Erwin Coumans\n"
+       "#ifndef B3_RIGIDBODY_DATA_H\n"
+       "#define B3_RIGIDBODY_DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#define B3_QUAT_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Quat;\n"
+       "       #define b3QuatConstArg const b3Quat\n"
+       "       \n"
+       "       \n"
+       "inline float4 b3FastNormalize4(float4 v)\n"
+       "{\n"
+       "       v = (float4)(v.xyz,0.f);\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "       \n"
+       "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+       "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+       "{\n"
+       "       b3Quat ans;\n"
+       "       ans = b3Cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+       "{\n"
+       "       b3Quat q;\n"
+       "       q=in;\n"
+       "       //return b3FastNormalize4(in);\n"
+       "       float len = native_sqrt(dot(q, q));\n"
+       "       if(len > 0.f)\n"
+       "       {\n"
+       "               q *= 1.f / len;\n"
+       "       }\n"
+       "       else\n"
+       "       {\n"
+       "               q.x = q.y = q.z = 0.f;\n"
+       "               q.w = 1.f;\n"
+       "       }\n"
+       "       return q;\n"
+       "}\n"
+       "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       b3Quat qInv = b3QuatInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+       "}\n"
+       "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg  orientation)\n"
+       "{\n"
+       "       return b3QuatRotate( orientation, point ) + (translation);\n"
+       "}\n"
+       "       \n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifndef B3_MAT3x3_H\n"
+       "#define B3_MAT3x3_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "typedef struct\n"
+       "{\n"
+       "       b3Float4 m_row[3];\n"
+       "}b3Mat3x3;\n"
+       "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+       "#define b3GetRow(m,row) (m.m_row[row])\n"
+       "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+       "{\n"
+       "       b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+       "       out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+       "       out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+       "       out.m_row[0].w = 0.f;\n"
+       "       out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+       "       out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+       "       out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+       "       out.m_row[1].w = 0.f;\n"
+       "       out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+       "       out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+       "       out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+       "       out.m_row[2].w = 0.f;\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = fabs(matIn.m_row[0]);\n"
+       "       out.m_row[1] = fabs(matIn.m_row[1]);\n"
+       "       out.m_row[2] = fabs(matIn.m_row[2]);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero();\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity();\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(0.f);\n"
+       "       m.m_row[1] = (b3Float4)(0.f);\n"
+       "       m.m_row[2] = (b3Float4)(0.f);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+       "       m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+       "       m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+       "       out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+       "       out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Mat3x3 transB;\n"
+       "       transB = mtTranspose( b );\n"
+       "       b3Mat3x3 ans;\n"
+       "       //      why this doesn't run when 0ing in the for{}\n"
+       "       a.m_row[0].w = 0.f;\n"
+       "       a.m_row[1].w = 0.f;\n"
+       "       a.m_row[2].w = 0.f;\n"
+       "       for(int i=0; i<3; i++)\n"
+       "       {\n"
+       "//     a.m_row[i].w = 0.f;\n"
+       "               ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+       "               ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+       "               ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+       "               ans.m_row[i].w = 0.f;\n"
+       "       }\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+       "{\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a.m_row[0], b );\n"
+       "       ans.y = b3Dot3F4( a.m_row[1], b );\n"
+       "       ans.z = b3Dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a, colx );\n"
+       "       ans.y = b3Dot3F4( a, coly );\n"
+       "       ans.z = b3Dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "#endif\n"
+       "#endif //B3_MAT3x3_H\n"
+       "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+       "struct b3RigidBodyData\n"
+       "{\n"
+       "       b3Float4                                m_pos;\n"
+       "       b3Quat                                  m_quat;\n"
+       "       b3Float4                                m_linVel;\n"
+       "       b3Float4                                m_angVel;\n"
+       "       int                                     m_collidableIdx;\n"
+       "       float                           m_invMass;\n"
+       "       float                           m_restituitionCoeff;\n"
+       "       float                           m_frictionCoeff;\n"
+       "};\n"
+       "typedef struct b3InertiaData b3InertiaData_t;\n"
+       "struct b3InertiaData\n"
+       "{\n"
+       "       b3Mat3x3 m_invInertiaWorld;\n"
+       "       b3Mat3x3 m_initInvInertia;\n"
+       "};\n"
+       "#endif //B3_RIGIDBODY_DATA_H\n"
+       "       \n"
+       "#ifndef B3_RIGIDBODY_DATA_H\n"
+       "#endif //B3_RIGIDBODY_DATA_H\n"
+       "       \n"
+       "inline void integrateSingleTransform( __global b3RigidBodyData_t* bodies,int nodeID, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)\n"
+       "{\n"
+       "       \n"
+       "       if (bodies[nodeID].m_invMass != 0.f)\n"
+       "       {\n"
+       "               float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
+       "               //angular velocity\n"
+       "               {\n"
+       "                       b3Float4 axis;\n"
+       "                       //add some hardcoded angular damping\n"
+       "                       bodies[nodeID].m_angVel.x *= angularDamping;\n"
+       "                       bodies[nodeID].m_angVel.y *= angularDamping;\n"
+       "                       bodies[nodeID].m_angVel.z *= angularDamping;\n"
+       "                       \n"
+       "                       b3Float4 angvel = bodies[nodeID].m_angVel;\n"
+       "                       float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));\n"
+       "                       \n"
+       "                       //limit the angular motion\n"
+       "                       if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)\n"
+       "                       {\n"
+       "                               fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
+       "                       }\n"
+       "                       if(fAngle < 0.001f)\n"
+       "                       {\n"
+       "                               // use Taylor's expansions of sync function\n"
+       "                               axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
+       "                       }\n"
+       "                       else\n"
+       "                       {\n"
+       "                               // sync(fAngle) = sin(c*fAngle)/t\n"
+       "                               axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);\n"
+       "                       }\n"
+       "                       \n"
+       "                       b3Quat dorn;\n"
+       "                       dorn.x = axis.x;\n"
+       "                       dorn.y = axis.y;\n"
+       "                       dorn.z = axis.z;\n"
+       "                       dorn.w = b3Cos(fAngle * timeStep * 0.5f);\n"
+       "                       b3Quat orn0 = bodies[nodeID].m_quat;\n"
+       "                       b3Quat predictedOrn = b3QuatMul(dorn, orn0);\n"
+       "                       predictedOrn = b3QuatNormalized(predictedOrn);\n"
+       "                       bodies[nodeID].m_quat=predictedOrn;\n"
+       "               }\n"
+       "               //linear velocity               \n"
+       "               bodies[nodeID].m_pos +=  bodies[nodeID].m_linVel * timeStep;\n"
+       "               \n"
+       "               //apply gravity\n"
+       "               bodies[nodeID].m_linVel += gravityAcceleration * timeStep;\n"
+       "               \n"
+       "       }\n"
+       "       \n"
+       "}\n"
+       "inline void b3IntegrateTransform( __global b3RigidBodyData_t* body, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)\n"
+       "{\n"
+       "       float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
+       "       \n"
+       "       if( (body->m_invMass != 0.f))\n"
+       "       {\n"
+       "               //angular velocity\n"
+       "               {\n"
+       "                       b3Float4 axis;\n"
+       "                       //add some hardcoded angular damping\n"
+       "                       body->m_angVel.x *= angularDamping;\n"
+       "                       body->m_angVel.y *= angularDamping;\n"
+       "                       body->m_angVel.z *= angularDamping;\n"
+       "                       \n"
+       "                       b3Float4 angvel = body->m_angVel;\n"
+       "                       float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));\n"
+       "                       //limit the angular motion\n"
+       "                       if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)\n"
+       "                       {\n"
+       "                               fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
+       "                       }\n"
+       "                       if(fAngle < 0.001f)\n"
+       "                       {\n"
+       "                               // use Taylor's expansions of sync function\n"
+       "                               axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
+       "                       }\n"
+       "                       else\n"
+       "                       {\n"
+       "                               // sync(fAngle) = sin(c*fAngle)/t\n"
+       "                               axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);\n"
+       "                       }\n"
+       "                       b3Quat dorn;\n"
+       "                       dorn.x = axis.x;\n"
+       "                       dorn.y = axis.y;\n"
+       "                       dorn.z = axis.z;\n"
+       "                       dorn.w = b3Cos(fAngle * timeStep * 0.5f);\n"
+       "                       b3Quat orn0 = body->m_quat;\n"
+       "                       b3Quat predictedOrn = b3QuatMul(dorn, orn0);\n"
+       "                       predictedOrn = b3QuatNormalized(predictedOrn);\n"
+       "                       body->m_quat=predictedOrn;\n"
+       "               }\n"
+       "               //apply gravity\n"
+       "               body->m_linVel += gravityAcceleration * timeStep;\n"
+       "               //linear velocity               \n"
+       "               body->m_pos +=  body->m_linVel * timeStep;\n"
+       "               \n"
+       "       }\n"
+       "       \n"
+       "}\n"
+       "__kernel void \n"
+       "  integrateTransformsKernel( __global b3RigidBodyData_t* bodies,const int numNodes, float timeStep, float angularDamping, float4 gravityAcceleration)\n"
+       "{\n"
+       "       int nodeID = get_global_id(0);\n"
+       "       \n"
+       "       if( nodeID < numNodes)\n"
+       "       {\n"
+       "               integrateSingleTransform(bodies,nodeID, timeStep, angularDamping,gravityAcceleration);\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl
new file mode 100644 (file)
index 0000000..7f5dabe
--- /dev/null
@@ -0,0 +1,877 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#define B3_CONSTRAINT_FLAG_ENABLED 1
+
+#define B3_GPU_POINT2POINT_CONSTRAINT_TYPE 3
+#define B3_GPU_FIXED_CONSTRAINT_TYPE 4
+
+#define MOTIONCLAMP 100000 //unused, for debugging/safety in case constraint solver fails
+#define B3_INFINITY 1e30f
+
+#define mymake_float4 (float4)
+
+
+__inline float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = mymake_float4(a.xyz,0.f);
+       float4 b1 = mymake_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+
+typedef float4 Quaternion;
+
+
+typedef struct
+{
+       float4 m_row[3];
+}Matrix3x3;
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b);
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b);
+
+
+
+
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b)
+{
+       float4 ans;
+       ans.x = dot3F4( a.m_row[0], b );
+       ans.y = dot3F4( a.m_row[1], b );
+       ans.z = dot3F4( a.m_row[2], b );
+       ans.w = 0.f;
+       return ans;
+}
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b)
+{
+       float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+       float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+       float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+       float4 ans;
+       ans.x = dot3F4( a, colx );
+       ans.y = dot3F4( a, coly );
+       ans.z = dot3F4( a, colz );
+       return ans;
+}
+
+
+
+typedef struct
+{
+       Matrix3x3 m_invInertiaWorld;
+       Matrix3x3 m_initInvInertia;
+} BodyInertia;
+
+
+typedef struct
+{
+       Matrix3x3 m_basis;//orientation
+       float4  m_origin;//transform
+}b3Transform;
+
+typedef struct
+{
+//     b3Transform             m_worldTransformUnused;
+       float4          m_deltaLinearVelocity;
+       float4          m_deltaAngularVelocity;
+       float4          m_angularFactor;
+       float4          m_linearFactor;
+       float4          m_invMass;
+       float4          m_pushVelocity;
+       float4          m_turnVelocity;
+       float4          m_linearVelocity;
+       float4          m_angularVelocity;
+
+       union 
+       {
+               void*   m_originalBody;
+               int             m_originalBodyIndex;
+       };
+       int padding[3];
+
+} b3GpuSolverBody;
+
+typedef struct
+{
+       float4 m_pos;
+       Quaternion m_quat;
+       float4 m_linVel;
+       float4 m_angVel;
+
+       unsigned int m_shapeIdx;
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+} b3RigidBodyCL;
+
+typedef struct
+{
+
+       float4          m_relpos1CrossNormal;
+       float4          m_contactNormal;
+
+       float4          m_relpos2CrossNormal;
+       //float4                m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
+
+       float4          m_angularComponentA;
+       float4          m_angularComponentB;
+       
+       float   m_appliedPushImpulse;
+       float   m_appliedImpulse;
+       int     m_padding1;
+       int     m_padding2;
+       float   m_friction;
+       float   m_jacDiagABInv;
+       float           m_rhs;
+       float           m_cfm;
+       
+    float              m_lowerLimit;
+       float           m_upperLimit;
+       float           m_rhsPenetration;
+       int                     m_originalConstraint;
+
+
+       int     m_overrideNumSolverIterations;
+    int                        m_frictionIndex;
+       int m_solverBodyIdA;
+       int m_solverBodyIdB;
+
+} b3SolverConstraint;
+
+typedef struct 
+{
+       int m_bodyAPtrAndSignBit;
+       int m_bodyBPtrAndSignBit;
+       int m_originalConstraintIndex;
+       int m_batchId;
+} b3BatchConstraint;
+
+
+
+
+
+
+typedef struct 
+{
+       int                             m_constraintType;
+       int                             m_rbA;
+       int                             m_rbB;
+       float                   m_breakingImpulseThreshold;
+
+       float4 m_pivotInA;
+       float4 m_pivotInB;
+       Quaternion m_relTargetAB;
+
+       int     m_flags;
+       int m_padding[3];
+} b3GpuGenericConstraint;
+
+
+/*b3Transform  getWorldTransform(b3RigidBodyCL* rb)
+{
+       b3Transform newTrans;
+       newTrans.setOrigin(rb->m_pos);
+       newTrans.setRotation(rb->m_quat);
+       return newTrans;
+}*/
+
+
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+       return cross(a,b);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+       v = mymake_float4(v.xyz,0.f);
+       return fast_normalize(v);
+}
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+       Quaternion ans;
+       ans = cross3( a, b );
+       ans += a.w*b+b.w*a;
+//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+       ans.w = a.w*b.w - dot3F4(a, b);
+       return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+       return fastNormalize4(in);
+//     in /= length( in );
+//     return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+       Quaternion qInv = qtInvert( q );
+       float4 vcpy = vec;
+       vcpy.w = 0.f;
+       float4 out = qtMul(qtMul(q,vcpy),qInv);
+       return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+       return (Quaternion)(-q.xyz, q.w);
+}
+
+
+__inline void internalApplyImpulse(__global b3GpuSolverBody* body,  float4 linearComponent, float4 angularComponent,float impulseMagnitude)
+{
+       body->m_deltaLinearVelocity += linearComponent*impulseMagnitude*body->m_linearFactor;
+       body->m_deltaAngularVelocity += angularComponent*(impulseMagnitude*body->m_angularFactor);
+}
+
+
+void resolveSingleConstraintRowGeneric(__global b3GpuSolverBody* body1, __global b3GpuSolverBody* body2, __global b3SolverConstraint* c)
+{
+       float deltaImpulse = c->m_rhs-c->m_appliedImpulse*c->m_cfm;
+       float deltaVel1Dotn     =       dot3F4(c->m_contactNormal,body1->m_deltaLinearVelocity)         + dot3F4(c->m_relpos1CrossNormal,body1->m_deltaAngularVelocity);
+       float deltaVel2Dotn     =       -dot3F4(c->m_contactNormal,body2->m_deltaLinearVelocity) + dot3F4(c->m_relpos2CrossNormal,body2->m_deltaAngularVelocity);
+
+       deltaImpulse    -=      deltaVel1Dotn*c->m_jacDiagABInv;
+       deltaImpulse    -=      deltaVel2Dotn*c->m_jacDiagABInv;
+
+       float sum = c->m_appliedImpulse + deltaImpulse;
+       if (sum < c->m_lowerLimit)
+       {
+               deltaImpulse = c->m_lowerLimit-c->m_appliedImpulse;
+               c->m_appliedImpulse = c->m_lowerLimit;
+       }
+       else if (sum > c->m_upperLimit) 
+       {
+               deltaImpulse = c->m_upperLimit-c->m_appliedImpulse;
+               c->m_appliedImpulse = c->m_upperLimit;
+       }
+       else
+       {
+               c->m_appliedImpulse = sum;
+       }
+
+       internalApplyImpulse(body1,c->m_contactNormal*body1->m_invMass,c->m_angularComponentA,deltaImpulse);
+       internalApplyImpulse(body2,-c->m_contactNormal*body2->m_invMass,c->m_angularComponentB,deltaImpulse);
+
+}
+
+__kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,
+                                         __global b3BatchConstraint* batchConstraints,
+                                               __global b3SolverConstraint* rows,
+                                               __global unsigned int* numConstraintRowsInfo1, 
+                                               __global unsigned int* rowOffsets,
+                                               __global b3GpuGenericConstraint* constraints,
+                                               int batchOffset,
+                                               int numConstraintsInBatch
+                      )
+{
+       int b = get_global_id(0);
+       if (b>=numConstraintsInBatch)
+               return;
+
+       __global b3BatchConstraint* c = &batchConstraints[b+batchOffset];
+       int originalConstraintIndex = c->m_originalConstraintIndex;
+       if (constraints[originalConstraintIndex].m_flags&B3_CONSTRAINT_FLAG_ENABLED)
+       {
+               int numConstraintRows = numConstraintRowsInfo1[originalConstraintIndex];
+               int rowOffset = rowOffsets[originalConstraintIndex];
+               for (int jj=0;jj<numConstraintRows;jj++)
+               {
+                       __global b3SolverConstraint* constraint = &rows[rowOffset+jj];
+                       resolveSingleConstraintRowGeneric(&solverBodies[constraint->m_solverBodyIdA],&solverBodies[constraint->m_solverBodyIdB],constraint);
+               }
+       }
+};
+
+__kernel void initSolverBodies(__global b3GpuSolverBody* solverBodies,__global b3RigidBodyCL* bodiesCL, int numBodies)
+{
+       int i = get_global_id(0);
+       if (i>=numBodies)
+               return;
+
+       __global b3GpuSolverBody* solverBody = &solverBodies[i];
+       __global b3RigidBodyCL* bodyCL = &bodiesCL[i];
+
+       solverBody->m_deltaLinearVelocity = (float4)(0.f,0.f,0.f,0.f);
+       solverBody->m_deltaAngularVelocity  = (float4)(0.f,0.f,0.f,0.f);
+       solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);
+       solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);
+       solverBody->m_invMass = (float4)(bodyCL->m_invMass,bodyCL->m_invMass,bodyCL->m_invMass,0.f);
+       solverBody->m_originalBodyIndex = i;
+       solverBody->m_angularFactor = (float4)(1,1,1,0);
+       solverBody->m_linearFactor = (float4) (1,1,1,0);
+       solverBody->m_linearVelocity = bodyCL->m_linVel;
+       solverBody->m_angularVelocity = bodyCL->m_angVel;
+}
+
+__kernel void breakViolatedConstraintsKernel(__global b3GpuGenericConstraint* constraints, __global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, __global b3SolverConstraint* rows, int numConstraints)
+{
+       int cid = get_global_id(0);
+       if (cid>=numConstraints)
+               return;
+       int numRows = numConstraintRows[cid];
+       if (numRows)
+       {
+               for (int i=0;i<numRows;i++)
+               {
+                       int rowIndex = rowOffsets[cid]+i;
+                       float breakingThreshold = constraints[cid].m_breakingImpulseThreshold;
+                       if (fabs(rows[rowIndex].m_appliedImpulse) >= breakingThreshold)
+                       {
+                               constraints[cid].m_flags =0;//&= ~B3_CONSTRAINT_FLAG_ENABLED;
+                       }
+               }
+       }
+}
+
+
+
+__kernel void getInfo1Kernel(__global unsigned int* infos, __global b3GpuGenericConstraint* constraints, int numConstraints)
+{
+       int i = get_global_id(0);
+       if (i>=numConstraints)
+               return;
+
+       __global b3GpuGenericConstraint* constraint = &constraints[i];
+
+       switch (constraint->m_constraintType)
+       {
+               case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
+               {
+                       infos[i] = 3;
+                       break;
+               }
+               case B3_GPU_FIXED_CONSTRAINT_TYPE:
+               {
+                       infos[i] = 6;
+                       break;
+               }
+               default:
+               {
+               }
+       }
+}
+
+__kernel void initBatchConstraintsKernel(__global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, 
+                                                                               __global b3BatchConstraint* batchConstraints, 
+                                                                               __global b3GpuGenericConstraint* constraints,
+                                                                               __global b3RigidBodyCL* bodies,
+                                                                               int numConstraints)
+{
+       int i = get_global_id(0);
+       if (i>=numConstraints)
+               return;
+
+       int rbA = constraints[i].m_rbA;
+       int rbB = constraints[i].m_rbB;
+
+       batchConstraints[i].m_bodyAPtrAndSignBit = bodies[rbA].m_invMass != 0.f ? rbA : -rbA;
+       batchConstraints[i].m_bodyBPtrAndSignBit = bodies[rbB].m_invMass != 0.f ? rbB : -rbB;
+       batchConstraints[i].m_batchId = -1;
+       batchConstraints[i].m_originalConstraintIndex = i;
+
+}
+
+
+
+
+typedef struct
+{
+       // integrator parameters: frames per second (1/stepsize), default error
+       // reduction parameter (0..1).
+       float fps,erp;
+
+       // for the first and second body, pointers to two (linear and angular)
+       // n*3 jacobian sub matrices, stored by rows. these matrices will have
+       // been initialized to 0 on entry. if the second body is zero then the
+       // J2xx pointers may be 0.
+       union 
+       {
+               __global float4* m_J1linearAxisFloat4;
+               __global float* m_J1linearAxis;
+       };
+       union
+       {
+               __global float4* m_J1angularAxisFloat4;
+               __global float* m_J1angularAxis;
+
+       };
+       union
+       {
+       __global float4* m_J2linearAxisFloat4;
+       __global float* m_J2linearAxis;
+       };
+       union
+       {
+               __global float4* m_J2angularAxisFloat4;
+               __global float* m_J2angularAxis;
+       };
+       // elements to jump from one row to the next in J's
+       int rowskip;
+
+       // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+       // "constraint force mixing" vector. c is set to zero on entry, cfm is
+       // set to a constant value (typically very small or zero) value on entry.
+       __global float* m_constraintError;
+       __global float* cfm;
+
+       // lo and hi limits for variables (set to -/+ infinity on entry).
+       __global float* m_lowerLimit;
+       __global float* m_upperLimit;
+
+       // findex vector for variables. see the LCP solver interface for a
+       // description of what this does. this is set to -1 on entry.
+       // note that the returned indexes are relative to the first index of
+       // the constraint.
+       __global int *findex;
+       // number of solver iterations
+       int m_numIterations;
+
+       //damping of the velocity
+       float   m_damping;
+} b3GpuConstraintInfo2;
+
+
+void   getSkewSymmetricMatrix(float4 vecIn, __global float4* v0,__global float4* v1,__global float4* v2)
+{
+       *v0 = (float4)(0.               ,-vecIn.z               ,vecIn.y,0.f);
+       *v1 = (float4)(vecIn.z  ,0.                     ,-vecIn.x,0.f);
+       *v2 = (float4)(-vecIn.y ,vecIn.x        ,0.f,0.f);
+}
+
+
+void getInfo2Point2Point(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies)
+{
+       float4 posA = bodies[constraint->m_rbA].m_pos;
+       Quaternion rotA = bodies[constraint->m_rbA].m_quat;
+
+       float4 posB = bodies[constraint->m_rbB].m_pos;
+       Quaternion rotB = bodies[constraint->m_rbB].m_quat;
+
+
+
+               // anchor points in global coordinates with respect to body PORs.
+   
+    // set jacobian
+    info->m_J1linearAxis[0] = 1;
+       info->m_J1linearAxis[info->rowskip+1] = 1;
+       info->m_J1linearAxis[2*info->rowskip+2] = 1;
+
+       float4 a1 = qtRotate(rotA,constraint->m_pivotInA);
+
+       {
+               __global float4* angular0 = (__global float4*)(info->m_J1angularAxis);
+               __global float4* angular1 = (__global float4*)(info->m_J1angularAxis+info->rowskip);
+               __global float4* angular2 = (__global float4*)(info->m_J1angularAxis+2*info->rowskip);
+               float4 a1neg = -a1;
+               getSkewSymmetricMatrix(a1neg,angular0,angular1,angular2);
+       }
+       if (info->m_J2linearAxis)
+       {
+               info->m_J2linearAxis[0] = -1;
+               info->m_J2linearAxis[info->rowskip+1] = -1;
+               info->m_J2linearAxis[2*info->rowskip+2] = -1;
+       }
+       
+       float4 a2 = qtRotate(rotB,constraint->m_pivotInB);
+   
+       {
+       //      float4 a2n = -a2;
+               __global float4* angular0 = (__global float4*)(info->m_J2angularAxis);
+               __global float4* angular1 = (__global float4*)(info->m_J2angularAxis+info->rowskip);
+               __global float4* angular2 = (__global float4*)(info->m_J2angularAxis+2*info->rowskip);
+               getSkewSymmetricMatrix(a2,angular0,angular1,angular2);
+       }
+    
+    // set right hand side
+//     float currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
+       float currERP = info->erp;
+
+       float k = info->fps * currERP;
+    int j;
+       float4 result = a2 + posB - a1 - posA;
+       float* resultPtr = &result;
+
+       for (j=0; j<3; j++)
+    {
+        info->m_constraintError[j*info->rowskip] = k * (resultPtr[j]);
+    }
+}
+
+Quaternion nearest( Quaternion first, Quaternion qd)
+{
+       Quaternion diff,sum;
+       diff = first- qd;
+       sum = first + qd;
+       
+       if( dot(diff,diff) < dot(sum,sum) )
+               return qd;
+       return (-qd);
+}
+
+float b3Acos(float x) 
+{ 
+       if (x<-1)       
+               x=-1; 
+       if (x>1)        
+               x=1;
+       return acos(x); 
+}
+
+float getAngle(Quaternion orn)
+{
+       if (orn.w>=1.f)
+               orn.w=1.f;
+       float s = 2.f * b3Acos(orn.w);
+       return s;
+}
+
+void calculateDiffAxisAngleQuaternion( Quaternion orn0,Quaternion orn1a,float4* axis,float* angle)
+{
+       Quaternion orn1 = nearest(orn0,orn1a);
+       
+       Quaternion dorn = qtMul(orn1,qtInvert(orn0));
+       *angle = getAngle(dorn);
+       *axis = (float4)(dorn.x,dorn.y,dorn.z,0.f);
+       
+       //check for axis length
+       float len = dot3F4(*axis,*axis);
+       if (len < FLT_EPSILON*FLT_EPSILON)
+               *axis = (float4)(1,0,0,0);
+       else
+               *axis /= sqrt(len);
+}
+
+
+
+void getInfo2FixedOrientation(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies, int start_row)
+{
+       Quaternion worldOrnA = bodies[constraint->m_rbA].m_quat;
+       Quaternion worldOrnB = bodies[constraint->m_rbB].m_quat;
+
+       int s = info->rowskip;
+       int start_index = start_row * s;
+
+       // 3 rows to make body rotations equal
+       info->m_J1angularAxis[start_index] = 1;
+       info->m_J1angularAxis[start_index + s + 1] = 1;
+       info->m_J1angularAxis[start_index + s*2+2] = 1;
+       if ( info->m_J2angularAxis)
+       {
+               info->m_J2angularAxis[start_index] = -1;
+               info->m_J2angularAxis[start_index + s+1] = -1;
+               info->m_J2angularAxis[start_index + s*2+2] = -1;
+       }
+       
+       float currERP = info->erp;
+       float k = info->fps * currERP;
+       float4 diff;
+       float angle;
+       float4 qrelCur = qtMul(worldOrnA,qtInvert(worldOrnB));
+       
+       calculateDiffAxisAngleQuaternion(constraint->m_relTargetAB,qrelCur,&diff,&angle);
+       diff*=-angle;
+               
+       float* resultPtr = &diff;
+       
+       for (int j=0; j<3; j++)
+    {
+        info->m_constraintError[(3+j)*info->rowskip] = k * resultPtr[j];
+    }
+       
+
+}
+
+
+__kernel void writeBackVelocitiesKernel(__global b3RigidBodyCL* bodies,__global b3GpuSolverBody* solverBodies,int numBodies)
+{
+       int i = get_global_id(0);
+       if (i>=numBodies)
+               return;
+
+       if (bodies[i].m_invMass)
+       {
+//             if (length(solverBodies[i].m_deltaLinearVelocity)<MOTIONCLAMP)
+               {
+                       bodies[i].m_linVel += solverBodies[i].m_deltaLinearVelocity;
+               }
+//             if (length(solverBodies[i].m_deltaAngularVelocity)<MOTIONCLAMP)
+               {
+                       bodies[i].m_angVel += solverBodies[i].m_deltaAngularVelocity;
+               } 
+       }
+}
+
+
+__kernel void getInfo2Kernel(__global b3SolverConstraint* solverConstraintRows, 
+                                                       __global unsigned int* infos, 
+                                                       __global unsigned int* constraintRowOffsets, 
+                                                       __global b3GpuGenericConstraint* constraints, 
+                                                       __global b3BatchConstraint* batchConstraints, 
+                                                       __global b3RigidBodyCL* bodies,
+                                                       __global BodyInertia* inertias,
+                                                       __global b3GpuSolverBody* solverBodies,
+                                                       float timeStep,
+                                                       float globalErp,
+                                                       float globalCfm,
+                                                       float globalDamping,
+                                                       int globalNumIterations,
+                                                       int numConstraints)
+{
+
+       int i = get_global_id(0);
+       if (i>=numConstraints)
+               return;
+               
+       //for now, always initialize the batch info
+       int info1 = infos[i];
+                       
+       __global b3SolverConstraint* currentConstraintRow = &solverConstraintRows[constraintRowOffsets[i]];
+       __global b3GpuGenericConstraint* constraint = &constraints[i];
+
+       __global b3RigidBodyCL* rbA = &bodies[ constraint->m_rbA];
+       __global b3RigidBodyCL* rbB = &bodies[ constraint->m_rbB];
+
+       int solverBodyIdA = constraint->m_rbA;
+       int solverBodyIdB = constraint->m_rbB;
+
+       __global b3GpuSolverBody* bodyAPtr = &solverBodies[solverBodyIdA];
+       __global b3GpuSolverBody* bodyBPtr = &solverBodies[solverBodyIdB];
+
+
+       if (rbA->m_invMass)
+       {
+               batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;
+       } else
+       {
+//                     if (!solverBodyIdA)
+//                             m_staticIdx = 0;
+               batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;
+       }
+
+       if (rbB->m_invMass)
+       {
+               batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;
+       } else
+       {
+//                     if (!solverBodyIdB)
+//                             m_staticIdx = 0;
+               batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;
+       }
+
+       if (info1)
+       {
+               int overrideNumSolverIterations = 0;//constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
+//             if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
+       //              m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
+
+
+               int j;
+               for ( j=0;j<info1;j++)
+               {
+//                     memset(&currentConstraintRow[j],0,sizeof(b3SolverConstraint));
+                       currentConstraintRow[j].m_angularComponentA = (float4)(0,0,0,0);
+                       currentConstraintRow[j].m_angularComponentB = (float4)(0,0,0,0);
+                       currentConstraintRow[j].m_appliedImpulse = 0.f;
+                       currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+                       currentConstraintRow[j].m_cfm = 0.f;
+                       currentConstraintRow[j].m_contactNormal = (float4)(0,0,0,0);
+                       currentConstraintRow[j].m_friction = 0.f;
+                       currentConstraintRow[j].m_frictionIndex = 0;
+                       currentConstraintRow[j].m_jacDiagABInv = 0.f;
+                       currentConstraintRow[j].m_lowerLimit = 0.f;
+                       currentConstraintRow[j].m_upperLimit = 0.f;
+
+                       currentConstraintRow[j].m_originalConstraint = i;
+                       currentConstraintRow[j].m_overrideNumSolverIterations = 0;
+                       currentConstraintRow[j].m_relpos1CrossNormal = (float4)(0,0,0,0);
+                       currentConstraintRow[j].m_relpos2CrossNormal = (float4)(0,0,0,0);
+                       currentConstraintRow[j].m_rhs = 0.f;
+                       currentConstraintRow[j].m_rhsPenetration = 0.f;
+                       currentConstraintRow[j].m_solverBodyIdA = 0;
+                       currentConstraintRow[j].m_solverBodyIdB = 0;
+                                                       
+                       currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
+                       currentConstraintRow[j].m_upperLimit = B3_INFINITY;
+                       currentConstraintRow[j].m_appliedImpulse = 0.f;
+                       currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+                       currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
+                       currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
+                       currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;            
+               }
+
+               bodyAPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);
+               bodyAPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);
+               bodyAPtr->m_pushVelocity = (float4)(0,0,0,0);
+               bodyAPtr->m_turnVelocity = (float4)(0,0,0,0);
+               bodyBPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);
+               bodyBPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);
+               bodyBPtr->m_pushVelocity = (float4)(0,0,0,0);
+               bodyBPtr->m_turnVelocity  = (float4)(0,0,0,0);
+
+               int rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this
+
+               
+
+
+               b3GpuConstraintInfo2 info2;
+               info2.fps = 1.f/timeStep;
+               info2.erp = globalErp;
+               info2.m_J1linearAxisFloat4 = &currentConstraintRow->m_contactNormal;
+               info2.m_J1angularAxisFloat4 = &currentConstraintRow->m_relpos1CrossNormal;
+               info2.m_J2linearAxisFloat4 = 0;
+               info2.m_J2angularAxisFloat4 = &currentConstraintRow->m_relpos2CrossNormal;
+               info2.rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this
+
+               ///the size of b3SolverConstraint needs be a multiple of float
+//             b3Assert(info2.rowskip*sizeof(float)== sizeof(b3SolverConstraint));
+               info2.m_constraintError = &currentConstraintRow->m_rhs;
+               currentConstraintRow->m_cfm = globalCfm;
+               info2.m_damping = globalDamping;
+               info2.cfm = &currentConstraintRow->m_cfm;
+               info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
+               info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
+               info2.m_numIterations = globalNumIterations;
+
+               switch (constraint->m_constraintType)
+               {
+                       case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
+                       {
+                               getInfo2Point2Point(constraint,&info2,bodies);
+                               break;
+                       }
+                       case B3_GPU_FIXED_CONSTRAINT_TYPE:
+                       {
+                               getInfo2Point2Point(constraint,&info2,bodies);
+
+                               getInfo2FixedOrientation(constraint,&info2,bodies,3);
+
+                               break;
+                       }
+
+                       default:
+                       {
+                       }
+               }
+
+               ///finalize the constraint setup
+               for ( j=0;j<info1;j++)
+               {
+                       __global b3SolverConstraint* solverConstraint = &currentConstraintRow[j];
+
+                       if (solverConstraint->m_upperLimit>=constraint->m_breakingImpulseThreshold)
+                       {
+                               solverConstraint->m_upperLimit = constraint->m_breakingImpulseThreshold;
+                       }
+
+                       if (solverConstraint->m_lowerLimit<=-constraint->m_breakingImpulseThreshold)
+                       {
+                               solverConstraint->m_lowerLimit = -constraint->m_breakingImpulseThreshold;
+                       }
+
+//                                             solverConstraint->m_originalContactPoint = constraint;
+                                                       
+                       Matrix3x3 invInertiaWorldA= inertias[constraint->m_rbA].m_invInertiaWorld;
+                       {
+
+                               //float4 angularFactorA(1,1,1);
+                               float4 ftorqueAxis1 = solverConstraint->m_relpos1CrossNormal;
+                               solverConstraint->m_angularComponentA = mtMul1(invInertiaWorldA,ftorqueAxis1);//*angularFactorA;
+                       }
+                                               
+                       Matrix3x3 invInertiaWorldB= inertias[constraint->m_rbB].m_invInertiaWorld;
+                       {
+
+                               float4 ftorqueAxis2 = solverConstraint->m_relpos2CrossNormal;
+                               solverConstraint->m_angularComponentB = mtMul1(invInertiaWorldB,ftorqueAxis2);//*constraint->m_rbB.getAngularFactor();
+                       }
+
+                       {
+                               //it is ok to use solverConstraint->m_contactNormal instead of -solverConstraint->m_contactNormal
+                               //because it gets multiplied iMJlB
+                               float4 iMJlA = solverConstraint->m_contactNormal*rbA->m_invMass;
+                               float4 iMJaA = mtMul3(solverConstraint->m_relpos1CrossNormal,invInertiaWorldA);
+                               float4 iMJlB = solverConstraint->m_contactNormal*rbB->m_invMass;//sign of normal?
+                               float4 iMJaB = mtMul3(solverConstraint->m_relpos2CrossNormal,invInertiaWorldB);
+
+                               float sum = dot3F4(iMJlA,solverConstraint->m_contactNormal);
+                               sum += dot3F4(iMJaA,solverConstraint->m_relpos1CrossNormal);
+                               sum += dot3F4(iMJlB,solverConstraint->m_contactNormal);
+                               sum += dot3F4(iMJaB,solverConstraint->m_relpos2CrossNormal);
+                               float fsum = fabs(sum);
+                               if (fsum>FLT_EPSILON)
+                               {
+                                       solverConstraint->m_jacDiagABInv = 1.f/sum;
+                               } else
+                               {
+                                       solverConstraint->m_jacDiagABInv = 0.f;
+                               }
+                       }
+
+
+                       ///fix rhs
+                       ///todo: add force/torque accelerators
+                       {
+                               float rel_vel;
+                               float vel1Dotn = dot3F4(solverConstraint->m_contactNormal,rbA->m_linVel) + dot3F4(solverConstraint->m_relpos1CrossNormal,rbA->m_angVel);
+                               float vel2Dotn = -dot3F4(solverConstraint->m_contactNormal,rbB->m_linVel) + dot3F4(solverConstraint->m_relpos2CrossNormal,rbB->m_angVel);
+
+                               rel_vel = vel1Dotn+vel2Dotn;
+
+                               float restitution = 0.f;
+                               float positionalError = solverConstraint->m_rhs;//already filled in by getConstraintInfo2
+                               float   velocityError = restitution - rel_vel * info2.m_damping;
+                               float   penetrationImpulse = positionalError*solverConstraint->m_jacDiagABInv;
+                               float   velocityImpulse = velocityError *solverConstraint->m_jacDiagABInv;
+                               solverConstraint->m_rhs = penetrationImpulse+velocityImpulse;
+                               solverConstraint->m_appliedImpulse = 0.f;
+
+                       }
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/jointSolver.h
new file mode 100644 (file)
index 0000000..c94b558
--- /dev/null
@@ -0,0 +1,720 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solveConstraintRowsCL =
+       "/*\n"
+       "Copyright (c) 2013 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Erwin Coumans\n"
+       "#define B3_CONSTRAINT_FLAG_ENABLED 1\n"
+       "#define B3_GPU_POINT2POINT_CONSTRAINT_TYPE 3\n"
+       "#define B3_GPU_FIXED_CONSTRAINT_TYPE 4\n"
+       "#define MOTIONCLAMP 100000 //unused, for debugging/safety in case constraint solver fails\n"
+       "#define B3_INFINITY 1e30f\n"
+       "#define mymake_float4 (float4)\n"
+       "__inline float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = mymake_float4(a.xyz,0.f);\n"
+       "       float4 b1 = mymake_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "typedef float4 Quaternion;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_row[3];\n"
+       "}Matrix3x3;\n"
+       "__inline\n"
+       "float4 mtMul1(Matrix3x3 a, float4 b);\n"
+       "__inline\n"
+       "float4 mtMul3(float4 a, Matrix3x3 b);\n"
+       "__inline\n"
+       "float4 mtMul1(Matrix3x3 a, float4 b)\n"
+       "{\n"
+       "       float4 ans;\n"
+       "       ans.x = dot3F4( a.m_row[0], b );\n"
+       "       ans.y = dot3F4( a.m_row[1], b );\n"
+       "       ans.z = dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "float4 mtMul3(float4 a, Matrix3x3 b)\n"
+       "{\n"
+       "       float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       float4 ans;\n"
+       "       ans.x = dot3F4( a, colx );\n"
+       "       ans.y = dot3F4( a, coly );\n"
+       "       ans.z = dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "typedef struct\n"
+       "{\n"
+       "       Matrix3x3 m_invInertiaWorld;\n"
+       "       Matrix3x3 m_initInvInertia;\n"
+       "} BodyInertia;\n"
+       "typedef struct\n"
+       "{\n"
+       "       Matrix3x3 m_basis;//orientation\n"
+       "       float4  m_origin;//transform\n"
+       "}b3Transform;\n"
+       "typedef struct\n"
+       "{\n"
+       "//     b3Transform             m_worldTransformUnused;\n"
+       "       float4          m_deltaLinearVelocity;\n"
+       "       float4          m_deltaAngularVelocity;\n"
+       "       float4          m_angularFactor;\n"
+       "       float4          m_linearFactor;\n"
+       "       float4          m_invMass;\n"
+       "       float4          m_pushVelocity;\n"
+       "       float4          m_turnVelocity;\n"
+       "       float4          m_linearVelocity;\n"
+       "       float4          m_angularVelocity;\n"
+       "       union \n"
+       "       {\n"
+       "               void*   m_originalBody;\n"
+       "               int             m_originalBodyIndex;\n"
+       "       };\n"
+       "       int padding[3];\n"
+       "} b3GpuSolverBody;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_pos;\n"
+       "       Quaternion m_quat;\n"
+       "       float4 m_linVel;\n"
+       "       float4 m_angVel;\n"
+       "       unsigned int m_shapeIdx;\n"
+       "       float m_invMass;\n"
+       "       float m_restituitionCoeff;\n"
+       "       float m_frictionCoeff;\n"
+       "} b3RigidBodyCL;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4          m_relpos1CrossNormal;\n"
+       "       float4          m_contactNormal;\n"
+       "       float4          m_relpos2CrossNormal;\n"
+       "       //float4                m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal\n"
+       "       float4          m_angularComponentA;\n"
+       "       float4          m_angularComponentB;\n"
+       "       \n"
+       "       float   m_appliedPushImpulse;\n"
+       "       float   m_appliedImpulse;\n"
+       "       int     m_padding1;\n"
+       "       int     m_padding2;\n"
+       "       float   m_friction;\n"
+       "       float   m_jacDiagABInv;\n"
+       "       float           m_rhs;\n"
+       "       float           m_cfm;\n"
+       "       \n"
+       "    float              m_lowerLimit;\n"
+       "       float           m_upperLimit;\n"
+       "       float           m_rhsPenetration;\n"
+       "       int                     m_originalConstraint;\n"
+       "       int     m_overrideNumSolverIterations;\n"
+       "    int                        m_frictionIndex;\n"
+       "       int m_solverBodyIdA;\n"
+       "       int m_solverBodyIdB;\n"
+       "} b3SolverConstraint;\n"
+       "typedef struct \n"
+       "{\n"
+       "       int m_bodyAPtrAndSignBit;\n"
+       "       int m_bodyBPtrAndSignBit;\n"
+       "       int m_originalConstraintIndex;\n"
+       "       int m_batchId;\n"
+       "} b3BatchConstraint;\n"
+       "typedef struct \n"
+       "{\n"
+       "       int                             m_constraintType;\n"
+       "       int                             m_rbA;\n"
+       "       int                             m_rbB;\n"
+       "       float                   m_breakingImpulseThreshold;\n"
+       "       float4 m_pivotInA;\n"
+       "       float4 m_pivotInB;\n"
+       "       Quaternion m_relTargetAB;\n"
+       "       int     m_flags;\n"
+       "       int m_padding[3];\n"
+       "} b3GpuGenericConstraint;\n"
+       "/*b3Transform  getWorldTransform(b3RigidBodyCL* rb)\n"
+       "{\n"
+       "       b3Transform newTrans;\n"
+       "       newTrans.setOrigin(rb->m_pos);\n"
+       "       newTrans.setRotation(rb->m_quat);\n"
+       "       return newTrans;\n"
+       "}*/\n"
+       "__inline\n"
+       "float4 cross3(float4 a, float4 b)\n"
+       "{\n"
+       "       return cross(a,b);\n"
+       "}\n"
+       "__inline\n"
+       "float4 fastNormalize4(float4 v)\n"
+       "{\n"
+       "       v = mymake_float4(v.xyz,0.f);\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in);\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec);\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q);\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+       "{\n"
+       "       Quaternion ans;\n"
+       "       ans = cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in)\n"
+       "{\n"
+       "       return fastNormalize4(in);\n"
+       "//     in /= length( in );\n"
+       "//     return in;\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec)\n"
+       "{\n"
+       "       Quaternion qInv = qtInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q)\n"
+       "{\n"
+       "       return (Quaternion)(-q.xyz, q.w);\n"
+       "}\n"
+       "__inline void internalApplyImpulse(__global b3GpuSolverBody* body,  float4 linearComponent, float4 angularComponent,float impulseMagnitude)\n"
+       "{\n"
+       "       body->m_deltaLinearVelocity += linearComponent*impulseMagnitude*body->m_linearFactor;\n"
+       "       body->m_deltaAngularVelocity += angularComponent*(impulseMagnitude*body->m_angularFactor);\n"
+       "}\n"
+       "void resolveSingleConstraintRowGeneric(__global b3GpuSolverBody* body1, __global b3GpuSolverBody* body2, __global b3SolverConstraint* c)\n"
+       "{\n"
+       "       float deltaImpulse = c->m_rhs-c->m_appliedImpulse*c->m_cfm;\n"
+       "       float deltaVel1Dotn     =       dot3F4(c->m_contactNormal,body1->m_deltaLinearVelocity)         + dot3F4(c->m_relpos1CrossNormal,body1->m_deltaAngularVelocity);\n"
+       "       float deltaVel2Dotn     =       -dot3F4(c->m_contactNormal,body2->m_deltaLinearVelocity) + dot3F4(c->m_relpos2CrossNormal,body2->m_deltaAngularVelocity);\n"
+       "       deltaImpulse    -=      deltaVel1Dotn*c->m_jacDiagABInv;\n"
+       "       deltaImpulse    -=      deltaVel2Dotn*c->m_jacDiagABInv;\n"
+       "       float sum = c->m_appliedImpulse + deltaImpulse;\n"
+       "       if (sum < c->m_lowerLimit)\n"
+       "       {\n"
+       "               deltaImpulse = c->m_lowerLimit-c->m_appliedImpulse;\n"
+       "               c->m_appliedImpulse = c->m_lowerLimit;\n"
+       "       }\n"
+       "       else if (sum > c->m_upperLimit) \n"
+       "       {\n"
+       "               deltaImpulse = c->m_upperLimit-c->m_appliedImpulse;\n"
+       "               c->m_appliedImpulse = c->m_upperLimit;\n"
+       "       }\n"
+       "       else\n"
+       "       {\n"
+       "               c->m_appliedImpulse = sum;\n"
+       "       }\n"
+       "       internalApplyImpulse(body1,c->m_contactNormal*body1->m_invMass,c->m_angularComponentA,deltaImpulse);\n"
+       "       internalApplyImpulse(body2,-c->m_contactNormal*body2->m_invMass,c->m_angularComponentB,deltaImpulse);\n"
+       "}\n"
+       "__kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,\n"
+       "                                         __global b3BatchConstraint* batchConstraints,\n"
+       "                                               __global b3SolverConstraint* rows,\n"
+       "                                               __global unsigned int* numConstraintRowsInfo1, \n"
+       "                                               __global unsigned int* rowOffsets,\n"
+       "                                               __global b3GpuGenericConstraint* constraints,\n"
+       "                                               int batchOffset,\n"
+       "                                               int numConstraintsInBatch\n"
+       "                      )\n"
+       "{\n"
+       "       int b = get_global_id(0);\n"
+       "       if (b>=numConstraintsInBatch)\n"
+       "               return;\n"
+       "       __global b3BatchConstraint* c = &batchConstraints[b+batchOffset];\n"
+       "       int originalConstraintIndex = c->m_originalConstraintIndex;\n"
+       "       if (constraints[originalConstraintIndex].m_flags&B3_CONSTRAINT_FLAG_ENABLED)\n"
+       "       {\n"
+       "               int numConstraintRows = numConstraintRowsInfo1[originalConstraintIndex];\n"
+       "               int rowOffset = rowOffsets[originalConstraintIndex];\n"
+       "               for (int jj=0;jj<numConstraintRows;jj++)\n"
+       "               {\n"
+       "                       __global b3SolverConstraint* constraint = &rows[rowOffset+jj];\n"
+       "                       resolveSingleConstraintRowGeneric(&solverBodies[constraint->m_solverBodyIdA],&solverBodies[constraint->m_solverBodyIdB],constraint);\n"
+       "               }\n"
+       "       }\n"
+       "};\n"
+       "__kernel void initSolverBodies(__global b3GpuSolverBody* solverBodies,__global b3RigidBodyCL* bodiesCL, int numBodies)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numBodies)\n"
+       "               return;\n"
+       "       __global b3GpuSolverBody* solverBody = &solverBodies[i];\n"
+       "       __global b3RigidBodyCL* bodyCL = &bodiesCL[i];\n"
+       "       solverBody->m_deltaLinearVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+       "       solverBody->m_deltaAngularVelocity  = (float4)(0.f,0.f,0.f,0.f);\n"
+       "       solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+       "       solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
+       "       solverBody->m_invMass = (float4)(bodyCL->m_invMass,bodyCL->m_invMass,bodyCL->m_invMass,0.f);\n"
+       "       solverBody->m_originalBodyIndex = i;\n"
+       "       solverBody->m_angularFactor = (float4)(1,1,1,0);\n"
+       "       solverBody->m_linearFactor = (float4) (1,1,1,0);\n"
+       "       solverBody->m_linearVelocity = bodyCL->m_linVel;\n"
+       "       solverBody->m_angularVelocity = bodyCL->m_angVel;\n"
+       "}\n"
+       "__kernel void breakViolatedConstraintsKernel(__global b3GpuGenericConstraint* constraints, __global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, __global b3SolverConstraint* rows, int numConstraints)\n"
+       "{\n"
+       "       int cid = get_global_id(0);\n"
+       "       if (cid>=numConstraints)\n"
+       "               return;\n"
+       "       int numRows = numConstraintRows[cid];\n"
+       "       if (numRows)\n"
+       "       {\n"
+       "               for (int i=0;i<numRows;i++)\n"
+       "               {\n"
+       "                       int rowIndex = rowOffsets[cid]+i;\n"
+       "                       float breakingThreshold = constraints[cid].m_breakingImpulseThreshold;\n"
+       "                       if (fabs(rows[rowIndex].m_appliedImpulse) >= breakingThreshold)\n"
+       "                       {\n"
+       "                               constraints[cid].m_flags =0;//&= ~B3_CONSTRAINT_FLAG_ENABLED;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__kernel void getInfo1Kernel(__global unsigned int* infos, __global b3GpuGenericConstraint* constraints, int numConstraints)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numConstraints)\n"
+       "               return;\n"
+       "       __global b3GpuGenericConstraint* constraint = &constraints[i];\n"
+       "       switch (constraint->m_constraintType)\n"
+       "       {\n"
+       "               case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:\n"
+       "               {\n"
+       "                       infos[i] = 3;\n"
+       "                       break;\n"
+       "               }\n"
+       "               case B3_GPU_FIXED_CONSTRAINT_TYPE:\n"
+       "               {\n"
+       "                       infos[i] = 6;\n"
+       "                       break;\n"
+       "               }\n"
+       "               default:\n"
+       "               {\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__kernel void initBatchConstraintsKernel(__global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, \n"
+       "                                                                               __global b3BatchConstraint* batchConstraints, \n"
+       "                                                                               __global b3GpuGenericConstraint* constraints,\n"
+       "                                                                               __global b3RigidBodyCL* bodies,\n"
+       "                                                                               int numConstraints)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numConstraints)\n"
+       "               return;\n"
+       "       int rbA = constraints[i].m_rbA;\n"
+       "       int rbB = constraints[i].m_rbB;\n"
+       "       batchConstraints[i].m_bodyAPtrAndSignBit = bodies[rbA].m_invMass != 0.f ? rbA : -rbA;\n"
+       "       batchConstraints[i].m_bodyBPtrAndSignBit = bodies[rbB].m_invMass != 0.f ? rbB : -rbB;\n"
+       "       batchConstraints[i].m_batchId = -1;\n"
+       "       batchConstraints[i].m_originalConstraintIndex = i;\n"
+       "}\n"
+       "typedef struct\n"
+       "{\n"
+       "       // integrator parameters: frames per second (1/stepsize), default error\n"
+       "       // reduction parameter (0..1).\n"
+       "       float fps,erp;\n"
+       "       // for the first and second body, pointers to two (linear and angular)\n"
+       "       // n*3 jacobian sub matrices, stored by rows. these matrices will have\n"
+       "       // been initialized to 0 on entry. if the second body is zero then the\n"
+       "       // J2xx pointers may be 0.\n"
+       "       union \n"
+       "       {\n"
+       "               __global float4* m_J1linearAxisFloat4;\n"
+       "               __global float* m_J1linearAxis;\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               __global float4* m_J1angularAxisFloat4;\n"
+       "               __global float* m_J1angularAxis;\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "       __global float4* m_J2linearAxisFloat4;\n"
+       "       __global float* m_J2linearAxis;\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               __global float4* m_J2angularAxisFloat4;\n"
+       "               __global float* m_J2angularAxis;\n"
+       "       };\n"
+       "       // elements to jump from one row to the next in J's\n"
+       "       int rowskip;\n"
+       "       // right hand sides of the equation J*v = c + cfm * lambda. cfm is the\n"
+       "       // \"constraint force mixing\" vector. c is set to zero on entry, cfm is\n"
+       "       // set to a constant value (typically very small or zero) value on entry.\n"
+       "       __global float* m_constraintError;\n"
+       "       __global float* cfm;\n"
+       "       // lo and hi limits for variables (set to -/+ infinity on entry).\n"
+       "       __global float* m_lowerLimit;\n"
+       "       __global float* m_upperLimit;\n"
+       "       // findex vector for variables. see the LCP solver interface for a\n"
+       "       // description of what this does. this is set to -1 on entry.\n"
+       "       // note that the returned indexes are relative to the first index of\n"
+       "       // the constraint.\n"
+       "       __global int *findex;\n"
+       "       // number of solver iterations\n"
+       "       int m_numIterations;\n"
+       "       //damping of the velocity\n"
+       "       float   m_damping;\n"
+       "} b3GpuConstraintInfo2;\n"
+       "void   getSkewSymmetricMatrix(float4 vecIn, __global float4* v0,__global float4* v1,__global float4* v2)\n"
+       "{\n"
+       "       *v0 = (float4)(0.               ,-vecIn.z               ,vecIn.y,0.f);\n"
+       "       *v1 = (float4)(vecIn.z  ,0.                     ,-vecIn.x,0.f);\n"
+       "       *v2 = (float4)(-vecIn.y ,vecIn.x        ,0.f,0.f);\n"
+       "}\n"
+       "void getInfo2Point2Point(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies)\n"
+       "{\n"
+       "       float4 posA = bodies[constraint->m_rbA].m_pos;\n"
+       "       Quaternion rotA = bodies[constraint->m_rbA].m_quat;\n"
+       "       float4 posB = bodies[constraint->m_rbB].m_pos;\n"
+       "       Quaternion rotB = bodies[constraint->m_rbB].m_quat;\n"
+       "               // anchor points in global coordinates with respect to body PORs.\n"
+       "   \n"
+       "    // set jacobian\n"
+       "    info->m_J1linearAxis[0] = 1;\n"
+       "       info->m_J1linearAxis[info->rowskip+1] = 1;\n"
+       "       info->m_J1linearAxis[2*info->rowskip+2] = 1;\n"
+       "       float4 a1 = qtRotate(rotA,constraint->m_pivotInA);\n"
+       "       {\n"
+       "               __global float4* angular0 = (__global float4*)(info->m_J1angularAxis);\n"
+       "               __global float4* angular1 = (__global float4*)(info->m_J1angularAxis+info->rowskip);\n"
+       "               __global float4* angular2 = (__global float4*)(info->m_J1angularAxis+2*info->rowskip);\n"
+       "               float4 a1neg = -a1;\n"
+       "               getSkewSymmetricMatrix(a1neg,angular0,angular1,angular2);\n"
+       "       }\n"
+       "       if (info->m_J2linearAxis)\n"
+       "       {\n"
+       "               info->m_J2linearAxis[0] = -1;\n"
+       "               info->m_J2linearAxis[info->rowskip+1] = -1;\n"
+       "               info->m_J2linearAxis[2*info->rowskip+2] = -1;\n"
+       "       }\n"
+       "       \n"
+       "       float4 a2 = qtRotate(rotB,constraint->m_pivotInB);\n"
+       "   \n"
+       "       {\n"
+       "       //      float4 a2n = -a2;\n"
+       "               __global float4* angular0 = (__global float4*)(info->m_J2angularAxis);\n"
+       "               __global float4* angular1 = (__global float4*)(info->m_J2angularAxis+info->rowskip);\n"
+       "               __global float4* angular2 = (__global float4*)(info->m_J2angularAxis+2*info->rowskip);\n"
+       "               getSkewSymmetricMatrix(a2,angular0,angular1,angular2);\n"
+       "       }\n"
+       "    \n"
+       "    // set right hand side\n"
+       "//     float currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;\n"
+       "       float currERP = info->erp;\n"
+       "       float k = info->fps * currERP;\n"
+       "    int j;\n"
+       "       float4 result = a2 + posB - a1 - posA;\n"
+       "       float* resultPtr = &result;\n"
+       "       for (j=0; j<3; j++)\n"
+       "    {\n"
+       "        info->m_constraintError[j*info->rowskip] = k * (resultPtr[j]);\n"
+       "    }\n"
+       "}\n"
+       "Quaternion nearest( Quaternion first, Quaternion qd)\n"
+       "{\n"
+       "       Quaternion diff,sum;\n"
+       "       diff = first- qd;\n"
+       "       sum = first + qd;\n"
+       "       \n"
+       "       if( dot(diff,diff) < dot(sum,sum) )\n"
+       "               return qd;\n"
+       "       return (-qd);\n"
+       "}\n"
+       "float b3Acos(float x) \n"
+       "{ \n"
+       "       if (x<-1)       \n"
+       "               x=-1; \n"
+       "       if (x>1)        \n"
+       "               x=1;\n"
+       "       return acos(x); \n"
+       "}\n"
+       "float getAngle(Quaternion orn)\n"
+       "{\n"
+       "       if (orn.w>=1.f)\n"
+       "               orn.w=1.f;\n"
+       "       float s = 2.f * b3Acos(orn.w);\n"
+       "       return s;\n"
+       "}\n"
+       "void calculateDiffAxisAngleQuaternion( Quaternion orn0,Quaternion orn1a,float4* axis,float* angle)\n"
+       "{\n"
+       "       Quaternion orn1 = nearest(orn0,orn1a);\n"
+       "       \n"
+       "       Quaternion dorn = qtMul(orn1,qtInvert(orn0));\n"
+       "       *angle = getAngle(dorn);\n"
+       "       *axis = (float4)(dorn.x,dorn.y,dorn.z,0.f);\n"
+       "       \n"
+       "       //check for axis length\n"
+       "       float len = dot3F4(*axis,*axis);\n"
+       "       if (len < FLT_EPSILON*FLT_EPSILON)\n"
+       "               *axis = (float4)(1,0,0,0);\n"
+       "       else\n"
+       "               *axis /= sqrt(len);\n"
+       "}\n"
+       "void getInfo2FixedOrientation(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies, int start_row)\n"
+       "{\n"
+       "       Quaternion worldOrnA = bodies[constraint->m_rbA].m_quat;\n"
+       "       Quaternion worldOrnB = bodies[constraint->m_rbB].m_quat;\n"
+       "       int s = info->rowskip;\n"
+       "       int start_index = start_row * s;\n"
+       "       // 3 rows to make body rotations equal\n"
+       "       info->m_J1angularAxis[start_index] = 1;\n"
+       "       info->m_J1angularAxis[start_index + s + 1] = 1;\n"
+       "       info->m_J1angularAxis[start_index + s*2+2] = 1;\n"
+       "       if ( info->m_J2angularAxis)\n"
+       "       {\n"
+       "               info->m_J2angularAxis[start_index] = -1;\n"
+       "               info->m_J2angularAxis[start_index + s+1] = -1;\n"
+       "               info->m_J2angularAxis[start_index + s*2+2] = -1;\n"
+       "       }\n"
+       "       \n"
+       "       float currERP = info->erp;\n"
+       "       float k = info->fps * currERP;\n"
+       "       float4 diff;\n"
+       "       float angle;\n"
+       "       float4 qrelCur = qtMul(worldOrnA,qtInvert(worldOrnB));\n"
+       "       \n"
+       "       calculateDiffAxisAngleQuaternion(constraint->m_relTargetAB,qrelCur,&diff,&angle);\n"
+       "       diff*=-angle;\n"
+       "               \n"
+       "       float* resultPtr = &diff;\n"
+       "       \n"
+       "       for (int j=0; j<3; j++)\n"
+       "    {\n"
+       "        info->m_constraintError[(3+j)*info->rowskip] = k * resultPtr[j];\n"
+       "    }\n"
+       "       \n"
+       "}\n"
+       "__kernel void writeBackVelocitiesKernel(__global b3RigidBodyCL* bodies,__global b3GpuSolverBody* solverBodies,int numBodies)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numBodies)\n"
+       "               return;\n"
+       "       if (bodies[i].m_invMass)\n"
+       "       {\n"
+       "//             if (length(solverBodies[i].m_deltaLinearVelocity)<MOTIONCLAMP)\n"
+       "               {\n"
+       "                       bodies[i].m_linVel += solverBodies[i].m_deltaLinearVelocity;\n"
+       "               }\n"
+       "//             if (length(solverBodies[i].m_deltaAngularVelocity)<MOTIONCLAMP)\n"
+       "               {\n"
+       "                       bodies[i].m_angVel += solverBodies[i].m_deltaAngularVelocity;\n"
+       "               } \n"
+       "       }\n"
+       "}\n"
+       "__kernel void getInfo2Kernel(__global b3SolverConstraint* solverConstraintRows, \n"
+       "                                                       __global unsigned int* infos, \n"
+       "                                                       __global unsigned int* constraintRowOffsets, \n"
+       "                                                       __global b3GpuGenericConstraint* constraints, \n"
+       "                                                       __global b3BatchConstraint* batchConstraints, \n"
+       "                                                       __global b3RigidBodyCL* bodies,\n"
+       "                                                       __global BodyInertia* inertias,\n"
+       "                                                       __global b3GpuSolverBody* solverBodies,\n"
+       "                                                       float timeStep,\n"
+       "                                                       float globalErp,\n"
+       "                                                       float globalCfm,\n"
+       "                                                       float globalDamping,\n"
+       "                                                       int globalNumIterations,\n"
+       "                                                       int numConstraints)\n"
+       "{\n"
+       "       int i = get_global_id(0);\n"
+       "       if (i>=numConstraints)\n"
+       "               return;\n"
+       "               \n"
+       "       //for now, always initialize the batch info\n"
+       "       int info1 = infos[i];\n"
+       "                       \n"
+       "       __global b3SolverConstraint* currentConstraintRow = &solverConstraintRows[constraintRowOffsets[i]];\n"
+       "       __global b3GpuGenericConstraint* constraint = &constraints[i];\n"
+       "       __global b3RigidBodyCL* rbA = &bodies[ constraint->m_rbA];\n"
+       "       __global b3RigidBodyCL* rbB = &bodies[ constraint->m_rbB];\n"
+       "       int solverBodyIdA = constraint->m_rbA;\n"
+       "       int solverBodyIdB = constraint->m_rbB;\n"
+       "       __global b3GpuSolverBody* bodyAPtr = &solverBodies[solverBodyIdA];\n"
+       "       __global b3GpuSolverBody* bodyBPtr = &solverBodies[solverBodyIdB];\n"
+       "       if (rbA->m_invMass)\n"
+       "       {\n"
+       "               batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;\n"
+       "       } else\n"
+       "       {\n"
+       "//                     if (!solverBodyIdA)\n"
+       "//                             m_staticIdx = 0;\n"
+       "               batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;\n"
+       "       }\n"
+       "       if (rbB->m_invMass)\n"
+       "       {\n"
+       "               batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;\n"
+       "       } else\n"
+       "       {\n"
+       "//                     if (!solverBodyIdB)\n"
+       "//                             m_staticIdx = 0;\n"
+       "               batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;\n"
+       "       }\n"
+       "       if (info1)\n"
+       "       {\n"
+       "               int overrideNumSolverIterations = 0;//constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;\n"
+       "//             if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)\n"
+       "       //              m_maxOverrideNumSolverIterations = overrideNumSolverIterations;\n"
+       "               int j;\n"
+       "               for ( j=0;j<info1;j++)\n"
+       "               {\n"
+       "//                     memset(&currentConstraintRow[j],0,sizeof(b3SolverConstraint));\n"
+       "                       currentConstraintRow[j].m_angularComponentA = (float4)(0,0,0,0);\n"
+       "                       currentConstraintRow[j].m_angularComponentB = (float4)(0,0,0,0);\n"
+       "                       currentConstraintRow[j].m_appliedImpulse = 0.f;\n"
+       "                       currentConstraintRow[j].m_appliedPushImpulse = 0.f;\n"
+       "                       currentConstraintRow[j].m_cfm = 0.f;\n"
+       "                       currentConstraintRow[j].m_contactNormal = (float4)(0,0,0,0);\n"
+       "                       currentConstraintRow[j].m_friction = 0.f;\n"
+       "                       currentConstraintRow[j].m_frictionIndex = 0;\n"
+       "                       currentConstraintRow[j].m_jacDiagABInv = 0.f;\n"
+       "                       currentConstraintRow[j].m_lowerLimit = 0.f;\n"
+       "                       currentConstraintRow[j].m_upperLimit = 0.f;\n"
+       "                       currentConstraintRow[j].m_originalConstraint = i;\n"
+       "                       currentConstraintRow[j].m_overrideNumSolverIterations = 0;\n"
+       "                       currentConstraintRow[j].m_relpos1CrossNormal = (float4)(0,0,0,0);\n"
+       "                       currentConstraintRow[j].m_relpos2CrossNormal = (float4)(0,0,0,0);\n"
+       "                       currentConstraintRow[j].m_rhs = 0.f;\n"
+       "                       currentConstraintRow[j].m_rhsPenetration = 0.f;\n"
+       "                       currentConstraintRow[j].m_solverBodyIdA = 0;\n"
+       "                       currentConstraintRow[j].m_solverBodyIdB = 0;\n"
+       "                                                       \n"
+       "                       currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;\n"
+       "                       currentConstraintRow[j].m_upperLimit = B3_INFINITY;\n"
+       "                       currentConstraintRow[j].m_appliedImpulse = 0.f;\n"
+       "                       currentConstraintRow[j].m_appliedPushImpulse = 0.f;\n"
+       "                       currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;\n"
+       "                       currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;\n"
+       "                       currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;            \n"
+       "               }\n"
+       "               bodyAPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);\n"
+       "               bodyAPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);\n"
+       "               bodyAPtr->m_pushVelocity = (float4)(0,0,0,0);\n"
+       "               bodyAPtr->m_turnVelocity = (float4)(0,0,0,0);\n"
+       "               bodyBPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);\n"
+       "               bodyBPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);\n"
+       "               bodyBPtr->m_pushVelocity = (float4)(0,0,0,0);\n"
+       "               bodyBPtr->m_turnVelocity  = (float4)(0,0,0,0);\n"
+       "               int rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this\n"
+       "               \n"
+       "               b3GpuConstraintInfo2 info2;\n"
+       "               info2.fps = 1.f/timeStep;\n"
+       "               info2.erp = globalErp;\n"
+       "               info2.m_J1linearAxisFloat4 = &currentConstraintRow->m_contactNormal;\n"
+       "               info2.m_J1angularAxisFloat4 = &currentConstraintRow->m_relpos1CrossNormal;\n"
+       "               info2.m_J2linearAxisFloat4 = 0;\n"
+       "               info2.m_J2angularAxisFloat4 = &currentConstraintRow->m_relpos2CrossNormal;\n"
+       "               info2.rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this\n"
+       "               ///the size of b3SolverConstraint needs be a multiple of float\n"
+       "//             b3Assert(info2.rowskip*sizeof(float)== sizeof(b3SolverConstraint));\n"
+       "               info2.m_constraintError = &currentConstraintRow->m_rhs;\n"
+       "               currentConstraintRow->m_cfm = globalCfm;\n"
+       "               info2.m_damping = globalDamping;\n"
+       "               info2.cfm = &currentConstraintRow->m_cfm;\n"
+       "               info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;\n"
+       "               info2.m_upperLimit = &currentConstraintRow->m_upperLimit;\n"
+       "               info2.m_numIterations = globalNumIterations;\n"
+       "               switch (constraint->m_constraintType)\n"
+       "               {\n"
+       "                       case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:\n"
+       "                       {\n"
+       "                               getInfo2Point2Point(constraint,&info2,bodies);\n"
+       "                               break;\n"
+       "                       }\n"
+       "                       case B3_GPU_FIXED_CONSTRAINT_TYPE:\n"
+       "                       {\n"
+       "                               getInfo2Point2Point(constraint,&info2,bodies);\n"
+       "                               getInfo2FixedOrientation(constraint,&info2,bodies,3);\n"
+       "                               break;\n"
+       "                       }\n"
+       "                       default:\n"
+       "                       {\n"
+       "                       }\n"
+       "               }\n"
+       "               ///finalize the constraint setup\n"
+       "               for ( j=0;j<info1;j++)\n"
+       "               {\n"
+       "                       __global b3SolverConstraint* solverConstraint = &currentConstraintRow[j];\n"
+       "                       if (solverConstraint->m_upperLimit>=constraint->m_breakingImpulseThreshold)\n"
+       "                       {\n"
+       "                               solverConstraint->m_upperLimit = constraint->m_breakingImpulseThreshold;\n"
+       "                       }\n"
+       "                       if (solverConstraint->m_lowerLimit<=-constraint->m_breakingImpulseThreshold)\n"
+       "                       {\n"
+       "                               solverConstraint->m_lowerLimit = -constraint->m_breakingImpulseThreshold;\n"
+       "                       }\n"
+       "//                                             solverConstraint->m_originalContactPoint = constraint;\n"
+       "                                                       \n"
+       "                       Matrix3x3 invInertiaWorldA= inertias[constraint->m_rbA].m_invInertiaWorld;\n"
+       "                       {\n"
+       "                               //float4 angularFactorA(1,1,1);\n"
+       "                               float4 ftorqueAxis1 = solverConstraint->m_relpos1CrossNormal;\n"
+       "                               solverConstraint->m_angularComponentA = mtMul1(invInertiaWorldA,ftorqueAxis1);//*angularFactorA;\n"
+       "                       }\n"
+       "                                               \n"
+       "                       Matrix3x3 invInertiaWorldB= inertias[constraint->m_rbB].m_invInertiaWorld;\n"
+       "                       {\n"
+       "                               float4 ftorqueAxis2 = solverConstraint->m_relpos2CrossNormal;\n"
+       "                               solverConstraint->m_angularComponentB = mtMul1(invInertiaWorldB,ftorqueAxis2);//*constraint->m_rbB.getAngularFactor();\n"
+       "                       }\n"
+       "                       {\n"
+       "                               //it is ok to use solverConstraint->m_contactNormal instead of -solverConstraint->m_contactNormal\n"
+       "                               //because it gets multiplied iMJlB\n"
+       "                               float4 iMJlA = solverConstraint->m_contactNormal*rbA->m_invMass;\n"
+       "                               float4 iMJaA = mtMul3(solverConstraint->m_relpos1CrossNormal,invInertiaWorldA);\n"
+       "                               float4 iMJlB = solverConstraint->m_contactNormal*rbB->m_invMass;//sign of normal?\n"
+       "                               float4 iMJaB = mtMul3(solverConstraint->m_relpos2CrossNormal,invInertiaWorldB);\n"
+       "                               float sum = dot3F4(iMJlA,solverConstraint->m_contactNormal);\n"
+       "                               sum += dot3F4(iMJaA,solverConstraint->m_relpos1CrossNormal);\n"
+       "                               sum += dot3F4(iMJlB,solverConstraint->m_contactNormal);\n"
+       "                               sum += dot3F4(iMJaB,solverConstraint->m_relpos2CrossNormal);\n"
+       "                               float fsum = fabs(sum);\n"
+       "                               if (fsum>FLT_EPSILON)\n"
+       "                               {\n"
+       "                                       solverConstraint->m_jacDiagABInv = 1.f/sum;\n"
+       "                               } else\n"
+       "                               {\n"
+       "                                       solverConstraint->m_jacDiagABInv = 0.f;\n"
+       "                               }\n"
+       "                       }\n"
+       "                       ///fix rhs\n"
+       "                       ///todo: add force/torque accelerators\n"
+       "                       {\n"
+       "                               float rel_vel;\n"
+       "                               float vel1Dotn = dot3F4(solverConstraint->m_contactNormal,rbA->m_linVel) + dot3F4(solverConstraint->m_relpos1CrossNormal,rbA->m_angVel);\n"
+       "                               float vel2Dotn = -dot3F4(solverConstraint->m_contactNormal,rbB->m_linVel) + dot3F4(solverConstraint->m_relpos2CrossNormal,rbB->m_angVel);\n"
+       "                               rel_vel = vel1Dotn+vel2Dotn;\n"
+       "                               float restitution = 0.f;\n"
+       "                               float positionalError = solverConstraint->m_rhs;//already filled in by getConstraintInfo2\n"
+       "                               float   velocityError = restitution - rel_vel * info2.m_damping;\n"
+       "                               float   penetrationImpulse = positionalError*solverConstraint->m_jacDiagABInv;\n"
+       "                               float   velocityImpulse = velocityError *solverConstraint->m_jacDiagABInv;\n"
+       "                               solverConstraint->m_rhs = penetrationImpulse+velocityImpulse;\n"
+       "                               solverConstraint->m_appliedImpulse = 0.f;\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl
new file mode 100644 (file)
index 0000000..5c4d62e
--- /dev/null
@@ -0,0 +1,501 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+
+//#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile global int*
+#endif
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define mymake_float4 (float4)
+//#define make_float2 (float2)
+//#define make_uint4 (uint4)
+//#define make_int4 (int4)
+//#define make_uint2 (uint2)
+//#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+///////////////////////////////////////
+//     Vector
+///////////////////////////////////////
+
+
+
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+       return fast_normalize(v);
+}
+
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+       return cross(a,b);
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = mymake_float4(a.xyz,0.f);
+       float4 b1 = mymake_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+       float4 n = mymake_float4(a.x, a.y, a.z, 0.f);
+       return fastNormalize4( n );
+//     float length = sqrtf(dot3F4(a, a));
+//     return 1.f/length * a;
+}
+
+
+
+
+///////////////////////////////////////
+//     Matrix3x3
+///////////////////////////////////////
+
+typedef struct
+{
+       float4 m_row[3];
+}Matrix3x3;
+
+
+
+
+
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b);
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b);
+
+
+
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b)
+{
+       float4 ans;
+       ans.x = dot3F4( a.m_row[0], b );
+       ans.y = dot3F4( a.m_row[1], b );
+       ans.z = dot3F4( a.m_row[2], b );
+       ans.w = 0.f;
+       return ans;
+}
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b)
+{
+       float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+       float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+       float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+       float4 ans;
+       ans.x = dot3F4( a, colx );
+       ans.y = dot3F4( a, coly );
+       ans.z = dot3F4( a, colz );
+       return ans;
+}
+
+///////////////////////////////////////
+//     Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+
+
+
+
+
+
+#define WG_SIZE 64
+
+typedef struct
+{
+       float4 m_pos;
+       Quaternion m_quat;
+       float4 m_linVel;
+       float4 m_angVel;
+
+       u32 m_shapeIdx;
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+} Body;
+
+typedef struct
+{
+       Matrix3x3 m_invInertia;
+       Matrix3x3 m_initInvInertia;
+} Shape;
+
+typedef struct
+{
+       float4 m_linear;
+       float4 m_worldPos[4];
+       float4 m_center;        
+       float m_jacCoeffInv[4];
+       float m_b[4];
+       float m_appliedRambdaDt[4];
+
+       float m_fJacCoeffInv[2];        
+       float m_fAppliedRambdaDt[2];    
+
+       u32 m_bodyA;
+       u32 m_bodyB;
+
+       int m_batchIdx;
+       u32 m_paddings[1];
+} Constraint4;
+
+
+
+typedef struct
+{
+       int m_nConstraints;
+       int m_start;
+       int m_batchIdx;
+       int m_nSplit;
+//     int m_paddings[1];
+} ConstBuffer;
+
+typedef struct
+{
+       int m_solveFriction;
+       int m_maxBatch; //      long batch really kills the performance
+       int m_batchIdx;
+       int m_nSplit;
+//     int m_paddings[1];
+} ConstBufferBatchSolve;
+
+void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);
+
+void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
+{
+       *linear = mymake_float4(-n.xyz,0.f);
+       *angular0 = -cross3(r0, n);
+       *angular1 = cross3(r1, n);
+}
+
+float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );
+
+float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
+{
+       return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
+}
+
+
+float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
+                                  float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);
+
+float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
+                                       float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)
+{
+       //      linear0,1 are normlized
+       float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
+       float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
+       float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
+       float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
+       return -1.f/(jmj0+jmj1+jmj2+jmj3);
+}
+
+
+void solveContact(__global Constraint4* cs,
+                                 float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
+                                 float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB);
+
+void solveContact(__global Constraint4* cs,
+                       float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
+                       float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)
+{
+       float minRambdaDt = 0;
+       float maxRambdaDt = FLT_MAX;
+
+       for(int ic=0; ic<4; ic++)
+       {
+               if( cs->m_jacCoeffInv[ic] == 0.f ) continue;
+
+               float4 angular0, angular1, linear;
+               float4 r0 = cs->m_worldPos[ic] - posA;
+               float4 r1 = cs->m_worldPos[ic] - posB;
+               setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );
+
+               float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, 
+                       *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];
+               rambdaDt *= cs->m_jacCoeffInv[ic];
+
+               {
+                       float prevSum = cs->m_appliedRambdaDt[ic];
+                       float updated = prevSum;
+                       updated += rambdaDt;
+                       updated = max2( updated, minRambdaDt );
+                       updated = min2( updated, maxRambdaDt );
+                       rambdaDt = updated - prevSum;
+                       cs->m_appliedRambdaDt[ic] = updated;
+               }
+
+               float4 linImp0 = invMassA*linear*rambdaDt;
+               float4 linImp1 = invMassB*(-linear)*rambdaDt;
+               float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
+               float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
+
+               *linVelA += linImp0;
+               *angVelA += angImp0;
+               *linVelB += linImp1;
+               *angVelB += angImp1;
+       }
+}
+
+void btPlaneSpace1 (const float4* n, float4* p, float4* q);
+ void btPlaneSpace1 (const float4* n, float4* p, float4* q)
+{
+  if (fabs(n[0].z) > 0.70710678f) {
+    // choose p in y-z plane
+    float a = n[0].y*n[0].y + n[0].z*n[0].z;
+    float k = 1.f/sqrt(a);
+    p[0].x = 0;
+       p[0].y = -n[0].z*k;
+       p[0].z = n[0].y*k;
+    // set q = n x p
+    q[0].x = a*k;
+       q[0].y = -n[0].x*p[0].z;
+       q[0].z = n[0].x*p[0].y;
+  }
+  else {
+    // choose p in x-y plane
+    float a = n[0].x*n[0].x + n[0].y*n[0].y;
+    float k = 1.f/sqrt(a);
+    p[0].x = -n[0].y*k;
+       p[0].y = n[0].x*k;
+       p[0].z = 0;
+    // set q = n x p
+    q[0].x = -n[0].z*p[0].y;
+       q[0].y = n[0].z*p[0].x;
+       q[0].z = a*k;
+  }
+}
+
+void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);
+void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)
+{
+       //float frictionCoeff = ldsCs[0].m_linear.w;
+       int aIdx = ldsCs[0].m_bodyA;
+       int bIdx = ldsCs[0].m_bodyB;
+
+       float4 posA = gBodies[aIdx].m_pos;
+       float4 linVelA = gBodies[aIdx].m_linVel;
+       float4 angVelA = gBodies[aIdx].m_angVel;
+       float invMassA = gBodies[aIdx].m_invMass;
+       Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
+
+       float4 posB = gBodies[bIdx].m_pos;
+       float4 linVelB = gBodies[bIdx].m_linVel;
+       float4 angVelB = gBodies[bIdx].m_angVel;
+       float invMassB = gBodies[bIdx].m_invMass;
+       Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
+
+       solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
+                       posB, &linVelB, &angVelB, invMassB, invInertiaB );
+
+  if (gBodies[aIdx].m_invMass)
+  {
+               gBodies[aIdx].m_linVel = linVelA;
+               gBodies[aIdx].m_angVel = angVelA;
+       } else
+       {
+               gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);
+               gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);
+       
+       }
+       if (gBodies[bIdx].m_invMass)
+  {
+               gBodies[bIdx].m_linVel = linVelB;
+               gBodies[bIdx].m_angVel = angVelB;
+       } else
+       {
+               gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);
+               gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);
+       
+       }
+
+}
+
+
+
+typedef struct 
+{
+       int m_valInt0;
+       int m_valInt1;
+       int m_valInt2;
+       int m_valInt3;
+
+       float m_val0;
+       float m_val1;
+       float m_val2;
+       float m_val3;
+} SolverDebugInfo;
+
+
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void BatchSolveKernelContact(__global Body* gBodies,
+                      __global Shape* gShapes,
+                      __global Constraint4* gConstraints,
+                      __global int* gN,
+                      __global int* gOffsets,
+                      __global int* batchSizes,
+                       int maxBatch1,
+                       int cellBatch,
+                       int4 nSplit
+                      )
+{
+       //__local int ldsBatchIdx[WG_SIZE+1];
+       __local int ldsCurBatch;
+       __local int ldsNextBatch;
+       __local int ldsStart;
+
+       int lIdx = GET_LOCAL_IDX;
+       int wgIdx = GET_GROUP_IDX;
+
+//     int gIdx = GET_GLOBAL_IDX;
+//     debugInfo[gIdx].m_valInt0 = gIdx;
+       //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;
+
+       
+       
+
+       int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);
+       int remain= (wgIdx%((nSplit.x*nSplit.y)/4));
+       int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);
+       int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);
+       int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);
+
+       //int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);
+       //int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);
+       //int cellIdx = xIdx+yIdx*nSplit;
+       
+       if( gN[cellIdx] == 0 ) 
+               return;
+
+       int maxBatch = batchSizes[cellIdx];
+       
+       
+       const int start = gOffsets[cellIdx];
+       const int end = start + gN[cellIdx];
+
+       
+       
+       
+       if( lIdx == 0 )
+       {
+               ldsCurBatch = 0;
+               ldsNextBatch = 0;
+               ldsStart = start;
+       }
+
+
+       GROUP_LDS_BARRIER;
+
+       int idx=ldsStart+lIdx;
+       while (ldsCurBatch < maxBatch)
+       {
+               for(; idx<end; )
+               {
+                       if (gConstraints[idx].m_batchIdx == ldsCurBatch)
+                       {
+                                       solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );
+
+                                idx+=64;
+                       } else
+                       {
+                               break;
+                       }
+               }
+               GROUP_LDS_BARRIER;
+       
+               if( lIdx == 0 )
+               {
+                       ldsCurBatch++;
+               }
+               GROUP_LDS_BARRIER;
+       }
+       
+    
+}
+
+
+
+__kernel void solveSingleContactKernel(__global Body* gBodies,
+                      __global Shape* gShapes,
+                      __global Constraint4* gConstraints,
+                       int cellIdx,
+                       int batchOffset,
+                       int numConstraintsInBatch
+                      )
+{
+
+       int index = get_global_id(0);
+       if (index < numConstraintsInBatch)
+       {
+               int idx=batchOffset+index;
+               solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );
+       }    
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveContact.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveContact.h
new file mode 100644 (file)
index 0000000..6e14ad5
--- /dev/null
@@ -0,0 +1,392 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solveContactCL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Takahiro Harada\n"
+       "//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+       "#ifdef cl_ext_atomic_counters_32\n"
+       "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+       "#else\n"
+       "#define counter32_t volatile global int*\n"
+       "#endif\n"
+       "typedef unsigned int u32;\n"
+       "typedef unsigned short u16;\n"
+       "typedef unsigned char u8;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GET_NUM_GROUPS get_num_groups(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define AppendInc(x, out) out = atomic_inc(x)\n"
+       "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+       "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+       "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+       "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+       "#define mymake_float4 (float4)\n"
+       "//#define make_float2 (float2)\n"
+       "//#define make_uint4 (uint4)\n"
+       "//#define make_int4 (int4)\n"
+       "//#define make_uint2 (uint2)\n"
+       "//#define make_int2 (int2)\n"
+       "#define max2 max\n"
+       "#define min2 min\n"
+       "///////////////////////////////////////\n"
+       "//     Vector\n"
+       "///////////////////////////////////////\n"
+       "__inline\n"
+       "float4 fastNormalize4(float4 v)\n"
+       "{\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "__inline\n"
+       "float4 cross3(float4 a, float4 b)\n"
+       "{\n"
+       "       return cross(a,b);\n"
+       "}\n"
+       "__inline\n"
+       "float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = mymake_float4(a.xyz,0.f);\n"
+       "       float4 b1 = mymake_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize3(const float4 a)\n"
+       "{\n"
+       "       float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
+       "       return fastNormalize4( n );\n"
+       "//     float length = sqrtf(dot3F4(a, a));\n"
+       "//     return 1.f/length * a;\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Matrix3x3\n"
+       "///////////////////////////////////////\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_row[3];\n"
+       "}Matrix3x3;\n"
+       "__inline\n"
+       "float4 mtMul1(Matrix3x3 a, float4 b);\n"
+       "__inline\n"
+       "float4 mtMul3(float4 a, Matrix3x3 b);\n"
+       "__inline\n"
+       "float4 mtMul1(Matrix3x3 a, float4 b)\n"
+       "{\n"
+       "       float4 ans;\n"
+       "       ans.x = dot3F4( a.m_row[0], b );\n"
+       "       ans.y = dot3F4( a.m_row[1], b );\n"
+       "       ans.z = dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "float4 mtMul3(float4 a, Matrix3x3 b)\n"
+       "{\n"
+       "       float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       float4 ans;\n"
+       "       ans.x = dot3F4( a, colx );\n"
+       "       ans.y = dot3F4( a, coly );\n"
+       "       ans.z = dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Quaternion\n"
+       "///////////////////////////////////////\n"
+       "typedef float4 Quaternion;\n"
+       "#define WG_SIZE 64\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_pos;\n"
+       "       Quaternion m_quat;\n"
+       "       float4 m_linVel;\n"
+       "       float4 m_angVel;\n"
+       "       u32 m_shapeIdx;\n"
+       "       float m_invMass;\n"
+       "       float m_restituitionCoeff;\n"
+       "       float m_frictionCoeff;\n"
+       "} Body;\n"
+       "typedef struct\n"
+       "{\n"
+       "       Matrix3x3 m_invInertia;\n"
+       "       Matrix3x3 m_initInvInertia;\n"
+       "} Shape;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_linear;\n"
+       "       float4 m_worldPos[4];\n"
+       "       float4 m_center;        \n"
+       "       float m_jacCoeffInv[4];\n"
+       "       float m_b[4];\n"
+       "       float m_appliedRambdaDt[4];\n"
+       "       float m_fJacCoeffInv[2];        \n"
+       "       float m_fAppliedRambdaDt[2];    \n"
+       "       u32 m_bodyA;\n"
+       "       u32 m_bodyB;\n"
+       "       int m_batchIdx;\n"
+       "       u32 m_paddings[1];\n"
+       "} Constraint4;\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_nConstraints;\n"
+       "       int m_start;\n"
+       "       int m_batchIdx;\n"
+       "       int m_nSplit;\n"
+       "//     int m_paddings[1];\n"
+       "} ConstBuffer;\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_solveFriction;\n"
+       "       int m_maxBatch; //      long batch really kills the performance\n"
+       "       int m_batchIdx;\n"
+       "       int m_nSplit;\n"
+       "//     int m_paddings[1];\n"
+       "} ConstBufferBatchSolve;\n"
+       "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
+       "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
+       "{\n"
+       "       *linear = mymake_float4(-n.xyz,0.f);\n"
+       "       *angular0 = -cross3(r0, n);\n"
+       "       *angular1 = cross3(r1, n);\n"
+       "}\n"
+       "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
+       "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
+       "{\n"
+       "       return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
+       "}\n"
+       "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+       "                                  float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
+       "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+       "                                       float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
+       "{\n"
+       "       //      linear0,1 are normlized\n"
+       "       float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
+       "       float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+       "       float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
+       "       float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+       "       return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
+       "}\n"
+       "void solveContact(__global Constraint4* cs,\n"
+       "                                 float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
+       "                                 float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB);\n"
+       "void solveContact(__global Constraint4* cs,\n"
+       "                       float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
+       "                       float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)\n"
+       "{\n"
+       "       float minRambdaDt = 0;\n"
+       "       float maxRambdaDt = FLT_MAX;\n"
+       "       for(int ic=0; ic<4; ic++)\n"
+       "       {\n"
+       "               if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
+       "               float4 angular0, angular1, linear;\n"
+       "               float4 r0 = cs->m_worldPos[ic] - posA;\n"
+       "               float4 r1 = cs->m_worldPos[ic] - posB;\n"
+       "               setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
+       "               float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
+       "                       *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];\n"
+       "               rambdaDt *= cs->m_jacCoeffInv[ic];\n"
+       "               {\n"
+       "                       float prevSum = cs->m_appliedRambdaDt[ic];\n"
+       "                       float updated = prevSum;\n"
+       "                       updated += rambdaDt;\n"
+       "                       updated = max2( updated, minRambdaDt );\n"
+       "                       updated = min2( updated, maxRambdaDt );\n"
+       "                       rambdaDt = updated - prevSum;\n"
+       "                       cs->m_appliedRambdaDt[ic] = updated;\n"
+       "               }\n"
+       "               float4 linImp0 = invMassA*linear*rambdaDt;\n"
+       "               float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+       "               float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+       "               float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+       "               *linVelA += linImp0;\n"
+       "               *angVelA += angImp0;\n"
+       "               *linVelB += linImp1;\n"
+       "               *angVelB += angImp1;\n"
+       "       }\n"
+       "}\n"
+       "void btPlaneSpace1 (const float4* n, float4* p, float4* q);\n"
+       " void btPlaneSpace1 (const float4* n, float4* p, float4* q)\n"
+       "{\n"
+       "  if (fabs(n[0].z) > 0.70710678f) {\n"
+       "    // choose p in y-z plane\n"
+       "    float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
+       "    float k = 1.f/sqrt(a);\n"
+       "    p[0].x = 0;\n"
+       "       p[0].y = -n[0].z*k;\n"
+       "       p[0].z = n[0].y*k;\n"
+       "    // set q = n x p\n"
+       "    q[0].x = a*k;\n"
+       "       q[0].y = -n[0].x*p[0].z;\n"
+       "       q[0].z = n[0].x*p[0].y;\n"
+       "  }\n"
+       "  else {\n"
+       "    // choose p in x-y plane\n"
+       "    float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
+       "    float k = 1.f/sqrt(a);\n"
+       "    p[0].x = -n[0].y*k;\n"
+       "       p[0].y = n[0].x*k;\n"
+       "       p[0].z = 0;\n"
+       "    // set q = n x p\n"
+       "    q[0].x = -n[0].z*p[0].y;\n"
+       "       q[0].y = n[0].z*p[0].x;\n"
+       "       q[0].z = a*k;\n"
+       "  }\n"
+       "}\n"
+       "void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
+       "void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
+       "{\n"
+       "       //float frictionCoeff = ldsCs[0].m_linear.w;\n"
+       "       int aIdx = ldsCs[0].m_bodyA;\n"
+       "       int bIdx = ldsCs[0].m_bodyB;\n"
+       "       float4 posA = gBodies[aIdx].m_pos;\n"
+       "       float4 linVelA = gBodies[aIdx].m_linVel;\n"
+       "       float4 angVelA = gBodies[aIdx].m_angVel;\n"
+       "       float invMassA = gBodies[aIdx].m_invMass;\n"
+       "       Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+       "       float4 posB = gBodies[bIdx].m_pos;\n"
+       "       float4 linVelB = gBodies[bIdx].m_linVel;\n"
+       "       float4 angVelB = gBodies[bIdx].m_angVel;\n"
+       "       float invMassB = gBodies[bIdx].m_invMass;\n"
+       "       Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+       "       solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+       "                       posB, &linVelB, &angVelB, invMassB, invInertiaB );\n"
+       "  if (gBodies[aIdx].m_invMass)\n"
+       "  {\n"
+       "               gBodies[aIdx].m_linVel = linVelA;\n"
+       "               gBodies[aIdx].m_angVel = angVelA;\n"
+       "       } else\n"
+       "       {\n"
+       "               gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+       "               gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+       "       \n"
+       "       }\n"
+       "       if (gBodies[bIdx].m_invMass)\n"
+       "  {\n"
+       "               gBodies[bIdx].m_linVel = linVelB;\n"
+       "               gBodies[bIdx].m_angVel = angVelB;\n"
+       "       } else\n"
+       "       {\n"
+       "               gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+       "               gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+       "       \n"
+       "       }\n"
+       "}\n"
+       "typedef struct \n"
+       "{\n"
+       "       int m_valInt0;\n"
+       "       int m_valInt1;\n"
+       "       int m_valInt2;\n"
+       "       int m_valInt3;\n"
+       "       float m_val0;\n"
+       "       float m_val1;\n"
+       "       float m_val2;\n"
+       "       float m_val3;\n"
+       "} SolverDebugInfo;\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void BatchSolveKernelContact(__global Body* gBodies,\n"
+       "                      __global Shape* gShapes,\n"
+       "                      __global Constraint4* gConstraints,\n"
+       "                      __global int* gN,\n"
+       "                      __global int* gOffsets,\n"
+       "                      __global int* batchSizes,\n"
+       "                       int maxBatch1,\n"
+       "                       int cellBatch,\n"
+       "                       int4 nSplit\n"
+       "                      )\n"
+       "{\n"
+       "       //__local int ldsBatchIdx[WG_SIZE+1];\n"
+       "       __local int ldsCurBatch;\n"
+       "       __local int ldsNextBatch;\n"
+       "       __local int ldsStart;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       int wgIdx = GET_GROUP_IDX;\n"
+       "//     int gIdx = GET_GLOBAL_IDX;\n"
+       "//     debugInfo[gIdx].m_valInt0 = gIdx;\n"
+       "       //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
+       "       \n"
+       "       \n"
+       "       int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);\n"
+       "       int remain= (wgIdx%((nSplit.x*nSplit.y)/4));\n"
+       "       int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);\n"
+       "       int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);\n"
+       "       int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);\n"
+       "       //int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);\n"
+       "       //int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);\n"
+       "       //int cellIdx = xIdx+yIdx*nSplit;\n"
+       "       \n"
+       "       if( gN[cellIdx] == 0 ) \n"
+       "               return;\n"
+       "       int maxBatch = batchSizes[cellIdx];\n"
+       "       \n"
+       "       \n"
+       "       const int start = gOffsets[cellIdx];\n"
+       "       const int end = start + gN[cellIdx];\n"
+       "       \n"
+       "       \n"
+       "       \n"
+       "       if( lIdx == 0 )\n"
+       "       {\n"
+       "               ldsCurBatch = 0;\n"
+       "               ldsNextBatch = 0;\n"
+       "               ldsStart = start;\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       int idx=ldsStart+lIdx;\n"
+       "       while (ldsCurBatch < maxBatch)\n"
+       "       {\n"
+       "               for(; idx<end; )\n"
+       "               {\n"
+       "                       if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
+       "                       {\n"
+       "                                       solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+       "                                idx+=64;\n"
+       "                       } else\n"
+       "                       {\n"
+       "                               break;\n"
+       "                       }\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "       \n"
+       "               if( lIdx == 0 )\n"
+       "               {\n"
+       "                       ldsCurBatch++;\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "       }\n"
+       "       \n"
+       "    \n"
+       "}\n"
+       "__kernel void solveSingleContactKernel(__global Body* gBodies,\n"
+       "                      __global Shape* gShapes,\n"
+       "                      __global Constraint4* gConstraints,\n"
+       "                       int cellIdx,\n"
+       "                       int batchOffset,\n"
+       "                       int numConstraintsInBatch\n"
+       "                      )\n"
+       "{\n"
+       "       int index = get_global_id(0);\n"
+       "       if (index < numConstraintsInBatch)\n"
+       "       {\n"
+       "               int idx=batchOffset+index;\n"
+       "               solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+       "       }    \n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl
new file mode 100644 (file)
index 0000000..1d70fbb
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+
+//#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile global int*
+#endif
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define mymake_float4 (float4)
+//#define make_float2 (float2)
+//#define make_uint4 (uint4)
+//#define make_int4 (int4)
+//#define make_uint2 (uint2)
+//#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+///////////////////////////////////////
+//     Vector
+///////////////////////////////////////
+
+
+
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+       return fast_normalize(v);
+}
+
+
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+       return cross(a,b);
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = mymake_float4(a.xyz,0.f);
+       float4 b1 = mymake_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+
+
+
+__inline
+float4 normalize3(const float4 a)
+{
+       float4 n = mymake_float4(a.x, a.y, a.z, 0.f);
+       return fastNormalize4( n );
+//     float length = sqrtf(dot3F4(a, a));
+//     return 1.f/length * a;
+}
+
+
+
+
+///////////////////////////////////////
+//     Matrix3x3
+///////////////////////////////////////
+
+typedef struct
+{
+       float4 m_row[3];
+}Matrix3x3;
+
+
+
+
+
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b);
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b);
+
+
+
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b)
+{
+       float4 ans;
+       ans.x = dot3F4( a.m_row[0], b );
+       ans.y = dot3F4( a.m_row[1], b );
+       ans.z = dot3F4( a.m_row[2], b );
+       ans.w = 0.f;
+       return ans;
+}
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b)
+{
+       float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+       float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+       float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+       float4 ans;
+       ans.x = dot3F4( a, colx );
+       ans.y = dot3F4( a, coly );
+       ans.z = dot3F4( a, colz );
+       return ans;
+}
+
+///////////////////////////////////////
+//     Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+
+
+
+
+
+
+#define WG_SIZE 64
+
+typedef struct
+{
+       float4 m_pos;
+       Quaternion m_quat;
+       float4 m_linVel;
+       float4 m_angVel;
+
+       u32 m_shapeIdx;
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+} Body;
+
+typedef struct
+{
+       Matrix3x3 m_invInertia;
+       Matrix3x3 m_initInvInertia;
+} Shape;
+
+typedef struct
+{
+       float4 m_linear;
+       float4 m_worldPos[4];
+       float4 m_center;        
+       float m_jacCoeffInv[4];
+       float m_b[4];
+       float m_appliedRambdaDt[4];
+
+       float m_fJacCoeffInv[2];        
+       float m_fAppliedRambdaDt[2];    
+
+       u32 m_bodyA;
+       u32 m_bodyB;
+
+       int m_batchIdx;
+       u32 m_paddings[1];
+} Constraint4;
+
+
+
+typedef struct
+{
+       int m_nConstraints;
+       int m_start;
+       int m_batchIdx;
+       int m_nSplit;
+//     int m_paddings[1];
+} ConstBuffer;
+
+typedef struct
+{
+       int m_solveFriction;
+       int m_maxBatch; //      long batch really kills the performance
+       int m_batchIdx;
+       int m_nSplit;
+//     int m_paddings[1];
+} ConstBufferBatchSolve;
+
+void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);
+
+void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
+{
+       *linear = mymake_float4(-n.xyz,0.f);
+       *angular0 = -cross3(r0, n);
+       *angular1 = cross3(r1, n);
+}
+
+float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );
+
+float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
+{
+       return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
+}
+
+
+float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
+                                  float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);
+
+float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
+                                       float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)
+{
+       //      linear0,1 are normlized
+       float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
+       float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
+       float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
+       float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
+       return -1.f/(jmj0+jmj1+jmj2+jmj3);
+}
+void btPlaneSpace1 (const float4* n, float4* p, float4* q);
+ void btPlaneSpace1 (const float4* n, float4* p, float4* q)
+{
+  if (fabs(n[0].z) > 0.70710678f) {
+    // choose p in y-z plane
+    float a = n[0].y*n[0].y + n[0].z*n[0].z;
+    float k = 1.f/sqrt(a);
+    p[0].x = 0;
+       p[0].y = -n[0].z*k;
+       p[0].z = n[0].y*k;
+    // set q = n x p
+    q[0].x = a*k;
+       q[0].y = -n[0].x*p[0].z;
+       q[0].z = n[0].x*p[0].y;
+  }
+  else {
+    // choose p in x-y plane
+    float a = n[0].x*n[0].x + n[0].y*n[0].y;
+    float k = 1.f/sqrt(a);
+    p[0].x = -n[0].y*k;
+       p[0].y = n[0].x*k;
+       p[0].z = 0;
+    // set q = n x p
+    q[0].x = -n[0].z*p[0].y;
+       q[0].y = n[0].z*p[0].x;
+       q[0].z = a*k;
+  }
+}
+
+
+void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);
+void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)
+{
+       float frictionCoeff = ldsCs[0].m_linear.w;
+       int aIdx = ldsCs[0].m_bodyA;
+       int bIdx = ldsCs[0].m_bodyB;
+
+
+       float4 posA = gBodies[aIdx].m_pos;
+       float4 linVelA = gBodies[aIdx].m_linVel;
+       float4 angVelA = gBodies[aIdx].m_angVel;
+       float invMassA = gBodies[aIdx].m_invMass;
+       Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
+
+       float4 posB = gBodies[bIdx].m_pos;
+       float4 linVelB = gBodies[bIdx].m_linVel;
+       float4 angVelB = gBodies[bIdx].m_angVel;
+       float invMassB = gBodies[bIdx].m_invMass;
+       Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
+       
+
+       {
+               float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+               float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+               float sum = 0;
+               for(int j=0; j<4; j++)
+               {
+                       sum +=ldsCs[0].m_appliedRambdaDt[j];
+               }
+               frictionCoeff = 0.7f;
+               for(int j=0; j<4; j++)
+               {
+                       maxRambdaDt[j] = frictionCoeff*sum;
+                       minRambdaDt[j] = -maxRambdaDt[j];
+               }
+
+               
+//             solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
+//                     posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );
+               
+               
+               {
+                       
+                       __global Constraint4* cs = ldsCs;
+                       
+                       if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;
+                       const float4 center = cs->m_center;
+                       
+                       float4 n = -cs->m_linear;
+                       
+                       float4 tangent[2];
+                       btPlaneSpace1(&n,&tangent[0],&tangent[1]);
+                       float4 angular0, angular1, linear;
+                       float4 r0 = center - posA;
+                       float4 r1 = center - posB;
+                       for(int i=0; i<2; i++)
+                       {
+                               setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );
+                               float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
+                                                                                       linVelA, angVelA, linVelB, angVelB );
+                               rambdaDt *= cs->m_fJacCoeffInv[i];
+                               
+                               {
+                                       float prevSum = cs->m_fAppliedRambdaDt[i];
+                                       float updated = prevSum;
+                                       updated += rambdaDt;
+                                       updated = max2( updated, minRambdaDt[i] );
+                                       updated = min2( updated, maxRambdaDt[i] );
+                                       rambdaDt = updated - prevSum;
+                                       cs->m_fAppliedRambdaDt[i] = updated;
+                               }
+                               
+                               float4 linImp0 = invMassA*linear*rambdaDt;
+                               float4 linImp1 = invMassB*(-linear)*rambdaDt;
+                               float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
+                               float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
+                               
+                               linVelA += linImp0;
+                               angVelA += angImp0;
+                               linVelB += linImp1;
+                               angVelB += angImp1;
+                       }
+                       {       //      angular damping for point constraint
+                               float4 ab = normalize3( posB - posA );
+                               float4 ac = normalize3( center - posA );
+                               if( dot3F4( ab, ac ) > 0.95f  || (invMassA == 0.f || invMassB == 0.f))
+                               {
+                                       float angNA = dot3F4( n, angVelA );
+                                       float angNB = dot3F4( n, angVelB );
+                                       
+                                       angVelA -= (angNA*0.1f)*n;
+                                       angVelB -= (angNB*0.1f)*n;
+                               }
+                       }
+               }
+
+               
+               
+       }
+
+       if (gBodies[aIdx].m_invMass)
+       {
+               gBodies[aIdx].m_linVel = linVelA;
+               gBodies[aIdx].m_angVel = angVelA;
+       } else
+       {
+               gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);
+               gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);
+       }
+       if (gBodies[bIdx].m_invMass)
+       {
+               gBodies[bIdx].m_linVel = linVelB;
+               gBodies[bIdx].m_angVel = angVelB;
+       } else
+       {
+               gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);
+               gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);
+       }
+
+}
+
+typedef struct 
+{
+       int m_valInt0;
+       int m_valInt1;
+       int m_valInt2;
+       int m_valInt3;
+
+       float m_val0;
+       float m_val1;
+       float m_val2;
+       float m_val3;
+} SolverDebugInfo;
+
+
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void BatchSolveKernelFriction(__global Body* gBodies,
+                      __global Shape* gShapes,
+                      __global Constraint4* gConstraints,
+                      __global int* gN,
+                      __global int* gOffsets,
+                      __global int* batchSizes,
+                       int maxBatch1,
+                       int cellBatch,
+                       int4 nSplit
+                      )
+{
+       //__local int ldsBatchIdx[WG_SIZE+1];
+       __local int ldsCurBatch;
+       __local int ldsNextBatch;
+       __local int ldsStart;
+
+       int lIdx = GET_LOCAL_IDX;
+       int wgIdx = GET_GROUP_IDX;
+
+//     int gIdx = GET_GLOBAL_IDX;
+//     debugInfo[gIdx].m_valInt0 = gIdx;
+       //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;
+
+
+       int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);
+       int remain= (wgIdx%((nSplit.x*nSplit.y)/4));
+       int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);
+       int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);
+       int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);
+
+       
+       if( gN[cellIdx] == 0 ) 
+               return;
+
+       int maxBatch = batchSizes[cellIdx];
+
+       const int start = gOffsets[cellIdx];
+       const int end = start + gN[cellIdx];
+
+       
+       if( lIdx == 0 )
+       {
+               ldsCurBatch = 0;
+               ldsNextBatch = 0;
+               ldsStart = start;
+       }
+
+
+       GROUP_LDS_BARRIER;
+
+       int idx=ldsStart+lIdx;
+       while (ldsCurBatch < maxBatch)
+       {
+               for(; idx<end; )
+               {
+                       if (gConstraints[idx].m_batchIdx == ldsCurBatch)
+                       {
+
+                                       solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );
+
+                                idx+=64;
+                       } else
+                       {
+                               break;
+                       }
+               }
+               GROUP_LDS_BARRIER;
+               if( lIdx == 0 )
+               {
+                       ldsCurBatch++;
+               }
+               GROUP_LDS_BARRIER;
+       }
+       
+    
+}
+
+
+
+
+
+
+__kernel void solveSingleFrictionKernel(__global Body* gBodies,
+                      __global Shape* gShapes,
+                      __global Constraint4* gConstraints,
+                       int cellIdx,
+                       int batchOffset,
+                       int numConstraintsInBatch
+                      )
+{
+
+       int index = get_global_id(0);
+       if (index < numConstraintsInBatch)
+       {
+               
+               int idx=batchOffset+index;
+       
+               solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );
+       }    
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solveFriction.h
new file mode 100644 (file)
index 0000000..9707cdb
--- /dev/null
@@ -0,0 +1,420 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solveFrictionCL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Takahiro Harada\n"
+       "//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+       "#ifdef cl_ext_atomic_counters_32\n"
+       "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+       "#else\n"
+       "#define counter32_t volatile global int*\n"
+       "#endif\n"
+       "typedef unsigned int u32;\n"
+       "typedef unsigned short u16;\n"
+       "typedef unsigned char u8;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GET_NUM_GROUPS get_num_groups(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define AppendInc(x, out) out = atomic_inc(x)\n"
+       "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+       "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+       "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+       "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+       "#define mymake_float4 (float4)\n"
+       "//#define make_float2 (float2)\n"
+       "//#define make_uint4 (uint4)\n"
+       "//#define make_int4 (int4)\n"
+       "//#define make_uint2 (uint2)\n"
+       "//#define make_int2 (int2)\n"
+       "#define max2 max\n"
+       "#define min2 min\n"
+       "///////////////////////////////////////\n"
+       "//     Vector\n"
+       "///////////////////////////////////////\n"
+       "__inline\n"
+       "float4 fastNormalize4(float4 v)\n"
+       "{\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "__inline\n"
+       "float4 cross3(float4 a, float4 b)\n"
+       "{\n"
+       "       return cross(a,b);\n"
+       "}\n"
+       "__inline\n"
+       "float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = mymake_float4(a.xyz,0.f);\n"
+       "       float4 b1 = mymake_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize3(const float4 a)\n"
+       "{\n"
+       "       float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
+       "       return fastNormalize4( n );\n"
+       "//     float length = sqrtf(dot3F4(a, a));\n"
+       "//     return 1.f/length * a;\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Matrix3x3\n"
+       "///////////////////////////////////////\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_row[3];\n"
+       "}Matrix3x3;\n"
+       "__inline\n"
+       "float4 mtMul1(Matrix3x3 a, float4 b);\n"
+       "__inline\n"
+       "float4 mtMul3(float4 a, Matrix3x3 b);\n"
+       "__inline\n"
+       "float4 mtMul1(Matrix3x3 a, float4 b)\n"
+       "{\n"
+       "       float4 ans;\n"
+       "       ans.x = dot3F4( a.m_row[0], b );\n"
+       "       ans.y = dot3F4( a.m_row[1], b );\n"
+       "       ans.z = dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "float4 mtMul3(float4 a, Matrix3x3 b)\n"
+       "{\n"
+       "       float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       float4 ans;\n"
+       "       ans.x = dot3F4( a, colx );\n"
+       "       ans.y = dot3F4( a, coly );\n"
+       "       ans.z = dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Quaternion\n"
+       "///////////////////////////////////////\n"
+       "typedef float4 Quaternion;\n"
+       "#define WG_SIZE 64\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_pos;\n"
+       "       Quaternion m_quat;\n"
+       "       float4 m_linVel;\n"
+       "       float4 m_angVel;\n"
+       "       u32 m_shapeIdx;\n"
+       "       float m_invMass;\n"
+       "       float m_restituitionCoeff;\n"
+       "       float m_frictionCoeff;\n"
+       "} Body;\n"
+       "typedef struct\n"
+       "{\n"
+       "       Matrix3x3 m_invInertia;\n"
+       "       Matrix3x3 m_initInvInertia;\n"
+       "} Shape;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_linear;\n"
+       "       float4 m_worldPos[4];\n"
+       "       float4 m_center;        \n"
+       "       float m_jacCoeffInv[4];\n"
+       "       float m_b[4];\n"
+       "       float m_appliedRambdaDt[4];\n"
+       "       float m_fJacCoeffInv[2];        \n"
+       "       float m_fAppliedRambdaDt[2];    \n"
+       "       u32 m_bodyA;\n"
+       "       u32 m_bodyB;\n"
+       "       int m_batchIdx;\n"
+       "       u32 m_paddings[1];\n"
+       "} Constraint4;\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_nConstraints;\n"
+       "       int m_start;\n"
+       "       int m_batchIdx;\n"
+       "       int m_nSplit;\n"
+       "//     int m_paddings[1];\n"
+       "} ConstBuffer;\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_solveFriction;\n"
+       "       int m_maxBatch; //      long batch really kills the performance\n"
+       "       int m_batchIdx;\n"
+       "       int m_nSplit;\n"
+       "//     int m_paddings[1];\n"
+       "} ConstBufferBatchSolve;\n"
+       "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
+       "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
+       "{\n"
+       "       *linear = mymake_float4(-n.xyz,0.f);\n"
+       "       *angular0 = -cross3(r0, n);\n"
+       "       *angular1 = cross3(r1, n);\n"
+       "}\n"
+       "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
+       "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
+       "{\n"
+       "       return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
+       "}\n"
+       "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+       "                                  float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
+       "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+       "                                       float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
+       "{\n"
+       "       //      linear0,1 are normlized\n"
+       "       float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
+       "       float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+       "       float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
+       "       float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+       "       return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
+       "}\n"
+       "void btPlaneSpace1 (const float4* n, float4* p, float4* q);\n"
+       " void btPlaneSpace1 (const float4* n, float4* p, float4* q)\n"
+       "{\n"
+       "  if (fabs(n[0].z) > 0.70710678f) {\n"
+       "    // choose p in y-z plane\n"
+       "    float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
+       "    float k = 1.f/sqrt(a);\n"
+       "    p[0].x = 0;\n"
+       "       p[0].y = -n[0].z*k;\n"
+       "       p[0].z = n[0].y*k;\n"
+       "    // set q = n x p\n"
+       "    q[0].x = a*k;\n"
+       "       q[0].y = -n[0].x*p[0].z;\n"
+       "       q[0].z = n[0].x*p[0].y;\n"
+       "  }\n"
+       "  else {\n"
+       "    // choose p in x-y plane\n"
+       "    float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
+       "    float k = 1.f/sqrt(a);\n"
+       "    p[0].x = -n[0].y*k;\n"
+       "       p[0].y = n[0].x*k;\n"
+       "       p[0].z = 0;\n"
+       "    // set q = n x p\n"
+       "    q[0].x = -n[0].z*p[0].y;\n"
+       "       q[0].y = n[0].z*p[0].x;\n"
+       "       q[0].z = a*k;\n"
+       "  }\n"
+       "}\n"
+       "void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
+       "void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
+       "{\n"
+       "       float frictionCoeff = ldsCs[0].m_linear.w;\n"
+       "       int aIdx = ldsCs[0].m_bodyA;\n"
+       "       int bIdx = ldsCs[0].m_bodyB;\n"
+       "       float4 posA = gBodies[aIdx].m_pos;\n"
+       "       float4 linVelA = gBodies[aIdx].m_linVel;\n"
+       "       float4 angVelA = gBodies[aIdx].m_angVel;\n"
+       "       float invMassA = gBodies[aIdx].m_invMass;\n"
+       "       Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+       "       float4 posB = gBodies[bIdx].m_pos;\n"
+       "       float4 linVelB = gBodies[bIdx].m_linVel;\n"
+       "       float4 angVelB = gBodies[bIdx].m_angVel;\n"
+       "       float invMassB = gBodies[bIdx].m_invMass;\n"
+       "       Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+       "       \n"
+       "       {\n"
+       "               float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
+       "               float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
+       "               float sum = 0;\n"
+       "               for(int j=0; j<4; j++)\n"
+       "               {\n"
+       "                       sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
+       "               }\n"
+       "               frictionCoeff = 0.7f;\n"
+       "               for(int j=0; j<4; j++)\n"
+       "               {\n"
+       "                       maxRambdaDt[j] = frictionCoeff*sum;\n"
+       "                       minRambdaDt[j] = -maxRambdaDt[j];\n"
+       "               }\n"
+       "               \n"
+       "//             solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+       "//                     posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
+       "               \n"
+       "               \n"
+       "               {\n"
+       "                       \n"
+       "                       __global Constraint4* cs = ldsCs;\n"
+       "                       \n"
+       "                       if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
+       "                       const float4 center = cs->m_center;\n"
+       "                       \n"
+       "                       float4 n = -cs->m_linear;\n"
+       "                       \n"
+       "                       float4 tangent[2];\n"
+       "                       btPlaneSpace1(&n,&tangent[0],&tangent[1]);\n"
+       "                       float4 angular0, angular1, linear;\n"
+       "                       float4 r0 = center - posA;\n"
+       "                       float4 r1 = center - posB;\n"
+       "                       for(int i=0; i<2; i++)\n"
+       "                       {\n"
+       "                               setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
+       "                               float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
+       "                                                                                       linVelA, angVelA, linVelB, angVelB );\n"
+       "                               rambdaDt *= cs->m_fJacCoeffInv[i];\n"
+       "                               \n"
+       "                               {\n"
+       "                                       float prevSum = cs->m_fAppliedRambdaDt[i];\n"
+       "                                       float updated = prevSum;\n"
+       "                                       updated += rambdaDt;\n"
+       "                                       updated = max2( updated, minRambdaDt[i] );\n"
+       "                                       updated = min2( updated, maxRambdaDt[i] );\n"
+       "                                       rambdaDt = updated - prevSum;\n"
+       "                                       cs->m_fAppliedRambdaDt[i] = updated;\n"
+       "                               }\n"
+       "                               \n"
+       "                               float4 linImp0 = invMassA*linear*rambdaDt;\n"
+       "                               float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+       "                               float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+       "                               float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+       "                               \n"
+       "                               linVelA += linImp0;\n"
+       "                               angVelA += angImp0;\n"
+       "                               linVelB += linImp1;\n"
+       "                               angVelB += angImp1;\n"
+       "                       }\n"
+       "                       {       //      angular damping for point constraint\n"
+       "                               float4 ab = normalize3( posB - posA );\n"
+       "                               float4 ac = normalize3( center - posA );\n"
+       "                               if( dot3F4( ab, ac ) > 0.95f  || (invMassA == 0.f || invMassB == 0.f))\n"
+       "                               {\n"
+       "                                       float angNA = dot3F4( n, angVelA );\n"
+       "                                       float angNB = dot3F4( n, angVelB );\n"
+       "                                       \n"
+       "                                       angVelA -= (angNA*0.1f)*n;\n"
+       "                                       angVelB -= (angNB*0.1f)*n;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "               \n"
+       "       }\n"
+       "       if (gBodies[aIdx].m_invMass)\n"
+       "       {\n"
+       "               gBodies[aIdx].m_linVel = linVelA;\n"
+       "               gBodies[aIdx].m_angVel = angVelA;\n"
+       "       } else\n"
+       "       {\n"
+       "               gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+       "               gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+       "       }\n"
+       "       if (gBodies[bIdx].m_invMass)\n"
+       "       {\n"
+       "               gBodies[bIdx].m_linVel = linVelB;\n"
+       "               gBodies[bIdx].m_angVel = angVelB;\n"
+       "       } else\n"
+       "       {\n"
+       "               gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
+       "               gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
+       "       }\n"
+       " \n"
+       "}\n"
+       "typedef struct \n"
+       "{\n"
+       "       int m_valInt0;\n"
+       "       int m_valInt1;\n"
+       "       int m_valInt2;\n"
+       "       int m_valInt3;\n"
+       "       float m_val0;\n"
+       "       float m_val1;\n"
+       "       float m_val2;\n"
+       "       float m_val3;\n"
+       "} SolverDebugInfo;\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void BatchSolveKernelFriction(__global Body* gBodies,\n"
+       "                      __global Shape* gShapes,\n"
+       "                      __global Constraint4* gConstraints,\n"
+       "                      __global int* gN,\n"
+       "                      __global int* gOffsets,\n"
+       "                      __global int* batchSizes,\n"
+       "                       int maxBatch1,\n"
+       "                       int cellBatch,\n"
+       "                       int4 nSplit\n"
+       "                      )\n"
+       "{\n"
+       "       //__local int ldsBatchIdx[WG_SIZE+1];\n"
+       "       __local int ldsCurBatch;\n"
+       "       __local int ldsNextBatch;\n"
+       "       __local int ldsStart;\n"
+       "       int lIdx = GET_LOCAL_IDX;\n"
+       "       int wgIdx = GET_GROUP_IDX;\n"
+       "//     int gIdx = GET_GLOBAL_IDX;\n"
+       "//     debugInfo[gIdx].m_valInt0 = gIdx;\n"
+       "       //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
+       "       int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);\n"
+       "       int remain= (wgIdx%((nSplit.x*nSplit.y)/4));\n"
+       "       int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);\n"
+       "       int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);\n"
+       "       int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);\n"
+       "       \n"
+       "       if( gN[cellIdx] == 0 ) \n"
+       "               return;\n"
+       "       int maxBatch = batchSizes[cellIdx];\n"
+       "       const int start = gOffsets[cellIdx];\n"
+       "       const int end = start + gN[cellIdx];\n"
+       "       \n"
+       "       if( lIdx == 0 )\n"
+       "       {\n"
+       "               ldsCurBatch = 0;\n"
+       "               ldsNextBatch = 0;\n"
+       "               ldsStart = start;\n"
+       "       }\n"
+       "       GROUP_LDS_BARRIER;\n"
+       "       int idx=ldsStart+lIdx;\n"
+       "       while (ldsCurBatch < maxBatch)\n"
+       "       {\n"
+       "               for(; idx<end; )\n"
+       "               {\n"
+       "                       if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
+       "                       {\n"
+       "                                       solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+       "                                idx+=64;\n"
+       "                       } else\n"
+       "                       {\n"
+       "                               break;\n"
+       "                       }\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "               if( lIdx == 0 )\n"
+       "               {\n"
+       "                       ldsCurBatch++;\n"
+       "               }\n"
+       "               GROUP_LDS_BARRIER;\n"
+       "       }\n"
+       "       \n"
+       "    \n"
+       "}\n"
+       "__kernel void solveSingleFrictionKernel(__global Body* gBodies,\n"
+       "                      __global Shape* gShapes,\n"
+       "                      __global Constraint4* gConstraints,\n"
+       "                       int cellIdx,\n"
+       "                       int batchOffset,\n"
+       "                       int numConstraintsInBatch\n"
+       "                      )\n"
+       "{\n"
+       "       int index = get_global_id(0);\n"
+       "       if (index < numConstraintsInBatch)\n"
+       "       {\n"
+       "               \n"
+       "               int idx=batchOffset+index;\n"
+       "       \n"
+       "               solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
+       "       }    \n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl
new file mode 100644 (file)
index 0000000..8e2de7b
--- /dev/null
@@ -0,0 +1,277 @@
+
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+#include "Bullet3Dynamics/shared/b3ConvertConstraint4.h"
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile global int*
+#endif
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+///////////////////////////////////////
+//     Vector
+///////////////////////////////////////
+__inline
+float fastDiv(float numerator, float denominator)
+{
+       return native_divide(numerator, denominator);   
+//     return numerator/denominator;   
+}
+
+__inline
+float4 fastDiv4(float4 numerator, float4 denominator)
+{
+       return native_divide(numerator, denominator);   
+}
+
+__inline
+float fastSqrtf(float f2)
+{
+       return native_sqrt(f2);
+//     return sqrt(f2);
+}
+
+__inline
+float fastRSqrt(float f2)
+{
+       return native_rsqrt(f2);
+}
+
+__inline
+float fastLength4(float4 v)
+{
+       return fast_length(v);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+       return fast_normalize(v);
+}
+
+
+__inline
+float sqrtf(float a)
+{
+//     return sqrt(a);
+       return native_sqrt(a);
+}
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+       return cross(a,b);
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = make_float4(a.xyz,0.f);
+       float4 b1 = make_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+__inline
+float length3(const float4 a)
+{
+       return sqrtf(dot3F4(a,a));
+}
+
+__inline
+float dot4(const float4 a, const float4 b)
+{
+       return dot( a, b );
+}
+
+//     for height
+__inline
+float dot3w1(const float4 point, const float4 eqn)
+{
+       return dot3F4(point,eqn) + eqn.w;
+}
+
+__inline
+float4 normalize3(const float4 a)
+{
+       float4 n = make_float4(a.x, a.y, a.z, 0.f);
+       return fastNormalize4( n );
+//     float length = sqrtf(dot3F4(a, a));
+//     return 1.f/length * a;
+}
+
+__inline
+float4 normalize4(const float4 a)
+{
+       float length = sqrtf(dot4(a, a));
+       return 1.f/length * a;
+}
+
+__inline
+float4 createEquation(const float4 a, const float4 b, const float4 c)
+{
+       float4 eqn;
+       float4 ab = b-a;
+       float4 ac = c-a;
+       eqn = normalize3( cross3(ab, ac) );
+       eqn.w = -dot3F4(eqn,a);
+       return eqn;
+}
+
+
+
+#define WG_SIZE 64
+
+
+
+
+
+
+
+typedef struct
+{
+       int m_nConstraints;
+       int m_start;
+       int m_batchIdx;
+       int m_nSplit;
+//     int m_paddings[1];
+} ConstBuffer;
+
+typedef struct
+{
+       int m_solveFriction;
+       int m_maxBatch; //      long batch really kills the performance
+       int m_batchIdx;
+       int m_nSplit;
+//     int m_paddings[1];
+} ConstBufferBatchSolve;
+
+
+
+
+
+
+typedef struct 
+{
+       int m_valInt0;
+       int m_valInt1;
+       int m_valInt2;
+       int m_valInt3;
+
+       float m_val0;
+       float m_val1;
+       float m_val2;
+       float m_val3;
+} SolverDebugInfo;
+
+
+
+
+
+
+typedef struct
+{
+       int m_nContacts;
+       float m_dt;
+       float m_positionDrift;
+       float m_positionConstraintCoeff;
+} ConstBufferCTC;
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void ContactToConstraintKernel(__global struct b3Contact4Data* gContact, __global b3RigidBodyData_t* gBodies, __global b3InertiaData_t* gShapes, __global b3ContactConstraint4_t* gConstraintOut, 
+int nContacts,
+float dt,
+float positionDrift,
+float positionConstraintCoeff
+)
+{
+       int gIdx = GET_GLOBAL_IDX;
+       
+       if( gIdx < nContacts )
+       {
+               int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
+               int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
+
+               float4 posA = gBodies[aIdx].m_pos;
+               float4 linVelA = gBodies[aIdx].m_linVel;
+               float4 angVelA = gBodies[aIdx].m_angVel;
+               float invMassA = gBodies[aIdx].m_invMass;
+               b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;
+
+               float4 posB = gBodies[bIdx].m_pos;
+               float4 linVelB = gBodies[bIdx].m_linVel;
+               float4 angVelB = gBodies[bIdx].m_angVel;
+               float invMassB = gBodies[bIdx].m_invMass;
+               b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;
+
+               b3ContactConstraint4_t cs;
+
+       setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
+                       &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,
+                       &cs );
+               
+               cs.m_batchIdx = gContact[gIdx].m_batchIdx;
+
+               gConstraintOut[gIdx] = cs;
+       }
+}
+
+
+
+
+
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup.h
new file mode 100644 (file)
index 0000000..d53db03
--- /dev/null
@@ -0,0 +1,702 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solverSetupCL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Takahiro Harada\n"
+       "#ifndef B3_CONTACT4DATA_H\n"
+       "#define B3_CONTACT4DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "typedef  struct b3Contact4Data b3Contact4Data_t;\n"
+       "struct b3Contact4Data\n"
+       "{\n"
+       "       b3Float4        m_worldPosB[4];\n"
+       "//     b3Float4        m_localPosA[4];\n"
+       "//     b3Float4        m_localPosB[4];\n"
+       "       b3Float4        m_worldNormalOnB;       //      w: m_nPoints\n"
+       "       unsigned short  m_restituitionCoeffCmp;\n"
+       "       unsigned short  m_frictionCoeffCmp;\n"
+       "       int m_batchIdx;\n"
+       "       int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+       "       int m_bodyBPtrAndSignBit;\n"
+       "       int     m_childIndexA;\n"
+       "       int     m_childIndexB;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "};\n"
+       "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+       "{\n"
+       "       return (int)contact->m_worldNormalOnB.w;\n"
+       "};\n"
+       "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+       "{\n"
+       "       contact->m_worldNormalOnB.w = (float)numPoints;\n"
+       "};\n"
+       "#endif //B3_CONTACT4DATA_H\n"
+       "#ifndef B3_CONTACT_CONSTRAINT5_H\n"
+       "#define B3_CONTACT_CONSTRAINT5_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "typedef struct b3ContactConstraint4 b3ContactConstraint4_t;\n"
+       "struct b3ContactConstraint4\n"
+       "{\n"
+       "       b3Float4 m_linear;//normal?\n"
+       "       b3Float4 m_worldPos[4];\n"
+       "       b3Float4 m_center;      //      friction\n"
+       "       float m_jacCoeffInv[4];\n"
+       "       float m_b[4];\n"
+       "       float m_appliedRambdaDt[4];\n"
+       "       float m_fJacCoeffInv[2];        //      friction\n"
+       "       float m_fAppliedRambdaDt[2];    //      friction\n"
+       "       unsigned int m_bodyA;\n"
+       "       unsigned int m_bodyB;\n"
+       "       int                     m_batchIdx;\n"
+       "       unsigned int m_paddings;\n"
+       "};\n"
+       "//inline       void setFrictionCoeff(float value) { m_linear[3] = value; }\n"
+       "inline float b3GetFrictionCoeff(b3ContactConstraint4_t* constraint) \n"
+       "{\n"
+       "       return constraint->m_linear.w; \n"
+       "}\n"
+       "#endif //B3_CONTACT_CONSTRAINT5_H\n"
+       "#ifndef B3_RIGIDBODY_DATA_H\n"
+       "#define B3_RIGIDBODY_DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#define B3_QUAT_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Quat;\n"
+       "       #define b3QuatConstArg const b3Quat\n"
+       "       \n"
+       "       \n"
+       "inline float4 b3FastNormalize4(float4 v)\n"
+       "{\n"
+       "       v = (float4)(v.xyz,0.f);\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "       \n"
+       "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+       "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+       "{\n"
+       "       b3Quat ans;\n"
+       "       ans = b3Cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+       "{\n"
+       "       b3Quat q;\n"
+       "       q=in;\n"
+       "       //return b3FastNormalize4(in);\n"
+       "       float len = native_sqrt(dot(q, q));\n"
+       "       if(len > 0.f)\n"
+       "       {\n"
+       "               q *= 1.f / len;\n"
+       "       }\n"
+       "       else\n"
+       "       {\n"
+       "               q.x = q.y = q.z = 0.f;\n"
+       "               q.w = 1.f;\n"
+       "       }\n"
+       "       return q;\n"
+       "}\n"
+       "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       b3Quat qInv = b3QuatInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+       "}\n"
+       "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg  orientation)\n"
+       "{\n"
+       "       return b3QuatRotate( orientation, point ) + (translation);\n"
+       "}\n"
+       "       \n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifndef B3_MAT3x3_H\n"
+       "#define B3_MAT3x3_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "typedef struct\n"
+       "{\n"
+       "       b3Float4 m_row[3];\n"
+       "}b3Mat3x3;\n"
+       "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+       "#define b3GetRow(m,row) (m.m_row[row])\n"
+       "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+       "{\n"
+       "       b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+       "       out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+       "       out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+       "       out.m_row[0].w = 0.f;\n"
+       "       out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+       "       out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+       "       out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+       "       out.m_row[1].w = 0.f;\n"
+       "       out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+       "       out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+       "       out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+       "       out.m_row[2].w = 0.f;\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = fabs(matIn.m_row[0]);\n"
+       "       out.m_row[1] = fabs(matIn.m_row[1]);\n"
+       "       out.m_row[2] = fabs(matIn.m_row[2]);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero();\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity();\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(0.f);\n"
+       "       m.m_row[1] = (b3Float4)(0.f);\n"
+       "       m.m_row[2] = (b3Float4)(0.f);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+       "       m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+       "       m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+       "       out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+       "       out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Mat3x3 transB;\n"
+       "       transB = mtTranspose( b );\n"
+       "       b3Mat3x3 ans;\n"
+       "       //      why this doesn't run when 0ing in the for{}\n"
+       "       a.m_row[0].w = 0.f;\n"
+       "       a.m_row[1].w = 0.f;\n"
+       "       a.m_row[2].w = 0.f;\n"
+       "       for(int i=0; i<3; i++)\n"
+       "       {\n"
+       "//     a.m_row[i].w = 0.f;\n"
+       "               ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+       "               ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+       "               ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+       "               ans.m_row[i].w = 0.f;\n"
+       "       }\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+       "{\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a.m_row[0], b );\n"
+       "       ans.y = b3Dot3F4( a.m_row[1], b );\n"
+       "       ans.z = b3Dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a, colx );\n"
+       "       ans.y = b3Dot3F4( a, coly );\n"
+       "       ans.z = b3Dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "#endif\n"
+       "#endif //B3_MAT3x3_H\n"
+       "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+       "struct b3RigidBodyData\n"
+       "{\n"
+       "       b3Float4                                m_pos;\n"
+       "       b3Quat                                  m_quat;\n"
+       "       b3Float4                                m_linVel;\n"
+       "       b3Float4                                m_angVel;\n"
+       "       int                                     m_collidableIdx;\n"
+       "       float                           m_invMass;\n"
+       "       float                           m_restituitionCoeff;\n"
+       "       float                           m_frictionCoeff;\n"
+       "};\n"
+       "typedef struct b3InertiaData b3InertiaData_t;\n"
+       "struct b3InertiaData\n"
+       "{\n"
+       "       b3Mat3x3 m_invInertiaWorld;\n"
+       "       b3Mat3x3 m_initInvInertia;\n"
+       "};\n"
+       "#endif //B3_RIGIDBODY_DATA_H\n"
+       "       \n"
+       "void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q);\n"
+       " void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q)\n"
+       "{\n"
+       "  if (b3Fabs(n.z) > 0.70710678f) {\n"
+       "    // choose p in y-z plane\n"
+       "    float a = n.y*n.y + n.z*n.z;\n"
+       "    float k = 1.f/sqrt(a);\n"
+       "    p[0].x = 0;\n"
+       "       p[0].y = -n.z*k;\n"
+       "       p[0].z = n.y*k;\n"
+       "    // set q = n x p\n"
+       "    q[0].x = a*k;\n"
+       "       q[0].y = -n.x*p[0].z;\n"
+       "       q[0].z = n.x*p[0].y;\n"
+       "  }\n"
+       "  else {\n"
+       "    // choose p in x-y plane\n"
+       "    float a = n.x*n.x + n.y*n.y;\n"
+       "    float k = 1.f/sqrt(a);\n"
+       "    p[0].x = -n.y*k;\n"
+       "       p[0].y = n.x*k;\n"
+       "       p[0].z = 0;\n"
+       "    // set q = n x p\n"
+       "    q[0].x = -n.z*p[0].y;\n"
+       "       q[0].y = n.z*p[0].x;\n"
+       "       q[0].z = a*k;\n"
+       "  }\n"
+       "}\n"
+       " \n"
+       "void setLinearAndAngular( b3Float4ConstArg n, b3Float4ConstArg r0, b3Float4ConstArg r1, b3Float4* linear, b3Float4* angular0, b3Float4* angular1)\n"
+       "{\n"
+       "       *linear = b3MakeFloat4(n.x,n.y,n.z,0.f);\n"
+       "       *angular0 = b3Cross3(r0, n);\n"
+       "       *angular1 = -b3Cross3(r1, n);\n"
+       "}\n"
+       "float calcRelVel( b3Float4ConstArg l0, b3Float4ConstArg l1, b3Float4ConstArg a0, b3Float4ConstArg a1, b3Float4ConstArg linVel0,\n"
+       "       b3Float4ConstArg angVel0, b3Float4ConstArg linVel1, b3Float4ConstArg angVel1 )\n"
+       "{\n"
+       "       return b3Dot3F4(l0, linVel0) + b3Dot3F4(a0, angVel0) + b3Dot3F4(l1, linVel1) + b3Dot3F4(a1, angVel1);\n"
+       "}\n"
+       "float calcJacCoeff(b3Float4ConstArg linear0, b3Float4ConstArg linear1, b3Float4ConstArg angular0, b3Float4ConstArg angular1,\n"
+       "                                       float invMass0, const b3Mat3x3* invInertia0, float invMass1, const b3Mat3x3* invInertia1)\n"
+       "{\n"
+       "       //      linear0,1 are normlized\n"
+       "       float jmj0 = invMass0;//b3Dot3F4(linear0, linear0)*invMass0;\n"
+       "       float jmj1 = b3Dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+       "       float jmj2 = invMass1;//b3Dot3F4(linear1, linear1)*invMass1;\n"
+       "       float jmj3 = b3Dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+       "       return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
+       "}\n"
+       "void setConstraint4( b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4ConstArg angVelA, float invMassA, b3Mat3x3ConstArg invInertiaA,\n"
+       "       b3Float4ConstArg posB, b3Float4ConstArg linVelB, b3Float4ConstArg angVelB, float invMassB, b3Mat3x3ConstArg invInertiaB, \n"
+       "       __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,\n"
+       "       b3ContactConstraint4_t* dstC )\n"
+       "{\n"
+       "       dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
+       "       dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
+       "       float dtInv = 1.f/dt;\n"
+       "       for(int ic=0; ic<4; ic++)\n"
+       "       {\n"
+       "               dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+       "       }\n"
+       "       dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
+       "       dstC->m_linear = src->m_worldNormalOnB;\n"
+       "       dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
+       "       for(int ic=0; ic<4; ic++)\n"
+       "       {\n"
+       "               b3Float4 r0 = src->m_worldPosB[ic] - posA;\n"
+       "               b3Float4 r1 = src->m_worldPosB[ic] - posB;\n"
+       "               if( ic >= src->m_worldNormalOnB.w )//npoints\n"
+       "               {\n"
+       "                       dstC->m_jacCoeffInv[ic] = 0.f;\n"
+       "                       continue;\n"
+       "               }\n"
+       "               float relVelN;\n"
+       "               {\n"
+       "                       b3Float4 linear, angular0, angular1;\n"
+       "                       setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);\n"
+       "                       dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+       "                               invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
+       "                       relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
+       "                               linVelA, angVelA, linVelB, angVelB);\n"
+       "                       float e = 0.f;//src->getRestituitionCoeff();\n"
+       "                       if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
+       "                       dstC->m_b[ic] = e*relVelN;\n"
+       "                       //float penetration = src->m_worldPosB[ic].w;\n"
+       "                       dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
+       "                       dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+       "               }\n"
+       "       }\n"
+       "       if( src->m_worldNormalOnB.w > 0 )//npoints\n"
+       "       {       //      prepare friction\n"
+       "               b3Float4 center = b3MakeFloat4(0.f,0.f,0.f,0.f);\n"
+       "               for(int i=0; i<src->m_worldNormalOnB.w; i++) \n"
+       "                       center += src->m_worldPosB[i];\n"
+       "               center /= (float)src->m_worldNormalOnB.w;\n"
+       "               b3Float4 tangent[2];\n"
+       "               b3PlaneSpace1(src->m_worldNormalOnB,&tangent[0],&tangent[1]);\n"
+       "               \n"
+       "               b3Float4 r[2];\n"
+       "               r[0] = center - posA;\n"
+       "               r[1] = center - posB;\n"
+       "               for(int i=0; i<2; i++)\n"
+       "               {\n"
+       "                       b3Float4 linear, angular0, angular1;\n"
+       "                       setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
+       "                       dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+       "                               invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
+       "                       dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
+       "               }\n"
+       "               dstC->m_center = center;\n"
+       "       }\n"
+       "       for(int i=0; i<4; i++)\n"
+       "       {\n"
+       "               if( i<src->m_worldNormalOnB.w )\n"
+       "               {\n"
+       "                       dstC->m_worldPos[i] = src->m_worldPosB[i];\n"
+       "               }\n"
+       "               else\n"
+       "               {\n"
+       "                       dstC->m_worldPos[i] = b3MakeFloat4(0.f,0.f,0.f,0.f);\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+       "#ifdef cl_ext_atomic_counters_32\n"
+       "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+       "#else\n"
+       "#define counter32_t volatile global int*\n"
+       "#endif\n"
+       "typedef unsigned int u32;\n"
+       "typedef unsigned short u16;\n"
+       "typedef unsigned char u8;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GET_NUM_GROUPS get_num_groups(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define AppendInc(x, out) out = atomic_inc(x)\n"
+       "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+       "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+       "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+       "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+       "#define make_float4 (float4)\n"
+       "#define make_float2 (float2)\n"
+       "#define make_uint4 (uint4)\n"
+       "#define make_int4 (int4)\n"
+       "#define make_uint2 (uint2)\n"
+       "#define make_int2 (int2)\n"
+       "#define max2 max\n"
+       "#define min2 min\n"
+       "///////////////////////////////////////\n"
+       "//     Vector\n"
+       "///////////////////////////////////////\n"
+       "__inline\n"
+       "float fastDiv(float numerator, float denominator)\n"
+       "{\n"
+       "       return native_divide(numerator, denominator);   \n"
+       "//     return numerator/denominator;   \n"
+       "}\n"
+       "__inline\n"
+       "float4 fastDiv4(float4 numerator, float4 denominator)\n"
+       "{\n"
+       "       return native_divide(numerator, denominator);   \n"
+       "}\n"
+       "__inline\n"
+       "float fastSqrtf(float f2)\n"
+       "{\n"
+       "       return native_sqrt(f2);\n"
+       "//     return sqrt(f2);\n"
+       "}\n"
+       "__inline\n"
+       "float fastRSqrt(float f2)\n"
+       "{\n"
+       "       return native_rsqrt(f2);\n"
+       "}\n"
+       "__inline\n"
+       "float fastLength4(float4 v)\n"
+       "{\n"
+       "       return fast_length(v);\n"
+       "}\n"
+       "__inline\n"
+       "float4 fastNormalize4(float4 v)\n"
+       "{\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "__inline\n"
+       "float sqrtf(float a)\n"
+       "{\n"
+       "//     return sqrt(a);\n"
+       "       return native_sqrt(a);\n"
+       "}\n"
+       "__inline\n"
+       "float4 cross3(float4 a, float4 b)\n"
+       "{\n"
+       "       return cross(a,b);\n"
+       "}\n"
+       "__inline\n"
+       "float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = make_float4(a.xyz,0.f);\n"
+       "       float4 b1 = make_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "float length3(const float4 a)\n"
+       "{\n"
+       "       return sqrtf(dot3F4(a,a));\n"
+       "}\n"
+       "__inline\n"
+       "float dot4(const float4 a, const float4 b)\n"
+       "{\n"
+       "       return dot( a, b );\n"
+       "}\n"
+       "//     for height\n"
+       "__inline\n"
+       "float dot3w1(const float4 point, const float4 eqn)\n"
+       "{\n"
+       "       return dot3F4(point,eqn) + eqn.w;\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize3(const float4 a)\n"
+       "{\n"
+       "       float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+       "       return fastNormalize4( n );\n"
+       "//     float length = sqrtf(dot3F4(a, a));\n"
+       "//     return 1.f/length * a;\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize4(const float4 a)\n"
+       "{\n"
+       "       float length = sqrtf(dot4(a, a));\n"
+       "       return 1.f/length * a;\n"
+       "}\n"
+       "__inline\n"
+       "float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
+       "{\n"
+       "       float4 eqn;\n"
+       "       float4 ab = b-a;\n"
+       "       float4 ac = c-a;\n"
+       "       eqn = normalize3( cross3(ab, ac) );\n"
+       "       eqn.w = -dot3F4(eqn,a);\n"
+       "       return eqn;\n"
+       "}\n"
+       "#define WG_SIZE 64\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_nConstraints;\n"
+       "       int m_start;\n"
+       "       int m_batchIdx;\n"
+       "       int m_nSplit;\n"
+       "//     int m_paddings[1];\n"
+       "} ConstBuffer;\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_solveFriction;\n"
+       "       int m_maxBatch; //      long batch really kills the performance\n"
+       "       int m_batchIdx;\n"
+       "       int m_nSplit;\n"
+       "//     int m_paddings[1];\n"
+       "} ConstBufferBatchSolve;\n"
+       " \n"
+       "typedef struct \n"
+       "{\n"
+       "       int m_valInt0;\n"
+       "       int m_valInt1;\n"
+       "       int m_valInt2;\n"
+       "       int m_valInt3;\n"
+       "       float m_val0;\n"
+       "       float m_val1;\n"
+       "       float m_val2;\n"
+       "       float m_val3;\n"
+       "} SolverDebugInfo;\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_nContacts;\n"
+       "       float m_dt;\n"
+       "       float m_positionDrift;\n"
+       "       float m_positionConstraintCoeff;\n"
+       "} ConstBufferCTC;\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void ContactToConstraintKernel(__global struct b3Contact4Data* gContact, __global b3RigidBodyData_t* gBodies, __global b3InertiaData_t* gShapes, __global b3ContactConstraint4_t* gConstraintOut, \n"
+       "int nContacts,\n"
+       "float dt,\n"
+       "float positionDrift,\n"
+       "float positionConstraintCoeff\n"
+       ")\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       \n"
+       "       if( gIdx < nContacts )\n"
+       "       {\n"
+       "               int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
+       "               int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
+       "               float4 posA = gBodies[aIdx].m_pos;\n"
+       "               float4 linVelA = gBodies[aIdx].m_linVel;\n"
+       "               float4 angVelA = gBodies[aIdx].m_angVel;\n"
+       "               float invMassA = gBodies[aIdx].m_invMass;\n"
+       "               b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;\n"
+       "               float4 posB = gBodies[bIdx].m_pos;\n"
+       "               float4 linVelB = gBodies[bIdx].m_linVel;\n"
+       "               float4 angVelB = gBodies[bIdx].m_angVel;\n"
+       "               float invMassB = gBodies[bIdx].m_invMass;\n"
+       "               b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;\n"
+       "               b3ContactConstraint4_t cs;\n"
+       "       setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
+       "                       &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,\n"
+       "                       &cs );\n"
+       "               \n"
+       "               cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
+       "               gConstraintOut[gIdx] = cs;\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl
new file mode 100644 (file)
index 0000000..3dc48d4
--- /dev/null
@@ -0,0 +1,613 @@
+/*
+Copyright (c) 2012 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Takahiro Harada
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile global int*
+#endif
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+///////////////////////////////////////
+//     Vector
+///////////////////////////////////////
+__inline
+float fastDiv(float numerator, float denominator)
+{
+       return native_divide(numerator, denominator);   
+//     return numerator/denominator;   
+}
+
+__inline
+float4 fastDiv4(float4 numerator, float4 denominator)
+{
+       return native_divide(numerator, denominator);   
+}
+
+__inline
+float fastSqrtf(float f2)
+{
+       return native_sqrt(f2);
+//     return sqrt(f2);
+}
+
+__inline
+float fastRSqrt(float f2)
+{
+       return native_rsqrt(f2);
+}
+
+__inline
+float fastLength4(float4 v)
+{
+       return fast_length(v);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+       return fast_normalize(v);
+}
+
+
+__inline
+float sqrtf(float a)
+{
+//     return sqrt(a);
+       return native_sqrt(a);
+}
+
+__inline
+float4 cross3(float4 a, float4 b)
+{
+       return cross(a,b);
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = make_float4(a.xyz,0.f);
+       float4 b1 = make_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+__inline
+float length3(const float4 a)
+{
+       return sqrtf(dot3F4(a,a));
+}
+
+__inline
+float dot4(const float4 a, const float4 b)
+{
+       return dot( a, b );
+}
+
+//     for height
+__inline
+float dot3w1(const float4 point, const float4 eqn)
+{
+       return dot3F4(point,eqn) + eqn.w;
+}
+
+__inline
+float4 normalize3(const float4 a)
+{
+       float4 n = make_float4(a.x, a.y, a.z, 0.f);
+       return fastNormalize4( n );
+//     float length = sqrtf(dot3F4(a, a));
+//     return 1.f/length * a;
+}
+
+__inline
+float4 normalize4(const float4 a)
+{
+       float length = sqrtf(dot4(a, a));
+       return 1.f/length * a;
+}
+
+__inline
+float4 createEquation(const float4 a, const float4 b, const float4 c)
+{
+       float4 eqn;
+       float4 ab = b-a;
+       float4 ac = c-a;
+       eqn = normalize3( cross3(ab, ac) );
+       eqn.w = -dot3F4(eqn,a);
+       return eqn;
+}
+
+///////////////////////////////////////
+//     Matrix3x3
+///////////////////////////////////////
+
+typedef struct
+{
+       float4 m_row[3];
+}Matrix3x3;
+
+__inline
+Matrix3x3 mtZero();
+
+__inline
+Matrix3x3 mtIdentity();
+
+__inline
+Matrix3x3 mtTranspose(Matrix3x3 m);
+
+__inline
+Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b);
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b);
+
+__inline
+Matrix3x3 mtZero()
+{
+       Matrix3x3 m;
+       m.m_row[0] = (float4)(0.f);
+       m.m_row[1] = (float4)(0.f);
+       m.m_row[2] = (float4)(0.f);
+       return m;
+}
+
+__inline
+Matrix3x3 mtIdentity()
+{
+       Matrix3x3 m;
+       m.m_row[0] = (float4)(1,0,0,0);
+       m.m_row[1] = (float4)(0,1,0,0);
+       m.m_row[2] = (float4)(0,0,1,0);
+       return m;
+}
+
+__inline
+Matrix3x3 mtTranspose(Matrix3x3 m)
+{
+       Matrix3x3 out;
+       out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
+       out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
+       out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
+       return out;
+}
+
+__inline
+Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)
+{
+       Matrix3x3 transB;
+       transB = mtTranspose( b );
+       Matrix3x3 ans;
+       //      why this doesn't run when 0ing in the for{}
+       a.m_row[0].w = 0.f;
+       a.m_row[1].w = 0.f;
+       a.m_row[2].w = 0.f;
+       for(int i=0; i<3; i++)
+       {
+//     a.m_row[i].w = 0.f;
+               ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);
+               ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);
+               ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);
+               ans.m_row[i].w = 0.f;
+       }
+       return ans;
+}
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b)
+{
+       float4 ans;
+       ans.x = dot3F4( a.m_row[0], b );
+       ans.y = dot3F4( a.m_row[1], b );
+       ans.z = dot3F4( a.m_row[2], b );
+       ans.w = 0.f;
+       return ans;
+}
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b)
+{
+       float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+       float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+       float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+       float4 ans;
+       ans.x = dot3F4( a, colx );
+       ans.y = dot3F4( a, coly );
+       ans.z = dot3F4( a, colz );
+       return ans;
+}
+
+///////////////////////////////////////
+//     Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+       Quaternion ans;
+       ans = cross3( a, b );
+       ans += a.w*b+b.w*a;
+//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+       ans.w = a.w*b.w - dot3F4(a, b);
+       return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+       return fastNormalize4(in);
+//     in /= length( in );
+//     return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+       Quaternion qInv = qtInvert( q );
+       float4 vcpy = vec;
+       vcpy.w = 0.f;
+       float4 out = qtMul(qtMul(q,vcpy),qInv);
+       return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+       return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+       return qtRotate( qtInvert( q ), vec );
+}
+
+
+
+
+#define WG_SIZE 64
+
+typedef struct
+{
+       float4 m_pos;
+       Quaternion m_quat;
+       float4 m_linVel;
+       float4 m_angVel;
+
+       u32 m_shapeIdx;
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+} Body;
+
+typedef struct
+{
+       Matrix3x3 m_invInertia;
+       Matrix3x3 m_initInvInertia;
+} Shape;
+
+typedef struct
+{
+       float4 m_linear;
+       float4 m_worldPos[4];
+       float4 m_center;        
+       float m_jacCoeffInv[4];
+       float m_b[4];
+       float m_appliedRambdaDt[4];
+
+       float m_fJacCoeffInv[2];        
+       float m_fAppliedRambdaDt[2];    
+
+       u32 m_bodyA;
+       u32 m_bodyB;
+
+       int m_batchIdx;
+       u32 m_paddings[1];
+} Constraint4;
+
+
+
+typedef struct
+{
+       int m_nConstraints;
+       int m_start;
+       int m_batchIdx;
+       int m_nSplit;
+//     int m_paddings[1];
+} ConstBuffer;
+
+typedef struct
+{
+       int m_solveFriction;
+       int m_maxBatch; //      long batch really kills the performance
+       int m_batchIdx;
+       int m_nSplit;
+//     int m_paddings[1];
+} ConstBufferBatchSolve;
+
+
+
+
+typedef struct 
+{
+       int m_valInt0;
+       int m_valInt1;
+       int m_valInt2;
+       int m_valInt3;
+
+       float m_val0;
+       float m_val1;
+       float m_val2;
+       float m_val3;
+} SolverDebugInfo;
+
+
+
+
+//     others
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )
+{
+       int nContacts = cb.x;
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < nContacts )
+       {
+               int srcIdx = sortData[gIdx].y;
+               out[gIdx] = in[srcIdx];
+       }
+}
+
+__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SetDeterminismSortDataChildShapeB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataOut, int nContacts)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < nContacts )
+       {
+               int2 sd;
+               sd.x = contactsIn[gIdx].m_childIndexB;
+               sd.y = gIdx;
+               sortDataOut[gIdx] = sd;
+       }
+}
+
+__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SetDeterminismSortDataChildShapeA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < nContacts )
+       {
+               int2 sdIn;
+               sdIn = sortDataInOut[gIdx];
+               int2 sdOut;
+               sdOut.x = contactsIn[sdIn.y].m_childIndexA;
+               sdOut.y = sdIn.y;
+               sortDataInOut[gIdx] = sdOut;
+       }
+}
+
+__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SetDeterminismSortDataBodyA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < nContacts )
+       {
+               int2 sdIn;
+               sdIn = sortDataInOut[gIdx];
+               int2 sdOut;
+               sdOut.x = contactsIn[sdIn.y].m_bodyAPtrAndSignBit;
+               sdOut.y = sdIn.y;
+               sortDataInOut[gIdx] = sdOut;
+       }
+}
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SetDeterminismSortDataBodyB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)
+{
+       int gIdx = GET_GLOBAL_IDX;
+
+       if( gIdx < nContacts )
+       {
+               int2 sdIn;
+               sdIn = sortDataInOut[gIdx];
+               int2 sdOut;
+               sdOut.x = contactsIn[sdIn.y].m_bodyBPtrAndSignBit;
+               sdOut.y = sdIn.y;
+               sortDataInOut[gIdx] = sdOut;
+       }
+}
+
+
+
+
+typedef struct
+{
+       int m_nContacts;
+       int m_staticIdx;
+       float m_scale;
+       int m_nSplit;
+} ConstBufferSSD;
+
+
+__constant const int gridTable4x4[] = 
+{
+    0,1,17,16,
+       1,2,18,19,
+       17,18,32,3,
+       16,19,3,34
+};
+
+__constant const int gridTable8x8[] = 
+{
+         0,  2,  3, 16, 17, 18, 19,  1,
+        66, 64, 80, 67, 82, 81, 65, 83,
+       131,144,128,130,147,129,145,146,
+       208,195,194,192,193,211,210,209,
+        21, 22, 23,  5,  4,  6,  7, 20,
+        86, 85, 69, 87, 70, 68, 84, 71,
+       151,133,149,150,135,148,132,134,
+       197,27,214,213,212,199,198,196
+       
+};
+
+
+
+
+#define USE_SPATIAL_BATCHING 1
+#define USE_4x4_GRID 1
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void SetSortDataKernel(__global struct b3Contact4Data* gContact, __global Body* gBodies, __global int2* gSortDataOut, 
+int nContacts,float scale,int4 nSplit,int staticIdx)
+
+{
+       int gIdx = GET_GLOBAL_IDX;
+       
+       if( gIdx < nContacts )
+       {
+               int aPtrAndSignBit  = gContact[gIdx].m_bodyAPtrAndSignBit;
+               int bPtrAndSignBit  = gContact[gIdx].m_bodyBPtrAndSignBit;
+
+               int aIdx = abs(aPtrAndSignBit );
+               int bIdx = abs(bPtrAndSignBit);
+
+               bool aStatic = (aPtrAndSignBit<0) ||(aPtrAndSignBit==staticIdx);
+               bool bStatic = (bPtrAndSignBit<0) ||(bPtrAndSignBit==staticIdx);
+
+#if USE_SPATIAL_BATCHING               
+               int idx = (aStatic)? bIdx: aIdx;
+               float4 p = gBodies[idx].m_pos;
+               int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (nSplit.x-1);
+               int yIdx = (int)((p.y-((p.y<0.f)?1.f:0.f))*scale) & (nSplit.y-1);
+               int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (nSplit.z-1);
+               int newIndex = (xIdx+yIdx*nSplit.x+zIdx*nSplit.x*nSplit.y);
+               
+#else//USE_SPATIAL_BATCHING
+       #if USE_4x4_GRID
+               int aa = aIdx&3;
+               int bb = bIdx&3;
+               if (aStatic)
+                       aa = bb;
+               if (bStatic)
+                       bb = aa;
+
+               int gridIndex = aa + bb*4;
+               int newIndex = gridTable4x4[gridIndex];
+       #else//USE_4x4_GRID
+               int aa = aIdx&7;
+               int bb = bIdx&7;
+               if (aStatic)
+                       aa = bb;
+               if (bStatic)
+                       bb = aa;
+
+               int gridIndex = aa + bb*8;
+               int newIndex = gridTable8x8[gridIndex];
+       #endif//USE_4x4_GRID
+#endif//USE_SPATIAL_BATCHING
+
+
+               gSortDataOut[gIdx].x = newIndex;
+               gSortDataOut[gIdx].y = gIdx;
+       }
+       else
+       {
+               gSortDataOut[gIdx].x = 0xffffffff;
+       }
+}
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void CopyConstraintKernel(__global struct b3Contact4Data* gIn, __global struct b3Contact4Data* gOut, int4 cb )
+{
+       int gIdx = GET_GLOBAL_IDX;
+       if( gIdx < cb.x )
+       {
+               gOut[gIdx] = gIn[gIdx];
+       }
+}
+
+
+
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h
new file mode 100644 (file)
index 0000000..1e6e357
--- /dev/null
@@ -0,0 +1,600 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solverSetup2CL =
+       "/*\n"
+       "Copyright (c) 2012 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Takahiro Harada\n"
+       "#ifndef B3_CONTACT4DATA_H\n"
+       "#define B3_CONTACT4DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "typedef  struct b3Contact4Data b3Contact4Data_t;\n"
+       "struct b3Contact4Data\n"
+       "{\n"
+       "       b3Float4        m_worldPosB[4];\n"
+       "//     b3Float4        m_localPosA[4];\n"
+       "//     b3Float4        m_localPosB[4];\n"
+       "       b3Float4        m_worldNormalOnB;       //      w: m_nPoints\n"
+       "       unsigned short  m_restituitionCoeffCmp;\n"
+       "       unsigned short  m_frictionCoeffCmp;\n"
+       "       int m_batchIdx;\n"
+       "       int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+       "       int m_bodyBPtrAndSignBit;\n"
+       "       int     m_childIndexA;\n"
+       "       int     m_childIndexB;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "};\n"
+       "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+       "{\n"
+       "       return (int)contact->m_worldNormalOnB.w;\n"
+       "};\n"
+       "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+       "{\n"
+       "       contact->m_worldNormalOnB.w = (float)numPoints;\n"
+       "};\n"
+       "#endif //B3_CONTACT4DATA_H\n"
+       "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+       "#ifdef cl_ext_atomic_counters_32\n"
+       "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+       "#else\n"
+       "#define counter32_t volatile global int*\n"
+       "#endif\n"
+       "typedef unsigned int u32;\n"
+       "typedef unsigned short u16;\n"
+       "typedef unsigned char u8;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GET_NUM_GROUPS get_num_groups(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define AppendInc(x, out) out = atomic_inc(x)\n"
+       "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+       "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+       "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+       "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+       "#define make_float4 (float4)\n"
+       "#define make_float2 (float2)\n"
+       "#define make_uint4 (uint4)\n"
+       "#define make_int4 (int4)\n"
+       "#define make_uint2 (uint2)\n"
+       "#define make_int2 (int2)\n"
+       "#define max2 max\n"
+       "#define min2 min\n"
+       "///////////////////////////////////////\n"
+       "//     Vector\n"
+       "///////////////////////////////////////\n"
+       "__inline\n"
+       "float fastDiv(float numerator, float denominator)\n"
+       "{\n"
+       "       return native_divide(numerator, denominator);   \n"
+       "//     return numerator/denominator;   \n"
+       "}\n"
+       "__inline\n"
+       "float4 fastDiv4(float4 numerator, float4 denominator)\n"
+       "{\n"
+       "       return native_divide(numerator, denominator);   \n"
+       "}\n"
+       "__inline\n"
+       "float fastSqrtf(float f2)\n"
+       "{\n"
+       "       return native_sqrt(f2);\n"
+       "//     return sqrt(f2);\n"
+       "}\n"
+       "__inline\n"
+       "float fastRSqrt(float f2)\n"
+       "{\n"
+       "       return native_rsqrt(f2);\n"
+       "}\n"
+       "__inline\n"
+       "float fastLength4(float4 v)\n"
+       "{\n"
+       "       return fast_length(v);\n"
+       "}\n"
+       "__inline\n"
+       "float4 fastNormalize4(float4 v)\n"
+       "{\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "__inline\n"
+       "float sqrtf(float a)\n"
+       "{\n"
+       "//     return sqrt(a);\n"
+       "       return native_sqrt(a);\n"
+       "}\n"
+       "__inline\n"
+       "float4 cross3(float4 a, float4 b)\n"
+       "{\n"
+       "       return cross(a,b);\n"
+       "}\n"
+       "__inline\n"
+       "float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = make_float4(a.xyz,0.f);\n"
+       "       float4 b1 = make_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "float length3(const float4 a)\n"
+       "{\n"
+       "       return sqrtf(dot3F4(a,a));\n"
+       "}\n"
+       "__inline\n"
+       "float dot4(const float4 a, const float4 b)\n"
+       "{\n"
+       "       return dot( a, b );\n"
+       "}\n"
+       "//     for height\n"
+       "__inline\n"
+       "float dot3w1(const float4 point, const float4 eqn)\n"
+       "{\n"
+       "       return dot3F4(point,eqn) + eqn.w;\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize3(const float4 a)\n"
+       "{\n"
+       "       float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+       "       return fastNormalize4( n );\n"
+       "//     float length = sqrtf(dot3F4(a, a));\n"
+       "//     return 1.f/length * a;\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize4(const float4 a)\n"
+       "{\n"
+       "       float length = sqrtf(dot4(a, a));\n"
+       "       return 1.f/length * a;\n"
+       "}\n"
+       "__inline\n"
+       "float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
+       "{\n"
+       "       float4 eqn;\n"
+       "       float4 ab = b-a;\n"
+       "       float4 ac = c-a;\n"
+       "       eqn = normalize3( cross3(ab, ac) );\n"
+       "       eqn.w = -dot3F4(eqn,a);\n"
+       "       return eqn;\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Matrix3x3\n"
+       "///////////////////////////////////////\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_row[3];\n"
+       "}Matrix3x3;\n"
+       "__inline\n"
+       "Matrix3x3 mtZero();\n"
+       "__inline\n"
+       "Matrix3x3 mtIdentity();\n"
+       "__inline\n"
+       "Matrix3x3 mtTranspose(Matrix3x3 m);\n"
+       "__inline\n"
+       "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
+       "__inline\n"
+       "float4 mtMul1(Matrix3x3 a, float4 b);\n"
+       "__inline\n"
+       "float4 mtMul3(float4 a, Matrix3x3 b);\n"
+       "__inline\n"
+       "Matrix3x3 mtZero()\n"
+       "{\n"
+       "       Matrix3x3 m;\n"
+       "       m.m_row[0] = (float4)(0.f);\n"
+       "       m.m_row[1] = (float4)(0.f);\n"
+       "       m.m_row[2] = (float4)(0.f);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "Matrix3x3 mtIdentity()\n"
+       "{\n"
+       "       Matrix3x3 m;\n"
+       "       m.m_row[0] = (float4)(1,0,0,0);\n"
+       "       m.m_row[1] = (float4)(0,1,0,0);\n"
+       "       m.m_row[2] = (float4)(0,0,1,0);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "Matrix3x3 mtTranspose(Matrix3x3 m)\n"
+       "{\n"
+       "       Matrix3x3 out;\n"
+       "       out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+       "       out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+       "       out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
+       "{\n"
+       "       Matrix3x3 transB;\n"
+       "       transB = mtTranspose( b );\n"
+       "       Matrix3x3 ans;\n"
+       "       //      why this doesn't run when 0ing in the for{}\n"
+       "       a.m_row[0].w = 0.f;\n"
+       "       a.m_row[1].w = 0.f;\n"
+       "       a.m_row[2].w = 0.f;\n"
+       "       for(int i=0; i<3; i++)\n"
+       "       {\n"
+       "//     a.m_row[i].w = 0.f;\n"
+       "               ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
+       "               ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
+       "               ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
+       "               ans.m_row[i].w = 0.f;\n"
+       "       }\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "float4 mtMul1(Matrix3x3 a, float4 b)\n"
+       "{\n"
+       "       float4 ans;\n"
+       "       ans.x = dot3F4( a.m_row[0], b );\n"
+       "       ans.y = dot3F4( a.m_row[1], b );\n"
+       "       ans.z = dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "float4 mtMul3(float4 a, Matrix3x3 b)\n"
+       "{\n"
+       "       float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       float4 ans;\n"
+       "       ans.x = dot3F4( a, colx );\n"
+       "       ans.y = dot3F4( a, coly );\n"
+       "       ans.z = dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Quaternion\n"
+       "///////////////////////////////////////\n"
+       "typedef float4 Quaternion;\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in);\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec);\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q);\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+       "{\n"
+       "       Quaternion ans;\n"
+       "       ans = cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in)\n"
+       "{\n"
+       "       return fastNormalize4(in);\n"
+       "//     in /= length( in );\n"
+       "//     return in;\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec)\n"
+       "{\n"
+       "       Quaternion qInv = qtInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q)\n"
+       "{\n"
+       "       return (Quaternion)(-q.xyz, q.w);\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+       "{\n"
+       "       return qtRotate( qtInvert( q ), vec );\n"
+       "}\n"
+       "#define WG_SIZE 64\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_pos;\n"
+       "       Quaternion m_quat;\n"
+       "       float4 m_linVel;\n"
+       "       float4 m_angVel;\n"
+       "       u32 m_shapeIdx;\n"
+       "       float m_invMass;\n"
+       "       float m_restituitionCoeff;\n"
+       "       float m_frictionCoeff;\n"
+       "} Body;\n"
+       "typedef struct\n"
+       "{\n"
+       "       Matrix3x3 m_invInertia;\n"
+       "       Matrix3x3 m_initInvInertia;\n"
+       "} Shape;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_linear;\n"
+       "       float4 m_worldPos[4];\n"
+       "       float4 m_center;        \n"
+       "       float m_jacCoeffInv[4];\n"
+       "       float m_b[4];\n"
+       "       float m_appliedRambdaDt[4];\n"
+       "       float m_fJacCoeffInv[2];        \n"
+       "       float m_fAppliedRambdaDt[2];    \n"
+       "       u32 m_bodyA;\n"
+       "       u32 m_bodyB;\n"
+       "       int m_batchIdx;\n"
+       "       u32 m_paddings[1];\n"
+       "} Constraint4;\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_nConstraints;\n"
+       "       int m_start;\n"
+       "       int m_batchIdx;\n"
+       "       int m_nSplit;\n"
+       "//     int m_paddings[1];\n"
+       "} ConstBuffer;\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_solveFriction;\n"
+       "       int m_maxBatch; //      long batch really kills the performance\n"
+       "       int m_batchIdx;\n"
+       "       int m_nSplit;\n"
+       "//     int m_paddings[1];\n"
+       "} ConstBufferBatchSolve;\n"
+       " \n"
+       "typedef struct \n"
+       "{\n"
+       "       int m_valInt0;\n"
+       "       int m_valInt1;\n"
+       "       int m_valInt2;\n"
+       "       int m_valInt3;\n"
+       "       float m_val0;\n"
+       "       float m_val1;\n"
+       "       float m_val2;\n"
+       "       float m_val3;\n"
+       "} SolverDebugInfo;\n"
+       "//     others\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )\n"
+       "{\n"
+       "       int nContacts = cb.x;\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < nContacts )\n"
+       "       {\n"
+       "               int srcIdx = sortData[gIdx].y;\n"
+       "               out[gIdx] = in[srcIdx];\n"
+       "       }\n"
+       "}\n"
+       "__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void SetDeterminismSortDataChildShapeB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataOut, int nContacts)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < nContacts )\n"
+       "       {\n"
+       "               int2 sd;\n"
+       "               sd.x = contactsIn[gIdx].m_childIndexB;\n"
+       "               sd.y = gIdx;\n"
+       "               sortDataOut[gIdx] = sd;\n"
+       "       }\n"
+       "}\n"
+       "__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void SetDeterminismSortDataChildShapeA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < nContacts )\n"
+       "       {\n"
+       "               int2 sdIn;\n"
+       "               sdIn = sortDataInOut[gIdx];\n"
+       "               int2 sdOut;\n"
+       "               sdOut.x = contactsIn[sdIn.y].m_childIndexA;\n"
+       "               sdOut.y = sdIn.y;\n"
+       "               sortDataInOut[gIdx] = sdOut;\n"
+       "       }\n"
+       "}\n"
+       "__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void SetDeterminismSortDataBodyA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < nContacts )\n"
+       "       {\n"
+       "               int2 sdIn;\n"
+       "               sdIn = sortDataInOut[gIdx];\n"
+       "               int2 sdOut;\n"
+       "               sdOut.x = contactsIn[sdIn.y].m_bodyAPtrAndSignBit;\n"
+       "               sdOut.y = sdIn.y;\n"
+       "               sortDataInOut[gIdx] = sdOut;\n"
+       "       }\n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void SetDeterminismSortDataBodyB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < nContacts )\n"
+       "       {\n"
+       "               int2 sdIn;\n"
+       "               sdIn = sortDataInOut[gIdx];\n"
+       "               int2 sdOut;\n"
+       "               sdOut.x = contactsIn[sdIn.y].m_bodyBPtrAndSignBit;\n"
+       "               sdOut.y = sdIn.y;\n"
+       "               sortDataInOut[gIdx] = sdOut;\n"
+       "       }\n"
+       "}\n"
+       "typedef struct\n"
+       "{\n"
+       "       int m_nContacts;\n"
+       "       int m_staticIdx;\n"
+       "       float m_scale;\n"
+       "       int m_nSplit;\n"
+       "} ConstBufferSSD;\n"
+       "__constant const int gridTable4x4[] = \n"
+       "{\n"
+       "    0,1,17,16,\n"
+       "       1,2,18,19,\n"
+       "       17,18,32,3,\n"
+       "       16,19,3,34\n"
+       "};\n"
+       "__constant const int gridTable8x8[] = \n"
+       "{\n"
+       "         0,  2,  3, 16, 17, 18, 19,  1,\n"
+       "        66, 64, 80, 67, 82, 81, 65, 83,\n"
+       "       131,144,128,130,147,129,145,146,\n"
+       "       208,195,194,192,193,211,210,209,\n"
+       "        21, 22, 23,  5,  4,  6,  7, 20,\n"
+       "        86, 85, 69, 87, 70, 68, 84, 71,\n"
+       "       151,133,149,150,135,148,132,134,\n"
+       "       197,27,214,213,212,199,198,196\n"
+       "       \n"
+       "};\n"
+       "#define USE_SPATIAL_BATCHING 1\n"
+       "#define USE_4x4_GRID 1\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void SetSortDataKernel(__global struct b3Contact4Data* gContact, __global Body* gBodies, __global int2* gSortDataOut, \n"
+       "int nContacts,float scale,int4 nSplit,int staticIdx)\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       \n"
+       "       if( gIdx < nContacts )\n"
+       "       {\n"
+       "               int aPtrAndSignBit  = gContact[gIdx].m_bodyAPtrAndSignBit;\n"
+       "               int bPtrAndSignBit  = gContact[gIdx].m_bodyBPtrAndSignBit;\n"
+       "               int aIdx = abs(aPtrAndSignBit );\n"
+       "               int bIdx = abs(bPtrAndSignBit);\n"
+       "               bool aStatic = (aPtrAndSignBit<0) ||(aPtrAndSignBit==staticIdx);\n"
+       "               bool bStatic = (bPtrAndSignBit<0) ||(bPtrAndSignBit==staticIdx);\n"
+       "#if USE_SPATIAL_BATCHING               \n"
+       "               int idx = (aStatic)? bIdx: aIdx;\n"
+       "               float4 p = gBodies[idx].m_pos;\n"
+       "               int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (nSplit.x-1);\n"
+       "               int yIdx = (int)((p.y-((p.y<0.f)?1.f:0.f))*scale) & (nSplit.y-1);\n"
+       "               int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (nSplit.z-1);\n"
+       "               int newIndex = (xIdx+yIdx*nSplit.x+zIdx*nSplit.x*nSplit.y);\n"
+       "               \n"
+       "#else//USE_SPATIAL_BATCHING\n"
+       "       #if USE_4x4_GRID\n"
+       "               int aa = aIdx&3;\n"
+       "               int bb = bIdx&3;\n"
+       "               if (aStatic)\n"
+       "                       aa = bb;\n"
+       "               if (bStatic)\n"
+       "                       bb = aa;\n"
+       "               int gridIndex = aa + bb*4;\n"
+       "               int newIndex = gridTable4x4[gridIndex];\n"
+       "       #else//USE_4x4_GRID\n"
+       "               int aa = aIdx&7;\n"
+       "               int bb = bIdx&7;\n"
+       "               if (aStatic)\n"
+       "                       aa = bb;\n"
+       "               if (bStatic)\n"
+       "                       bb = aa;\n"
+       "               int gridIndex = aa + bb*8;\n"
+       "               int newIndex = gridTable8x8[gridIndex];\n"
+       "       #endif//USE_4x4_GRID\n"
+       "#endif//USE_SPATIAL_BATCHING\n"
+       "               gSortDataOut[gIdx].x = newIndex;\n"
+       "               gSortDataOut[gIdx].y = gIdx;\n"
+       "       }\n"
+       "       else\n"
+       "       {\n"
+       "               gSortDataOut[gIdx].x = 0xffffffff;\n"
+       "       }\n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void CopyConstraintKernel(__global struct b3Contact4Data* gIn, __global struct b3Contact4Data* gOut, int4 cb )\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       if( gIdx < cb.x )\n"
+       "       {\n"
+       "               gOut[gIdx] = gIn[gIdx];\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl
new file mode 100644 (file)
index 0000000..a21a08c
--- /dev/null
@@ -0,0 +1,968 @@
+/*
+Copyright (c) 2013 Advanced Micro Devices, Inc.  
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+//Originally written by Erwin Coumans
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
+
+#pragma OPENCL EXTENSION cl_amd_printf : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+
+
+#ifdef cl_ext_atomic_counters_32
+#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
+#else
+#define counter32_t volatile global int*
+#endif
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define GET_GROUP_IDX get_group_id(0)
+#define GET_LOCAL_IDX get_local_id(0)
+#define GET_GLOBAL_IDX get_global_id(0)
+#define GET_GROUP_SIZE get_local_size(0)
+#define GET_NUM_GROUPS get_num_groups(0)
+#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
+#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
+#define AtomInc(x) atom_inc(&(x))
+#define AtomInc1(x, out) out = atom_inc(&(x))
+#define AppendInc(x, out) out = atomic_inc(x)
+#define AtomAdd(x, value) atom_add(&(x), value)
+#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
+#define AtomXhg(x, value) atom_xchg ( &(x), value )
+
+
+#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
+
+#define make_float4 (float4)
+#define make_float2 (float2)
+#define make_uint4 (uint4)
+#define make_int4 (int4)
+#define make_uint2 (uint2)
+#define make_int2 (int2)
+
+
+#define max2 max
+#define min2 min
+
+
+///////////////////////////////////////
+//     Vector
+///////////////////////////////////////
+__inline
+float fastDiv(float numerator, float denominator)
+{
+       return native_divide(numerator, denominator);   
+//     return numerator/denominator;   
+}
+
+__inline
+float4 fastDiv4(float4 numerator, float4 denominator)
+{
+       return native_divide(numerator, denominator);   
+}
+
+__inline
+float fastSqrtf(float f2)
+{
+       return native_sqrt(f2);
+//     return sqrt(f2);
+}
+
+__inline
+float fastRSqrt(float f2)
+{
+       return native_rsqrt(f2);
+}
+
+__inline
+float fastLength4(float4 v)
+{
+       return fast_length(v);
+}
+
+__inline
+float4 fastNormalize4(float4 v)
+{
+       return fast_normalize(v);
+}
+
+
+__inline
+float sqrtf(float a)
+{
+//     return sqrt(a);
+       return native_sqrt(a);
+}
+
+__inline
+float4 cross3(float4 a1, float4 b1)
+{
+
+       float4  a=make_float4(a1.xyz,0.f);
+       float4  b=make_float4(b1.xyz,0.f);
+       //float4        a=a1;
+       //float4        b=b1;
+       return cross(a,b);
+}
+
+__inline
+float dot3F4(float4 a, float4 b)
+{
+       float4 a1 = make_float4(a.xyz,0.f);
+       float4 b1 = make_float4(b.xyz,0.f);
+       return dot(a1, b1);
+}
+
+__inline
+float length3(const float4 a)
+{
+       return sqrtf(dot3F4(a,a));
+}
+
+__inline
+float dot4(const float4 a, const float4 b)
+{
+       return dot( a, b );
+}
+
+//     for height
+__inline
+float dot3w1(const float4 point, const float4 eqn)
+{
+       return dot3F4(point,eqn) + eqn.w;
+}
+
+__inline
+float4 normalize3(const float4 a)
+{
+       float4 n = make_float4(a.x, a.y, a.z, 0.f);
+       return fastNormalize4( n );
+//     float length = sqrtf(dot3F4(a, a));
+//     return 1.f/length * a;
+}
+
+__inline
+float4 normalize4(const float4 a)
+{
+       float length = sqrtf(dot4(a, a));
+       return 1.f/length * a;
+}
+
+__inline
+float4 createEquation(const float4 a, const float4 b, const float4 c)
+{
+       float4 eqn;
+       float4 ab = b-a;
+       float4 ac = c-a;
+       eqn = normalize3( cross3(ab, ac) );
+       eqn.w = -dot3F4(eqn,a);
+       return eqn;
+}
+
+///////////////////////////////////////
+//     Matrix3x3
+///////////////////////////////////////
+
+typedef struct
+{
+       float4 m_row[3];
+}Matrix3x3;
+
+__inline
+Matrix3x3 mtZero();
+
+__inline
+Matrix3x3 mtIdentity();
+
+__inline
+Matrix3x3 mtTranspose(Matrix3x3 m);
+
+__inline
+Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b);
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b);
+
+__inline
+Matrix3x3 mtZero()
+{
+       Matrix3x3 m;
+       m.m_row[0] = (float4)(0.f);
+       m.m_row[1] = (float4)(0.f);
+       m.m_row[2] = (float4)(0.f);
+       return m;
+}
+
+__inline
+Matrix3x3 mtIdentity()
+{
+       Matrix3x3 m;
+       m.m_row[0] = (float4)(1,0,0,0);
+       m.m_row[1] = (float4)(0,1,0,0);
+       m.m_row[2] = (float4)(0,0,1,0);
+       return m;
+}
+
+__inline
+Matrix3x3 mtTranspose(Matrix3x3 m)
+{
+       Matrix3x3 out;
+       out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
+       out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
+       out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
+       return out;
+}
+
+__inline
+Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)
+{
+       Matrix3x3 transB;
+       transB = mtTranspose( b );
+       Matrix3x3 ans;
+       //      why this doesn't run when 0ing in the for{}
+       a.m_row[0].w = 0.f;
+       a.m_row[1].w = 0.f;
+       a.m_row[2].w = 0.f;
+       for(int i=0; i<3; i++)
+       {
+//     a.m_row[i].w = 0.f;
+               ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);
+               ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);
+               ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);
+               ans.m_row[i].w = 0.f;
+       }
+       return ans;
+}
+
+__inline
+float4 mtMul1(Matrix3x3 a, float4 b)
+{
+       float4 ans;
+       ans.x = dot3F4( a.m_row[0], b );
+       ans.y = dot3F4( a.m_row[1], b );
+       ans.z = dot3F4( a.m_row[2], b );
+       ans.w = 0.f;
+       return ans;
+}
+
+__inline
+float4 mtMul3(float4 a, Matrix3x3 b)
+{
+       float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
+       float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
+       float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
+
+       float4 ans;
+       ans.x = dot3F4( a, colx );
+       ans.y = dot3F4( a, coly );
+       ans.z = dot3F4( a, colz );
+       return ans;
+}
+
+///////////////////////////////////////
+//     Quaternion
+///////////////////////////////////////
+
+typedef float4 Quaternion;
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b);
+
+__inline
+Quaternion qtNormalize(Quaternion in);
+
+__inline
+float4 qtRotate(Quaternion q, float4 vec);
+
+__inline
+Quaternion qtInvert(Quaternion q);
+
+
+
+
+
+__inline
+Quaternion qtMul(Quaternion a, Quaternion b)
+{
+       Quaternion ans;
+       ans = cross3( a, b );
+       ans += a.w*b+b.w*a;
+//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
+       ans.w = a.w*b.w - dot3F4(a, b);
+       return ans;
+}
+
+__inline
+Quaternion qtNormalize(Quaternion in)
+{
+       return fastNormalize4(in);
+//     in /= length( in );
+//     return in;
+}
+__inline
+float4 qtRotate(Quaternion q, float4 vec)
+{
+       Quaternion qInv = qtInvert( q );
+       float4 vcpy = vec;
+       vcpy.w = 0.f;
+       float4 out = qtMul(qtMul(q,vcpy),qInv);
+       return out;
+}
+
+__inline
+Quaternion qtInvert(Quaternion q)
+{
+       return (Quaternion)(-q.xyz, q.w);
+}
+
+__inline
+float4 qtInvRotate(const Quaternion q, float4 vec)
+{
+       return qtRotate( qtInvert( q ), vec );
+}
+
+
+
+
+#define WG_SIZE 64
+
+typedef struct
+{
+       float4 m_pos;
+       Quaternion m_quat;
+       float4 m_linVel;
+       float4 m_angVel;
+
+       u32 m_shapeIdx;
+       float m_invMass;
+       float m_restituitionCoeff;
+       float m_frictionCoeff;
+} Body;
+
+
+
+typedef struct
+{
+       Matrix3x3 m_invInertia;
+       Matrix3x3 m_initInvInertia;
+} Shape;
+
+typedef struct
+{
+       float4 m_linear;
+       float4 m_worldPos[4];
+       float4 m_center;        
+       float m_jacCoeffInv[4];
+       float m_b[4];
+       float m_appliedRambdaDt[4];
+
+       float m_fJacCoeffInv[2];        
+       float m_fAppliedRambdaDt[2];    
+
+       u32 m_bodyA;
+       u32 m_bodyB;
+       int m_batchIdx;
+       u32 m_paddings;
+} Constraint4;
+
+
+
+
+
+
+__kernel void CountBodiesKernel(__global struct b3Contact4Data* manifoldPtr, __global unsigned int* bodyCount, __global int2* contactConstraintOffsets, int numContactManifolds, int fixedBodyIndex)
+{
+       int i = GET_GLOBAL_IDX;
+       
+       if( i < numContactManifolds)
+       {
+               int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;
+               bool isFixedA = (pa <0) || (pa == fixedBodyIndex);
+               int bodyIndexA = abs(pa);
+               if (!isFixedA)
+               {
+                        AtomInc1(bodyCount[bodyIndexA],contactConstraintOffsets[i].x);
+               }
+               barrier(CLK_GLOBAL_MEM_FENCE);
+               int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;
+               bool isFixedB = (pb <0) || (pb == fixedBodyIndex);
+               int bodyIndexB = abs(pb);
+               if (!isFixedB)
+               {
+                       AtomInc1(bodyCount[bodyIndexB],contactConstraintOffsets[i].y);
+               } 
+       }
+}
+
+__kernel void ClearVelocitiesKernel(__global float4* linearVelocities,__global float4* angularVelocities, int numSplitBodies)
+{
+       int i = GET_GLOBAL_IDX;
+       
+       if( i < numSplitBodies)
+       {
+               linearVelocities[i] = make_float4(0);
+               angularVelocities[i] = make_float4(0);
+       }
+}
+
+
+__kernel void AverageVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,
+__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)
+{
+       int i = GET_GLOBAL_IDX;
+       if (i<numBodies)
+       {
+               if (gBodies[i].m_invMass)
+               {
+                       int bodyOffset = offsetSplitBodies[i];
+                       int count = bodyCount[i];
+                       float factor = 1.f/((float)count);
+                       float4 averageLinVel = make_float4(0.f);
+                       float4 averageAngVel = make_float4(0.f);
+                       
+                       for (int j=0;j<count;j++)
+                       {
+                               averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
+                               averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
+                       }
+                       
+                       for (int j=0;j<count;j++)
+                       {
+                               deltaLinearVelocities[bodyOffset+j] = averageLinVel;
+                               deltaAngularVelocities[bodyOffset+j] = averageAngVel;
+                       }
+                       
+               }//bodies[i].m_invMass
+       }//i<numBodies
+}
+
+
+
+void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
+{
+       *linear = make_float4(n.xyz,0.f);
+       *angular0 = cross3(r0, n);
+       *angular1 = -cross3(r1, n);
+}
+
+
+float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
+{
+       return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
+}
+
+
+float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
+                                       float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1, float countA, float countB)
+{
+       //      linear0,1 are normlized
+       float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
+       float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
+       float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
+       float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
+       return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);
+}
+
+
+void btPlaneSpace1 (float4 n, float4* p, float4* q);
+ void btPlaneSpace1 (float4 n, float4* p, float4* q)
+{
+  if (fabs(n.z) > 0.70710678f) {
+    // choose p in y-z plane
+    float a = n.y*n.y + n.z*n.z;
+    float k = 1.f/sqrt(a);
+    p[0].x = 0;
+       p[0].y = -n.z*k;
+       p[0].z = n.y*k;
+    // set q = n x p
+    q[0].x = a*k;
+       q[0].y = -n.x*p[0].z;
+       q[0].z = n.x*p[0].y;
+  }
+  else {
+    // choose p in x-y plane
+    float a = n.x*n.x + n.y*n.y;
+    float k = 1.f/sqrt(a);
+    p[0].x = -n.y*k;
+       p[0].y = n.x*k;
+       p[0].z = 0;
+    // set q = n x p
+    q[0].x = -n.z*p[0].y;
+       q[0].y = n.z*p[0].x;
+       q[0].z = a*k;
+  }
+}
+
+
+
+
+
+void solveContact(__global Constraint4* cs,
+                       float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
+                       float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,
+                       float4* dLinVelA, float4* dAngVelA, float4* dLinVelB, float4* dAngVelB)
+{
+       float minRambdaDt = 0;
+       float maxRambdaDt = FLT_MAX;
+
+       for(int ic=0; ic<4; ic++)
+       {
+               if( cs->m_jacCoeffInv[ic] == 0.f ) continue;
+
+               float4 angular0, angular1, linear;
+               float4 r0 = cs->m_worldPos[ic] - posA;
+               float4 r1 = cs->m_worldPos[ic] - posB;
+               setLinearAndAngular( cs->m_linear, r0, r1, &linear, &angular0, &angular1 );
+       
+
+
+               float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, 
+                       *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];
+               rambdaDt *= cs->m_jacCoeffInv[ic];
+
+               
+               {
+                       float prevSum = cs->m_appliedRambdaDt[ic];
+                       float updated = prevSum;
+                       updated += rambdaDt;
+                       updated = max2( updated, minRambdaDt );
+                       updated = min2( updated, maxRambdaDt );
+                       rambdaDt = updated - prevSum;
+                       cs->m_appliedRambdaDt[ic] = updated;
+               }
+
+                       
+               float4 linImp0 = invMassA*linear*rambdaDt;
+               float4 linImp1 = invMassB*(-linear)*rambdaDt;
+               float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
+               float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
+
+               
+               if (invMassA)
+               {
+                       *dLinVelA += linImp0;
+                       *dAngVelA += angImp0;
+               }
+               if (invMassB)
+               {
+                       *dLinVelB += linImp1;
+                       *dAngVelB += angImp1;
+               }
+       }
+}
+
+
+//     solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,contactConstraintOffsets,offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
+
+
+void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs, 
+__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
+__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)
+{
+
+       //float frictionCoeff = ldsCs[0].m_linear.w;
+       int aIdx = ldsCs[0].m_bodyA;
+       int bIdx = ldsCs[0].m_bodyB;
+
+       float4 posA = gBodies[aIdx].m_pos;
+       float4 linVelA = gBodies[aIdx].m_linVel;
+       float4 angVelA = gBodies[aIdx].m_angVel;
+       float invMassA = gBodies[aIdx].m_invMass;
+       Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
+
+       float4 posB = gBodies[bIdx].m_pos;
+       float4 linVelB = gBodies[bIdx].m_linVel;
+       float4 angVelB = gBodies[bIdx].m_angVel;
+       float invMassB = gBodies[bIdx].m_invMass;
+       Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
+
+                       
+       float4 dLinVelA = make_float4(0,0,0,0);
+       float4 dAngVelA = make_float4(0,0,0,0);
+       float4 dLinVelB = make_float4(0,0,0,0);
+       float4 dAngVelB = make_float4(0,0,0,0);
+                       
+       int bodyOffsetA = offsetSplitBodies[aIdx];
+       int constraintOffsetA = contactConstraintOffsets[0].x;
+       int splitIndexA = bodyOffsetA+constraintOffsetA;
+       
+       if (invMassA)
+       {
+               dLinVelA = deltaLinearVelocities[splitIndexA];
+               dAngVelA = deltaAngularVelocities[splitIndexA];
+       }
+
+       int bodyOffsetB = offsetSplitBodies[bIdx];
+       int constraintOffsetB = contactConstraintOffsets[0].y;
+       int splitIndexB= bodyOffsetB+constraintOffsetB;
+
+       if (invMassB)
+       {
+               dLinVelB = deltaLinearVelocities[splitIndexB];
+               dAngVelB = deltaAngularVelocities[splitIndexB];
+       }
+
+       solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
+                       posB, &linVelB, &angVelB, invMassB, invInertiaB ,&dLinVelA, &dAngVelA, &dLinVelB, &dAngVelB);
+
+       if (invMassA)
+       {
+               deltaLinearVelocities[splitIndexA] = dLinVelA;
+               deltaAngularVelocities[splitIndexA] = dAngVelA;
+       } 
+       if (invMassB)
+       {
+               deltaLinearVelocities[splitIndexB] = dLinVelB;
+               deltaAngularVelocities[splitIndexB] = dAngVelB;
+       }
+
+}
+
+
+__kernel void SolveContactJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,
+__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,
+float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds
+)
+{
+       int i = GET_GLOBAL_IDX;
+       if (i<numManifolds)
+       {
+               solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
+       }
+}
+
+
+
+
+void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,
+                                                       __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
+                                                       __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)
+{
+       float frictionCoeff = 0.7f;//ldsCs[0].m_linear.w;
+       int aIdx = ldsCs[0].m_bodyA;
+       int bIdx = ldsCs[0].m_bodyB;
+
+
+       float4 posA = gBodies[aIdx].m_pos;
+       float4 linVelA = gBodies[aIdx].m_linVel;
+       float4 angVelA = gBodies[aIdx].m_angVel;
+       float invMassA = gBodies[aIdx].m_invMass;
+       Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
+
+       float4 posB = gBodies[bIdx].m_pos;
+       float4 linVelB = gBodies[bIdx].m_linVel;
+       float4 angVelB = gBodies[bIdx].m_angVel;
+       float invMassB = gBodies[bIdx].m_invMass;
+       Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
+       
+
+       float4 dLinVelA = make_float4(0,0,0,0);
+       float4 dAngVelA = make_float4(0,0,0,0);
+       float4 dLinVelB = make_float4(0,0,0,0);
+       float4 dAngVelB = make_float4(0,0,0,0);
+                       
+       int bodyOffsetA = offsetSplitBodies[aIdx];
+       int constraintOffsetA = contactConstraintOffsets[0].x;
+       int splitIndexA = bodyOffsetA+constraintOffsetA;
+       
+       if (invMassA)
+       {
+               dLinVelA = deltaLinearVelocities[splitIndexA];
+               dAngVelA = deltaAngularVelocities[splitIndexA];
+       }
+
+       int bodyOffsetB = offsetSplitBodies[bIdx];
+       int constraintOffsetB = contactConstraintOffsets[0].y;
+       int splitIndexB= bodyOffsetB+constraintOffsetB;
+
+       if (invMassB)
+       {
+               dLinVelB = deltaLinearVelocities[splitIndexB];
+               dAngVelB = deltaAngularVelocities[splitIndexB];
+       }
+
+
+
+
+       {
+               float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
+               float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
+
+               float sum = 0;
+               for(int j=0; j<4; j++)
+               {
+                       sum +=ldsCs[0].m_appliedRambdaDt[j];
+               }
+               frictionCoeff = 0.7f;
+               for(int j=0; j<4; j++)
+               {
+                       maxRambdaDt[j] = frictionCoeff*sum;
+                       minRambdaDt[j] = -maxRambdaDt[j];
+               }
+
+               
+//             solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
+//                     posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );
+               
+               
+               {
+                       
+                       __global Constraint4* cs = ldsCs;
+                       
+                       if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;
+                       const float4 center = cs->m_center;
+                       
+                       float4 n = -cs->m_linear;
+                       
+                       float4 tangent[2];
+                       btPlaneSpace1(n,&tangent[0],&tangent[1]);
+                       float4 angular0, angular1, linear;
+                       float4 r0 = center - posA;
+                       float4 r1 = center - posB;
+                       for(int i=0; i<2; i++)
+                       {
+                               setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );
+                               float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
+                                                                                       linVelA+dLinVelA, angVelA+dAngVelA, linVelB+dLinVelB, angVelB+dAngVelB );
+                               rambdaDt *= cs->m_fJacCoeffInv[i];
+                               
+                               {
+                                       float prevSum = cs->m_fAppliedRambdaDt[i];
+                                       float updated = prevSum;
+                                       updated += rambdaDt;
+                                       updated = max2( updated, minRambdaDt[i] );
+                                       updated = min2( updated, maxRambdaDt[i] );
+                                       rambdaDt = updated - prevSum;
+                                       cs->m_fAppliedRambdaDt[i] = updated;
+                               }
+                               
+                               float4 linImp0 = invMassA*linear*rambdaDt;
+                               float4 linImp1 = invMassB*(-linear)*rambdaDt;
+                               float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
+                               float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
+                               
+                               dLinVelA += linImp0;
+                               dAngVelA += angImp0;
+                               dLinVelB += linImp1;
+                               dAngVelB += angImp1;
+                       }
+                       {       //      angular damping for point constraint
+                               float4 ab = normalize3( posB - posA );
+                               float4 ac = normalize3( center - posA );
+                               if( dot3F4( ab, ac ) > 0.95f  || (invMassA == 0.f || invMassB == 0.f))
+                               {
+                                       float angNA = dot3F4( n, angVelA );
+                                       float angNB = dot3F4( n, angVelB );
+                                       
+                                       dAngVelA -= (angNA*0.1f)*n;
+                                       dAngVelB -= (angNB*0.1f)*n;
+                               }
+                       }
+               }
+
+               
+               
+       }
+
+       if (invMassA)
+       {
+               deltaLinearVelocities[splitIndexA] = dLinVelA;
+               deltaAngularVelocities[splitIndexA] = dAngVelA;
+       } 
+       if (invMassB)
+       {
+               deltaLinearVelocities[splitIndexB] = dLinVelB;
+               deltaAngularVelocities[splitIndexB] = dAngVelB;
+       }
+
+}
+
+
+__kernel void SolveFrictionJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,
+                                                                               __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
+                                                                               __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,
+                                                                               float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds
+)
+{
+       int i = GET_GLOBAL_IDX;
+       if (i<numManifolds)
+       {
+               solveFrictionConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
+       }
+}
+
+
+__kernel void UpdateBodyVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,
+                                                                       __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)
+{
+       int i = GET_GLOBAL_IDX;
+       if (i<numBodies)
+       {
+               if (gBodies[i].m_invMass)
+               {
+                       int bodyOffset = offsetSplitBodies[i];
+                       int count = bodyCount[i];
+                       if (count)
+                       {
+                               gBodies[i].m_linVel += deltaLinearVelocities[bodyOffset];
+                               gBodies[i].m_angVel += deltaAngularVelocities[bodyOffset];
+                       }
+               }
+       }
+}
+
+
+
+void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,
+       const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB, 
+       __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,float countA, float countB,
+       Constraint4* dstC )
+{
+       dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
+       dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
+
+       float dtInv = 1.f/dt;
+       for(int ic=0; ic<4; ic++)
+       {
+               dstC->m_appliedRambdaDt[ic] = 0.f;
+       }
+       dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
+
+
+       dstC->m_linear = src->m_worldNormalOnB;
+       dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );
+       for(int ic=0; ic<4; ic++)
+       {
+               float4 r0 = src->m_worldPosB[ic] - posA;
+               float4 r1 = src->m_worldPosB[ic] - posB;
+
+               if( ic >= src->m_worldNormalOnB.w )//npoints
+               {
+                       dstC->m_jacCoeffInv[ic] = 0.f;
+                       continue;
+               }
+
+               float relVelN;
+               {
+                       float4 linear, angular0, angular1;
+                       setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);
+
+                       dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
+                               invMassA, &invInertiaA, invMassB, &invInertiaB , countA, countB);
+
+                       relVelN = calcRelVel(linear, -linear, angular0, angular1,
+                               linVelA, angVelA, linVelB, angVelB);
+
+                       float e = 0.f;//src->getRestituitionCoeff();
+                       if( relVelN*relVelN < 0.004f ) e = 0.f;
+
+                       dstC->m_b[ic] = e*relVelN;
+                       //float penetration = src->m_worldPosB[ic].w;
+                       dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;
+                       dstC->m_appliedRambdaDt[ic] = 0.f;
+               }
+       }
+
+       if( src->m_worldNormalOnB.w > 0 )//npoints
+       {       //      prepare friction
+               float4 center = make_float4(0.f);
+               for(int i=0; i<src->m_worldNormalOnB.w; i++) 
+                       center += src->m_worldPosB[i];
+               center /= (float)src->m_worldNormalOnB.w;
+
+               float4 tangent[2];
+               btPlaneSpace1(-src->m_worldNormalOnB,&tangent[0],&tangent[1]);
+               
+               float4 r[2];
+               r[0] = center - posA;
+               r[1] = center - posB;
+
+               for(int i=0; i<2; i++)
+               {
+                       float4 linear, angular0, angular1;
+                       setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);
+
+                       dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
+                               invMassA, &invInertiaA, invMassB, &invInertiaB ,countA, countB);
+                       dstC->m_fAppliedRambdaDt[i] = 0.f;
+               }
+               dstC->m_center = center;
+       }
+
+       for(int i=0; i<4; i++)
+       {
+               if( i<src->m_worldNormalOnB.w )
+               {
+                       dstC->m_worldPos[i] = src->m_worldPosB[i];
+               }
+               else
+               {
+                       dstC->m_worldPos[i] = make_float4(0.f);
+               }
+       }
+}
+
+
+__kernel
+__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
+void ContactToConstraintSplitKernel(__global const struct b3Contact4Data* gContact, __global const Body* gBodies, __global const Shape* gShapes, __global Constraint4* gConstraintOut, 
+__global const unsigned int* bodyCount,
+int nContacts,
+float dt,
+float positionDrift,
+float positionConstraintCoeff
+)
+{
+       int gIdx = GET_GLOBAL_IDX;
+       
+       if( gIdx < nContacts )
+       {
+               int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
+               int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
+
+               float4 posA = gBodies[aIdx].m_pos;
+               float4 linVelA = gBodies[aIdx].m_linVel;
+               float4 angVelA = gBodies[aIdx].m_angVel;
+               float invMassA = gBodies[aIdx].m_invMass;
+               Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
+
+               float4 posB = gBodies[bIdx].m_pos;
+               float4 linVelB = gBodies[bIdx].m_linVel;
+               float4 angVelB = gBodies[bIdx].m_angVel;
+               float invMassB = gBodies[bIdx].m_invMass;
+               Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
+
+               Constraint4 cs;
+
+               float countA = invMassA != 0.f ? (float)bodyCount[aIdx] : 1;
+               float countB = invMassB != 0.f ? (float)bodyCount[bIdx] : 1;
+
+       setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
+                       &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,
+                       &cs  );
+               
+               cs.m_batchIdx = gContact[gIdx].m_batchIdx;
+
+               gConstraintOut[gIdx] = cs;
+       }
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/solverUtils.h
new file mode 100644 (file)
index 0000000..f4d98d9
--- /dev/null
@@ -0,0 +1,908 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* solverUtilsCL =
+       "/*\n"
+       "Copyright (c) 2013 Advanced Micro Devices, Inc.  \n"
+       "This software is provided 'as-is', without any express or implied warranty.\n"
+       "In no event will the authors be held liable for any damages arising from the use of this software.\n"
+       "Permission is granted to anyone to use this software for any purpose, \n"
+       "including commercial applications, and to alter it and redistribute it freely, \n"
+       "subject to the following restrictions:\n"
+       "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
+       "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
+       "3. This notice may not be removed or altered from any source distribution.\n"
+       "*/\n"
+       "//Originally written by Erwin Coumans\n"
+       "#ifndef B3_CONTACT4DATA_H\n"
+       "#define B3_CONTACT4DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "typedef  struct b3Contact4Data b3Contact4Data_t;\n"
+       "struct b3Contact4Data\n"
+       "{\n"
+       "       b3Float4        m_worldPosB[4];\n"
+       "//     b3Float4        m_localPosA[4];\n"
+       "//     b3Float4        m_localPosB[4];\n"
+       "       b3Float4        m_worldNormalOnB;       //      w: m_nPoints\n"
+       "       unsigned short  m_restituitionCoeffCmp;\n"
+       "       unsigned short  m_frictionCoeffCmp;\n"
+       "       int m_batchIdx;\n"
+       "       int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
+       "       int m_bodyBPtrAndSignBit;\n"
+       "       int     m_childIndexA;\n"
+       "       int     m_childIndexB;\n"
+       "       int m_unused1;\n"
+       "       int m_unused2;\n"
+       "};\n"
+       "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
+       "{\n"
+       "       return (int)contact->m_worldNormalOnB.w;\n"
+       "};\n"
+       "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
+       "{\n"
+       "       contact->m_worldNormalOnB.w = (float)numPoints;\n"
+       "};\n"
+       "#endif //B3_CONTACT4DATA_H\n"
+       "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
+       "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
+       "#ifdef cl_ext_atomic_counters_32\n"
+       "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
+       "#else\n"
+       "#define counter32_t volatile global int*\n"
+       "#endif\n"
+       "typedef unsigned int u32;\n"
+       "typedef unsigned short u16;\n"
+       "typedef unsigned char u8;\n"
+       "#define GET_GROUP_IDX get_group_id(0)\n"
+       "#define GET_LOCAL_IDX get_local_id(0)\n"
+       "#define GET_GLOBAL_IDX get_global_id(0)\n"
+       "#define GET_GROUP_SIZE get_local_size(0)\n"
+       "#define GET_NUM_GROUPS get_num_groups(0)\n"
+       "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
+       "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
+       "#define AtomInc(x) atom_inc(&(x))\n"
+       "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
+       "#define AppendInc(x, out) out = atomic_inc(x)\n"
+       "#define AtomAdd(x, value) atom_add(&(x), value)\n"
+       "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
+       "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
+       "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
+       "#define make_float4 (float4)\n"
+       "#define make_float2 (float2)\n"
+       "#define make_uint4 (uint4)\n"
+       "#define make_int4 (int4)\n"
+       "#define make_uint2 (uint2)\n"
+       "#define make_int2 (int2)\n"
+       "#define max2 max\n"
+       "#define min2 min\n"
+       "///////////////////////////////////////\n"
+       "//     Vector\n"
+       "///////////////////////////////////////\n"
+       "__inline\n"
+       "float fastDiv(float numerator, float denominator)\n"
+       "{\n"
+       "       return native_divide(numerator, denominator);   \n"
+       "//     return numerator/denominator;   \n"
+       "}\n"
+       "__inline\n"
+       "float4 fastDiv4(float4 numerator, float4 denominator)\n"
+       "{\n"
+       "       return native_divide(numerator, denominator);   \n"
+       "}\n"
+       "__inline\n"
+       "float fastSqrtf(float f2)\n"
+       "{\n"
+       "       return native_sqrt(f2);\n"
+       "//     return sqrt(f2);\n"
+       "}\n"
+       "__inline\n"
+       "float fastRSqrt(float f2)\n"
+       "{\n"
+       "       return native_rsqrt(f2);\n"
+       "}\n"
+       "__inline\n"
+       "float fastLength4(float4 v)\n"
+       "{\n"
+       "       return fast_length(v);\n"
+       "}\n"
+       "__inline\n"
+       "float4 fastNormalize4(float4 v)\n"
+       "{\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "__inline\n"
+       "float sqrtf(float a)\n"
+       "{\n"
+       "//     return sqrt(a);\n"
+       "       return native_sqrt(a);\n"
+       "}\n"
+       "__inline\n"
+       "float4 cross3(float4 a1, float4 b1)\n"
+       "{\n"
+       "       float4  a=make_float4(a1.xyz,0.f);\n"
+       "       float4  b=make_float4(b1.xyz,0.f);\n"
+       "       //float4        a=a1;\n"
+       "       //float4        b=b1;\n"
+       "       return cross(a,b);\n"
+       "}\n"
+       "__inline\n"
+       "float dot3F4(float4 a, float4 b)\n"
+       "{\n"
+       "       float4 a1 = make_float4(a.xyz,0.f);\n"
+       "       float4 b1 = make_float4(b.xyz,0.f);\n"
+       "       return dot(a1, b1);\n"
+       "}\n"
+       "__inline\n"
+       "float length3(const float4 a)\n"
+       "{\n"
+       "       return sqrtf(dot3F4(a,a));\n"
+       "}\n"
+       "__inline\n"
+       "float dot4(const float4 a, const float4 b)\n"
+       "{\n"
+       "       return dot( a, b );\n"
+       "}\n"
+       "//     for height\n"
+       "__inline\n"
+       "float dot3w1(const float4 point, const float4 eqn)\n"
+       "{\n"
+       "       return dot3F4(point,eqn) + eqn.w;\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize3(const float4 a)\n"
+       "{\n"
+       "       float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
+       "       return fastNormalize4( n );\n"
+       "//     float length = sqrtf(dot3F4(a, a));\n"
+       "//     return 1.f/length * a;\n"
+       "}\n"
+       "__inline\n"
+       "float4 normalize4(const float4 a)\n"
+       "{\n"
+       "       float length = sqrtf(dot4(a, a));\n"
+       "       return 1.f/length * a;\n"
+       "}\n"
+       "__inline\n"
+       "float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
+       "{\n"
+       "       float4 eqn;\n"
+       "       float4 ab = b-a;\n"
+       "       float4 ac = c-a;\n"
+       "       eqn = normalize3( cross3(ab, ac) );\n"
+       "       eqn.w = -dot3F4(eqn,a);\n"
+       "       return eqn;\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Matrix3x3\n"
+       "///////////////////////////////////////\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_row[3];\n"
+       "}Matrix3x3;\n"
+       "__inline\n"
+       "Matrix3x3 mtZero();\n"
+       "__inline\n"
+       "Matrix3x3 mtIdentity();\n"
+       "__inline\n"
+       "Matrix3x3 mtTranspose(Matrix3x3 m);\n"
+       "__inline\n"
+       "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
+       "__inline\n"
+       "float4 mtMul1(Matrix3x3 a, float4 b);\n"
+       "__inline\n"
+       "float4 mtMul3(float4 a, Matrix3x3 b);\n"
+       "__inline\n"
+       "Matrix3x3 mtZero()\n"
+       "{\n"
+       "       Matrix3x3 m;\n"
+       "       m.m_row[0] = (float4)(0.f);\n"
+       "       m.m_row[1] = (float4)(0.f);\n"
+       "       m.m_row[2] = (float4)(0.f);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "Matrix3x3 mtIdentity()\n"
+       "{\n"
+       "       Matrix3x3 m;\n"
+       "       m.m_row[0] = (float4)(1,0,0,0);\n"
+       "       m.m_row[1] = (float4)(0,1,0,0);\n"
+       "       m.m_row[2] = (float4)(0,0,1,0);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "Matrix3x3 mtTranspose(Matrix3x3 m)\n"
+       "{\n"
+       "       Matrix3x3 out;\n"
+       "       out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+       "       out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+       "       out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
+       "{\n"
+       "       Matrix3x3 transB;\n"
+       "       transB = mtTranspose( b );\n"
+       "       Matrix3x3 ans;\n"
+       "       //      why this doesn't run when 0ing in the for{}\n"
+       "       a.m_row[0].w = 0.f;\n"
+       "       a.m_row[1].w = 0.f;\n"
+       "       a.m_row[2].w = 0.f;\n"
+       "       for(int i=0; i<3; i++)\n"
+       "       {\n"
+       "//     a.m_row[i].w = 0.f;\n"
+       "               ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
+       "               ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
+       "               ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
+       "               ans.m_row[i].w = 0.f;\n"
+       "       }\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "float4 mtMul1(Matrix3x3 a, float4 b)\n"
+       "{\n"
+       "       float4 ans;\n"
+       "       ans.x = dot3F4( a.m_row[0], b );\n"
+       "       ans.y = dot3F4( a.m_row[1], b );\n"
+       "       ans.z = dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "float4 mtMul3(float4 a, Matrix3x3 b)\n"
+       "{\n"
+       "       float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       float4 ans;\n"
+       "       ans.x = dot3F4( a, colx );\n"
+       "       ans.y = dot3F4( a, coly );\n"
+       "       ans.z = dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "///////////////////////////////////////\n"
+       "//     Quaternion\n"
+       "///////////////////////////////////////\n"
+       "typedef float4 Quaternion;\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b);\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in);\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec);\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q);\n"
+       "__inline\n"
+       "Quaternion qtMul(Quaternion a, Quaternion b)\n"
+       "{\n"
+       "       Quaternion ans;\n"
+       "       ans = cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtNormalize(Quaternion in)\n"
+       "{\n"
+       "       return fastNormalize4(in);\n"
+       "//     in /= length( in );\n"
+       "//     return in;\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtRotate(Quaternion q, float4 vec)\n"
+       "{\n"
+       "       Quaternion qInv = qtInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "Quaternion qtInvert(Quaternion q)\n"
+       "{\n"
+       "       return (Quaternion)(-q.xyz, q.w);\n"
+       "}\n"
+       "__inline\n"
+       "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
+       "{\n"
+       "       return qtRotate( qtInvert( q ), vec );\n"
+       "}\n"
+       "#define WG_SIZE 64\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_pos;\n"
+       "       Quaternion m_quat;\n"
+       "       float4 m_linVel;\n"
+       "       float4 m_angVel;\n"
+       "       u32 m_shapeIdx;\n"
+       "       float m_invMass;\n"
+       "       float m_restituitionCoeff;\n"
+       "       float m_frictionCoeff;\n"
+       "} Body;\n"
+       "typedef struct\n"
+       "{\n"
+       "       Matrix3x3 m_invInertia;\n"
+       "       Matrix3x3 m_initInvInertia;\n"
+       "} Shape;\n"
+       "typedef struct\n"
+       "{\n"
+       "       float4 m_linear;\n"
+       "       float4 m_worldPos[4];\n"
+       "       float4 m_center;        \n"
+       "       float m_jacCoeffInv[4];\n"
+       "       float m_b[4];\n"
+       "       float m_appliedRambdaDt[4];\n"
+       "       float m_fJacCoeffInv[2];        \n"
+       "       float m_fAppliedRambdaDt[2];    \n"
+       "       u32 m_bodyA;\n"
+       "       u32 m_bodyB;\n"
+       "       int m_batchIdx;\n"
+       "       u32 m_paddings;\n"
+       "} Constraint4;\n"
+       "__kernel void CountBodiesKernel(__global struct b3Contact4Data* manifoldPtr, __global unsigned int* bodyCount, __global int2* contactConstraintOffsets, int numContactManifolds, int fixedBodyIndex)\n"
+       "{\n"
+       "       int i = GET_GLOBAL_IDX;\n"
+       "       \n"
+       "       if( i < numContactManifolds)\n"
+       "       {\n"
+       "               int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;\n"
+       "               bool isFixedA = (pa <0) || (pa == fixedBodyIndex);\n"
+       "               int bodyIndexA = abs(pa);\n"
+       "               if (!isFixedA)\n"
+       "               {\n"
+       "                        AtomInc1(bodyCount[bodyIndexA],contactConstraintOffsets[i].x);\n"
+       "               }\n"
+       "               barrier(CLK_GLOBAL_MEM_FENCE);\n"
+       "               int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;\n"
+       "               bool isFixedB = (pb <0) || (pb == fixedBodyIndex);\n"
+       "               int bodyIndexB = abs(pb);\n"
+       "               if (!isFixedB)\n"
+       "               {\n"
+       "                       AtomInc1(bodyCount[bodyIndexB],contactConstraintOffsets[i].y);\n"
+       "               } \n"
+       "       }\n"
+       "}\n"
+       "__kernel void ClearVelocitiesKernel(__global float4* linearVelocities,__global float4* angularVelocities, int numSplitBodies)\n"
+       "{\n"
+       "       int i = GET_GLOBAL_IDX;\n"
+       "       \n"
+       "       if( i < numSplitBodies)\n"
+       "       {\n"
+       "               linearVelocities[i] = make_float4(0);\n"
+       "               angularVelocities[i] = make_float4(0);\n"
+       "       }\n"
+       "}\n"
+       "__kernel void AverageVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
+       "__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
+       "{\n"
+       "       int i = GET_GLOBAL_IDX;\n"
+       "       if (i<numBodies)\n"
+       "       {\n"
+       "               if (gBodies[i].m_invMass)\n"
+       "               {\n"
+       "                       int bodyOffset = offsetSplitBodies[i];\n"
+       "                       int count = bodyCount[i];\n"
+       "                       float factor = 1.f/((float)count);\n"
+       "                       float4 averageLinVel = make_float4(0.f);\n"
+       "                       float4 averageAngVel = make_float4(0.f);\n"
+       "                       \n"
+       "                       for (int j=0;j<count;j++)\n"
+       "                       {\n"
+       "                               averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;\n"
+       "                               averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;\n"
+       "                       }\n"
+       "                       \n"
+       "                       for (int j=0;j<count;j++)\n"
+       "                       {\n"
+       "                               deltaLinearVelocities[bodyOffset+j] = averageLinVel;\n"
+       "                               deltaAngularVelocities[bodyOffset+j] = averageAngVel;\n"
+       "                       }\n"
+       "                       \n"
+       "               }//bodies[i].m_invMass\n"
+       "       }//i<numBodies\n"
+       "}\n"
+       "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
+       "{\n"
+       "       *linear = make_float4(n.xyz,0.f);\n"
+       "       *angular0 = cross3(r0, n);\n"
+       "       *angular1 = -cross3(r1, n);\n"
+       "}\n"
+       "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
+       "{\n"
+       "       return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
+       "}\n"
+       "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
+       "                                       float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1, float countA, float countB)\n"
+       "{\n"
+       "       //      linear0,1 are normlized\n"
+       "       float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
+       "       float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
+       "       float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
+       "       float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
+       "       return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);\n"
+       "}\n"
+       "void btPlaneSpace1 (float4 n, float4* p, float4* q);\n"
+       " void btPlaneSpace1 (float4 n, float4* p, float4* q)\n"
+       "{\n"
+       "  if (fabs(n.z) > 0.70710678f) {\n"
+       "    // choose p in y-z plane\n"
+       "    float a = n.y*n.y + n.z*n.z;\n"
+       "    float k = 1.f/sqrt(a);\n"
+       "    p[0].x = 0;\n"
+       "       p[0].y = -n.z*k;\n"
+       "       p[0].z = n.y*k;\n"
+       "    // set q = n x p\n"
+       "    q[0].x = a*k;\n"
+       "       q[0].y = -n.x*p[0].z;\n"
+       "       q[0].z = n.x*p[0].y;\n"
+       "  }\n"
+       "  else {\n"
+       "    // choose p in x-y plane\n"
+       "    float a = n.x*n.x + n.y*n.y;\n"
+       "    float k = 1.f/sqrt(a);\n"
+       "    p[0].x = -n.y*k;\n"
+       "       p[0].y = n.x*k;\n"
+       "       p[0].z = 0;\n"
+       "    // set q = n x p\n"
+       "    q[0].x = -n.z*p[0].y;\n"
+       "       q[0].y = n.z*p[0].x;\n"
+       "       q[0].z = a*k;\n"
+       "  }\n"
+       "}\n"
+       "void solveContact(__global Constraint4* cs,\n"
+       "                       float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
+       "                       float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,\n"
+       "                       float4* dLinVelA, float4* dAngVelA, float4* dLinVelB, float4* dAngVelB)\n"
+       "{\n"
+       "       float minRambdaDt = 0;\n"
+       "       float maxRambdaDt = FLT_MAX;\n"
+       "       for(int ic=0; ic<4; ic++)\n"
+       "       {\n"
+       "               if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
+       "               float4 angular0, angular1, linear;\n"
+       "               float4 r0 = cs->m_worldPos[ic] - posA;\n"
+       "               float4 r1 = cs->m_worldPos[ic] - posB;\n"
+       "               setLinearAndAngular( cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
+       "       \n"
+       "               float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
+       "                       *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];\n"
+       "               rambdaDt *= cs->m_jacCoeffInv[ic];\n"
+       "               \n"
+       "               {\n"
+       "                       float prevSum = cs->m_appliedRambdaDt[ic];\n"
+       "                       float updated = prevSum;\n"
+       "                       updated += rambdaDt;\n"
+       "                       updated = max2( updated, minRambdaDt );\n"
+       "                       updated = min2( updated, maxRambdaDt );\n"
+       "                       rambdaDt = updated - prevSum;\n"
+       "                       cs->m_appliedRambdaDt[ic] = updated;\n"
+       "               }\n"
+       "                       \n"
+       "               float4 linImp0 = invMassA*linear*rambdaDt;\n"
+       "               float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+       "               float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+       "               float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+       "               \n"
+       "               if (invMassA)\n"
+       "               {\n"
+       "                       *dLinVelA += linImp0;\n"
+       "                       *dAngVelA += angImp0;\n"
+       "               }\n"
+       "               if (invMassB)\n"
+       "               {\n"
+       "                       *dLinVelB += linImp1;\n"
+       "                       *dAngVelB += angImp1;\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "//     solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,contactConstraintOffsets,offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
+       "void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs, \n"
+       "__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
+       "__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
+       "{\n"
+       "       //float frictionCoeff = ldsCs[0].m_linear.w;\n"
+       "       int aIdx = ldsCs[0].m_bodyA;\n"
+       "       int bIdx = ldsCs[0].m_bodyB;\n"
+       "       float4 posA = gBodies[aIdx].m_pos;\n"
+       "       float4 linVelA = gBodies[aIdx].m_linVel;\n"
+       "       float4 angVelA = gBodies[aIdx].m_angVel;\n"
+       "       float invMassA = gBodies[aIdx].m_invMass;\n"
+       "       Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+       "       float4 posB = gBodies[bIdx].m_pos;\n"
+       "       float4 linVelB = gBodies[bIdx].m_linVel;\n"
+       "       float4 angVelB = gBodies[bIdx].m_angVel;\n"
+       "       float invMassB = gBodies[bIdx].m_invMass;\n"
+       "       Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+       "                       \n"
+       "       float4 dLinVelA = make_float4(0,0,0,0);\n"
+       "       float4 dAngVelA = make_float4(0,0,0,0);\n"
+       "       float4 dLinVelB = make_float4(0,0,0,0);\n"
+       "       float4 dAngVelB = make_float4(0,0,0,0);\n"
+       "                       \n"
+       "       int bodyOffsetA = offsetSplitBodies[aIdx];\n"
+       "       int constraintOffsetA = contactConstraintOffsets[0].x;\n"
+       "       int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
+       "       \n"
+       "       if (invMassA)\n"
+       "       {\n"
+       "               dLinVelA = deltaLinearVelocities[splitIndexA];\n"
+       "               dAngVelA = deltaAngularVelocities[splitIndexA];\n"
+       "       }\n"
+       "       int bodyOffsetB = offsetSplitBodies[bIdx];\n"
+       "       int constraintOffsetB = contactConstraintOffsets[0].y;\n"
+       "       int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
+       "       if (invMassB)\n"
+       "       {\n"
+       "               dLinVelB = deltaLinearVelocities[splitIndexB];\n"
+       "               dAngVelB = deltaAngularVelocities[splitIndexB];\n"
+       "       }\n"
+       "       solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+       "                       posB, &linVelB, &angVelB, invMassB, invInertiaB ,&dLinVelA, &dAngVelA, &dLinVelB, &dAngVelB);\n"
+       "       if (invMassA)\n"
+       "       {\n"
+       "               deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
+       "               deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
+       "       } \n"
+       "       if (invMassB)\n"
+       "       {\n"
+       "               deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
+       "               deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
+       "       }\n"
+       "}\n"
+       "__kernel void SolveContactJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
+       "__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
+       "float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
+       ")\n"
+       "{\n"
+       "       int i = GET_GLOBAL_IDX;\n"
+       "       if (i<numManifolds)\n"
+       "       {\n"
+       "               solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
+       "       }\n"
+       "}\n"
+       "void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,\n"
+       "                                                       __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
+       "                                                       __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
+       "{\n"
+       "       float frictionCoeff = 0.7f;//ldsCs[0].m_linear.w;\n"
+       "       int aIdx = ldsCs[0].m_bodyA;\n"
+       "       int bIdx = ldsCs[0].m_bodyB;\n"
+       "       float4 posA = gBodies[aIdx].m_pos;\n"
+       "       float4 linVelA = gBodies[aIdx].m_linVel;\n"
+       "       float4 angVelA = gBodies[aIdx].m_angVel;\n"
+       "       float invMassA = gBodies[aIdx].m_invMass;\n"
+       "       Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+       "       float4 posB = gBodies[bIdx].m_pos;\n"
+       "       float4 linVelB = gBodies[bIdx].m_linVel;\n"
+       "       float4 angVelB = gBodies[bIdx].m_angVel;\n"
+       "       float invMassB = gBodies[bIdx].m_invMass;\n"
+       "       Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+       "       \n"
+       "       float4 dLinVelA = make_float4(0,0,0,0);\n"
+       "       float4 dAngVelA = make_float4(0,0,0,0);\n"
+       "       float4 dLinVelB = make_float4(0,0,0,0);\n"
+       "       float4 dAngVelB = make_float4(0,0,0,0);\n"
+       "                       \n"
+       "       int bodyOffsetA = offsetSplitBodies[aIdx];\n"
+       "       int constraintOffsetA = contactConstraintOffsets[0].x;\n"
+       "       int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
+       "       \n"
+       "       if (invMassA)\n"
+       "       {\n"
+       "               dLinVelA = deltaLinearVelocities[splitIndexA];\n"
+       "               dAngVelA = deltaAngularVelocities[splitIndexA];\n"
+       "       }\n"
+       "       int bodyOffsetB = offsetSplitBodies[bIdx];\n"
+       "       int constraintOffsetB = contactConstraintOffsets[0].y;\n"
+       "       int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
+       "       if (invMassB)\n"
+       "       {\n"
+       "               dLinVelB = deltaLinearVelocities[splitIndexB];\n"
+       "               dAngVelB = deltaAngularVelocities[splitIndexB];\n"
+       "       }\n"
+       "       {\n"
+       "               float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
+       "               float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
+       "               float sum = 0;\n"
+       "               for(int j=0; j<4; j++)\n"
+       "               {\n"
+       "                       sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
+       "               }\n"
+       "               frictionCoeff = 0.7f;\n"
+       "               for(int j=0; j<4; j++)\n"
+       "               {\n"
+       "                       maxRambdaDt[j] = frictionCoeff*sum;\n"
+       "                       minRambdaDt[j] = -maxRambdaDt[j];\n"
+       "               }\n"
+       "               \n"
+       "//             solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
+       "//                     posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
+       "               \n"
+       "               \n"
+       "               {\n"
+       "                       \n"
+       "                       __global Constraint4* cs = ldsCs;\n"
+       "                       \n"
+       "                       if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
+       "                       const float4 center = cs->m_center;\n"
+       "                       \n"
+       "                       float4 n = -cs->m_linear;\n"
+       "                       \n"
+       "                       float4 tangent[2];\n"
+       "                       btPlaneSpace1(n,&tangent[0],&tangent[1]);\n"
+       "                       float4 angular0, angular1, linear;\n"
+       "                       float4 r0 = center - posA;\n"
+       "                       float4 r1 = center - posB;\n"
+       "                       for(int i=0; i<2; i++)\n"
+       "                       {\n"
+       "                               setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
+       "                               float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
+       "                                                                                       linVelA+dLinVelA, angVelA+dAngVelA, linVelB+dLinVelB, angVelB+dAngVelB );\n"
+       "                               rambdaDt *= cs->m_fJacCoeffInv[i];\n"
+       "                               \n"
+       "                               {\n"
+       "                                       float prevSum = cs->m_fAppliedRambdaDt[i];\n"
+       "                                       float updated = prevSum;\n"
+       "                                       updated += rambdaDt;\n"
+       "                                       updated = max2( updated, minRambdaDt[i] );\n"
+       "                                       updated = min2( updated, maxRambdaDt[i] );\n"
+       "                                       rambdaDt = updated - prevSum;\n"
+       "                                       cs->m_fAppliedRambdaDt[i] = updated;\n"
+       "                               }\n"
+       "                               \n"
+       "                               float4 linImp0 = invMassA*linear*rambdaDt;\n"
+       "                               float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
+       "                               float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
+       "                               float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
+       "                               \n"
+       "                               dLinVelA += linImp0;\n"
+       "                               dAngVelA += angImp0;\n"
+       "                               dLinVelB += linImp1;\n"
+       "                               dAngVelB += angImp1;\n"
+       "                       }\n"
+       "                       {       //      angular damping for point constraint\n"
+       "                               float4 ab = normalize3( posB - posA );\n"
+       "                               float4 ac = normalize3( center - posA );\n"
+       "                               if( dot3F4( ab, ac ) > 0.95f  || (invMassA == 0.f || invMassB == 0.f))\n"
+       "                               {\n"
+       "                                       float angNA = dot3F4( n, angVelA );\n"
+       "                                       float angNB = dot3F4( n, angVelB );\n"
+       "                                       \n"
+       "                                       dAngVelA -= (angNA*0.1f)*n;\n"
+       "                                       dAngVelB -= (angNB*0.1f)*n;\n"
+       "                               }\n"
+       "                       }\n"
+       "               }\n"
+       "               \n"
+       "               \n"
+       "       }\n"
+       "       if (invMassA)\n"
+       "       {\n"
+       "               deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
+       "               deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
+       "       } \n"
+       "       if (invMassB)\n"
+       "       {\n"
+       "               deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
+       "               deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
+       "       }\n"
+       " \n"
+       "}\n"
+       "__kernel void SolveFrictionJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
+       "                                                                               __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
+       "                                                                               __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
+       "                                                                               float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
+       ")\n"
+       "{\n"
+       "       int i = GET_GLOBAL_IDX;\n"
+       "       if (i<numManifolds)\n"
+       "       {\n"
+       "               solveFrictionConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
+       "       }\n"
+       "}\n"
+       "__kernel void UpdateBodyVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
+       "                                                                       __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
+       "{\n"
+       "       int i = GET_GLOBAL_IDX;\n"
+       "       if (i<numBodies)\n"
+       "       {\n"
+       "               if (gBodies[i].m_invMass)\n"
+       "               {\n"
+       "                       int bodyOffset = offsetSplitBodies[i];\n"
+       "                       int count = bodyCount[i];\n"
+       "                       if (count)\n"
+       "                       {\n"
+       "                               gBodies[i].m_linVel += deltaLinearVelocities[bodyOffset];\n"
+       "                               gBodies[i].m_angVel += deltaAngularVelocities[bodyOffset];\n"
+       "                       }\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,\n"
+       "       const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB, \n"
+       "       __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,float countA, float countB,\n"
+       "       Constraint4* dstC )\n"
+       "{\n"
+       "       dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
+       "       dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
+       "       float dtInv = 1.f/dt;\n"
+       "       for(int ic=0; ic<4; ic++)\n"
+       "       {\n"
+       "               dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+       "       }\n"
+       "       dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
+       "       dstC->m_linear = src->m_worldNormalOnB;\n"
+       "       dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
+       "       for(int ic=0; ic<4; ic++)\n"
+       "       {\n"
+       "               float4 r0 = src->m_worldPosB[ic] - posA;\n"
+       "               float4 r1 = src->m_worldPosB[ic] - posB;\n"
+       "               if( ic >= src->m_worldNormalOnB.w )//npoints\n"
+       "               {\n"
+       "                       dstC->m_jacCoeffInv[ic] = 0.f;\n"
+       "                       continue;\n"
+       "               }\n"
+       "               float relVelN;\n"
+       "               {\n"
+       "                       float4 linear, angular0, angular1;\n"
+       "                       setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);\n"
+       "                       dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+       "                               invMassA, &invInertiaA, invMassB, &invInertiaB , countA, countB);\n"
+       "                       relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
+       "                               linVelA, angVelA, linVelB, angVelB);\n"
+       "                       float e = 0.f;//src->getRestituitionCoeff();\n"
+       "                       if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
+       "                       dstC->m_b[ic] = e*relVelN;\n"
+       "                       //float penetration = src->m_worldPosB[ic].w;\n"
+       "                       dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
+       "                       dstC->m_appliedRambdaDt[ic] = 0.f;\n"
+       "               }\n"
+       "       }\n"
+       "       if( src->m_worldNormalOnB.w > 0 )//npoints\n"
+       "       {       //      prepare friction\n"
+       "               float4 center = make_float4(0.f);\n"
+       "               for(int i=0; i<src->m_worldNormalOnB.w; i++) \n"
+       "                       center += src->m_worldPosB[i];\n"
+       "               center /= (float)src->m_worldNormalOnB.w;\n"
+       "               float4 tangent[2];\n"
+       "               btPlaneSpace1(-src->m_worldNormalOnB,&tangent[0],&tangent[1]);\n"
+       "               \n"
+       "               float4 r[2];\n"
+       "               r[0] = center - posA;\n"
+       "               r[1] = center - posB;\n"
+       "               for(int i=0; i<2; i++)\n"
+       "               {\n"
+       "                       float4 linear, angular0, angular1;\n"
+       "                       setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
+       "                       dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
+       "                               invMassA, &invInertiaA, invMassB, &invInertiaB ,countA, countB);\n"
+       "                       dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
+       "               }\n"
+       "               dstC->m_center = center;\n"
+       "       }\n"
+       "       for(int i=0; i<4; i++)\n"
+       "       {\n"
+       "               if( i<src->m_worldNormalOnB.w )\n"
+       "               {\n"
+       "                       dstC->m_worldPos[i] = src->m_worldPosB[i];\n"
+       "               }\n"
+       "               else\n"
+       "               {\n"
+       "                       dstC->m_worldPos[i] = make_float4(0.f);\n"
+       "               }\n"
+       "       }\n"
+       "}\n"
+       "__kernel\n"
+       "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
+       "void ContactToConstraintSplitKernel(__global const struct b3Contact4Data* gContact, __global const Body* gBodies, __global const Shape* gShapes, __global Constraint4* gConstraintOut, \n"
+       "__global const unsigned int* bodyCount,\n"
+       "int nContacts,\n"
+       "float dt,\n"
+       "float positionDrift,\n"
+       "float positionConstraintCoeff\n"
+       ")\n"
+       "{\n"
+       "       int gIdx = GET_GLOBAL_IDX;\n"
+       "       \n"
+       "       if( gIdx < nContacts )\n"
+       "       {\n"
+       "               int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
+       "               int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
+       "               float4 posA = gBodies[aIdx].m_pos;\n"
+       "               float4 linVelA = gBodies[aIdx].m_linVel;\n"
+       "               float4 angVelA = gBodies[aIdx].m_angVel;\n"
+       "               float invMassA = gBodies[aIdx].m_invMass;\n"
+       "               Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
+       "               float4 posB = gBodies[bIdx].m_pos;\n"
+       "               float4 linVelB = gBodies[bIdx].m_linVel;\n"
+       "               float4 angVelB = gBodies[bIdx].m_angVel;\n"
+       "               float invMassB = gBodies[bIdx].m_invMass;\n"
+       "               Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
+       "               Constraint4 cs;\n"
+       "               float countA = invMassA != 0.f ? (float)bodyCount[aIdx] : 1;\n"
+       "               float countB = invMassB != 0.f ? (float)bodyCount[bIdx] : 1;\n"
+       "       setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
+       "                       &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,\n"
+       "                       &cs  );\n"
+       "               \n"
+       "               cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
+       "               gConstraintOut[gIdx] = cs;\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl
new file mode 100644 (file)
index 0000000..ba8ba73
--- /dev/null
@@ -0,0 +1,22 @@
+
+
+#include "Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h"
+
+
+__kernel void initializeGpuAabbsFull(  const int numNodes, __global b3RigidBodyData_t* gBodies,__global b3Collidable_t* collidables, __global b3Aabb_t* plocalShapeAABB, __global b3Aabb_t* pAABB)
+{
+       int nodeID = get_global_id(0);
+       if( nodeID < numNodes )
+       {
+               b3ComputeWorldAabb(nodeID, gBodies, collidables, plocalShapeAABB,pAABB);
+       }
+}
+
+__kernel void clearOverlappingPairsKernel(  __global int4* pairs, int numPairs)
+{
+       int pairId = get_global_id(0);
+       if( pairId< numPairs )
+       {
+               pairs[pairId].z = 0xffffffff;
+       }
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h
new file mode 100644 (file)
index 0000000..bb949b2
--- /dev/null
@@ -0,0 +1,482 @@
+//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
+static const char* updateAabbsKernelCL =
+       "#ifndef B3_UPDATE_AABBS_H\n"
+       "#define B3_UPDATE_AABBS_H\n"
+       "#ifndef B3_AABB_H\n"
+       "#define B3_AABB_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#define B3_FLOAT4_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#define B3_PLATFORM_DEFINITIONS_H\n"
+       "struct MyTest\n"
+       "{\n"
+       "       int bla;\n"
+       "};\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
+       "#define B3_LARGE_FLOAT 1e18f\n"
+       "#define B3_INFINITY 1e18f\n"
+       "#define b3Assert(a)\n"
+       "#define b3ConstArray(a) __global const a*\n"
+       "#define b3AtomicInc atomic_inc\n"
+       "#define b3AtomicAdd atomic_add\n"
+       "#define b3Fabs fabs\n"
+       "#define b3Sqrt native_sqrt\n"
+       "#define b3Sin native_sin\n"
+       "#define b3Cos native_cos\n"
+       "#define B3_STATIC\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Float4;\n"
+       "       #define b3Float4ConstArg const b3Float4\n"
+       "       #define b3MakeFloat4 (float4)\n"
+       "       float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return dot(a1, b1);\n"
+       "       }\n"
+       "       b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
+       "       {\n"
+       "               float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
+       "               float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
+       "               return cross(a1, b1);\n"
+       "       }\n"
+       "       #define b3MinFloat4 min\n"
+       "       #define b3MaxFloat4 max\n"
+       "       #define b3Normalized(a) normalize(a)\n"
+       "#endif \n"
+       "               \n"
+       "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
+       "{\n"
+       "       if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6)    \n"
+       "               return false;\n"
+       "       return true;\n"
+       "}\n"
+       "inline int    b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
+       "{\n"
+       "    float maxDot = -B3_INFINITY;\n"
+       "    int i = 0;\n"
+       "    int ptIndex = -1;\n"
+       "    for( i = 0; i < vecLen; i++ )\n"
+       "    {\n"
+       "        float dot = b3Dot3F4(vecArray[i],vec);\n"
+       "            \n"
+       "        if( dot > maxDot )\n"
+       "        {\n"
+       "            maxDot = dot;\n"
+       "            ptIndex = i;\n"
+       "        }\n"
+       "    }\n"
+       "       b3Assert(ptIndex>=0);\n"
+       "    if (ptIndex<0)\n"
+       "       {\n"
+       "               ptIndex = 0;\n"
+       "       }\n"
+       "    *dotOut = maxDot;\n"
+       "    return ptIndex;\n"
+       "}\n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_MAT3x3_H\n"
+       "#define B3_MAT3x3_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#define B3_QUAT_H\n"
+       "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif\n"
+       "#endif\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "       typedef float4  b3Quat;\n"
+       "       #define b3QuatConstArg const b3Quat\n"
+       "       \n"
+       "       \n"
+       "inline float4 b3FastNormalize4(float4 v)\n"
+       "{\n"
+       "       v = (float4)(v.xyz,0.f);\n"
+       "       return fast_normalize(v);\n"
+       "}\n"
+       "       \n"
+       "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
+       "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
+       "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
+       "{\n"
+       "       b3Quat ans;\n"
+       "       ans = b3Cross3( a, b );\n"
+       "       ans += a.w*b+b.w*a;\n"
+       "//     ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
+       "       ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
+       "       return ans;\n"
+       "}\n"
+       "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
+       "{\n"
+       "       b3Quat q;\n"
+       "       q=in;\n"
+       "       //return b3FastNormalize4(in);\n"
+       "       float len = native_sqrt(dot(q, q));\n"
+       "       if(len > 0.f)\n"
+       "       {\n"
+       "               q *= 1.f / len;\n"
+       "       }\n"
+       "       else\n"
+       "       {\n"
+       "               q.x = q.y = q.z = 0.f;\n"
+       "               q.w = 1.f;\n"
+       "       }\n"
+       "       return q;\n"
+       "}\n"
+       "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       b3Quat qInv = b3QuatInvert( q );\n"
+       "       float4 vcpy = vec;\n"
+       "       vcpy.w = 0.f;\n"
+       "       float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
+       "{\n"
+       "       return (b3Quat)(-q.xyz, q.w);\n"
+       "}\n"
+       "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
+       "{\n"
+       "       return b3QuatRotate( b3QuatInvert( q ), vec );\n"
+       "}\n"
+       "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg  orientation)\n"
+       "{\n"
+       "       return b3QuatRotate( orientation, point ) + (translation);\n"
+       "}\n"
+       "       \n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "typedef struct\n"
+       "{\n"
+       "       b3Float4 m_row[3];\n"
+       "}b3Mat3x3;\n"
+       "#define b3Mat3x3ConstArg const b3Mat3x3\n"
+       "#define b3GetRow(m,row) (m.m_row[row])\n"
+       "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
+       "{\n"
+       "       b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
+       "       out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
+       "       out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
+       "       out.m_row[0].w = 0.f;\n"
+       "       out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
+       "       out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
+       "       out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
+       "       out.m_row[1].w = 0.f;\n"
+       "       out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
+       "       out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
+       "       out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
+       "       out.m_row[2].w = 0.f;\n"
+       "       return out;\n"
+       "}\n"
+       "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = fabs(matIn.m_row[0]);\n"
+       "       out.m_row[1] = fabs(matIn.m_row[1]);\n"
+       "       out.m_row[2] = fabs(matIn.m_row[2]);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero();\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity();\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
+       "__inline\n"
+       "b3Mat3x3 mtZero()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(0.f);\n"
+       "       m.m_row[1] = (b3Float4)(0.f);\n"
+       "       m.m_row[2] = (b3Float4)(0.f);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtIdentity()\n"
+       "{\n"
+       "       b3Mat3x3 m;\n"
+       "       m.m_row[0] = (b3Float4)(1,0,0,0);\n"
+       "       m.m_row[1] = (b3Float4)(0,1,0,0);\n"
+       "       m.m_row[2] = (b3Float4)(0,0,1,0);\n"
+       "       return m;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
+       "{\n"
+       "       b3Mat3x3 out;\n"
+       "       out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
+       "       out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
+       "       out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
+       "       return out;\n"
+       "}\n"
+       "__inline\n"
+       "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Mat3x3 transB;\n"
+       "       transB = mtTranspose( b );\n"
+       "       b3Mat3x3 ans;\n"
+       "       //      why this doesn't run when 0ing in the for{}\n"
+       "       a.m_row[0].w = 0.f;\n"
+       "       a.m_row[1].w = 0.f;\n"
+       "       a.m_row[2].w = 0.f;\n"
+       "       for(int i=0; i<3; i++)\n"
+       "       {\n"
+       "//     a.m_row[i].w = 0.f;\n"
+       "               ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
+       "               ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
+       "               ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
+       "               ans.m_row[i].w = 0.f;\n"
+       "       }\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
+       "{\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a.m_row[0], b );\n"
+       "       ans.y = b3Dot3F4( a.m_row[1], b );\n"
+       "       ans.z = b3Dot3F4( a.m_row[2], b );\n"
+       "       ans.w = 0.f;\n"
+       "       return ans;\n"
+       "}\n"
+       "__inline\n"
+       "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
+       "{\n"
+       "       b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
+       "       b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
+       "       b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
+       "       b3Float4 ans;\n"
+       "       ans.x = b3Dot3F4( a, colx );\n"
+       "       ans.y = b3Dot3F4( a, coly );\n"
+       "       ans.z = b3Dot3F4( a, colz );\n"
+       "       return ans;\n"
+       "}\n"
+       "#endif\n"
+       "#endif //B3_MAT3x3_H\n"
+       "typedef struct b3Aabb b3Aabb_t;\n"
+       "struct b3Aabb\n"
+       "{\n"
+       "       union\n"
+       "       {\n"
+       "               float m_min[4];\n"
+       "               b3Float4 m_minVec;\n"
+       "               int m_minIndices[4];\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float   m_max[4];\n"
+       "               b3Float4 m_maxVec;\n"
+       "               int m_signedMaxIndices[4];\n"
+       "       };\n"
+       "};\n"
+       "inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
+       "                                               b3Float4ConstArg pos,\n"
+       "                                               b3QuatConstArg orn,\n"
+       "                                               b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
+       "{\n"
+       "               b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
+       "               localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
+       "               b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
+       "               b3Mat3x3 m;\n"
+       "               m = b3QuatGetRotationMatrix(orn);\n"
+       "               b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
+       "               b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
+       "               \n"
+       "               b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
+       "                                                                                b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
+       "                                                                                b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
+       "                                                                                0.f);\n"
+       "               *aabbMinOut = center-extent;\n"
+       "               *aabbMaxOut = center+extent;\n"
+       "}\n"
+       "/// conservative test for overlap between two aabbs\n"
+       "inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
+       "                                                               b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
+       "{\n"
+       "       bool overlap = true;\n"
+       "       overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
+       "       overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
+       "       overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
+       "       return overlap;\n"
+       "}\n"
+       "#endif //B3_AABB_H\n"
+       "#ifndef B3_COLLIDABLE_H\n"
+       "#define B3_COLLIDABLE_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "enum b3ShapeTypes\n"
+       "{\n"
+       "       SHAPE_HEIGHT_FIELD=1,\n"
+       "       SHAPE_CONVEX_HULL=3,\n"
+       "       SHAPE_PLANE=4,\n"
+       "       SHAPE_CONCAVE_TRIMESH=5,\n"
+       "       SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
+       "       SHAPE_SPHERE=7,\n"
+       "       MAX_NUM_SHAPE_TYPES,\n"
+       "};\n"
+       "typedef struct b3Collidable b3Collidable_t;\n"
+       "struct b3Collidable\n"
+       "{\n"
+       "       union {\n"
+       "               int m_numChildShapes;\n"
+       "               int m_bvhIndex;\n"
+       "       };\n"
+       "       union\n"
+       "       {\n"
+       "               float m_radius;\n"
+       "               int     m_compoundBvhIndex;\n"
+       "       };\n"
+       "       int m_shapeType;\n"
+       "       union\n"
+       "       {\n"
+       "               int m_shapeIndex;\n"
+       "               float m_height;\n"
+       "       };\n"
+       "};\n"
+       "typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
+       "struct b3GpuChildShape\n"
+       "{\n"
+       "       b3Float4        m_childPosition;\n"
+       "       b3Quat          m_childOrientation;\n"
+       "       union\n"
+       "       {\n"
+       "               int                     m_shapeIndex;//used for SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
+       "               int                     m_capsuleAxis;\n"
+       "       };\n"
+       "       union \n"
+       "       {\n"
+       "               float           m_radius;//used for childshape of SHAPE_COMPOUND_OF_SPHERES or SHAPE_COMPOUND_OF_CAPSULES\n"
+       "               int                     m_numChildShapes;//used for compound shape\n"
+       "       };\n"
+       "       union \n"
+       "       {\n"
+       "               float           m_height;//used for childshape of SHAPE_COMPOUND_OF_CAPSULES\n"
+       "               int     m_collidableShapeIndex;\n"
+       "       };\n"
+       "       int                     m_shapeType;\n"
+       "};\n"
+       "struct b3CompoundOverlappingPair\n"
+       "{\n"
+       "       int m_bodyIndexA;\n"
+       "       int m_bodyIndexB;\n"
+       "//     int     m_pairType;\n"
+       "       int m_childShapeIndexA;\n"
+       "       int m_childShapeIndexB;\n"
+       "};\n"
+       "#endif //B3_COLLIDABLE_H\n"
+       "#ifndef B3_RIGIDBODY_DATA_H\n"
+       "#define B3_RIGIDBODY_DATA_H\n"
+       "#ifndef B3_FLOAT4_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_FLOAT4_H\n"
+       "#ifndef B3_QUAT_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif \n"
+       "#endif //B3_QUAT_H\n"
+       "#ifndef B3_MAT3x3_H\n"
+       "#ifdef __cplusplus\n"
+       "#else\n"
+       "#endif\n"
+       "#endif //B3_MAT3x3_H\n"
+       "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
+       "struct b3RigidBodyData\n"
+       "{\n"
+       "       b3Float4                                m_pos;\n"
+       "       b3Quat                                  m_quat;\n"
+       "       b3Float4                                m_linVel;\n"
+       "       b3Float4                                m_angVel;\n"
+       "       int                                     m_collidableIdx;\n"
+       "       float                           m_invMass;\n"
+       "       float                           m_restituitionCoeff;\n"
+       "       float                           m_frictionCoeff;\n"
+       "};\n"
+       "typedef struct b3InertiaData b3InertiaData_t;\n"
+       "struct b3InertiaData\n"
+       "{\n"
+       "       b3Mat3x3 m_invInertiaWorld;\n"
+       "       b3Mat3x3 m_initInvInertia;\n"
+       "};\n"
+       "#endif //B3_RIGIDBODY_DATA_H\n"
+       "       \n"
+       "void b3ComputeWorldAabb(  int bodyId, __global const b3RigidBodyData_t* bodies, __global const  b3Collidable_t* collidables, __global const  b3Aabb_t* localShapeAABB, __global b3Aabb_t* worldAabbs)\n"
+       "{\n"
+       "       __global const b3RigidBodyData_t* body = &bodies[bodyId];\n"
+       "       b3Float4 position = body->m_pos;\n"
+       "       b3Quat  orientation = body->m_quat;\n"
+       "       \n"
+       "       int collidableIndex = body->m_collidableIdx;\n"
+       "       int shapeIndex = collidables[collidableIndex].m_shapeIndex;\n"
+       "               \n"
+       "       if (shapeIndex>=0)\n"
+       "       {\n"
+       "                               \n"
+       "               b3Aabb_t localAabb = localShapeAABB[collidableIndex];\n"
+       "               b3Aabb_t worldAabb;\n"
+       "               \n"
+       "               b3Float4 aabbAMinOut,aabbAMaxOut;       \n"
+       "               float margin = 0.f;\n"
+       "               b3TransformAabb2(localAabb.m_minVec,localAabb.m_maxVec,margin,position,orientation,&aabbAMinOut,&aabbAMaxOut);\n"
+       "               \n"
+       "               worldAabb.m_minVec =aabbAMinOut;\n"
+       "               worldAabb.m_minIndices[3] = bodyId;\n"
+       "               worldAabb.m_maxVec = aabbAMaxOut;\n"
+       "               worldAabb.m_signedMaxIndices[3] = body[bodyId].m_invMass==0.f? 0 : 1;\n"
+       "               worldAabbs[bodyId] = worldAabb;\n"
+       "       }\n"
+       "}\n"
+       "#endif //B3_UPDATE_AABBS_H\n"
+       "__kernel void initializeGpuAabbsFull(  const int numNodes, __global b3RigidBodyData_t* gBodies,__global b3Collidable_t* collidables, __global b3Aabb_t* plocalShapeAABB, __global b3Aabb_t* pAABB)\n"
+       "{\n"
+       "       int nodeID = get_global_id(0);\n"
+       "       if( nodeID < numNodes )\n"
+       "       {\n"
+       "               b3ComputeWorldAabb(nodeID, gBodies, collidables, plocalShapeAABB,pAABB);\n"
+       "       }\n"
+       "}\n"
+       "__kernel void clearOverlappingPairsKernel(  __global int4* pairs, int numPairs)\n"
+       "{\n"
+       "       int pairId = get_global_id(0);\n"
+       "       if( pairId< numPairs )\n"
+       "       {\n"
+       "               pairs[pairId].z = 0xffffffff;\n"
+       "       }\n"
+       "}\n";
diff --git a/dali-physics/third-party/bullet3/src/Bullet3OpenCL/premake4.lua b/dali-physics/third-party/bullet3/src/Bullet3OpenCL/premake4.lua
new file mode 100644 (file)
index 0000000..ee35fdb
--- /dev/null
@@ -0,0 +1,32 @@
+function createProject(vendor)
+       hasCL = findOpenCL(vendor)
+       
+       if (hasCL) then
+               
+               project ("Bullet3OpenCL_" .. vendor)
+       
+               initOpenCL(vendor)
+                       
+               kind "StaticLib"
+               
+        if os.is("Linux") then
+            buildoptions{"-fPIC"}
+        end
+               
+               includedirs {
+                       ".",".."
+               }
+               
+               files {
+                       "**.cpp",
+                       "**.h"
+               }
+               
+       end
+end
+
+createProject("clew")
+createProject("AMD")
+createProject("Intel")
+createProject("NVIDIA")
+createProject("Apple")
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/CMakeLists.txt b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1255766
--- /dev/null
@@ -0,0 +1,55 @@
+
+INCLUDE_DIRECTORIES(
+       ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(Bullet2FileLoader_SRCS
+       b3BulletFile.cpp
+       b3Chunk.cpp
+       b3DNA.cpp
+       b3File.cpp
+       b3Serializer.cpp
+)
+
+
+SET(Bullet2FileLoader_HDRS
+       b3BulletFile.h
+       b3Chunk.h
+       b3Common.h
+       b3Defines.h
+       b3DNA.h
+       b3File.h
+       b3Serializer.h
+       autogenerated/bullet2.h
+)
+
+ADD_LIBRARY(Bullet2FileLoader ${Bullet2FileLoader_SRCS} ${Bullet2FileLoader_HDRS})
+if (BUILD_SHARED_LIBS)
+  target_link_libraries(Bullet2FileLoader Bullet3Common)
+endif ()
+SET_TARGET_PROPERTIES(Bullet2FileLoader PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(Bullet2FileLoader PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               #FILES_MATCHING requires CMake 2.6
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet2FileLoader DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS Bullet2FileLoader
+                                       RUNTIME DESTINATION bin
+                                       LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                       ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h"  PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(Bullet2FileLoader PROPERTIES FRAMEWORK true)
+                       SET_TARGET_PROPERTIES(Bullet2FileLoader PROPERTIES PUBLIC_HEADER "${Bullet2FileLoader_HDRS}")
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h
new file mode 100644 (file)
index 0000000..eaa27df
--- /dev/null
@@ -0,0 +1,987 @@
+/* Copyright (C) 2011 Erwin Coumans & Charlie C
+*
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+// Auto generated from Bullet/Extras/HeaderGenerator/bulletGenerate.py
+#ifndef __BULLET2_H__
+#define __BULLET2_H__
+namespace Bullet3SerializeBullet2
+{
+// put an empty struct in the case
+typedef struct bInvalidHandle
+{
+       int unused;
+} bInvalidHandle;
+
+class PointerArray;
+class b3PhysicsSystem;
+class ListBase;
+class b3Vector3FloatData;
+class b3Vector3DoubleData;
+class b3Matrix3x3FloatData;
+class b3Matrix3x3DoubleData;
+class b3TransformFloatData;
+class b3TransformDoubleData;
+class b3BvhSubtreeInfoData;
+class b3OptimizedBvhNodeFloatData;
+class b3OptimizedBvhNodeDoubleData;
+class b3QuantizedBvhNodeData;
+class b3QuantizedBvhFloatData;
+class b3QuantizedBvhDoubleData;
+class b3CollisionShapeData;
+class b3StaticPlaneShapeData;
+class b3ConvexInternalShapeData;
+class b3PositionAndRadius;
+class b3MultiSphereShapeData;
+class b3IntIndexData;
+class b3ShortIntIndexData;
+class b3ShortIntIndexTripletData;
+class b3CharIndexTripletData;
+class b3MeshPartData;
+class b3StridingMeshInterfaceData;
+class b3TriangleMeshShapeData;
+class b3ScaledTriangleMeshShapeData;
+class b3CompoundShapeChildData;
+class b3CompoundShapeData;
+class b3CylinderShapeData;
+class b3CapsuleShapeData;
+class b3TriangleInfoData;
+class b3TriangleInfoMapData;
+class b3GImpactMeshShapeData;
+class b3ConvexHullShapeData;
+class b3CollisionObjectDoubleData;
+class b3CollisionObjectFloatData;
+class b3DynamicsWorldDoubleData;
+class b3DynamicsWorldFloatData;
+class b3RigidBodyFloatData;
+class b3RigidBodyDoubleData;
+class b3ConstraintInfo1;
+class b3TypedConstraintData;
+class b3Point2PointConstraintFloatData;
+class b3Point2PointConstraintDoubleData;
+class b3HingeConstraintDoubleData;
+class b3HingeConstraintFloatData;
+class b3ConeTwistConstraintData;
+class b3Generic6DofConstraintData;
+class b3Generic6DofSpringConstraintData;
+class b3SliderConstraintData;
+class b3ContactSolverInfoDoubleData;
+class b3ContactSolverInfoFloatData;
+class SoftBodyMaterialData;
+class SoftBodyNodeData;
+class SoftBodyLinkData;
+class SoftBodyFaceData;
+class SoftBodyTetraData;
+class SoftRigidAnchorData;
+class SoftBodyConfigData;
+class SoftBodyPoseData;
+class SoftBodyClusterData;
+class b3SoftBodyJointData;
+class b3SoftBodyFloatData;
+// -------------------------------------------------- //
+class PointerArray
+{
+public:
+       int m_size;
+       int m_capacity;
+       void *m_data;
+};
+
+// -------------------------------------------------- //
+class b3PhysicsSystem
+{
+public:
+       PointerArray m_collisionShapes;
+       PointerArray m_collisionObjects;
+       PointerArray m_constraints;
+};
+
+// -------------------------------------------------- //
+class ListBase
+{
+public:
+       void *first;
+       void *last;
+};
+
+// -------------------------------------------------- //
+class b3Vector3FloatData
+{
+public:
+       float m_floats[4];
+};
+
+// -------------------------------------------------- //
+class b3Vector3DoubleData
+{
+public:
+       double m_floats[4];
+};
+
+// -------------------------------------------------- //
+class b3Matrix3x3FloatData
+{
+public:
+       b3Vector3FloatData m_el[3];
+};
+
+// -------------------------------------------------- //
+class b3Matrix3x3DoubleData
+{
+public:
+       b3Vector3DoubleData m_el[3];
+};
+
+// -------------------------------------------------- //
+class b3TransformFloatData
+{
+public:
+       b3Matrix3x3FloatData m_basis;
+       b3Vector3FloatData m_origin;
+};
+
+// -------------------------------------------------- //
+class b3TransformDoubleData
+{
+public:
+       b3Matrix3x3DoubleData m_basis;
+       b3Vector3DoubleData m_origin;
+};
+
+// -------------------------------------------------- //
+class b3BvhSubtreeInfoData
+{
+public:
+       int m_rootNodeIndex;
+       int m_subtreeSize;
+       short m_quantizedAabbMin[3];
+       short m_quantizedAabbMax[3];
+};
+
+// -------------------------------------------------- //
+class b3OptimizedBvhNodeFloatData
+{
+public:
+       b3Vector3FloatData m_aabbMinOrg;
+       b3Vector3FloatData m_aabbMaxOrg;
+       int m_escapeIndex;
+       int m_subPart;
+       int m_triangleIndex;
+       char m_pad[4];
+};
+
+// -------------------------------------------------- //
+class b3OptimizedBvhNodeDoubleData
+{
+public:
+       b3Vector3DoubleData m_aabbMinOrg;
+       b3Vector3DoubleData m_aabbMaxOrg;
+       int m_escapeIndex;
+       int m_subPart;
+       int m_triangleIndex;
+       char m_pad[4];
+};
+
+// -------------------------------------------------- //
+class b3QuantizedBvhNodeData
+{
+public:
+       short m_quantizedAabbMin[3];
+       short m_quantizedAabbMax[3];
+       int m_escapeIndexOrTriangleIndex;
+};
+
+// -------------------------------------------------- //
+class b3QuantizedBvhFloatData
+{
+public:
+       b3Vector3FloatData m_bvhAabbMin;
+       b3Vector3FloatData m_bvhAabbMax;
+       b3Vector3FloatData m_bvhQuantization;
+       int m_curNodeIndex;
+       int m_useQuantization;
+       int m_numContiguousLeafNodes;
+       int m_numQuantizedContiguousNodes;
+       b3OptimizedBvhNodeFloatData *m_contiguousNodesPtr;
+       b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
+       b3BvhSubtreeInfoData *m_subTreeInfoPtr;
+       int m_traversalMode;
+       int m_numSubtreeHeaders;
+};
+
+// -------------------------------------------------- //
+class b3QuantizedBvhDoubleData
+{
+public:
+       b3Vector3DoubleData m_bvhAabbMin;
+       b3Vector3DoubleData m_bvhAabbMax;
+       b3Vector3DoubleData m_bvhQuantization;
+       int m_curNodeIndex;
+       int m_useQuantization;
+       int m_numContiguousLeafNodes;
+       int m_numQuantizedContiguousNodes;
+       b3OptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
+       b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
+       int m_traversalMode;
+       int m_numSubtreeHeaders;
+       b3BvhSubtreeInfoData *m_subTreeInfoPtr;
+};
+
+// -------------------------------------------------- //
+class b3CollisionShapeData
+{
+public:
+       char *m_name;
+       int m_shapeType;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3StaticPlaneShapeData
+{
+public:
+       b3CollisionShapeData m_collisionShapeData;
+       b3Vector3FloatData m_localScaling;
+       b3Vector3FloatData m_planeNormal;
+       float m_planeConstant;
+       char m_pad[4];
+};
+
+// -------------------------------------------------- //
+class b3ConvexInternalShapeData
+{
+public:
+       b3CollisionShapeData m_collisionShapeData;
+       b3Vector3FloatData m_localScaling;
+       b3Vector3FloatData m_implicitShapeDimensions;
+       float m_collisionMargin;
+       int m_padding;
+};
+
+// -------------------------------------------------- //
+class b3PositionAndRadius
+{
+public:
+       b3Vector3FloatData m_pos;
+       float m_radius;
+};
+
+// -------------------------------------------------- //
+class b3MultiSphereShapeData
+{
+public:
+       b3ConvexInternalShapeData m_convexInternalShapeData;
+       b3PositionAndRadius *m_localPositionArrayPtr;
+       int m_localPositionArraySize;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3IntIndexData
+{
+public:
+       int m_value;
+};
+
+// -------------------------------------------------- //
+class b3ShortIntIndexData
+{
+public:
+       short m_value;
+       char m_pad[2];
+};
+
+// -------------------------------------------------- //
+class b3ShortIntIndexTripletData
+{
+public:
+       short m_values[3];
+       char m_pad[2];
+};
+
+// -------------------------------------------------- //
+class b3CharIndexTripletData
+{
+public:
+       char m_values[3];
+       char m_pad;
+};
+
+// -------------------------------------------------- //
+class b3MeshPartData
+{
+public:
+       b3Vector3FloatData *m_vertices3f;
+       b3Vector3DoubleData *m_vertices3d;
+       b3IntIndexData *m_indices32;
+       b3ShortIntIndexTripletData *m_3indices16;
+       b3CharIndexTripletData *m_3indices8;
+       b3ShortIntIndexData *m_indices16;
+       int m_numTriangles;
+       int m_numVertices;
+};
+
+// -------------------------------------------------- //
+class b3StridingMeshInterfaceData
+{
+public:
+       b3MeshPartData *m_meshPartsPtr;
+       b3Vector3FloatData m_scaling;
+       int m_numMeshParts;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3TriangleMeshShapeData
+{
+public:
+       b3CollisionShapeData m_collisionShapeData;
+       b3StridingMeshInterfaceData m_meshInterface;
+       b3QuantizedBvhFloatData *m_quantizedFloatBvh;
+       b3QuantizedBvhDoubleData *m_quantizedDoubleBvh;
+       b3TriangleInfoMapData *m_triangleInfoMap;
+       float m_collisionMargin;
+       char m_pad3[4];
+};
+
+// -------------------------------------------------- //
+class b3ScaledTriangleMeshShapeData
+{
+public:
+       b3TriangleMeshShapeData m_trimeshShapeData;
+       b3Vector3FloatData m_localScaling;
+};
+
+// -------------------------------------------------- //
+class b3CompoundShapeChildData
+{
+public:
+       b3TransformFloatData m_transform;
+       b3CollisionShapeData *m_childShape;
+       int m_childShapeType;
+       float m_childMargin;
+};
+
+// -------------------------------------------------- //
+class b3CompoundShapeData
+{
+public:
+       b3CollisionShapeData m_collisionShapeData;
+       b3CompoundShapeChildData *m_childShapePtr;
+       int m_numChildShapes;
+       float m_collisionMargin;
+};
+
+// -------------------------------------------------- //
+class b3CylinderShapeData
+{
+public:
+       b3ConvexInternalShapeData m_convexInternalShapeData;
+       int m_upAxis;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3CapsuleShapeData
+{
+public:
+       b3ConvexInternalShapeData m_convexInternalShapeData;
+       int m_upAxis;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3TriangleInfoData
+{
+public:
+       int m_flags;
+       float m_edgeV0V1Angle;
+       float m_edgeV1V2Angle;
+       float m_edgeV2V0Angle;
+};
+
+// -------------------------------------------------- //
+class b3TriangleInfoMapData
+{
+public:
+       int *m_hashTablePtr;
+       int *m_nextPtr;
+       b3TriangleInfoData *m_valueArrayPtr;
+       int *m_keyArrayPtr;
+       float m_convexEpsilon;
+       float m_planarEpsilon;
+       float m_equalVertexThreshold;
+       float m_edgeDistanceThreshold;
+       float m_zeroAreaThreshold;
+       int m_nextSize;
+       int m_hashTableSize;
+       int m_numValues;
+       int m_numKeys;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3GImpactMeshShapeData
+{
+public:
+       b3CollisionShapeData m_collisionShapeData;
+       b3StridingMeshInterfaceData m_meshInterface;
+       b3Vector3FloatData m_localScaling;
+       float m_collisionMargin;
+       int m_gimpactSubType;
+};
+
+// -------------------------------------------------- //
+class b3ConvexHullShapeData
+{
+public:
+       b3ConvexInternalShapeData m_convexInternalShapeData;
+       b3Vector3FloatData *m_unscaledPointsFloatPtr;
+       b3Vector3DoubleData *m_unscaledPointsDoublePtr;
+       int m_numUnscaledPoints;
+       char m_padding3[4];
+};
+
+// -------------------------------------------------- //
+class b3CollisionObjectDoubleData
+{
+public:
+       void *m_broadphaseHandle;
+       void *m_collisionShape;
+       b3CollisionShapeData *m_rootCollisionShape;
+       char *m_name;
+       b3TransformDoubleData m_worldTransform;
+       b3TransformDoubleData m_interpolationWorldTransform;
+       b3Vector3DoubleData m_interpolationLinearVelocity;
+       b3Vector3DoubleData m_interpolationAngularVelocity;
+       b3Vector3DoubleData m_anisotropicFriction;
+       double m_contactProcessingThreshold;
+       double m_deactivationTime;
+       double m_friction;
+       double m_rollingFriction;
+       double m_restitution;
+       double m_hitFraction;
+       double m_ccdSweptSphereRadius;
+       double m_ccdMotionThreshold;
+       int m_hasAnisotropicFriction;
+       int m_collisionFlags;
+       int m_islandTag1;
+       int m_companionId;
+       int m_activationState1;
+       int m_internalType;
+       int m_checkCollideWith;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3CollisionObjectFloatData
+{
+public:
+       void *m_broadphaseHandle;
+       void *m_collisionShape;
+       b3CollisionShapeData *m_rootCollisionShape;
+       char *m_name;
+       b3TransformFloatData m_worldTransform;
+       b3TransformFloatData m_interpolationWorldTransform;
+       b3Vector3FloatData m_interpolationLinearVelocity;
+       b3Vector3FloatData m_interpolationAngularVelocity;
+       b3Vector3FloatData m_anisotropicFriction;
+       float m_contactProcessingThreshold;
+       float m_deactivationTime;
+       float m_friction;
+       float m_rollingFriction;
+       float m_restitution;
+       float m_hitFraction;
+       float m_ccdSweptSphereRadius;
+       float m_ccdMotionThreshold;
+       int m_hasAnisotropicFriction;
+       int m_collisionFlags;
+       int m_islandTag1;
+       int m_companionId;
+       int m_activationState1;
+       int m_internalType;
+       int m_checkCollideWith;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3RigidBodyFloatData
+{
+public:
+       b3CollisionObjectFloatData m_collisionObjectData;
+       b3Matrix3x3FloatData m_invInertiaTensorWorld;
+       b3Vector3FloatData m_linearVelocity;
+       b3Vector3FloatData m_angularVelocity;
+       b3Vector3FloatData m_angularFactor;
+       b3Vector3FloatData m_linearFactor;
+       b3Vector3FloatData m_gravity;
+       b3Vector3FloatData m_gravity_acceleration;
+       b3Vector3FloatData m_invInertiaLocal;
+       b3Vector3FloatData m_totalForce;
+       b3Vector3FloatData m_totalTorque;
+       float m_inverseMass;
+       float m_linearDamping;
+       float m_angularDamping;
+       float m_additionalDampingFactor;
+       float m_additionalLinearDampingThresholdSqr;
+       float m_additionalAngularDampingThresholdSqr;
+       float m_additionalAngularDampingFactor;
+       float m_linearSleepingThreshold;
+       float m_angularSleepingThreshold;
+       int m_additionalDamping;
+};
+
+// -------------------------------------------------- //
+class b3RigidBodyDoubleData
+{
+public:
+       b3CollisionObjectDoubleData m_collisionObjectData;
+       b3Matrix3x3DoubleData m_invInertiaTensorWorld;
+       b3Vector3DoubleData m_linearVelocity;
+       b3Vector3DoubleData m_angularVelocity;
+       b3Vector3DoubleData m_angularFactor;
+       b3Vector3DoubleData m_linearFactor;
+       b3Vector3DoubleData m_gravity;
+       b3Vector3DoubleData m_gravity_acceleration;
+       b3Vector3DoubleData m_invInertiaLocal;
+       b3Vector3DoubleData m_totalForce;
+       b3Vector3DoubleData m_totalTorque;
+       double m_inverseMass;
+       double m_linearDamping;
+       double m_angularDamping;
+       double m_additionalDampingFactor;
+       double m_additionalLinearDampingThresholdSqr;
+       double m_additionalAngularDampingThresholdSqr;
+       double m_additionalAngularDampingFactor;
+       double m_linearSleepingThreshold;
+       double m_angularSleepingThreshold;
+       int m_additionalDamping;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3ConstraintInfo1
+{
+public:
+       int m_numConstraintRows;
+       int nub;
+};
+
+// -------------------------------------------------- //
+class b3TypedConstraintData
+{
+public:
+       bInvalidHandle *m_rbA;
+       bInvalidHandle *m_rbB;
+       char *m_name;
+       int m_objectType;
+       int m_userConstraintType;
+       int m_userConstraintId;
+       int m_needsFeedback;
+       float m_appliedImpulse;
+       float m_dbgDrawSize;
+       int m_disableCollisionsBetweenLinkedBodies;
+       int m_overrideNumSolverIterations;
+       float m_breakingImpulseThreshold;
+       int m_isEnabled;
+};
+
+// -------------------------------------------------- //
+class b3Point2PointConstraintFloatData
+{
+public:
+       b3TypedConstraintData m_typeConstraintData;
+       b3Vector3FloatData m_pivotInA;
+       b3Vector3FloatData m_pivotInB;
+};
+
+// -------------------------------------------------- //
+class b3Point2PointConstraintDoubleData
+{
+public:
+       b3TypedConstraintData m_typeConstraintData;
+       b3Vector3DoubleData m_pivotInA;
+       b3Vector3DoubleData m_pivotInB;
+};
+
+// -------------------------------------------------- //
+class b3HingeConstraintDoubleData
+{
+public:
+       b3TypedConstraintData m_typeConstraintData;
+       b3TransformDoubleData m_rbAFrame;
+       b3TransformDoubleData m_rbBFrame;
+       int m_useReferenceFrameA;
+       int m_angularOnly;
+       int m_enableAngularMotor;
+       float m_motorTargetVelocity;
+       float m_maxMotorImpulse;
+       float m_lowerLimit;
+       float m_upperLimit;
+       float m_limitSoftness;
+       float m_biasFactor;
+       float m_relaxationFactor;
+};
+
+// -------------------------------------------------- //
+class b3HingeConstraintFloatData
+{
+public:
+       b3TypedConstraintData m_typeConstraintData;
+       b3TransformFloatData m_rbAFrame;
+       b3TransformFloatData m_rbBFrame;
+       int m_useReferenceFrameA;
+       int m_angularOnly;
+       int m_enableAngularMotor;
+       float m_motorTargetVelocity;
+       float m_maxMotorImpulse;
+       float m_lowerLimit;
+       float m_upperLimit;
+       float m_limitSoftness;
+       float m_biasFactor;
+       float m_relaxationFactor;
+};
+
+// -------------------------------------------------- //
+class b3ConeTwistConstraintData
+{
+public:
+       b3TypedConstraintData m_typeConstraintData;
+       b3TransformFloatData m_rbAFrame;
+       b3TransformFloatData m_rbBFrame;
+       float m_swingSpan1;
+       float m_swingSpan2;
+       float m_twistSpan;
+       float m_limitSoftness;
+       float m_biasFactor;
+       float m_relaxationFactor;
+       float m_damping;
+       char m_pad[4];
+};
+
+// -------------------------------------------------- //
+class b3Generic6DofConstraintData
+{
+public:
+       b3TypedConstraintData m_typeConstraintData;
+       b3TransformFloatData m_rbAFrame;
+       b3TransformFloatData m_rbBFrame;
+       b3Vector3FloatData m_linearUpperLimit;
+       b3Vector3FloatData m_linearLowerLimit;
+       b3Vector3FloatData m_angularUpperLimit;
+       b3Vector3FloatData m_angularLowerLimit;
+       int m_useLinearReferenceFrameA;
+       int m_useOffsetForConstraintFrame;
+};
+
+// -------------------------------------------------- //
+class b3Generic6DofSpringConstraintData
+{
+public:
+       b3Generic6DofConstraintData m_6dofData;
+       int m_springEnabled[6];
+       float m_equilibriumPoint[6];
+       float m_springStiffness[6];
+       float m_springDamping[6];
+};
+
+// -------------------------------------------------- //
+class b3SliderConstraintData
+{
+public:
+       b3TypedConstraintData m_typeConstraintData;
+       b3TransformFloatData m_rbAFrame;
+       b3TransformFloatData m_rbBFrame;
+       float m_linearUpperLimit;
+       float m_linearLowerLimit;
+       float m_angularUpperLimit;
+       float m_angularLowerLimit;
+       int m_useLinearReferenceFrameA;
+       int m_useOffsetForConstraintFrame;
+};
+
+// -------------------------------------------------- //
+class b3ContactSolverInfoDoubleData
+{
+public:
+       double m_tau;
+       double m_damping;
+       double m_friction;
+       double m_timeStep;
+       double m_restitution;
+       double m_maxErrorReduction;
+       double m_sor;
+       double m_erp;
+       double m_erp2;
+       double m_globalCfm;
+       double m_splitImpulsePenetrationThreshold;
+       double m_splitImpulseTurnErp;
+       double m_linearSlop;
+       double m_warmstartingFactor;
+       double m_maxGyroscopicForce;
+       double m_singleAxisRollingFrictionThreshold;
+       int m_numIterations;
+       int m_solverMode;
+       int m_restingContactRestitutionThreshold;
+       int m_minimumSolverBatchSize;
+       int m_splitImpulse;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3ContactSolverInfoFloatData
+{
+public:
+       float m_tau;
+       float m_damping;
+       float m_friction;
+       float m_timeStep;
+       float m_restitution;
+       float m_maxErrorReduction;
+       float m_sor;
+       float m_erp;
+       float m_erp2;
+       float m_globalCfm;
+       float m_splitImpulsePenetrationThreshold;
+       float m_splitImpulseTurnErp;
+       float m_linearSlop;
+       float m_warmstartingFactor;
+       float m_maxGyroscopicForce;
+       float m_singleAxisRollingFrictionThreshold;
+       int m_numIterations;
+       int m_solverMode;
+       int m_restingContactRestitutionThreshold;
+       int m_minimumSolverBatchSize;
+       int m_splitImpulse;
+       char m_padding[4];
+};
+
+// -------------------------------------------------- //
+class b3DynamicsWorldDoubleData
+{
+public:
+       b3ContactSolverInfoDoubleData m_solverInfo;
+       b3Vector3DoubleData m_gravity;
+};
+
+// -------------------------------------------------- //
+class b3DynamicsWorldFloatData
+{
+public:
+       b3ContactSolverInfoFloatData m_solverInfo;
+       b3Vector3FloatData m_gravity;
+};
+
+// -------------------------------------------------- //
+class SoftBodyMaterialData
+{
+public:
+       float m_linearStiffness;
+       float m_angularStiffness;
+       float m_volumeStiffness;
+       int m_flags;
+};
+
+// -------------------------------------------------- //
+class SoftBodyNodeData
+{
+public:
+       SoftBodyMaterialData *m_material;
+       b3Vector3FloatData m_position;
+       b3Vector3FloatData m_previousPosition;
+       b3Vector3FloatData m_velocity;
+       b3Vector3FloatData m_accumulatedForce;
+       b3Vector3FloatData m_normal;
+       float m_inverseMass;
+       float m_area;
+       int m_attach;
+       int m_pad;
+};
+
+// -------------------------------------------------- //
+class SoftBodyLinkData
+{
+public:
+       SoftBodyMaterialData *m_material;
+       int m_nodeIndices[2];
+       float m_restLength;
+       int m_bbending;
+};
+
+// -------------------------------------------------- //
+class SoftBodyFaceData
+{
+public:
+       b3Vector3FloatData m_normal;
+       SoftBodyMaterialData *m_material;
+       int m_nodeIndices[3];
+       float m_restArea;
+};
+
+// -------------------------------------------------- //
+class SoftBodyTetraData
+{
+public:
+       b3Vector3FloatData m_c0[4];
+       SoftBodyMaterialData *m_material;
+       int m_nodeIndices[4];
+       float m_restVolume;
+       float m_c1;
+       float m_c2;
+       int m_pad;
+};
+
+// -------------------------------------------------- //
+class SoftRigidAnchorData
+{
+public:
+       b3Matrix3x3FloatData m_c0;
+       b3Vector3FloatData m_c1;
+       b3Vector3FloatData m_localFrame;
+       bInvalidHandle *m_rigidBody;
+       int m_nodeIndex;
+       float m_c2;
+};
+
+// -------------------------------------------------- //
+class SoftBodyConfigData
+{
+public:
+       int m_aeroModel;
+       float m_baumgarte;
+       float m_damping;
+       float m_drag;
+       float m_lift;
+       float m_pressure;
+       float m_volume;
+       float m_dynamicFriction;
+       float m_poseMatch;
+       float m_rigidContactHardness;
+       float m_kineticContactHardness;
+       float m_softContactHardness;
+       float m_anchorHardness;
+       float m_softRigidClusterHardness;
+       float m_softKineticClusterHardness;
+       float m_softSoftClusterHardness;
+       float m_softRigidClusterImpulseSplit;
+       float m_softKineticClusterImpulseSplit;
+       float m_softSoftClusterImpulseSplit;
+       float m_maxVolume;
+       float m_timeScale;
+       int m_velocityIterations;
+       int m_positionIterations;
+       int m_driftIterations;
+       int m_clusterIterations;
+       int m_collisionFlags;
+};
+
+// -------------------------------------------------- //
+class SoftBodyPoseData
+{
+public:
+       b3Matrix3x3FloatData m_rot;
+       b3Matrix3x3FloatData m_scale;
+       b3Matrix3x3FloatData m_aqq;
+       b3Vector3FloatData m_com;
+       b3Vector3FloatData *m_positions;
+       float *m_weights;
+       int m_numPositions;
+       int m_numWeigts;
+       int m_bvolume;
+       int m_bframe;
+       float m_restVolume;
+       int m_pad;
+};
+
+// -------------------------------------------------- //
+class SoftBodyClusterData
+{
+public:
+       b3TransformFloatData m_framexform;
+       b3Matrix3x3FloatData m_locii;
+       b3Matrix3x3FloatData m_invwi;
+       b3Vector3FloatData m_com;
+       b3Vector3FloatData m_vimpulses[2];
+       b3Vector3FloatData m_dimpulses[2];
+       b3Vector3FloatData m_lv;
+       b3Vector3FloatData m_av;
+       b3Vector3FloatData *m_framerefs;
+       int *m_nodeIndices;
+       float *m_masses;
+       int m_numFrameRefs;
+       int m_numNodes;
+       int m_numMasses;
+       float m_idmass;
+       float m_imass;
+       int m_nvimpulses;
+       int m_ndimpulses;
+       float m_ndamping;
+       float m_ldamping;
+       float m_adamping;
+       float m_matching;
+       float m_maxSelfCollisionImpulse;
+       float m_selfCollisionImpulseFactor;
+       int m_containsAnchor;
+       int m_collide;
+       int m_clusterIndex;
+};
+
+// -------------------------------------------------- //
+class b3SoftBodyJointData
+{
+public:
+       void *m_bodyA;
+       void *m_bodyB;
+       b3Vector3FloatData m_refs[2];
+       float m_cfm;
+       float m_erp;
+       float m_split;
+       int m_delete;
+       b3Vector3FloatData m_relPosition[2];
+       int m_bodyAtype;
+       int m_bodyBtype;
+       int m_jointType;
+       int m_pad;
+};
+
+// -------------------------------------------------- //
+class b3SoftBodyFloatData
+{
+public:
+       b3CollisionObjectFloatData m_collisionObjectData;
+       SoftBodyPoseData *m_pose;
+       SoftBodyMaterialData **m_materials;
+       SoftBodyNodeData *m_nodes;
+       SoftBodyLinkData *m_links;
+       SoftBodyFaceData *m_faces;
+       SoftBodyTetraData *m_tetrahedra;
+       SoftRigidAnchorData *m_anchors;
+       SoftBodyClusterData *m_clusters;
+       b3SoftBodyJointData *m_joints;
+       int m_numMaterials;
+       int m_numNodes;
+       int m_numLinks;
+       int m_numFaces;
+       int m_numTetrahedra;
+       int m_numAnchors;
+       int m_numClusters;
+       int m_numJoints;
+       SoftBodyConfigData m_config;
+};
+
+}  // namespace Bullet3SerializeBullet2
+#endif  //__BULLET2_H__
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp
new file mode 100644 (file)
index 0000000..d2a7163
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+bParse
+Copyright (c) 2006-2010 Erwin Coumans  http://gamekit.googlecode.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 "b3BulletFile.h"
+#include "b3Defines.h"
+#include "b3DNA.h"
+
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+// 32 && 64 bit versions
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#ifdef _WIN64
+extern char b3s_bulletDNAstr64[];
+extern int b3s_bulletDNAlen64;
+#else
+extern char b3s_bulletDNAstr[];
+extern int b3s_bulletDNAlen;
+#endif  //_WIN64
+#else   //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
+extern char b3s_bulletDNAstr64[];
+extern int b3s_bulletDNAlen64;
+extern char b3s_bulletDNAstr[];
+extern int b3s_bulletDNAlen;
+
+#endif  //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
+using namespace bParse;
+
+b3BulletFile::b3BulletFile()
+       : bFile("", "BULLET ")
+{
+       mMemoryDNA = new bDNA();  //this memory gets released in the bFile::~bFile destructor,@todo not consistent with the rule 'who allocates it, has to deallocate it"
+
+       m_DnaCopy = 0;
+
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#ifdef _WIN64
+       m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
+       memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+       mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen64);
+#else   //_WIN64
+       m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
+       memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
+       mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen);
+#endif  //_WIN64
+#else   //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+       if (VOID_IS_8)
+       {
+               m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
+               memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+               mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen64);
+       }
+       else
+       {
+               m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
+               memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
+               mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen);
+       }
+#endif  //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+}
+
+b3BulletFile::b3BulletFile(const char* fileName)
+       : bFile(fileName, "BULLET ")
+{
+       m_DnaCopy = 0;
+}
+
+b3BulletFile::b3BulletFile(char* memoryBuffer, int len)
+       : bFile(memoryBuffer, len, "BULLET ")
+{
+       m_DnaCopy = 0;
+}
+
+b3BulletFile::~b3BulletFile()
+{
+       if (m_DnaCopy)
+               b3AlignedFree(m_DnaCopy);
+
+       while (m_dataBlocks.size())
+       {
+               char* dataBlock = m_dataBlocks[m_dataBlocks.size() - 1];
+               delete[] dataBlock;
+               m_dataBlocks.pop_back();
+       }
+}
+
+// ----------------------------------------------------- //
+void b3BulletFile::parseData()
+{
+       //      printf ("Building datablocks");
+       //      printf ("Chunk size = %d",CHUNK_HEADER_LEN);
+       //      printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
+
+       const bool brokenDNA = (mFlags & FD_BROKEN_DNA) != 0;
+
+       //const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
+
+       mDataStart = 12;
+
+       char* dataPtr = mFileBuffer + mDataStart;
+
+       bChunkInd dataChunk;
+       dataChunk.code = 0;
+
+       //dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
+       int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+
+       if (mFlags & FD_ENDIAN_SWAP)
+               swapLen(dataPtr);
+
+       //dataPtr += ChunkUtils::getOffset(mFlags);
+       char* dataPtrHead = 0;
+
+       while (dataChunk.code != B3_DNA1)
+       {
+               if (!brokenDNA || (dataChunk.code != B3_QUANTIZED_BVH_CODE))
+               {
+                       // one behind
+                       if (dataChunk.code == B3_SDNA) break;
+                       //if (dataChunk.code == DNA1) break;
+
+                       // same as (BHEAD+DATA dependency)
+                       dataPtrHead = dataPtr + ChunkUtils::getOffset(mFlags);
+                       if (dataChunk.dna_nr >= 0)
+                       {
+                               char* id = readStruct(dataPtrHead, dataChunk);
+
+                               // lookup maps
+                               if (id)
+                               {
+                                       m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk);
+                                       mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id);
+
+                                       m_chunks.push_back(dataChunk);
+                                       // block it
+                                       //bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
+                                       //if (listID)
+                                       //      listID->push_back((bStructHandle*)id);
+                               }
+
+                               if (dataChunk.code == B3_SOFTBODY_CODE)
+                               {
+                                       m_softBodies.push_back((bStructHandle*)id);
+                               }
+
+                               if (dataChunk.code == B3_RIGIDBODY_CODE)
+                               {
+                                       m_rigidBodies.push_back((bStructHandle*)id);
+                               }
+
+                               if (dataChunk.code == B3_DYNAMICSWORLD_CODE)
+                               {
+                                       m_dynamicsWorldInfo.push_back((bStructHandle*)id);
+                               }
+
+                               if (dataChunk.code == B3_CONSTRAINT_CODE)
+                               {
+                                       m_constraints.push_back((bStructHandle*)id);
+                               }
+
+                               if (dataChunk.code == B3_QUANTIZED_BVH_CODE)
+                               {
+                                       m_bvhs.push_back((bStructHandle*)id);
+                               }
+
+                               if (dataChunk.code == B3_TRIANLGE_INFO_MAP)
+                               {
+                                       m_triangleInfoMaps.push_back((bStructHandle*)id);
+                               }
+
+                               if (dataChunk.code == B3_COLLISIONOBJECT_CODE)
+                               {
+                                       m_collisionObjects.push_back((bStructHandle*)id);
+                               }
+
+                               if (dataChunk.code == B3_SHAPE_CODE)
+                               {
+                                       m_collisionShapes.push_back((bStructHandle*)id);
+                               }
+
+                               //              if (dataChunk.code == GLOB)
+                               //              {
+                               //                      m_glob = (bStructHandle*) id;
+                               //              }
+                       }
+                       else
+                       {
+                               //printf("unknown chunk\n");
+
+                               mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead);
+                       }
+               }
+               else
+               {
+                       printf("skipping B3_QUANTIZED_BVH_CODE due to broken DNA\n");
+               }
+
+               dataPtr += seek;
+
+               seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+               if (mFlags & FD_ENDIAN_SWAP)
+                       swapLen(dataPtr);
+
+               if (seek < 0)
+                       break;
+       }
+}
+
+void b3BulletFile::addDataBlock(char* dataBlock)
+{
+       m_dataBlocks.push_back(dataBlock);
+}
+
+void b3BulletFile::writeDNA(FILE* fp)
+{
+       bChunkInd dataChunk;
+       dataChunk.code = B3_DNA1;
+       dataChunk.dna_nr = 0;
+       dataChunk.nr = 1;
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+       if (VOID_IS_8)
+       {
+#ifdef _WIN64
+               dataChunk.len = b3s_bulletDNAlen64;
+               dataChunk.oldPtr = b3s_bulletDNAstr64;
+               fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
+               fwrite(b3s_bulletDNAstr64, b3s_bulletDNAlen64, 1, fp);
+#else
+               b3Assert(0);
+#endif
+       }
+       else
+       {
+#ifndef _WIN64
+               dataChunk.len = b3s_bulletDNAlen;
+               dataChunk.oldPtr = b3s_bulletDNAstr;
+               fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
+               fwrite(b3s_bulletDNAstr, b3s_bulletDNAlen, 1, fp);
+#else   //_WIN64
+               b3Assert(0);
+#endif  //_WIN64
+       }
+#else   //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+       if (VOID_IS_8)
+       {
+               dataChunk.len = b3s_bulletDNAlen64;
+               dataChunk.oldPtr = b3s_bulletDNAstr64;
+               fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
+               fwrite(b3s_bulletDNAstr64, b3s_bulletDNAlen64, 1, fp);
+       }
+       else
+       {
+               dataChunk.len = b3s_bulletDNAlen;
+               dataChunk.oldPtr = b3s_bulletDNAstr;
+               fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
+               fwrite(b3s_bulletDNAstr, b3s_bulletDNAlen, 1, fp);
+       }
+#endif  //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+}
+
+void b3BulletFile::parse(int verboseMode)
+{
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+       if (VOID_IS_8)
+       {
+#ifdef _WIN64
+
+               if (m_DnaCopy)
+                       delete m_DnaCopy;
+               m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
+               memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+               parseInternal(verboseMode, (char*)b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+#else
+               b3Assert(0);
+#endif
+       }
+       else
+       {
+#ifndef _WIN64
+
+               if (m_DnaCopy)
+                       delete m_DnaCopy;
+               m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
+               memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
+               parseInternal(verboseMode, m_DnaCopy, b3s_bulletDNAlen);
+#else
+               b3Assert(0);
+#endif
+       }
+#else   //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+       if (VOID_IS_8)
+       {
+               if (m_DnaCopy)
+                       delete m_DnaCopy;
+               m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
+               memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+               parseInternal(verboseMode, m_DnaCopy, b3s_bulletDNAlen64);
+       }
+       else
+       {
+               if (m_DnaCopy)
+                       delete m_DnaCopy;
+               m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
+               memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
+               parseInternal(verboseMode, m_DnaCopy, b3s_bulletDNAlen);
+       }
+#endif  //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
+       //the parsing will convert to cpu endian
+       mFlags &= ~FD_ENDIAN_SWAP;
+
+       int littleEndian = 1;
+       littleEndian = ((char*)&littleEndian)[0];
+
+       mFileBuffer[8] = littleEndian ? 'v' : 'V';
+}
+
+// experimental
+int b3BulletFile::write(const char* fileName, bool fixupPointers)
+{
+       FILE* fp = fopen(fileName, "wb");
+       if (fp)
+       {
+               char header[B3_SIZEOFBLENDERHEADER];
+               memcpy(header, m_headerString, 7);
+               int endian = 1;
+               endian = ((char*)&endian)[0];
+
+               if (endian)
+               {
+                       header[7] = '_';
+               }
+               else
+               {
+                       header[7] = '-';
+               }
+               if (VOID_IS_8)
+               {
+                       header[8] = 'V';
+               }
+               else
+               {
+                       header[8] = 'v';
+               }
+
+               header[9] = '2';
+               header[10] = '7';
+               header[11] = '5';
+
+               fwrite(header, B3_SIZEOFBLENDERHEADER, 1, fp);
+
+               writeChunks(fp, fixupPointers);
+
+               writeDNA(fp);
+
+               fclose(fp);
+       }
+       else
+       {
+               printf("Error: cannot open file %s for writing\n", fileName);
+               return 0;
+       }
+       return 1;
+}
+
+void b3BulletFile::addStruct(const char* structType, void* data, int len, void* oldPtr, int code)
+{
+       bParse::bChunkInd dataChunk;
+       dataChunk.code = code;
+       dataChunk.nr = 1;
+       dataChunk.len = len;
+       dataChunk.dna_nr = mMemoryDNA->getReverseType(structType);
+       dataChunk.oldPtr = oldPtr;
+
+       ///Perform structure size validation
+       short* structInfo = mMemoryDNA->getStruct(dataChunk.dna_nr);
+       int elemBytes;
+       elemBytes = mMemoryDNA->getLength(structInfo[0]);
+       //      int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
+       assert(len == elemBytes);
+
+       mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data);
+       m_chunks.push_back(dataChunk);
+}
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h
new file mode 100644 (file)
index 0000000..ede1d37
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+bParse
+Copyright (c) 2006-2010 Charlie C & Erwin Coumans  http://gamekit.googlecode.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.
+*/
+
+#ifndef B3_BULLET_FILE_H
+#define B3_BULLET_FILE_H
+
+#include "b3File.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "b3Defines.h"
+
+#include "Bullet3Serialize/Bullet2FileLoader/b3Serializer.h"
+
+namespace bParse
+{
+// ----------------------------------------------------- //
+class b3BulletFile : public bFile
+{
+protected:
+       char* m_DnaCopy;
+
+public:
+       b3AlignedObjectArray<bStructHandle*> m_softBodies;
+
+       b3AlignedObjectArray<bStructHandle*> m_rigidBodies;
+
+       b3AlignedObjectArray<bStructHandle*> m_collisionObjects;
+
+       b3AlignedObjectArray<bStructHandle*> m_collisionShapes;
+
+       b3AlignedObjectArray<bStructHandle*> m_constraints;
+
+       b3AlignedObjectArray<bStructHandle*> m_bvhs;
+
+       b3AlignedObjectArray<bStructHandle*> m_triangleInfoMaps;
+
+       b3AlignedObjectArray<bStructHandle*> m_dynamicsWorldInfo;
+
+       b3AlignedObjectArray<char*> m_dataBlocks;
+       b3BulletFile();
+
+       b3BulletFile(const char* fileName);
+
+       b3BulletFile(char* memoryBuffer, int len);
+
+       virtual ~b3BulletFile();
+
+       virtual void addDataBlock(char* dataBlock);
+
+       // experimental
+       virtual int write(const char* fileName, bool fixupPointers = false);
+
+       virtual void parse(int verboseMode);
+
+       virtual void parseData();
+
+       virtual void writeDNA(FILE* fp);
+
+       void addStruct(const char* structType, void* data, int len, void* oldPtr, int code);
+};
+};  // namespace bParse
+
+#endif  //B3_BULLET_FILE_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp
new file mode 100644 (file)
index 0000000..ff75ff8
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.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 "b3Chunk.h"
+#include "b3Defines.h"
+#include "b3File.h"
+
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+using namespace bParse;
+
+// ----------------------------------------------------- //
+short ChunkUtils::swapShort(short sht)
+{
+       B3_SWITCH_SHORT(sht);
+       return sht;
+}
+
+// ----------------------------------------------------- //
+int ChunkUtils::swapInt(int inte)
+{
+       B3_SWITCH_INT(inte);
+       return inte;
+}
+
+// ----------------------------------------------------- //
+b3Long64 ChunkUtils::swapLong64(b3Long64 lng)
+{
+       B3_SWITCH_LONGINT(lng);
+       return lng;
+}
+
+// ----------------------------------------------------- //
+int ChunkUtils::getOffset(int flags)
+{
+       // if the file is saved in a
+       // different format, get the
+       // file's chunk size
+       int res = CHUNK_HEADER_LEN;
+
+       if (VOID_IS_8)
+       {
+               if (flags & FD_BITS_VARIES)
+                       res = sizeof(bChunkPtr4);
+       }
+       else
+       {
+               if (flags & FD_BITS_VARIES)
+                       res = sizeof(bChunkPtr8);
+       }
+       return res;
+}
+
+//eof
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h
new file mode 100644 (file)
index 0000000..c9d0f37
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.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.
+*/
+
+#ifndef __BCHUNK_H__
+#define __BCHUNK_H__
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+#define b3Long64 __int64
+#elif defined(__MINGW32__)
+#include <stdint.h>
+#define b3Long64 int64_t
+#else
+#define b3Long64 long long
+#endif
+
+namespace bParse
+{
+// ----------------------------------------------------- //
+class bChunkPtr4
+{
+public:
+       bChunkPtr4() {}
+       int code;
+       int len;
+       union {
+               int m_uniqueInt;
+       };
+       int dna_nr;
+       int nr;
+};
+
+// ----------------------------------------------------- //
+class bChunkPtr8
+{
+public:
+       bChunkPtr8() {}
+       int code, len;
+       union {
+               b3Long64 oldPrev;
+               int m_uniqueInts[2];
+       };
+       int dna_nr, nr;
+};
+
+// ----------------------------------------------------- //
+class bChunkInd
+{
+public:
+       bChunkInd() {}
+       int code, len;
+       void *oldPtr;
+       int dna_nr, nr;
+};
+
+// ----------------------------------------------------- //
+class ChunkUtils
+{
+public:
+       // file chunk offset
+       static int getOffset(int flags);
+
+       // endian utils
+       static short swapShort(short sht);
+       static int swapInt(int inte);
+       static b3Long64 swapLong64(b3Long64 lng);
+};
+
+const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd)));
+const bool VOID_IS_8 = ((sizeof(void *) == 8));
+}  // namespace bParse
+
+#endif  //__BCHUNK_H__
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Common.h b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Common.h
new file mode 100644 (file)
index 0000000..5884fad
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.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.
+*/
+
+#ifndef __BCOMMON_H__
+#define __BCOMMON_H__
+
+#include <assert.h>
+//#include "bLog.h"
+#include "Bullet3Common/b3AlignedObjectArray.h"
+#include "Bullet3Common/b3HashMap.h"
+
+namespace bParse
+{
+class bMain;
+class bFileData;
+class bFile;
+class bDNA;
+
+// delete void* undefined
+typedef struct bStructHandle
+{
+       int unused;
+} bStructHandle;
+typedef b3AlignedObjectArray<bStructHandle*> bListBasePtr;
+typedef b3HashMap<b3HashPtr, bStructHandle*> bPtrMap;
+}  // namespace bParse
+
+#endif  //__BCOMMON_H__
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp
new file mode 100644 (file)
index 0000000..09c8f23
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.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 <assert.h>
+
+#include "b3DNA.h"
+#include "b3Chunk.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+//this define will force traversal of structures, to check backward (and forward) compatibility
+//#define TEST_BACKWARD_FORWARD_COMPATIBILITY
+
+using namespace bParse;
+
+// ----------------------------------------------------- //
+bDNA::bDNA()
+       : mPtrLen(0)
+{
+       // --
+}
+
+// ----------------------------------------------------- //
+bDNA::~bDNA()
+{
+       // --
+}
+
+// ----------------------------------------------------- //
+bool bDNA::lessThan(bDNA *file)
+{
+       return (m_Names.size() < file->m_Names.size());
+}
+
+// ----------------------------------------------------- //
+char *bDNA::getName(int ind)
+{
+       assert(ind <= (int)m_Names.size());
+       return m_Names[ind].m_name;
+}
+
+// ----------------------------------------------------- //
+char *bDNA::getType(int ind)
+{
+       assert(ind <= (int)mTypes.size());
+       return mTypes[ind];
+}
+
+// ----------------------------------------------------- //
+short *bDNA::getStruct(int ind)
+{
+       assert(ind <= (int)mStructs.size());
+       return mStructs[ind];
+}
+
+// ----------------------------------------------------- //
+short bDNA::getLength(int ind)
+{
+       assert(ind <= (int)mTlens.size());
+       return mTlens[ind];
+}
+
+// ----------------------------------------------------- //
+int bDNA::getReverseType(short type)
+{
+       int *intPtr = mStructReverse.find(type);
+       if (intPtr)
+               return *intPtr;
+
+       return -1;
+}
+
+// ----------------------------------------------------- //
+int bDNA::getReverseType(const char *type)
+{
+       b3HashString key(type);
+       int *valuePtr = mTypeLookup.find(key);
+       if (valuePtr)
+               return *valuePtr;
+
+       return -1;
+}
+
+// ----------------------------------------------------- //
+int bDNA::getNumStructs()
+{
+       return (int)mStructs.size();
+}
+
+// ----------------------------------------------------- //
+bool bDNA::flagNotEqual(int dna_nr)
+{
+       assert(dna_nr <= (int)mCMPFlags.size());
+       return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
+}
+
+// ----------------------------------------------------- //
+bool bDNA::flagEqual(int dna_nr)
+{
+       assert(dna_nr <= (int)mCMPFlags.size());
+       int flag = mCMPFlags[dna_nr];
+       return flag == FDF_STRUCT_EQU;
+}
+
+// ----------------------------------------------------- //
+bool bDNA::flagNone(int dna_nr)
+{
+       assert(dna_nr <= (int)mCMPFlags.size());
+       return mCMPFlags[dna_nr] == FDF_NONE;
+}
+
+// ----------------------------------------------------- //
+int bDNA::getPointerSize()
+{
+       return mPtrLen;
+}
+
+// ----------------------------------------------------- //
+void bDNA::initRecurseCmpFlags(int iter)
+{
+       // iter is FDF_STRUCT_NEQU
+
+       short *oldStrc = mStructs[iter];
+       short type = oldStrc[0];
+
+       for (int i = 0; i < (int)mStructs.size(); i++)
+       {
+               if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU)
+               {
+                       short *curStruct = mStructs[i];
+                       int eleLen = curStruct[1];
+                       curStruct += 2;
+
+                       for (int j = 0; j < eleLen; j++, curStruct += 2)
+                       {
+                               if (curStruct[0] == type)
+                               {
+                                       //char *name = m_Names[curStruct[1]].m_name;
+                                       //if (name[0] != '*')
+                                       if (m_Names[curStruct[1]].m_isPointer)
+                                       {
+                                               mCMPFlags[i] = FDF_STRUCT_NEQU;
+                                               initRecurseCmpFlags(i);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+// ----------------------------------------------------- //
+void bDNA::initCmpFlags(bDNA *memDNA)
+{
+       // compare the file to memory
+       // this ptr should be the file data
+
+       assert(!(m_Names.size() == 0));  // && "SDNA empty!");
+       mCMPFlags.resize(mStructs.size(), FDF_NONE);
+
+       int i;
+       for (i = 0; i < (int)mStructs.size(); i++)
+       {
+               short *oldStruct = mStructs[i];
+
+               int oldLookup = getReverseType(oldStruct[0]);
+               if (oldLookup == -1)
+               {
+                       mCMPFlags[i] = FDF_NONE;
+                       continue;
+               }
+               //char* typeName = mTypes[oldStruct[0]];
+
+//#define SLOW_FORWARD_COMPATIBLE 1
+#ifdef SLOW_FORWARD_COMPATIBLE
+               char *typeName = mTypes[oldLookup];
+               int newLookup = memDNA->getReverseType(typeName);
+               if (newLookup == -1)
+               {
+                       mCMPFlags[i] = FDF_NONE;
+                       continue;
+               }
+               short *curStruct = memDNA->mStructs[newLookup];
+#else
+               // memory for file
+
+               if (oldLookup < memDNA->mStructs.size())
+               {
+                       short *curStruct = memDNA->mStructs[oldLookup];
+#endif
+
+               // rebuild...
+               mCMPFlags[i] = FDF_STRUCT_NEQU;
+
+#ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
+
+               if (curStruct[1] == oldStruct[1])
+               {
+                       // type len same ...
+                       if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
+                       {
+                               bool isSame = true;
+                               int elementLength = oldStruct[1];
+
+                               curStruct += 2;
+                               oldStruct += 2;
+
+                               for (int j = 0; j < elementLength; j++, curStruct += 2, oldStruct += 2)
+                               {
+                                       // type the same
+                                       //const char* typeFileDNA = mTypes[oldStruct[0]];
+                                       //const char* typeMemDNA = mTypes[curStruct[0]];
+                                       if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]]) != 0)
+                                       {
+                                               isSame = false;
+                                               break;
+                                       }
+
+                                       // name the same
+                                       if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name) != 0)
+                                       {
+                                               isSame = false;
+                                               break;
+                                       }
+                               }
+                               // flag valid ==
+                               if (isSame)
+                                       mCMPFlags[i] = FDF_STRUCT_EQU;
+                       }
+               }
+#endif
+       }
+}
+
+// recurse in
+for (i = 0; i < (int)mStructs.size(); i++)
+{
+       if (mCMPFlags[i] == FDF_STRUCT_NEQU)
+               initRecurseCmpFlags(i);
+}
+}
+
+static int name_is_array(char *name, int *dim1, int *dim2)
+{
+       int len = strlen(name);
+       /*fprintf(stderr,"[%s]",name);*/
+       /*if (len >= 1) {
+       if (name[len-1] != ']')
+       return 1;
+       }
+       return 0;*/
+       char *bp;
+       int num;
+       if (dim1)
+       {
+               *dim1 = 1;
+       }
+       if (dim2)
+       {
+               *dim2 = 1;
+       }
+       bp = strchr(name, '[');
+       if (!bp)
+       {
+               return 0;
+       }
+       num = 0;
+       while (++bp < name + len - 1)
+       {
+               const char c = *bp;
+               if (c == ']')
+               {
+                       break;
+               }
+               if (c <= '9' && c >= '0')
+               {
+                       num *= 10;
+                       num += (c - '0');
+               }
+               else
+               {
+                       printf("array parse error.\n");
+                       return 0;
+               }
+       }
+       if (dim2)
+       {
+               *dim2 = num;
+       }
+
+       /* find second dim, if any. */
+       bp = strchr(bp, '[');
+       if (!bp)
+       {
+               return 1; /* at least we got the first dim. */
+       }
+       num = 0;
+       while (++bp < name + len - 1)
+       {
+               const char c = *bp;
+               if (c == ']')
+               {
+                       break;
+               }
+               if (c <= '9' && c >= '0')
+               {
+                       num *= 10;
+                       num += (c - '0');
+               }
+               else
+               {
+                       printf("array2 parse error.\n");
+                       return 1;
+               }
+       }
+       if (dim1)
+       {
+               if (dim2)
+               {
+                       *dim1 = *dim2;
+                       *dim2 = num;
+               }
+               else
+               {
+                       *dim1 = num;
+               }
+       }
+
+       return 1;
+}
+
+// ----------------------------------------------------- //
+void bDNA::init(char *data, int len, bool swap)
+{
+       int *intPtr = 0;
+       short *shtPtr = 0;
+       char *cp = 0;
+       int dataLen = 0;
+       //long nr=0;
+       intPtr = (int *)data;
+
+       /*
+               SDNA (4 bytes) (magic number)
+               NAME (4 bytes)
+               <nr> (4 bytes) amount of names (int)
+               <string>
+               <string>
+       */
+
+       if (strncmp(data, "SDNA", 4) == 0)
+       {
+               // skip ++ NAME
+               intPtr++;
+               intPtr++;
+       }
+
+       // Parse names
+       if (swap)
+       {
+               *intPtr = ChunkUtils::swapInt(*intPtr);
+       }
+       dataLen = *intPtr;
+       intPtr++;
+
+       cp = (char *)intPtr;
+       int i;
+       for (i = 0; i < dataLen; i++)
+       {
+               bNameInfo info;
+               info.m_name = cp;
+               info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
+               name_is_array(info.m_name, &info.m_dim0, &info.m_dim1);
+               m_Names.push_back(info);
+               while (*cp) cp++;
+               cp++;
+       }
+
+       cp = b3AlignPointer(cp, 4);
+
+       /*
+               TYPE (4 bytes)
+               <nr> amount of types (int)
+               <string>
+               <string>
+       */
+
+       intPtr = (int *)cp;
+       assert(strncmp(cp, "TYPE", 4) == 0);
+       intPtr++;
+
+       if (swap)
+       {
+               *intPtr = ChunkUtils::swapInt(*intPtr);
+       }
+       dataLen = *intPtr;
+       intPtr++;
+
+       cp = (char *)intPtr;
+       for (i = 0; i < dataLen; i++)
+       {
+               mTypes.push_back(cp);
+               while (*cp) cp++;
+               cp++;
+       }
+
+       cp = b3AlignPointer(cp, 4);
+
+       /*
+               TLEN (4 bytes)
+               <len> (short) the lengths of types
+               <len>
+       */
+
+       // Parse type lens
+       intPtr = (int *)cp;
+       assert(strncmp(cp, "TLEN", 4) == 0);
+       intPtr++;
+
+       dataLen = (int)mTypes.size();
+
+       shtPtr = (short *)intPtr;
+       for (i = 0; i < dataLen; i++, shtPtr++)
+       {
+               if (swap)
+                       shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+               mTlens.push_back(shtPtr[0]);
+       }
+
+       if (dataLen & 1) shtPtr++;
+
+       /*
+               STRC (4 bytes)
+               <nr> amount of structs (int)
+               <typenr>
+               <nr_of_elems>
+               <typenr>
+               <namenr>
+               <typenr>
+               <namenr>
+       */
+
+       intPtr = (int *)shtPtr;
+       cp = (char *)intPtr;
+       assert(strncmp(cp, "STRC", 4) == 0);
+       intPtr++;
+
+       if (swap)
+       {
+               *intPtr = ChunkUtils::swapInt(*intPtr);
+       }
+       dataLen = *intPtr;
+       intPtr++;
+
+       shtPtr = (short *)intPtr;
+       for (i = 0; i < dataLen; i++)
+       {
+               mStructs.push_back(shtPtr);
+               if (swap)
+               {
+                       shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+                       shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
+
+                       int len = shtPtr[1];
+                       shtPtr += 2;
+
+                       for (int a = 0; a < len; a++, shtPtr += 2)
+                       {
+                               shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+                               shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
+                       }
+               }
+               else
+                       shtPtr += (2 * shtPtr[1]) + 2;
+       }
+
+       // build reverse lookups
+       for (i = 0; i < (int)mStructs.size(); i++)
+       {
+               short *strc = mStructs.at(i);
+               if (!mPtrLen && strcmp(mTypes[strc[0]], "ListBase") == 0)
+               {
+                       mPtrLen = mTlens[strc[0]] / 2;
+               }
+
+               mStructReverse.insert(strc[0], i);
+               mTypeLookup.insert(b3HashString(mTypes[strc[0]]), i);
+       }
+}
+
+// ----------------------------------------------------- //
+int bDNA::getArraySize(char *string)
+{
+       int ret = 1;
+       int len = strlen(string);
+
+       char *next = 0;
+       for (int i = 0; i < len; i++)
+       {
+               char c = string[i];
+
+               if (c == '[')
+                       next = &string[i + 1];
+               else if (c == ']')
+                       if (next)
+                               ret *= atoi(next);
+       }
+
+       //      print (string << ' ' << ret);
+       return ret;
+}
+
+void bDNA::dumpTypeDefinitions()
+{
+       int i;
+
+       int numTypes = mTypes.size();
+
+       for (i = 0; i < numTypes; i++)
+       {
+       }
+
+       for (i = 0; i < (int)mStructs.size(); i++)
+       {
+               int totalBytes = 0;
+               short *oldStruct = mStructs[i];
+
+               int oldLookup = getReverseType(oldStruct[0]);
+               if (oldLookup == -1)
+               {
+                       mCMPFlags[i] = FDF_NONE;
+                       continue;
+               }
+
+               short *newStruct = mStructs[oldLookup];
+               char *typeName = mTypes[newStruct[0]];
+               printf("%3d: %s ", i, typeName);
+
+               //char *name = mNames[oldStruct[1]];
+               int len = oldStruct[1];
+               printf(" (%d fields) ", len);
+               oldStruct += 2;
+
+               printf("{");
+               int j;
+               for (j = 0; j < len; ++j, oldStruct += 2)
+               {
+                       const char *name = m_Names[oldStruct[1]].m_name;
+                       printf("%s %s", mTypes[oldStruct[0]], name);
+                       int elemNumBytes = 0;
+                       int arrayDimensions = getArraySizeNew(oldStruct[1]);
+
+                       if (m_Names[oldStruct[1]].m_isPointer)
+                       {
+                               elemNumBytes = VOID_IS_8 ? 8 : 4;
+                       }
+                       else
+                       {
+                               elemNumBytes = getLength(oldStruct[0]);
+                       }
+                       printf(" /* %d bytes */", elemNumBytes * arrayDimensions);
+
+                       if (j == len - 1)
+                       {
+                               printf(";}");
+                       }
+                       else
+                       {
+                               printf("; ");
+                       }
+                       totalBytes += elemNumBytes * arrayDimensions;
+               }
+               printf("\ntotalBytes=%d\n\n", totalBytes);
+       }
+
+#if 0
+       /* dump out display of types and their sizes */
+       for (i=0; i<bf->types_count; ++i) {
+               /* if (!bf->types[i].is_struct)*/
+               {
+                       printf("%3d: sizeof(%s%s)=%d",
+                               i,
+                               bf->types[i].is_struct ? "struct " : "atomic ",
+                               bf->types[i].name, bf->types[i].size);
+                       if (bf->types[i].is_struct) {
+                               int j;
+                               printf(", %d fields: { ", bf->types[i].fieldtypes_count);
+                               for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
+                                       printf("%s %s",
+                                               bf->types[bf->types[i].fieldtypes[j]].name,
+                                               bf->names[bf->types[i].fieldnames[j]]);
+                                       if (j == bf->types[i].fieldtypes_count-1) {
+                                               printf(";}");
+                                       } else {
+                                               printf("; ");
+                                       }
+                               }
+                       }
+                       printf("\n\n");
+
+               }
+       }
+#endif
+}
+
+//eof
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.h b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3DNA.h
new file mode 100644 (file)
index 0000000..ca6004d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.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.
+*/
+
+#ifndef __BDNA_H__
+#define __BDNA_H__
+
+#include "b3Common.h"
+
+namespace bParse
+{
+struct bNameInfo
+{
+       char *m_name;
+       bool m_isPointer;
+       int m_dim0;
+       int m_dim1;
+};
+
+class bDNA
+{
+public:
+       bDNA();
+       ~bDNA();
+
+       void init(char *data, int len, bool swap = false);
+
+       int getArraySize(char *str);
+       int getArraySizeNew(short name)
+       {
+               const bNameInfo &nameInfo = m_Names[name];
+               return nameInfo.m_dim0 * nameInfo.m_dim1;
+       }
+       int getElementSize(short type, short name)
+       {
+               const bNameInfo &nameInfo = m_Names[name];
+               int size = nameInfo.m_isPointer ? mPtrLen * nameInfo.m_dim0 * nameInfo.m_dim1 : mTlens[type] * nameInfo.m_dim0 * nameInfo.m_dim1;
+               return size;
+       }
+
+       int getNumNames() const
+       {
+               return m_Names.size();
+       }
+
+       char *getName(int ind);
+       char *getType(int ind);
+       short *getStruct(int ind);
+       short getLength(int ind);
+       int getReverseType(short type);
+       int getReverseType(const char *type);
+
+       int getNumStructs();
+
+       //
+       bool lessThan(bDNA *other);
+
+       void initCmpFlags(bDNA *memDNA);
+       bool flagNotEqual(int dna_nr);
+       bool flagEqual(int dna_nr);
+       bool flagNone(int dna_nr);
+
+       int getPointerSize();
+
+       void dumpTypeDefinitions();
+
+private:
+       enum FileDNAFlags
+       {
+               FDF_NONE = 0,
+               FDF_STRUCT_NEQU,
+               FDF_STRUCT_EQU
+       };
+
+       void initRecurseCmpFlags(int i);
+
+       b3AlignedObjectArray<int> mCMPFlags;
+
+       b3AlignedObjectArray<bNameInfo> m_Names;
+       b3AlignedObjectArray<char *> mTypes;
+       b3AlignedObjectArray<short *> mStructs;
+       b3AlignedObjectArray<short> mTlens;
+       b3HashMap<b3HashInt, int> mStructReverse;
+       b3HashMap<b3HashString, int> mTypeLookup;
+
+       int mPtrLen;
+};
+}  // namespace bParse
+
+#endif  //__BDNA_H__
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Defines.h b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Defines.h
new file mode 100644 (file)
index 0000000..0524c94
--- /dev/null
@@ -0,0 +1,149 @@
+/* Copyright (C) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.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.
+*/
+#ifndef __B_DEFINES_H__
+#define __B_DEFINES_H__
+
+// MISC defines, see BKE_global.h, BKE_utildefines.h
+#define B3_SIZEOFBLENDERHEADER 12
+
+// ------------------------------------------------------------
+#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
+#define B3_MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
+#else
+#define B3_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
+#endif
+
+// ------------------------------------------------------------
+#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
+#define B3_MAKE_ID2(c, d) ((c) << 8 | (d))
+#else
+#define B3_MAKE_ID2(c, d) ((d) << 8 | (c))
+#endif
+
+// ------------------------------------------------------------
+#define B3_ID_SCE B3_MAKE_ID2('S', 'C')
+#define B3_ID_LI B3_MAKE_ID2('L', 'I')
+#define B3_ID_OB B3_MAKE_ID2('O', 'B')
+#define B3_ID_ME B3_MAKE_ID2('M', 'E')
+#define B3_ID_CU B3_MAKE_ID2('C', 'U')
+#define B3_ID_MB B3_MAKE_ID2('M', 'B')
+#define B3_ID_MA B3_MAKE_ID2('M', 'A')
+#define B3_ID_TE B3_MAKE_ID2('T', 'E')
+#define B3_ID_IM B3_MAKE_ID2('I', 'M')
+#define B3_ID_IK B3_MAKE_ID2('I', 'K')
+#define B3_ID_WV B3_MAKE_ID2('W', 'V')
+#define B3_ID_LT B3_MAKE_ID2('L', 'T')
+#define B3_ID_SE B3_MAKE_ID2('S', 'E')
+#define B3_ID_LF B3_MAKE_ID2('L', 'F')
+#define B3_ID_LA B3_MAKE_ID2('L', 'A')
+#define B3_ID_CA B3_MAKE_ID2('C', 'A')
+#define B3_ID_IP B3_MAKE_ID2('I', 'P')
+#define B3_ID_KE B3_MAKE_ID2('K', 'E')
+#define B3_ID_WO B3_MAKE_ID2('W', 'O')
+#define B3_ID_SCR B3_MAKE_ID2('S', 'R')
+#define B3_ID_VF B3_MAKE_ID2('V', 'F')
+#define B3_ID_TXT B3_MAKE_ID2('T', 'X')
+#define B3_ID_SO B3_MAKE_ID2('S', 'O')
+#define B3_ID_SAMPLE B3_MAKE_ID2('S', 'A')
+#define B3_ID_GR B3_MAKE_ID2('G', 'R')
+#define B3_ID_ID B3_MAKE_ID2('I', 'D')
+#define B3_ID_AR B3_MAKE_ID2('A', 'R')
+#define B3_ID_AC B3_MAKE_ID2('A', 'C')
+#define B3_ID_SCRIPT B3_MAKE_ID2('P', 'Y')
+#define B3_ID_FLUIDSIM B3_MAKE_ID2('F', 'S')
+#define B3_ID_NT B3_MAKE_ID2('N', 'T')
+#define B3_ID_BR B3_MAKE_ID2('B', 'R')
+
+#define B3_ID_SEQ B3_MAKE_ID2('S', 'Q')
+#define B3_ID_CO B3_MAKE_ID2('C', 'O')
+#define B3_ID_PO B3_MAKE_ID2('A', 'C')
+#define B3_ID_NLA B3_MAKE_ID2('N', 'L')
+
+#define B3_ID_VS B3_MAKE_ID2('V', 'S')
+#define B3_ID_VN B3_MAKE_ID2('V', 'N')
+
+// ------------------------------------------------------------
+#define B3_FORM B3_MAKE_ID('F', 'O', 'R', 'M')
+#define B3_DDG1 B3_MAKE_ID('3', 'D', 'G', '1')
+#define B3_DDG2 B3_MAKE_ID('3', 'D', 'G', '2')
+#define B3_DDG3 B3_MAKE_ID('3', 'D', 'G', '3')
+#define B3_DDG4 B3_MAKE_ID('3', 'D', 'G', '4')
+#define B3_GOUR B3_MAKE_ID('G', 'O', 'U', 'R')
+#define B3_BLEN B3_MAKE_ID('B', 'L', 'E', 'N')
+#define B3_DER_ B3_MAKE_ID('D', 'E', 'R', '_')
+#define B3_V100 B3_MAKE_ID('V', '1', '0', '0')
+#define B3_DATA B3_MAKE_ID('D', 'A', 'T', 'A')
+#define B3_GLOB B3_MAKE_ID('G', 'L', 'O', 'B')
+#define B3_IMAG B3_MAKE_ID('I', 'M', 'A', 'G')
+#define B3_TEST B3_MAKE_ID('T', 'E', 'S', 'T')
+#define B3_USER B3_MAKE_ID('U', 'S', 'E', 'R')
+
+// ------------------------------------------------------------
+#define B3_DNA1 B3_MAKE_ID('D', 'N', 'A', '1')
+#define B3_REND B3_MAKE_ID('R', 'E', 'N', 'D')
+#define B3_ENDB B3_MAKE_ID('E', 'N', 'D', 'B')
+#define B3_NAME B3_MAKE_ID('N', 'A', 'M', 'E')
+#define B3_SDNA B3_MAKE_ID('S', 'D', 'N', 'A')
+#define B3_TYPE B3_MAKE_ID('T', 'Y', 'P', 'E')
+#define B3_TLEN B3_MAKE_ID('T', 'L', 'E', 'N')
+#define B3_STRC B3_MAKE_ID('S', 'T', 'R', 'C')
+
+// ------------------------------------------------------------
+#define B3_SWITCH_INT(a)    \
+       {                       \
+               char s_i, *p_i;     \
+               p_i = (char *)&(a); \
+               s_i = p_i[0];       \
+               p_i[0] = p_i[3];    \
+               p_i[3] = s_i;       \
+               s_i = p_i[1];       \
+               p_i[1] = p_i[2];    \
+               p_i[2] = s_i;       \
+       }
+
+// ------------------------------------------------------------
+#define B3_SWITCH_SHORT(a)  \
+       {                       \
+               char s_i, *p_i;     \
+               p_i = (char *)&(a); \
+               s_i = p_i[0];       \
+               p_i[0] = p_i[1];    \
+               p_i[1] = s_i;       \
+       }
+
+// ------------------------------------------------------------
+#define B3_SWITCH_LONGINT(a) \
+       {                        \
+               char s_i, *p_i;      \
+               p_i = (char *)&(a);  \
+               s_i = p_i[0];        \
+               p_i[0] = p_i[7];     \
+               p_i[7] = s_i;        \
+               s_i = p_i[1];        \
+               p_i[1] = p_i[6];     \
+               p_i[6] = s_i;        \
+               s_i = p_i[2];        \
+               p_i[2] = p_i[5];     \
+               p_i[5] = s_i;        \
+               s_i = p_i[3];        \
+               p_i[3] = p_i[4];     \
+               p_i[4] = s_i;        \
+       }
+
+#endif  //__B_DEFINES_H__
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
new file mode 100644 (file)
index 0000000..f6c779a
--- /dev/null
@@ -0,0 +1,1653 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.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 "b3File.h"
+#include "b3Common.h"
+#include "b3Chunk.h"
+#include "b3DNA.h"
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "b3Defines.h"
+#include "Bullet3Serialize/Bullet2FileLoader/b3Serializer.h"
+#include "Bullet3Common/b3AlignedAllocator.h"
+#include "Bullet3Common/b3MinMax.h"
+
+#define B3_SIZEOFBLENDERHEADER 12
+#define MAX_ARRAY_LENGTH 512
+using namespace bParse;
+#define MAX_STRLEN 1024
+
+const char *getCleanName(const char *memName, char *buffer)
+{
+       int slen = strlen(memName);
+       assert(slen < MAX_STRLEN);
+       slen = b3Min(slen, MAX_STRLEN);
+       for (int i = 0; i < slen; i++)
+       {
+               if (memName[i] == ']' || memName[i] == '[')
+               {
+                       buffer[i] = 0;  //'_';
+               }
+               else
+               {
+                       buffer[i] = memName[i];
+               }
+       }
+       buffer[slen] = 0;
+       return buffer;
+}
+
+// ----------------------------------------------------- //
+bFile::bFile(const char *filename, const char headerString[7])
+       : mOwnsBuffer(true),
+         mFileBuffer(0),
+         mFileLen(0),
+         mVersion(0),
+         mDataStart(0),
+         mFileDNA(0),
+         mMemoryDNA(0),
+         mFlags(FD_INVALID)
+{
+       for (int i = 0; i < 7; i++)
+       {
+               m_headerString[i] = headerString[i];
+       }
+
+       FILE *fp = fopen(filename, "rb");
+       if (fp)
+       {
+               fseek(fp, 0L, SEEK_END);
+               mFileLen = ftell(fp);
+               fseek(fp, 0L, SEEK_SET);
+
+               mFileBuffer = (char *)malloc(mFileLen + 1);
+               int bytesRead;
+               bytesRead = fread(mFileBuffer, mFileLen, 1, fp);
+
+               fclose(fp);
+
+               //
+               parseHeader();
+       }
+}
+
+// ----------------------------------------------------- //
+bFile::bFile(char *memoryBuffer, int len, const char headerString[7])
+       : mOwnsBuffer(false),
+         mFileBuffer(0),
+         mFileLen(0),
+         mVersion(0),
+         mDataStart(0),
+         mFileDNA(0),
+         mMemoryDNA(0),
+         mFlags(FD_INVALID)
+{
+       for (int i = 0; i < 7; i++)
+       {
+               m_headerString[i] = headerString[i];
+       }
+       mFileBuffer = memoryBuffer;
+       mFileLen = len;
+
+       parseHeader();
+}
+
+// ----------------------------------------------------- //
+bFile::~bFile()
+{
+       if (mOwnsBuffer && mFileBuffer)
+       {
+               free(mFileBuffer);
+               mFileBuffer = 0;
+       }
+
+       delete mMemoryDNA;
+       delete mFileDNA;
+}
+
+// ----------------------------------------------------- //
+void bFile::parseHeader()
+{
+       if (!mFileLen || !mFileBuffer)
+               return;
+
+       char *blenderBuf = mFileBuffer;
+       char header[B3_SIZEOFBLENDERHEADER + 1];
+       memcpy(header, blenderBuf, B3_SIZEOFBLENDERHEADER);
+       header[B3_SIZEOFBLENDERHEADER] = '\0';
+
+       if (strncmp(header, m_headerString, 6) != 0)
+       {
+               memcpy(header, m_headerString, B3_SIZEOFBLENDERHEADER);
+               return;
+       }
+
+       if (header[6] == 'd')
+       {
+               mFlags |= FD_DOUBLE_PRECISION;
+       }
+
+       char *ver = header + 9;
+       mVersion = atoi(ver);
+       if (mVersion <= 241)
+       {
+               //printf("Warning, %d not fully tested : <= 242\n", mVersion);
+       }
+
+       int littleEndian = 1;
+       littleEndian = ((char *)&littleEndian)[0];
+
+       // swap ptr sizes...
+       if (header[7] == '-')
+       {
+               mFlags |= FD_FILE_64;
+               if (!VOID_IS_8)
+                       mFlags |= FD_BITS_VARIES;
+       }
+       else if (VOID_IS_8)
+               mFlags |= FD_BITS_VARIES;
+
+       // swap endian...
+       if (header[8] == 'V')
+       {
+               if (littleEndian == 1)
+                       mFlags |= FD_ENDIAN_SWAP;
+       }
+       else if (littleEndian == 0)
+               mFlags |= FD_ENDIAN_SWAP;
+
+       mFlags |= FD_OK;
+}
+
+// ----------------------------------------------------- //
+bool bFile::ok()
+{
+       return (mFlags & FD_OK) != 0;
+}
+
+// ----------------------------------------------------- //
+void bFile::parseInternal(int verboseMode, char *memDna, int memDnaLength)
+{
+       if ((mFlags & FD_OK) == 0)
+               return;
+
+       char *blenderData = mFileBuffer;
+       bChunkInd dna;
+       dna.oldPtr = 0;
+
+       char *tempBuffer = blenderData;
+       for (int i = 0; i < mFileLen; i++)
+       {
+               // looking for the data's starting position
+               // and the start of SDNA decls
+
+               if (!mDataStart && strncmp(tempBuffer, "REND", 4) == 0)
+                       mDataStart = i;
+
+               if (strncmp(tempBuffer, "DNA1", 4) == 0)
+               {
+                       // read the DNA1 block and extract SDNA
+                       if (getNextBlock(&dna, tempBuffer, mFlags) > 0)
+                       {
+                               if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) == 0)
+                                       dna.oldPtr = (tempBuffer + ChunkUtils::getOffset(mFlags));
+                               else
+                                       dna.oldPtr = 0;
+                       }
+                       else
+                               dna.oldPtr = 0;
+               }
+               // Some Bullet files are missing the DNA1 block
+               // In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME
+               // In Bullet tests its SDNA + NAME
+               else if (strncmp(tempBuffer, "SDNANAME", 8) == 0)
+               {
+                       dna.oldPtr = blenderData + i;
+                       dna.len = mFileLen - i;
+
+                       // Also no REND block, so exit now.
+                       if (mVersion == 276) break;
+               }
+
+               if (mDataStart && dna.oldPtr) break;
+               tempBuffer++;
+       }
+       if (!dna.oldPtr || !dna.len)
+       {
+               //printf("Failed to find DNA1+SDNA pair\n");
+               mFlags &= ~FD_OK;
+               return;
+       }
+
+       mFileDNA = new bDNA();
+
+       ///mFileDNA->init will convert part of DNA file endianness to current CPU endianness if necessary
+       mFileDNA->init((char *)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP) != 0);
+
+       if (mVersion == 276)
+       {
+               int i;
+               for (i = 0; i < mFileDNA->getNumNames(); i++)
+               {
+                       if (strcmp(mFileDNA->getName(i), "int") == 0)
+                       {
+                               mFlags |= FD_BROKEN_DNA;
+                       }
+               }
+               if ((mFlags & FD_BROKEN_DNA) != 0)
+               {
+                       //printf("warning: fixing some broken DNA version\n");
+               }
+       }
+
+       if (verboseMode & FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS)
+               mFileDNA->dumpTypeDefinitions();
+
+       mMemoryDNA = new bDNA();
+       int littleEndian = 1;
+       littleEndian = ((char *)&littleEndian)[0];
+
+       mMemoryDNA->init(memDna, memDnaLength, littleEndian == 0);
+
+       ///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files
+       if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames())
+       {
+               mFlags |= FD_VERSION_VARIES;
+               //printf ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform");
+       }
+
+       // as long as it kept up to date it will be ok!!
+       if (mMemoryDNA->lessThan(mFileDNA))
+       {
+               //printf ("Warning, file DNA is newer than built in.");
+       }
+
+       mFileDNA->initCmpFlags(mMemoryDNA);
+
+       parseData();
+
+       resolvePointers(verboseMode);
+
+       updateOldPointers();
+}
+
+// ----------------------------------------------------- //
+void bFile::swap(char *head, bChunkInd &dataChunk, bool ignoreEndianFlag)
+{
+       char *data = head;
+       short *strc = mFileDNA->getStruct(dataChunk.dna_nr);
+
+       const char s[] = "SoftBodyMaterialData";
+       int szs = sizeof(s);
+       if (strncmp((char *)&dataChunk.code, "ARAY", 4) == 0)
+       {
+               short *oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+               char *oldType = mFileDNA->getType(oldStruct[0]);
+               if (strncmp(oldType, s, szs) == 0)
+               {
+                       return;
+               }
+       }
+
+       int len = mFileDNA->getLength(strc[0]);
+
+       for (int i = 0; i < dataChunk.nr; i++)
+       {
+               swapStruct(dataChunk.dna_nr, data, ignoreEndianFlag);
+               data += len;
+       }
+}
+
+void bFile::swapLen(char *dataPtr)
+{
+       const bool VOID_IS_8 = ((sizeof(void *) == 8));
+       if (VOID_IS_8)
+       {
+               if (mFlags & FD_BITS_VARIES)
+               {
+                       bChunkPtr4 *c = (bChunkPtr4 *)dataPtr;
+                       if ((c->code & 0xFFFF) == 0)
+                               c->code >>= 16;
+                       B3_SWITCH_INT(c->len);
+                       B3_SWITCH_INT(c->dna_nr);
+                       B3_SWITCH_INT(c->nr);
+               }
+               else
+               {
+                       bChunkPtr8 *c = (bChunkPtr8 *)dataPtr;
+                       if ((c->code & 0xFFFF) == 0)
+                               c->code >>= 16;
+                       B3_SWITCH_INT(c->len);
+                       B3_SWITCH_INT(c->dna_nr);
+                       B3_SWITCH_INT(c->nr);
+               }
+       }
+       else
+       {
+               if (mFlags & FD_BITS_VARIES)
+               {
+                       bChunkPtr8 *c = (bChunkPtr8 *)dataPtr;
+                       if ((c->code & 0xFFFF) == 0)
+                               c->code >>= 16;
+                       B3_SWITCH_INT(c->len);
+                       B3_SWITCH_INT(c->dna_nr);
+                       B3_SWITCH_INT(c->nr);
+               }
+               else
+               {
+                       bChunkPtr4 *c = (bChunkPtr4 *)dataPtr;
+                       if ((c->code & 0xFFFF) == 0)
+                               c->code >>= 16;
+                       B3_SWITCH_INT(c->len);
+
+                       B3_SWITCH_INT(c->dna_nr);
+                       B3_SWITCH_INT(c->nr);
+               }
+       }
+}
+
+void bFile::swapDNA(char *ptr)
+{
+       bool swap = ((mFlags & FD_ENDIAN_SWAP) != 0);
+
+       char *data = &ptr[20];
+       //      void bDNA::init(char *data, int len, bool swap)
+       int *intPtr = 0;
+       short *shtPtr = 0;
+       char *cp = 0;
+       int dataLen = 0;
+       //long nr=0;
+       intPtr = (int *)data;
+
+       /*
+               SDNA (4 bytes) (magic number)
+               NAME (4 bytes)
+               <nr> (4 bytes) amount of names (int)
+               <string>
+               <string>
+       */
+
+       if (strncmp(data, "SDNA", 4) == 0)
+       {
+               // skip ++ NAME
+               intPtr++;
+               intPtr++;
+       }
+
+       // Parse names
+       if (swap)
+               dataLen = ChunkUtils::swapInt(*intPtr);
+       else
+               dataLen = *intPtr;
+
+       *intPtr = ChunkUtils::swapInt(*intPtr);
+       intPtr++;
+
+       cp = (char *)intPtr;
+       int i;
+       for (i = 0; i < dataLen; i++)
+       {
+               while (*cp) cp++;
+               cp++;
+       }
+
+       cp = b3AlignPointer(cp, 4);
+
+       /*
+               TYPE (4 bytes)
+               <nr> amount of types (int)
+               <string>
+               <string>
+       */
+
+       intPtr = (int *)cp;
+       assert(strncmp(cp, "TYPE", 4) == 0);
+       intPtr++;
+
+       if (swap)
+               dataLen = ChunkUtils::swapInt(*intPtr);
+       else
+               dataLen = *intPtr;
+
+       *intPtr = ChunkUtils::swapInt(*intPtr);
+
+       intPtr++;
+
+       cp = (char *)intPtr;
+       for (i = 0; i < dataLen; i++)
+       {
+               while (*cp) cp++;
+               cp++;
+       }
+
+       cp = b3AlignPointer(cp, 4);
+
+       /*
+               TLEN (4 bytes)
+               <len> (short) the lengths of types
+               <len>
+       */
+
+       // Parse type lens
+       intPtr = (int *)cp;
+       assert(strncmp(cp, "TLEN", 4) == 0);
+       intPtr++;
+
+       shtPtr = (short *)intPtr;
+       for (i = 0; i < dataLen; i++, shtPtr++)
+       {
+               //??????if (swap)
+               shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+       }
+
+       if (dataLen & 1)
+               shtPtr++;
+
+       /*
+               STRC (4 bytes)
+               <nr> amount of structs (int)
+               <typenr>
+               <nr_of_elems>
+               <typenr>
+               <namenr>
+               <typenr>
+               <namenr>
+       */
+
+       intPtr = (int *)shtPtr;
+       cp = (char *)intPtr;
+       assert(strncmp(cp, "STRC", 4) == 0);
+       intPtr++;
+
+       if (swap)
+               dataLen = ChunkUtils::swapInt(*intPtr);
+       else
+               dataLen = *intPtr;
+
+       *intPtr = ChunkUtils::swapInt(*intPtr);
+
+       intPtr++;
+
+       shtPtr = (short *)intPtr;
+       for (i = 0; i < dataLen; i++)
+       {
+               //if (swap)
+               {
+                       int len = shtPtr[1];
+
+                       shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+                       shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
+
+                       shtPtr += 2;
+
+                       for (int a = 0; a < len; a++, shtPtr += 2)
+                       {
+                               shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+                               shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
+                       }
+               }
+               //              else
+               //                      shtPtr+= (2*shtPtr[1])+2;
+       }
+}
+
+void bFile::writeFile(const char *fileName)
+{
+       FILE *f = fopen(fileName, "wb");
+       fwrite(mFileBuffer, 1, mFileLen, f);
+       fclose(f);
+}
+
+void bFile::preSwap()
+{
+       //const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
+       //FD_ENDIAN_SWAP
+       //byte 8 determines the endianness of the file, little (v) versus big (V)
+       int littleEndian = 1;
+       littleEndian = ((char *)&littleEndian)[0];
+
+       if (mFileBuffer[8] == 'V')
+       {
+               mFileBuffer[8] = 'v';
+       }
+       else
+       {
+               mFileBuffer[8] = 'V';
+       }
+
+       mDataStart = 12;
+
+       char *dataPtr = mFileBuffer + mDataStart;
+
+       bChunkInd dataChunk;
+       dataChunk.code = 0;
+       bool ignoreEndianFlag = true;
+
+       //we always want to swap here
+
+       int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+       //dataPtr += ChunkUtils::getOffset(mFlags);
+       char *dataPtrHead = 0;
+
+       while (1)
+       {
+               // one behind
+               if (dataChunk.code == B3_SDNA || dataChunk.code == B3_DNA1 || dataChunk.code == B3_TYPE || dataChunk.code == B3_TLEN || dataChunk.code == B3_STRC)
+               {
+                       swapDNA(dataPtr);
+                       break;
+               }
+               else
+               {
+                       //if (dataChunk.code == DNA1) break;
+                       dataPtrHead = dataPtr + ChunkUtils::getOffset(mFlags);
+
+                       swapLen(dataPtr);
+                       if (dataChunk.dna_nr >= 0)
+                       {
+                               swap(dataPtrHead, dataChunk, ignoreEndianFlag);
+                       }
+                       else
+                       {
+                               //printf("unknown chunk\n");
+                       }
+               }
+
+               // next please!
+               dataPtr += seek;
+
+               seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+               if (seek < 0)
+                       break;
+       }
+
+       if (mFlags & FD_ENDIAN_SWAP)
+       {
+               mFlags &= ~FD_ENDIAN_SWAP;
+       }
+       else
+       {
+               mFlags |= FD_ENDIAN_SWAP;
+       }
+}
+
+// ----------------------------------------------------- //
+char *bFile::readStruct(char *head, bChunkInd &dataChunk)
+{
+       bool ignoreEndianFlag = false;
+
+       if (mFlags & FD_ENDIAN_SWAP)
+               swap(head, dataChunk, ignoreEndianFlag);
+
+       if (!mFileDNA->flagEqual(dataChunk.dna_nr))
+       {
+               // Ouch! need to rebuild the struct
+               short *oldStruct, *curStruct;
+               char *oldType, *newType;
+               int oldLen, curLen, reverseOld;
+
+               oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+               oldType = mFileDNA->getType(oldStruct[0]);
+
+               oldLen = mFileDNA->getLength(oldStruct[0]);
+
+               if ((mFlags & FD_BROKEN_DNA) != 0)
+               {
+                       if ((strcmp(oldType, "b3QuantizedBvhNodeData") == 0) && oldLen == 20)
+                       {
+                               return 0;
+                       }
+                       if ((strcmp(oldType, "b3ShortIntIndexData") == 0))
+                       {
+                               int allocLen = 2;
+                               char *dataAlloc = new char[(dataChunk.nr * allocLen) + 1];
+                               memset(dataAlloc, 0, (dataChunk.nr * allocLen) + 1);
+                               short *dest = (short *)dataAlloc;
+                               const short *src = (short *)head;
+                               for (int i = 0; i < dataChunk.nr; i++)
+                               {
+                                       dest[i] = src[i];
+                                       if (mFlags & FD_ENDIAN_SWAP)
+                                       {
+                                               B3_SWITCH_SHORT(dest[i]);
+                                       }
+                               }
+                               addDataBlock(dataAlloc);
+                               return dataAlloc;
+                       }
+               }
+
+               ///don't try to convert Link block data, just memcpy it. Other data can be converted.
+               if (strcmp("Link", oldType) != 0)
+               {
+                       reverseOld = mMemoryDNA->getReverseType(oldType);
+
+                       if ((reverseOld != -1))
+                       {
+                               // make sure it's here
+                               //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
+
+                               //
+                               curStruct = mMemoryDNA->getStruct(reverseOld);
+                               newType = mMemoryDNA->getType(curStruct[0]);
+                               curLen = mMemoryDNA->getLength(curStruct[0]);
+
+                               // make sure it's the same
+                               assert((strcmp(oldType, newType) == 0) && "internal error, struct mismatch!");
+
+                               // numBlocks * length
+
+                               int allocLen = (curLen);
+                               char *dataAlloc = new char[(dataChunk.nr * allocLen) + 1];
+                               memset(dataAlloc, 0, (dataChunk.nr * allocLen));
+
+                               // track allocated
+                               addDataBlock(dataAlloc);
+
+                               char *cur = dataAlloc;
+                               char *old = head;
+                               for (int block = 0; block < dataChunk.nr; block++)
+                               {
+                                       bool fixupPointers = true;
+                                       parseStruct(cur, old, dataChunk.dna_nr, reverseOld, fixupPointers);
+                                       mLibPointers.insert(old, (bStructHandle *)cur);
+
+                                       cur += curLen;
+                                       old += oldLen;
+                               }
+                               return dataAlloc;
+                       }
+               }
+               else
+               {
+                       //printf("Link found\n");
+               }
+       }
+       else
+       {
+//#define DEBUG_EQUAL_STRUCTS
+#ifdef DEBUG_EQUAL_STRUCTS
+               short *oldStruct;
+               char *oldType;
+               oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+               oldType = mFileDNA->getType(oldStruct[0]);
+               printf("%s equal structure, just memcpy\n", oldType);
+#endif  //
+       }
+
+       char *dataAlloc = new char[(dataChunk.len) + 1];
+       memset(dataAlloc, 0, dataChunk.len + 1);
+
+       // track allocated
+       addDataBlock(dataAlloc);
+
+       memcpy(dataAlloc, head, dataChunk.len);
+       return dataAlloc;
+}
+
+// ----------------------------------------------------- //
+void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers)
+{
+       if (old_dna == -1) return;
+       if (new_dna == -1) return;
+
+       //disable this, because we need to fixup pointers/ListBase
+       if (0)  //mFileDNA->flagEqual(old_dna))
+       {
+               short *strc = mFileDNA->getStruct(old_dna);
+               int len = mFileDNA->getLength(strc[0]);
+
+               memcpy(strcPtr, dtPtr, len);
+               return;
+       }
+
+       // Ok, now build the struct
+       char *memType, *memName, *cpc, *cpo;
+       short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct;
+       int elementLength, size, revType, old_nr, new_nr, fpLen;
+       short firstStructType;
+
+       // File to memory lookup
+       memoryStruct = mMemoryDNA->getStruct(new_dna);
+       fileStruct = mFileDNA->getStruct(old_dna);
+       firstStruct = fileStruct;
+
+       filePtrOld = fileStruct;
+       firstStructType = mMemoryDNA->getStruct(0)[0];
+
+       // Get number of elements
+       elementLength = memoryStruct[1];
+       memoryStruct += 2;
+
+       cpc = strcPtr;
+       cpo = 0;
+       for (int ele = 0; ele < elementLength; ele++, memoryStruct += 2)
+       {
+               memType = mMemoryDNA->getType(memoryStruct[0]);
+               memName = mMemoryDNA->getName(memoryStruct[1]);
+
+               size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]);
+               revType = mMemoryDNA->getReverseType(memoryStruct[0]);
+
+               if (revType != -1 && memoryStruct[0] >= firstStructType && memName[0] != '*')
+               {
+                       cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld);
+                       if (cpo)
+                       {
+                               int arrayLen = mFileDNA->getArraySizeNew(filePtrOld[1]);
+                               old_nr = mFileDNA->getReverseType(memType);
+                               new_nr = revType;
+                               fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]);
+                               if (arrayLen == 1)
+                               {
+                                       parseStruct(cpc, cpo, old_nr, new_nr, fixupPointers);
+                               }
+                               else
+                               {
+                                       char *tmpCpc = cpc;
+                                       char *tmpCpo = cpo;
+
+                                       for (int i = 0; i < arrayLen; i++)
+                                       {
+                                               parseStruct(tmpCpc, tmpCpo, old_nr, new_nr, fixupPointers);
+                                               tmpCpc += size / arrayLen;
+                                               tmpCpo += fpLen / arrayLen;
+                                       }
+                               }
+                               cpc += size;
+                               cpo += fpLen;
+                       }
+                       else
+                               cpc += size;
+               }
+               else
+               {
+                       getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr, fixupPointers);
+                       cpc += size;
+               }
+       }
+}
+
+// ----------------------------------------------------- //
+static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
+{
+#define b3GetEle(value, current, type, cast, size, ptr) \
+       if (strcmp(current, type) == 0)                     \
+       {                                                   \
+               value = (*(cast *)ptr);                         \
+               ptr += size;                                    \
+       }
+
+#define b3SetEle(value, current, type, cast, size, ptr) \
+       if (strcmp(current, type) == 0)                     \
+       {                                                   \
+               (*(cast *)ptr) = (cast)value;                   \
+               ptr += size;                                    \
+       }
+       double value = 0.0;
+
+       for (int i = 0; i < arrayLen; i++)
+       {
+               b3GetEle(value, old, "char", char, sizeof(char), oldPtr);
+               b3SetEle(value, cur, "char", char, sizeof(char), curData);
+               b3GetEle(value, old, "short", short, sizeof(short), oldPtr);
+               b3SetEle(value, cur, "short", short, sizeof(short), curData);
+               b3GetEle(value, old, "ushort", unsigned short, sizeof(unsigned short), oldPtr);
+               b3SetEle(value, cur, "ushort", unsigned short, sizeof(unsigned short), curData);
+               b3GetEle(value, old, "int", int, sizeof(int), oldPtr);
+               b3SetEle(value, cur, "int", int, sizeof(int), curData);
+               b3GetEle(value, old, "long", int, sizeof(int), oldPtr);
+               b3SetEle(value, cur, "long", int, sizeof(int), curData);
+               b3GetEle(value, old, "float", float, sizeof(float), oldPtr);
+               b3SetEle(value, cur, "float", float, sizeof(float), curData);
+               b3GetEle(value, old, "double", double, sizeof(double), oldPtr);
+               b3SetEle(value, cur, "double", double, sizeof(double), curData);
+       }
+}
+
+// ----------------------------------------------------- //
+void bFile::swapData(char *data, short type, int arraySize, bool ignoreEndianFlag)
+{
+       if (ignoreEndianFlag || (mFlags & FD_ENDIAN_SWAP))
+       {
+               if (type == 2 || type == 3)
+               {
+                       short *sp = (short *)data;
+                       for (int i = 0; i < arraySize; i++)
+                       {
+                               sp[0] = ChunkUtils::swapShort(sp[0]);
+                               sp++;
+                       }
+               }
+               if (type > 3 && type < 8)
+               {
+                       char c;
+                       char *cp = data;
+                       for (int i = 0; i < arraySize; i++)
+                       {
+                               c = cp[0];
+                               cp[0] = cp[3];
+                               cp[3] = c;
+                               c = cp[1];
+                               cp[1] = cp[2];
+                               cp[2] = c;
+                               cp += 4;
+                       }
+               }
+       }
+}
+
+void bFile::safeSwapPtr(char *dst, const char *src)
+{
+       if (!src || !dst)
+               return;
+
+       int ptrFile = mFileDNA->getPointerSize();
+       int ptrMem = mMemoryDNA->getPointerSize();
+
+       if (ptrFile == ptrMem)
+       {
+               memcpy(dst, src, ptrMem);
+       }
+       else if (ptrMem == 4 && ptrFile == 8)
+       {
+               b3PointerUid *oldPtr = (b3PointerUid *)src;
+               b3PointerUid *newPtr = (b3PointerUid *)dst;
+
+               if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
+               {
+                       //Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers
+                       //so it can be used to distinguish between .blend and .bullet
+                       newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
+               }
+               else
+               {
+                       //deal with pointers the Blender .blend style way, see
+                       //readfile.c in the Blender source tree
+                       b3Long64 longValue = *((b3Long64 *)src);
+                       //endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros
+                       if (mFlags & FD_ENDIAN_SWAP)
+                               B3_SWITCH_LONGINT(longValue);
+                       *((int *)dst) = (int)(longValue >> 3);
+               }
+       }
+       else if (ptrMem == 8 && ptrFile == 4)
+       {
+               b3PointerUid *oldPtr = (b3PointerUid *)src;
+               b3PointerUid *newPtr = (b3PointerUid *)dst;
+               if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
+               {
+                       newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
+                       newPtr->m_uniqueIds[1] = 0;
+               }
+               else
+               {
+                       *((b3Long64 *)dst) = *((int *)src);
+               }
+       }
+       else
+       {
+               printf("%d %d\n", ptrFile, ptrMem);
+               assert(0 && "Invalid pointer len");
+       }
+}
+
+// ----------------------------------------------------- //
+void bFile::getMatchingFileDNA(short *dna_addr, const char *lookupName, const char *lookupType, char *strcData, char *data, bool fixupPointers)
+{
+       // find the matching memory dna data
+       // to the file being loaded. Fill the
+       // memory with the file data...
+
+       int len = dna_addr[1];
+       dna_addr += 2;
+
+       for (int i = 0; i < len; i++, dna_addr += 2)
+       {
+               const char *type = mFileDNA->getType(dna_addr[0]);
+               const char *name = mFileDNA->getName(dna_addr[1]);
+
+               int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
+
+               if ((mFlags & FD_BROKEN_DNA) != 0)
+               {
+                       if ((strcmp(type, "short") == 0) && (strcmp(name, "int") == 0))
+                       {
+                               eleLen = 0;
+                       }
+               }
+
+               if (strcmp(lookupName, name) == 0)
+               {
+                       //int arrayLenold = mFileDNA->getArraySize((char*)name.c_str());
+                       int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]);
+                       //assert(arrayLenold == arrayLen);
+
+                       if (name[0] == '*')
+                       {
+                               // cast pointers
+                               int ptrFile = mFileDNA->getPointerSize();
+                               int ptrMem = mMemoryDNA->getPointerSize();
+                               safeSwapPtr(strcData, data);
+
+                               if (fixupPointers)
+                               {
+                                       if (arrayLen > 1)
+                                       {
+                                               //void **sarray = (void**)strcData;
+                                               //void **darray = (void**)data;
+
+                                               char *cpc, *cpo;
+                                               cpc = (char *)strcData;
+                                               cpo = (char *)data;
+
+                                               for (int a = 0; a < arrayLen; a++)
+                                               {
+                                                       safeSwapPtr(cpc, cpo);
+                                                       m_pointerFixupArray.push_back(cpc);
+                                                       cpc += ptrMem;
+                                                       cpo += ptrFile;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (name[1] == '*')
+                                                       m_pointerPtrFixupArray.push_back(strcData);
+                                               else
+                                                       m_pointerFixupArray.push_back(strcData);
+                                       }
+                               }
+                               else
+                               {
+                                       //                                      printf("skipped %s %s : %x\n",type.c_str(),name.c_str(),strcData);
+                               }
+                       }
+
+                       else if (strcmp(type, lookupType) == 0)
+                               memcpy(strcData, data, eleLen);
+                       else
+                               getElement(arrayLen, lookupType, type, data, strcData);
+
+                       // --
+                       return;
+               }
+               data += eleLen;
+       }
+}
+
+// ----------------------------------------------------- //
+char *bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
+{
+       short *old = firstStruct;  //mFileDNA->getStruct(old_nr);
+       int elementLength = old[1];
+       old += 2;
+
+       for (int i = 0; i < elementLength; i++, old += 2)
+       {
+               char *type = mFileDNA->getType(old[0]);
+               char *name = mFileDNA->getName(old[1]);
+               int len = mFileDNA->getElementSize(old[0], old[1]);
+
+               if (strcmp(lookupName, name) == 0)
+               {
+                       if (strcmp(type, lookupType) == 0)
+                       {
+                               if (foundPos)
+                                       *foundPos = old;
+                               return data;
+                       }
+                       return 0;
+               }
+               data += len;
+       }
+       return 0;
+}
+
+// ----------------------------------------------------- //
+void bFile::swapStruct(int dna_nr, char *data, bool ignoreEndianFlag)
+{
+       if (dna_nr == -1) return;
+
+       short *strc = mFileDNA->getStruct(dna_nr);
+       //short *firstStrc = strc;
+
+       int elementLen = strc[1];
+       strc += 2;
+
+       short first = mFileDNA->getStruct(0)[0];
+
+       char *buf = data;
+       for (int i = 0; i < elementLen; i++, strc += 2)
+       {
+               char *type = mFileDNA->getType(strc[0]);
+               char *name = mFileDNA->getName(strc[1]);
+
+               int size = mFileDNA->getElementSize(strc[0], strc[1]);
+               if (strc[0] >= first && name[0] != '*')
+               {
+                       int old_nr = mFileDNA->getReverseType(type);
+                       int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
+                       if (arrayLen == 1)
+                       {
+                               swapStruct(old_nr, buf, ignoreEndianFlag);
+                       }
+                       else
+                       {
+                               char *tmpBuf = buf;
+                               for (int i = 0; i < arrayLen; i++)
+                               {
+                                       swapStruct(old_nr, tmpBuf, ignoreEndianFlag);
+                                       tmpBuf += size / arrayLen;
+                               }
+                       }
+               }
+               else
+               {
+                       //int arrayLenOld = mFileDNA->getArraySize(name);
+                       int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
+                       //assert(arrayLenOld == arrayLen);
+                       swapData(buf, strc[0], arrayLen, ignoreEndianFlag);
+               }
+               buf += size;
+       }
+}
+
+void bFile::resolvePointersMismatch()
+{
+       //      printf("resolvePointersStructMismatch\n");
+
+       int i;
+
+       for (i = 0; i < m_pointerFixupArray.size(); i++)
+       {
+               char *cur = m_pointerFixupArray.at(i);
+               void **ptrptr = (void **)cur;
+               void *ptr = *ptrptr;
+               ptr = findLibPointer(ptr);
+               if (ptr)
+               {
+                       //printf("Fixup pointer!\n");
+                       *(ptrptr) = ptr;
+               }
+               else
+               {
+                       //                      printf("pointer not found: %x\n",cur);
+               }
+       }
+
+       for (i = 0; i < m_pointerPtrFixupArray.size(); i++)
+       {
+               char *cur = m_pointerPtrFixupArray.at(i);
+               void **ptrptr = (void **)cur;
+
+               bChunkInd *block = m_chunkPtrPtrMap.find(*ptrptr);
+               if (block)
+               {
+                       int ptrMem = mMemoryDNA->getPointerSize();
+                       int ptrFile = mFileDNA->getPointerSize();
+
+                       int blockLen = block->len / ptrFile;
+
+                       void *onptr = findLibPointer(*ptrptr);
+                       if (onptr)
+                       {
+                               char *newPtr = new char[blockLen * ptrMem];
+                               addDataBlock(newPtr);
+                               memset(newPtr, 0, blockLen * ptrMem);
+
+                               void **onarray = (void **)onptr;
+                               char *oldPtr = (char *)onarray;
+
+                               int p = 0;
+                               while (blockLen-- > 0)
+                               {
+                                       b3PointerUid dp = {{0}};
+                                       safeSwapPtr((char *)dp.m_uniqueIds, oldPtr);
+
+                                       void **tptr = (void **)(newPtr + p * ptrMem);
+                                       *tptr = findLibPointer(dp.m_ptr);
+
+                                       oldPtr += ptrFile;
+                                       ++p;
+                               }
+
+                               *ptrptr = newPtr;
+                       }
+               }
+       }
+}
+
+///this loop only works fine if the Blender DNA structure of the file matches the headerfiles
+void bFile::resolvePointersChunk(const bChunkInd &dataChunk, int verboseMode)
+{
+       bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+       short int *oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+       short oldLen = fileDna->getLength(oldStruct[0]);
+       //char* structType = fileDna->getType(oldStruct[0]);
+
+       char *cur = (char *)findLibPointer(dataChunk.oldPtr);
+       for (int block = 0; block < dataChunk.nr; block++)
+       {
+               resolvePointersStructRecursive(cur, dataChunk.dna_nr, verboseMode, 1);
+               cur += oldLen;
+       }
+}
+
+int bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, int verboseMode, int recursion)
+{
+       bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+       char *memType;
+       char *memName;
+       short firstStructType = fileDna->getStruct(0)[0];
+
+       char *elemPtr = strcPtr;
+
+       short int *oldStruct = fileDna->getStruct(dna_nr);
+
+       int elementLength = oldStruct[1];
+       oldStruct += 2;
+
+       int totalSize = 0;
+
+       for (int ele = 0; ele < elementLength; ele++, oldStruct += 2)
+       {
+               memType = fileDna->getType(oldStruct[0]);
+               memName = fileDna->getName(oldStruct[1]);
+
+               int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
+               if (memName[0] == '*')
+               {
+                       if (arrayLen > 1)
+                       {
+                               void **array = (void **)elemPtr;
+                               for (int a = 0; a < arrayLen; a++)
+                               {
+                                       if (verboseMode & FD_VERBOSE_EXPORT_XML)
+                                       {
+                                               for (int i = 0; i < recursion; i++)
+                                               {
+                                                       printf("  ");
+                                               }
+                                               //skip the *
+                                               printf("<%s type=\"pointer\"> ", &memName[1]);
+                                               printf("%p ", array[a]);
+                                               printf("</%s>\n", &memName[1]);
+                                       }
+
+                                       array[a] = findLibPointer(array[a]);
+                               }
+                       }
+                       else
+                       {
+                               void **ptrptr = (void **)elemPtr;
+                               void *ptr = *ptrptr;
+                               if (verboseMode & FD_VERBOSE_EXPORT_XML)
+                               {
+                                       for (int i = 0; i < recursion; i++)
+                                       {
+                                               printf("  ");
+                                       }
+                                       printf("<%s type=\"pointer\"> ", &memName[1]);
+                                       printf("%p ", ptr);
+                                       printf("</%s>\n", &memName[1]);
+                               }
+                               ptr = findLibPointer(ptr);
+
+                               if (ptr)
+                               {
+                                       //                              printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
+                                       *(ptrptr) = ptr;
+                                       if (memName[1] == '*' && ptrptr && *ptrptr)
+                                       {
+                                               // This will only work if the given     **array is continuous
+                                               void **array = (void **)*(ptrptr);
+                                               void *np = array[0];
+                                               int n = 0;
+                                               while (np)
+                                               {
+                                                       np = findLibPointer(array[n]);
+                                                       if (np) array[n] = np;
+                                                       n++;
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       //                              printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
+                               }
+                       }
+               }
+               else
+               {
+                       int revType = fileDna->getReverseType(oldStruct[0]);
+                       if (oldStruct[0] >= firstStructType)  //revType != -1 &&
+                       {
+                               char cleanName[MAX_STRLEN];
+                               getCleanName(memName, cleanName);
+
+                               int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
+                               int byteOffset = 0;
+
+                               if (verboseMode & FD_VERBOSE_EXPORT_XML)
+                               {
+                                       for (int i = 0; i < recursion; i++)
+                                       {
+                                               printf("  ");
+                                       }
+
+                                       if (arrayLen > 1)
+                                       {
+                                               printf("<%s type=\"%s\" count=%d>\n", cleanName, memType, arrayLen);
+                                       }
+                                       else
+                                       {
+                                               printf("<%s type=\"%s\">\n", cleanName, memType);
+                                       }
+                               }
+
+                               for (int i = 0; i < arrayLen; i++)
+                               {
+                                       byteOffset += resolvePointersStructRecursive(elemPtr + byteOffset, revType, verboseMode, recursion + 1);
+                               }
+                               if (verboseMode & FD_VERBOSE_EXPORT_XML)
+                               {
+                                       for (int i = 0; i < recursion; i++)
+                                       {
+                                               printf("  ");
+                                       }
+                                       printf("</%s>\n", cleanName);
+                               }
+                       }
+                       else
+                       {
+                               //export a simple type
+                               if (verboseMode & FD_VERBOSE_EXPORT_XML)
+                               {
+                                       if (arrayLen > MAX_ARRAY_LENGTH)
+                                       {
+                                               printf("too long\n");
+                                       }
+                                       else
+                                       {
+                                               //printf("%s %s\n",memType,memName);
+
+                                               bool isIntegerType = (strcmp(memType, "char") == 0) || (strcmp(memType, "int") == 0) || (strcmp(memType, "short") == 0);
+
+                                               if (isIntegerType)
+                                               {
+                                                       const char *newtype = "int";
+                                                       int dbarray[MAX_ARRAY_LENGTH];
+                                                       int *dbPtr = 0;
+                                                       char *tmp = elemPtr;
+                                                       dbPtr = &dbarray[0];
+                                                       if (dbPtr)
+                                                       {
+                                                               char cleanName[MAX_STRLEN];
+                                                               getCleanName(memName, cleanName);
+
+                                                               int i;
+                                                               getElement(arrayLen, newtype, memType, tmp, (char *)dbPtr);
+                                                               for (i = 0; i < recursion; i++)
+                                                                       printf("  ");
+                                                               if (arrayLen == 1)
+                                                                       printf("<%s type=\"%s\">", cleanName, memType);
+                                                               else
+                                                                       printf("<%s type=\"%s\" count=%d>", cleanName, memType, arrayLen);
+                                                               for (i = 0; i < arrayLen; i++)
+                                                                       printf(" %d ", dbPtr[i]);
+                                                               printf("</%s>\n", cleanName);
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       const char *newtype = "double";
+                                                       double dbarray[MAX_ARRAY_LENGTH];
+                                                       double *dbPtr = 0;
+                                                       char *tmp = elemPtr;
+                                                       dbPtr = &dbarray[0];
+                                                       if (dbPtr)
+                                                       {
+                                                               int i;
+                                                               getElement(arrayLen, newtype, memType, tmp, (char *)dbPtr);
+                                                               for (i = 0; i < recursion; i++)
+                                                                       printf("  ");
+                                                               char cleanName[MAX_STRLEN];
+                                                               getCleanName(memName, cleanName);
+
+                                                               if (arrayLen == 1)
+                                                               {
+                                                                       printf("<%s type=\"%s\">", memName, memType);
+                                                               }
+                                                               else
+                                                               {
+                                                                       printf("<%s type=\"%s\" count=%d>", cleanName, memType, arrayLen);
+                                                               }
+                                                               for (i = 0; i < arrayLen; i++)
+                                                                       printf(" %f ", dbPtr[i]);
+                                                               printf("</%s>\n", cleanName);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]);
+               totalSize += size;
+               elemPtr += size;
+       }
+
+       return totalSize;
+}
+
+///Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory structures
+void bFile::resolvePointers(int verboseMode)
+{
+       bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+       //char *dataPtr = mFileBuffer+mDataStart;
+
+       if (1)  //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES))
+       {
+               resolvePointersMismatch();
+       }
+
+       {
+               if (verboseMode & FD_VERBOSE_EXPORT_XML)
+               {
+                       printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+                       int numitems = m_chunks.size();
+                       printf("<bullet_physics version=%d itemcount = %d>\n", b3GetVersion(), numitems);
+               }
+               for (int i = 0; i < m_chunks.size(); i++)
+               {
+                       const bChunkInd &dataChunk = m_chunks.at(i);
+
+                       if (!mFileDNA || fileDna->flagEqual(dataChunk.dna_nr))
+                       {
+                               //dataChunk.len
+                               short int *oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+                               char *oldType = fileDna->getType(oldStruct[0]);
+
+                               if (verboseMode & FD_VERBOSE_EXPORT_XML)
+                                       printf(" <%s pointer=%p>\n", oldType, dataChunk.oldPtr);
+
+                               resolvePointersChunk(dataChunk, verboseMode);
+
+                               if (verboseMode & FD_VERBOSE_EXPORT_XML)
+                                       printf(" </%s>\n", oldType);
+                       }
+                       else
+                       {
+                               //printf("skipping mStruct\n");
+                       }
+               }
+               if (verboseMode & FD_VERBOSE_EXPORT_XML)
+               {
+                       printf("</bullet_physics>\n");
+               }
+       }
+}
+
+// ----------------------------------------------------- //
+void *bFile::findLibPointer(void *ptr)
+{
+       bStructHandle **ptrptr = getLibPointers().find(ptr);
+       if (ptrptr)
+               return *ptrptr;
+       return 0;
+}
+
+void bFile::updateOldPointers()
+{
+       int i;
+
+       for (i = 0; i < m_chunks.size(); i++)
+       {
+               bChunkInd &dataChunk = m_chunks[i];
+               dataChunk.oldPtr = findLibPointer(dataChunk.oldPtr);
+       }
+}
+void bFile::dumpChunks(bParse::bDNA *dna)
+{
+       int i;
+
+       for (i = 0; i < m_chunks.size(); i++)
+       {
+               bChunkInd &dataChunk = m_chunks[i];
+               char *codeptr = (char *)&dataChunk.code;
+               char codestr[5] = {codeptr[0], codeptr[1], codeptr[2], codeptr[3], 0};
+
+               short *newStruct = dna->getStruct(dataChunk.dna_nr);
+               char *typeName = dna->getType(newStruct[0]);
+               printf("%3d: %s  ", i, typeName);
+
+               printf("code=%s  ", codestr);
+
+               printf("ptr=%p  ", dataChunk.oldPtr);
+               printf("len=%d  ", dataChunk.len);
+               printf("nr=%d  ", dataChunk.nr);
+               if (dataChunk.nr != 1)
+               {
+                       printf("not 1\n");
+               }
+               printf("\n");
+       }
+
+#if 0
+       IDFinderData ifd;
+       ifd.success = 0;
+       ifd.IDname = NULL;
+       ifd.just_print_it = 1;
+       for (i=0; i<bf->m_blocks.size(); ++i)
+       {
+               BlendBlock* bb = bf->m_blocks[i];
+               printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]",              bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size());
+               block_ID_finder(bb, bf, &ifd);
+               printf("\n");
+       }
+#endif
+}
+
+void bFile::writeChunks(FILE *fp, bool fixupPointers)
+{
+       bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+       for (int i = 0; i < m_chunks.size(); i++)
+       {
+               bChunkInd &dataChunk = m_chunks.at(i);
+
+               // Ouch! need to rebuild the struct
+               short *oldStruct, *curStruct;
+               char *oldType, *newType;
+               int oldLen, curLen, reverseOld;
+
+               oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+               oldType = fileDna->getType(oldStruct[0]);
+               oldLen = fileDna->getLength(oldStruct[0]);
+               ///don't try to convert Link block data, just memcpy it. Other data can be converted.
+               reverseOld = mMemoryDNA->getReverseType(oldType);
+
+               if ((reverseOld != -1))
+               {
+                       // make sure it's here
+                       //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
+                       //
+                       curStruct = mMemoryDNA->getStruct(reverseOld);
+                       newType = mMemoryDNA->getType(curStruct[0]);
+                       // make sure it's the same
+                       assert((strcmp(oldType, newType) == 0) && "internal error, struct mismatch!");
+
+                       curLen = mMemoryDNA->getLength(curStruct[0]);
+                       dataChunk.dna_nr = reverseOld;
+                       if (strcmp("Link", oldType) != 0)
+                       {
+                               dataChunk.len = curLen * dataChunk.nr;
+                       }
+                       else
+                       {
+                               //                              printf("keep length of link = %d\n",dataChunk.len);
+                       }
+
+                       //write the structure header
+                       fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
+
+                       short int *curStruct1;
+                       curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr);
+                       assert(curStruct1 == curStruct);
+
+                       char *cur = fixupPointers ? (char *)findLibPointer(dataChunk.oldPtr) : (char *)dataChunk.oldPtr;
+
+                       //write the actual contents of the structure(s)
+                       fwrite(cur, dataChunk.len, 1, fp);
+               }
+               else
+               {
+                       printf("serious error, struct mismatch: don't write\n");
+               }
+       }
+}
+
+// ----------------------------------------------------- //
+int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
+{
+       bool swap = false;
+       bool varies = false;
+
+       if (flags & FD_ENDIAN_SWAP)
+               swap = true;
+       if (flags & FD_BITS_VARIES)
+               varies = true;
+
+       if (VOID_IS_8)
+       {
+               if (varies)
+               {
+                       bChunkPtr4 head;
+                       memcpy(&head, dataPtr, sizeof(bChunkPtr4));
+
+                       bChunkPtr8 chunk;
+
+                       chunk.code = head.code;
+                       chunk.len = head.len;
+                       chunk.m_uniqueInts[0] = head.m_uniqueInt;
+                       chunk.m_uniqueInts[1] = 0;
+                       chunk.dna_nr = head.dna_nr;
+                       chunk.nr = head.nr;
+
+                       if (swap)
+                       {
+                               if ((chunk.code & 0xFFFF) == 0)
+                                       chunk.code >>= 16;
+
+                               B3_SWITCH_INT(chunk.len);
+                               B3_SWITCH_INT(chunk.dna_nr);
+                               B3_SWITCH_INT(chunk.nr);
+                       }
+
+                       memcpy(dataChunk, &chunk, sizeof(bChunkInd));
+               }
+               else
+               {
+                       bChunkPtr8 c;
+                       memcpy(&c, dataPtr, sizeof(bChunkPtr8));
+
+                       if (swap)
+                       {
+                               if ((c.code & 0xFFFF) == 0)
+                                       c.code >>= 16;
+
+                               B3_SWITCH_INT(c.len);
+                               B3_SWITCH_INT(c.dna_nr);
+                               B3_SWITCH_INT(c.nr);
+                       }
+
+                       memcpy(dataChunk, &c, sizeof(bChunkInd));
+               }
+       }
+       else
+       {
+               if (varies)
+               {
+                       bChunkPtr8 head;
+                       memcpy(&head, dataPtr, sizeof(bChunkPtr8));
+
+                       bChunkPtr4 chunk;
+                       chunk.code = head.code;
+                       chunk.len = head.len;
+
+                       if (head.m_uniqueInts[0] == head.m_uniqueInts[1])
+                       {
+                               chunk.m_uniqueInt = head.m_uniqueInts[0];
+                       }
+                       else
+                       {
+                               b3Long64 oldPtr = 0;
+                               memcpy(&oldPtr, &head.m_uniqueInts[0], 8);
+                               if (swap)
+                                       B3_SWITCH_LONGINT(oldPtr);
+                               chunk.m_uniqueInt = (int)(oldPtr >> 3);
+                       }
+
+                       chunk.dna_nr = head.dna_nr;
+                       chunk.nr = head.nr;
+
+                       if (swap)
+                       {
+                               if ((chunk.code & 0xFFFF) == 0)
+                                       chunk.code >>= 16;
+
+                               B3_SWITCH_INT(chunk.len);
+                               B3_SWITCH_INT(chunk.dna_nr);
+                               B3_SWITCH_INT(chunk.nr);
+                       }
+
+                       memcpy(dataChunk, &chunk, sizeof(bChunkInd));
+               }
+               else
+               {
+                       bChunkPtr4 c;
+                       memcpy(&c, dataPtr, sizeof(bChunkPtr4));
+
+                       if (swap)
+                       {
+                               if ((c.code & 0xFFFF) == 0)
+                                       c.code >>= 16;
+
+                               B3_SWITCH_INT(c.len);
+                               B3_SWITCH_INT(c.dna_nr);
+                               B3_SWITCH_INT(c.nr);
+                       }
+                       memcpy(dataChunk, &c, sizeof(bChunkInd));
+               }
+       }
+
+       if (dataChunk->len < 0)
+               return -1;
+
+#if 0
+       print ("----------");
+       print (dataChunk->code);
+       print (dataChunk->len);
+       print (dataChunk->old);
+       print (dataChunk->dna_nr);
+       print (dataChunk->nr);
+#endif
+       return (dataChunk->len + ChunkUtils::getOffset(flags));
+}
+
+//eof
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3File.h b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3File.h
new file mode 100644 (file)
index 0000000..bda229c
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.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.
+*/
+
+#ifndef __BFILE_H__
+#define __BFILE_H__
+
+#include "b3Common.h"
+#include "b3Chunk.h"
+#include <stdio.h>
+
+namespace bParse
+{
+// ----------------------------------------------------- //
+enum bFileFlags
+{
+       FD_INVALID = 0,
+       FD_OK = 1,
+       FD_VOID_IS_8 = 2,
+       FD_ENDIAN_SWAP = 4,
+       FD_FILE_64 = 8,
+       FD_BITS_VARIES = 16,
+       FD_VERSION_VARIES = 32,
+       FD_DOUBLE_PRECISION = 64,
+       FD_BROKEN_DNA = 128
+};
+
+enum bFileVerboseMode
+{
+       FD_VERBOSE_EXPORT_XML = 1,
+       FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS = 2,
+       FD_VERBOSE_DUMP_CHUNKS = 4,
+       FD_VERBOSE_DUMP_FILE_INFO = 8,
+};
+// ----------------------------------------------------- //
+class bFile
+{
+protected:
+       char m_headerString[7];
+
+       bool mOwnsBuffer;
+       char *mFileBuffer;
+       int mFileLen;
+       int mVersion;
+
+       bPtrMap mLibPointers;
+
+       int mDataStart;
+       bDNA *mFileDNA;
+       bDNA *mMemoryDNA;
+
+       b3AlignedObjectArray<char *> m_pointerFixupArray;
+       b3AlignedObjectArray<char *> m_pointerPtrFixupArray;
+
+       b3AlignedObjectArray<bChunkInd> m_chunks;
+       b3HashMap<b3HashPtr, bChunkInd> m_chunkPtrPtrMap;
+
+       //
+
+       bPtrMap mDataPointers;
+
+       int mFlags;
+
+       // ////////////////////////////////////////////////////////////////////////////
+
+       // buffer offset util
+       int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags);
+       void safeSwapPtr(char *dst, const char *src);
+
+       virtual void parseHeader();
+
+       virtual void parseData() = 0;
+
+       void resolvePointersMismatch();
+       void resolvePointersChunk(const bChunkInd &dataChunk, int verboseMode);
+
+       int resolvePointersStructRecursive(char *strcPtr, int old_dna, int verboseMode, int recursion);
+       //void swapPtr(char *dst, char *src);
+
+       void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers);
+       void getMatchingFileDNA(short *old, const char *lookupName, const char *lookupType, char *strcData, char *data, bool fixupPointers);
+       char *getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos);
+
+       void swap(char *head, class bChunkInd &ch, bool ignoreEndianFlag);
+       void swapData(char *data, short type, int arraySize, bool ignoreEndianFlag);
+       void swapStruct(int dna_nr, char *data, bool ignoreEndianFlag);
+       void swapLen(char *dataPtr);
+       void swapDNA(char *ptr);
+
+       char *readStruct(char *head, class bChunkInd &chunk);
+       char *getAsString(int code);
+
+       void parseInternal(int verboseMode, char *memDna, int memDnaLength);
+
+public:
+       bFile(const char *filename, const char headerString[7]);
+
+       //todo: make memoryBuffer const char
+       //bFile( const char *memoryBuffer, int len);
+       bFile(char *memoryBuffer, int len, const char headerString[7]);
+       virtual ~bFile();
+
+       bDNA *getFileDNA()
+       {
+               return mFileDNA;
+       }
+
+       virtual void addDataBlock(char *dataBlock) = 0;
+
+       int getFlags() const
+       {
+               return mFlags;
+       }
+
+       bPtrMap &getLibPointers()
+       {
+               return mLibPointers;
+       }
+
+       void *findLibPointer(void *ptr);
+
+       bool ok();
+
+       virtual void parse(int verboseMode) = 0;
+
+       virtual int write(const char *fileName, bool fixupPointers = false) = 0;
+
+       virtual void writeChunks(FILE *fp, bool fixupPointers);
+
+       virtual void writeDNA(FILE *fp) = 0;
+
+       void updateOldPointers();
+       void resolvePointers(int verboseMode);
+
+       void dumpChunks(bDNA *dna);
+
+       int getVersion() const
+       {
+               return mVersion;
+       }
+       //pre-swap the endianness, so that data loaded on a target with different endianness doesn't need to be swapped
+       void preSwap();
+       void writeFile(const char *fileName);
+};
+}  // namespace bParse
+
+#endif  //__BFILE_H__
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp
new file mode 100644 (file)
index 0000000..ea4a8e2
--- /dev/null
@@ -0,0 +1,18062 @@
+char b3s_bulletDNAstr[] = {
+       char(83),
+       char(68),
+       char(78),
+       char(65),
+       char(78),
+       char(65),
+       char(77),
+       char(69),
+       char(63),
+       char(1),
+       char(0),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(97),
+       char(112),
+       char(97),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(100),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(79),
+       char(98),
+       char(106),
+       char(101),
+       char(99),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(0),
+       char(42),
+       char(102),
+       char(105),
+       char(114),
+       char(115),
+       char(116),
+       char(0),
+       char(42),
+       char(108),
+       char(97),
+       char(115),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(102),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(115),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(108),
+       char(91),
+       char(51),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(97),
+       char(115),
+       char(105),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(111),
+       char(114),
+       char(105),
+       char(103),
+       char(105),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(111),
+       char(111),
+       char(116),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(117),
+       char(98),
+       char(116),
+       char(114),
+       char(101),
+       char(101),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(113),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(65),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(105),
+       char(110),
+       char(91),
+       char(51),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(113),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(65),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(97),
+       char(120),
+       char(91),
+       char(51),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(105),
+       char(110),
+       char(79),
+       char(114),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(97),
+       char(120),
+       char(79),
+       char(114),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(115),
+       char(99),
+       char(97),
+       char(112),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(117),
+       char(98),
+       char(80),
+       char(97),
+       char(114),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(115),
+       char(99),
+       char(97),
+       char(112),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(79),
+       char(114),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(118),
+       char(104),
+       char(65),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(105),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(118),
+       char(104),
+       char(65),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(97),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(118),
+       char(104),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(117),
+       char(114),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(105),
+       char(103),
+       char(117),
+       char(111),
+       char(117),
+       char(115),
+       char(76),
+       char(101),
+       char(97),
+       char(102),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(105),
+       char(103),
+       char(117),
+       char(111),
+       char(117),
+       char(115),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(116),
+       char(105),
+       char(103),
+       char(117),
+       char(111),
+       char(117),
+       char(115),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(113),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(105),
+       char(103),
+       char(117),
+       char(111),
+       char(117),
+       char(115),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(115),
+       char(117),
+       char(98),
+       char(84),
+       char(114),
+       char(101),
+       char(101),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(114),
+       char(97),
+       char(118),
+       char(101),
+       char(114),
+       char(115),
+       char(97),
+       char(108),
+       char(77),
+       char(111),
+       char(100),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(83),
+       char(117),
+       char(98),
+       char(116),
+       char(114),
+       char(101),
+       char(101),
+       char(72),
+       char(101),
+       char(97),
+       char(100),
+       char(101),
+       char(114),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(110),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(110),
+       char(103),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(99),
+       char(97),
+       char(108),
+       char(83),
+       char(99),
+       char(97),
+       char(108),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(108),
+       char(97),
+       char(110),
+       char(101),
+       char(78),
+       char(111),
+       char(114),
+       char(109),
+       char(97),
+       char(108),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(108),
+       char(97),
+       char(110),
+       char(101),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(97),
+       char(110),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(109),
+       char(112),
+       char(108),
+       char(105),
+       char(99),
+       char(105),
+       char(116),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(105),
+       char(109),
+       char(101),
+       char(110),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(77),
+       char(97),
+       char(114),
+       char(103),
+       char(105),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(97),
+       char(100),
+       char(105),
+       char(117),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(118),
+       char(101),
+       char(120),
+       char(73),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(110),
+       char(97),
+       char(108),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(99),
+       char(97),
+       char(108),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(65),
+       char(114),
+       char(114),
+       char(97),
+       char(121),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(99),
+       char(97),
+       char(108),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(65),
+       char(114),
+       char(114),
+       char(97),
+       char(121),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(97),
+       char(108),
+       char(117),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(97),
+       char(108),
+       char(117),
+       char(101),
+       char(115),
+       char(91),
+       char(51),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(118),
+       char(101),
+       char(114),
+       char(116),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(51),
+       char(102),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(118),
+       char(101),
+       char(114),
+       char(116),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(51),
+       char(100),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(51),
+       char(50),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(51),
+       char(105),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(49),
+       char(54),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(51),
+       char(105),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(56),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(49),
+       char(54),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(86),
+       char(101),
+       char(114),
+       char(116),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(109),
+       char(101),
+       char(115),
+       char(104),
+       char(80),
+       char(97),
+       char(114),
+       char(116),
+       char(115),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(99),
+       char(97),
+       char(108),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(80),
+       char(97),
+       char(114),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(101),
+       char(115),
+       char(104),
+       char(73),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(102),
+       char(97),
+       char(99),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(113),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(66),
+       char(118),
+       char(104),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(113),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(66),
+       char(118),
+       char(104),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(116),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(77),
+       char(97),
+       char(112),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(51),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(114),
+       char(105),
+       char(109),
+       char(101),
+       char(115),
+       char(104),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(114),
+       char(97),
+       char(110),
+       char(115),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(99),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(77),
+       char(97),
+       char(114),
+       char(103),
+       char(105),
+       char(110),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(99),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(67),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(112),
+       char(65),
+       char(120),
+       char(105),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(102),
+       char(108),
+       char(97),
+       char(103),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(100),
+       char(103),
+       char(101),
+       char(86),
+       char(48),
+       char(86),
+       char(49),
+       char(65),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(100),
+       char(103),
+       char(101),
+       char(86),
+       char(49),
+       char(86),
+       char(50),
+       char(65),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(100),
+       char(103),
+       char(101),
+       char(86),
+       char(50),
+       char(86),
+       char(48),
+       char(65),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(104),
+       char(97),
+       char(115),
+       char(104),
+       char(84),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(110),
+       char(101),
+       char(120),
+       char(116),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(118),
+       char(97),
+       char(108),
+       char(117),
+       char(101),
+       char(65),
+       char(114),
+       char(114),
+       char(97),
+       char(121),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(107),
+       char(101),
+       char(121),
+       char(65),
+       char(114),
+       char(114),
+       char(97),
+       char(121),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(118),
+       char(101),
+       char(120),
+       char(69),
+       char(112),
+       char(115),
+       char(105),
+       char(108),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(108),
+       char(97),
+       char(110),
+       char(97),
+       char(114),
+       char(69),
+       char(112),
+       char(115),
+       char(105),
+       char(108),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(113),
+       char(117),
+       char(97),
+       char(108),
+       char(86),
+       char(101),
+       char(114),
+       char(116),
+       char(101),
+       char(120),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(100),
+       char(103),
+       char(101),
+       char(68),
+       char(105),
+       char(115),
+       char(116),
+       char(97),
+       char(110),
+       char(99),
+       char(101),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(122),
+       char(101),
+       char(114),
+       char(111),
+       char(65),
+       char(114),
+       char(101),
+       char(97),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(101),
+       char(120),
+       char(116),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(104),
+       char(97),
+       char(115),
+       char(104),
+       char(84),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(86),
+       char(97),
+       char(108),
+       char(117),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(75),
+       char(101),
+       char(121),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(103),
+       char(105),
+       char(109),
+       char(112),
+       char(97),
+       char(99),
+       char(116),
+       char(83),
+       char(117),
+       char(98),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(117),
+       char(110),
+       char(115),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(100),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(117),
+       char(110),
+       char(115),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(100),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(85),
+       char(110),
+       char(115),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(100),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(110),
+       char(103),
+       char(51),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(98),
+       char(114),
+       char(111),
+       char(97),
+       char(100),
+       char(112),
+       char(104),
+       char(97),
+       char(115),
+       char(101),
+       char(72),
+       char(97),
+       char(110),
+       char(100),
+       char(108),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(114),
+       char(111),
+       char(111),
+       char(116),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(119),
+       char(111),
+       char(114),
+       char(108),
+       char(100),
+       char(84),
+       char(114),
+       char(97),
+       char(110),
+       char(115),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(112),
+       char(111),
+       char(108),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(87),
+       char(111),
+       char(114),
+       char(108),
+       char(100),
+       char(84),
+       char(114),
+       char(97),
+       char(110),
+       char(115),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(112),
+       char(111),
+       char(108),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(76),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(86),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(112),
+       char(111),
+       char(108),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(65),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(86),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(105),
+       char(115),
+       char(111),
+       char(116),
+       char(114),
+       char(111),
+       char(112),
+       char(105),
+       char(99),
+       char(70),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(80),
+       char(114),
+       char(111),
+       char(99),
+       char(101),
+       char(115),
+       char(115),
+       char(105),
+       char(110),
+       char(103),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(101),
+       char(97),
+       char(99),
+       char(116),
+       char(105),
+       char(118),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(84),
+       char(105),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(102),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(110),
+       char(103),
+       char(70),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(115),
+       char(116),
+       char(105),
+       char(116),
+       char(117),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(104),
+       char(105),
+       char(116),
+       char(70),
+       char(114),
+       char(97),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(99),
+       char(100),
+       char(83),
+       char(119),
+       char(101),
+       char(112),
+       char(116),
+       char(83),
+       char(112),
+       char(104),
+       char(101),
+       char(114),
+       char(101),
+       char(82),
+       char(97),
+       char(100),
+       char(105),
+       char(117),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(99),
+       char(100),
+       char(77),
+       char(111),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(104),
+       char(97),
+       char(115),
+       char(65),
+       char(110),
+       char(105),
+       char(115),
+       char(111),
+       char(116),
+       char(114),
+       char(111),
+       char(112),
+       char(105),
+       char(99),
+       char(70),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(70),
+       char(108),
+       char(97),
+       char(103),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(115),
+       char(108),
+       char(97),
+       char(110),
+       char(100),
+       char(84),
+       char(97),
+       char(103),
+       char(49),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(109),
+       char(112),
+       char(97),
+       char(110),
+       char(105),
+       char(111),
+       char(110),
+       char(73),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(99),
+       char(116),
+       char(105),
+       char(118),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(116),
+       char(97),
+       char(116),
+       char(101),
+       char(49),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(110),
+       char(97),
+       char(108),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(104),
+       char(101),
+       char(99),
+       char(107),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(100),
+       char(101),
+       char(87),
+       char(105),
+       char(116),
+       char(104),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(0),
+       char(109),
+       char(95),
+       char(103),
+       char(114),
+       char(97),
+       char(118),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(79),
+       char(98),
+       char(106),
+       char(101),
+       char(99),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(118),
+       char(73),
+       char(110),
+       char(101),
+       char(114),
+       char(116),
+       char(105),
+       char(97),
+       char(84),
+       char(101),
+       char(110),
+       char(115),
+       char(111),
+       char(114),
+       char(87),
+       char(111),
+       char(114),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(86),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(86),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(103),
+       char(114),
+       char(97),
+       char(118),
+       char(105),
+       char(116),
+       char(121),
+       char(95),
+       char(97),
+       char(99),
+       char(99),
+       char(101),
+       char(108),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(118),
+       char(73),
+       char(110),
+       char(101),
+       char(114),
+       char(116),
+       char(105),
+       char(97),
+       char(76),
+       char(111),
+       char(99),
+       char(97),
+       char(108),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(111),
+       char(116),
+       char(97),
+       char(108),
+       char(70),
+       char(111),
+       char(114),
+       char(99),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(111),
+       char(116),
+       char(97),
+       char(108),
+       char(84),
+       char(111),
+       char(114),
+       char(113),
+       char(117),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(118),
+       char(101),
+       char(114),
+       char(115),
+       char(101),
+       char(77),
+       char(97),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(97),
+       char(108),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(97),
+       char(108),
+       char(76),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(83),
+       char(113),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(97),
+       char(108),
+       char(65),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(83),
+       char(113),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(97),
+       char(108),
+       char(65),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(83),
+       char(108),
+       char(101),
+       char(101),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(83),
+       char(108),
+       char(101),
+       char(101),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(97),
+       char(108),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(82),
+       char(111),
+       char(119),
+       char(115),
+       char(0),
+       char(110),
+       char(117),
+       char(98),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(114),
+       char(98),
+       char(65),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(114),
+       char(98),
+       char(66),
+       char(0),
+       char(109),
+       char(95),
+       char(111),
+       char(98),
+       char(106),
+       char(101),
+       char(99),
+       char(116),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(114),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(114),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(73),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(101),
+       char(101),
+       char(100),
+       char(115),
+       char(70),
+       char(101),
+       char(101),
+       char(100),
+       char(98),
+       char(97),
+       char(99),
+       char(107),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(112),
+       char(112),
+       char(108),
+       char(105),
+       char(101),
+       char(100),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(98),
+       char(103),
+       char(68),
+       char(114),
+       char(97),
+       char(119),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(105),
+       char(115),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(66),
+       char(101),
+       char(116),
+       char(119),
+       char(101),
+       char(101),
+       char(110),
+       char(76),
+       char(105),
+       char(110),
+       char(107),
+       char(101),
+       char(100),
+       char(66),
+       char(111),
+       char(100),
+       char(105),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(111),
+       char(118),
+       char(101),
+       char(114),
+       char(114),
+       char(105),
+       char(100),
+       char(101),
+       char(78),
+       char(117),
+       char(109),
+       char(83),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(114),
+       char(101),
+       char(97),
+       char(107),
+       char(105),
+       char(110),
+       char(103),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(115),
+       char(69),
+       char(110),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(121),
+       char(112),
+       char(101),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(105),
+       char(118),
+       char(111),
+       char(116),
+       char(73),
+       char(110),
+       char(65),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(105),
+       char(118),
+       char(111),
+       char(116),
+       char(73),
+       char(110),
+       char(66),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(98),
+       char(65),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(98),
+       char(66),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(82),
+       char(101),
+       char(102),
+       char(101),
+       char(114),
+       char(101),
+       char(110),
+       char(99),
+       char(101),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(65),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(79),
+       char(110),
+       char(108),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(110),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(65),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(77),
+       char(111),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(111),
+       char(116),
+       char(111),
+       char(114),
+       char(84),
+       char(97),
+       char(114),
+       char(103),
+       char(101),
+       char(116),
+       char(86),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(120),
+       char(77),
+       char(111),
+       char(116),
+       char(111),
+       char(114),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(119),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(112),
+       char(112),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(105),
+       char(97),
+       char(115),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(108),
+       char(97),
+       char(120),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(119),
+       char(105),
+       char(110),
+       char(103),
+       char(83),
+       char(112),
+       char(97),
+       char(110),
+       char(49),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(119),
+       char(105),
+       char(110),
+       char(103),
+       char(83),
+       char(112),
+       char(97),
+       char(110),
+       char(50),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(119),
+       char(105),
+       char(115),
+       char(116),
+       char(83),
+       char(112),
+       char(97),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(85),
+       char(112),
+       char(112),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(76),
+       char(111),
+       char(119),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(85),
+       char(112),
+       char(112),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(76),
+       char(111),
+       char(119),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(76),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(82),
+       char(101),
+       char(102),
+       char(101),
+       char(114),
+       char(101),
+       char(110),
+       char(99),
+       char(101),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(65),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(79),
+       char(102),
+       char(102),
+       char(115),
+       char(101),
+       char(116),
+       char(70),
+       char(111),
+       char(114),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(54),
+       char(100),
+       char(111),
+       char(102),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(114),
+       char(105),
+       char(110),
+       char(103),
+       char(69),
+       char(110),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(100),
+       char(91),
+       char(54),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(113),
+       char(117),
+       char(105),
+       char(108),
+       char(105),
+       char(98),
+       char(114),
+       char(105),
+       char(117),
+       char(109),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(91),
+       char(54),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(114),
+       char(105),
+       char(110),
+       char(103),
+       char(83),
+       char(116),
+       char(105),
+       char(102),
+       char(102),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(91),
+       char(54),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(114),
+       char(105),
+       char(110),
+       char(103),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(91),
+       char(54),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(97),
+       char(117),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(105),
+       char(109),
+       char(101),
+       char(83),
+       char(116),
+       char(101),
+       char(112),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(120),
+       char(69),
+       char(114),
+       char(114),
+       char(111),
+       char(114),
+       char(82),
+       char(101),
+       char(100),
+       char(117),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(114),
+       char(112),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(114),
+       char(112),
+       char(50),
+       char(0),
+       char(109),
+       char(95),
+       char(103),
+       char(108),
+       char(111),
+       char(98),
+       char(97),
+       char(108),
+       char(67),
+       char(102),
+       char(109),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(80),
+       char(101),
+       char(110),
+       char(101),
+       char(116),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(84),
+       char(117),
+       char(114),
+       char(110),
+       char(69),
+       char(114),
+       char(112),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(83),
+       char(108),
+       char(111),
+       char(112),
+       char(0),
+       char(109),
+       char(95),
+       char(119),
+       char(97),
+       char(114),
+       char(109),
+       char(115),
+       char(116),
+       char(97),
+       char(114),
+       char(116),
+       char(105),
+       char(110),
+       char(103),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(120),
+       char(71),
+       char(121),
+       char(114),
+       char(111),
+       char(115),
+       char(99),
+       char(111),
+       char(112),
+       char(105),
+       char(99),
+       char(70),
+       char(111),
+       char(114),
+       char(99),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(105),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(65),
+       char(120),
+       char(105),
+       char(115),
+       char(82),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(110),
+       char(103),
+       char(70),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(77),
+       char(111),
+       char(100),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(115),
+       char(116),
+       char(105),
+       char(110),
+       char(103),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(82),
+       char(101),
+       char(115),
+       char(116),
+       char(105),
+       char(116),
+       char(117),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(105),
+       char(110),
+       char(105),
+       char(109),
+       char(117),
+       char(109),
+       char(83),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(66),
+       char(97),
+       char(116),
+       char(99),
+       char(104),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(83),
+       char(116),
+       char(105),
+       char(102),
+       char(102),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(83),
+       char(116),
+       char(105),
+       char(102),
+       char(102),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(111),
+       char(108),
+       char(117),
+       char(109),
+       char(101),
+       char(83),
+       char(116),
+       char(105),
+       char(102),
+       char(102),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(116),
+       char(101),
+       char(114),
+       char(105),
+       char(97),
+       char(108),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(114),
+       char(101),
+       char(118),
+       char(105),
+       char(111),
+       char(117),
+       char(115),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(99),
+       char(99),
+       char(117),
+       char(109),
+       char(117),
+       char(108),
+       char(97),
+       char(116),
+       char(101),
+       char(100),
+       char(70),
+       char(111),
+       char(114),
+       char(99),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(114),
+       char(109),
+       char(97),
+       char(108),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(114),
+       char(101),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(116),
+       char(116),
+       char(97),
+       char(99),
+       char(104),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(115),
+       char(116),
+       char(76),
+       char(101),
+       char(110),
+       char(103),
+       char(116),
+       char(104),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(98),
+       char(101),
+       char(110),
+       char(100),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(91),
+       char(51),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(115),
+       char(116),
+       char(65),
+       char(114),
+       char(101),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(48),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(115),
+       char(116),
+       char(86),
+       char(111),
+       char(108),
+       char(117),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(49),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(50),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(48),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(99),
+       char(97),
+       char(108),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(114),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(101),
+       char(114),
+       char(111),
+       char(77),
+       char(111),
+       char(100),
+       char(101),
+       char(108),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(97),
+       char(117),
+       char(109),
+       char(103),
+       char(97),
+       char(114),
+       char(116),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(114),
+       char(97),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(102),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(114),
+       char(101),
+       char(115),
+       char(115),
+       char(117),
+       char(114),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(111),
+       char(108),
+       char(117),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(121),
+       char(110),
+       char(97),
+       char(109),
+       char(105),
+       char(99),
+       char(70),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(101),
+       char(77),
+       char(97),
+       char(116),
+       char(99),
+       char(104),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(107),
+       char(105),
+       char(110),
+       char(101),
+       char(116),
+       char(105),
+       char(99),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(99),
+       char(104),
+       char(111),
+       char(114),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(75),
+       char(105),
+       char(110),
+       char(101),
+       char(116),
+       char(105),
+       char(99),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(83),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(75),
+       char(105),
+       char(110),
+       char(101),
+       char(116),
+       char(105),
+       char(99),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(83),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(83),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(120),
+       char(86),
+       char(111),
+       char(108),
+       char(117),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(105),
+       char(109),
+       char(101),
+       char(83),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(114),
+       char(105),
+       char(102),
+       char(116),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(111),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(113),
+       char(113),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(109),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(119),
+       char(101),
+       char(105),
+       char(103),
+       char(104),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(87),
+       char(101),
+       char(105),
+       char(103),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(118),
+       char(111),
+       char(108),
+       char(117),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(102),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(102),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(120),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(105),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(118),
+       char(119),
+       char(105),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(105),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(115),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(105),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(115),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(118),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(118),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(102),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(114),
+       char(101),
+       char(102),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(115),
+       char(115),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(82),
+       char(101),
+       char(102),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(77),
+       char(97),
+       char(115),
+       char(115),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(100),
+       char(109),
+       char(97),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(109),
+       char(97),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(118),
+       char(105),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(100),
+       char(105),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(100),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(100),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(116),
+       char(99),
+       char(104),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(120),
+       char(83),
+       char(101),
+       char(108),
+       char(102),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(101),
+       char(108),
+       char(102),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(105),
+       char(110),
+       char(115),
+       char(65),
+       char(110),
+       char(99),
+       char(104),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(100),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(98),
+       char(111),
+       char(100),
+       char(121),
+       char(65),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(98),
+       char(111),
+       char(100),
+       char(121),
+       char(66),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(102),
+       char(115),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(102),
+       char(109),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(101),
+       char(108),
+       char(101),
+       char(116),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(108),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(111),
+       char(100),
+       char(121),
+       char(65),
+       char(116),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(111),
+       char(100),
+       char(121),
+       char(66),
+       char(116),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(106),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(101),
+       char(0),
+       char(42),
+       char(42),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(116),
+       char(101),
+       char(114),
+       char(105),
+       char(97),
+       char(108),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(107),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(102),
+       char(97),
+       char(99),
+       char(101),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(116),
+       char(101),
+       char(116),
+       char(114),
+       char(97),
+       char(104),
+       char(101),
+       char(100),
+       char(114),
+       char(97),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(99),
+       char(104),
+       char(111),
+       char(114),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(99),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(106),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(77),
+       char(97),
+       char(116),
+       char(101),
+       char(114),
+       char(105),
+       char(97),
+       char(108),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(76),
+       char(105),
+       char(110),
+       char(107),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(70),
+       char(97),
+       char(99),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(84),
+       char(101),
+       char(116),
+       char(114),
+       char(97),
+       char(104),
+       char(101),
+       char(100),
+       char(114),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(65),
+       char(110),
+       char(99),
+       char(104),
+       char(111),
+       char(114),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(74),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(102),
+       char(105),
+       char(103),
+       char(0),
+       char(84),
+       char(89),
+       char(80),
+       char(69),
+       char(76),
+       char(0),
+       char(0),
+       char(0),
+       char(99),
+       char(104),
+       char(97),
+       char(114),
+       char(0),
+       char(117),
+       char(99),
+       char(104),
+       char(97),
+       char(114),
+       char(0),
+       char(115),
+       char(104),
+       char(111),
+       char(114),
+       char(116),
+       char(0),
+       char(117),
+       char(115),
+       char(104),
+       char(111),
+       char(114),
+       char(116),
+       char(0),
+       char(105),
+       char(110),
+       char(116),
+       char(0),
+       char(108),
+       char(111),
+       char(110),
+       char(103),
+       char(0),
+       char(117),
+       char(108),
+       char(111),
+       char(110),
+       char(103),
+       char(0),
+       char(102),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(0),
+       char(100),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(0),
+       char(118),
+       char(111),
+       char(105),
+       char(100),
+       char(0),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(65),
+       char(114),
+       char(114),
+       char(97),
+       char(121),
+       char(0),
+       char(98),
+       char(116),
+       char(80),
+       char(104),
+       char(121),
+       char(115),
+       char(105),
+       char(99),
+       char(115),
+       char(83),
+       char(121),
+       char(115),
+       char(116),
+       char(101),
+       char(109),
+       char(0),
+       char(76),
+       char(105),
+       char(115),
+       char(116),
+       char(66),
+       char(97),
+       char(115),
+       char(101),
+       char(0),
+       char(98),
+       char(116),
+       char(86),
+       char(101),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(51),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(86),
+       char(101),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(51),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(77),
+       char(97),
+       char(116),
+       char(114),
+       char(105),
+       char(120),
+       char(51),
+       char(120),
+       char(51),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(77),
+       char(97),
+       char(116),
+       char(114),
+       char(105),
+       char(120),
+       char(51),
+       char(120),
+       char(51),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(114),
+       char(97),
+       char(110),
+       char(115),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(114),
+       char(97),
+       char(110),
+       char(115),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(66),
+       char(118),
+       char(104),
+       char(83),
+       char(117),
+       char(98),
+       char(116),
+       char(114),
+       char(101),
+       char(101),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(79),
+       char(112),
+       char(116),
+       char(105),
+       char(109),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(66),
+       char(118),
+       char(104),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(79),
+       char(112),
+       char(116),
+       char(105),
+       char(109),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(66),
+       char(118),
+       char(104),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(66),
+       char(118),
+       char(104),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(66),
+       char(118),
+       char(104),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(66),
+       char(118),
+       char(104),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(116),
+       char(97),
+       char(116),
+       char(105),
+       char(99),
+       char(80),
+       char(108),
+       char(97),
+       char(110),
+       char(101),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(118),
+       char(101),
+       char(120),
+       char(73),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(110),
+       char(97),
+       char(108),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(65),
+       char(110),
+       char(100),
+       char(82),
+       char(97),
+       char(100),
+       char(105),
+       char(117),
+       char(115),
+       char(0),
+       char(98),
+       char(116),
+       char(77),
+       char(117),
+       char(108),
+       char(116),
+       char(105),
+       char(83),
+       char(112),
+       char(104),
+       char(101),
+       char(114),
+       char(101),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(73),
+       char(110),
+       char(116),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(104),
+       char(111),
+       char(114),
+       char(116),
+       char(73),
+       char(110),
+       char(116),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(104),
+       char(111),
+       char(114),
+       char(116),
+       char(73),
+       char(110),
+       char(116),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(84),
+       char(114),
+       char(105),
+       char(112),
+       char(108),
+       char(101),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(104),
+       char(97),
+       char(114),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(84),
+       char(114),
+       char(105),
+       char(112),
+       char(108),
+       char(101),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(80),
+       char(97),
+       char(114),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(116),
+       char(114),
+       char(105),
+       char(100),
+       char(105),
+       char(110),
+       char(103),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(73),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(102),
+       char(97),
+       char(99),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(77),
+       char(97),
+       char(112),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(100),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(109),
+       char(112),
+       char(111),
+       char(117),
+       char(110),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(67),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(109),
+       char(112),
+       char(111),
+       char(117),
+       char(110),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(121),
+       char(108),
+       char(105),
+       char(110),
+       char(100),
+       char(101),
+       char(114),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(97),
+       char(112),
+       char(115),
+       char(117),
+       char(108),
+       char(101),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(71),
+       char(73),
+       char(109),
+       char(112),
+       char(97),
+       char(99),
+       char(116),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(118),
+       char(101),
+       char(120),
+       char(72),
+       char(117),
+       char(108),
+       char(108),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(79),
+       char(98),
+       char(106),
+       char(101),
+       char(99),
+       char(116),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(79),
+       char(98),
+       char(106),
+       char(101),
+       char(99),
+       char(116),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(68),
+       char(121),
+       char(110),
+       char(97),
+       char(109),
+       char(105),
+       char(99),
+       char(115),
+       char(87),
+       char(111),
+       char(114),
+       char(108),
+       char(100),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(83),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(68),
+       char(121),
+       char(110),
+       char(97),
+       char(109),
+       char(105),
+       char(99),
+       char(115),
+       char(87),
+       char(111),
+       char(114),
+       char(108),
+       char(100),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(83),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(49),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(100),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(50),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(50),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(72),
+       char(105),
+       char(110),
+       char(103),
+       char(101),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(72),
+       char(105),
+       char(110),
+       char(103),
+       char(101),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(101),
+       char(84),
+       char(119),
+       char(105),
+       char(115),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(71),
+       char(101),
+       char(110),
+       char(101),
+       char(114),
+       char(105),
+       char(99),
+       char(54),
+       char(68),
+       char(111),
+       char(102),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(71),
+       char(101),
+       char(110),
+       char(101),
+       char(114),
+       char(105),
+       char(99),
+       char(54),
+       char(68),
+       char(111),
+       char(102),
+       char(83),
+       char(112),
+       char(114),
+       char(105),
+       char(110),
+       char(103),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(108),
+       char(105),
+       char(100),
+       char(101),
+       char(114),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(77),
+       char(97),
+       char(116),
+       char(101),
+       char(114),
+       char(105),
+       char(97),
+       char(108),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(76),
+       char(105),
+       char(110),
+       char(107),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(70),
+       char(97),
+       char(99),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(84),
+       char(101),
+       char(116),
+       char(114),
+       char(97),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(65),
+       char(110),
+       char(99),
+       char(104),
+       char(111),
+       char(114),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(67),
+       char(111),
+       char(110),
+       char(102),
+       char(105),
+       char(103),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(80),
+       char(111),
+       char(115),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(74),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(0),
+       char(0),
+       char(84),
+       char(76),
+       char(69),
+       char(78),
+       char(1),
+       char(0),
+       char(1),
+       char(0),
+       char(2),
+       char(0),
+       char(2),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(8),
+       char(0),
+       char(0),
+       char(0),
+       char(12),
+       char(0),
+       char(36),
+       char(0),
+       char(8),
+       char(0),
+       char(16),
+       char(0),
+       char(32),
+       char(0),
+       char(48),
+       char(0),
+       char(96),
+       char(0),
+       char(64),
+       char(0),
+       char(-128),
+       char(0),
+       char(20),
+       char(0),
+       char(48),
+       char(0),
+       char(80),
+       char(0),
+       char(16),
+       char(0),
+       char(84),
+       char(0),
+       char(-124),
+       char(0),
+       char(12),
+       char(0),
+       char(52),
+       char(0),
+       char(52),
+       char(0),
+       char(20),
+       char(0),
+       char(64),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(8),
+       char(0),
+       char(4),
+       char(0),
+       char(32),
+       char(0),
+       char(28),
+       char(0),
+       char(60),
+       char(0),
+       char(56),
+       char(0),
+       char(76),
+       char(0),
+       char(76),
+       char(0),
+       char(24),
+       char(0),
+       char(60),
+       char(0),
+       char(60),
+       char(0),
+       char(16),
+       char(0),
+       char(64),
+       char(0),
+       char(68),
+       char(0),
+       char(-48),
+       char(1),
+       char(0),
+       char(1),
+       char(-72),
+       char(0),
+       char(-104),
+       char(0),
+       char(104),
+       char(0),
+       char(88),
+       char(0),
+       char(-24),
+       char(1),
+       char(-96),
+       char(3),
+       char(8),
+       char(0),
+       char(52),
+       char(0),
+       char(0),
+       char(0),
+       char(84),
+       char(0),
+       char(116),
+       char(0),
+       char(92),
+       char(1),
+       char(-36),
+       char(0),
+       char(-44),
+       char(0),
+       char(-4),
+       char(0),
+       char(92),
+       char(1),
+       char(-52),
+       char(0),
+       char(16),
+       char(0),
+       char(100),
+       char(0),
+       char(20),
+       char(0),
+       char(36),
+       char(0),
+       char(100),
+       char(0),
+       char(92),
+       char(0),
+       char(104),
+       char(0),
+       char(-64),
+       char(0),
+       char(92),
+       char(1),
+       char(104),
+       char(0),
+       char(-84),
+       char(1),
+       char(83),
+       char(84),
+       char(82),
+       char(67),
+       char(65),
+       char(0),
+       char(0),
+       char(0),
+       char(10),
+       char(0),
+       char(3),
+       char(0),
+       char(4),
+       char(0),
+       char(0),
+       char(0),
+       char(4),
+       char(0),
+       char(1),
+       char(0),
+       char(9),
+       char(0),
+       char(2),
+       char(0),
+       char(11),
+       char(0),
+       char(3),
+       char(0),
+       char(10),
+       char(0),
+       char(3),
+       char(0),
+       char(10),
+       char(0),
+       char(4),
+       char(0),
+       char(10),
+       char(0),
+       char(5),
+       char(0),
+       char(12),
+       char(0),
+       char(2),
+       char(0),
+       char(9),
+       char(0),
+       char(6),
+       char(0),
+       char(9),
+       char(0),
+       char(7),
+       char(0),
+       char(13),
+       char(0),
+       char(1),
+       char(0),
+       char(7),
+       char(0),
+       char(8),
+       char(0),
+       char(14),
+       char(0),
+       char(1),
+       char(0),
+       char(8),
+       char(0),
+       char(8),
+       char(0),
+       char(15),
+       char(0),
+       char(1),
+       char(0),
+       char(13),
+       char(0),
+       char(9),
+       char(0),
+       char(16),
+       char(0),
+       char(1),
+       char(0),
+       char(14),
+       char(0),
+       char(9),
+       char(0),
+       char(17),
+       char(0),
+       char(2),
+       char(0),
+       char(15),
+       char(0),
+       char(10),
+       char(0),
+       char(13),
+       char(0),
+       char(11),
+       char(0),
+       char(18),
+       char(0),
+       char(2),
+       char(0),
+       char(16),
+       char(0),
+       char(10),
+       char(0),
+       char(14),
+       char(0),
+       char(11),
+       char(0),
+       char(19),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(12),
+       char(0),
+       char(4),
+       char(0),
+       char(13),
+       char(0),
+       char(2),
+       char(0),
+       char(14),
+       char(0),
+       char(2),
+       char(0),
+       char(15),
+       char(0),
+       char(20),
+       char(0),
+       char(6),
+       char(0),
+       char(13),
+       char(0),
+       char(16),
+       char(0),
+       char(13),
+       char(0),
+       char(17),
+       char(0),
+       char(4),
+       char(0),
+       char(18),
+       char(0),
+       char(4),
+       char(0),
+       char(19),
+       char(0),
+       char(4),
+       char(0),
+       char(20),
+       char(0),
+       char(0),
+       char(0),
+       char(21),
+       char(0),
+       char(21),
+       char(0),
+       char(6),
+       char(0),
+       char(14),
+       char(0),
+       char(16),
+       char(0),
+       char(14),
+       char(0),
+       char(17),
+       char(0),
+       char(4),
+       char(0),
+       char(18),
+       char(0),
+       char(4),
+       char(0),
+       char(19),
+       char(0),
+       char(4),
+       char(0),
+       char(20),
+       char(0),
+       char(0),
+       char(0),
+       char(21),
+       char(0),
+       char(22),
+       char(0),
+       char(3),
+       char(0),
+       char(2),
+       char(0),
+       char(14),
+       char(0),
+       char(2),
+       char(0),
+       char(15),
+       char(0),
+       char(4),
+       char(0),
+       char(22),
+       char(0),
+       char(23),
+       char(0),
+       char(12),
+       char(0),
+       char(13),
+       char(0),
+       char(23),
+       char(0),
+       char(13),
+       char(0),
+       char(24),
+       char(0),
+       char(13),
+       char(0),
+       char(25),
+       char(0),
+       char(4),
+       char(0),
+       char(26),
+       char(0),
+       char(4),
+       char(0),
+       char(27),
+       char(0),
+       char(4),
+       char(0),
+       char(28),
+       char(0),
+       char(4),
+       char(0),
+       char(29),
+       char(0),
+       char(20),
+       char(0),
+       char(30),
+       char(0),
+       char(22),
+       char(0),
+       char(31),
+       char(0),
+       char(19),
+       char(0),
+       char(32),
+       char(0),
+       char(4),
+       char(0),
+       char(33),
+       char(0),
+       char(4),
+       char(0),
+       char(34),
+       char(0),
+       char(24),
+       char(0),
+       char(12),
+       char(0),
+       char(14),
+       char(0),
+       char(23),
+       char(0),
+       char(14),
+       char(0),
+       char(24),
+       char(0),
+       char(14),
+       char(0),
+       char(25),
+       char(0),
+       char(4),
+       char(0),
+       char(26),
+       char(0),
+       char(4),
+       char(0),
+       char(27),
+       char(0),
+       char(4),
+       char(0),
+       char(28),
+       char(0),
+       char(4),
+       char(0),
+       char(29),
+       char(0),
+       char(21),
+       char(0),
+       char(30),
+       char(0),
+       char(22),
+       char(0),
+       char(31),
+       char(0),
+       char(4),
+       char(0),
+       char(33),
+       char(0),
+       char(4),
+       char(0),
+       char(34),
+       char(0),
+       char(19),
+       char(0),
+       char(32),
+       char(0),
+       char(25),
+       char(0),
+       char(3),
+       char(0),
+       char(0),
+       char(0),
+       char(35),
+       char(0),
+       char(4),
+       char(0),
+       char(36),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(26),
+       char(0),
+       char(5),
+       char(0),
+       char(25),
+       char(0),
+       char(38),
+       char(0),
+       char(13),
+       char(0),
+       char(39),
+       char(0),
+       char(13),
+       char(0),
+       char(40),
+       char(0),
+       char(7),
+       char(0),
+       char(41),
+       char(0),
+       char(0),
+       char(0),
+       char(21),
+       char(0),
+       char(27),
+       char(0),
+       char(5),
+       char(0),
+       char(25),
+       char(0),
+       char(38),
+       char(0),
+       char(13),
+       char(0),
+       char(39),
+       char(0),
+       char(13),
+       char(0),
+       char(42),
+       char(0),
+       char(7),
+       char(0),
+       char(43),
+       char(0),
+       char(4),
+       char(0),
+       char(44),
+       char(0),
+       char(28),
+       char(0),
+       char(2),
+       char(0),
+       char(13),
+       char(0),
+       char(45),
+       char(0),
+       char(7),
+       char(0),
+       char(46),
+       char(0),
+       char(29),
+       char(0),
+       char(4),
+       char(0),
+       char(27),
+       char(0),
+       char(47),
+       char(0),
+       char(28),
+       char(0),
+       char(48),
+       char(0),
+       char(4),
+       char(0),
+       char(49),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(30),
+       char(0),
+       char(1),
+       char(0),
+       char(4),
+       char(0),
+       char(50),
+       char(0),
+       char(31),
+       char(0),
+       char(2),
+       char(0),
+       char(2),
+       char(0),
+       char(50),
+       char(0),
+       char(0),
+       char(0),
+       char(51),
+       char(0),
+       char(32),
+       char(0),
+       char(2),
+       char(0),
+       char(2),
+       char(0),
+       char(52),
+       char(0),
+       char(0),
+       char(0),
+       char(51),
+       char(0),
+       char(33),
+       char(0),
+       char(2),
+       char(0),
+       char(0),
+       char(0),
+       char(52),
+       char(0),
+       char(0),
+       char(0),
+       char(53),
+       char(0),
+       char(34),
+       char(0),
+       char(8),
+       char(0),
+       char(13),
+       char(0),
+       char(54),
+       char(0),
+       char(14),
+       char(0),
+       char(55),
+       char(0),
+       char(30),
+       char(0),
+       char(56),
+       char(0),
+       char(32),
+       char(0),
+       char(57),
+       char(0),
+       char(33),
+       char(0),
+       char(58),
+       char(0),
+       char(31),
+       char(0),
+       char(59),
+       char(0),
+       char(4),
+       char(0),
+       char(60),
+       char(0),
+       char(4),
+       char(0),
+       char(61),
+       char(0),
+       char(35),
+       char(0),
+       char(4),
+       char(0),
+       char(34),
+       char(0),
+       char(62),
+       char(0),
+       char(13),
+       char(0),
+       char(63),
+       char(0),
+       char(4),
+       char(0),
+       char(64),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(36),
+       char(0),
+       char(7),
+       char(0),
+       char(25),
+       char(0),
+       char(38),
+       char(0),
+       char(35),
+       char(0),
+       char(65),
+       char(0),
+       char(23),
+       char(0),
+       char(66),
+       char(0),
+       char(24),
+       char(0),
+       char(67),
+       char(0),
+       char(37),
+       char(0),
+       char(68),
+       char(0),
+       char(7),
+       char(0),
+       char(43),
+       char(0),
+       char(0),
+       char(0),
+       char(69),
+       char(0),
+       char(38),
+       char(0),
+       char(2),
+       char(0),
+       char(36),
+       char(0),
+       char(70),
+       char(0),
+       char(13),
+       char(0),
+       char(39),
+       char(0),
+       char(39),
+       char(0),
+       char(4),
+       char(0),
+       char(17),
+       char(0),
+       char(71),
+       char(0),
+       char(25),
+       char(0),
+       char(72),
+       char(0),
+       char(4),
+       char(0),
+       char(73),
+       char(0),
+       char(7),
+       char(0),
+       char(74),
+       char(0),
+       char(40),
+       char(0),
+       char(4),
+       char(0),
+       char(25),
+       char(0),
+       char(38),
+       char(0),
+       char(39),
+       char(0),
+       char(75),
+       char(0),
+       char(4),
+       char(0),
+       char(76),
+       char(0),
+       char(7),
+       char(0),
+       char(43),
+       char(0),
+       char(41),
+       char(0),
+       char(3),
+       char(0),
+       char(27),
+       char(0),
+       char(47),
+       char(0),
+       char(4),
+       char(0),
+       char(77),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(42),
+       char(0),
+       char(3),
+       char(0),
+       char(27),
+       char(0),
+       char(47),
+       char(0),
+       char(4),
+       char(0),
+       char(77),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(43),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(78),
+       char(0),
+       char(7),
+       char(0),
+       char(79),
+       char(0),
+       char(7),
+       char(0),
+       char(80),
+       char(0),
+       char(7),
+       char(0),
+       char(81),
+       char(0),
+       char(37),
+       char(0),
+       char(14),
+       char(0),
+       char(4),
+       char(0),
+       char(82),
+       char(0),
+       char(4),
+       char(0),
+       char(83),
+       char(0),
+       char(43),
+       char(0),
+       char(84),
+       char(0),
+       char(4),
+       char(0),
+       char(85),
+       char(0),
+       char(7),
+       char(0),
+       char(86),
+       char(0),
+       char(7),
+       char(0),
+       char(87),
+       char(0),
+       char(7),
+       char(0),
+       char(88),
+       char(0),
+       char(7),
+       char(0),
+       char(89),
+       char(0),
+       char(7),
+       char(0),
+       char(90),
+       char(0),
+       char(4),
+       char(0),
+       char(91),
+       char(0),
+       char(4),
+       char(0),
+       char(92),
+       char(0),
+       char(4),
+       char(0),
+       char(93),
+       char(0),
+       char(4),
+       char(0),
+       char(94),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(44),
+       char(0),
+       char(5),
+       char(0),
+       char(25),
+       char(0),
+       char(38),
+       char(0),
+       char(35),
+       char(0),
+       char(65),
+       char(0),
+       char(13),
+       char(0),
+       char(39),
+       char(0),
+       char(7),
+       char(0),
+       char(43),
+       char(0),
+       char(4),
+       char(0),
+       char(95),
+       char(0),
+       char(45),
+       char(0),
+       char(5),
+       char(0),
+       char(27),
+       char(0),
+       char(47),
+       char(0),
+       char(13),
+       char(0),
+       char(96),
+       char(0),
+       char(14),
+       char(0),
+       char(97),
+       char(0),
+       char(4),
+       char(0),
+       char(98),
+       char(0),
+       char(0),
+       char(0),
+       char(99),
+       char(0),
+       char(46),
+       char(0),
+       char(25),
+       char(0),
+       char(9),
+       char(0),
+       char(100),
+       char(0),
+       char(9),
+       char(0),
+       char(101),
+       char(0),
+       char(25),
+       char(0),
+       char(102),
+       char(0),
+       char(0),
+       char(0),
+       char(35),
+       char(0),
+       char(18),
+       char(0),
+       char(103),
+       char(0),
+       char(18),
+       char(0),
+       char(104),
+       char(0),
+       char(14),
+       char(0),
+       char(105),
+       char(0),
+       char(14),
+       char(0),
+       char(106),
+       char(0),
+       char(14),
+       char(0),
+       char(107),
+       char(0),
+       char(8),
+       char(0),
+       char(108),
+       char(0),
+       char(8),
+       char(0),
+       char(109),
+       char(0),
+       char(8),
+       char(0),
+       char(110),
+       char(0),
+       char(8),
+       char(0),
+       char(111),
+       char(0),
+       char(8),
+       char(0),
+       char(112),
+       char(0),
+       char(8),
+       char(0),
+       char(113),
+       char(0),
+       char(8),
+       char(0),
+       char(114),
+       char(0),
+       char(8),
+       char(0),
+       char(115),
+       char(0),
+       char(4),
+       char(0),
+       char(116),
+       char(0),
+       char(4),
+       char(0),
+       char(117),
+       char(0),
+       char(4),
+       char(0),
+       char(118),
+       char(0),
+       char(4),
+       char(0),
+       char(119),
+       char(0),
+       char(4),
+       char(0),
+       char(120),
+       char(0),
+       char(4),
+       char(0),
+       char(121),
+       char(0),
+       char(4),
+       char(0),
+       char(122),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(47),
+       char(0),
+       char(25),
+       char(0),
+       char(9),
+       char(0),
+       char(100),
+       char(0),
+       char(9),
+       char(0),
+       char(101),
+       char(0),
+       char(25),
+       char(0),
+       char(102),
+       char(0),
+       char(0),
+       char(0),
+       char(35),
+       char(0),
+       char(17),
+       char(0),
+       char(103),
+       char(0),
+       char(17),
+       char(0),
+       char(104),
+       char(0),
+       char(13),
+       char(0),
+       char(105),
+       char(0),
+       char(13),
+       char(0),
+       char(106),
+       char(0),
+       char(13),
+       char(0),
+       char(107),
+       char(0),
+       char(7),
+       char(0),
+       char(108),
+       char(0),
+       char(7),
+       char(0),
+       char(109),
+       char(0),
+       char(7),
+       char(0),
+       char(110),
+       char(0),
+       char(7),
+       char(0),
+       char(111),
+       char(0),
+       char(7),
+       char(0),
+       char(112),
+       char(0),
+       char(7),
+       char(0),
+       char(113),
+       char(0),
+       char(7),
+       char(0),
+       char(114),
+       char(0),
+       char(7),
+       char(0),
+       char(115),
+       char(0),
+       char(4),
+       char(0),
+       char(116),
+       char(0),
+       char(4),
+       char(0),
+       char(117),
+       char(0),
+       char(4),
+       char(0),
+       char(118),
+       char(0),
+       char(4),
+       char(0),
+       char(119),
+       char(0),
+       char(4),
+       char(0),
+       char(120),
+       char(0),
+       char(4),
+       char(0),
+       char(121),
+       char(0),
+       char(4),
+       char(0),
+       char(122),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(48),
+       char(0),
+       char(2),
+       char(0),
+       char(49),
+       char(0),
+       char(123),
+       char(0),
+       char(14),
+       char(0),
+       char(124),
+       char(0),
+       char(50),
+       char(0),
+       char(2),
+       char(0),
+       char(51),
+       char(0),
+       char(123),
+       char(0),
+       char(13),
+       char(0),
+       char(124),
+       char(0),
+       char(52),
+       char(0),
+       char(21),
+       char(0),
+       char(47),
+       char(0),
+       char(125),
+       char(0),
+       char(15),
+       char(0),
+       char(126),
+       char(0),
+       char(13),
+       char(0),
+       char(127),
+       char(0),
+       char(13),
+       char(0),
+       char(-128),
+       char(0),
+       char(13),
+       char(0),
+       char(-127),
+       char(0),
+       char(13),
+       char(0),
+       char(-126),
+       char(0),
+       char(13),
+       char(0),
+       char(124),
+       char(0),
+       char(13),
+       char(0),
+       char(-125),
+       char(0),
+       char(13),
+       char(0),
+       char(-124),
+       char(0),
+       char(13),
+       char(0),
+       char(-123),
+       char(0),
+       char(13),
+       char(0),
+       char(-122),
+       char(0),
+       char(7),
+       char(0),
+       char(-121),
+       char(0),
+       char(7),
+       char(0),
+       char(-120),
+       char(0),
+       char(7),
+       char(0),
+       char(-119),
+       char(0),
+       char(7),
+       char(0),
+       char(-118),
+       char(0),
+       char(7),
+       char(0),
+       char(-117),
+       char(0),
+       char(7),
+       char(0),
+       char(-116),
+       char(0),
+       char(7),
+       char(0),
+       char(-115),
+       char(0),
+       char(7),
+       char(0),
+       char(-114),
+       char(0),
+       char(7),
+       char(0),
+       char(-113),
+       char(0),
+       char(4),
+       char(0),
+       char(-112),
+       char(0),
+       char(53),
+       char(0),
+       char(22),
+       char(0),
+       char(46),
+       char(0),
+       char(125),
+       char(0),
+       char(16),
+       char(0),
+       char(126),
+       char(0),
+       char(14),
+       char(0),
+       char(127),
+       char(0),
+       char(14),
+       char(0),
+       char(-128),
+       char(0),
+       char(14),
+       char(0),
+       char(-127),
+       char(0),
+       char(14),
+       char(0),
+       char(-126),
+       char(0),
+       char(14),
+       char(0),
+       char(124),
+       char(0),
+       char(14),
+       char(0),
+       char(-125),
+       char(0),
+       char(14),
+       char(0),
+       char(-124),
+       char(0),
+       char(14),
+       char(0),
+       char(-123),
+       char(0),
+       char(14),
+       char(0),
+       char(-122),
+       char(0),
+       char(8),
+       char(0),
+       char(-121),
+       char(0),
+       char(8),
+       char(0),
+       char(-120),
+       char(0),
+       char(8),
+       char(0),
+       char(-119),
+       char(0),
+       char(8),
+       char(0),
+       char(-118),
+       char(0),
+       char(8),
+       char(0),
+       char(-117),
+       char(0),
+       char(8),
+       char(0),
+       char(-116),
+       char(0),
+       char(8),
+       char(0),
+       char(-115),
+       char(0),
+       char(8),
+       char(0),
+       char(-114),
+       char(0),
+       char(8),
+       char(0),
+       char(-113),
+       char(0),
+       char(4),
+       char(0),
+       char(-112),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(54),
+       char(0),
+       char(2),
+       char(0),
+       char(4),
+       char(0),
+       char(-111),
+       char(0),
+       char(4),
+       char(0),
+       char(-110),
+       char(0),
+       char(55),
+       char(0),
+       char(13),
+       char(0),
+       char(56),
+       char(0),
+       char(-109),
+       char(0),
+       char(56),
+       char(0),
+       char(-108),
+       char(0),
+       char(0),
+       char(0),
+       char(35),
+       char(0),
+       char(4),
+       char(0),
+       char(-107),
+       char(0),
+       char(4),
+       char(0),
+       char(-106),
+       char(0),
+       char(4),
+       char(0),
+       char(-105),
+       char(0),
+       char(4),
+       char(0),
+       char(-104),
+       char(0),
+       char(7),
+       char(0),
+       char(-103),
+       char(0),
+       char(7),
+       char(0),
+       char(-102),
+       char(0),
+       char(4),
+       char(0),
+       char(-101),
+       char(0),
+       char(4),
+       char(0),
+       char(-100),
+       char(0),
+       char(7),
+       char(0),
+       char(-99),
+       char(0),
+       char(4),
+       char(0),
+       char(-98),
+       char(0),
+       char(57),
+       char(0),
+       char(3),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(13),
+       char(0),
+       char(-96),
+       char(0),
+       char(13),
+       char(0),
+       char(-95),
+       char(0),
+       char(58),
+       char(0),
+       char(3),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(14),
+       char(0),
+       char(-96),
+       char(0),
+       char(14),
+       char(0),
+       char(-95),
+       char(0),
+       char(59),
+       char(0),
+       char(13),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(18),
+       char(0),
+       char(-94),
+       char(0),
+       char(18),
+       char(0),
+       char(-93),
+       char(0),
+       char(4),
+       char(0),
+       char(-92),
+       char(0),
+       char(4),
+       char(0),
+       char(-91),
+       char(0),
+       char(4),
+       char(0),
+       char(-90),
+       char(0),
+       char(7),
+       char(0),
+       char(-89),
+       char(0),
+       char(7),
+       char(0),
+       char(-88),
+       char(0),
+       char(7),
+       char(0),
+       char(-87),
+       char(0),
+       char(7),
+       char(0),
+       char(-86),
+       char(0),
+       char(7),
+       char(0),
+       char(-85),
+       char(0),
+       char(7),
+       char(0),
+       char(-84),
+       char(0),
+       char(7),
+       char(0),
+       char(-83),
+       char(0),
+       char(60),
+       char(0),
+       char(13),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(17),
+       char(0),
+       char(-94),
+       char(0),
+       char(17),
+       char(0),
+       char(-93),
+       char(0),
+       char(4),
+       char(0),
+       char(-92),
+       char(0),
+       char(4),
+       char(0),
+       char(-91),
+       char(0),
+       char(4),
+       char(0),
+       char(-90),
+       char(0),
+       char(7),
+       char(0),
+       char(-89),
+       char(0),
+       char(7),
+       char(0),
+       char(-88),
+       char(0),
+       char(7),
+       char(0),
+       char(-87),
+       char(0),
+       char(7),
+       char(0),
+       char(-86),
+       char(0),
+       char(7),
+       char(0),
+       char(-85),
+       char(0),
+       char(7),
+       char(0),
+       char(-84),
+       char(0),
+       char(7),
+       char(0),
+       char(-83),
+       char(0),
+       char(61),
+       char(0),
+       char(11),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(17),
+       char(0),
+       char(-94),
+       char(0),
+       char(17),
+       char(0),
+       char(-93),
+       char(0),
+       char(7),
+       char(0),
+       char(-82),
+       char(0),
+       char(7),
+       char(0),
+       char(-81),
+       char(0),
+       char(7),
+       char(0),
+       char(-80),
+       char(0),
+       char(7),
+       char(0),
+       char(-85),
+       char(0),
+       char(7),
+       char(0),
+       char(-84),
+       char(0),
+       char(7),
+       char(0),
+       char(-83),
+       char(0),
+       char(7),
+       char(0),
+       char(-79),
+       char(0),
+       char(0),
+       char(0),
+       char(21),
+       char(0),
+       char(62),
+       char(0),
+       char(9),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(17),
+       char(0),
+       char(-94),
+       char(0),
+       char(17),
+       char(0),
+       char(-93),
+       char(0),
+       char(13),
+       char(0),
+       char(-78),
+       char(0),
+       char(13),
+       char(0),
+       char(-77),
+       char(0),
+       char(13),
+       char(0),
+       char(-76),
+       char(0),
+       char(13),
+       char(0),
+       char(-75),
+       char(0),
+       char(4),
+       char(0),
+       char(-74),
+       char(0),
+       char(4),
+       char(0),
+       char(-73),
+       char(0),
+       char(63),
+       char(0),
+       char(5),
+       char(0),
+       char(62),
+       char(0),
+       char(-72),
+       char(0),
+       char(4),
+       char(0),
+       char(-71),
+       char(0),
+       char(7),
+       char(0),
+       char(-70),
+       char(0),
+       char(7),
+       char(0),
+       char(-69),
+       char(0),
+       char(7),
+       char(0),
+       char(-68),
+       char(0),
+       char(64),
+       char(0),
+       char(9),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(17),
+       char(0),
+       char(-94),
+       char(0),
+       char(17),
+       char(0),
+       char(-93),
+       char(0),
+       char(7),
+       char(0),
+       char(-78),
+       char(0),
+       char(7),
+       char(0),
+       char(-77),
+       char(0),
+       char(7),
+       char(0),
+       char(-76),
+       char(0),
+       char(7),
+       char(0),
+       char(-75),
+       char(0),
+       char(4),
+       char(0),
+       char(-74),
+       char(0),
+       char(4),
+       char(0),
+       char(-73),
+       char(0),
+       char(49),
+       char(0),
+       char(22),
+       char(0),
+       char(8),
+       char(0),
+       char(-67),
+       char(0),
+       char(8),
+       char(0),
+       char(-79),
+       char(0),
+       char(8),
+       char(0),
+       char(110),
+       char(0),
+       char(8),
+       char(0),
+       char(-66),
+       char(0),
+       char(8),
+       char(0),
+       char(112),
+       char(0),
+       char(8),
+       char(0),
+       char(-65),
+       char(0),
+       char(8),
+       char(0),
+       char(-64),
+       char(0),
+       char(8),
+       char(0),
+       char(-63),
+       char(0),
+       char(8),
+       char(0),
+       char(-62),
+       char(0),
+       char(8),
+       char(0),
+       char(-61),
+       char(0),
+       char(8),
+       char(0),
+       char(-60),
+       char(0),
+       char(8),
+       char(0),
+       char(-59),
+       char(0),
+       char(8),
+       char(0),
+       char(-58),
+       char(0),
+       char(8),
+       char(0),
+       char(-57),
+       char(0),
+       char(8),
+       char(0),
+       char(-56),
+       char(0),
+       char(8),
+       char(0),
+       char(-55),
+       char(0),
+       char(4),
+       char(0),
+       char(-54),
+       char(0),
+       char(4),
+       char(0),
+       char(-53),
+       char(0),
+       char(4),
+       char(0),
+       char(-52),
+       char(0),
+       char(4),
+       char(0),
+       char(-51),
+       char(0),
+       char(4),
+       char(0),
+       char(-50),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(51),
+       char(0),
+       char(22),
+       char(0),
+       char(7),
+       char(0),
+       char(-67),
+       char(0),
+       char(7),
+       char(0),
+       char(-79),
+       char(0),
+       char(7),
+       char(0),
+       char(110),
+       char(0),
+       char(7),
+       char(0),
+       char(-66),
+       char(0),
+       char(7),
+       char(0),
+       char(112),
+       char(0),
+       char(7),
+       char(0),
+       char(-65),
+       char(0),
+       char(7),
+       char(0),
+       char(-64),
+       char(0),
+       char(7),
+       char(0),
+       char(-63),
+       char(0),
+       char(7),
+       char(0),
+       char(-62),
+       char(0),
+       char(7),
+       char(0),
+       char(-61),
+       char(0),
+       char(7),
+       char(0),
+       char(-60),
+       char(0),
+       char(7),
+       char(0),
+       char(-59),
+       char(0),
+       char(7),
+       char(0),
+       char(-58),
+       char(0),
+       char(7),
+       char(0),
+       char(-57),
+       char(0),
+       char(7),
+       char(0),
+       char(-56),
+       char(0),
+       char(7),
+       char(0),
+       char(-55),
+       char(0),
+       char(4),
+       char(0),
+       char(-54),
+       char(0),
+       char(4),
+       char(0),
+       char(-53),
+       char(0),
+       char(4),
+       char(0),
+       char(-52),
+       char(0),
+       char(4),
+       char(0),
+       char(-51),
+       char(0),
+       char(4),
+       char(0),
+       char(-50),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(65),
+       char(0),
+       char(4),
+       char(0),
+       char(7),
+       char(0),
+       char(-49),
+       char(0),
+       char(7),
+       char(0),
+       char(-48),
+       char(0),
+       char(7),
+       char(0),
+       char(-47),
+       char(0),
+       char(4),
+       char(0),
+       char(78),
+       char(0),
+       char(66),
+       char(0),
+       char(10),
+       char(0),
+       char(65),
+       char(0),
+       char(-46),
+       char(0),
+       char(13),
+       char(0),
+       char(-45),
+       char(0),
+       char(13),
+       char(0),
+       char(-44),
+       char(0),
+       char(13),
+       char(0),
+       char(-43),
+       char(0),
+       char(13),
+       char(0),
+       char(-42),
+       char(0),
+       char(13),
+       char(0),
+       char(-41),
+       char(0),
+       char(7),
+       char(0),
+       char(-121),
+       char(0),
+       char(7),
+       char(0),
+       char(-40),
+       char(0),
+       char(4),
+       char(0),
+       char(-39),
+       char(0),
+       char(4),
+       char(0),
+       char(53),
+       char(0),
+       char(67),
+       char(0),
+       char(4),
+       char(0),
+       char(65),
+       char(0),
+       char(-46),
+       char(0),
+       char(4),
+       char(0),
+       char(-38),
+       char(0),
+       char(7),
+       char(0),
+       char(-37),
+       char(0),
+       char(4),
+       char(0),
+       char(-36),
+       char(0),
+       char(68),
+       char(0),
+       char(4),
+       char(0),
+       char(13),
+       char(0),
+       char(-41),
+       char(0),
+       char(65),
+       char(0),
+       char(-46),
+       char(0),
+       char(4),
+       char(0),
+       char(-35),
+       char(0),
+       char(7),
+       char(0),
+       char(-34),
+       char(0),
+       char(69),
+       char(0),
+       char(7),
+       char(0),
+       char(13),
+       char(0),
+       char(-33),
+       char(0),
+       char(65),
+       char(0),
+       char(-46),
+       char(0),
+       char(4),
+       char(0),
+       char(-32),
+       char(0),
+       char(7),
+       char(0),
+       char(-31),
+       char(0),
+       char(7),
+       char(0),
+       char(-30),
+       char(0),
+       char(7),
+       char(0),
+       char(-29),
+       char(0),
+       char(4),
+       char(0),
+       char(53),
+       char(0),
+       char(70),
+       char(0),
+       char(6),
+       char(0),
+       char(15),
+       char(0),
+       char(-28),
+       char(0),
+       char(13),
+       char(0),
+       char(-30),
+       char(0),
+       char(13),
+       char(0),
+       char(-27),
+       char(0),
+       char(56),
+       char(0),
+       char(-26),
+       char(0),
+       char(4),
+       char(0),
+       char(-25),
+       char(0),
+       char(7),
+       char(0),
+       char(-29),
+       char(0),
+       char(71),
+       char(0),
+       char(26),
+       char(0),
+       char(4),
+       char(0),
+       char(-24),
+       char(0),
+       char(7),
+       char(0),
+       char(-23),
+       char(0),
+       char(7),
+       char(0),
+       char(-79),
+       char(0),
+       char(7),
+       char(0),
+       char(-22),
+       char(0),
+       char(7),
+       char(0),
+       char(-21),
+       char(0),
+       char(7),
+       char(0),
+       char(-20),
+       char(0),
+       char(7),
+       char(0),
+       char(-19),
+       char(0),
+       char(7),
+       char(0),
+       char(-18),
+       char(0),
+       char(7),
+       char(0),
+       char(-17),
+       char(0),
+       char(7),
+       char(0),
+       char(-16),
+       char(0),
+       char(7),
+       char(0),
+       char(-15),
+       char(0),
+       char(7),
+       char(0),
+       char(-14),
+       char(0),
+       char(7),
+       char(0),
+       char(-13),
+       char(0),
+       char(7),
+       char(0),
+       char(-12),
+       char(0),
+       char(7),
+       char(0),
+       char(-11),
+       char(0),
+       char(7),
+       char(0),
+       char(-10),
+       char(0),
+       char(7),
+       char(0),
+       char(-9),
+       char(0),
+       char(7),
+       char(0),
+       char(-8),
+       char(0),
+       char(7),
+       char(0),
+       char(-7),
+       char(0),
+       char(7),
+       char(0),
+       char(-6),
+       char(0),
+       char(7),
+       char(0),
+       char(-5),
+       char(0),
+       char(4),
+       char(0),
+       char(-4),
+       char(0),
+       char(4),
+       char(0),
+       char(-3),
+       char(0),
+       char(4),
+       char(0),
+       char(-2),
+       char(0),
+       char(4),
+       char(0),
+       char(-1),
+       char(0),
+       char(4),
+       char(0),
+       char(117),
+       char(0),
+       char(72),
+       char(0),
+       char(12),
+       char(0),
+       char(15),
+       char(0),
+       char(0),
+       char(1),
+       char(15),
+       char(0),
+       char(1),
+       char(1),
+       char(15),
+       char(0),
+       char(2),
+       char(1),
+       char(13),
+       char(0),
+       char(3),
+       char(1),
+       char(13),
+       char(0),
+       char(4),
+       char(1),
+       char(7),
+       char(0),
+       char(5),
+       char(1),
+       char(4),
+       char(0),
+       char(6),
+       char(1),
+       char(4),
+       char(0),
+       char(7),
+       char(1),
+       char(4),
+       char(0),
+       char(8),
+       char(1),
+       char(4),
+       char(0),
+       char(9),
+       char(1),
+       char(7),
+       char(0),
+       char(-31),
+       char(0),
+       char(4),
+       char(0),
+       char(53),
+       char(0),
+       char(73),
+       char(0),
+       char(27),
+       char(0),
+       char(17),
+       char(0),
+       char(10),
+       char(1),
+       char(15),
+       char(0),
+       char(11),
+       char(1),
+       char(15),
+       char(0),
+       char(12),
+       char(1),
+       char(13),
+       char(0),
+       char(3),
+       char(1),
+       char(13),
+       char(0),
+       char(13),
+       char(1),
+       char(13),
+       char(0),
+       char(14),
+       char(1),
+       char(13),
+       char(0),
+       char(15),
+       char(1),
+       char(13),
+       char(0),
+       char(16),
+       char(1),
+       char(13),
+       char(0),
+       char(17),
+       char(1),
+       char(4),
+       char(0),
+       char(18),
+       char(1),
+       char(7),
+       char(0),
+       char(19),
+       char(1),
+       char(4),
+       char(0),
+       char(20),
+       char(1),
+       char(4),
+       char(0),
+       char(21),
+       char(1),
+       char(4),
+       char(0),
+       char(22),
+       char(1),
+       char(7),
+       char(0),
+       char(23),
+       char(1),
+       char(7),
+       char(0),
+       char(24),
+       char(1),
+       char(4),
+       char(0),
+       char(25),
+       char(1),
+       char(4),
+       char(0),
+       char(26),
+       char(1),
+       char(7),
+       char(0),
+       char(27),
+       char(1),
+       char(7),
+       char(0),
+       char(28),
+       char(1),
+       char(7),
+       char(0),
+       char(29),
+       char(1),
+       char(7),
+       char(0),
+       char(30),
+       char(1),
+       char(7),
+       char(0),
+       char(31),
+       char(1),
+       char(7),
+       char(0),
+       char(32),
+       char(1),
+       char(4),
+       char(0),
+       char(33),
+       char(1),
+       char(4),
+       char(0),
+       char(34),
+       char(1),
+       char(4),
+       char(0),
+       char(35),
+       char(1),
+       char(74),
+       char(0),
+       char(12),
+       char(0),
+       char(9),
+       char(0),
+       char(36),
+       char(1),
+       char(9),
+       char(0),
+       char(37),
+       char(1),
+       char(13),
+       char(0),
+       char(38),
+       char(1),
+       char(7),
+       char(0),
+       char(39),
+       char(1),
+       char(7),
+       char(0),
+       char(-63),
+       char(0),
+       char(7),
+       char(0),
+       char(40),
+       char(1),
+       char(4),
+       char(0),
+       char(41),
+       char(1),
+       char(13),
+       char(0),
+       char(42),
+       char(1),
+       char(4),
+       char(0),
+       char(43),
+       char(1),
+       char(4),
+       char(0),
+       char(44),
+       char(1),
+       char(4),
+       char(0),
+       char(45),
+       char(1),
+       char(4),
+       char(0),
+       char(53),
+       char(0),
+       char(75),
+       char(0),
+       char(19),
+       char(0),
+       char(47),
+       char(0),
+       char(125),
+       char(0),
+       char(72),
+       char(0),
+       char(46),
+       char(1),
+       char(65),
+       char(0),
+       char(47),
+       char(1),
+       char(66),
+       char(0),
+       char(48),
+       char(1),
+       char(67),
+       char(0),
+       char(49),
+       char(1),
+       char(68),
+       char(0),
+       char(50),
+       char(1),
+       char(69),
+       char(0),
+       char(51),
+       char(1),
+       char(70),
+       char(0),
+       char(52),
+       char(1),
+       char(73),
+       char(0),
+       char(53),
+       char(1),
+       char(74),
+       char(0),
+       char(54),
+       char(1),
+       char(4),
+       char(0),
+       char(55),
+       char(1),
+       char(4),
+       char(0),
+       char(21),
+       char(1),
+       char(4),
+       char(0),
+       char(56),
+       char(1),
+       char(4),
+       char(0),
+       char(57),
+       char(1),
+       char(4),
+       char(0),
+       char(58),
+       char(1),
+       char(4),
+       char(0),
+       char(59),
+       char(1),
+       char(4),
+       char(0),
+       char(60),
+       char(1),
+       char(4),
+       char(0),
+       char(61),
+       char(1),
+       char(71),
+       char(0),
+       char(62),
+       char(1),
+};
+int b3s_bulletDNAlen = sizeof(b3s_bulletDNAstr);
+char b3s_bulletDNAstr64[] = {
+       char(83),
+       char(68),
+       char(78),
+       char(65),
+       char(78),
+       char(65),
+       char(77),
+       char(69),
+       char(63),
+       char(1),
+       char(0),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(97),
+       char(112),
+       char(97),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(100),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(79),
+       char(98),
+       char(106),
+       char(101),
+       char(99),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(0),
+       char(42),
+       char(102),
+       char(105),
+       char(114),
+       char(115),
+       char(116),
+       char(0),
+       char(42),
+       char(108),
+       char(97),
+       char(115),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(102),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(115),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(108),
+       char(91),
+       char(51),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(97),
+       char(115),
+       char(105),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(111),
+       char(114),
+       char(105),
+       char(103),
+       char(105),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(111),
+       char(111),
+       char(116),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(117),
+       char(98),
+       char(116),
+       char(114),
+       char(101),
+       char(101),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(113),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(65),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(105),
+       char(110),
+       char(91),
+       char(51),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(113),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(65),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(97),
+       char(120),
+       char(91),
+       char(51),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(105),
+       char(110),
+       char(79),
+       char(114),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(97),
+       char(120),
+       char(79),
+       char(114),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(115),
+       char(99),
+       char(97),
+       char(112),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(117),
+       char(98),
+       char(80),
+       char(97),
+       char(114),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(115),
+       char(99),
+       char(97),
+       char(112),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(79),
+       char(114),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(118),
+       char(104),
+       char(65),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(105),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(118),
+       char(104),
+       char(65),
+       char(97),
+       char(98),
+       char(98),
+       char(77),
+       char(97),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(118),
+       char(104),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(117),
+       char(114),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(105),
+       char(103),
+       char(117),
+       char(111),
+       char(117),
+       char(115),
+       char(76),
+       char(101),
+       char(97),
+       char(102),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(105),
+       char(103),
+       char(117),
+       char(111),
+       char(117),
+       char(115),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(116),
+       char(105),
+       char(103),
+       char(117),
+       char(111),
+       char(117),
+       char(115),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(113),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(105),
+       char(103),
+       char(117),
+       char(111),
+       char(117),
+       char(115),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(115),
+       char(117),
+       char(98),
+       char(84),
+       char(114),
+       char(101),
+       char(101),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(114),
+       char(97),
+       char(118),
+       char(101),
+       char(114),
+       char(115),
+       char(97),
+       char(108),
+       char(77),
+       char(111),
+       char(100),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(83),
+       char(117),
+       char(98),
+       char(116),
+       char(114),
+       char(101),
+       char(101),
+       char(72),
+       char(101),
+       char(97),
+       char(100),
+       char(101),
+       char(114),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(110),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(110),
+       char(103),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(99),
+       char(97),
+       char(108),
+       char(83),
+       char(99),
+       char(97),
+       char(108),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(108),
+       char(97),
+       char(110),
+       char(101),
+       char(78),
+       char(111),
+       char(114),
+       char(109),
+       char(97),
+       char(108),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(108),
+       char(97),
+       char(110),
+       char(101),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(97),
+       char(110),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(109),
+       char(112),
+       char(108),
+       char(105),
+       char(99),
+       char(105),
+       char(116),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(105),
+       char(109),
+       char(101),
+       char(110),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(77),
+       char(97),
+       char(114),
+       char(103),
+       char(105),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(97),
+       char(100),
+       char(105),
+       char(117),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(118),
+       char(101),
+       char(120),
+       char(73),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(110),
+       char(97),
+       char(108),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(99),
+       char(97),
+       char(108),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(65),
+       char(114),
+       char(114),
+       char(97),
+       char(121),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(99),
+       char(97),
+       char(108),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(65),
+       char(114),
+       char(114),
+       char(97),
+       char(121),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(97),
+       char(108),
+       char(117),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(97),
+       char(108),
+       char(117),
+       char(101),
+       char(115),
+       char(91),
+       char(51),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(118),
+       char(101),
+       char(114),
+       char(116),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(51),
+       char(102),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(118),
+       char(101),
+       char(114),
+       char(116),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(51),
+       char(100),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(51),
+       char(50),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(51),
+       char(105),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(49),
+       char(54),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(51),
+       char(105),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(56),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(49),
+       char(54),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(86),
+       char(101),
+       char(114),
+       char(116),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(109),
+       char(101),
+       char(115),
+       char(104),
+       char(80),
+       char(97),
+       char(114),
+       char(116),
+       char(115),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(99),
+       char(97),
+       char(108),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(80),
+       char(97),
+       char(114),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(101),
+       char(115),
+       char(104),
+       char(73),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(102),
+       char(97),
+       char(99),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(113),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(66),
+       char(118),
+       char(104),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(113),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(66),
+       char(118),
+       char(104),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(116),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(77),
+       char(97),
+       char(112),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(51),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(114),
+       char(105),
+       char(109),
+       char(101),
+       char(115),
+       char(104),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(114),
+       char(97),
+       char(110),
+       char(115),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(99),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(77),
+       char(97),
+       char(114),
+       char(103),
+       char(105),
+       char(110),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(99),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(67),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(112),
+       char(65),
+       char(120),
+       char(105),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(102),
+       char(108),
+       char(97),
+       char(103),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(100),
+       char(103),
+       char(101),
+       char(86),
+       char(48),
+       char(86),
+       char(49),
+       char(65),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(100),
+       char(103),
+       char(101),
+       char(86),
+       char(49),
+       char(86),
+       char(50),
+       char(65),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(100),
+       char(103),
+       char(101),
+       char(86),
+       char(50),
+       char(86),
+       char(48),
+       char(65),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(104),
+       char(97),
+       char(115),
+       char(104),
+       char(84),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(110),
+       char(101),
+       char(120),
+       char(116),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(118),
+       char(97),
+       char(108),
+       char(117),
+       char(101),
+       char(65),
+       char(114),
+       char(114),
+       char(97),
+       char(121),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(107),
+       char(101),
+       char(121),
+       char(65),
+       char(114),
+       char(114),
+       char(97),
+       char(121),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(118),
+       char(101),
+       char(120),
+       char(69),
+       char(112),
+       char(115),
+       char(105),
+       char(108),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(108),
+       char(97),
+       char(110),
+       char(97),
+       char(114),
+       char(69),
+       char(112),
+       char(115),
+       char(105),
+       char(108),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(113),
+       char(117),
+       char(97),
+       char(108),
+       char(86),
+       char(101),
+       char(114),
+       char(116),
+       char(101),
+       char(120),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(100),
+       char(103),
+       char(101),
+       char(68),
+       char(105),
+       char(115),
+       char(116),
+       char(97),
+       char(110),
+       char(99),
+       char(101),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(122),
+       char(101),
+       char(114),
+       char(111),
+       char(65),
+       char(114),
+       char(101),
+       char(97),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(101),
+       char(120),
+       char(116),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(104),
+       char(97),
+       char(115),
+       char(104),
+       char(84),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(86),
+       char(97),
+       char(108),
+       char(117),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(75),
+       char(101),
+       char(121),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(103),
+       char(105),
+       char(109),
+       char(112),
+       char(97),
+       char(99),
+       char(116),
+       char(83),
+       char(117),
+       char(98),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(117),
+       char(110),
+       char(115),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(100),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(117),
+       char(110),
+       char(115),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(100),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(80),
+       char(116),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(85),
+       char(110),
+       char(115),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(100),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(110),
+       char(103),
+       char(51),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(98),
+       char(114),
+       char(111),
+       char(97),
+       char(100),
+       char(112),
+       char(104),
+       char(97),
+       char(115),
+       char(101),
+       char(72),
+       char(97),
+       char(110),
+       char(100),
+       char(108),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(114),
+       char(111),
+       char(111),
+       char(116),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(119),
+       char(111),
+       char(114),
+       char(108),
+       char(100),
+       char(84),
+       char(114),
+       char(97),
+       char(110),
+       char(115),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(112),
+       char(111),
+       char(108),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(87),
+       char(111),
+       char(114),
+       char(108),
+       char(100),
+       char(84),
+       char(114),
+       char(97),
+       char(110),
+       char(115),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(112),
+       char(111),
+       char(108),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(76),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(86),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(112),
+       char(111),
+       char(108),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(65),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(86),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(105),
+       char(115),
+       char(111),
+       char(116),
+       char(114),
+       char(111),
+       char(112),
+       char(105),
+       char(99),
+       char(70),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(80),
+       char(114),
+       char(111),
+       char(99),
+       char(101),
+       char(115),
+       char(115),
+       char(105),
+       char(110),
+       char(103),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(101),
+       char(97),
+       char(99),
+       char(116),
+       char(105),
+       char(118),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(84),
+       char(105),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(102),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(110),
+       char(103),
+       char(70),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(115),
+       char(116),
+       char(105),
+       char(116),
+       char(117),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(104),
+       char(105),
+       char(116),
+       char(70),
+       char(114),
+       char(97),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(99),
+       char(100),
+       char(83),
+       char(119),
+       char(101),
+       char(112),
+       char(116),
+       char(83),
+       char(112),
+       char(104),
+       char(101),
+       char(114),
+       char(101),
+       char(82),
+       char(97),
+       char(100),
+       char(105),
+       char(117),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(99),
+       char(100),
+       char(77),
+       char(111),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(104),
+       char(97),
+       char(115),
+       char(65),
+       char(110),
+       char(105),
+       char(115),
+       char(111),
+       char(116),
+       char(114),
+       char(111),
+       char(112),
+       char(105),
+       char(99),
+       char(70),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(70),
+       char(108),
+       char(97),
+       char(103),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(115),
+       char(108),
+       char(97),
+       char(110),
+       char(100),
+       char(84),
+       char(97),
+       char(103),
+       char(49),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(109),
+       char(112),
+       char(97),
+       char(110),
+       char(105),
+       char(111),
+       char(110),
+       char(73),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(99),
+       char(116),
+       char(105),
+       char(118),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(116),
+       char(97),
+       char(116),
+       char(101),
+       char(49),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(110),
+       char(97),
+       char(108),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(104),
+       char(101),
+       char(99),
+       char(107),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(100),
+       char(101),
+       char(87),
+       char(105),
+       char(116),
+       char(104),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(0),
+       char(109),
+       char(95),
+       char(103),
+       char(114),
+       char(97),
+       char(118),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(79),
+       char(98),
+       char(106),
+       char(101),
+       char(99),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(118),
+       char(73),
+       char(110),
+       char(101),
+       char(114),
+       char(116),
+       char(105),
+       char(97),
+       char(84),
+       char(101),
+       char(110),
+       char(115),
+       char(111),
+       char(114),
+       char(87),
+       char(111),
+       char(114),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(86),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(86),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(103),
+       char(114),
+       char(97),
+       char(118),
+       char(105),
+       char(116),
+       char(121),
+       char(95),
+       char(97),
+       char(99),
+       char(99),
+       char(101),
+       char(108),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(118),
+       char(73),
+       char(110),
+       char(101),
+       char(114),
+       char(116),
+       char(105),
+       char(97),
+       char(76),
+       char(111),
+       char(99),
+       char(97),
+       char(108),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(111),
+       char(116),
+       char(97),
+       char(108),
+       char(70),
+       char(111),
+       char(114),
+       char(99),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(111),
+       char(116),
+       char(97),
+       char(108),
+       char(84),
+       char(111),
+       char(114),
+       char(113),
+       char(117),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(118),
+       char(101),
+       char(114),
+       char(115),
+       char(101),
+       char(77),
+       char(97),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(97),
+       char(108),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(97),
+       char(108),
+       char(76),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(83),
+       char(113),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(97),
+       char(108),
+       char(65),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(83),
+       char(113),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(97),
+       char(108),
+       char(65),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(83),
+       char(108),
+       char(101),
+       char(101),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(83),
+       char(108),
+       char(101),
+       char(101),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(100),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(97),
+       char(108),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(82),
+       char(111),
+       char(119),
+       char(115),
+       char(0),
+       char(110),
+       char(117),
+       char(98),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(114),
+       char(98),
+       char(65),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(114),
+       char(98),
+       char(66),
+       char(0),
+       char(109),
+       char(95),
+       char(111),
+       char(98),
+       char(106),
+       char(101),
+       char(99),
+       char(116),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(114),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(114),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(73),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(101),
+       char(101),
+       char(100),
+       char(115),
+       char(70),
+       char(101),
+       char(101),
+       char(100),
+       char(98),
+       char(97),
+       char(99),
+       char(107),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(112),
+       char(112),
+       char(108),
+       char(105),
+       char(101),
+       char(100),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(98),
+       char(103),
+       char(68),
+       char(114),
+       char(97),
+       char(119),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(105),
+       char(115),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(66),
+       char(101),
+       char(116),
+       char(119),
+       char(101),
+       char(101),
+       char(110),
+       char(76),
+       char(105),
+       char(110),
+       char(107),
+       char(101),
+       char(100),
+       char(66),
+       char(111),
+       char(100),
+       char(105),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(111),
+       char(118),
+       char(101),
+       char(114),
+       char(114),
+       char(105),
+       char(100),
+       char(101),
+       char(78),
+       char(117),
+       char(109),
+       char(83),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(114),
+       char(101),
+       char(97),
+       char(107),
+       char(105),
+       char(110),
+       char(103),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(115),
+       char(69),
+       char(110),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(121),
+       char(112),
+       char(101),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(105),
+       char(118),
+       char(111),
+       char(116),
+       char(73),
+       char(110),
+       char(65),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(105),
+       char(118),
+       char(111),
+       char(116),
+       char(73),
+       char(110),
+       char(66),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(98),
+       char(65),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(98),
+       char(66),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(82),
+       char(101),
+       char(102),
+       char(101),
+       char(114),
+       char(101),
+       char(110),
+       char(99),
+       char(101),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(65),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(79),
+       char(110),
+       char(108),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(110),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(65),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(77),
+       char(111),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(111),
+       char(116),
+       char(111),
+       char(114),
+       char(84),
+       char(97),
+       char(114),
+       char(103),
+       char(101),
+       char(116),
+       char(86),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(120),
+       char(77),
+       char(111),
+       char(116),
+       char(111),
+       char(114),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(119),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(112),
+       char(112),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(105),
+       char(97),
+       char(115),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(108),
+       char(97),
+       char(120),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(119),
+       char(105),
+       char(110),
+       char(103),
+       char(83),
+       char(112),
+       char(97),
+       char(110),
+       char(49),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(119),
+       char(105),
+       char(110),
+       char(103),
+       char(83),
+       char(112),
+       char(97),
+       char(110),
+       char(50),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(119),
+       char(105),
+       char(115),
+       char(116),
+       char(83),
+       char(112),
+       char(97),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(85),
+       char(112),
+       char(112),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(76),
+       char(111),
+       char(119),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(85),
+       char(112),
+       char(112),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(76),
+       char(111),
+       char(119),
+       char(101),
+       char(114),
+       char(76),
+       char(105),
+       char(109),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(76),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(82),
+       char(101),
+       char(102),
+       char(101),
+       char(114),
+       char(101),
+       char(110),
+       char(99),
+       char(101),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(65),
+       char(0),
+       char(109),
+       char(95),
+       char(117),
+       char(115),
+       char(101),
+       char(79),
+       char(102),
+       char(102),
+       char(115),
+       char(101),
+       char(116),
+       char(70),
+       char(111),
+       char(114),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(54),
+       char(100),
+       char(111),
+       char(102),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(114),
+       char(105),
+       char(110),
+       char(103),
+       char(69),
+       char(110),
+       char(97),
+       char(98),
+       char(108),
+       char(101),
+       char(100),
+       char(91),
+       char(54),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(113),
+       char(117),
+       char(105),
+       char(108),
+       char(105),
+       char(98),
+       char(114),
+       char(105),
+       char(117),
+       char(109),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(91),
+       char(54),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(114),
+       char(105),
+       char(110),
+       char(103),
+       char(83),
+       char(116),
+       char(105),
+       char(102),
+       char(102),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(91),
+       char(54),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(114),
+       char(105),
+       char(110),
+       char(103),
+       char(68),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(91),
+       char(54),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(97),
+       char(117),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(105),
+       char(109),
+       char(101),
+       char(83),
+       char(116),
+       char(101),
+       char(112),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(120),
+       char(69),
+       char(114),
+       char(114),
+       char(111),
+       char(114),
+       char(82),
+       char(101),
+       char(100),
+       char(117),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(114),
+       char(112),
+       char(0),
+       char(109),
+       char(95),
+       char(101),
+       char(114),
+       char(112),
+       char(50),
+       char(0),
+       char(109),
+       char(95),
+       char(103),
+       char(108),
+       char(111),
+       char(98),
+       char(97),
+       char(108),
+       char(67),
+       char(102),
+       char(109),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(80),
+       char(101),
+       char(110),
+       char(101),
+       char(116),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(84),
+       char(117),
+       char(114),
+       char(110),
+       char(69),
+       char(114),
+       char(112),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(83),
+       char(108),
+       char(111),
+       char(112),
+       char(0),
+       char(109),
+       char(95),
+       char(119),
+       char(97),
+       char(114),
+       char(109),
+       char(115),
+       char(116),
+       char(97),
+       char(114),
+       char(116),
+       char(105),
+       char(110),
+       char(103),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(120),
+       char(71),
+       char(121),
+       char(114),
+       char(111),
+       char(115),
+       char(99),
+       char(111),
+       char(112),
+       char(105),
+       char(99),
+       char(70),
+       char(111),
+       char(114),
+       char(99),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(105),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(65),
+       char(120),
+       char(105),
+       char(115),
+       char(82),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(110),
+       char(103),
+       char(70),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(77),
+       char(111),
+       char(100),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(115),
+       char(116),
+       char(105),
+       char(110),
+       char(103),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(82),
+       char(101),
+       char(115),
+       char(116),
+       char(105),
+       char(116),
+       char(117),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(84),
+       char(104),
+       char(114),
+       char(101),
+       char(115),
+       char(104),
+       char(111),
+       char(108),
+       char(100),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(105),
+       char(110),
+       char(105),
+       char(109),
+       char(117),
+       char(109),
+       char(83),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(66),
+       char(97),
+       char(116),
+       char(99),
+       char(104),
+       char(83),
+       char(105),
+       char(122),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(101),
+       char(97),
+       char(114),
+       char(83),
+       char(116),
+       char(105),
+       char(102),
+       char(102),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(103),
+       char(117),
+       char(108),
+       char(97),
+       char(114),
+       char(83),
+       char(116),
+       char(105),
+       char(102),
+       char(102),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(111),
+       char(108),
+       char(117),
+       char(109),
+       char(101),
+       char(83),
+       char(116),
+       char(105),
+       char(102),
+       char(102),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(116),
+       char(101),
+       char(114),
+       char(105),
+       char(97),
+       char(108),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(114),
+       char(101),
+       char(118),
+       char(105),
+       char(111),
+       char(117),
+       char(115),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(99),
+       char(99),
+       char(117),
+       char(109),
+       char(117),
+       char(108),
+       char(97),
+       char(116),
+       char(101),
+       char(100),
+       char(70),
+       char(111),
+       char(114),
+       char(99),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(114),
+       char(109),
+       char(97),
+       char(108),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(114),
+       char(101),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(116),
+       char(116),
+       char(97),
+       char(99),
+       char(104),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(115),
+       char(116),
+       char(76),
+       char(101),
+       char(110),
+       char(103),
+       char(116),
+       char(104),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(98),
+       char(101),
+       char(110),
+       char(100),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(91),
+       char(51),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(115),
+       char(116),
+       char(65),
+       char(114),
+       char(101),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(48),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(91),
+       char(52),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(115),
+       char(116),
+       char(86),
+       char(111),
+       char(108),
+       char(117),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(49),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(50),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(48),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(99),
+       char(97),
+       char(108),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(114),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(101),
+       char(114),
+       char(111),
+       char(77),
+       char(111),
+       char(100),
+       char(101),
+       char(108),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(97),
+       char(117),
+       char(109),
+       char(103),
+       char(97),
+       char(114),
+       char(116),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(114),
+       char(97),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(102),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(114),
+       char(101),
+       char(115),
+       char(115),
+       char(117),
+       char(114),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(111),
+       char(108),
+       char(117),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(121),
+       char(110),
+       char(97),
+       char(109),
+       char(105),
+       char(99),
+       char(70),
+       char(114),
+       char(105),
+       char(99),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(101),
+       char(77),
+       char(97),
+       char(116),
+       char(99),
+       char(104),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(107),
+       char(105),
+       char(110),
+       char(101),
+       char(116),
+       char(105),
+       char(99),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(99),
+       char(104),
+       char(111),
+       char(114),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(75),
+       char(105),
+       char(110),
+       char(101),
+       char(116),
+       char(105),
+       char(99),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(72),
+       char(97),
+       char(114),
+       char(100),
+       char(110),
+       char(101),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(83),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(75),
+       char(105),
+       char(110),
+       char(101),
+       char(116),
+       char(105),
+       char(99),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(83),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(111),
+       char(102),
+       char(116),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(83),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(120),
+       char(86),
+       char(111),
+       char(108),
+       char(117),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(116),
+       char(105),
+       char(109),
+       char(101),
+       char(83),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(101),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(116),
+       char(121),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(114),
+       char(105),
+       char(102),
+       char(116),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(73),
+       char(116),
+       char(101),
+       char(114),
+       char(97),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(111),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(113),
+       char(113),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(109),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(119),
+       char(101),
+       char(105),
+       char(103),
+       char(104),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(87),
+       char(101),
+       char(105),
+       char(103),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(118),
+       char(111),
+       char(108),
+       char(117),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(102),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(102),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(120),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(111),
+       char(99),
+       char(105),
+       char(105),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(110),
+       char(118),
+       char(119),
+       char(105),
+       char(0),
+       char(109),
+       char(95),
+       char(118),
+       char(105),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(115),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(105),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(115),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(118),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(118),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(102),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(114),
+       char(101),
+       char(102),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(73),
+       char(110),
+       char(100),
+       char(105),
+       char(99),
+       char(101),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(115),
+       char(115),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(70),
+       char(114),
+       char(97),
+       char(109),
+       char(101),
+       char(82),
+       char(101),
+       char(102),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(77),
+       char(97),
+       char(115),
+       char(115),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(100),
+       char(109),
+       char(97),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(105),
+       char(109),
+       char(97),
+       char(115),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(118),
+       char(105),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(100),
+       char(105),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(100),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(108),
+       char(100),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(97),
+       char(100),
+       char(97),
+       char(109),
+       char(112),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(116),
+       char(99),
+       char(104),
+       char(105),
+       char(110),
+       char(103),
+       char(0),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(120),
+       char(83),
+       char(101),
+       char(108),
+       char(102),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(101),
+       char(108),
+       char(102),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(73),
+       char(109),
+       char(112),
+       char(117),
+       char(108),
+       char(115),
+       char(101),
+       char(70),
+       char(97),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(105),
+       char(110),
+       char(115),
+       char(65),
+       char(110),
+       char(99),
+       char(104),
+       char(111),
+       char(114),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(100),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(98),
+       char(111),
+       char(100),
+       char(121),
+       char(65),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(98),
+       char(111),
+       char(100),
+       char(121),
+       char(66),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(102),
+       char(115),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(102),
+       char(109),
+       char(0),
+       char(109),
+       char(95),
+       char(115),
+       char(112),
+       char(108),
+       char(105),
+       char(116),
+       char(0),
+       char(109),
+       char(95),
+       char(100),
+       char(101),
+       char(108),
+       char(101),
+       char(116),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(114),
+       char(101),
+       char(108),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(91),
+       char(50),
+       char(93),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(111),
+       char(100),
+       char(121),
+       char(65),
+       char(116),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(98),
+       char(111),
+       char(100),
+       char(121),
+       char(66),
+       char(116),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(109),
+       char(95),
+       char(106),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(112),
+       char(111),
+       char(115),
+       char(101),
+       char(0),
+       char(42),
+       char(42),
+       char(109),
+       char(95),
+       char(109),
+       char(97),
+       char(116),
+       char(101),
+       char(114),
+       char(105),
+       char(97),
+       char(108),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(110),
+       char(111),
+       char(100),
+       char(101),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(108),
+       char(105),
+       char(110),
+       char(107),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(102),
+       char(97),
+       char(99),
+       char(101),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(116),
+       char(101),
+       char(116),
+       char(114),
+       char(97),
+       char(104),
+       char(101),
+       char(100),
+       char(114),
+       char(97),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(97),
+       char(110),
+       char(99),
+       char(104),
+       char(111),
+       char(114),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(99),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(115),
+       char(0),
+       char(42),
+       char(109),
+       char(95),
+       char(106),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(77),
+       char(97),
+       char(116),
+       char(101),
+       char(114),
+       char(105),
+       char(97),
+       char(108),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(76),
+       char(105),
+       char(110),
+       char(107),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(70),
+       char(97),
+       char(99),
+       char(101),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(84),
+       char(101),
+       char(116),
+       char(114),
+       char(97),
+       char(104),
+       char(101),
+       char(100),
+       char(114),
+       char(97),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(65),
+       char(110),
+       char(99),
+       char(104),
+       char(111),
+       char(114),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(110),
+       char(117),
+       char(109),
+       char(74),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(115),
+       char(0),
+       char(109),
+       char(95),
+       char(99),
+       char(111),
+       char(110),
+       char(102),
+       char(105),
+       char(103),
+       char(0),
+       char(84),
+       char(89),
+       char(80),
+       char(69),
+       char(76),
+       char(0),
+       char(0),
+       char(0),
+       char(99),
+       char(104),
+       char(97),
+       char(114),
+       char(0),
+       char(117),
+       char(99),
+       char(104),
+       char(97),
+       char(114),
+       char(0),
+       char(115),
+       char(104),
+       char(111),
+       char(114),
+       char(116),
+       char(0),
+       char(117),
+       char(115),
+       char(104),
+       char(111),
+       char(114),
+       char(116),
+       char(0),
+       char(105),
+       char(110),
+       char(116),
+       char(0),
+       char(108),
+       char(111),
+       char(110),
+       char(103),
+       char(0),
+       char(117),
+       char(108),
+       char(111),
+       char(110),
+       char(103),
+       char(0),
+       char(102),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(0),
+       char(100),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(0),
+       char(118),
+       char(111),
+       char(105),
+       char(100),
+       char(0),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(65),
+       char(114),
+       char(114),
+       char(97),
+       char(121),
+       char(0),
+       char(98),
+       char(116),
+       char(80),
+       char(104),
+       char(121),
+       char(115),
+       char(105),
+       char(99),
+       char(115),
+       char(83),
+       char(121),
+       char(115),
+       char(116),
+       char(101),
+       char(109),
+       char(0),
+       char(76),
+       char(105),
+       char(115),
+       char(116),
+       char(66),
+       char(97),
+       char(115),
+       char(101),
+       char(0),
+       char(98),
+       char(116),
+       char(86),
+       char(101),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(51),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(86),
+       char(101),
+       char(99),
+       char(116),
+       char(111),
+       char(114),
+       char(51),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(77),
+       char(97),
+       char(116),
+       char(114),
+       char(105),
+       char(120),
+       char(51),
+       char(120),
+       char(51),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(77),
+       char(97),
+       char(116),
+       char(114),
+       char(105),
+       char(120),
+       char(51),
+       char(120),
+       char(51),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(114),
+       char(97),
+       char(110),
+       char(115),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(114),
+       char(97),
+       char(110),
+       char(115),
+       char(102),
+       char(111),
+       char(114),
+       char(109),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(66),
+       char(118),
+       char(104),
+       char(83),
+       char(117),
+       char(98),
+       char(116),
+       char(114),
+       char(101),
+       char(101),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(79),
+       char(112),
+       char(116),
+       char(105),
+       char(109),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(66),
+       char(118),
+       char(104),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(79),
+       char(112),
+       char(116),
+       char(105),
+       char(109),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(66),
+       char(118),
+       char(104),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(66),
+       char(118),
+       char(104),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(66),
+       char(118),
+       char(104),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(81),
+       char(117),
+       char(97),
+       char(110),
+       char(116),
+       char(105),
+       char(122),
+       char(101),
+       char(100),
+       char(66),
+       char(118),
+       char(104),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(116),
+       char(97),
+       char(116),
+       char(105),
+       char(99),
+       char(80),
+       char(108),
+       char(97),
+       char(110),
+       char(101),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(118),
+       char(101),
+       char(120),
+       char(73),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(110),
+       char(97),
+       char(108),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(80),
+       char(111),
+       char(115),
+       char(105),
+       char(116),
+       char(105),
+       char(111),
+       char(110),
+       char(65),
+       char(110),
+       char(100),
+       char(82),
+       char(97),
+       char(100),
+       char(105),
+       char(117),
+       char(115),
+       char(0),
+       char(98),
+       char(116),
+       char(77),
+       char(117),
+       char(108),
+       char(116),
+       char(105),
+       char(83),
+       char(112),
+       char(104),
+       char(101),
+       char(114),
+       char(101),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(73),
+       char(110),
+       char(116),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(104),
+       char(111),
+       char(114),
+       char(116),
+       char(73),
+       char(110),
+       char(116),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(104),
+       char(111),
+       char(114),
+       char(116),
+       char(73),
+       char(110),
+       char(116),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(84),
+       char(114),
+       char(105),
+       char(112),
+       char(108),
+       char(101),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(104),
+       char(97),
+       char(114),
+       char(73),
+       char(110),
+       char(100),
+       char(101),
+       char(120),
+       char(84),
+       char(114),
+       char(105),
+       char(112),
+       char(108),
+       char(101),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(80),
+       char(97),
+       char(114),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(116),
+       char(114),
+       char(105),
+       char(100),
+       char(105),
+       char(110),
+       char(103),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(73),
+       char(110),
+       char(116),
+       char(101),
+       char(114),
+       char(102),
+       char(97),
+       char(99),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(77),
+       char(97),
+       char(112),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(99),
+       char(97),
+       char(108),
+       char(101),
+       char(100),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(109),
+       char(112),
+       char(111),
+       char(117),
+       char(110),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(67),
+       char(104),
+       char(105),
+       char(108),
+       char(100),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(109),
+       char(112),
+       char(111),
+       char(117),
+       char(110),
+       char(100),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(121),
+       char(108),
+       char(105),
+       char(110),
+       char(100),
+       char(101),
+       char(114),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(97),
+       char(112),
+       char(115),
+       char(117),
+       char(108),
+       char(101),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(114),
+       char(105),
+       char(97),
+       char(110),
+       char(103),
+       char(108),
+       char(101),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(71),
+       char(73),
+       char(109),
+       char(112),
+       char(97),
+       char(99),
+       char(116),
+       char(77),
+       char(101),
+       char(115),
+       char(104),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(118),
+       char(101),
+       char(120),
+       char(72),
+       char(117),
+       char(108),
+       char(108),
+       char(83),
+       char(104),
+       char(97),
+       char(112),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(79),
+       char(98),
+       char(106),
+       char(101),
+       char(99),
+       char(116),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(108),
+       char(108),
+       char(105),
+       char(115),
+       char(105),
+       char(111),
+       char(110),
+       char(79),
+       char(98),
+       char(106),
+       char(101),
+       char(99),
+       char(116),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(68),
+       char(121),
+       char(110),
+       char(97),
+       char(109),
+       char(105),
+       char(99),
+       char(115),
+       char(87),
+       char(111),
+       char(114),
+       char(108),
+       char(100),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(83),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(68),
+       char(121),
+       char(110),
+       char(97),
+       char(109),
+       char(105),
+       char(99),
+       char(115),
+       char(87),
+       char(111),
+       char(114),
+       char(108),
+       char(100),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(116),
+       char(97),
+       char(99),
+       char(116),
+       char(83),
+       char(111),
+       char(108),
+       char(118),
+       char(101),
+       char(114),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(73),
+       char(110),
+       char(102),
+       char(111),
+       char(49),
+       char(0),
+       char(98),
+       char(116),
+       char(84),
+       char(121),
+       char(112),
+       char(101),
+       char(100),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(50),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(50),
+       char(80),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(72),
+       char(105),
+       char(110),
+       char(103),
+       char(101),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(111),
+       char(117),
+       char(98),
+       char(108),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(72),
+       char(105),
+       char(110),
+       char(103),
+       char(101),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(101),
+       char(84),
+       char(119),
+       char(105),
+       char(115),
+       char(116),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(71),
+       char(101),
+       char(110),
+       char(101),
+       char(114),
+       char(105),
+       char(99),
+       char(54),
+       char(68),
+       char(111),
+       char(102),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(71),
+       char(101),
+       char(110),
+       char(101),
+       char(114),
+       char(105),
+       char(99),
+       char(54),
+       char(68),
+       char(111),
+       char(102),
+       char(83),
+       char(112),
+       char(114),
+       char(105),
+       char(110),
+       char(103),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(108),
+       char(105),
+       char(100),
+       char(101),
+       char(114),
+       char(67),
+       char(111),
+       char(110),
+       char(115),
+       char(116),
+       char(114),
+       char(97),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(77),
+       char(97),
+       char(116),
+       char(101),
+       char(114),
+       char(105),
+       char(97),
+       char(108),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(78),
+       char(111),
+       char(100),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(76),
+       char(105),
+       char(110),
+       char(107),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(70),
+       char(97),
+       char(99),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(84),
+       char(101),
+       char(116),
+       char(114),
+       char(97),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(82),
+       char(105),
+       char(103),
+       char(105),
+       char(100),
+       char(65),
+       char(110),
+       char(99),
+       char(104),
+       char(111),
+       char(114),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(67),
+       char(111),
+       char(110),
+       char(102),
+       char(105),
+       char(103),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(80),
+       char(111),
+       char(115),
+       char(101),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(67),
+       char(108),
+       char(117),
+       char(115),
+       char(116),
+       char(101),
+       char(114),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(74),
+       char(111),
+       char(105),
+       char(110),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(98),
+       char(116),
+       char(83),
+       char(111),
+       char(102),
+       char(116),
+       char(66),
+       char(111),
+       char(100),
+       char(121),
+       char(70),
+       char(108),
+       char(111),
+       char(97),
+       char(116),
+       char(68),
+       char(97),
+       char(116),
+       char(97),
+       char(0),
+       char(0),
+       char(0),
+       char(84),
+       char(76),
+       char(69),
+       char(78),
+       char(1),
+       char(0),
+       char(1),
+       char(0),
+       char(2),
+       char(0),
+       char(2),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(8),
+       char(0),
+       char(0),
+       char(0),
+       char(16),
+       char(0),
+       char(48),
+       char(0),
+       char(16),
+       char(0),
+       char(16),
+       char(0),
+       char(32),
+       char(0),
+       char(48),
+       char(0),
+       char(96),
+       char(0),
+       char(64),
+       char(0),
+       char(-128),
+       char(0),
+       char(20),
+       char(0),
+       char(48),
+       char(0),
+       char(80),
+       char(0),
+       char(16),
+       char(0),
+       char(96),
+       char(0),
+       char(-112),
+       char(0),
+       char(16),
+       char(0),
+       char(56),
+       char(0),
+       char(56),
+       char(0),
+       char(20),
+       char(0),
+       char(72),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(8),
+       char(0),
+       char(4),
+       char(0),
+       char(56),
+       char(0),
+       char(32),
+       char(0),
+       char(80),
+       char(0),
+       char(72),
+       char(0),
+       char(96),
+       char(0),
+       char(80),
+       char(0),
+       char(32),
+       char(0),
+       char(64),
+       char(0),
+       char(64),
+       char(0),
+       char(16),
+       char(0),
+       char(72),
+       char(0),
+       char(80),
+       char(0),
+       char(-32),
+       char(1),
+       char(16),
+       char(1),
+       char(-72),
+       char(0),
+       char(-104),
+       char(0),
+       char(104),
+       char(0),
+       char(88),
+       char(0),
+       char(-8),
+       char(1),
+       char(-80),
+       char(3),
+       char(8),
+       char(0),
+       char(64),
+       char(0),
+       char(0),
+       char(0),
+       char(96),
+       char(0),
+       char(-128),
+       char(0),
+       char(104),
+       char(1),
+       char(-24),
+       char(0),
+       char(-32),
+       char(0),
+       char(8),
+       char(1),
+       char(104),
+       char(1),
+       char(-40),
+       char(0),
+       char(16),
+       char(0),
+       char(104),
+       char(0),
+       char(24),
+       char(0),
+       char(40),
+       char(0),
+       char(104),
+       char(0),
+       char(96),
+       char(0),
+       char(104),
+       char(0),
+       char(-56),
+       char(0),
+       char(104),
+       char(1),
+       char(112),
+       char(0),
+       char(-32),
+       char(1),
+       char(83),
+       char(84),
+       char(82),
+       char(67),
+       char(65),
+       char(0),
+       char(0),
+       char(0),
+       char(10),
+       char(0),
+       char(3),
+       char(0),
+       char(4),
+       char(0),
+       char(0),
+       char(0),
+       char(4),
+       char(0),
+       char(1),
+       char(0),
+       char(9),
+       char(0),
+       char(2),
+       char(0),
+       char(11),
+       char(0),
+       char(3),
+       char(0),
+       char(10),
+       char(0),
+       char(3),
+       char(0),
+       char(10),
+       char(0),
+       char(4),
+       char(0),
+       char(10),
+       char(0),
+       char(5),
+       char(0),
+       char(12),
+       char(0),
+       char(2),
+       char(0),
+       char(9),
+       char(0),
+       char(6),
+       char(0),
+       char(9),
+       char(0),
+       char(7),
+       char(0),
+       char(13),
+       char(0),
+       char(1),
+       char(0),
+       char(7),
+       char(0),
+       char(8),
+       char(0),
+       char(14),
+       char(0),
+       char(1),
+       char(0),
+       char(8),
+       char(0),
+       char(8),
+       char(0),
+       char(15),
+       char(0),
+       char(1),
+       char(0),
+       char(13),
+       char(0),
+       char(9),
+       char(0),
+       char(16),
+       char(0),
+       char(1),
+       char(0),
+       char(14),
+       char(0),
+       char(9),
+       char(0),
+       char(17),
+       char(0),
+       char(2),
+       char(0),
+       char(15),
+       char(0),
+       char(10),
+       char(0),
+       char(13),
+       char(0),
+       char(11),
+       char(0),
+       char(18),
+       char(0),
+       char(2),
+       char(0),
+       char(16),
+       char(0),
+       char(10),
+       char(0),
+       char(14),
+       char(0),
+       char(11),
+       char(0),
+       char(19),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(12),
+       char(0),
+       char(4),
+       char(0),
+       char(13),
+       char(0),
+       char(2),
+       char(0),
+       char(14),
+       char(0),
+       char(2),
+       char(0),
+       char(15),
+       char(0),
+       char(20),
+       char(0),
+       char(6),
+       char(0),
+       char(13),
+       char(0),
+       char(16),
+       char(0),
+       char(13),
+       char(0),
+       char(17),
+       char(0),
+       char(4),
+       char(0),
+       char(18),
+       char(0),
+       char(4),
+       char(0),
+       char(19),
+       char(0),
+       char(4),
+       char(0),
+       char(20),
+       char(0),
+       char(0),
+       char(0),
+       char(21),
+       char(0),
+       char(21),
+       char(0),
+       char(6),
+       char(0),
+       char(14),
+       char(0),
+       char(16),
+       char(0),
+       char(14),
+       char(0),
+       char(17),
+       char(0),
+       char(4),
+       char(0),
+       char(18),
+       char(0),
+       char(4),
+       char(0),
+       char(19),
+       char(0),
+       char(4),
+       char(0),
+       char(20),
+       char(0),
+       char(0),
+       char(0),
+       char(21),
+       char(0),
+       char(22),
+       char(0),
+       char(3),
+       char(0),
+       char(2),
+       char(0),
+       char(14),
+       char(0),
+       char(2),
+       char(0),
+       char(15),
+       char(0),
+       char(4),
+       char(0),
+       char(22),
+       char(0),
+       char(23),
+       char(0),
+       char(12),
+       char(0),
+       char(13),
+       char(0),
+       char(23),
+       char(0),
+       char(13),
+       char(0),
+       char(24),
+       char(0),
+       char(13),
+       char(0),
+       char(25),
+       char(0),
+       char(4),
+       char(0),
+       char(26),
+       char(0),
+       char(4),
+       char(0),
+       char(27),
+       char(0),
+       char(4),
+       char(0),
+       char(28),
+       char(0),
+       char(4),
+       char(0),
+       char(29),
+       char(0),
+       char(20),
+       char(0),
+       char(30),
+       char(0),
+       char(22),
+       char(0),
+       char(31),
+       char(0),
+       char(19),
+       char(0),
+       char(32),
+       char(0),
+       char(4),
+       char(0),
+       char(33),
+       char(0),
+       char(4),
+       char(0),
+       char(34),
+       char(0),
+       char(24),
+       char(0),
+       char(12),
+       char(0),
+       char(14),
+       char(0),
+       char(23),
+       char(0),
+       char(14),
+       char(0),
+       char(24),
+       char(0),
+       char(14),
+       char(0),
+       char(25),
+       char(0),
+       char(4),
+       char(0),
+       char(26),
+       char(0),
+       char(4),
+       char(0),
+       char(27),
+       char(0),
+       char(4),
+       char(0),
+       char(28),
+       char(0),
+       char(4),
+       char(0),
+       char(29),
+       char(0),
+       char(21),
+       char(0),
+       char(30),
+       char(0),
+       char(22),
+       char(0),
+       char(31),
+       char(0),
+       char(4),
+       char(0),
+       char(33),
+       char(0),
+       char(4),
+       char(0),
+       char(34),
+       char(0),
+       char(19),
+       char(0),
+       char(32),
+       char(0),
+       char(25),
+       char(0),
+       char(3),
+       char(0),
+       char(0),
+       char(0),
+       char(35),
+       char(0),
+       char(4),
+       char(0),
+       char(36),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(26),
+       char(0),
+       char(5),
+       char(0),
+       char(25),
+       char(0),
+       char(38),
+       char(0),
+       char(13),
+       char(0),
+       char(39),
+       char(0),
+       char(13),
+       char(0),
+       char(40),
+       char(0),
+       char(7),
+       char(0),
+       char(41),
+       char(0),
+       char(0),
+       char(0),
+       char(21),
+       char(0),
+       char(27),
+       char(0),
+       char(5),
+       char(0),
+       char(25),
+       char(0),
+       char(38),
+       char(0),
+       char(13),
+       char(0),
+       char(39),
+       char(0),
+       char(13),
+       char(0),
+       char(42),
+       char(0),
+       char(7),
+       char(0),
+       char(43),
+       char(0),
+       char(4),
+       char(0),
+       char(44),
+       char(0),
+       char(28),
+       char(0),
+       char(2),
+       char(0),
+       char(13),
+       char(0),
+       char(45),
+       char(0),
+       char(7),
+       char(0),
+       char(46),
+       char(0),
+       char(29),
+       char(0),
+       char(4),
+       char(0),
+       char(27),
+       char(0),
+       char(47),
+       char(0),
+       char(28),
+       char(0),
+       char(48),
+       char(0),
+       char(4),
+       char(0),
+       char(49),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(30),
+       char(0),
+       char(1),
+       char(0),
+       char(4),
+       char(0),
+       char(50),
+       char(0),
+       char(31),
+       char(0),
+       char(2),
+       char(0),
+       char(2),
+       char(0),
+       char(50),
+       char(0),
+       char(0),
+       char(0),
+       char(51),
+       char(0),
+       char(32),
+       char(0),
+       char(2),
+       char(0),
+       char(2),
+       char(0),
+       char(52),
+       char(0),
+       char(0),
+       char(0),
+       char(51),
+       char(0),
+       char(33),
+       char(0),
+       char(2),
+       char(0),
+       char(0),
+       char(0),
+       char(52),
+       char(0),
+       char(0),
+       char(0),
+       char(53),
+       char(0),
+       char(34),
+       char(0),
+       char(8),
+       char(0),
+       char(13),
+       char(0),
+       char(54),
+       char(0),
+       char(14),
+       char(0),
+       char(55),
+       char(0),
+       char(30),
+       char(0),
+       char(56),
+       char(0),
+       char(32),
+       char(0),
+       char(57),
+       char(0),
+       char(33),
+       char(0),
+       char(58),
+       char(0),
+       char(31),
+       char(0),
+       char(59),
+       char(0),
+       char(4),
+       char(0),
+       char(60),
+       char(0),
+       char(4),
+       char(0),
+       char(61),
+       char(0),
+       char(35),
+       char(0),
+       char(4),
+       char(0),
+       char(34),
+       char(0),
+       char(62),
+       char(0),
+       char(13),
+       char(0),
+       char(63),
+       char(0),
+       char(4),
+       char(0),
+       char(64),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(36),
+       char(0),
+       char(7),
+       char(0),
+       char(25),
+       char(0),
+       char(38),
+       char(0),
+       char(35),
+       char(0),
+       char(65),
+       char(0),
+       char(23),
+       char(0),
+       char(66),
+       char(0),
+       char(24),
+       char(0),
+       char(67),
+       char(0),
+       char(37),
+       char(0),
+       char(68),
+       char(0),
+       char(7),
+       char(0),
+       char(43),
+       char(0),
+       char(0),
+       char(0),
+       char(69),
+       char(0),
+       char(38),
+       char(0),
+       char(2),
+       char(0),
+       char(36),
+       char(0),
+       char(70),
+       char(0),
+       char(13),
+       char(0),
+       char(39),
+       char(0),
+       char(39),
+       char(0),
+       char(4),
+       char(0),
+       char(17),
+       char(0),
+       char(71),
+       char(0),
+       char(25),
+       char(0),
+       char(72),
+       char(0),
+       char(4),
+       char(0),
+       char(73),
+       char(0),
+       char(7),
+       char(0),
+       char(74),
+       char(0),
+       char(40),
+       char(0),
+       char(4),
+       char(0),
+       char(25),
+       char(0),
+       char(38),
+       char(0),
+       char(39),
+       char(0),
+       char(75),
+       char(0),
+       char(4),
+       char(0),
+       char(76),
+       char(0),
+       char(7),
+       char(0),
+       char(43),
+       char(0),
+       char(41),
+       char(0),
+       char(3),
+       char(0),
+       char(27),
+       char(0),
+       char(47),
+       char(0),
+       char(4),
+       char(0),
+       char(77),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(42),
+       char(0),
+       char(3),
+       char(0),
+       char(27),
+       char(0),
+       char(47),
+       char(0),
+       char(4),
+       char(0),
+       char(77),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(43),
+       char(0),
+       char(4),
+       char(0),
+       char(4),
+       char(0),
+       char(78),
+       char(0),
+       char(7),
+       char(0),
+       char(79),
+       char(0),
+       char(7),
+       char(0),
+       char(80),
+       char(0),
+       char(7),
+       char(0),
+       char(81),
+       char(0),
+       char(37),
+       char(0),
+       char(14),
+       char(0),
+       char(4),
+       char(0),
+       char(82),
+       char(0),
+       char(4),
+       char(0),
+       char(83),
+       char(0),
+       char(43),
+       char(0),
+       char(84),
+       char(0),
+       char(4),
+       char(0),
+       char(85),
+       char(0),
+       char(7),
+       char(0),
+       char(86),
+       char(0),
+       char(7),
+       char(0),
+       char(87),
+       char(0),
+       char(7),
+       char(0),
+       char(88),
+       char(0),
+       char(7),
+       char(0),
+       char(89),
+       char(0),
+       char(7),
+       char(0),
+       char(90),
+       char(0),
+       char(4),
+       char(0),
+       char(91),
+       char(0),
+       char(4),
+       char(0),
+       char(92),
+       char(0),
+       char(4),
+       char(0),
+       char(93),
+       char(0),
+       char(4),
+       char(0),
+       char(94),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(44),
+       char(0),
+       char(5),
+       char(0),
+       char(25),
+       char(0),
+       char(38),
+       char(0),
+       char(35),
+       char(0),
+       char(65),
+       char(0),
+       char(13),
+       char(0),
+       char(39),
+       char(0),
+       char(7),
+       char(0),
+       char(43),
+       char(0),
+       char(4),
+       char(0),
+       char(95),
+       char(0),
+       char(45),
+       char(0),
+       char(5),
+       char(0),
+       char(27),
+       char(0),
+       char(47),
+       char(0),
+       char(13),
+       char(0),
+       char(96),
+       char(0),
+       char(14),
+       char(0),
+       char(97),
+       char(0),
+       char(4),
+       char(0),
+       char(98),
+       char(0),
+       char(0),
+       char(0),
+       char(99),
+       char(0),
+       char(46),
+       char(0),
+       char(25),
+       char(0),
+       char(9),
+       char(0),
+       char(100),
+       char(0),
+       char(9),
+       char(0),
+       char(101),
+       char(0),
+       char(25),
+       char(0),
+       char(102),
+       char(0),
+       char(0),
+       char(0),
+       char(35),
+       char(0),
+       char(18),
+       char(0),
+       char(103),
+       char(0),
+       char(18),
+       char(0),
+       char(104),
+       char(0),
+       char(14),
+       char(0),
+       char(105),
+       char(0),
+       char(14),
+       char(0),
+       char(106),
+       char(0),
+       char(14),
+       char(0),
+       char(107),
+       char(0),
+       char(8),
+       char(0),
+       char(108),
+       char(0),
+       char(8),
+       char(0),
+       char(109),
+       char(0),
+       char(8),
+       char(0),
+       char(110),
+       char(0),
+       char(8),
+       char(0),
+       char(111),
+       char(0),
+       char(8),
+       char(0),
+       char(112),
+       char(0),
+       char(8),
+       char(0),
+       char(113),
+       char(0),
+       char(8),
+       char(0),
+       char(114),
+       char(0),
+       char(8),
+       char(0),
+       char(115),
+       char(0),
+       char(4),
+       char(0),
+       char(116),
+       char(0),
+       char(4),
+       char(0),
+       char(117),
+       char(0),
+       char(4),
+       char(0),
+       char(118),
+       char(0),
+       char(4),
+       char(0),
+       char(119),
+       char(0),
+       char(4),
+       char(0),
+       char(120),
+       char(0),
+       char(4),
+       char(0),
+       char(121),
+       char(0),
+       char(4),
+       char(0),
+       char(122),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(47),
+       char(0),
+       char(25),
+       char(0),
+       char(9),
+       char(0),
+       char(100),
+       char(0),
+       char(9),
+       char(0),
+       char(101),
+       char(0),
+       char(25),
+       char(0),
+       char(102),
+       char(0),
+       char(0),
+       char(0),
+       char(35),
+       char(0),
+       char(17),
+       char(0),
+       char(103),
+       char(0),
+       char(17),
+       char(0),
+       char(104),
+       char(0),
+       char(13),
+       char(0),
+       char(105),
+       char(0),
+       char(13),
+       char(0),
+       char(106),
+       char(0),
+       char(13),
+       char(0),
+       char(107),
+       char(0),
+       char(7),
+       char(0),
+       char(108),
+       char(0),
+       char(7),
+       char(0),
+       char(109),
+       char(0),
+       char(7),
+       char(0),
+       char(110),
+       char(0),
+       char(7),
+       char(0),
+       char(111),
+       char(0),
+       char(7),
+       char(0),
+       char(112),
+       char(0),
+       char(7),
+       char(0),
+       char(113),
+       char(0),
+       char(7),
+       char(0),
+       char(114),
+       char(0),
+       char(7),
+       char(0),
+       char(115),
+       char(0),
+       char(4),
+       char(0),
+       char(116),
+       char(0),
+       char(4),
+       char(0),
+       char(117),
+       char(0),
+       char(4),
+       char(0),
+       char(118),
+       char(0),
+       char(4),
+       char(0),
+       char(119),
+       char(0),
+       char(4),
+       char(0),
+       char(120),
+       char(0),
+       char(4),
+       char(0),
+       char(121),
+       char(0),
+       char(4),
+       char(0),
+       char(122),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(48),
+       char(0),
+       char(2),
+       char(0),
+       char(49),
+       char(0),
+       char(123),
+       char(0),
+       char(14),
+       char(0),
+       char(124),
+       char(0),
+       char(50),
+       char(0),
+       char(2),
+       char(0),
+       char(51),
+       char(0),
+       char(123),
+       char(0),
+       char(13),
+       char(0),
+       char(124),
+       char(0),
+       char(52),
+       char(0),
+       char(21),
+       char(0),
+       char(47),
+       char(0),
+       char(125),
+       char(0),
+       char(15),
+       char(0),
+       char(126),
+       char(0),
+       char(13),
+       char(0),
+       char(127),
+       char(0),
+       char(13),
+       char(0),
+       char(-128),
+       char(0),
+       char(13),
+       char(0),
+       char(-127),
+       char(0),
+       char(13),
+       char(0),
+       char(-126),
+       char(0),
+       char(13),
+       char(0),
+       char(124),
+       char(0),
+       char(13),
+       char(0),
+       char(-125),
+       char(0),
+       char(13),
+       char(0),
+       char(-124),
+       char(0),
+       char(13),
+       char(0),
+       char(-123),
+       char(0),
+       char(13),
+       char(0),
+       char(-122),
+       char(0),
+       char(7),
+       char(0),
+       char(-121),
+       char(0),
+       char(7),
+       char(0),
+       char(-120),
+       char(0),
+       char(7),
+       char(0),
+       char(-119),
+       char(0),
+       char(7),
+       char(0),
+       char(-118),
+       char(0),
+       char(7),
+       char(0),
+       char(-117),
+       char(0),
+       char(7),
+       char(0),
+       char(-116),
+       char(0),
+       char(7),
+       char(0),
+       char(-115),
+       char(0),
+       char(7),
+       char(0),
+       char(-114),
+       char(0),
+       char(7),
+       char(0),
+       char(-113),
+       char(0),
+       char(4),
+       char(0),
+       char(-112),
+       char(0),
+       char(53),
+       char(0),
+       char(22),
+       char(0),
+       char(46),
+       char(0),
+       char(125),
+       char(0),
+       char(16),
+       char(0),
+       char(126),
+       char(0),
+       char(14),
+       char(0),
+       char(127),
+       char(0),
+       char(14),
+       char(0),
+       char(-128),
+       char(0),
+       char(14),
+       char(0),
+       char(-127),
+       char(0),
+       char(14),
+       char(0),
+       char(-126),
+       char(0),
+       char(14),
+       char(0),
+       char(124),
+       char(0),
+       char(14),
+       char(0),
+       char(-125),
+       char(0),
+       char(14),
+       char(0),
+       char(-124),
+       char(0),
+       char(14),
+       char(0),
+       char(-123),
+       char(0),
+       char(14),
+       char(0),
+       char(-122),
+       char(0),
+       char(8),
+       char(0),
+       char(-121),
+       char(0),
+       char(8),
+       char(0),
+       char(-120),
+       char(0),
+       char(8),
+       char(0),
+       char(-119),
+       char(0),
+       char(8),
+       char(0),
+       char(-118),
+       char(0),
+       char(8),
+       char(0),
+       char(-117),
+       char(0),
+       char(8),
+       char(0),
+       char(-116),
+       char(0),
+       char(8),
+       char(0),
+       char(-115),
+       char(0),
+       char(8),
+       char(0),
+       char(-114),
+       char(0),
+       char(8),
+       char(0),
+       char(-113),
+       char(0),
+       char(4),
+       char(0),
+       char(-112),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(54),
+       char(0),
+       char(2),
+       char(0),
+       char(4),
+       char(0),
+       char(-111),
+       char(0),
+       char(4),
+       char(0),
+       char(-110),
+       char(0),
+       char(55),
+       char(0),
+       char(13),
+       char(0),
+       char(56),
+       char(0),
+       char(-109),
+       char(0),
+       char(56),
+       char(0),
+       char(-108),
+       char(0),
+       char(0),
+       char(0),
+       char(35),
+       char(0),
+       char(4),
+       char(0),
+       char(-107),
+       char(0),
+       char(4),
+       char(0),
+       char(-106),
+       char(0),
+       char(4),
+       char(0),
+       char(-105),
+       char(0),
+       char(4),
+       char(0),
+       char(-104),
+       char(0),
+       char(7),
+       char(0),
+       char(-103),
+       char(0),
+       char(7),
+       char(0),
+       char(-102),
+       char(0),
+       char(4),
+       char(0),
+       char(-101),
+       char(0),
+       char(4),
+       char(0),
+       char(-100),
+       char(0),
+       char(7),
+       char(0),
+       char(-99),
+       char(0),
+       char(4),
+       char(0),
+       char(-98),
+       char(0),
+       char(57),
+       char(0),
+       char(3),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(13),
+       char(0),
+       char(-96),
+       char(0),
+       char(13),
+       char(0),
+       char(-95),
+       char(0),
+       char(58),
+       char(0),
+       char(3),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(14),
+       char(0),
+       char(-96),
+       char(0),
+       char(14),
+       char(0),
+       char(-95),
+       char(0),
+       char(59),
+       char(0),
+       char(13),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(18),
+       char(0),
+       char(-94),
+       char(0),
+       char(18),
+       char(0),
+       char(-93),
+       char(0),
+       char(4),
+       char(0),
+       char(-92),
+       char(0),
+       char(4),
+       char(0),
+       char(-91),
+       char(0),
+       char(4),
+       char(0),
+       char(-90),
+       char(0),
+       char(7),
+       char(0),
+       char(-89),
+       char(0),
+       char(7),
+       char(0),
+       char(-88),
+       char(0),
+       char(7),
+       char(0),
+       char(-87),
+       char(0),
+       char(7),
+       char(0),
+       char(-86),
+       char(0),
+       char(7),
+       char(0),
+       char(-85),
+       char(0),
+       char(7),
+       char(0),
+       char(-84),
+       char(0),
+       char(7),
+       char(0),
+       char(-83),
+       char(0),
+       char(60),
+       char(0),
+       char(13),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(17),
+       char(0),
+       char(-94),
+       char(0),
+       char(17),
+       char(0),
+       char(-93),
+       char(0),
+       char(4),
+       char(0),
+       char(-92),
+       char(0),
+       char(4),
+       char(0),
+       char(-91),
+       char(0),
+       char(4),
+       char(0),
+       char(-90),
+       char(0),
+       char(7),
+       char(0),
+       char(-89),
+       char(0),
+       char(7),
+       char(0),
+       char(-88),
+       char(0),
+       char(7),
+       char(0),
+       char(-87),
+       char(0),
+       char(7),
+       char(0),
+       char(-86),
+       char(0),
+       char(7),
+       char(0),
+       char(-85),
+       char(0),
+       char(7),
+       char(0),
+       char(-84),
+       char(0),
+       char(7),
+       char(0),
+       char(-83),
+       char(0),
+       char(61),
+       char(0),
+       char(11),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(17),
+       char(0),
+       char(-94),
+       char(0),
+       char(17),
+       char(0),
+       char(-93),
+       char(0),
+       char(7),
+       char(0),
+       char(-82),
+       char(0),
+       char(7),
+       char(0),
+       char(-81),
+       char(0),
+       char(7),
+       char(0),
+       char(-80),
+       char(0),
+       char(7),
+       char(0),
+       char(-85),
+       char(0),
+       char(7),
+       char(0),
+       char(-84),
+       char(0),
+       char(7),
+       char(0),
+       char(-83),
+       char(0),
+       char(7),
+       char(0),
+       char(-79),
+       char(0),
+       char(0),
+       char(0),
+       char(21),
+       char(0),
+       char(62),
+       char(0),
+       char(9),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(17),
+       char(0),
+       char(-94),
+       char(0),
+       char(17),
+       char(0),
+       char(-93),
+       char(0),
+       char(13),
+       char(0),
+       char(-78),
+       char(0),
+       char(13),
+       char(0),
+       char(-77),
+       char(0),
+       char(13),
+       char(0),
+       char(-76),
+       char(0),
+       char(13),
+       char(0),
+       char(-75),
+       char(0),
+       char(4),
+       char(0),
+       char(-74),
+       char(0),
+       char(4),
+       char(0),
+       char(-73),
+       char(0),
+       char(63),
+       char(0),
+       char(5),
+       char(0),
+       char(62),
+       char(0),
+       char(-72),
+       char(0),
+       char(4),
+       char(0),
+       char(-71),
+       char(0),
+       char(7),
+       char(0),
+       char(-70),
+       char(0),
+       char(7),
+       char(0),
+       char(-69),
+       char(0),
+       char(7),
+       char(0),
+       char(-68),
+       char(0),
+       char(64),
+       char(0),
+       char(9),
+       char(0),
+       char(55),
+       char(0),
+       char(-97),
+       char(0),
+       char(17),
+       char(0),
+       char(-94),
+       char(0),
+       char(17),
+       char(0),
+       char(-93),
+       char(0),
+       char(7),
+       char(0),
+       char(-78),
+       char(0),
+       char(7),
+       char(0),
+       char(-77),
+       char(0),
+       char(7),
+       char(0),
+       char(-76),
+       char(0),
+       char(7),
+       char(0),
+       char(-75),
+       char(0),
+       char(4),
+       char(0),
+       char(-74),
+       char(0),
+       char(4),
+       char(0),
+       char(-73),
+       char(0),
+       char(49),
+       char(0),
+       char(22),
+       char(0),
+       char(8),
+       char(0),
+       char(-67),
+       char(0),
+       char(8),
+       char(0),
+       char(-79),
+       char(0),
+       char(8),
+       char(0),
+       char(110),
+       char(0),
+       char(8),
+       char(0),
+       char(-66),
+       char(0),
+       char(8),
+       char(0),
+       char(112),
+       char(0),
+       char(8),
+       char(0),
+       char(-65),
+       char(0),
+       char(8),
+       char(0),
+       char(-64),
+       char(0),
+       char(8),
+       char(0),
+       char(-63),
+       char(0),
+       char(8),
+       char(0),
+       char(-62),
+       char(0),
+       char(8),
+       char(0),
+       char(-61),
+       char(0),
+       char(8),
+       char(0),
+       char(-60),
+       char(0),
+       char(8),
+       char(0),
+       char(-59),
+       char(0),
+       char(8),
+       char(0),
+       char(-58),
+       char(0),
+       char(8),
+       char(0),
+       char(-57),
+       char(0),
+       char(8),
+       char(0),
+       char(-56),
+       char(0),
+       char(8),
+       char(0),
+       char(-55),
+       char(0),
+       char(4),
+       char(0),
+       char(-54),
+       char(0),
+       char(4),
+       char(0),
+       char(-53),
+       char(0),
+       char(4),
+       char(0),
+       char(-52),
+       char(0),
+       char(4),
+       char(0),
+       char(-51),
+       char(0),
+       char(4),
+       char(0),
+       char(-50),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(51),
+       char(0),
+       char(22),
+       char(0),
+       char(7),
+       char(0),
+       char(-67),
+       char(0),
+       char(7),
+       char(0),
+       char(-79),
+       char(0),
+       char(7),
+       char(0),
+       char(110),
+       char(0),
+       char(7),
+       char(0),
+       char(-66),
+       char(0),
+       char(7),
+       char(0),
+       char(112),
+       char(0),
+       char(7),
+       char(0),
+       char(-65),
+       char(0),
+       char(7),
+       char(0),
+       char(-64),
+       char(0),
+       char(7),
+       char(0),
+       char(-63),
+       char(0),
+       char(7),
+       char(0),
+       char(-62),
+       char(0),
+       char(7),
+       char(0),
+       char(-61),
+       char(0),
+       char(7),
+       char(0),
+       char(-60),
+       char(0),
+       char(7),
+       char(0),
+       char(-59),
+       char(0),
+       char(7),
+       char(0),
+       char(-58),
+       char(0),
+       char(7),
+       char(0),
+       char(-57),
+       char(0),
+       char(7),
+       char(0),
+       char(-56),
+       char(0),
+       char(7),
+       char(0),
+       char(-55),
+       char(0),
+       char(4),
+       char(0),
+       char(-54),
+       char(0),
+       char(4),
+       char(0),
+       char(-53),
+       char(0),
+       char(4),
+       char(0),
+       char(-52),
+       char(0),
+       char(4),
+       char(0),
+       char(-51),
+       char(0),
+       char(4),
+       char(0),
+       char(-50),
+       char(0),
+       char(0),
+       char(0),
+       char(37),
+       char(0),
+       char(65),
+       char(0),
+       char(4),
+       char(0),
+       char(7),
+       char(0),
+       char(-49),
+       char(0),
+       char(7),
+       char(0),
+       char(-48),
+       char(0),
+       char(7),
+       char(0),
+       char(-47),
+       char(0),
+       char(4),
+       char(0),
+       char(78),
+       char(0),
+       char(66),
+       char(0),
+       char(10),
+       char(0),
+       char(65),
+       char(0),
+       char(-46),
+       char(0),
+       char(13),
+       char(0),
+       char(-45),
+       char(0),
+       char(13),
+       char(0),
+       char(-44),
+       char(0),
+       char(13),
+       char(0),
+       char(-43),
+       char(0),
+       char(13),
+       char(0),
+       char(-42),
+       char(0),
+       char(13),
+       char(0),
+       char(-41),
+       char(0),
+       char(7),
+       char(0),
+       char(-121),
+       char(0),
+       char(7),
+       char(0),
+       char(-40),
+       char(0),
+       char(4),
+       char(0),
+       char(-39),
+       char(0),
+       char(4),
+       char(0),
+       char(53),
+       char(0),
+       char(67),
+       char(0),
+       char(4),
+       char(0),
+       char(65),
+       char(0),
+       char(-46),
+       char(0),
+       char(4),
+       char(0),
+       char(-38),
+       char(0),
+       char(7),
+       char(0),
+       char(-37),
+       char(0),
+       char(4),
+       char(0),
+       char(-36),
+       char(0),
+       char(68),
+       char(0),
+       char(4),
+       char(0),
+       char(13),
+       char(0),
+       char(-41),
+       char(0),
+       char(65),
+       char(0),
+       char(-46),
+       char(0),
+       char(4),
+       char(0),
+       char(-35),
+       char(0),
+       char(7),
+       char(0),
+       char(-34),
+       char(0),
+       char(69),
+       char(0),
+       char(7),
+       char(0),
+       char(13),
+       char(0),
+       char(-33),
+       char(0),
+       char(65),
+       char(0),
+       char(-46),
+       char(0),
+       char(4),
+       char(0),
+       char(-32),
+       char(0),
+       char(7),
+       char(0),
+       char(-31),
+       char(0),
+       char(7),
+       char(0),
+       char(-30),
+       char(0),
+       char(7),
+       char(0),
+       char(-29),
+       char(0),
+       char(4),
+       char(0),
+       char(53),
+       char(0),
+       char(70),
+       char(0),
+       char(6),
+       char(0),
+       char(15),
+       char(0),
+       char(-28),
+       char(0),
+       char(13),
+       char(0),
+       char(-30),
+       char(0),
+       char(13),
+       char(0),
+       char(-27),
+       char(0),
+       char(56),
+       char(0),
+       char(-26),
+       char(0),
+       char(4),
+       char(0),
+       char(-25),
+       char(0),
+       char(7),
+       char(0),
+       char(-29),
+       char(0),
+       char(71),
+       char(0),
+       char(26),
+       char(0),
+       char(4),
+       char(0),
+       char(-24),
+       char(0),
+       char(7),
+       char(0),
+       char(-23),
+       char(0),
+       char(7),
+       char(0),
+       char(-79),
+       char(0),
+       char(7),
+       char(0),
+       char(-22),
+       char(0),
+       char(7),
+       char(0),
+       char(-21),
+       char(0),
+       char(7),
+       char(0),
+       char(-20),
+       char(0),
+       char(7),
+       char(0),
+       char(-19),
+       char(0),
+       char(7),
+       char(0),
+       char(-18),
+       char(0),
+       char(7),
+       char(0),
+       char(-17),
+       char(0),
+       char(7),
+       char(0),
+       char(-16),
+       char(0),
+       char(7),
+       char(0),
+       char(-15),
+       char(0),
+       char(7),
+       char(0),
+       char(-14),
+       char(0),
+       char(7),
+       char(0),
+       char(-13),
+       char(0),
+       char(7),
+       char(0),
+       char(-12),
+       char(0),
+       char(7),
+       char(0),
+       char(-11),
+       char(0),
+       char(7),
+       char(0),
+       char(-10),
+       char(0),
+       char(7),
+       char(0),
+       char(-9),
+       char(0),
+       char(7),
+       char(0),
+       char(-8),
+       char(0),
+       char(7),
+       char(0),
+       char(-7),
+       char(0),
+       char(7),
+       char(0),
+       char(-6),
+       char(0),
+       char(7),
+       char(0),
+       char(-5),
+       char(0),
+       char(4),
+       char(0),
+       char(-4),
+       char(0),
+       char(4),
+       char(0),
+       char(-3),
+       char(0),
+       char(4),
+       char(0),
+       char(-2),
+       char(0),
+       char(4),
+       char(0),
+       char(-1),
+       char(0),
+       char(4),
+       char(0),
+       char(117),
+       char(0),
+       char(72),
+       char(0),
+       char(12),
+       char(0),
+       char(15),
+       char(0),
+       char(0),
+       char(1),
+       char(15),
+       char(0),
+       char(1),
+       char(1),
+       char(15),
+       char(0),
+       char(2),
+       char(1),
+       char(13),
+       char(0),
+       char(3),
+       char(1),
+       char(13),
+       char(0),
+       char(4),
+       char(1),
+       char(7),
+       char(0),
+       char(5),
+       char(1),
+       char(4),
+       char(0),
+       char(6),
+       char(1),
+       char(4),
+       char(0),
+       char(7),
+       char(1),
+       char(4),
+       char(0),
+       char(8),
+       char(1),
+       char(4),
+       char(0),
+       char(9),
+       char(1),
+       char(7),
+       char(0),
+       char(-31),
+       char(0),
+       char(4),
+       char(0),
+       char(53),
+       char(0),
+       char(73),
+       char(0),
+       char(27),
+       char(0),
+       char(17),
+       char(0),
+       char(10),
+       char(1),
+       char(15),
+       char(0),
+       char(11),
+       char(1),
+       char(15),
+       char(0),
+       char(12),
+       char(1),
+       char(13),
+       char(0),
+       char(3),
+       char(1),
+       char(13),
+       char(0),
+       char(13),
+       char(1),
+       char(13),
+       char(0),
+       char(14),
+       char(1),
+       char(13),
+       char(0),
+       char(15),
+       char(1),
+       char(13),
+       char(0),
+       char(16),
+       char(1),
+       char(13),
+       char(0),
+       char(17),
+       char(1),
+       char(4),
+       char(0),
+       char(18),
+       char(1),
+       char(7),
+       char(0),
+       char(19),
+       char(1),
+       char(4),
+       char(0),
+       char(20),
+       char(1),
+       char(4),
+       char(0),
+       char(21),
+       char(1),
+       char(4),
+       char(0),
+       char(22),
+       char(1),
+       char(7),
+       char(0),
+       char(23),
+       char(1),
+       char(7),
+       char(0),
+       char(24),
+       char(1),
+       char(4),
+       char(0),
+       char(25),
+       char(1),
+       char(4),
+       char(0),
+       char(26),
+       char(1),
+       char(7),
+       char(0),
+       char(27),
+       char(1),
+       char(7),
+       char(0),
+       char(28),
+       char(1),
+       char(7),
+       char(0),
+       char(29),
+       char(1),
+       char(7),
+       char(0),
+       char(30),
+       char(1),
+       char(7),
+       char(0),
+       char(31),
+       char(1),
+       char(7),
+       char(0),
+       char(32),
+       char(1),
+       char(4),
+       char(0),
+       char(33),
+       char(1),
+       char(4),
+       char(0),
+       char(34),
+       char(1),
+       char(4),
+       char(0),
+       char(35),
+       char(1),
+       char(74),
+       char(0),
+       char(12),
+       char(0),
+       char(9),
+       char(0),
+       char(36),
+       char(1),
+       char(9),
+       char(0),
+       char(37),
+       char(1),
+       char(13),
+       char(0),
+       char(38),
+       char(1),
+       char(7),
+       char(0),
+       char(39),
+       char(1),
+       char(7),
+       char(0),
+       char(-63),
+       char(0),
+       char(7),
+       char(0),
+       char(40),
+       char(1),
+       char(4),
+       char(0),
+       char(41),
+       char(1),
+       char(13),
+       char(0),
+       char(42),
+       char(1),
+       char(4),
+       char(0),
+       char(43),
+       char(1),
+       char(4),
+       char(0),
+       char(44),
+       char(1),
+       char(4),
+       char(0),
+       char(45),
+       char(1),
+       char(4),
+       char(0),
+       char(53),
+       char(0),
+       char(75),
+       char(0),
+       char(19),
+       char(0),
+       char(47),
+       char(0),
+       char(125),
+       char(0),
+       char(72),
+       char(0),
+       char(46),
+       char(1),
+       char(65),
+       char(0),
+       char(47),
+       char(1),
+       char(66),
+       char(0),
+       char(48),
+       char(1),
+       char(67),
+       char(0),
+       char(49),
+       char(1),
+       char(68),
+       char(0),
+       char(50),
+       char(1),
+       char(69),
+       char(0),
+       char(51),
+       char(1),
+       char(70),
+       char(0),
+       char(52),
+       char(1),
+       char(73),
+       char(0),
+       char(53),
+       char(1),
+       char(74),
+       char(0),
+       char(54),
+       char(1),
+       char(4),
+       char(0),
+       char(55),
+       char(1),
+       char(4),
+       char(0),
+       char(21),
+       char(1),
+       char(4),
+       char(0),
+       char(56),
+       char(1),
+       char(4),
+       char(0),
+       char(57),
+       char(1),
+       char(4),
+       char(0),
+       char(58),
+       char(1),
+       char(4),
+       char(0),
+       char(59),
+       char(1),
+       char(4),
+       char(0),
+       char(60),
+       char(1),
+       char(4),
+       char(0),
+       char(61),
+       char(1),
+       char(71),
+       char(0),
+       char(62),
+       char(1),
+};
+int b3s_bulletDNAlen64 = sizeof(b3s_bulletDNAstr64);
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h
new file mode 100644 (file)
index 0000000..d9e153e
--- /dev/null
@@ -0,0 +1,601 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 B3_SERIALIZER_H
+#define B3_SERIALIZER_H
+
+#include "Bullet3Common/b3Scalar.h"  // has definitions like B3_FORCE_INLINE
+#include "Bullet3Common/b3StackAlloc.h"
+#include "Bullet3Common/b3HashMap.h"
+
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+extern char b3s_bulletDNAstr[];
+extern int b3s_bulletDNAlen;
+extern char b3s_bulletDNAstr64[];
+extern int b3s_bulletDNAlen64;
+
+B3_FORCE_INLINE int b3StrLen(const char* str)
+{
+       if (!str)
+               return (0);
+       int len = 0;
+
+       while (*str != 0)
+       {
+               str++;
+               len++;
+       }
+
+       return len;
+}
+
+class b3Chunk
+{
+public:
+       int m_chunkCode;
+       int m_length;
+       void* m_oldPtr;
+       int m_dna_nr;
+       int m_number;
+};
+
+enum b3SerializationFlags
+{
+       B3_SERIALIZE_NO_BVH = 1,
+       B3_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
+       B3_SERIALIZE_NO_DUPLICATE_ASSERT = 4
+};
+
+class b3Serializer
+{
+public:
+       virtual ~b3Serializer() {}
+
+       virtual const unsigned char* getBufferPointer() const = 0;
+
+       virtual int getCurrentBufferSize() const = 0;
+
+       virtual b3Chunk* allocate(size_t size, int numElements) = 0;
+
+       virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode, void* oldPtr) = 0;
+
+       virtual void* findPointer(void* oldPtr) = 0;
+
+       virtual void* getUniquePointer(void* oldPtr) = 0;
+
+       virtual void startSerialization() = 0;
+
+       virtual void finishSerialization() = 0;
+
+       virtual const char* findNameForPointer(const void* ptr) const = 0;
+
+       virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
+
+       virtual void serializeName(const char* ptr) = 0;
+
+       virtual int getSerializationFlags() const = 0;
+
+       virtual void setSerializationFlags(int flags) = 0;
+};
+
+#define B3_HEADER_LENGTH 12
+#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
+#define B3_MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
+#else
+#define B3_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
+#endif
+
+#define B3_SOFTBODY_CODE B3_MAKE_ID('S', 'B', 'D', 'Y')
+#define B3_COLLISIONOBJECT_CODE B3_MAKE_ID('C', 'O', 'B', 'J')
+#define B3_RIGIDBODY_CODE B3_MAKE_ID('R', 'B', 'D', 'Y')
+#define B3_CONSTRAINT_CODE B3_MAKE_ID('C', 'O', 'N', 'S')
+#define B3_BOXSHAPE_CODE B3_MAKE_ID('B', 'O', 'X', 'S')
+#define B3_QUANTIZED_BVH_CODE B3_MAKE_ID('Q', 'B', 'V', 'H')
+#define B3_TRIANLGE_INFO_MAP B3_MAKE_ID('T', 'M', 'A', 'P')
+#define B3_SHAPE_CODE B3_MAKE_ID('S', 'H', 'A', 'P')
+#define B3_ARRAY_CODE B3_MAKE_ID('A', 'R', 'A', 'Y')
+#define B3_SBMATERIAL_CODE B3_MAKE_ID('S', 'B', 'M', 'T')
+#define B3_SBNODE_CODE B3_MAKE_ID('S', 'B', 'N', 'D')
+#define B3_DYNAMICSWORLD_CODE B3_MAKE_ID('D', 'W', 'L', 'D')
+#define B3_DNA_CODE B3_MAKE_ID('D', 'N', 'A', '1')
+
+struct b3PointerUid
+{
+       union {
+               void* m_ptr;
+               int m_uniqueIds[2];
+       };
+};
+
+///The b3DefaultSerializer is the main Bullet serialization class.
+///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
+class b3DefaultSerializer : public b3Serializer
+{
+       b3AlignedObjectArray<char*> mTypes;
+       b3AlignedObjectArray<short*> mStructs;
+       b3AlignedObjectArray<short> mTlens;
+       b3HashMap<b3HashInt, int> mStructReverse;
+       b3HashMap<b3HashString, int> mTypeLookup;
+
+       b3HashMap<b3HashPtr, void*> m_chunkP;
+
+       b3HashMap<b3HashPtr, const char*> m_nameMap;
+
+       b3HashMap<b3HashPtr, b3PointerUid> m_uniquePointers;
+       int m_uniqueIdGenerator;
+
+       int m_totalSize;
+       unsigned char* m_buffer;
+       int m_currentSize;
+       void* m_dna;
+       int m_dnaLength;
+
+       int m_serializationFlags;
+
+       b3AlignedObjectArray<b3Chunk*> m_chunkPtrs;
+
+protected:
+       virtual void* findPointer(void* oldPtr)
+       {
+               void** ptr = m_chunkP.find(oldPtr);
+               if (ptr && *ptr)
+                       return *ptr;
+               return 0;
+       }
+
+       void writeDNA()
+       {
+               b3Chunk* dnaChunk = allocate(m_dnaLength, 1);
+               memcpy(dnaChunk->m_oldPtr, m_dna, m_dnaLength);
+               finalizeChunk(dnaChunk, "DNA1", B3_DNA_CODE, m_dna);
+       }
+
+       int getReverseType(const char* type) const
+       {
+               b3HashString key(type);
+               const int* valuePtr = mTypeLookup.find(key);
+               if (valuePtr)
+                       return *valuePtr;
+
+               return -1;
+       }
+
+       void initDNA(const char* bdnaOrg, int dnalen)
+       {
+               ///was already initialized
+               if (m_dna)
+                       return;
+
+               int littleEndian = 1;
+               littleEndian = ((char*)&littleEndian)[0];
+
+               m_dna = b3AlignedAlloc(dnalen, 16);
+               memcpy(m_dna, bdnaOrg, dnalen);
+               m_dnaLength = dnalen;
+
+               int* intPtr = 0;
+               short* shtPtr = 0;
+               char* cp = 0;
+               int dataLen = 0;
+               intPtr = (int*)m_dna;
+
+               /*
+                               SDNA (4 bytes) (magic number)
+                               NAME (4 bytes)
+                               <nr> (4 bytes) amount of names (int)
+                               <string>
+                               <string>
+                       */
+
+               if (strncmp((const char*)m_dna, "SDNA", 4) == 0)
+               {
+                       // skip ++ NAME
+                       intPtr++;
+                       intPtr++;
+               }
+
+               // Parse names
+               if (!littleEndian)
+                       *intPtr = b3SwapEndian(*intPtr);
+
+               dataLen = *intPtr;
+
+               intPtr++;
+
+               cp = (char*)intPtr;
+               int i;
+               for (i = 0; i < dataLen; i++)
+               {
+                       while (*cp) cp++;
+                       cp++;
+               }
+               cp = b3AlignPointer(cp, 4);
+
+               /*
+                               TYPE (4 bytes)
+                               <nr> amount of types (int)
+                               <string>
+                               <string>
+                       */
+
+               intPtr = (int*)cp;
+               b3Assert(strncmp(cp, "TYPE", 4) == 0);
+               intPtr++;
+
+               if (!littleEndian)
+                       *intPtr = b3SwapEndian(*intPtr);
+
+               dataLen = *intPtr;
+               intPtr++;
+
+               cp = (char*)intPtr;
+               for (i = 0; i < dataLen; i++)
+               {
+                       mTypes.push_back(cp);
+                       while (*cp) cp++;
+                       cp++;
+               }
+
+               cp = b3AlignPointer(cp, 4);
+
+               /*
+                               TLEN (4 bytes)
+                               <len> (short) the lengths of types
+                               <len>
+                       */
+
+               // Parse type lens
+               intPtr = (int*)cp;
+               b3Assert(strncmp(cp, "TLEN", 4) == 0);
+               intPtr++;
+
+               dataLen = (int)mTypes.size();
+
+               shtPtr = (short*)intPtr;
+               for (i = 0; i < dataLen; i++, shtPtr++)
+               {
+                       if (!littleEndian)
+                               shtPtr[0] = b3SwapEndian(shtPtr[0]);
+                       mTlens.push_back(shtPtr[0]);
+               }
+
+               if (dataLen & 1) shtPtr++;
+
+               /*
+                               STRC (4 bytes)
+                               <nr> amount of structs (int)
+                               <typenr>
+                               <nr_of_elems>
+                               <typenr>
+                               <namenr>
+                               <typenr>
+                               <namenr>
+                       */
+
+               intPtr = (int*)shtPtr;
+               cp = (char*)intPtr;
+               b3Assert(strncmp(cp, "STRC", 4) == 0);
+               intPtr++;
+
+               if (!littleEndian)
+                       *intPtr = b3SwapEndian(*intPtr);
+               dataLen = *intPtr;
+               intPtr++;
+
+               shtPtr = (short*)intPtr;
+               for (i = 0; i < dataLen; i++)
+               {
+                       mStructs.push_back(shtPtr);
+
+                       if (!littleEndian)
+                       {
+                               shtPtr[0] = b3SwapEndian(shtPtr[0]);
+                               shtPtr[1] = b3SwapEndian(shtPtr[1]);
+
+                               int len = shtPtr[1];
+                               shtPtr += 2;
+
+                               for (int a = 0; a < len; a++, shtPtr += 2)
+                               {
+                                       shtPtr[0] = b3SwapEndian(shtPtr[0]);
+                                       shtPtr[1] = b3SwapEndian(shtPtr[1]);
+                               }
+                       }
+                       else
+                       {
+                               shtPtr += (2 * shtPtr[1]) + 2;
+                       }
+               }
+
+               // build reverse lookups
+               for (i = 0; i < (int)mStructs.size(); i++)
+               {
+                       short* strc = mStructs.at(i);
+                       mStructReverse.insert(strc[0], i);
+                       mTypeLookup.insert(b3HashString(mTypes[strc[0]]), i);
+               }
+       }
+
+public:
+       b3DefaultSerializer(int totalSize = 0)
+               : m_totalSize(totalSize),
+                 m_currentSize(0),
+                 m_dna(0),
+                 m_dnaLength(0),
+                 m_serializationFlags(0)
+       {
+               m_buffer = m_totalSize ? (unsigned char*)b3AlignedAlloc(totalSize, 16) : 0;
+
+               const bool VOID_IS_8 = ((sizeof(void*) == 8));
+
+#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+               if (VOID_IS_8)
+               {
+#if _WIN64
+                       initDNA((const char*)b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+#else
+                       b3Assert(0);
+#endif
+               }
+               else
+               {
+#ifndef _WIN64
+                       initDNA((const char*)b3s_bulletDNAstr, b3s_bulletDNAlen);
+#else
+                       b3Assert(0);
+#endif
+               }
+
+#else   //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+               if (VOID_IS_8)
+               {
+                       initDNA((const char*)b3s_bulletDNAstr64, b3s_bulletDNAlen64);
+               }
+               else
+               {
+                       initDNA((const char*)b3s_bulletDNAstr, b3s_bulletDNAlen);
+               }
+#endif  //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+       }
+
+       virtual ~b3DefaultSerializer()
+       {
+               if (m_buffer)
+                       b3AlignedFree(m_buffer);
+               if (m_dna)
+                       b3AlignedFree(m_dna);
+       }
+
+       void writeHeader(unsigned char* buffer) const
+       {
+#ifdef B3_USE_DOUBLE_PRECISION
+               memcpy(buffer, "BULLETd", 7);
+#else
+               memcpy(buffer, "BULLETf", 7);
+#endif  //B3_USE_DOUBLE_PRECISION
+
+               int littleEndian = 1;
+               littleEndian = ((char*)&littleEndian)[0];
+
+               if (sizeof(void*) == 8)
+               {
+                       buffer[7] = '-';
+               }
+               else
+               {
+                       buffer[7] = '_';
+               }
+
+               if (littleEndian)
+               {
+                       buffer[8] = 'v';
+               }
+               else
+               {
+                       buffer[8] = 'V';
+               }
+
+               buffer[9] = '2';
+               buffer[10] = '8';
+               buffer[11] = '1';
+       }
+
+       virtual void startSerialization()
+       {
+               m_uniqueIdGenerator = 1;
+               if (m_totalSize)
+               {
+                       unsigned char* buffer = internalAlloc(B3_HEADER_LENGTH);
+                       writeHeader(buffer);
+               }
+       }
+
+       virtual void finishSerialization()
+       {
+               writeDNA();
+
+               //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
+               int mysize = 0;
+               if (!m_totalSize)
+               {
+                       if (m_buffer)
+                               b3AlignedFree(m_buffer);
+
+                       m_currentSize += B3_HEADER_LENGTH;
+                       m_buffer = (unsigned char*)b3AlignedAlloc(m_currentSize, 16);
+
+                       unsigned char* currentPtr = m_buffer;
+                       writeHeader(m_buffer);
+                       currentPtr += B3_HEADER_LENGTH;
+                       mysize += B3_HEADER_LENGTH;
+                       for (int i = 0; i < m_chunkPtrs.size(); i++)
+                       {
+                               int curLength = sizeof(b3Chunk) + m_chunkPtrs[i]->m_length;
+                               memcpy(currentPtr, m_chunkPtrs[i], curLength);
+                               b3AlignedFree(m_chunkPtrs[i]);
+                               currentPtr += curLength;
+                               mysize += curLength;
+                       }
+               }
+
+               mTypes.clear();
+               mStructs.clear();
+               mTlens.clear();
+               mStructReverse.clear();
+               mTypeLookup.clear();
+               m_chunkP.clear();
+               m_nameMap.clear();
+               m_uniquePointers.clear();
+               m_chunkPtrs.clear();
+       }
+
+       virtual void* getUniquePointer(void* oldPtr)
+       {
+               if (!oldPtr)
+                       return 0;
+
+               b3PointerUid* uptr = (b3PointerUid*)m_uniquePointers.find(oldPtr);
+               if (uptr)
+               {
+                       return uptr->m_ptr;
+               }
+               m_uniqueIdGenerator++;
+
+               b3PointerUid uid;
+               uid.m_uniqueIds[0] = m_uniqueIdGenerator;
+               uid.m_uniqueIds[1] = m_uniqueIdGenerator;
+               m_uniquePointers.insert(oldPtr, uid);
+               return uid.m_ptr;
+       }
+
+       virtual const unsigned char* getBufferPointer() const
+       {
+               return m_buffer;
+       }
+
+       virtual int getCurrentBufferSize() const
+       {
+               return m_currentSize;
+       }
+
+       virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode, void* oldPtr)
+       {
+               if (!(m_serializationFlags & B3_SERIALIZE_NO_DUPLICATE_ASSERT))
+               {
+                       b3Assert(!findPointer(oldPtr));
+               }
+
+               chunk->m_dna_nr = getReverseType(structType);
+
+               chunk->m_chunkCode = chunkCode;
+
+               void* uniquePtr = getUniquePointer(oldPtr);
+
+               m_chunkP.insert(oldPtr, uniquePtr);  //chunk->m_oldPtr);
+               chunk->m_oldPtr = uniquePtr;         //oldPtr;
+       }
+
+       virtual unsigned char* internalAlloc(size_t size)
+       {
+               unsigned char* ptr = 0;
+
+               if (m_totalSize)
+               {
+                       ptr = m_buffer + m_currentSize;
+                       m_currentSize += int(size);
+                       b3Assert(m_currentSize < m_totalSize);
+               }
+               else
+               {
+                       ptr = (unsigned char*)b3AlignedAlloc(size, 16);
+                       m_currentSize += int(size);
+               }
+               return ptr;
+       }
+
+       virtual b3Chunk* allocate(size_t size, int numElements)
+       {
+               unsigned char* ptr = internalAlloc(int(size) * numElements + sizeof(b3Chunk));
+
+               unsigned char* data = ptr + sizeof(b3Chunk);
+
+               b3Chunk* chunk = (b3Chunk*)ptr;
+               chunk->m_chunkCode = 0;
+               chunk->m_oldPtr = data;
+               chunk->m_length = int(size) * numElements;
+               chunk->m_number = numElements;
+
+               m_chunkPtrs.push_back(chunk);
+
+               return chunk;
+       }
+
+       virtual const char* findNameForPointer(const void* ptr) const
+       {
+               const char* const* namePtr = m_nameMap.find(ptr);
+               if (namePtr && *namePtr)
+                       return *namePtr;
+               return 0;
+       }
+
+       virtual void registerNameForPointer(const void* ptr, const char* name)
+       {
+               m_nameMap.insert(ptr, name);
+       }
+
+       virtual void serializeName(const char* name)
+       {
+               if (name)
+               {
+                       //don't serialize name twice
+                       if (findPointer((void*)name))
+                               return;
+
+                       int len = b3StrLen(name);
+                       if (len)
+                       {
+                               int newLen = len + 1;
+                               int padding = ((newLen + 3) & ~3) - newLen;
+                               newLen += padding;
+
+                               //serialize name string now
+                               b3Chunk* chunk = allocate(sizeof(char), newLen);
+                               char* destinationName = (char*)chunk->m_oldPtr;
+                               for (int i = 0; i < len; i++)
+                               {
+                                       destinationName[i] = name[i];
+                               }
+                               destinationName[len] = 0;
+                               finalizeChunk(chunk, "char", B3_ARRAY_CODE, (void*)name);
+                       }
+               }
+       }
+
+       virtual int getSerializationFlags() const
+       {
+               return m_serializationFlags;
+       }
+
+       virtual void setSerializationFlags(int flags)
+       {
+               m_serializationFlags = flags;
+       }
+};
+
+#endif  //B3_SERIALIZER_H
diff --git a/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/premake4.lua b/dali-physics/third-party/bullet3/src/Bullet3Serialize/Bullet2FileLoader/premake4.lua
new file mode 100644 (file)
index 0000000..b9ee301
--- /dev/null
@@ -0,0 +1,16 @@
+       project "Bullet2FileLoader"
+               
+       kind "StaticLib"
+       
+       includedirs {
+               "../../../src"
+       }
+       
+    if os.is("Linux") then
+        buildoptions{"-fPIC"}
+    end
+        
+       files {
+               "**.cpp",
+               "**.h"
+       }
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
new file mode 100644 (file)
index 0000000..29310ec
--- /dev/null
@@ -0,0 +1,33 @@
+
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+//
+// btAxisSweep3
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+#include "btAxisSweep3.h"
+
+btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
+       : btAxisSweep3Internal<unsigned short int>(worldAabbMin, worldAabbMax, 0xfffe, 0xffff, maxHandles, pairCache, disableRaycastAccelerator)
+{
+       // 1 handle is reserved as sentinel
+       btAssert(maxHandles > 1 && maxHandles < 32767);
+}
+
+bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
+       : btAxisSweep3Internal<unsigned int>(worldAabbMin, worldAabbMax, 0xfffffffe, 0x7fffffff, maxHandles, pairCache, disableRaycastAccelerator)
+{
+       // 1 handle is reserved as sentinel
+       btAssert(maxHandles > 1 && maxHandles < 2147483647);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
new file mode 100644 (file)
index 0000000..4f5f614
--- /dev/null
@@ -0,0 +1,48 @@
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+//
+// btAxisSweep3.h
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+
+#ifndef BT_AXIS_SWEEP_3_H
+#define BT_AXIS_SWEEP_3_H
+
+#include "LinearMath/btVector3.h"
+#include "btOverlappingPairCache.h"
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+#include "btDbvtBroadphase.h"
+#include "btAxisSweep3Internal.h"
+
+/// 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 btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+};
+
+/// 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 btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+};
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h
new file mode 100644 (file)
index 0000000..e481fdc
--- /dev/null
@@ -0,0 +1,954 @@
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+//
+// btAxisSweep3.h
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+
+#ifndef BT_AXIS_SWEEP_3_INTERNAL_H
+#define BT_AXIS_SWEEP_3_INTERNAL_H
+
+#include "LinearMath/btVector3.h"
+#include "btOverlappingPairCache.h"
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+#include "btDbvtBroadphase.h"
+
+//#define DEBUG_BROADPHASE 1
+#define USE_OVERLAP_TEST_ON_REMOVES 1
+
+/// 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:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       class Edge
+       {
+       public:
+               BP_FP_INT_TYPE m_pos;  // low bit is min/max
+               BP_FP_INT_TYPE m_handle;
+
+               BP_FP_INT_TYPE IsMax() const { return static_cast<BP_FP_INT_TYPE>(m_pos & 1); }
+       };
+
+public:
+       class Handle : public btBroadphaseProxy
+       {
+       public:
+               BT_DECLARE_ALIGNED_ALLOCATOR();
+
+               // indexes into the edge arrays
+               BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3];  // 6 * 2 = 12
+                                                                                                         //            BP_FP_INT_TYPE m_uniqueId;
+               btBroadphaseProxy* m_dbvtProxy;               //for faster raycast
+               //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
+
+               SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) { m_minEdges[0] = next; }
+               SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const { return m_minEdges[0]; }
+       };  // 24 bytes + 24 for Edge structures = 44 bytes total per entry
+
+protected:
+       btVector3 m_worldAabbMin;  // overall system bounds
+       btVector3 m_worldAabbMax;  // overall system bounds
+
+       btVector3 m_quantize;  // scaling factor for quantization
+
+       BP_FP_INT_TYPE m_numHandles;  // number of active handles
+       BP_FP_INT_TYPE m_maxHandles;  // max number of handles
+       Handle* m_pHandles;           // handles pool
+
+       BP_FP_INT_TYPE m_firstFreeHandle;  // free handles list
+
+       Edge* m_pEdges[3];  // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
+       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;
+
+       ///additional dynamic aabb structure, used to accelerate ray cast queries.
+       ///can be disabled using a optional argument in the constructor
+       btDbvtBroadphase* m_raycastAccelerator;
+       btOverlappingPairCache* m_nullPairCache;
+
+       // allocation/deallocation
+       BP_FP_INT_TYPE allocHandle();
+       void freeHandle(BP_FP_INT_TYPE handle);
+
+       bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1);
+
+#ifdef DEBUG_BROADPHASE
+       void debugPrintAxis(int axis, bool checkCardinality = true);
+#endif  //DEBUG_BROADPHASE
+
+       //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
+       //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
+
+       void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
+       void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
+       void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
+       void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
+
+public:
+       btAxisSweep3Internal(const btVector3& worldAabbMin, const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+
+       virtual ~btAxisSweep3Internal();
+
+       BP_FP_INT_TYPE getNumHandles() const
+       {
+               return m_numHandles;
+       }
+
+       virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+
+       BP_FP_INT_TYPE addHandle(const btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
+       void removeHandle(BP_FP_INT_TYPE handle, btDispatcher* dispatcher);
+       void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
+       SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const { return m_pHandles + index; }
+
+       virtual void resetPool(btDispatcher* dispatcher);
+
+       void processAllOverlappingPairs(btOverlapCallback* callback);
+
+       //Broadphase Interface
+       virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
+       virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
+       virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
+       virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
+       virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+       void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
+       ///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
+       void unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       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)
+               btAssert(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, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
+{
+       (void)shapeType;
+       BP_FP_INT_TYPE handleId = addHandle(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
+
+       Handle* handle = getHandle(handleId);
+
+       if (m_raycastAccelerator)
+       {
+               btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
+               handle->m_dbvtProxy = rayProxy;
+       }
+       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);
+       if (m_raycastAccelerator)
+               m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy, dispatcher);
+       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);
+       handle->m_aabbMin = aabbMin;
+       handle->m_aabbMax = aabbMax;
+       updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax, dispatcher);
+       if (m_raycastAccelerator)
+               m_raycastAccelerator->setAabb(handle->m_dbvtProxy, aabbMin, aabbMax, dispatcher);
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
+{
+       if (m_raycastAccelerator)
+       {
+               m_raycastAccelerator->rayTest(rayFrom, rayTo, rayCallback, aabbMin, aabbMax);
+       }
+       else
+       {
+               //choose axis?
+               BP_FP_INT_TYPE axis = 0;
+               //for each proxy
+               for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
+               {
+                       if (m_pEdges[axis][i].IsMax())
+                       {
+                               rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
+                       }
+               }
+       }
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+{
+       if (m_raycastAccelerator)
+       {
+               m_raycastAccelerator->aabbTest(aabbMin, aabbMax, callback);
+       }
+       else
+       {
+               //choose axis?
+               BP_FP_INT_TYPE axis = 0;
+               //for each proxy
+               for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
+               {
+                       if (m_pEdges[axis][i].IsMax())
+                       {
+                               Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
+                               if (TestAabbAgainstAabb2(aabbMin, aabbMax, handle->m_aabbMin, handle->m_aabbMax))
+                               {
+                                       callback.process(handle);
+                               }
+                       }
+               }
+       }
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       Handle* pHandle = static_cast<Handle*>(proxy);
+       aabbMin = pHandle->m_aabbMin;
+       aabbMax = pHandle->m_aabbMax;
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       Handle* pHandle = static_cast<Handle*>(proxy);
+
+       unsigned short vecInMin[3];
+       unsigned short vecInMax[3];
+
+       vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos;
+       vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos + 1;
+       vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos;
+       vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos + 1;
+       vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos;
+       vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos + 1;
+
+       aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()), (btScalar)(vecInMin[1]) / (m_quantize.getY()), (btScalar)(vecInMin[2]) / (m_quantize.getZ()));
+       aabbMin += m_worldAabbMin;
+
+       aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()), (btScalar)(vecInMax[1]) / (m_quantize.getY()), (btScalar)(vecInMax[2]) / (m_quantize.getZ()));
+       aabbMax += m_worldAabbMin;
+}
+
+template <typename BP_FP_INT_TYPE>
+btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btVector3& worldAabbMin, const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
+       : m_bpHandleMask(handleMask),
+         m_handleSentinel(handleSentinel),
+         m_pairCache(pairCache),
+         m_userPairCallback(0),
+         m_ownsPairCache(false),
+         m_invalidPair(0),
+         m_raycastAccelerator(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;
+       }
+
+       if (!disableRaycastAccelerator)
+       {
+               m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache), 16)) btNullPairCache();
+               m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase), 16)) btDbvtBroadphase(m_nullPairCache);  //m_pairCache);
+               m_raycastAccelerator->m_deferedcollide = true;                                                                //don't add/remove pairs
+       }
+
+       //btAssert(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, using btAlignedAlloc, 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(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()
+{
+       if (m_raycastAccelerator)
+       {
+               m_nullPairCache->~btOverlappingPairCache();
+               btAlignedFree(m_nullPairCache);
+               m_raycastAccelerator->~btDbvtBroadphase();
+               btAlignedFree(m_raycastAccelerator);
+       }
+
+       for (int i = 2; i >= 0; i--)
+       {
+               btAlignedFree(m_pEdgesRawPtr[i]);
+       }
+       delete[] m_pHandles;
+
+       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 btVector3& point, int isMax) const
+{
+#ifdef OLD_CLAMPING_METHOD
+       ///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax]
+       ///see http://code.google.com/p/bullet/issues/detail?id=87
+       btVector3 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);
+#else
+       btVector3 v = (point - m_worldAabbMin) * m_quantize;
+       out[0] = (v[0] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[0] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0] & m_bpHandleMask) | isMax);
+       out[1] = (v[1] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[1] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1] & m_bpHandleMask) | isMax);
+       out[2] = (v[2] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[2] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2] & m_bpHandleMask) | isMax);
+#endif  //OLD_CLAMPING_METHOD
+}
+
+template <typename BP_FP_INT_TYPE>
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
+{
+       btAssert(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)
+{
+       btAssert(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 btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
+{
+       // quantize the bounds
+       BP_FP_INT_TYPE min[3], max[3];
+       quantize(min, aabbMin, 0);
+       quantize(max, aabbMax, 1);
+
+       // allocate a handle
+       BP_FP_INT_TYPE handle = allocHandle();
+
+       Handle* pHandle = getHandle(handle);
+
+       pHandle->m_uniqueId = static_cast<int>(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 = 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);
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* /*dispatcher*/)
+{
+       if (m_numHandles == 0)
+       {
+               m_firstFreeHandle = 1;
+               {
+                       for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++)
+                               m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
+                       m_pHandles[m_maxHandles - 1].SetNextFree(0);
+               }
+       }
+}
+
+//#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)
+                       {
+                               ///important to use an AABB test that is consistent with the broadphase
+                               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++;
+                       }
+               }
+
+///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>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1)
+{
+       //optimization 1: check the array index (memory address), instead of the m_pos
+
+       if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
+               pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
+               pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
+               pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
+       {
+               return false;
+       }
+       return true;
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher)
+{
+       //      btAssert(bounds.IsFinite());
+       //btAssert(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
+                       const int axis1 = (1 << axis) & 3;
+                       const int axis2 = (1 << axis1) & 3;
+                       if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev, axis1, axis2))
+                       {
+                               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())
+               {
+                       Handle* handle0 = getHandle(pEdge->m_handle);
+                       Handle* handle1 = getHandle(pNext->m_handle);
+                       const int axis1 = (1 << axis) & 3;
+                       const int axis2 = (1 << axis1) & 3;
+
+                       // if next edge is maximum remove any overlap between the two handles
+                       if (updateOverlaps
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+                               && testOverlap2D(handle0, handle1, axis1, axis2)
+#endif  //USE_OVERLAP_TEST_ON_REMOVES
+                       )
+                       {
+                               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
+                       Handle* handle0 = getHandle(pEdge->m_handle);
+                       Handle* handle1 = getHandle(pPrev->m_handle);
+                       const int axis1 = (1 << axis) & 3;
+                       const int axis2 = (1 << axis1) & 3;
+
+                       if (updateOverlaps
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+                               && testOverlap2D(handle0, handle1, axis1, axis2)
+#endif  //USE_OVERLAP_TEST_ON_REMOVES
+                       )
+                       {
+                               //this is done during the overlappingpairarray iteration/narrowphase collision
+
+                               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);
+
+               const int axis1 = (1 << axis) & 3;
+               const int axis2 = (1 << axis1) & 3;
+
+               if (!pNext->IsMax())
+               {
+                       // if next edge is a minimum check the bounds and add an overlap if necessary
+                       if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext, axis1, axis2))
+                       {
+                               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++;
+       }
+}
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
new file mode 100644 (file)
index 0000000..4176256
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_BROADPHASE_INTERFACE_H
+#define BT_BROADPHASE_INTERFACE_H
+
+struct btDispatcherInfo;
+class btDispatcher;
+#include "btBroadphaseProxy.h"
+
+class btOverlappingPairCache;
+
+struct btBroadphaseAabbCallback
+{
+       virtual ~btBroadphaseAabbCallback() {}
+       virtual bool process(const btBroadphaseProxy* proxy) = 0;
+};
+
+struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
+{
+       ///added some cached data to accelerate ray-AABB tests
+       btVector3 m_rayDirectionInverse;
+       unsigned int m_signs[3];
+       btScalar m_lambda_max;
+
+       virtual ~btBroadphaseRayCallback() {}
+
+protected:
+       btBroadphaseRayCallback() {}
+};
+
+#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& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher) = 0;
+       virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
+       virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher) = 0;
+       virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const = 0;
+
+       virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0)) = 0;
+
+       virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 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;
+
+       ///reset broadphase internal structures, to ensure determinism/reproducability
+       virtual void resetPool(btDispatcher* dispatcher) { (void)dispatcher; };
+
+       virtual void printStats() = 0;
+};
+
+#endif  //BT_BROADPHASE_INTERFACE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
new file mode 100644 (file)
index 0000000..317c3f6
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBroadphaseProxy.h"
+
+BT_NOT_EMPTY_FILE  // fix warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
new file mode 100644 (file)
index 0000000..fb23281
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_BROADPHASE_PROXY_H
+#define BT_BROADPHASE_PROXY_H
+
+#include "LinearMath/btScalar.h"  //for SIMD_FORCE_INLINE
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+/// btDispatcher uses these types
+/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
+/// to facilitate type checking
+/// CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE and CUSTOM_CONCAVE_SHAPE_TYPE can be used to extend Bullet without modifying source code
+enum BroadphaseNativeTypes
+{
+       // polyhedral convex shapes
+       BOX_SHAPE_PROXYTYPE,
+       TRIANGLE_SHAPE_PROXYTYPE,
+       TETRAHEDRAL_SHAPE_PROXYTYPE,
+       CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE,
+       CONVEX_HULL_SHAPE_PROXYTYPE,
+       CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
+       CUSTOM_POLYHEDRAL_SHAPE_TYPE,
+       //implicit convex shapes
+       IMPLICIT_CONVEX_SHAPES_START_HERE,
+       SPHERE_SHAPE_PROXYTYPE,
+       MULTI_SPHERE_SHAPE_PROXYTYPE,
+       CAPSULE_SHAPE_PROXYTYPE,
+       CONE_SHAPE_PROXYTYPE,
+       CONVEX_SHAPE_PROXYTYPE,
+       CYLINDER_SHAPE_PROXYTYPE,
+       UNIFORM_SCALING_SHAPE_PROXYTYPE,
+       MINKOWSKI_SUM_SHAPE_PROXYTYPE,
+       MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
+       BOX_2D_SHAPE_PROXYTYPE,
+       CONVEX_2D_SHAPE_PROXYTYPE,
+       CUSTOM_CONVEX_SHAPE_TYPE,
+       //concave shapes
+       CONCAVE_SHAPES_START_HERE,
+       //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
+       TRIANGLE_MESH_SHAPE_PROXYTYPE,
+       SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
+       ///used for demo integration FAST/Swift collision library and Bullet
+       FAST_CONCAVE_MESH_PROXYTYPE,
+       //terrain
+       TERRAIN_SHAPE_PROXYTYPE,
+       ///Used for GIMPACT Trimesh integration
+       GIMPACT_SHAPE_PROXYTYPE,
+       ///Multimaterial mesh
+       MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
+
+       EMPTY_SHAPE_PROXYTYPE,
+       STATIC_PLANE_PROXYTYPE,
+       CUSTOM_CONCAVE_SHAPE_TYPE,
+       SDF_SHAPE_PROXYTYPE = CUSTOM_CONCAVE_SHAPE_TYPE,
+       CONCAVE_SHAPES_END_HERE,
+
+       COMPOUND_SHAPE_PROXYTYPE,
+
+       SOFTBODY_SHAPE_PROXYTYPE,
+       HFFLUID_SHAPE_PROXYTYPE,
+       HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE,
+       INVALID_SHAPE_PROXYTYPE,
+
+       MAX_BROADPHASE_COLLISION_TYPES
+
+};
+
+///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
+       {
+               DefaultFilter = 1,
+               StaticFilter = 2,
+               KinematicFilter = 4,
+               DebrisFilter = 8,
+               SensorTrigger = 16,
+               CharacterFilter = 32,
+               AllFilter = -1  //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+       };
+
+       //Usually the client btCollisionObject or Rigidbody class
+       void* m_clientObject;
+       int m_collisionFilterGroup;
+       int m_collisionFilterMask;
+
+       int m_uniqueId;  //m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+
+       btVector3 m_aabbMin;
+       btVector3 m_aabbMax;
+
+       SIMD_FORCE_INLINE int getUid() const
+       {
+               return m_uniqueId;
+       }
+
+       //used for memory pools
+       btBroadphaseProxy() : m_clientObject(0)
+       {
+       }
+
+       btBroadphaseProxy(const btVector3& aabbMin, const btVector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
+               : m_clientObject(userPtr),
+                 m_collisionFilterGroup(collisionFilterGroup),
+                 m_collisionFilterMask(collisionFilterMask),
+                 m_aabbMin(aabbMin),
+                 m_aabbMax(aabbMax)
+       {
+       }
+
+       static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
+       {
+               return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
+       }
+
+       static SIMD_FORCE_INLINE bool isConvex(int proxyType)
+       {
+               return (proxyType < CONCAVE_SHAPES_START_HERE);
+       }
+
+       static SIMD_FORCE_INLINE bool isNonMoving(int proxyType)
+       {
+               return (isConcave(proxyType) && !(proxyType == GIMPACT_SHAPE_PROXYTYPE));
+       }
+
+       static SIMD_FORCE_INLINE bool isConcave(int proxyType)
+       {
+               return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
+                               (proxyType < CONCAVE_SHAPES_END_HERE));
+       }
+       static SIMD_FORCE_INLINE bool isCompound(int proxyType)
+       {
+               return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
+       }
+
+       static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
+       {
+               return (proxyType == SOFTBODY_SHAPE_PROXYTYPE);
+       }
+
+       static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
+       {
+               return (proxyType == STATIC_PLANE_PROXYTYPE);
+       }
+
+       static SIMD_FORCE_INLINE bool isConvex2d(int proxyType)
+       {
+               return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
+       }
+};
+
+class btCollisionAlgorithm;
+
+struct btBroadphaseProxy;
+
+///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()
+               : m_pProxy0(0),
+                 m_pProxy1(0),
+                 m_algorithm(0),
+                 m_internalInfo1(0)
+       {
+       }
+
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btBroadphasePair(btBroadphaseProxy & proxy0, btBroadphaseProxy & proxy1)
+       {
+               //keep them sorted, so the std::set operations work
+               if (proxy0.m_uniqueId < proxy1.m_uniqueId)
+               {
+                       m_pProxy0 = &proxy0;
+                       m_pProxy1 = &proxy1;
+               }
+               else
+               {
+                       m_pProxy0 = &proxy1;
+                       m_pProxy1 = &proxy0;
+               }
+
+               m_algorithm = 0;
+               m_internalInfo1 = 0;
+       }
+
+       btBroadphaseProxy* m_pProxy0;
+       btBroadphaseProxy* m_pProxy1;
+
+       mutable btCollisionAlgorithm* m_algorithm;
+       union {
+               void* m_internalInfo1;
+               int m_internalTmpValue;
+       };  //don't use this data, it will be removed in future version.
+};
+
+/*
+//comparison for set operation, see Solid DT_Encounter
+SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b) 
+{ 
+    return a.m_pProxy0 < b.m_pProxy0 || 
+        (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1); 
+}
+*/
+
+class btBroadphasePairSortPredicate
+{
+public:
+       bool operator()(const btBroadphasePair& a, const btBroadphasePair& b) const
+       {
+               const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
+               const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
+               const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
+               const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
+
+               return uidA0 > uidB0 ||
+                          (a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
+                          (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
+       }
+};
+
+SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
+{
+       return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
+}
+
+#endif  //BT_BROADPHASE_PROXY_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..9cb6225
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionAlgorithm.h"
+#include "btDispatcher.h"
+
+btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+{
+       m_dispatcher = ci.m_dispatcher1;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..25a347e
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_ALGORITHM_H
+#define BT_COLLISION_ALGORITHM_H
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct btBroadphaseProxy;
+class btDispatcher;
+class btManifoldResult;
+class btCollisionObject;
+struct btCollisionObjectWrapper;
+struct btDispatcherInfo;
+class btPersistentManifold;
+
+typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
+
+struct btCollisionAlgorithmConstructionInfo
+{
+       btCollisionAlgorithmConstructionInfo()
+               : m_dispatcher1(0),
+                 m_manifold(0)
+       {
+       }
+       btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher, int temp)
+               : m_dispatcher1(dispatcher)
+       {
+               (void)temp;
+       }
+
+       btDispatcher* m_dispatcher1;
+       btPersistentManifold* m_manifold;
+
+       //      int     getDispatcherId();
+};
+
+///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher.
+///It is persistent over frames
+class btCollisionAlgorithm
+{
+protected:
+       btDispatcher* m_dispatcher;
+
+protected:
+       //      int     getDispatcherId();
+
+public:
+       btCollisionAlgorithm(){};
+
+       btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
+
+       virtual ~btCollisionAlgorithm(){};
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut) = 0;
+
+       virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut) = 0;
+
+       virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
+};
+
+#endif  //BT_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvt.cpp
new file mode 100644 (file)
index 0000000..ae087c8
--- /dev/null
@@ -0,0 +1,1357 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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)
+{
+#ifdef BT_USE_SSE
+       ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]);
+       btDbvtVolume* ptr = (btDbvtVolume*)locals;
+       btDbvtVolume& res = *ptr;
+#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[1], 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 == 0) return;
+       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 bool leftOfAxis(const btDbvtNode* node,
+                                          const btVector3& org,
+                                          const btVector3& axis)
+{
+       return btDot(axis, node->volume.Center() - org) <= 0;
+}
+
+// Partitions leaves such that leaves[0, n) are on the
+// left of axis, and leaves[n, count) are on the right
+// of axis. returns N.
+static int split(btDbvtNode** leaves,
+                                int count,
+                                const btVector3& org,
+                                const btVector3& axis)
+{
+       int begin = 0;
+       int end = count;
+       for (;;)
+       {
+               while (begin != end && leftOfAxis(leaves[begin], org, axis))
+               {
+                       ++begin;
+               }
+
+               if (begin == end)
+               {
+                       break;
+               }
+
+               while (begin != end && !leftOfAxis(leaves[end - 1], org, axis))
+               {
+                       --end;
+               }
+
+               if (begin == end)
+               {
+                       break;
+               }
+
+               // swap out of place nodes
+               --end;
+               btDbvtNode* temp = leaves[begin];
+               leaves[begin] = leaves[end];
+               leaves[end] = temp;
+               ++begin;
+       }
+
+       return begin;
+}
+
+//
+static btDbvtVolume bounds(btDbvtNode** leaves,
+                                                  int count)
+{
+#ifdef BT_USE_SSE
+       ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
+       btDbvtVolume* ptr = (btDbvtVolume*)locals;
+       btDbvtVolume& volume = *ptr;
+       volume = leaves[0]->volume;
+#else
+       btDbvtVolume volume = leaves[0]->volume;
+#endif
+       for (int i = 1, ni = count; i < ni; ++i)
+       {
+               Merge(volume, leaves[i]->volume, volume);
+       }
+       return (volume);
+}
+
+//
+static void bottomup(btDbvt* pdbvt,
+                                        btDbvtNode** leaves,
+                                        int count)
+{
+       while (count > 1)
+       {
+               btScalar minsize = SIMD_INFINITY;
+               int minidx[2] = {-1, -1};
+               for (int i = 0; i < count; ++i)
+               {
+                       for (int j = i + 1; j < count; ++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[minidx[1]] = leaves[count - 1];
+               --count;
+       }
+}
+
+//
+static btDbvtNode* topdown(btDbvt* pdbvt,
+                                                  btDbvtNode** leaves,
+                                                  int count,
+                                                  int bu_treshold)
+{
+       static const btVector3 axis[] = {btVector3(1, 0, 0),
+                                                                        btVector3(0, 1, 0),
+                                                                        btVector3(0, 0, 1)};
+       btAssert(bu_treshold > 2);
+       if (count > 1)
+       {
+               if (count > bu_treshold)
+               {
+                       const btDbvtVolume vol = bounds(leaves, count);
+                       const btVector3 org = vol.Center();
+                       int partition;
+                       int bestaxis = -1;
+                       int bestmidp = count;
+                       int splitcount[3][2] = {{0, 0}, {0, 0}, {0, 0}};
+                       int i;
+                       for (i = 0; i < count; ++i)
+                       {
+                               const btVector3 x = leaves[i]->volume.Center() - org;
+                               for (int j = 0; j < 3; ++j)
+                               {
+                                       ++splitcount[j][btDot(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)
+                       {
+                               partition = split(leaves, count, org, axis[bestaxis]);
+                               btAssert(partition != 0 && partition != count);
+                       }
+                       else
+                       {
+                               partition = count / 2 + 1;
+                       }
+                       btDbvtNode* node = createnode(pdbvt, 0, vol, 0);
+                       node->childs[0] = topdown(pdbvt, &leaves[0], partition, bu_treshold);
+                       node->childs[1] = topdown(pdbvt, &leaves[partition], count - partition, bu_treshold);
+                       node->childs[0]->parent = node;
+                       node->childs[1]->parent = node;
+                       return (node);
+               }
+               else
+               {
+                       bottomup(pdbvt, leaves, count);
+                       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);
+}
+
+#if 0
+static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
+{
+       while(n&&(count--)) n=n->parent;
+       return(n);
+}
+#endif
+
+//
+// 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;
+       m_lkhd = -1;
+       m_stkStack.clear();
+       m_opath = 0;
+}
+
+//
+void btDbvt::optimizeBottomUp()
+{
+       if (m_root)
+       {
+               tNodeArray leaves;
+               leaves.reserve(m_leaves);
+               fetchleaves(this, m_root, leaves);
+               bottomup(this, &leaves[0], leaves.size());
+               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[0], leaves.size(), 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, 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: 3499 ms (-1%)
+[2] btDbvtVolume merges: 1934 ms (0%)
+[3] btDbvt::collideTT: 5485 ms (-21%)
+[4] btDbvt::collideTT self: 2814 ms (-20%)
+[5] btDbvt::collideTT xform: 7379 ms (-1%)
+[6] btDbvt::collideTT xform,self: 7270 ms (-2%)
+[7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
+[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
+[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
+[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
+[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
+[12] btDbvtVolume notequal: 3659 ms (0%)
+[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
+[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
+[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
+[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
+[17] btDbvtVolume select: 3419 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 = 3499;
+       //[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 = 5485;
+       //[4] btDbvt::collideTT self
+       bool cfgBenchmark4_Enable = cfgEnable;
+       static const int cfgBenchmark4_Iterations = 512;
+       static const int cfgBenchmark4_Reference = 2814;
+       //[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 = 7379;
+       //[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 = 7270;
+       //[7] btDbvt::rayTest
+       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 = 1879;
+       //[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 = 1244;
+       //[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] select
+       bool cfgBenchmark17_Enable = cfgEnable;
+       static const int cfgBenchmark17_Iterations = 4;
+       static const int cfgBenchmark17_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::rayTest: ");
+               wallclock.reset();
+               for (int i = 0; i < cfgBenchmark7_Passes; ++i)
+               {
+                       for (int j = 0; j < cfgBenchmark7_Iterations; ++j)
+                       {
+                               btDbvt::rayTest(dbvt.m_root, rayorg[j], 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<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("[17] btDbvtVolume select: ");
+               wallclock.reset();
+               for (int i = 0; i < cfgBenchmark17_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 - cfgBenchmark17_Reference) * 100 / time);
+       }
+       printf("\r\n\r\n");
+}
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvt.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvt.h
new file mode 100644 (file)
index 0000000..430f577
--- /dev/null
@@ -0,0 +1,1578 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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"
+#include "LinearMath/btAabbUtil2.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
+#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
+
+// Use only intrinsics instead of inline asm
+#define DBVT_USE_INTRINSIC_SSE 1
+
+// Using memmov for collideOCL
+#define DBVT_USE_MEMMOVE 1
+
+// Enable benchmarking code
+#define DBVT_ENABLE_BENCHMARK 0
+
+// Inlining
+#define DBVT_INLINE SIMD_FORCE_INLINE
+
+// Specific methods implementation
+
+//SSE gives errors on a MSVC 7.1
+#if defined(BT_USE_SSE)  //&& defined (_WIN32)
+#define DBVT_SELECT_IMPL DBVT_IMPL_SSE
+#define DBVT_MERGE_IMPL DBVT_IMPL_SSE
+#define DBVT_INT0_IMPL DBVT_IMPL_SSE
+#else
+#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC
+#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC
+#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC
+#endif
+
+#if (DBVT_SELECT_IMPL == DBVT_IMPL_SSE) || \
+       (DBVT_MERGE_IMPL == DBVT_IMPL_SSE) ||  \
+       (DBVT_INT0_IMPL == DBVT_IMPL_SSE)
+#include <emmintrin.h>
+#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*)1; \
+       (void)typechecker;
+#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
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
+#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_SELECT_IMPL
+#error "DBVT_SELECT_IMPL undefined"
+#endif
+
+#ifndef DBVT_MERGE_IMPL
+#error "DBVT_MERGE_IMPL undefined"
+#endif
+
+#ifndef DBVT_INT0_IMPL
+#error "DBVT_INT0_IMPL undefined"
+#endif
+
+//
+// Defaults volumes
+//
+
+/* btDbvtAabbMm                        */
+struct btDbvtAabbMm
+{
+    DBVT_INLINE 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 btVector3& b);
+
+       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);
+
+       DBVT_INLINE btVector3& tMins() { return (mi); }
+       DBVT_INLINE btVector3& tMaxs() { return (mx); }
+
+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;
+       DBVT_INLINE bool isleaf() const { return (childs[1] == 0); }
+       DBVT_INLINE bool isinternal() const { return (!isleaf()); }
+       union {
+               btDbvtNode* childs[2];
+               void* data;
+               int dataAsInt;
+       };
+};
+
+/* btDbv(normal)tNode                */
+struct btDbvntNode
+{
+    btDbvtVolume volume;
+    btVector3 normal;
+    btScalar angle;
+    DBVT_INLINE bool isleaf() const { return (childs[1] == 0); }
+    DBVT_INLINE bool isinternal() const { return (!isleaf()); }
+    btDbvntNode* childs[2];
+    void* data;
+
+    btDbvntNode(const btDbvtNode* n)
+    : volume(n->volume)
+    , normal(0,0,0)
+    , angle(0)
+    , data(n->data)
+    {
+        childs[0] = 0;
+        childs[1] = 0;
+    }
+    
+    ~btDbvntNode()
+    {
+        if (childs[0])
+            delete childs[0];
+        if (childs[1])
+            delete childs[1];
+    }
+};
+
+typedef btAlignedObjectArray<const btDbvtNode*> btNodeStack;
+
+///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) {}
+       };
+    
+    struct sStknNN
+    {
+        const btDbvntNode* a;
+        const btDbvntNode* b;
+        sStknNN() {}
+        sStknNN(const btDbvntNode* na, const btDbvntNode* nb) : a(na), b(nb) {}
+    };
+       // 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 void Process(const btDbvntNode*, const btDbvntNode*) {}
+               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;
+
+       btAlignedObjectArray<sStkNN> m_stkStack;
+
+       // 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, 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
+       void collideTT(const btDbvtNode* root0,
+                                  const btDbvtNode* root1,
+                                  DBVT_IPOLICY);
+    DBVT_PREFIX
+    void selfCollideT(const btDbvntNode* root,
+                   DBVT_IPOLICY);
+    DBVT_PREFIX
+    void selfCollideTT(const btDbvtNode* root,
+                      DBVT_IPOLICY);
+
+       DBVT_PREFIX
+       void collideTTpersistentStack(const btDbvtNode* root0,
+                                                                 const btDbvtNode* root1,
+                                                                 DBVT_IPOLICY);
+#if 0
+       DBVT_PREFIX
+               void            collideTT(      const btDbvtNode* root0,
+               const btDbvtNode* root1,
+               const btTransform& xform,
+               DBVT_IPOLICY);
+       DBVT_PREFIX
+               void            collideTT(      const btDbvtNode* root0,
+               const btTransform& xform0,
+               const btDbvtNode* root1,
+               const btTransform& xform1,
+               DBVT_IPOLICY);
+#endif
+
+       DBVT_PREFIX
+       void collideTV(const btDbvtNode* root,
+                                  const btDbvtVolume& volume,
+                                  DBVT_IPOLICY) const;
+
+       DBVT_PREFIX
+       void collideTVNoStackAlloc(const btDbvtNode* root,
+                                                          const btDbvtVolume& volume,
+                                                          btNodeStack& stack,
+                                                          DBVT_IPOLICY) const;
+
+       ///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc)
+       ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
+       DBVT_PREFIX
+       static void rayTest(const btDbvtNode* root,
+                                               const btVector3& rayFrom,
+                                               const btVector3& rayTo,
+                                               DBVT_IPOLICY);
+       ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
+       ///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts
+       DBVT_PREFIX
+       void rayTestInternal(const btDbvtNode* root,
+                                                const btVector3& rayFrom,
+                                                const btVector3& rayTo,
+                                                const btVector3& rayDirectionInverse,
+                                                unsigned int signs[3],
+                                                btScalar lambda_max,
+                                                const btVector3& aabbMin,
+                                                const btVector3& aabbMax,
+                                                btAlignedObjectArray<const btDbvtNode*>& stack,
+                                                DBVT_IPOLICY) const;
+
+       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[0]);
+       else
+               mi.setX(mi.x() + e[0]);
+       if (e.y() > 0)
+               mx.setY(mx.y() + e[1]);
+       else
+               mi.setY(mi.y() + e[1]);
+       if (e.z() > 0)
+               mx.setZ(mx.z() + e[2]);
+       else
+               mi.setZ(mi.z() + e[2]);
+}
+
+//
+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 ((btDot(n, px) + o) < 0) return (-1);
+       if ((btDot(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 (btDot(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)
+{
+#if DBVT_INT0_IMPL == DBVT_IMPL_SSE
+       const __m128 rt(_mm_or_ps(_mm_cmplt_ps(_mm_load_ps(b.mx), _mm_load_ps(a.mi)),
+                                                         _mm_cmplt_ps(_mm_load_ps(a.mx), _mm_load_ps(b.mi))));
+#if defined(_WIN32)
+       const __int32* pu((const __int32*)&rt);
+#else
+       const int* pu((const int*)&rt);
+#endif
+       return ((pu[0] | pu[1] | pu[2]) == 0);
+#else
+       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()));
+#endif
+}
+
+//
+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 btScalar Proximity(const btDbvtAabbMm& a,
+                                                          const btDbvtAabbMm& b)
+{
+       const btVector3 d = (a.mi + a.mx) - (b.mi + b.mx);
+       return (btFabs(d.x()) + btFabs(d.y()) + btFabs(d.z()));
+}
+
+//
+DBVT_INLINE int Select(const btDbvtAabbMm& o,
+                                          const btDbvtAabbMm& a,
+                                          const btDbvtAabbMm& b)
+{
+#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE
+
+#if defined(_WIN32)
+       static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
+#else
+       static ATTRIBUTE_ALIGNED16(const unsigned int) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x00000000 /*0x7fffffff*/};
+#endif
+       ///@todo: the intrinsic version is 11% slower
+#if DBVT_USE_INTRINSIC_SSE
+
+       union btSSEUnion  ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory
+       {
+               __m128 ssereg;
+               float floats[4];
+               int ints[4];
+       };
+
+       __m128 omi(_mm_load_ps(o.mi));
+       omi = _mm_add_ps(omi, _mm_load_ps(o.mx));
+       __m128 ami(_mm_load_ps(a.mi));
+       ami = _mm_add_ps(ami, _mm_load_ps(a.mx));
+       ami = _mm_sub_ps(ami, omi);
+       ami = _mm_and_ps(ami, _mm_load_ps((const float*)mask));
+       __m128 bmi(_mm_load_ps(b.mi));
+       bmi = _mm_add_ps(bmi, _mm_load_ps(b.mx));
+       bmi = _mm_sub_ps(bmi, omi);
+       bmi = _mm_and_ps(bmi, _mm_load_ps((const float*)mask));
+       __m128 t0(_mm_movehl_ps(ami, ami));
+       ami = _mm_add_ps(ami, t0);
+       ami = _mm_add_ss(ami, _mm_shuffle_ps(ami, ami, 1));
+       __m128 t1(_mm_movehl_ps(bmi, bmi));
+       bmi = _mm_add_ps(bmi, t1);
+       bmi = _mm_add_ss(bmi, _mm_shuffle_ps(bmi, bmi, 1));
+
+       btSSEUnion tmp;
+       tmp.ssereg = _mm_cmple_ss(bmi, ami);
+       return tmp.ints[0] & 1;
+
+#else
+       ATTRIBUTE_ALIGNED16(__int32 r[1]);
+       __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);
+#endif
+#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
+       __m128 ami(_mm_load_ps(a.mi));
+       __m128 amx(_mm_load_ps(a.mx));
+       __m128 bmi(_mm_load_ps(b.mi));
+       __m128 bmx(_mm_load_ps(b.mx));
+       ami = _mm_min_ps(ami, bmi);
+       amx = _mm_max_ps(amx, bmx);
+       _mm_store_ps(r.mi, ami);
+       _mm_store_ps(r.mx, amx);
+#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)
+       {
+               int depth = 1;
+               int treshold = DOUBLE_STACKSIZE - 4;
+               btAlignedObjectArray<sStkNN> stkStack;
+               stkStack.resize(DOUBLE_STACKSIZE);
+               stkStack[0] = sStkNN(root0, root1);
+               do
+               {
+                       sStkNN p = stkStack[--depth];
+                       if (depth > treshold)
+                       {
+                               stkStack.resize(stkStack.size() * 2);
+                               treshold = stkStack.size() - 4;
+                       }
+                       if (p.a == p.b)
+                       {
+                               if (p.a->isinternal())
+                               {
+                                       stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+                                       stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+                                       stkStack[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())
+                                       {
+                                               stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+                                               stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+                                               stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+                                               stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                               stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+                                               stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
+                                       }
+                               }
+                               else
+                               {
+                                       if (p.b->isinternal())
+                                       {
+                                               stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+                                               stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                               policy.Process(p.a, p.b);
+                                       }
+                               }
+                       }
+               } while (depth);
+       }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::selfCollideT(const btDbvntNode* root,
+                              DBVT_IPOLICY)
+{
+    DBVT_CHECKTYPE
+    if (root)
+    {
+        int depth = 1;
+        int treshold = DOUBLE_STACKSIZE - 4;
+        btAlignedObjectArray<sStknNN> stkStack;
+        stkStack.resize(DOUBLE_STACKSIZE);
+        stkStack[0] = sStknNN(root, root);
+        do
+        {
+            sStknNN p = stkStack[--depth];
+            if (depth > treshold)
+            {
+                stkStack.resize(stkStack.size() * 2);
+                treshold = stkStack.size() - 4;
+            }
+            if (p.a == p.b)
+            {
+                if (p.a->isinternal() && p.a->angle > SIMD_PI)
+                {
+                    stkStack[depth++] = sStknNN(p.a->childs[0], p.a->childs[0]);
+                    stkStack[depth++] = sStknNN(p.a->childs[1], p.a->childs[1]);
+                    stkStack[depth++] = sStknNN(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())
+                    {
+                        stkStack[depth++] = sStknNN(p.a->childs[0], p.b->childs[0]);
+                        stkStack[depth++] = sStknNN(p.a->childs[1], p.b->childs[0]);
+                        stkStack[depth++] = sStknNN(p.a->childs[0], p.b->childs[1]);
+                        stkStack[depth++] = sStknNN(p.a->childs[1], p.b->childs[1]);
+                    }
+                    else
+                    {
+                        stkStack[depth++] = sStknNN(p.a->childs[0], p.b);
+                        stkStack[depth++] = sStknNN(p.a->childs[1], p.b);
+                    }
+                }
+                else
+                {
+                    if (p.b->isinternal())
+                    {
+                        stkStack[depth++] = sStknNN(p.a, p.b->childs[0]);
+                        stkStack[depth++] = sStknNN(p.a, p.b->childs[1]);
+                    }
+                    else
+                    {
+                        policy.Process(p.a, p.b);
+                    }
+                }
+            }
+        } while (depth);
+    }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::selfCollideTT(const btDbvtNode* root,
+                                 DBVT_IPOLICY)
+{
+    DBVT_CHECKTYPE
+    if (root)
+    {
+        int depth = 1;
+        int treshold = DOUBLE_STACKSIZE - 4;
+        btAlignedObjectArray<sStkNN> stkStack;
+        stkStack.resize(DOUBLE_STACKSIZE);
+        stkStack[0] = sStkNN(root, root);
+        do
+        {
+            sStkNN p = stkStack[--depth];
+            if (depth > treshold)
+            {
+                stkStack.resize(stkStack.size() * 2);
+                treshold = stkStack.size() - 4;
+            }
+            if (p.a == p.b)
+            {
+                if (p.a->isinternal())
+                {
+                    stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+                    stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+                    stkStack[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())
+                    {
+                        stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+                        stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+                        stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+                        stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+                    }
+                    else
+                    {
+                        stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+                        stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
+                    }
+                }
+                else
+                {
+                    if (p.b->isinternal())
+                    {
+                        stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+                        stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
+                    }
+                    else
+                    {
+                        policy.Process(p.a, p.b);
+                    }
+                }
+            }
+        } while (depth);
+    }
+}
+
+
+DBVT_PREFIX
+inline void btDbvt::collideTTpersistentStack(const btDbvtNode* root0,
+                                                                                        const btDbvtNode* root1,
+                                                                                        DBVT_IPOLICY)
+{
+       DBVT_CHECKTYPE
+       if (root0 && root1)
+       {
+               int depth = 1;
+               int treshold = DOUBLE_STACKSIZE - 4;
+
+               m_stkStack.resize(DOUBLE_STACKSIZE);
+               m_stkStack[0] = sStkNN(root0, root1);
+               do
+               {
+                       sStkNN p = m_stkStack[--depth];
+                       if (depth > treshold)
+                       {
+                               m_stkStack.resize(m_stkStack.size() * 2);
+                               treshold = m_stkStack.size() - 4;
+                       }
+                       if (p.a == p.b)
+                       {
+                               if (p.a->isinternal())
+                               {
+                                       m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
+                                       m_stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
+                                       m_stkStack[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())
+                                       {
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
+                                               m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
+                                       }
+                               }
+                               else
+                               {
+                                       if (p.b->isinternal())
+                                       {
+                                               m_stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
+                                               m_stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                               policy.Process(p.a, p.b);
+                                       }
+                               }
+                       }
+               } while (depth);
+       }
+}
+
+#if 0
+//
+DBVT_PREFIX
+inline void            btDbvt::collideTT(      const btDbvtNode* root0,
+                                                                 const btDbvtNode* root1,
+                                                                 const btTransform& xform,
+                                                                 DBVT_IPOLICY)
+{
+       DBVT_CHECKTYPE
+               if(root0&&root1)
+               {
+                       int                                                             depth=1;
+                       int                                                             treshold=DOUBLE_STACKSIZE-4;
+                       btAlignedObjectArray<sStkNN>    stkStack;
+                       stkStack.resize(DOUBLE_STACKSIZE);
+                       stkStack[0]=sStkNN(root0,root1);
+                       do      {
+                               sStkNN  p=stkStack[--depth];
+                               if(Intersect(p.a->volume,p.b->volume,xform))
+                               {
+                                       if(depth>treshold)
+                                       {
+                                               stkStack.resize(stkStack.size()*2);
+                                               treshold=stkStack.size()-4;
+                                       }
+                                       if(p.a->isinternal())
+                                       {
+                                               if(p.b->isinternal())
+                                               {                                       
+                                                       stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+                                                       stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+                                                       stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+                                                       stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+                                               }
+                                               else
+                                               {
+                                                       stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+                                                       stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if(p.b->isinternal())
+                                               {
+                                                       stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+                                                       stkStack[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);
+}
+#endif
+
+DBVT_PREFIX
+inline void btDbvt::collideTV(const btDbvtNode* root,
+                                                         const btDbvtVolume& vol,
+                                                         DBVT_IPOLICY) const
+{
+       DBVT_CHECKTYPE
+       if (root)
+       {
+               ATTRIBUTE_ALIGNED16(btDbvtVolume)
+               volume(vol);
+               btAlignedObjectArray<const btDbvtNode*> stack;
+               stack.resize(0);
+#ifndef BT_DISABLE_STACK_TEMP_MEMORY
+               char tempmemory[SIMPLE_STACKSIZE * sizeof(const btDbvtNode*)];
+               stack.initializeFromBuffer(tempmemory, 0, SIMPLE_STACKSIZE);
+#else
+               stack.reserve(SIMPLE_STACKSIZE);
+#endif  //BT_DISABLE_STACK_TEMP_MEMORY
+
+               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::collideTVNoStackAlloc(const btDbvtNode* root,
+                                                                                 const btDbvtVolume& vol,
+                                                                                 btNodeStack& stack,
+                                                                                 DBVT_IPOLICY) const
+{
+       DBVT_CHECKTYPE
+       if (root)
+       {
+               ATTRIBUTE_ALIGNED16(btDbvtVolume)
+               volume(vol);
+               stack.resize(0);
+               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::rayTestInternal(const btDbvtNode* root,
+                                                                       const btVector3& rayFrom,
+                                                                       const btVector3& rayTo,
+                                                                       const btVector3& rayDirectionInverse,
+                                                                       unsigned int signs[3],
+                                                                       btScalar lambda_max,
+                                                                       const btVector3& aabbMin,
+                                                                       const btVector3& aabbMax,
+                                                                       btAlignedObjectArray<const btDbvtNode*>& stack,
+                                                                       DBVT_IPOLICY) const
+{
+       (void)rayTo;
+       DBVT_CHECKTYPE
+       if (root)
+       {
+               btVector3 resultNormal;
+
+               int depth = 1;
+               int treshold = DOUBLE_STACKSIZE - 2;
+               stack.resize(DOUBLE_STACKSIZE);
+               stack[0] = root;
+               btVector3 bounds[2];
+               do
+               {
+                       const btDbvtNode* node = stack[--depth];
+                       bounds[0] = node->volume.Mins() - aabbMax;
+                       bounds[1] = node->volume.Maxs() - aabbMin;
+                       btScalar tmin = 1.f, lambda_min = 0.f;
+                       unsigned int result1 = false;
+                       result1 = btRayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
+                       if (result1)
+                       {
+                               if (node->isinternal())
+                               {
+                                       if (depth > treshold)
+                                       {
+                                               stack.resize(stack.size() * 2);
+                                               treshold = stack.size() - 2;
+                                       }
+                                       stack[depth++] = node->childs[0];
+                                       stack[depth++] = node->childs[1];
+                               }
+                               else
+                               {
+                                       policy.Process(node);
+                               }
+                       }
+               } while (depth);
+       }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::rayTest(const btDbvtNode* root,
+                                                       const btVector3& rayFrom,
+                                                       const btVector3& rayTo,
+                                                       DBVT_IPOLICY)
+{
+       DBVT_CHECKTYPE
+       if (root)
+       {
+               btVector3 rayDir = (rayTo - rayFrom);
+               rayDir.normalize();
+
+               ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+               btVector3 rayDirectionInverse;
+               rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+               rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+               rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+               unsigned int signs[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+
+               btScalar lambda_max = rayDir.dot(rayTo - rayFrom);
+
+               btVector3 resultNormal;
+
+               btAlignedObjectArray<const btDbvtNode*> stack;
+
+               int depth = 1;
+               int treshold = DOUBLE_STACKSIZE - 2;
+
+               char tempmemory[DOUBLE_STACKSIZE * sizeof(const btDbvtNode*)];
+#ifndef BT_DISABLE_STACK_TEMP_MEMORY
+               stack.initializeFromBuffer(tempmemory, DOUBLE_STACKSIZE, DOUBLE_STACKSIZE);
+#else   //BT_DISABLE_STACK_TEMP_MEMORY
+               stack.resize(DOUBLE_STACKSIZE);
+#endif  //BT_DISABLE_STACK_TEMP_MEMORY
+               stack[0] = root;
+               btVector3 bounds[2];
+               do
+               {
+                       const btDbvtNode* node = stack[--depth];
+
+                       bounds[0] = node->volume.Mins();
+                       bounds[1] = node->volume.Maxs();
+
+                       btScalar tmin = 1.f, lambda_min = 0.f;
+                       unsigned int result1 = btRayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
+
+#ifdef COMPARE_BTRAY_AABB2
+                       btScalar param = 1.f;
+                       bool result2 = btRayAabb(rayFrom, rayTo, node->volume.Mins(), node->volume.Maxs(), param, resultNormal);
+                       btAssert(result1 == result2);
+#endif  //TEST_BTRAY_AABB2
+
+                       if (result1)
+                       {
+                               if (node->isinternal())
+                               {
+                                       if (depth > treshold)
+                                       {
+                                               stack.resize(stack.size() * 2);
+                                               treshold = stack.size() - 2;
+                                       }
+                                       stack[depth++] = node->childs[0];
+                                       stack[depth++] = node->childs[1];
+                               }
+                               else
+                               {
+                                       policy.Process(node);
+                               }
+                       }
+               } while (depth);
+       }
+}
+
+//
+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);
+
+                                               //void * memmove ( void * destination, const void * source, size_t num );
+
+#if DBVT_USE_MEMMOVE
+                                               {
+                                                       int num_items_to_move = stack.size() - 1 - j;
+                                                       if (num_items_to_move > 0)
+                                                               memmove(&stack[j + 1], &stack[j], sizeof(int) * num_items_to_move);
+                                               }
+#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
+                                               {
+                                                       int num_items_to_move = stack.size() - 1 - j;
+                                                       if (num_items_to_move > 0)
+                                                               memmove(&stack[j + 1], &stack[j], sizeof(int) * num_items_to_move);
+                                               }
+#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_SSE
+#undef DBVT_USE_INTRINSIC_SSE
+#undef DBVT_SELECT_IMPL
+#undef DBVT_MERGE_IMPL
+#undef DBVT_INT0_IMPL
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
new file mode 100644 (file)
index 0000000..7b39dbd
--- /dev/null
@@ -0,0 +1,828 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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"
+#include "LinearMath/btThreads.h"
+btScalar gDbvtMargin = btScalar(0.05);
+//
+// Profiling
+//
+
+#if DBVT_BP_PROFILE || DBVT_BP_ENABLE_BENCHMARK
+#include <stdio.h>
+#endif
+
+#if DBVT_BP_PROFILE
+struct ProfileScope
+{
+       __forceinline ProfileScope(btClock& clock, unsigned long& value) : m_clock(&clock), m_value(&value), m_base(clock.getTimeMicroseconds())
+       {
+       }
+       __forceinline ~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;
+       btDbvtProxy* proxy;
+       btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
+       void Process(const btDbvtNode* na, const btDbvtNode* nb)
+       {
+               if (na != nb)
+               {
+                       btDbvtProxy* pa = (btDbvtProxy*)na->data;
+                       btDbvtProxy* pb = (btDbvtProxy*)nb->data;
+#if DBVT_BP_SORTPAIRS
+                       if (pa->m_uniqueId > pb->m_uniqueId)
+                               btSwap(pa, pb);
+#endif
+                       pbp->m_paircache->addOverlappingPair(pa, pb);
+                       ++pbp->m_newpairs;
+               }
+       }
+       void Process(const btDbvtNode* n)
+       {
+               Process(n, proxy->leaf);
+       }
+};
+
+//
+// btDbvtBroadphase
+//
+
+//
+btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
+{
+       m_deferedcollide = false;
+       m_needcleanup = true;
+       m_releasepaircache = (paircache != 0) ? false : true;
+       m_prediction = 0;
+       m_stageCurrent = 0;
+       m_fixedleft = 0;
+       m_fupdates = 1;
+       m_dupdates = 0;
+       m_cupdates = 10;
+       m_newpairs = 1;
+       m_updates_call = 0;
+       m_updates_done = 0;
+       m_updates_ratio = 0;
+       m_paircache = paircache ? paircache : new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16)) btHashedOverlappingPairCache();
+       m_gid = 0;
+       m_pid = 0;
+       m_cid = 0;
+       for (int i = 0; i <= STAGECOUNT; ++i)
+       {
+               m_stageRoots[i] = 0;
+       }
+#if BT_THREADSAFE
+       m_rayTestStacks.resize(BT_MAX_THREAD_COUNT);
+#else
+       m_rayTestStacks.resize(1);
+#endif
+#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,
+                                                                                                int collisionFilterGroup,
+                                                                                                int collisionFilterMask,
+                                                                                                btDispatcher* /*dispatcher*/)
+{
+       btDbvtProxy* proxy = new (btAlignedAlloc(sizeof(btDbvtProxy), 16)) btDbvtProxy(aabbMin, aabbMax, userPtr,
+                                                                                                                                                                  collisionFilterGroup,
+                                                                                                                                                                  collisionFilterMask);
+
+       btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
+
+       //bproxy->aabb                  =       btDbvtVolume::FromMM(aabbMin,aabbMax);
+       proxy->stage = m_stageCurrent;
+       proxy->m_uniqueId = ++m_gid;
+       proxy->leaf = m_sets[0].insert(aabb, proxy);
+       listappend(proxy, m_stageRoots[m_stageCurrent]);
+       if (!m_deferedcollide)
+       {
+               btDbvtTreeCollider collider(this);
+               collider.proxy = proxy;
+               m_sets[0].collideTV(m_sets[0].m_root, aabb, collider);
+               m_sets[1].collideTV(m_sets[1].m_root, aabb, collider);
+       }
+       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);
+       m_needcleanup = true;
+}
+
+void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
+       aabbMin = proxy->m_aabbMin;
+       aabbMax = proxy->m_aabbMax;
+}
+
+struct BroadphaseRayTester : btDbvt::ICollide
+{
+       btBroadphaseRayCallback& m_rayCallback;
+       BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
+               : m_rayCallback(orgCallback)
+       {
+       }
+       void Process(const btDbvtNode* leaf)
+       {
+               btDbvtProxy* proxy = (btDbvtProxy*)leaf->data;
+               m_rayCallback.process(proxy);
+       }
+};
+
+void btDbvtBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
+{
+       BroadphaseRayTester callback(rayCallback);
+       btAlignedObjectArray<const btDbvtNode*>* stack = &m_rayTestStacks[0];
+#if BT_THREADSAFE
+       // for this function to be threadsafe, each thread must have a separate copy
+       // of this stack.  This could be thread-local static to avoid dynamic allocations,
+       // instead of just a local.
+       int threadIndex = btGetCurrentThreadIndex();
+       btAlignedObjectArray<const btDbvtNode*> localStack;
+       //todo(erwincoumans, "why do we get tsan issue here?")
+       if (0)//threadIndex < m_rayTestStacks.size())
+       //if (threadIndex < m_rayTestStacks.size())
+       {
+               // use per-thread preallocated stack if possible to avoid dynamic allocations
+               stack = &m_rayTestStacks[threadIndex];
+       }
+       else
+       {
+               stack = &localStack;
+       }
+#endif
+
+       m_sets[0].rayTestInternal(m_sets[0].m_root,
+                                                         rayFrom,
+                                                         rayTo,
+                                                         rayCallback.m_rayDirectionInverse,
+                                                         rayCallback.m_signs,
+                                                         rayCallback.m_lambda_max,
+                                                         aabbMin,
+                                                         aabbMax,
+                                                         *stack,
+                                                         callback);
+
+       m_sets[1].rayTestInternal(m_sets[1].m_root,
+                                                         rayFrom,
+                                                         rayTo,
+                                                         rayCallback.m_rayDirectionInverse,
+                                                         rayCallback.m_signs,
+                                                         rayCallback.m_lambda_max,
+                                                         aabbMin,
+                                                         aabbMax,
+                                                         *stack,
+                                                         callback);
+}
+
+struct BroadphaseAabbTester : btDbvt::ICollide
+{
+       btBroadphaseAabbCallback& m_aabbCallback;
+       BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback)
+               : m_aabbCallback(orgCallback)
+       {
+       }
+       void Process(const btDbvtNode* leaf)
+       {
+               btDbvtProxy* proxy = (btDbvtProxy*)leaf->data;
+               m_aabbCallback.process(proxy);
+       }
+};
+
+void btDbvtBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& aabbCallback)
+{
+       BroadphaseAabbTester callback(aabbCallback);
+
+       const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(aabbMin, aabbMax);
+       //process all children, that overlap with  the given AABB bounds
+       m_sets[0].collideTV(m_sets[0].m_root, bounds, callback);
+       m_sets[1].collideTV(m_sets[1].m_root, bounds, callback);
+}
+
+//
+void btDbvtBroadphase::setAabb(btBroadphaseProxy* absproxy,
+                                                          const btVector3& aabbMin,
+                                                          const btVector3& aabbMax,
+                                                          btDispatcher* /*dispatcher*/)
+{
+       btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
+       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+       aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
+#if DBVT_BP_PREVENTFALSEUPDATE
+       if (NotEqual(aabb, proxy->leaf->volume))
+#endif
+       {
+               bool docollide = false;
+               if (proxy->stage == STAGECOUNT)
+               { /* fixed -> dynamic set       */
+                       m_sets[1].remove(proxy->leaf);
+                       proxy->leaf = m_sets[0].insert(aabb, proxy);
+                       docollide = true;
+               }
+               else
+               { /* dynamic set                                */
+                       ++m_updates_call;
+                       if (Intersect(proxy->leaf->volume, aabb))
+                       { /* Moving                             */
+
+                               const btVector3 delta = aabbMin - proxy->m_aabbMin;
+                               btVector3 velocity(((proxy->m_aabbMax - proxy->m_aabbMin) / 2) * m_prediction);
+                               if (delta[0] < 0) velocity[0] = -velocity[0];
+                               if (delta[1] < 0) velocity[1] = -velocity[1];
+                               if (delta[2] < 0) velocity[2] = -velocity[2];
+                               if (
+                                       m_sets[0].update(proxy->leaf, aabb, velocity, gDbvtMargin)
+
+                               )
+                               {
+                                       ++m_updates_done;
+                                       docollide = true;
+                               }
+                       }
+                       else
+                       { /* Teleporting                        */
+                               m_sets[0].update(proxy->leaf, aabb);
+                               ++m_updates_done;
+                               docollide = true;
+                       }
+               }
+               listremove(proxy, m_stageRoots[proxy->stage]);
+               proxy->m_aabbMin = aabbMin;
+               proxy->m_aabbMax = aabbMax;
+               proxy->stage = m_stageCurrent;
+               listappend(proxy, m_stageRoots[m_stageCurrent]);
+               if (docollide)
+               {
+                       m_needcleanup = true;
+                       if (!m_deferedcollide)
+                       {
+                               btDbvtTreeCollider collider(this);
+                               m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
+                               m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
+                       }
+               }
+       }
+}
+
+//
+void btDbvtBroadphase::setAabbForceUpdate(btBroadphaseProxy* absproxy,
+                                                                                 const btVector3& aabbMin,
+                                                                                 const btVector3& aabbMax,
+                                                                                 btDispatcher* /*dispatcher*/)
+{
+       btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
+       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+       aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
+       bool docollide = false;
+       if (proxy->stage == STAGECOUNT)
+       { /* fixed -> dynamic set       */
+               m_sets[1].remove(proxy->leaf);
+               proxy->leaf = m_sets[0].insert(aabb, proxy);
+               docollide = true;
+       }
+       else
+       { /* dynamic set                                */
+               ++m_updates_call;
+               /* Teleporting                  */
+               m_sets[0].update(proxy->leaf, aabb);
+               ++m_updates_done;
+               docollide = true;
+       }
+       listremove(proxy, m_stageRoots[proxy->stage]);
+       proxy->m_aabbMin = aabbMin;
+       proxy->m_aabbMax = aabbMax;
+       proxy->stage = m_stageCurrent;
+       listappend(proxy, m_stageRoots[m_stageCurrent]);
+       if (docollide)
+       {
+               m_needcleanup = true;
+               if (!m_deferedcollide)
+               {
+                       btDbvtTreeCollider collider(this);
+                       m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
+                       m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
+               }
+       }
+}
+
+//
+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
+
+       performDeferredRemoval(dispatcher);
+}
+
+void btDbvtBroadphase::performDeferredRemoval(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());
+
+               int 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)
+                       {
+                               //important to perform AABB check that is consistent with the broadphase
+                               btDbvtProxy* pa = (btDbvtProxy*)pair.m_pProxy0;
+                               btDbvtProxy* pb = (btDbvtProxy*)pair.m_pProxy1;
+                               bool hasOverlap = Intersect(pa->leaf->volume, pb->leaf->volume);
+
+                               if (hasOverlap)
+                               {
+                                       needsRemoval = false;
+                               }
+                               else
+                               {
+                                       needsRemoval = true;
+                               }
+                       }
+                       else
+                       {
+                               //remove duplicate
+                               needsRemoval = true;
+                               //should have no algorithm
+                               btAssert(!pair.m_algorithm);
+                       }
+
+                       if (needsRemoval)
+                       {
+                               m_paircache->cleanOverlappingPair(pair, dispatcher);
+
+                               pair.m_pProxy0 = 0;
+                               pair.m_pProxy1 = 0;
+                               invalidPair++;
+                       }
+               }
+
+               //perform a sort, to sort 'invalid' pairs to the end
+               overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+               overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
+       }
+}
+
+//
+void btDbvtBroadphase::collide(btDispatcher* dispatcher)
+{
+       /*printf("---------------------------------------------------------\n");
+       printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
+       printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
+       printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
+       {
+               int i;
+               for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
+               {
+                       printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
+                               getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
+               }
+               printf("\n");
+       }
+*/
+
+       SPC(m_profiling.m_total);
+       /* optimize                             */
+       m_sets[0].optimizeIncremental(1 + (m_sets[0].m_leaves * m_dupdates) / 100);
+       if (m_fixedleft)
+       {
+               const int count = 1 + (m_sets[1].m_leaves * m_fupdates) / 100;
+               m_sets[1].optimizeIncremental(1 + (m_sets[1].m_leaves * m_fupdates) / 100);
+               m_fixedleft = btMax<int>(0, m_fixedleft - count);
+       }
+       /* dynamic -> fixed set */
+       m_stageCurrent = (m_stageCurrent + 1) % STAGECOUNT;
+       btDbvtProxy* current = m_stageRoots[m_stageCurrent];
+       if (current)
+       {
+#if DBVT_BP_ACCURATESLEEPING
+               btDbvtTreeCollider collider(this);
+#endif
+               do
+               {
+                       btDbvtProxy* next = current->links[1];
+                       listremove(current, m_stageRoots[current->stage]);
+                       listappend(current, m_stageRoots[STAGECOUNT]);
+#if DBVT_BP_ACCURATESLEEPING
+                       m_paircache->removeOverlappingPairsContainingProxy(current, dispatcher);
+                       collider.proxy = current;
+                       btDbvt::collideTV(m_sets[0].m_root, current->aabb, collider);
+                       btDbvt::collideTV(m_sets[1].m_root, current->aabb, collider);
+#endif
+                       m_sets[0].remove(current->leaf);
+                       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+                       curAabb = btDbvtVolume::FromMM(current->m_aabbMin, current->m_aabbMax);
+                       current->leaf = m_sets[1].insert(curAabb, current);
+                       current->stage = STAGECOUNT;
+                       current = next;
+               } while (current);
+               m_fixedleft = m_sets[1].m_leaves;
+               m_needcleanup = true;
+       }
+       /* collide dynamics             */
+       {
+               btDbvtTreeCollider collider(this);
+               if (m_deferedcollide)
+               {
+                       SPC(m_profiling.m_fdcollide);
+                       m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[1].m_root, collider);
+               }
+               if (m_deferedcollide)
+               {
+                       SPC(m_profiling.m_ddcollide);
+                       m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[0].m_root, collider);
+               }
+       }
+       /* clean up                             */
+       if (m_needcleanup)
+       {
+               SPC(m_profiling.m_cleanup);
+               btBroadphasePairArray& pairs = m_paircache->getOverlappingPairArray();
+               if (pairs.size() > 0)
+               {
+                       int ni = btMin(pairs.size(), btMax<int>(m_newpairs, (pairs.size() * m_cupdates) / 100));
+                       for (int i = 0; i < ni; ++i)
+                       {
+                               btBroadphasePair& p = pairs[(m_cid + i) % pairs.size()];
+                               btDbvtProxy* pa = (btDbvtProxy*)p.m_pProxy0;
+                               btDbvtProxy* pb = (btDbvtProxy*)p.m_pProxy1;
+                               if (!Intersect(pa->leaf->volume, pb->leaf->volume))
+                               {
+#if DBVT_BP_SORTPAIRS
+                                       if (pa->m_uniqueId > pb->m_uniqueId)
+                                               btSwap(pa, pb);
+#endif
+                                       m_paircache->removeOverlappingPair(pa, pb, dispatcher);
+                                       --ni;
+                                       --i;
+                               }
+                       }
+                       if (pairs.size() > 0)
+                               m_cid = (m_cid + ni) % pairs.size();
+                       else
+                               m_cid = 0;
+               }
+       }
+       ++m_pid;
+       m_newpairs = 1;
+       m_needcleanup = false;
+       if (m_updates_call > 0)
+       {
+               m_updates_ratio = m_updates_done / (btScalar)m_updates_call;
+       }
+       else
+       {
+               m_updates_ratio = 0;
+       }
+       m_updates_done /= 2;
+       m_updates_call /= 2;
+}
+
+//
+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::resetPool(btDispatcher* dispatcher)
+{
+       int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
+       if (!totalObjects)
+       {
+               //reset internal dynamic tree data structures
+               m_sets[0].clear();
+               m_sets[1].clear();
+
+               m_deferedcollide = false;
+               m_needcleanup = true;
+               m_stageCurrent = 0;
+               m_fixedleft = 0;
+               m_fupdates = 1;
+               m_dupdates = 0;
+               m_cupdates = 10;
+               m_newpairs = 1;
+               m_updates_call = 0;
+               m_updates_done = 0;
+               m_updates_ratio = 0;
+
+               m_gid = 0;
+               m_pid = 0;
+               m_cid = 0;
+               for (int i = 0; i <= STAGECOUNT; ++i)
+               {
+                       m_stageRoots[i] = 0;
+               }
+       }
+}
+
+//
+void btDbvtBroadphase::printStats()
+{
+}
+
+//
+#if DBVT_BP_ENABLE_BENCHMARK
+
+struct btBroadphaseBenchmark
+{
+       struct Experiment
+       {
+               const char* name;
+               int object_count;
+               int update_count;
+               int spawn_count;
+               int iterations;
+               btScalar speed;
+               btScalar amplitude;
+       };
+       struct Object
+       {
+               btVector3 center;
+               btVector3 extents;
+               btBroadphaseProxy* proxy;
+               btScalar time;
+               void update(btScalar speed, btScalar amplitude, btBroadphaseInterface* pbi)
+               {
+                       time += speed;
+                       center[0] = btCos(time * (btScalar)2.17) * amplitude +
+                                               btSin(time) * amplitude / 2;
+                       center[1] = btCos(time * (btScalar)1.38) * amplitude +
+                                               btSin(time) * amplitude;
+                       center[2] = btSin(time * (btScalar)0.777) * amplitude;
+                       pbi->setAabb(proxy, center - extents, center + extents, 0);
+               }
+       };
+       static int UnsignedRand(int range = RAND_MAX - 1) { return (rand() % (range + 1)); }
+       static btScalar UnitRand() { return (UnsignedRand(16384) / (btScalar)16384); }
+       static void OutputTime(const char* name, btClock& c, unsigned count = 0)
+       {
+               const unsigned long us = c.getTimeMicroseconds();
+               const unsigned long ms = (us + 500) / 1000;
+               const btScalar sec = us / (btScalar)(1000 * 1000);
+               if (count > 0)
+                       printf("%s : %u us (%u ms), %.2f/s\r\n", name, us, ms, count / sec);
+               else
+                       printf("%s : %u us (%u ms)\r\n", name, us, ms);
+       }
+};
+
+void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
+{
+       static const btBroadphaseBenchmark::Experiment experiments[] =
+               {
+                       {"1024o.10%", 1024, 10, 0, 8192, (btScalar)0.005, (btScalar)100},
+                       /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
+               {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
+               };
+       static const int nexperiments = sizeof(experiments) / sizeof(experiments[0]);
+       btAlignedObjectArray<btBroadphaseBenchmark::Object*> objects;
+       btClock wallclock;
+       /* Begin                        */
+       for (int iexp = 0; iexp < nexperiments; ++iexp)
+       {
+               const btBroadphaseBenchmark::Experiment& experiment = experiments[iexp];
+               const int object_count = experiment.object_count;
+               const int update_count = (object_count * experiment.update_count) / 100;
+               const int spawn_count = (object_count * experiment.spawn_count) / 100;
+               const btScalar speed = experiment.speed;
+               const btScalar amplitude = experiment.amplitude;
+               printf("Experiment #%u '%s':\r\n", iexp, experiment.name);
+               printf("\tObjects: %u\r\n", object_count);
+               printf("\tUpdate: %u\r\n", update_count);
+               printf("\tSpawn: %u\r\n", spawn_count);
+               printf("\tSpeed: %f\r\n", speed);
+               printf("\tAmplitude: %f\r\n", amplitude);
+               srand(180673);
+               /* Create objects       */
+               wallclock.reset();
+               objects.reserve(object_count);
+               for (int i = 0; i < object_count; ++i)
+               {
+                       btBroadphaseBenchmark::Object* po = new btBroadphaseBenchmark::Object();
+                       po->center[0] = btBroadphaseBenchmark::UnitRand() * 50;
+                       po->center[1] = btBroadphaseBenchmark::UnitRand() * 50;
+                       po->center[2] = btBroadphaseBenchmark::UnitRand() * 50;
+                       po->extents[0] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
+                       po->extents[1] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
+                       po->extents[2] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
+                       po->time = btBroadphaseBenchmark::UnitRand() * 2000;
+                       po->proxy = pbi->createProxy(po->center - po->extents, po->center + po->extents, 0, po, 1, 1, 0, 0);
+                       objects.push_back(po);
+               }
+               btBroadphaseBenchmark::OutputTime("\tInitialization", wallclock);
+               /* First update         */
+               wallclock.reset();
+               for (int i = 0; i < objects.size(); ++i)
+               {
+                       objects[i]->update(speed, amplitude, pbi);
+               }
+               btBroadphaseBenchmark::OutputTime("\tFirst update", wallclock);
+               /* Updates                      */
+               wallclock.reset();
+               for (int i = 0; i < experiment.iterations; ++i)
+               {
+                       for (int j = 0; j < update_count; ++j)
+                       {
+                               objects[j]->update(speed, amplitude, pbi);
+                       }
+                       pbi->calculateOverlappingPairs(0);
+               }
+               btBroadphaseBenchmark::OutputTime("\tUpdate", wallclock, experiment.iterations);
+               /* Clean up                     */
+               wallclock.reset();
+               for (int i = 0; i < objects.size(); ++i)
+               {
+                       pbi->destroyProxy(objects[i]->proxy, 0);
+                       delete objects[i];
+               }
+               objects.resize(0);
+               btBroadphaseBenchmark::OutputTime("\tRelease", wallclock);
+       }
+}
+#else
+void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
+{
+}
+#endif
+
+#if DBVT_BP_PROFILE
+#undef SPC
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
new file mode 100644 (file)
index 0000000..a71feef
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SORTPAIRS                            1
+#define DBVT_BP_PREVENTFALSEUPDATE 0
+#define DBVT_BP_ACCURATESLEEPING 0
+#define DBVT_BP_ENABLE_BENCHMARK 0
+//#define DBVT_BP_MARGIN                                       (btScalar)0.05
+extern btScalar gDbvtMargin;
+
+#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(const btVector3& aabbMin, const btVector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask) : btBroadphaseProxy(aabbMin, aabbMax, 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_prediction;                      // Velocity prediction
+       int m_stageCurrent;                         // Current stage
+       int m_fupdates;                             // % of fixed updates per frame
+       int m_dupdates;                             // % of dynamic updates per frame
+       int m_cupdates;                             // % of cleanup updates per frame
+       int m_newpairs;                             // Number of pairs created
+       int m_fixedleft;                            // Fixed optimization left
+       unsigned m_updates_call;                    // Number of updates call
+       unsigned m_updates_done;                    // Number of updates done
+       btScalar m_updates_ratio;                   // m_updates_done/m_updates_call
+       int m_pid;                                  // Parse id
+       int m_cid;                                  // Cleanup index
+       int m_gid;                                  // Gen id
+       bool m_releasepaircache;                    // Release pair cache on delete
+       bool m_deferedcollide;                      // Defere dynamic/static collision to collide call
+       bool m_needcleanup;                         // Need to run cleanup?
+       btAlignedObjectArray<btAlignedObjectArray<const btDbvtNode*> > m_rayTestStacks;
+#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, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
+       virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
+       virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
+       virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
+       virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+       virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
+       virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+       virtual btOverlappingPairCache* getOverlappingPairCache();
+       virtual const btOverlappingPairCache* getOverlappingPairCache() const;
+       virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const;
+       virtual void printStats();
+
+       ///reset broadphase internal structures, to ensure determinism/reproducability
+       virtual void resetPool(btDispatcher* dispatcher);
+
+       void performDeferredRemoval(btDispatcher* dispatcher);
+
+       void setVelocityPrediction(btScalar prediction)
+       {
+               m_prediction = prediction;
+       }
+       btScalar getVelocityPrediction() const
+       {
+               return m_prediction;
+       }
+
+       ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
+       ///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase.
+       ///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
+       ///http://code.google.com/p/bullet/issues/detail?id=223
+       void setAabbForceUpdate(btBroadphaseProxy* absproxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* /*dispatcher*/);
+
+       static void benchmark(btBroadphaseInterface*);
+};
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp
new file mode 100644 (file)
index 0000000..e71cb7d
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btDispatcher.h"
+
+btDispatcher::~btDispatcher()
+{
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btDispatcher.h
new file mode 100644 (file)
index 0000000..d59441c
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_DISPATCHER_H
+#define BT_DISPATCHER_H
+#include "LinearMath/btScalar.h"
+
+class btCollisionAlgorithm;
+struct btBroadphaseProxy;
+class btRigidBody;
+class btCollisionObject;
+class btOverlappingPairCache;
+struct btCollisionObjectWrapper;
+
+class btPersistentManifold;
+class btPoolAllocator;
+
+struct btDispatcherInfo
+{
+       enum DispatchFunc
+       {
+               DISPATCH_DISCRETE = 1,
+               DISPATCH_CONTINUOUS
+       };
+       btDispatcherInfo()
+               : m_timeStep(btScalar(0.)),
+                 m_stepCount(0),
+                 m_dispatchFunc(DISPATCH_DISCRETE),
+                 m_timeOfImpact(btScalar(1.)),
+                 m_useContinuous(true),
+                 m_debugDraw(0),
+                 m_enableSatConvex(false),
+                 m_enableSPU(true),
+                 m_useEpa(true),
+                 m_allowedCcdPenetration(btScalar(0.04)),
+                 m_useConvexConservativeDistanceUtil(false),
+                 m_convexConservativeDistanceThreshold(0.0f),
+                 m_deterministicOverlappingPairs(false)
+       {
+       }
+       btScalar m_timeStep;
+       int m_stepCount;
+       int m_dispatchFunc;
+       mutable btScalar m_timeOfImpact;
+       bool m_useContinuous;
+       class btIDebugDraw* m_debugDraw;
+       bool m_enableSatConvex;
+       bool m_enableSPU;
+       bool m_useEpa;
+       btScalar m_allowedCcdPenetration;
+       bool m_useConvexConservativeDistanceUtil;
+       btScalar m_convexConservativeDistanceThreshold;
+       bool m_deterministicOverlappingPairs;
+};
+
+enum ebtDispatcherQueryType
+{
+       BT_CONTACT_POINT_ALGORITHMS = 1,
+       BT_CLOSEST_POINT_ALGORITHMS = 2
+};
+
+///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
+{
+public:
+       virtual ~btDispatcher();
+
+       virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType) = 0;
+
+       virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0, const btCollisionObject* b1) = 0;
+
+       virtual void releaseManifold(btPersistentManifold* manifold) = 0;
+
+       virtual void clearManifold(btPersistentManifold* manifold) = 0;
+
+       virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1) = 0;
+
+       virtual bool needsResponse(const btCollisionObject* body0, const btCollisionObject* body1) = 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 btPoolAllocator* getInternalManifoldPool() = 0;
+
+       virtual const btPoolAllocator* getInternalManifoldPool() const = 0;
+
+       virtual void* allocateCollisionAlgorithm(int size) = 0;
+
+       virtual void freeCollisionAlgorithm(void* ptr) = 0;
+};
+
+#endif  //BT_DISPATCHER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
new file mode 100644 (file)
index 0000000..fb36acd
--- /dev/null
@@ -0,0 +1,611 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btOverlappingPairCache.h"
+
+#include "btDispatcher.h"
+#include "btCollisionAlgorithm.h"
+#include "LinearMath/btAabbUtil2.h"
+
+#include <stdio.h>
+
+btHashedOverlappingPairCache::btHashedOverlappingPairCache() : m_overlapFilterCallback(0),
+                                                                                                                          m_ghostPairCallback(0)
+{
+       int initialAllocatedSize = 2;
+       m_overlappingPairArray.reserve(initialAllocatedSize);
+       growTables();
+}
+
+btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
+{
+}
+
+void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher)
+{
+       if (pair.m_algorithm && dispatcher)
+       {
+               {
+                       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
+       {
+               btBroadphaseProxy* m_obsoleteProxy;
+
+       public:
+               RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+                       : m_obsoleteProxy(obsoleteProxy)
+               {
+               }
+               virtual bool processOverlap(btBroadphasePair& pair)
+               {
+                       return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+                                       (pair.m_pProxy1 == m_obsoleteProxy));
+               }
+       };
+
+       RemovePairCallback removeCallback(proxy);
+
+       processAllOverlappingPairs(&removeCallback, dispatcher);
+}
+
+btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+       if (proxy0->m_uniqueId > proxy1->m_uniqueId)
+               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->m_uniqueId > proxy1->m_uniqueId)
+               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.expandNonInitializing();
+
+       //this is where we add an actual pair, so also call the 'ghost'
+       if (m_ghostPairCallback)
+               m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
+
+       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_internalTmpValue = 0;
+
+       m_next[count] = m_hashTable[hash];
+       m_hashTable[hash] = count;
+
+       return pair;
+}
+
+void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
+{
+       if (proxy0->m_uniqueId > proxy1->m_uniqueId)
+               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_internalInfo1;
+
+       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 (m_ghostPairCallback)
+               m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1, dispatcher);
+
+       // 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>
+#include "LinearMath/btQuickprof.h"
+void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher)
+{
+       BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
+       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);
+               }
+               else
+               {
+                       i++;
+               }
+       }
+}
+
+struct MyPairIndex
+{
+       int m_orgIndex;
+       int m_uidA0;
+       int m_uidA1;
+};
+
+class MyPairIndeSortPredicate
+{
+public:
+       bool operator()(const MyPairIndex& a, const MyPairIndex& b) const
+       {
+               const int uidA0 = a.m_uidA0;
+               const int uidB0 = b.m_uidA0;
+               const int uidA1 = a.m_uidA1;
+               const int uidB1 = b.m_uidA1;
+               return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
+       }
+};
+
+void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo)
+{
+       if (dispatchInfo.m_deterministicOverlappingPairs)
+       {
+               btBroadphasePairArray& pa = getOverlappingPairArray();
+               btAlignedObjectArray<MyPairIndex> indices;
+               {
+                       BT_PROFILE("sortOverlappingPairs");
+                       indices.resize(pa.size());
+                       for (int i = 0; i < indices.size(); i++)
+                       {
+                               const btBroadphasePair& p = pa[i];
+                               const int uidA0 = p.m_pProxy0 ? p.m_pProxy0->m_uniqueId : -1;
+                               const int uidA1 = p.m_pProxy1 ? p.m_pProxy1->m_uniqueId : -1;
+
+                               indices[i].m_uidA0 = uidA0;
+                               indices[i].m_uidA1 = uidA1;
+                               indices[i].m_orgIndex = i;
+                       }
+                       indices.quickSort(MyPairIndeSortPredicate());
+               }
+               {
+                       BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
+                       int i;
+                       for (i = 0; i < indices.size();)
+                       {
+                               btBroadphasePair* pair = &pa[indices[i].m_orgIndex];
+                               if (callback->processOverlap(*pair))
+                               {
+                                       removeOverlappingPair(pair->m_pProxy0, pair->m_pProxy1, dispatcher);
+                               }
+                               else
+                               {
+                                       i++;
+                               }
+                       }
+               }
+       }
+       else
+       {
+               processAllOverlappingPairs(callback, dispatcher);
+       }
+}
+
+void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+{
+       ///need to keep hashmap in sync with pair address, so rebuild all
+       btBroadphasePairArray tmpPairs;
+       int i;
+       for (i = 0; i < m_overlappingPairArray.size(); i++)
+       {
+               tmpPairs.push_back(m_overlappingPairArray[i]);
+       }
+
+       for (i = 0; i < tmpPairs.size(); i++)
+       {
+               removeOverlappingPair(tmpPairs[i].m_pProxy0, tmpPairs[i].m_pProxy1, dispatcher);
+       }
+
+       for (i = 0; i < m_next.size(); i++)
+       {
+               m_next[i] = BT_NULL_PAIR;
+       }
+
+       tmpPairs.quickSort(btBroadphasePairSortPredicate());
+
+       for (i = 0; i < tmpPairs.size(); i++)
+       {
+               addOverlappingPair(tmpPairs[i].m_pProxy0, tmpPairs[i].m_pProxy1);
+       }
+}
+
+void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
+{
+       if (!hasDeferredRemoval())
+       {
+               btBroadphasePair findPair(*proxy0, *proxy1);
+
+               int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
+               if (findIndex < m_overlappingPairArray.size())
+               {
+                       btBroadphasePair& pair = m_overlappingPairArray[findIndex];
+                       void* userData = pair.m_internalInfo1;
+                       cleanOverlappingPair(pair, dispatcher);
+                       if (m_ghostPairCallback)
+                               m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1, dispatcher);
+
+                       m_overlappingPairArray.swap(findIndex, m_overlappingPairArray.capacity() - 1);
+                       m_overlappingPairArray.pop_back();
+                       return userData;
+               }
+       }
+
+       return 0;
+}
+
+btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+       //don't add overlap with own
+       btAssert(proxy0 != proxy1);
+
+       if (!needsBroadphaseCollision(proxy0, proxy1))
+               return 0;
+
+       void* mem = &m_overlappingPairArray.expandNonInitializing();
+       btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0, *proxy1);
+
+       if (m_ghostPairCallback)
+               m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
+       return pair;
+}
+
+///this findPair becomes really slow. Either sort the list to speedup the query, or
+///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
+///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
+///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
+btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+       if (!needsBroadphaseCollision(proxy0, proxy1))
+               return 0;
+
+       btBroadphasePair tmpPair(*proxy0, *proxy1);
+       int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
+
+       if (findIndex < m_overlappingPairArray.size())
+       {
+               //btAssert(it != m_overlappingPairSet.end());
+               btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
+               return pair;
+       }
+       return 0;
+}
+
+//#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);
+                       pair->m_pProxy0 = 0;
+                       pair->m_pProxy1 = 0;
+                       m_overlappingPairArray.swap(i, m_overlappingPairArray.size() - 1);
+                       m_overlappingPairArray.pop_back();
+               }
+               else
+               {
+                       i++;
+               }
+       }
+}
+
+btSortedOverlappingPairCache::btSortedOverlappingPairCache() : m_blockedForChanges(false),
+                                                                                                                          m_hasDeferredRemoval(true),
+                                                                                                                          m_overlapFilterCallback(0),
+                                                                                                                          m_ghostPairCallback(0)
+{
+       int initialAllocatedSize = 2;
+       m_overlappingPairArray.reserve(initialAllocatedSize);
+}
+
+btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
+{
+}
+
+void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher)
+{
+       if (pair.m_algorithm)
+       {
+               {
+                       pair.m_algorithm->~btCollisionAlgorithm();
+                       dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+                       pair.m_algorithm = 0;
+               }
+       }
+}
+
+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, 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 btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
+{
+       class RemovePairCallback : public btOverlapCallback
+       {
+               btBroadphaseProxy* m_obsoleteProxy;
+
+       public:
+               RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+                       : m_obsoleteProxy(obsoleteProxy)
+               {
+               }
+               virtual bool processOverlap(btBroadphasePair& pair)
+               {
+                       return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+                                       (pair.m_pProxy1 == m_obsoleteProxy));
+               }
+       };
+
+       RemovePairCallback removeCallback(proxy);
+
+       processAllOverlappingPairs(&removeCallback, dispatcher);
+}
+
+void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+{
+       //should already be sorted
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
new file mode 100644 (file)
index 0000000..1d82726
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_OVERLAPPING_PAIR_CACHE_H
+#define BT_OVERLAPPING_PAIR_CACHE_H
+
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
+
+typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
+
+struct btOverlapCallback
+{
+       virtual ~btOverlapCallback()
+       {
+       }
+       //return true for deletion of the pair
+       virtual bool processOverlap(btBroadphasePair& pair) = 0;
+};
+
+struct btOverlapFilterCallback
+{
+       virtual ~btOverlapFilterCallback()
+       {
+       }
+       // return true when pairs need collision
+       virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const = 0;
+};
+
+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 bool needsBroadphaseCollision(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1) const = 0;
+       virtual btOverlapFilterCallback* getOverlapFilterCallback() = 0;
+       virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
+
+       virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
+
+       virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher) = 0;
+
+       virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& /*dispatchInfo*/)
+       {
+               processAllOverlappingPairs(callback, dispatcher);
+       }
+       virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
+
+       virtual bool hasDeferredRemoval() = 0;
+
+       virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) = 0;
+
+       virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
+};
+
+/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
+
+ATTRIBUTE_ALIGNED16(class)
+btHashedOverlappingPairCache : public btOverlappingPairCache
+{
+       btBroadphasePairArray m_overlappingPairArray;
+       btOverlapFilterCallback* m_overlapFilterCallback;
+
+protected:
+       btAlignedObjectArray<int> m_hashTable;
+       btAlignedObjectArray<int> m_next;
+       btOverlappingPairCallback* m_ghostPairCallback;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       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)
+       {
+               if (!needsBroadphaseCollision(proxy0, proxy1))
+                       return 0;
+
+               return internalAddPair(proxy0, proxy1);
+       }
+
+       void cleanProxyFromPairs(btBroadphaseProxy * proxy, btDispatcher * dispatcher);
+
+       virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher * dispatcher);
+
+       virtual void processAllOverlappingPairs(btOverlapCallback * callback, btDispatcher * dispatcher, const struct btDispatcherInfo& dispatchInfo);
+
+       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)
+       {
+               unsigned int key = proxyId1 | (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 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;
+       }
+
+       virtual void setInternalGhostPairCallback(btOverlappingPairCallback * ghostPairCallback)
+       {
+               m_ghostPairCallback = ghostPairCallback;
+       }
+
+       virtual void sortOverlappingPairs(btDispatcher * dispatcher);
+};
+
+///btSortedOverlappingPairCache maintains the objects with overlapping AABB
+///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
+class btSortedOverlappingPairCache : public btOverlappingPairCache
+{
+protected:
+       //avoid brute-force finding all the time
+       btBroadphasePairArray m_overlappingPairArray;
+
+       //during the dispatch, check that user doesn't destroy/create proxy
+       bool m_blockedForChanges;
+
+       ///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;
+
+       btOverlappingPairCallback* m_ghostPairCallback;
+
+public:
+       btSortedOverlappingPairCache();
+       virtual ~btSortedOverlappingPairCache();
+
+       virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher);
+
+       void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher);
+
+       void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher);
+
+       btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
+
+       btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
+
+       void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
+
+       void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
+
+       inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const
+       {
+               if (m_overlapFilterCallback)
+                       return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
+
+               bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+               collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+
+               return collides;
+       }
+
+       btBroadphasePairArray& getOverlappingPairArray()
+       {
+               return m_overlappingPairArray;
+       }
+
+       const btBroadphasePairArray& getOverlappingPairArray() const
+       {
+               return m_overlappingPairArray;
+       }
+
+       btBroadphasePair* getOverlappingPairArrayPtr()
+       {
+               return &m_overlappingPairArray[0];
+       }
+
+       const btBroadphasePair* getOverlappingPairArrayPtr() const
+       {
+               return &m_overlappingPairArray[0];
+       }
+
+       int getNumOverlappingPairs() const
+       {
+               return m_overlappingPairArray.size();
+       }
+
+       btOverlapFilterCallback* getOverlapFilterCallback()
+       {
+               return m_overlapFilterCallback;
+       }
+
+       void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+       {
+               m_overlapFilterCallback = callback;
+       }
+
+       virtual bool hasDeferredRemoval()
+       {
+               return m_hasDeferredRemoval;
+       }
+
+       virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+       {
+               m_ghostPairCallback = ghostPairCallback;
+       }
+
+       virtual void sortOverlappingPairs(btDispatcher* dispatcher);
+};
+
+///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit 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*/)
+       {
+       }
+
+       bool needsBroadphaseCollision(btBroadphaseProxy*, btBroadphaseProxy*) const
+       {
+               return true;
+       }
+       btOverlapFilterCallback* getOverlapFilterCallback()
+       {
+               return 0;
+       }
+       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 void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
+       {
+       }
+
+       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*/)
+       {
+       }
+
+       virtual void sortOverlappingPairs(btDispatcher* dispatcher)
+       {
+               (void)dispatcher;
+       }
+};
+
+#endif  //BT_OVERLAPPING_PAIR_CACHE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
new file mode 100644 (file)
index 0000000..36e5068
--- /dev/null
@@ -0,0 +1,41 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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
+{
+protected:
+       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/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
new file mode 100644 (file)
index 0000000..e23610e
--- /dev/null
@@ -0,0 +1,1341 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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"
+#include "LinearMath/btSerializer.h"
+
+#define RAYAABB2
+
+btQuantizedBvh::btQuantizedBvh() : m_bulletVersion(BT_BULLET_VERSION),
+                                                                  m_useQuantization(false),
+                                                                  //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+                                                                  m_traversalMode(TRAVERSAL_STACKLESS)
+                                                                  //m_traversalMode(TRAVERSAL_RECURSIVE)
+                                                                  ,
+                                                                  m_subtreeHeaderCount(0)  //PCK: add this line
+{
+       m_bvhAabbMin.setValue(-SIMD_INFINITY, -SIMD_INFINITY, -SIMD_INFINITY);
+       m_bvhAabbMax.setValue(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
+}
+
+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(1, 0, 0),
+               btVector3(0, 1, 0),
+               btVector3(0, 0, 1),
+               btVector3(0, 1, 1)};
+#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;
+
+       {
+               unsigned short vecIn[3];
+               btVector3 v;
+               {
+                       quantize(vecIn, m_bvhAabbMin, false);
+                       v = unQuantize(vecIn);
+                       m_bvhAabbMin.setMin(v - clampValue);
+               }
+               aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+               m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
+               {
+                       quantize(vecIn, m_bvhAabbMax, true);
+                       v = unQuantize(vecIn);
+                       m_bvhAabbMax.setMax(v + clampValue);
+               }
+               aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+               m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
+       }
+}
+
+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;
+
+       btAssert(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;
+
+       //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
+       //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
+       setInternalNodeAabbMin(m_curNodeIndex, m_bvhAabbMax);  //can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization
+       setInternalNodeAabbMax(m_curNodeIndex, m_bvhAabbMin);  //can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization
+
+       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);
+               }
+       }
+       else
+       {
+       }
+
+       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);
+       }
+}
+
+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
+               btAssert(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;
+               }
+       }
+}
+
+/*
+///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::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) 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 = 0;
+       unsigned rayBoxOverlap = 0;
+       btScalar lambda_max = 1.0;
+
+       /* 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;
+
+#ifdef RAYAABB2
+       btVector3 rayDir = (rayTarget - raySource);
+       rayDir.safeNormalize();// stephengold changed normalize to safeNormalize 2020-02-17
+       lambda_max = rayDir.dot(rayTarget - raySource);
+       ///what about division by zero? --> just set rayDirection[i] to 1.0
+       btVector3 rayDirectionInverse;
+       rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+       rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+       rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+       unsigned int sign[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+#endif
+
+       btVector3 bounds[2];
+
+       while (curIndex < m_curNodeIndex)
+       {
+               btScalar param = 1.0;
+               //catch bugs in tree data
+               btAssert(walkIterations < m_curNodeIndex);
+
+               walkIterations++;
+
+               bounds[0] = rootNode->m_aabbMinOrg;
+               bounds[1] = rootNode->m_aabbMaxOrg;
+               /* Add box cast extents */
+               bounds[0] -= aabbMax;
+               bounds[1] -= aabbMin;
+
+               aabbOverlap = TestAabbAgainstAabb2(rayAabbMin, rayAabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
+               //perhaps profile if it is worth doing the aabbOverlap test first
+
+#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 = aabbOverlap ? btRayAabb2(raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
+
+#else
+               btVector3 normal;
+               rayBoxOverlap = btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+#endif
+
+               isLeafNode = rootNode->m_escapeIndex == -1;
+
+               //PCK: unsigned instead of bool
+               if (isLeafNode && (rayBoxOverlap != 0))
+               {
+                       nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
+               }
+
+               //PCK: unsigned instead of bool
+               if ((rayBoxOverlap != 0) || isLeafNode)
+               {
+                       rootNode++;
+                       curIndex++;
+               }
+               else
+               {
+                       escapeIndex = rootNode->m_escapeIndex;
+                       rootNode += escapeIndex;
+                       curIndex += escapeIndex;
+               }
+       }
+}
+
+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;
+
+#ifdef RAYAABB2
+       btVector3 rayDirection = (rayTarget - raySource);
+       rayDirection.safeNormalize();// stephengold changed normalize to safeNormalize 2020-02-17
+       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(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0];
+       rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[1];
+       rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : 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
+               btAssert(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] -= aabbMax;
+                       bounds[1] -= aabbMin;
+                       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
+
+                       //BT_PROFILE("btRayAabb2");
+                       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;
+               }
+       }
+}
+
+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
+               btAssert(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;
+               }
+       }
+}
+
+//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
+{
+       reportBoxCastOverlappingNodex(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0));
+}
+
+void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+       //always use stackless
+
+       if (m_useQuantization)
+       {
+               walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+       }
+       else
+       {
+               walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+       }
+       /*
+       {
+               //recursive traversal
+               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>
+
+#if 0
+//PCK: consts
+static const unsigned BVH_ALIGNMENT = 16;
+static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
+
+static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
+#endif
+
+unsigned int btQuantizedBvh::getAlignmentSerializationPadding()
+{
+       // I changed this to 0 since the extra padding is not needed or used.
+       return 0;  //BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+}
+
+unsigned btQuantizedBvh::calculateSerializeBufferSize() const
+{
+       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) const
+{
+       btAssert(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;
+
+               // this clears the pointer in the member variable it doesn't really do anything to the data
+               // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+               // so the memory (which is not freed) is left alone
+               targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0);
+       }
+       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;
+
+               // this clears the pointer in the member variable it doesn't really do anything to the data
+               // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+               // so the memory (which is not freed) is left alone
+               targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
+       }
+
+       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);
+
+                       // need to clear padding in destination buffer
+                       targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0;
+                       targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0;
+                       targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0;
+               }
+       }
+       nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+
+       // this clears the pointer in the member variable it doesn't really do anything to the data
+       // it does call the destructor on the contained objects, but they are all classes with no destructor defined
+       // so the memory (which is not freed) is left alone
+       targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0);
+
+       // this wipes the virtual function table pointer at the start of the buffer for the class
+       *((void**)o_alignedDataBuffer) = NULL;
+
+       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),
+                                                                                                                                                         m_bulletVersion(BT_BULLET_VERSION)
+{
+}
+
+void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData)
+{
+       m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax);
+       m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin);
+       m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
+
+       m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
+       m_useQuantization = quantizedBvhFloatData.m_useQuantization != 0;
+
+       {
+               int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
+               m_contiguousNodes.resize(numElem);
+
+               if (numElem)
+               {
+                       btOptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
+
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
+                               m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
+                               m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+                               m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+                               m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+                       }
+               }
+       }
+
+       {
+               int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
+               m_quantizedContiguousNodes.resize(numElem);
+
+               if (numElem)
+               {
+                       btQuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+                       }
+               }
+       }
+
+       m_traversalMode = btTraversalMode(quantizedBvhFloatData.m_traversalMode);
+
+       {
+               int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
+               m_SubtreeHeaders.resize(numElem);
+               if (numElem)
+               {
+                       btBvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+                               m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+                               m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+                       }
+               }
+       }
+}
+
+void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData)
+{
+       m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax);
+       m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin);
+       m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
+
+       m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
+       m_useQuantization = quantizedBvhDoubleData.m_useQuantization != 0;
+
+       {
+               int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
+               m_contiguousNodes.resize(numElem);
+
+               if (numElem)
+               {
+                       btOptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
+
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
+                               m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
+                               m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+                               m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+                               m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+                       }
+               }
+       }
+
+       {
+               int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
+               m_quantizedContiguousNodes.resize(numElem);
+
+               if (numElem)
+               {
+                       btQuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+                               m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+                       }
+               }
+       }
+
+       m_traversalMode = btTraversalMode(quantizedBvhDoubleData.m_traversalMode);
+
+       {
+               int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
+               m_SubtreeHeaders.resize(numElem);
+               if (numElem)
+               {
+                       btBvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+                               m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+                               m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+                               m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+                               m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+                       }
+               }
+       }
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btQuantizedBvhData* quantizedData = (btQuantizedBvhData*)dataBuffer;
+
+       m_bvhAabbMax.serialize(quantizedData->m_bvhAabbMax);
+       m_bvhAabbMin.serialize(quantizedData->m_bvhAabbMin);
+       m_bvhQuantization.serialize(quantizedData->m_bvhQuantization);
+
+       quantizedData->m_curNodeIndex = m_curNodeIndex;
+       quantizedData->m_useQuantization = m_useQuantization;
+
+       quantizedData->m_numContiguousLeafNodes = m_contiguousNodes.size();
+       quantizedData->m_contiguousNodesPtr = (btOptimizedBvhNodeData*)(m_contiguousNodes.size() ? serializer->getUniquePointer((void*)&m_contiguousNodes[0]) : 0);
+       if (quantizedData->m_contiguousNodesPtr)
+       {
+               int sz = sizeof(btOptimizedBvhNodeData);
+               int numElem = m_contiguousNodes.size();
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               btOptimizedBvhNodeData* memPtr = (btOptimizedBvhNodeData*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       m_contiguousNodes[i].m_aabbMaxOrg.serialize(memPtr->m_aabbMaxOrg);
+                       m_contiguousNodes[i].m_aabbMinOrg.serialize(memPtr->m_aabbMinOrg);
+                       memPtr->m_escapeIndex = m_contiguousNodes[i].m_escapeIndex;
+                       memPtr->m_subPart = m_contiguousNodes[i].m_subPart;
+                       memPtr->m_triangleIndex = m_contiguousNodes[i].m_triangleIndex;
+                       // Fill padding with zeros to appease msan.
+                       memset(memPtr->m_pad, 0, sizeof(memPtr->m_pad));
+               }
+               serializer->finalizeChunk(chunk, "btOptimizedBvhNodeData", BT_ARRAY_CODE, (void*)&m_contiguousNodes[0]);
+       }
+
+       quantizedData->m_numQuantizedContiguousNodes = m_quantizedContiguousNodes.size();
+       //      printf("quantizedData->m_numQuantizedContiguousNodes=%d\n",quantizedData->m_numQuantizedContiguousNodes);
+       quantizedData->m_quantizedContiguousNodesPtr = (btQuantizedBvhNodeData*)(m_quantizedContiguousNodes.size() ? serializer->getUniquePointer((void*)&m_quantizedContiguousNodes[0]) : 0);
+       if (quantizedData->m_quantizedContiguousNodesPtr)
+       {
+               int sz = sizeof(btQuantizedBvhNodeData);
+               int numElem = m_quantizedContiguousNodes.size();
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               btQuantizedBvhNodeData* memPtr = (btQuantizedBvhNodeData*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       memPtr->m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex;
+                       memPtr->m_quantizedAabbMax[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[0];
+                       memPtr->m_quantizedAabbMax[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[1];
+                       memPtr->m_quantizedAabbMax[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[2];
+                       memPtr->m_quantizedAabbMin[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[0];
+                       memPtr->m_quantizedAabbMin[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[1];
+                       memPtr->m_quantizedAabbMin[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[2];
+               }
+               serializer->finalizeChunk(chunk, "btQuantizedBvhNodeData", BT_ARRAY_CODE, (void*)&m_quantizedContiguousNodes[0]);
+       }
+
+       quantizedData->m_traversalMode = int(m_traversalMode);
+       quantizedData->m_numSubtreeHeaders = m_SubtreeHeaders.size();
+
+       quantizedData->m_subTreeInfoPtr = (btBvhSubtreeInfoData*)(m_SubtreeHeaders.size() ? serializer->getUniquePointer((void*)&m_SubtreeHeaders[0]) : 0);
+       if (quantizedData->m_subTreeInfoPtr)
+       {
+               int sz = sizeof(btBvhSubtreeInfoData);
+               int numElem = m_SubtreeHeaders.size();
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               btBvhSubtreeInfoData* memPtr = (btBvhSubtreeInfoData*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       memPtr->m_quantizedAabbMax[0] = m_SubtreeHeaders[i].m_quantizedAabbMax[0];
+                       memPtr->m_quantizedAabbMax[1] = m_SubtreeHeaders[i].m_quantizedAabbMax[1];
+                       memPtr->m_quantizedAabbMax[2] = m_SubtreeHeaders[i].m_quantizedAabbMax[2];
+                       memPtr->m_quantizedAabbMin[0] = m_SubtreeHeaders[i].m_quantizedAabbMin[0];
+                       memPtr->m_quantizedAabbMin[1] = m_SubtreeHeaders[i].m_quantizedAabbMin[1];
+                       memPtr->m_quantizedAabbMin[2] = m_SubtreeHeaders[i].m_quantizedAabbMin[2];
+
+                       memPtr->m_rootNodeIndex = m_SubtreeHeaders[i].m_rootNodeIndex;
+                       memPtr->m_subtreeSize = m_SubtreeHeaders[i].m_subtreeSize;
+               }
+               serializer->finalizeChunk(chunk, "btBvhSubtreeInfoData", BT_ARRAY_CODE, (void*)&m_SubtreeHeaders[0]);
+       }
+       return btQuantizedBvhDataName;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
new file mode 100644 (file)
index 0000000..1a01992
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_QUANTIZED_BVH_H
+#define BT_QUANTIZED_BVH_H
+
+class btSerializer;
+
+//#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"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btQuantizedBvhData btQuantizedBvhDoubleData
+#define btOptimizedBvhNodeData btOptimizedBvhNodeDoubleData
+#define btQuantizedBvhDataName "btQuantizedBvhDoubleData"
+#else
+#define btQuantizedBvhData btQuantizedBvhFloatData
+#define btOptimizedBvhNodeData btOptimizedBvhNodeFloatData
+#define btQuantizedBvhDataName "btQuantizedBvhFloatData"
+#endif
+
+//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());
+               unsigned int x = 0;
+               unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
+               // Get only the lower bits where the triangle index is stored
+               return (m_escapeIndexOrTriangleIndex & ~(y));
+       }
+       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;
+
+       //pad the size to 64 bytes
+       char m_padding[20];
+};
+
+///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.
+///It is recommended to use quantization for better performance and lower memory requirements.
+ATTRIBUTE_ALIGNED16(class)
+btQuantizedBvh
+{
+public:
+       enum btTraversalMode
+       {
+               TRAVERSAL_STACKLESS = 0,
+               TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
+               TRAVERSAL_RECURSIVE
+       };
+
+protected:
+       btVector3 m_bvhAabbMin;
+       btVector3 m_bvhAabbMax;
+       btVector3 m_bvhQuantization;
+
+       int m_bulletVersion;  //for serialization versioning. It could also be used to detect endianess.
+
+       int m_curNodeIndex;
+       //quantization data
+       bool m_useQuantization;
+
+       NodeArray m_leafNodes;
+       NodeArray m_contiguousNodes;
+       QuantizedNodeArray m_quantizedLeafNodes;
+       QuantizedNodeArray m_quantizedContiguousNodes;
+
+       btTraversalMode m_traversalMode;
+       BvhSubtreeInfoArray m_SubtreeHeaders;
+
+       //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
+       mutable 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;
+       void walkStacklessTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, 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;
+
+       void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       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() const;
+
+       /// Data buffer MUST be 16 byte aligned
+       virtual bool serialize(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
+
+       ///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();
+       //////////////////////////////////////////////////////////////////////
+
+       virtual int calculateSerializeBufferSizeNew() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+       virtual void deSerializeFloat(struct btQuantizedBvhFloatData & quantizedBvhFloatData);
+
+       virtual void deSerializeDouble(struct btQuantizedBvhDoubleData & quantizedBvhDoubleData);
+
+       ////////////////////////////////////////////////////////////////////
+
+       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);
+};
+
+// clang-format off
+// parser needs * with the name
+struct btBvhSubtreeInfoData
+{
+       int m_rootNodeIndex;
+       int m_subtreeSize;
+       unsigned short m_quantizedAabbMin[3];
+       unsigned short m_quantizedAabbMax[3];
+};
+
+struct btOptimizedBvhNodeFloatData
+{
+       btVector3FloatData m_aabbMinOrg;
+       btVector3FloatData m_aabbMaxOrg;
+       int m_escapeIndex;
+       int m_subPart;
+       int m_triangleIndex;
+       char m_pad[4];
+};
+
+struct btOptimizedBvhNodeDoubleData
+{
+       btVector3DoubleData m_aabbMinOrg;
+       btVector3DoubleData m_aabbMaxOrg;
+       int m_escapeIndex;
+       int m_subPart;
+       int m_triangleIndex;
+       char m_pad[4];
+};
+
+
+struct btQuantizedBvhNodeData
+{
+       unsigned short m_quantizedAabbMin[3];
+       unsigned short m_quantizedAabbMax[3];
+       int     m_escapeIndexOrTriangleIndex;
+};
+
+struct btQuantizedBvhFloatData
+{
+       btVector3FloatData                      m_bvhAabbMin;
+       btVector3FloatData                      m_bvhAabbMax;
+       btVector3FloatData                      m_bvhQuantization;
+       int                                     m_curNodeIndex;
+       int                                     m_useQuantization;
+       int                                     m_numContiguousLeafNodes;
+       int                                     m_numQuantizedContiguousNodes;
+       btOptimizedBvhNodeFloatData     *m_contiguousNodesPtr;
+       btQuantizedBvhNodeData          *m_quantizedContiguousNodesPtr;
+       btBvhSubtreeInfoData    *m_subTreeInfoPtr;
+       int                                     m_traversalMode;
+       int                                     m_numSubtreeHeaders;
+       
+};
+
+struct btQuantizedBvhDoubleData
+{
+       btVector3DoubleData                     m_bvhAabbMin;
+       btVector3DoubleData                     m_bvhAabbMax;
+       btVector3DoubleData                     m_bvhQuantization;
+       int                                                     m_curNodeIndex;
+       int                                                     m_useQuantization;
+       int                                                     m_numContiguousLeafNodes;
+       int                                                     m_numQuantizedContiguousNodes;
+       btOptimizedBvhNodeDoubleData    *m_contiguousNodesPtr;
+       btQuantizedBvhNodeData                  *m_quantizedContiguousNodesPtr;
+
+       int                                                     m_traversalMode;
+       int                                                     m_numSubtreeHeaders;
+       btBvhSubtreeInfoData            *m_subTreeInfoPtr;
+};
+// clang-format on
+
+SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const
+{
+       return sizeof(btQuantizedBvhData);
+}
+
+#endif  //BT_QUANTIZED_BVH_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
new file mode 100644 (file)
index 0000000..bb02df8
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btAabbUtil2.h"
+
+#include <new>
+
+void btSimpleBroadphase::validate()
+{
+       for (int i = 0; i < m_numHandles; i++)
+       {
+               for (int j = i + 1; j < m_numHandles; j++)
+               {
+                       btAssert(&m_pHandles[i] != &m_pHandles[j]);
+               }
+       }
+}
+
+btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
+       : m_pairCache(overlappingPairCache),
+         m_ownsPairCache(false),
+         m_invalidPair(0)
+{
+       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_LastHandleIndex = -1;
+
+       {
+               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[maxProxies - 1].SetNextFree(0);
+       }
+}
+
+btSimpleBroadphase::~btSimpleBroadphase()
+{
+       btAlignedFree(m_pHandlesRawPtr);
+
+       if (m_ownsPairCache)
+       {
+               m_pairCache->~btOverlappingPairCache();
+               btAlignedFree(m_pairCache);
+       }
+}
+
+btBroadphaseProxy* btSimpleBroadphase::createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* /*dispatcher*/)
+{
+       if (m_numHandles >= m_maxHandles)
+       {
+               btAssert(0);
+               return 0;  //should never happen, but don't let the game crash ;-)
+       }
+       btAssert(aabbMin[0] <= aabbMax[0] && aabbMin[1] <= aabbMax[1] && aabbMin[2] <= aabbMax[2]);
+
+       int newHandleIndex = allocHandle();
+       btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex]) btSimpleBroadphaseProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask);
+
+       return proxy;
+}
+
+class RemovingOverlapCallback : public btOverlapCallback
+{
+protected:
+       virtual bool processOverlap(btBroadphasePair& pair)
+       {
+               (void)pair;
+               btAssert(0);
+               return false;
+       }
+};
+
+class RemovePairContainingProxy
+{
+       btBroadphaseProxy* m_targetProxy;
+
+public:
+       virtual ~RemovePairContainingProxy()
+       {
+       }
+
+protected:
+       virtual bool processOverlap(btBroadphasePair& pair)
+       {
+               btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0);
+               btSimpleBroadphaseProxy* proxy1 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1);
+
+               return ((m_targetProxy == proxy0 || m_targetProxy == proxy1));
+       };
+};
+
+void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg, btDispatcher* dispatcher)
+{
+       m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg, dispatcher);
+
+       btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
+       freeHandle(proxy0);
+
+       //validate();
+}
+
+void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
+       aabbMin = sbp->m_aabbMin;
+       aabbMax = sbp->m_aabbMax;
+}
+
+void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
+{
+       btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
+       sbp->m_aabbMin = aabbMin;
+       sbp->m_aabbMax = aabbMax;
+}
+
+void btSimpleBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
+{
+       for (int i = 0; i <= m_LastHandleIndex; i++)
+       {
+               btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
+               if (!proxy->m_clientObject)
+               {
+                       continue;
+               }
+               rayCallback.process(proxy);
+       }
+}
+
+void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+{
+       for (int i = 0; i <= m_LastHandleIndex; i++)
+       {
+               btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
+               if (!proxy->m_clientObject)
+               {
+                       continue;
+               }
+               if (TestAabbAgainstAabb2(aabbMin, aabbMax, proxy->m_aabbMin, proxy->m_aabbMax))
+               {
+                       callback.process(proxy);
+               }
+       }
+}
+
+bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0, btSimpleBroadphaseProxy* proxy1)
+{
+       return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] &&
+                  proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] &&
+                  proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2];
+}
+
+//then remove non-overlapping ones
+class CheckOverlapCallback : public btOverlapCallback
+{
+public:
+       virtual bool processOverlap(btBroadphasePair& pair)
+       {
+               return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0), static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
+       }
+};
+
+void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+       //first check for new overlapping pairs
+       int i, j;
+       if (m_numHandles >= 0)
+       {
+               int new_largest_index = -1;
+               for (i = 0; i <= m_LastHandleIndex; i++)
+               {
+                       btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i];
+                       if (!proxy0->m_clientObject)
+                       {
+                               continue;
+                       }
+                       new_largest_index = i;
+                       for (j = i + 1; j <= m_LastHandleIndex; j++)
+                       {
+                               btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j];
+                               btAssert(proxy0 != proxy1);
+                               if (!proxy1->m_clientObject)
+                               {
+                                       continue;
+                               }
+
+                               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);
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               m_LastHandleIndex = new_largest_index;
+
+               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];
+
+                               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++;
+                               }
+                       }
+
+                       ///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);
+}
+
+void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
+{
+       //not yet
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/dali-physics/third-party/bullet3/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
new file mode 100644 (file)
index 0000000..f97073c
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SIMPLE_BROADPHASE_H
+#define BT_SIMPLE_BROADPHASE_H
+
+#include "btOverlappingPairCache.h"
+
+struct btSimpleBroadphaseProxy : public btBroadphaseProxy
+{
+       int m_nextFree;
+
+       //      int                     m_handleId;
+
+       btSimpleBroadphaseProxy(){};
+
+       btSimpleBroadphaseProxy(const btVector3& minpt, const btVector3& maxpt, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
+               : btBroadphaseProxy(minpt, maxpt, userPtr, collisionFilterGroup, collisionFilterMask)
+       {
+               (void)shapeType;
+       }
+
+       SIMD_FORCE_INLINE void SetNextFree(int next) { m_nextFree = next; }
+       SIMD_FORCE_INLINE int GetNextFree() const { return m_nextFree; }
+};
+
+///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:
+       int m_numHandles;  // number of active handles
+       int m_maxHandles;  // max number of handles
+       int m_LastHandleIndex;
+
+       btSimpleBroadphaseProxy* m_pHandles;  // handles pool
+
+       void* m_pHandlesRawPtr;
+       int m_firstFreeHandle;  // free handles list
+
+       int allocHandle()
+       {
+               btAssert(m_numHandles < m_maxHandles);
+               int freeHandle = m_firstFreeHandle;
+               m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree();
+               m_numHandles++;
+               if (freeHandle > m_LastHandleIndex)
+               {
+                       m_LastHandleIndex = freeHandle;
+               }
+               return freeHandle;
+       }
+
+       void freeHandle(btSimpleBroadphaseProxy* proxy)
+       {
+               int handle = int(proxy - m_pHandles);
+               btAssert(handle >= 0 && handle < m_maxHandles);
+               if (handle == m_LastHandleIndex)
+               {
+                       m_LastHandleIndex--;
+               }
+               proxy->SetNextFree(m_firstFreeHandle);
+               m_firstFreeHandle = handle;
+
+               proxy->m_clientObject = 0;
+
+               m_numHandles--;
+       }
+
+       btOverlappingPairCache* m_pairCache;
+       bool m_ownsPairCache;
+
+       int m_invalidPair;
+
+       inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
+       {
+               btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxy);
+               return proxy0;
+       }
+
+       inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
+       {
+               const btSimpleBroadphaseProxy* proxy0 = static_cast<const btSimpleBroadphaseProxy*>(proxy);
+               return proxy0;
+       }
+
+       ///reset broadphase internal structures, to ensure determinism/reproducability
+       virtual void resetPool(btDispatcher* dispatcher);
+
+       void validate();
+
+protected:
+public:
+       btSimpleBroadphase(int maxProxies = 16384, btOverlappingPairCache* overlappingPairCache = 0);
+       virtual ~btSimpleBroadphase();
+
+       static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0, btSimpleBroadphaseProxy* proxy1);
+
+       virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
+
+       virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+
+       virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
+       virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
+       virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
+       virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+       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(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT);
+               aabbMax.setValue(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
+       }
+
+       virtual void printStats()
+       {
+               //              printf("btSimpleBroadphase.h\n");
+               //              printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+       }
+};
+
+#endif  //BT_SIMPLE_BROADPHASE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CMakeLists.txt b/dali-physics/third-party/bullet3/src/BulletCollision/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f5d7255
--- /dev/null
@@ -0,0 +1,294 @@
+INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src  )
+
+SET(BulletCollision_SRCS
+       BroadphaseCollision/btAxisSweep3.cpp
+       BroadphaseCollision/btBroadphaseProxy.cpp
+       BroadphaseCollision/btCollisionAlgorithm.cpp
+       BroadphaseCollision/btDbvt.cpp
+       BroadphaseCollision/btDbvtBroadphase.cpp
+       BroadphaseCollision/btDispatcher.cpp
+       BroadphaseCollision/btOverlappingPairCache.cpp
+       BroadphaseCollision/btQuantizedBvh.cpp
+       BroadphaseCollision/btSimpleBroadphase.cpp
+       CollisionDispatch/btActivatingCollisionAlgorithm.cpp
+       CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
+       CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
+       CollisionDispatch/btBoxBoxDetector.cpp
+       CollisionDispatch/btCollisionDispatcher.cpp
+       CollisionDispatch/btCollisionDispatcherMt.cpp
+       CollisionDispatch/btCollisionObject.cpp
+       CollisionDispatch/btCollisionWorld.cpp
+       CollisionDispatch/btCollisionWorldImporter.cpp
+       CollisionDispatch/btCompoundCollisionAlgorithm.cpp
+       CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
+       CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
+       CollisionDispatch/btConvexConvexAlgorithm.cpp
+       CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
+       CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
+       CollisionDispatch/btDefaultCollisionConfiguration.cpp
+       CollisionDispatch/btEmptyCollisionAlgorithm.cpp
+       CollisionDispatch/btGhostObject.cpp
+       CollisionDispatch/btHashedSimplePairCache.cpp
+       CollisionDispatch/btInternalEdgeUtility.cpp
+       CollisionDispatch/btInternalEdgeUtility.h
+       CollisionDispatch/btManifoldResult.cpp
+       CollisionDispatch/btSimulationIslandManager.cpp
+       CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
+       CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
+       CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
+       CollisionDispatch/btUnionFind.cpp
+       CollisionDispatch/SphereTriangleDetector.cpp
+       CollisionShapes/btBoxShape.cpp
+       CollisionShapes/btBox2dShape.cpp
+       CollisionShapes/btBvhTriangleMeshShape.cpp
+       CollisionShapes/btCapsuleShape.cpp
+       CollisionShapes/btCollisionShape.cpp
+       CollisionShapes/btCompoundShape.cpp
+       CollisionShapes/btConcaveShape.cpp
+       CollisionShapes/btConeShape.cpp
+       CollisionShapes/btConvexHullShape.cpp
+       CollisionShapes/btConvexInternalShape.cpp
+       CollisionShapes/btConvexPointCloudShape.cpp
+       CollisionShapes/btConvexPolyhedron.cpp
+       CollisionShapes/btConvexShape.cpp
+       CollisionShapes/btConvex2dShape.cpp
+       CollisionShapes/btConvexTriangleMeshShape.cpp
+       CollisionShapes/btCylinderShape.cpp
+       CollisionShapes/btEmptyShape.cpp
+       CollisionShapes/btHeightfieldTerrainShape.cpp
+       CollisionShapes/btMiniSDF.cpp
+       CollisionShapes/btMinkowskiSumShape.cpp
+       CollisionShapes/btMultimaterialTriangleMeshShape.cpp
+       CollisionShapes/btMultiSphereShape.cpp
+       CollisionShapes/btOptimizedBvh.cpp
+       CollisionShapes/btPolyhedralConvexShape.cpp
+       CollisionShapes/btScaledBvhTriangleMeshShape.cpp
+       CollisionShapes/btSdfCollisionShape.cpp
+       CollisionShapes/btShapeHull.cpp
+       CollisionShapes/btSphereShape.cpp
+       CollisionShapes/btStaticPlaneShape.cpp
+       CollisionShapes/btStridingMeshInterface.cpp
+       CollisionShapes/btTetrahedronShape.cpp
+       CollisionShapes/btTriangleBuffer.cpp
+       CollisionShapes/btTriangleCallback.cpp
+       CollisionShapes/btTriangleIndexVertexArray.cpp
+       CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
+       CollisionShapes/btTriangleMesh.cpp
+       CollisionShapes/btTriangleMeshShape.cpp
+       CollisionShapes/btUniformScalingShape.cpp
+       Gimpact/btContactProcessing.cpp
+       Gimpact/btGenericPoolAllocator.cpp
+       Gimpact/btGImpactBvh.cpp
+       Gimpact/btGImpactCollisionAlgorithm.cpp
+       Gimpact/btGImpactQuantizedBvh.cpp
+       Gimpact/btGImpactShape.cpp
+       Gimpact/btTriangleShapeEx.cpp
+       Gimpact/gim_box_set.cpp
+       Gimpact/gim_contact.cpp
+       Gimpact/gim_memory.cpp
+       Gimpact/gim_tri_collision.cpp
+       NarrowPhaseCollision/btContinuousConvexCollision.cpp
+       NarrowPhaseCollision/btConvexCast.cpp
+       NarrowPhaseCollision/btGjkConvexCast.cpp
+       NarrowPhaseCollision/btGjkEpa2.cpp
+       NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
+       NarrowPhaseCollision/btGjkPairDetector.cpp
+       NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
+       NarrowPhaseCollision/btPersistentManifold.cpp
+       NarrowPhaseCollision/btRaycastCallback.cpp
+       NarrowPhaseCollision/btSubSimplexConvexCast.cpp
+       NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
+       NarrowPhaseCollision/btPolyhedralContactClipping.cpp
+)
+
+SET(Root_HDRS
+       ../btBulletCollisionCommon.h
+)
+SET(BroadphaseCollision_HDRS
+    BroadphaseCollision/btAxisSweep3Internal.h
+       BroadphaseCollision/btAxisSweep3.h
+       BroadphaseCollision/btBroadphaseInterface.h
+       BroadphaseCollision/btBroadphaseProxy.h
+       BroadphaseCollision/btCollisionAlgorithm.h
+       BroadphaseCollision/btDbvt.h
+       BroadphaseCollision/btDbvtBroadphase.h
+       BroadphaseCollision/btDispatcher.h
+       BroadphaseCollision/btOverlappingPairCache.h
+       BroadphaseCollision/btOverlappingPairCallback.h
+       BroadphaseCollision/btQuantizedBvh.h
+       BroadphaseCollision/btSimpleBroadphase.h
+)
+SET(CollisionDispatch_HDRS
+       CollisionDispatch/btActivatingCollisionAlgorithm.h
+       CollisionDispatch/btBoxBoxCollisionAlgorithm.h
+       CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
+       CollisionDispatch/btBoxBoxDetector.h
+       CollisionDispatch/btCollisionConfiguration.h
+       CollisionDispatch/btCollisionCreateFunc.h
+       CollisionDispatch/btCollisionDispatcher.h
+       CollisionDispatch/btCollisionDispatcherMt.h
+       CollisionDispatch/btCollisionObject.h
+       CollisionDispatch/btCollisionObjectWrapper.h
+       CollisionDispatch/btCollisionWorld.h
+       CollisionDispatch/btCollisionWorldImporter.h
+       CollisionDispatch/btCompoundCollisionAlgorithm.h
+       CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
+       CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
+       CollisionDispatch/btConvexConvexAlgorithm.h
+       CollisionDispatch/btConvex2dConvex2dAlgorithm.h
+       CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
+       CollisionDispatch/btDefaultCollisionConfiguration.h
+       CollisionDispatch/btEmptyCollisionAlgorithm.h
+       CollisionDispatch/btGhostObject.h
+       CollisionDispatch/btHashedSimplePairCache.h
+       CollisionDispatch/btManifoldResult.h
+       CollisionDispatch/btSimulationIslandManager.h
+       CollisionDispatch/btSphereBoxCollisionAlgorithm.h
+       CollisionDispatch/btSphereSphereCollisionAlgorithm.h
+       CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
+       CollisionDispatch/btUnionFind.h
+       CollisionDispatch/SphereTriangleDetector.h
+)
+SET(CollisionShapes_HDRS
+       CollisionShapes/btBoxShape.h
+       CollisionShapes/btBox2dShape.h
+       CollisionShapes/btBvhTriangleMeshShape.h
+       CollisionShapes/btCapsuleShape.h
+       CollisionShapes/btCollisionMargin.h
+       CollisionShapes/btCollisionShape.h
+       CollisionShapes/btCompoundShape.h
+       CollisionShapes/btConcaveShape.h
+       CollisionShapes/btConeShape.h
+       CollisionShapes/btConvexHullShape.h
+       CollisionShapes/btConvexInternalShape.h
+       CollisionShapes/btConvexPointCloudShape.h
+       CollisionShapes/btConvexPolyhedron.h
+       CollisionShapes/btConvexShape.h
+       CollisionShapes/btConvex2dShape.h
+       CollisionShapes/btConvexTriangleMeshShape.h
+       CollisionShapes/btCylinderShape.h
+       CollisionShapes/btEmptyShape.h
+       CollisionShapes/btHeightfieldTerrainShape.h
+       CollisionShapes/btMaterial.h
+       CollisionShapes/btMinkowskiSumShape.h
+       CollisionShapes/btMultimaterialTriangleMeshShape.h
+       CollisionShapes/btMultiSphereShape.h
+       CollisionShapes/btOptimizedBvh.h
+       CollisionShapes/btPolyhedralConvexShape.h
+       CollisionShapes/btScaledBvhTriangleMeshShape.h
+       CollisionShapes/btShapeHull.h
+       CollisionShapes/btSphereShape.h
+       CollisionShapes/btStaticPlaneShape.h
+       CollisionShapes/btStridingMeshInterface.h
+       CollisionShapes/btTetrahedronShape.h
+       CollisionShapes/btTriangleBuffer.h
+       CollisionShapes/btTriangleCallback.h
+       CollisionShapes/btTriangleIndexVertexArray.h
+       CollisionShapes/btTriangleIndexVertexMaterialArray.h
+       CollisionShapes/btTriangleInfoMap.h
+       CollisionShapes/btTriangleMesh.h
+       CollisionShapes/btTriangleMeshShape.h
+       CollisionShapes/btTriangleShape.h
+       CollisionShapes/btUniformScalingShape.h
+)
+SET(Gimpact_HDRS
+       Gimpact/btBoxCollision.h
+       Gimpact/btClipPolygon.h
+       Gimpact/btContactProcessingStructs.h
+       Gimpact/btContactProcessing.h
+       Gimpact/btGenericPoolAllocator.h
+       Gimpact/btGeometryOperations.h
+       Gimpact/btGImpactBvhStructs.h
+       Gimpact/btGImpactBvh.h
+       Gimpact/btGImpactCollisionAlgorithm.h
+       Gimpact/btGImpactMassUtil.h
+       Gimpact/btGImpactQuantizedBvhStructs.h
+       Gimpact/btGImpactQuantizedBvh.h
+       Gimpact/btGImpactShape.h
+       Gimpact/btQuantization.h
+       Gimpact/btTriangleShapeEx.h
+       Gimpact/gim_array.h
+       Gimpact/gim_basic_geometry_operations.h
+       Gimpact/gim_bitset.h
+       Gimpact/gim_box_collision.h
+       Gimpact/gim_box_set.h
+       Gimpact/gim_clip_polygon.h
+       Gimpact/gim_contact.h
+       Gimpact/gim_geom_types.h
+       Gimpact/gim_geometry.h
+       Gimpact/gim_hash_table.h
+       Gimpact/gim_linear_math.h
+       Gimpact/gim_math.h
+       Gimpact/gim_memory.h
+       Gimpact/gim_radixsort.h
+       Gimpact/gim_tri_collision.h
+)
+SET(NarrowPhaseCollision_HDRS
+       NarrowPhaseCollision/btContinuousConvexCollision.h
+       NarrowPhaseCollision/btConvexCast.h
+       NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
+       NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
+       NarrowPhaseCollision/btGjkConvexCast.h
+       NarrowPhaseCollision/btGjkEpa2.h
+       NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
+       NarrowPhaseCollision/btGjkPairDetector.h
+       NarrowPhaseCollision/btManifoldPoint.h
+       NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
+       NarrowPhaseCollision/btPersistentManifold.h
+       NarrowPhaseCollision/btPointCollector.h
+       NarrowPhaseCollision/btRaycastCallback.h
+       NarrowPhaseCollision/btSimplexSolverInterface.h
+       NarrowPhaseCollision/btSubSimplexConvexCast.h
+       NarrowPhaseCollision/btVoronoiSimplexSolver.h
+       NarrowPhaseCollision/btPolyhedralContactClipping.h
+)
+
+SET(BulletCollision_HDRS
+       ${Root_HDRS}
+       ${BroadphaseCollision_HDRS}
+       ${CollisionDispatch_HDRS}
+       ${CollisionShapes_HDRS}
+       ${Gimpact_HDRS}
+       ${NarrowPhaseCollision_HDRS}
+)
+
+
+ADD_LIBRARY(BulletCollision ${BulletCollision_SRCS} ${BulletCollision_HDRS})
+SET_TARGET_PROPERTIES(BulletCollision PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(BulletCollision PROPERTIES SOVERSION ${BULLET_VERSION})
+IF (BUILD_SHARED_LIBS)
+  TARGET_LINK_LIBRARIES(BulletCollision LinearMath)
+ENDIF (BUILD_SHARED_LIBS)
+
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               #INSTALL of other files requires CMake 2.6
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS BulletCollision DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS BulletCollision RUNTIME DESTINATION bin
+                                                               LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                                               ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+                               INSTALL(FILES ../btBulletCollisionCommon.h
+DESTINATION ${INCLUDE_INSTALL_DIR}/BulletCollision)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(BulletCollision PROPERTIES FRAMEWORK true)
+
+                       SET_TARGET_PROPERTIES(BulletCollision PROPERTIES PUBLIC_HEADER "${Root_HDRS}")
+                       # Have to list out sub-directories manually:
+                       SET_PROPERTY(SOURCE ${BroadphaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/BroadphaseCollision)
+                       SET_PROPERTY(SOURCE ${CollisionDispatch_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionDispatch)
+                       SET_PROPERTY(SOURCE ${CollisionShapes_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/CollisionShapes)
+                       SET_PROPERTY(SOURCE ${Gimpact_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Gimpact)
+                       SET_PROPERTY(SOURCE ${NarrowPhaseCollision_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/NarrowPhaseCollision)
+
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
new file mode 100644 (file)
index 0000000..5715210
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "LinearMath/btScalar.h"
+#include "SphereTriangleDetector.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere, btTriangleShape* triangle, btScalar contactBreakingThreshold)
+       : m_sphere(sphere),
+         m_triangle(triangle),
+         m_contactBreakingThreshold(contactBreakingThreshold)
+{
+}
+
+void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults)
+{
+       (void)debugDraw;
+       const btTransform& transformA = input.m_transformA;
+       const btTransform& transformB = input.m_transformB;
+
+       btVector3 point, normal;
+       btScalar timeOfImpact = btScalar(1.);
+       btScalar depth = btScalar(0.);
+       //      output.m_distance = btScalar(BT_LARGE_FLOAT);
+       //move sphere into triangle space
+       btTransform sphereInTr = transformB.inverseTimes(transformA);
+
+       if (collide(sphereInTr.getOrigin(), point, normal, depth, timeOfImpact, m_contactBreakingThreshold))
+       {
+               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);
+               }
+       }
+}
+
+// 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;
+       btScalar t = v.dot(diff);
+
+       if (t > 0)
+       {
+               btScalar dotVV = v.dot(v);
+               if (t < dotVV)
+               {
+                       t /= dotVV;
+                       diff -= t * v;
+               }
+               else
+               {
+                       t = 1;
+                       diff -= v;
+               }
+       }
+       else
+               t = 0;
+
+       nearest = from + t * v;
+       return diff.dot(diff);
+}
+
+bool SphereTriangleDetector::facecontains(const btVector3& p, const btVector3* vertices, btVector3& normal)
+{
+       btVector3 lp(p);
+       btVector3 lnormal(normal);
+
+       return pointInTriangle(vertices, lnormal, &lp);
+}
+
+bool SphereTriangleDetector::collide(const btVector3& sphereCenter, btVector3& point, btVector3& resultNormal, btScalar& depth, btScalar& timeOfImpact, btScalar contactBreakingThreshold)
+{
+       const btVector3* vertices = &m_triangle->getVertexPtr(0);
+
+       btScalar radius = m_sphere->getRadius();
+       btScalar radiusWithThreshold = radius + contactBreakingThreshold;
+
+       btVector3 normal = (vertices[1] - vertices[0]).cross(vertices[2] - vertices[0]);
+
+       btScalar l2 = normal.length2();
+       bool hasContact = false;
+       btVector3 contactPoint;
+
+       if (l2 >= SIMD_EPSILON * SIMD_EPSILON)
+       {
+               normal /= btSqrt(l2);
+
+               btVector3 p1ToCentre = sphereCenter - vertices[0];
+               btScalar distanceFromPlane = p1ToCentre.dot(normal);
+
+               if (distanceFromPlane < btScalar(0.))
+               {
+                       //triangle facing the other way
+                       distanceFromPlane *= btScalar(-1.);
+                       normal *= btScalar(-1.);
+               }
+
+               bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
+
+               // Check for contact / intersection
+
+               if (isInsideContactPlane)
+               {
+                       if (facecontains(sphereCenter, vertices, normal))
+                       {
+                               // Inside the contact wedge - touches a point on the shell plane
+                               hasContact = true;
+                               contactPoint = sphereCenter - normal * distanceFromPlane;
+                       }
+                       else
+                       {
+                               // Could be inside one of the contact capsules
+                               btScalar contactCapsuleRadiusSqr = radiusWithThreshold * radiusWithThreshold;
+                               btScalar minDistSqr = contactCapsuleRadiusSqr;
+                               btVector3 nearestOnEdge;
+                               for (int i = 0; i < m_triangle->getNumEdges(); i++)
+                               {
+                                       btVector3 pa;
+                                       btVector3 pb;
+
+                                       m_triangle->getEdge(i, pa, pb);
+
+                                       btScalar distanceSqr = SegmentSqrDistance(pa, pb, sphereCenter, nearestOnEdge);
+                                       if (distanceSqr < minDistSqr)
+                                       {
+                                               // Yep, we're inside a capsule, and record the capsule with smallest distance
+                                               minDistSqr = distanceSqr;
+                                               hasContact = true;
+                                               contactPoint = nearestOnEdge;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (hasContact)
+       {
+               btVector3 contactToCentre = sphereCenter - contactPoint;
+               btScalar distanceSqr = contactToCentre.length2();
+
+               if (distanceSqr < radiusWithThreshold * radiusWithThreshold)
+               {
+                       if (distanceSqr > SIMD_EPSILON)
+                       {
+                               btScalar distance = btSqrt(distanceSqr);
+                               resultNormal = contactToCentre;
+                               resultNormal.normalize();
+                               point = contactPoint;
+                               depth = -(radius - distance);
+                       }
+                       else
+                       {
+                               resultNormal = normal;
+                               point = contactPoint;
+                               depth = -radius;
+                       }
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3& normal, btVector3* p)
+{
+       const btVector3* p1 = &vertices[0];
+       const btVector3* p2 = &vertices[1];
+       const btVector3* p3 = &vertices[2];
+
+       btVector3 edge1(*p2 - *p1);
+       btVector3 edge2(*p3 - *p2);
+       btVector3 edge3(*p1 - *p3);
+
+       btVector3 p1_to_p(*p - *p1);
+       btVector3 p2_to_p(*p - *p2);
+       btVector3 p3_to_p(*p - *p3);
+
+       btVector3 edge1_normal(edge1.cross(normal));
+       btVector3 edge2_normal(edge2.cross(normal));
+       btVector3 edge3_normal(edge3.cross(normal));
+
+       btScalar r1, r2, r3;
+       r1 = edge1_normal.dot(p1_to_p);
+       r2 = edge2_normal.dot(p2_to_p);
+       r3 = edge3_normal.dot(p3_to_p);
+       if ((r1 > 0 && r2 > 0 && r3 > 0) ||
+               (r1 <= 0 && r2 <= 0 && r3 <= 0))
+               return true;
+       return false;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
new file mode 100644 (file)
index 0000000..01ebfe4
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SPHERE_TRIANGLE_DETECTOR_H
+#define BT_SPHERE_TRIANGLE_DETECTOR_H
+
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+class btSphereShape;
+class btTriangleShape;
+
+/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
+struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
+{
+       virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
+
+       SphereTriangleDetector(btSphereShape* sphere, btTriangleShape* triangle, btScalar contactBreakingThreshold);
+
+       virtual ~SphereTriangleDetector(){};
+
+       bool collide(const btVector3& sphereCenter, btVector3& point, btVector3& resultNormal, btScalar& depth, btScalar& timeOfImpact, btScalar contactBreakingThreshold);
+
+private:
+       bool pointInTriangle(const btVector3 vertices[], const btVector3& normal, btVector3* p);
+       bool facecontains(const btVector3& p, const btVector3* vertices, btVector3& normal);
+
+       btSphereShape* m_sphere;
+       btTriangleShape* m_triangle;
+       btScalar m_contactBreakingThreshold;
+};
+#endif  //BT_SPHERE_TRIANGLE_DETECTOR_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..ac5de45
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+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 "btActivatingCollisionAlgorithm.h"
+#include "btCollisionDispatcher.h"
+#include "btCollisionObject.h"
+
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+       : btCollisionAlgorithm(ci)
+//,
+//m_colObj0(0),
+//m_colObj1(0)
+{
+}
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper*, const btCollisionObjectWrapper*)
+       : btCollisionAlgorithm(ci)
+//,
+//m_colObj0(0),
+//m_colObj1(0)
+{
+       //      if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
+       //      {
+       //              m_colObj0 = colObj0;
+       //              m_colObj1 = colObj1;
+       //
+       //              m_colObj0->activate();
+       //              m_colObj1->activate();
+       //      }
+}
+
+btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm()
+{
+       //              m_colObj0->activate();
+       //              m_colObj1->activate();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..8620605
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+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.
+*/
+
+#ifndef __BT_ACTIVATING_COLLISION_ALGORITHM_H
+#define __BT_ACTIVATING_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+///This class is not enabled yet (work-in-progress) to more aggressively activate objects.
+class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
+{
+       //      btCollisionObject* m_colObj0;
+       //      btCollisionObject* m_colObj1;
+
+protected:
+       btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
+
+       btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
+
+public:
+       virtual ~btActivatingCollisionAlgorithm();
+};
+#endif  //__BT_ACTIVATING_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..6873a95
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+* The b2CollidePolygons routines are Copyright (c) 2006-2007 Erin Catto http://www.gphysics.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.
+*/
+
+///btBox2dBox2dCollisionAlgorithm, with modified b2CollidePolygons routines from the Box2D library.
+///The modifications include: switching from b2Vec to btVector3, redefinition of b2Dot, b2Cross
+
+#include "btBox2dBox2dCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h"
+#include "BulletCollision/CollisionShapes/btBox2dShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* obj0Wrap, const btCollisionObjectWrapper* obj1Wrap)
+       : btActivatingCollisionAlgorithm(ci, obj0Wrap, obj1Wrap),
+         m_ownManifold(false),
+         m_manifoldPtr(mf)
+{
+       if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(), obj1Wrap->getCollisionObject()))
+       {
+               m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(), obj1Wrap->getCollisionObject());
+               m_ownManifold = true;
+       }
+}
+
+btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm()
+{
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr)
+                       m_dispatcher->releaseManifold(m_manifoldPtr);
+       }
+}
+
+void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
+
+//#include <stdio.h>
+void btBox2dBox2dCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       if (!m_manifoldPtr)
+               return;
+
+       const btBox2dShape* box0 = (const btBox2dShape*)body0Wrap->getCollisionShape();
+       const btBox2dShape* box1 = (const btBox2dShape*)body1Wrap->getCollisionShape();
+
+       resultOut->setPersistentManifold(m_manifoldPtr);
+
+       b2CollidePolygons(resultOut, box0, body0Wrap->getWorldTransform(), box1, body1Wrap->getWorldTransform());
+
+       //  refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
+       if (m_ownManifold)
+       {
+               resultOut->refreshContactPoints();
+       }
+}
+
+btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
+{
+       //not yet
+       return 1.f;
+}
+
+struct ClipVertex
+{
+       btVector3 v;
+       int id;
+       //b2ContactID id;
+       //b2ContactID id;
+};
+
+#define b2Dot(a, b) (a).dot(b)
+#define b2Mul(a, b) (a) * (b)
+#define b2MulT(a, b) (a).transpose() * (b)
+#define b2Cross(a, b) (a).cross(b)
+#define btCrossS(a, s) btVector3(s* a.getY(), -s* a.getX(), 0.f)
+
+int b2_maxManifoldPoints = 2;
+
+static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
+                                                        const btVector3& normal, btScalar offset)
+{
+       // Start with no output points
+       int numOut = 0;
+
+       // Calculate the distance of end points to the line
+       btScalar distance0 = b2Dot(normal, vIn[0].v) - offset;
+       btScalar distance1 = b2Dot(normal, vIn[1].v) - offset;
+
+       // If the points are behind the plane
+       if (distance0 <= 0.0f) vOut[numOut++] = vIn[0];
+       if (distance1 <= 0.0f) vOut[numOut++] = vIn[1];
+
+       // If the points are on different sides of the plane
+       if (distance0 * distance1 < 0.0f)
+       {
+               // Find intersection point of edge and plane
+               btScalar interp = distance0 / (distance0 - distance1);
+               vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
+               if (distance0 > 0.0f)
+               {
+                       vOut[numOut].id = vIn[0].id;
+               }
+               else
+               {
+                       vOut[numOut].id = vIn[1].id;
+               }
+               ++numOut;
+       }
+
+       return numOut;
+}
+
+// Find the separation between poly1 and poly2 for a give edge normal on poly1.
+static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1,
+                                                          const btBox2dShape* poly2, const btTransform& xf2)
+{
+       const btVector3* vertices1 = poly1->getVertices();
+       const btVector3* normals1 = poly1->getNormals();
+
+       int count2 = poly2->getVertexCount();
+       const btVector3* vertices2 = poly2->getVertices();
+
+       btAssert(0 <= edge1 && edge1 < poly1->getVertexCount());
+
+       // Convert normal from poly1's frame into poly2's frame.
+       btVector3 normal1World = b2Mul(xf1.getBasis(), normals1[edge1]);
+       btVector3 normal1 = b2MulT(xf2.getBasis(), normal1World);
+
+       // Find support vertex on poly2 for -normal.
+       int index = 0;
+       btScalar minDot = BT_LARGE_FLOAT;
+
+       if (count2 > 0)
+               index = (int)normal1.minDot(vertices2, count2, minDot);
+
+       btVector3 v1 = b2Mul(xf1, vertices1[edge1]);
+       btVector3 v2 = b2Mul(xf2, vertices2[index]);
+       btScalar separation = b2Dot(v2 - v1, normal1World);
+       return separation;
+}
+
+// Find the max separation between poly1 and poly2 using edge normals from poly1.
+static btScalar FindMaxSeparation(int* edgeIndex,
+                                                                 const btBox2dShape* poly1, const btTransform& xf1,
+                                                                 const btBox2dShape* poly2, const btTransform& xf2)
+{
+       int count1 = poly1->getVertexCount();
+       const btVector3* normals1 = poly1->getNormals();
+
+       // Vector pointing from the centroid of poly1 to the centroid of poly2.
+       btVector3 d = b2Mul(xf2, poly2->getCentroid()) - b2Mul(xf1, poly1->getCentroid());
+       btVector3 dLocal1 = b2MulT(xf1.getBasis(), d);
+
+       // Find edge normal on poly1 that has the largest projection onto d.
+       int edge = 0;
+       btScalar maxDot;
+       if (count1 > 0)
+               edge = (int)dLocal1.maxDot(normals1, count1, maxDot);
+
+       // Get the separation for the edge normal.
+       btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
+       if (s > 0.0f)
+       {
+               return s;
+       }
+
+       // Check the separation for the previous edge normal.
+       int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1;
+       btScalar sPrev = EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2);
+       if (sPrev > 0.0f)
+       {
+               return sPrev;
+       }
+
+       // Check the separation for the next edge normal.
+       int nextEdge = edge + 1 < count1 ? edge + 1 : 0;
+       btScalar sNext = EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2);
+       if (sNext > 0.0f)
+       {
+               return sNext;
+       }
+
+       // Find the best edge and the search direction.
+       int bestEdge;
+       btScalar bestSeparation;
+       int increment;
+       if (sPrev > s && sPrev > sNext)
+       {
+               increment = -1;
+               bestEdge = prevEdge;
+               bestSeparation = sPrev;
+       }
+       else if (sNext > s)
+       {
+               increment = 1;
+               bestEdge = nextEdge;
+               bestSeparation = sNext;
+       }
+       else
+       {
+               *edgeIndex = edge;
+               return s;
+       }
+
+       // Perform a local search for the best edge normal.
+       for (;;)
+       {
+               if (increment == -1)
+                       edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
+               else
+                       edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;
+
+               s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
+               if (s > 0.0f)
+               {
+                       return s;
+               }
+
+               if (s > bestSeparation)
+               {
+                       bestEdge = edge;
+                       bestSeparation = s;
+               }
+               else
+               {
+                       break;
+               }
+       }
+
+       *edgeIndex = bestEdge;
+       return bestSeparation;
+}
+
+static void FindIncidentEdge(ClipVertex c[2],
+                                                        const btBox2dShape* poly1, const btTransform& xf1, int edge1,
+                                                        const btBox2dShape* poly2, const btTransform& xf2)
+{
+       const btVector3* normals1 = poly1->getNormals();
+
+       int count2 = poly2->getVertexCount();
+       const btVector3* vertices2 = poly2->getVertices();
+       const btVector3* normals2 = poly2->getNormals();
+
+       btAssert(0 <= edge1 && edge1 < poly1->getVertexCount());
+
+       // Get the normal of the reference edge in poly2's frame.
+       btVector3 normal1 = b2MulT(xf2.getBasis(), b2Mul(xf1.getBasis(), normals1[edge1]));
+
+       // Find the incident edge on poly2.
+       int index = 0;
+       btScalar minDot = BT_LARGE_FLOAT;
+       for (int i = 0; i < count2; ++i)
+       {
+               btScalar dot = b2Dot(normal1, normals2[i]);
+               if (dot < minDot)
+               {
+                       minDot = dot;
+                       index = i;
+               }
+       }
+
+       // Build the clip vertices for the incident edge.
+       int i1 = index;
+       int i2 = i1 + 1 < count2 ? i1 + 1 : 0;
+
+       c[0].v = b2Mul(xf2, vertices2[i1]);
+       //      c[0].id.features.referenceEdge = (unsigned char)edge1;
+       //      c[0].id.features.incidentEdge = (unsigned char)i1;
+       //      c[0].id.features.incidentVertex = 0;
+
+       c[1].v = b2Mul(xf2, vertices2[i2]);
+       //      c[1].id.features.referenceEdge = (unsigned char)edge1;
+       //      c[1].id.features.incidentEdge = (unsigned char)i2;
+       //      c[1].id.features.incidentVertex = 1;
+}
+
+// Find edge normal of max separation on A - return if separating axis is found
+// Find edge normal of max separation on B - return if separation axis is found
+// Choose reference edge as min(minA, minB)
+// Find incident edge
+// Clip
+
+// The normal points from 1 to 2
+void b2CollidePolygons(btManifoldResult* manifold,
+                                          const btBox2dShape* polyA, const btTransform& xfA,
+                                          const btBox2dShape* polyB, const btTransform& xfB)
+{
+       int edgeA = 0;
+       btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB);
+       if (separationA > 0.0f)
+               return;
+
+       int edgeB = 0;
+       btScalar separationB = FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA);
+       if (separationB > 0.0f)
+               return;
+
+       const btBox2dShape* poly1;  // reference poly
+       const btBox2dShape* poly2;  // incident poly
+       btTransform xf1, xf2;
+       int edge1;  // reference edge
+       unsigned char flip;
+       const btScalar k_relativeTol = 0.98f;
+       const btScalar k_absoluteTol = 0.001f;
+
+       // TODO_ERIN use "radius" of poly for absolute tolerance.
+       if (separationB > k_relativeTol * separationA + k_absoluteTol)
+       {
+               poly1 = polyB;
+               poly2 = polyA;
+               xf1 = xfB;
+               xf2 = xfA;
+               edge1 = edgeB;
+               flip = 1;
+       }
+       else
+       {
+               poly1 = polyA;
+               poly2 = polyB;
+               xf1 = xfA;
+               xf2 = xfB;
+               edge1 = edgeA;
+               flip = 0;
+       }
+
+       ClipVertex incidentEdge[2];
+       FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
+
+       int count1 = poly1->getVertexCount();
+       const btVector3* vertices1 = poly1->getVertices();
+
+       btVector3 v11 = vertices1[edge1];
+       btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1 + 1] : vertices1[0];
+
+       //btVector3 dv = v12 - v11;
+       btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11);
+       sideNormal.normalize();
+       btVector3 frontNormal = btCrossS(sideNormal, 1.0f);
+
+       v11 = b2Mul(xf1, v11);
+       v12 = b2Mul(xf1, v12);
+
+       btScalar frontOffset = b2Dot(frontNormal, v11);
+       btScalar sideOffset1 = -b2Dot(sideNormal, v11);
+       btScalar sideOffset2 = b2Dot(sideNormal, v12);
+
+       // Clip incident edge against extruded edge1 side edges.
+       ClipVertex clipPoints1[2];
+       clipPoints1[0].v.setValue(0, 0, 0);
+       clipPoints1[1].v.setValue(0, 0, 0);
+
+       ClipVertex clipPoints2[2];
+       clipPoints2[0].v.setValue(0, 0, 0);
+       clipPoints2[1].v.setValue(0, 0, 0);
+
+       int np;
+
+       // Clip to box side 1
+       np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1);
+
+       if (np < 2)
+               return;
+
+       // Clip to negative box side 1
+       np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2);
+
+       if (np < 2)
+       {
+               return;
+       }
+
+       // Now clipPoints2 contains the clipped points.
+       btVector3 manifoldNormal = flip ? -frontNormal : frontNormal;
+
+       int pointCount = 0;
+       for (int i = 0; i < b2_maxManifoldPoints; ++i)
+       {
+               btScalar separation = b2Dot(frontNormal, clipPoints2[i].v) - frontOffset;
+
+               if (separation <= 0.0f)
+               {
+                       //b2ManifoldPoint* cp = manifold->points + pointCount;
+                       //btScalar separation = separation;
+                       //cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v);
+                       //cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v);
+
+                       manifold->addContactPoint(-manifoldNormal, clipPoints2[i].v, separation);
+
+                       //                      cp->id = clipPoints2[i].id;
+                       //                      cp->id.features.flip = flip;
+                       ++pointCount;
+               }
+       }
+
+       //      manifold->pointCount = pointCount;}
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..f14fdc0
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+#define BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+
+///box-box collision detection
+class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+       bool m_ownManifold;
+       btPersistentManifold* m_manifoldPtr;
+
+public:
+       btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+               : btActivatingCollisionAlgorithm(ci) {}
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
+
+       virtual ~btBox2dBox2dCollisionAlgorithm();
+
+       virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+       {
+               if (m_manifoldPtr && m_ownManifold)
+               {
+                       manifoldArray.push_back(m_manifoldPtr);
+               }
+       }
+
+       struct CreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm);
+                       void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+                       return new (ptr) btBox2dBox2dCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
+               }
+       };
+};
+
+#endif  //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..39807fc
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+#define USE_PERSISTENT_CONTACTS 1
+
+btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+       : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+         m_ownManifold(false),
+         m_manifoldPtr(mf)
+{
+       if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject()))
+       {
+               m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
+               m_ownManifold = true;
+       }
+}
+
+btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
+{
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr)
+                       m_dispatcher->releaseManifold(m_manifoldPtr);
+       }
+}
+
+void btBoxBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       if (!m_manifoldPtr)
+               return;
+
+       const btBoxShape* box0 = (btBoxShape*)body0Wrap->getCollisionShape();
+       const btBoxShape* box1 = (btBoxShape*)body1Wrap->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 = BT_LARGE_FLOAT;
+       input.m_transformA = body0Wrap->getWorldTransform();
+       input.m_transformB = body1Wrap->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/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..d657242
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_BOX_BOX__COLLISION_ALGORITHM_H
+#define BT_BOX_BOX__COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.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 btActivatingCollisionAlgorithm
+{
+       bool m_ownManifold;
+       btPersistentManifold* m_manifoldPtr;
+
+public:
+       btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+               : btActivatingCollisionAlgorithm(ci) {}
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       btBoxBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
+
+       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, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
+                       void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+                       return new (ptr) btBoxBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
+               }
+       };
+};
+
+#endif  //BT_BOX_BOX__COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
new file mode 100644 (file)
index 0000000..4b51646
--- /dev/null
@@ -0,0 +1,767 @@
+/*
+ * 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  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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(const btBoxShape* box1, const 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];
+               if (btFabs(a + q) > SIMD_EPSILON)
+               {
+                       a = 1.f / (btScalar(3.0) * (a + q));
+               }
+               else
+               {
+                       a = BT_LARGE_FLOAT;
+               }
+               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;
+
+               *iret = i0;  // iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0
+
+               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;
+                               }
+                       }
+               }
+#if defined(DEBUG) || defined(_DEBUG)
+               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(0.f, 0.f, 0.f);
+       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 > SIMD_EPSILON) return 0;                     \
+       l = btSqrt((n1) * (n1) + (n2) * (n2) + (n3) * (n3)); \
+       if (l > SIMD_EPSILON)                                \
+       {                                                    \
+               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);                                 \
+               }                                                \
+       }
+
+       btScalar fudge2(1.0e-5f);
+
+       Q11 += fudge2;
+       Q12 += fudge2;
+       Q13 += fudge2;
+
+       Q21 += fudge2;
+       Q22 += fudge2;
+       Q23 += fudge2;
+
+       Q31 += fudge2;
+       Q32 += fudge2;
+       Q33 += fudge2;
+
+       // 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)
+       {
+               if (code < 4)
+               {
+                       // we have less contacts than we need, so we use them all
+                       for (j = 0; j < cnum; 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 less contacts than we need, so we use them all
+                       for (j = 0; j < cnum; j++)
+                       {
+                               btVector3 pointInWorld;
+                               for (i = 0; i < 3; i++)
+                                       pointInWorld[i] = point[j * 3 + i] + pa[i] - normal[i] * dep[j];
+                               //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];
+                       if (code < 4)
+                       {
+                               output.addContactPoint(-normal, posInWorld, -dep[iret[j]]);
+                       }
+                       else
+                       {
+                               output.addContactPoint(-normal, posInWorld - normal * dep[iret[j]], -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/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
new file mode 100644 (file)
index 0000000..9b1b36b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_BOX_BOX_DETECTOR_H
+#define BT_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
+{
+       const btBoxShape* m_box1;
+       const btBoxShape* m_box2;
+
+public:
+       btBoxBoxDetector(const btBoxShape* box1, const 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/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
new file mode 100644 (file)
index 0000000..3f578d6
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 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 btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
+
+       virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
+};
+
+#endif  //BT_COLLISION_CONFIGURATION
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
new file mode 100644 (file)
index 0000000..597f260
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CREATE_FUNC
+#define BT_COLLISION_CREATE_FUNC
+
+#include "LinearMath/btAlignedObjectArray.h"
+class btCollisionAlgorithm;
+class btCollisionObject;
+struct btCollisionObjectWrapper;
+struct btCollisionAlgorithmConstructionInfo;
+
+///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm
+struct btCollisionAlgorithmCreateFunc
+{
+       bool m_swapped;
+
+       btCollisionAlgorithmCreateFunc()
+               : m_swapped(false)
+       {
+       }
+       virtual ~btCollisionAlgorithmCreateFunc(){};
+
+       virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo&, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+       {
+               (void)body0Wrap;
+               (void)body1Wrap;
+               return 0;
+       }
+};
+#endif  //BT_COLLISION_CREATE_FUNC
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
new file mode 100644 (file)
index 0000000..e24757c
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionDispatcher.h"
+#include "LinearMath/btQuickprof.h"
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btPoolAllocator.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+#ifdef BT_DEBUG
+#include <stdio.h>
+#endif
+
+btCollisionDispatcher::btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration) : m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
+                                                                                                                                                                                                m_collisionConfiguration(collisionConfiguration)
+{
+       int i;
+
+       setNearCallback(defaultNearCallback);
+
+       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_doubleDispatchContactPoints[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i, j);
+                       btAssert(m_doubleDispatchContactPoints[i][j]);
+                       m_doubleDispatchClosestPoints[i][j] = m_collisionConfiguration->getClosestPointsAlgorithmCreateFunc(i, j);
+               }
+       }
+}
+
+void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
+{
+       m_doubleDispatchContactPoints[proxyType0][proxyType1] = createFunc;
+}
+
+void btCollisionDispatcher::registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
+{
+       m_doubleDispatchClosestPoints[proxyType0][proxyType1] = createFunc;
+}
+
+btCollisionDispatcher::~btCollisionDispatcher()
+{
+}
+
+btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       //btAssert(gNumManifold < 65535);
+
+       //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
+
+       btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
+                                                                                                                                                                                                                                                               : gContactBreakingThreshold;
+
+       btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
+
+       void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
+       if (NULL == mem)
+       {
+               //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
+               if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
+               {
+                       mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
+               }
+               else
+               {
+                       btAssert(0);
+                       //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
+                       return 0;
+               }
+       }
+       btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
+       manifold->m_index1a = m_manifoldsPtr.size();
+       m_manifoldsPtr.push_back(manifold);
+
+       return manifold;
+}
+
+void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
+{
+       manifold->clearManifold();
+}
+
+void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
+{
+       //printf("releaseManifold: gNumManifold %d\n",gNumManifold);
+       clearManifold(manifold);
+
+       int findIndex = manifold->m_index1a;
+       btAssert(findIndex < m_manifoldsPtr.size());
+       m_manifoldsPtr.swap(findIndex, m_manifoldsPtr.size() - 1);
+       m_manifoldsPtr[findIndex]->m_index1a = findIndex;
+       m_manifoldsPtr.pop_back();
+
+       manifold->~btPersistentManifold();
+       if (m_persistentManifoldPoolAllocator->validPtr(manifold))
+       {
+               m_persistentManifoldPoolAllocator->freeMemory(manifold);
+       }
+       else
+       {
+               btAlignedFree(manifold);
+       }
+}
+
+btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType algoType)
+{
+       btCollisionAlgorithmConstructionInfo ci;
+
+       ci.m_dispatcher1 = this;
+       ci.m_manifold = sharedManifold;
+       btCollisionAlgorithm* algo = 0;
+       if (algoType == BT_CONTACT_POINT_ALGORITHMS)
+       {
+               algo = m_doubleDispatchContactPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
+       }
+       else
+       {
+               algo = m_doubleDispatchClosestPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
+       }
+
+       return algo;
+}
+
+bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       //here you can do filtering
+       bool hasResponse =
+               (body0->hasContactResponse() && body1->hasContactResponse());
+       //no response between two static/kinematic bodies:
+       hasResponse = hasResponse &&
+                                 ((!body0->isStaticOrKinematicObject()) || (!body1->isStaticOrKinematicObject()));
+       return hasResponse;
+}
+
+bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       btAssert(body0);
+       btAssert(body1);
+
+       bool needsCollision = true;
+
+#ifdef BT_DEBUG
+       if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED))
+       {
+               //broadphase filtering already deals with this
+               if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject())
+               {
+                       m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED;
+                       printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
+               }
+       }
+#endif  //BT_DEBUG
+
+       if ((!body0->isActive()) && (!body1->isActive()))
+               needsCollision = false;
+       else if ((!body0->checkCollideWith(body1)) || (!body1->checkCollideWith(body0)))
+               needsCollision = false;
+
+       return needsCollision;
+}
+
+///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
+///this is useful for the collision dispatcher.
+class btCollisionPairCallback : public btOverlapCallback
+{
+       const btDispatcherInfo& m_dispatchInfo;
+       btCollisionDispatcher* m_dispatcher;
+
+public:
+       btCollisionPairCallback(const btDispatcherInfo& dispatchInfo, btCollisionDispatcher* dispatcher)
+               : m_dispatchInfo(dispatchInfo),
+                 m_dispatcher(dispatcher)
+       {
+       }
+
+       /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
+       {
+               m_dispatchInfo = other.m_dispatchInfo;
+               m_dispatcher = other.m_dispatcher;
+               return *this;
+       }
+       */
+
+       virtual ~btCollisionPairCallback() {}
+
+       virtual bool processOverlap(btBroadphasePair& pair)
+       {
+               (*m_dispatcher->getNearCallback())(pair, *m_dispatcher, m_dispatchInfo);
+               return false;
+       }
+};
+
+void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher)
+{
+       //m_blockedForChanges = true;
+
+       btCollisionPairCallback collisionCallback(dispatchInfo, this);
+
+       {
+               BT_PROFILE("processAllOverlappingPairs");
+               pairCache->processAllOverlappingPairs(&collisionCallback, dispatcher, dispatchInfo);
+       }
+
+       //m_blockedForChanges = false;
+}
+
+//by default, Bullet will use this near callback
+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;
+
+       if (dispatcher.needsCollision(colObj0, colObj1))
+       {
+               btCollisionObjectWrapper obj0Wrap(0, colObj0->getCollisionShape(), colObj0, colObj0->getWorldTransform(), -1, -1);
+               btCollisionObjectWrapper obj1Wrap(0, colObj1->getCollisionShape(), colObj1, colObj1->getWorldTransform(), -1, -1);
+
+               //dispatcher will keep algorithms persistent in the collision pair
+               if (!collisionPair.m_algorithm)
+               {
+                       collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap, &obj1Wrap, 0, BT_CONTACT_POINT_ALGORITHMS);
+               }
+
+               if (collisionPair.m_algorithm)
+               {
+                       btManifoldResult contactPointResult(&obj0Wrap, &obj1Wrap);
+
+                       if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
+                       {
+                               //discrete collision detection query
+
+                               collisionPair.m_algorithm->processCollision(&obj0Wrap, &obj1Wrap, dispatchInfo, &contactPointResult);
+                       }
+                       else
+                       {
+                               //continuous collision detection query, time of impact (toi)
+                               btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0, colObj1, dispatchInfo, &contactPointResult);
+                               if (dispatchInfo.m_timeOfImpact > toi)
+                                       dispatchInfo.m_timeOfImpact = toi;
+                       }
+               }
+       }
+}
+
+void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
+{
+       void* mem = m_collisionAlgorithmPoolAllocator->allocate(size);
+       if (NULL == mem)
+       {
+               //warn user for overflow?
+               return btAlignedAlloc(static_cast<size_t>(size), 16);
+       }
+       return mem;
+}
+
+void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
+{
+       if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
+       {
+               m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
+       }
+       else
+       {
+               btAlignedFree(ptr);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
new file mode 100644 (file)
index 0000000..1399148
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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__DISPATCHER_H
+#define BT_COLLISION__DISPATCHER_H
+
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+class btIDebugDraw;
+class btOverlappingPairCache;
+class btPoolAllocator;
+class btCollisionConfiguration;
+
+#include "btCollisionCreateFunc.h"
+
+#define USE_DISPATCH_REGISTRY_ARRAY 1
+
+class btCollisionDispatcher;
+///user can override this nearcallback for collision filtering and more finegrained control over collision detection
+typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
+
+///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
+///Time of Impact, Closest Points and Penetration Depth.
+class btCollisionDispatcher : public btDispatcher
+{
+protected:
+       int m_dispatcherFlags;
+
+       btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
+
+       btNearCallback m_nearCallback;
+
+       btPoolAllocator* m_collisionAlgorithmPoolAllocator;
+
+       btPoolAllocator* m_persistentManifoldPoolAllocator;
+
+       btCollisionAlgorithmCreateFunc* m_doubleDispatchContactPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
+
+       btCollisionAlgorithmCreateFunc* m_doubleDispatchClosestPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
+
+       btCollisionConfiguration* m_collisionConfiguration;
+
+public:
+       enum DispatcherFlags
+       {
+               CD_STATIC_STATIC_REPORTED = 1,
+               CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD = 2,
+               CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION = 4
+       };
+
+       int getDispatcherFlags() const
+       {
+               return m_dispatcherFlags;
+       }
+
+       void setDispatcherFlags(int flags)
+       {
+               m_dispatcherFlags = flags;
+       }
+
+       ///registerCollisionCreateFunc allows registration of custom/alternative collision create functions
+       void registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
+
+       void registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
+
+       int getNumManifolds() const
+       {
+               return int(m_manifoldsPtr.size());
+       }
+
+       btPersistentManifold** getInternalManifoldPointer()
+       {
+               return m_manifoldsPtr.size() ? &m_manifoldsPtr[0] : 0;
+       }
+
+       btPersistentManifold* getManifoldByIndexInternal(int index)
+       {
+               btAssert(index>=0);
+               btAssert(index<m_manifoldsPtr.size());
+               return m_manifoldsPtr[index];
+       }
+
+       const btPersistentManifold* getManifoldByIndexInternal(int index) const
+       {
+               btAssert(index>=0);
+               btAssert(index<m_manifoldsPtr.size());
+               return m_manifoldsPtr[index];
+       }
+
+       btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration);
+
+       virtual ~btCollisionDispatcher();
+
+       virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0, const btCollisionObject* b1);
+
+       virtual void releaseManifold(btPersistentManifold* manifold);
+
+       virtual void clearManifold(btPersistentManifold* manifold);
+
+       btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType);
+
+       virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1);
+
+       virtual bool needsResponse(const btCollisionObject* body0, const btCollisionObject* body1);
+
+       virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher);
+
+       void setNearCallback(btNearCallback nearCallback)
+       {
+               m_nearCallback = nearCallback;
+       }
+
+       btNearCallback getNearCallback() const
+       {
+               return m_nearCallback;
+       }
+
+       //by default, Bullet will use this near callback
+       static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, 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;
+       }
+
+       virtual btPoolAllocator* getInternalManifoldPool()
+       {
+               return m_persistentManifoldPoolAllocator;
+       }
+
+       virtual const btPoolAllocator* getInternalManifoldPool() const
+       {
+               return m_persistentManifoldPoolAllocator;
+       }
+};
+
+#endif  //BT_COLLISION__DISPATCHER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
new file mode 100644 (file)
index 0000000..9b38f5c
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btCollisionDispatcherMt.h"
+#include "LinearMath/btQuickprof.h"
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btPoolAllocator.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+btCollisionDispatcherMt::btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize)
+       : btCollisionDispatcher(config)
+{
+       m_batchManifoldsPtr.resize(btGetTaskScheduler()->getNumThreads());
+       m_batchReleasePtr.resize(btGetTaskScheduler()->getNumThreads());
+
+       m_batchUpdating = false;
+       m_grainSize = grainSize;  // iterations per task
+}
+
+btPersistentManifold* btCollisionDispatcherMt::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
+
+       btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
+                                                                                                                                                                                                                                                               : gContactBreakingThreshold;
+
+       btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
+
+       void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
+       if (NULL == mem)
+       {
+               //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
+               if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
+               {
+                       mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
+               }
+               else
+               {
+                       btAssert(0);
+                       //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
+                       return 0;
+               }
+       }
+       btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
+       if (!m_batchUpdating)
+       {
+               // batch updater will update manifold pointers array after finishing, so
+               // only need to update array when not batch-updating
+               //btAssert( !btThreadsAreRunning() );
+               manifold->m_index1a = m_manifoldsPtr.size();
+               m_manifoldsPtr.push_back(manifold);
+       }
+       else
+       {
+               m_batchManifoldsPtr[btGetCurrentThreadIndex()].push_back(manifold);
+       }
+
+       return manifold;
+}
+
+void btCollisionDispatcherMt::releaseManifold(btPersistentManifold* manifold)
+{
+       //btAssert( !btThreadsAreRunning() );
+       
+       if (!m_batchUpdating)
+       {
+               clearManifold(manifold);
+               // batch updater will update manifold pointers array after finishing, so
+               // only need to update array when not batch-updating
+               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();
+       } else {
+               m_batchReleasePtr[btGetCurrentThreadIndex()].push_back(manifold);
+               return;
+       }
+
+       manifold->~btPersistentManifold();
+       if (m_persistentManifoldPoolAllocator->validPtr(manifold))
+       {
+               m_persistentManifoldPoolAllocator->freeMemory(manifold);
+       }
+       else
+       {
+               btAlignedFree(manifold);
+       }
+}
+
+struct CollisionDispatcherUpdater : public btIParallelForBody
+{
+       btBroadphasePair* mPairArray;
+       btNearCallback mCallback;
+       btCollisionDispatcher* mDispatcher;
+       const btDispatcherInfo* mInfo;
+
+       CollisionDispatcherUpdater()
+       {
+               mPairArray = NULL;
+               mCallback = NULL;
+               mDispatcher = NULL;
+               mInfo = NULL;
+       }
+       void forLoop(int iBegin, int iEnd) const
+       {
+               for (int i = iBegin; i < iEnd; ++i)
+               {
+                       btBroadphasePair* pair = &mPairArray[i];
+                       mCallback(*pair, *mDispatcher, *mInfo);
+               }
+       }
+};
+
+void btCollisionDispatcherMt::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher)
+{
+       const int pairCount = pairCache->getNumOverlappingPairs();
+       if (pairCount == 0)
+       {
+               return;
+       }
+       CollisionDispatcherUpdater updater;
+       updater.mCallback = getNearCallback();
+       updater.mPairArray = pairCache->getOverlappingPairArrayPtr();
+       updater.mDispatcher = this;
+       updater.mInfo = &info;
+
+       m_batchUpdating = true;
+       btParallelFor(0, pairCount, m_grainSize, updater);
+       m_batchUpdating = false;
+
+       // merge new manifolds, if any
+       for (int i = 0; i < m_batchManifoldsPtr.size(); ++i)
+       {
+               btAlignedObjectArray<btPersistentManifold*>& batchManifoldsPtr = m_batchManifoldsPtr[i];
+
+               for (int j = 0; j < batchManifoldsPtr.size(); ++j)
+               {
+                       m_manifoldsPtr.push_back(batchManifoldsPtr[j]);
+               }
+
+               batchManifoldsPtr.resizeNoInitialize(0);
+       }
+
+       // remove batched remove manifolds.
+       for (int i = 0; i < m_batchReleasePtr.size(); ++i)
+       {
+               btAlignedObjectArray<btPersistentManifold*>& batchManifoldsPtr = m_batchReleasePtr[i];
+               for (int j = 0; j < batchManifoldsPtr.size(); ++j)
+               {
+                       releaseManifold(batchManifoldsPtr[j]);
+               }
+               batchManifoldsPtr.resizeNoInitialize(0);
+       }
+
+       // update the indices (used when releasing manifolds)
+       for (int i = 0; i < m_manifoldsPtr.size(); ++i)
+       {
+               m_manifoldsPtr[i]->m_index1a = i;
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
new file mode 100644 (file)
index 0000000..094e928
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_DISPATCHER_MT_H
+#define BT_COLLISION_DISPATCHER_MT_H
+
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "LinearMath/btThreads.h"
+
+class btCollisionDispatcherMt : public btCollisionDispatcher
+{
+public:
+       btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize = 40);
+
+       virtual btPersistentManifold* getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1) BT_OVERRIDE;
+       virtual void releaseManifold(btPersistentManifold* manifold) BT_OVERRIDE;
+
+       virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher) BT_OVERRIDE;
+
+protected:
+       btAlignedObjectArray<btAlignedObjectArray<btPersistentManifold*> > m_batchManifoldsPtr;
+       btAlignedObjectArray<btAlignedObjectArray<btPersistentManifold*> > m_batchReleasePtr;
+       bool m_batchUpdating;
+       int m_grainSize;
+};
+
+#endif  //BT_COLLISION_DISPATCHER_MT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
new file mode 100644 (file)
index 0000000..04dbbf2
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionObject.h"
+#include "LinearMath/btSerializer.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+
+btCollisionObject::btCollisionObject()
+       : m_interpolationLinearVelocity(0.f, 0.f, 0.f),
+         m_interpolationAngularVelocity(0.f, 0.f, 0.f),
+         m_anisotropicFriction(1.f, 1.f, 1.f),
+         m_hasAnisotropicFriction(false),
+         m_contactProcessingThreshold(BT_LARGE_FLOAT),
+         m_broadphaseHandle(0),
+         m_collisionShape(0),
+         m_extensionPointer(0),
+         m_rootCollisionShape(0),
+         m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
+         m_islandTag1(-1),
+         m_companionId(-1),
+         m_worldArrayIndex(-1),
+         m_activationState1(1),
+         m_deactivationTime(btScalar(0.)),
+         m_friction(btScalar(0.5)),
+         m_restitution(btScalar(0.)),
+         m_rollingFriction(0.0f),
+         m_spinningFriction(0.f),
+         m_contactDamping(.1),
+         m_contactStiffness(BT_LARGE_FLOAT),
+         m_internalType(CO_COLLISION_OBJECT),
+         m_userObjectPointer(0),
+         m_userIndex2(-1),
+         m_userIndex(-1),
+         m_userIndex3(-1),
+         m_hitFraction(btScalar(1.)),
+         m_ccdSweptSphereRadius(btScalar(0.)),
+         m_ccdMotionThreshold(btScalar(0.)),
+         m_checkCollideWith(false),
+         m_updateRevision(0)
+{
+       m_worldTransform.setIdentity();
+       m_interpolationWorldTransform.setIdentity();
+}
+
+btCollisionObject::~btCollisionObject()
+{
+}
+
+void btCollisionObject::setActivationState(int newState) const
+{
+       if ((m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
+               m_activationState1 = newState;
+}
+
+void btCollisionObject::forceActivationState(int newState) const
+{
+       m_activationState1 = newState;
+}
+
+void btCollisionObject::activate(bool forceActivation) const
+{
+       if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT)))
+       {
+               setActivationState(ACTIVE_TAG);
+               m_deactivationTime = btScalar(0.);
+       }
+}
+
+const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer;
+
+       m_worldTransform.serialize(dataOut->m_worldTransform);
+       m_interpolationWorldTransform.serialize(dataOut->m_interpolationWorldTransform);
+       m_interpolationLinearVelocity.serialize(dataOut->m_interpolationLinearVelocity);
+       m_interpolationAngularVelocity.serialize(dataOut->m_interpolationAngularVelocity);
+       m_anisotropicFriction.serialize(dataOut->m_anisotropicFriction);
+       dataOut->m_hasAnisotropicFriction = m_hasAnisotropicFriction;
+       dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold;
+       dataOut->m_broadphaseHandle = 0;
+       dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape);
+       dataOut->m_rootCollisionShape = 0;  //@todo
+       dataOut->m_collisionFlags = m_collisionFlags;
+       dataOut->m_islandTag1 = m_islandTag1;
+       dataOut->m_companionId = m_companionId;
+       dataOut->m_activationState1 = m_activationState1;
+       dataOut->m_deactivationTime = m_deactivationTime;
+       dataOut->m_friction = m_friction;
+       dataOut->m_rollingFriction = m_rollingFriction;
+       dataOut->m_contactDamping = m_contactDamping;
+       dataOut->m_contactStiffness = m_contactStiffness;
+       dataOut->m_restitution = m_restitution;
+       dataOut->m_internalType = m_internalType;
+
+       char* name = (char*)serializer->findNameForPointer(this);
+       dataOut->m_name = (char*)serializer->getUniquePointer(name);
+       if (dataOut->m_name)
+       {
+               serializer->serializeName(name);
+       }
+       dataOut->m_hitFraction = m_hitFraction;
+       dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius;
+       dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
+       dataOut->m_checkCollideWith = m_checkCollideWith;
+       if (m_broadphaseHandle)
+       {
+               dataOut->m_collisionFilterGroup = m_broadphaseHandle->m_collisionFilterGroup;
+               dataOut->m_collisionFilterMask = m_broadphaseHandle->m_collisionFilterMask;
+               dataOut->m_uniqueId = m_broadphaseHandle->m_uniqueId;
+       }
+       else
+       {
+               dataOut->m_collisionFilterGroup = 0;
+               dataOut->m_collisionFilterMask = 0;
+               dataOut->m_uniqueId = -1;
+       }
+       return btCollisionObjectDataName;
+}
+
+void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const
+{
+       int len = calculateSerializeBufferSize();
+       btChunk* chunk = serializer->allocate(len, 1);
+       const char* structType = serialize(chunk->m_oldPtr, serializer);
+       serializer->finalizeChunk(chunk, structType, BT_COLLISIONOBJECT_CODE, (void*)this);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionObject.h
new file mode 100644 (file)
index 0000000..d1456a9
--- /dev/null
@@ -0,0 +1,690 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_OBJECT_H
+#define BT_COLLISION_OBJECT_H
+
+#include "LinearMath/btTransform.h"
+
+//island management, m_activationState1
+#define ACTIVE_TAG 1
+#define ISLAND_SLEEPING 2
+#define WANTS_DEACTIVATION 3
+#define DISABLE_DEACTIVATION 4
+#define DISABLE_SIMULATION 5
+#define FIXED_BASE_MULTI_BODY 6
+
+struct btBroadphaseProxy;
+class btCollisionShape;
+struct btCollisionShapeData;
+#include "LinearMath/btMotionState.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btCollisionObjectData btCollisionObjectDoubleData
+#define btCollisionObjectDataName "btCollisionObjectDoubleData"
+#else
+#define btCollisionObjectData btCollisionObjectFloatData
+#define btCollisionObjectDataName "btCollisionObjectFloatData"
+#endif
+
+/// btCollisionObject can be used to manage collision detection objects.
+/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
+/// They can be added to the btCollisionWorld.
+ATTRIBUTE_ALIGNED16(class)
+btCollisionObject
+{
+protected:
+       btTransform m_worldTransform;
+
+       ///m_interpolationWorldTransform is used for CCD and interpolation
+       ///it can be either previous or future (predicted) transform
+       btTransform m_interpolationWorldTransform;
+       //those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
+       //without destroying the continuous interpolated motion (which uses this interpolation velocities)
+       btVector3 m_interpolationLinearVelocity;
+       btVector3 m_interpolationAngularVelocity;
+
+       btVector3 m_anisotropicFriction;
+       int m_hasAnisotropicFriction;
+       btScalar m_contactProcessingThreshold;
+
+       btBroadphaseProxy* m_broadphaseHandle;
+       btCollisionShape* m_collisionShape;
+       ///m_extensionPointer is used by some internal low-level Bullet extensions.
+       void* m_extensionPointer;
+
+       ///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;
+
+       int m_islandTag1;
+       int m_companionId;
+       int m_worldArrayIndex;  // index of object in world's collisionObjects array
+
+       mutable int m_activationState1;
+       mutable btScalar m_deactivationTime;
+
+       btScalar m_friction;
+       btScalar m_restitution;
+       btScalar m_rollingFriction;   //torsional friction orthogonal to contact normal (useful to stop spheres rolling forever)
+       btScalar m_spinningFriction;  // torsional friction around the contact normal (useful for grasping)
+       btScalar m_contactDamping;
+       btScalar m_contactStiffness;
+
+       ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc.
+       ///do not assign your own m_internalType unless you write a new dynamics object class.
+       int m_internalType;
+
+       ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
+
+       void* m_userObjectPointer;
+
+       int m_userIndex2;
+
+       int m_userIndex;
+
+       int m_userIndex3;
+
+       ///time of impact calculation
+       btScalar m_hitFraction;
+
+       ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+       btScalar m_ccdSweptSphereRadius;
+
+       /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
+       btScalar m_ccdMotionThreshold;
+
+       /// If some object should have elaborate collision filtering by sub-classes
+       int m_checkCollideWith;
+
+       btAlignedObjectArray<const btCollisionObject*> m_objectsWithoutCollisionCheck;
+
+       ///internal update revision number. It will be increased when the object changes. This allows some subsystems to perform lazy evaluation.
+       int m_updateRevision;
+
+       btVector3 m_customDebugColorRGB;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       enum CollisionFlags
+       {
+               CF_DYNAMIC_OBJECT = 0,
+               CF_STATIC_OBJECT = 1,
+               CF_KINEMATIC_OBJECT = 2,
+               CF_NO_CONTACT_RESPONSE = 4,
+               CF_CUSTOM_MATERIAL_CALLBACK = 8,  //this allows per-triangle material (friction/restitution)
+               CF_CHARACTER_OBJECT = 16,
+               CF_DISABLE_VISUALIZE_OBJECT = 32,          //disable debug drawing
+               CF_DISABLE_SPU_COLLISION_PROCESSING = 64,  //disable parallel/SPU processing
+               CF_HAS_CONTACT_STIFFNESS_DAMPING = 128,
+               CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR = 256,
+               CF_HAS_FRICTION_ANCHOR = 512,
+               CF_HAS_COLLISION_SOUND_TRIGGER = 1024
+       };
+
+       enum CollisionObjectTypes
+       {
+               CO_COLLISION_OBJECT = 1,
+               CO_RIGID_BODY = 2,
+               ///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter
+               ///It is useful for collision sensors, explosion objects, character controller etc.
+               CO_GHOST_OBJECT = 4,
+               CO_SOFT_BODY = 8,
+               CO_HF_FLUID = 16,
+               CO_USER_TYPE = 32,
+               CO_FEATHERSTONE_LINK = 64
+       };
+
+       enum AnisotropicFrictionFlags
+       {
+               CF_ANISOTROPIC_FRICTION_DISABLED = 0,
+               CF_ANISOTROPIC_FRICTION = 1,
+               CF_ANISOTROPIC_ROLLING_FRICTION = 2
+       };
+
+       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);
+       }
+
+       const btVector3& getAnisotropicFriction() const
+       {
+               return m_anisotropicFriction;
+       }
+       void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
+       {
+               m_anisotropicFriction = anisotropicFriction;
+               bool isUnity = (anisotropicFriction[0] != 1.f) || (anisotropicFriction[1] != 1.f) || (anisotropicFriction[2] != 1.f);
+               m_hasAnisotropicFriction = isUnity ? frictionMode : 0;
+       }
+       bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
+       {
+               return (m_hasAnisotropicFriction & frictionMode) != 0;
+       }
+
+       ///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
+       ///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges
+       void setContactProcessingThreshold(btScalar contactProcessingThreshold)
+       {
+               m_contactProcessingThreshold = contactProcessingThreshold;
+       }
+       btScalar getContactProcessingThreshold() const
+       {
+               return m_contactProcessingThreshold;
+       }
+
+       SIMD_FORCE_INLINE bool isStaticObject() const
+       {
+               return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
+       }
+
+       SIMD_FORCE_INLINE bool isKinematicObject() const
+       {
+               return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
+       }
+
+       SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
+       {
+               return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0;
+       }
+
+       SIMD_FORCE_INLINE bool hasContactResponse() const
+       {
+               return (m_collisionFlags & CF_NO_CONTACT_RESPONSE) == 0;
+       }
+
+       btCollisionObject();
+
+       virtual ~btCollisionObject();
+
+       virtual void setCollisionShape(btCollisionShape * collisionShape)
+       {
+               m_updateRevision++;
+               m_collisionShape = collisionShape;
+               m_rootCollisionShape = collisionShape;
+       }
+
+       SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
+       {
+               return m_collisionShape;
+       }
+
+       SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
+       {
+               return m_collisionShape;
+       }
+
+       void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck)
+       {
+               if (ignoreCollisionCheck)
+               {
+                       //We don't check for duplicates. Is it ok to leave that up to the user of this API?
+                       //int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
+                       //if (index == m_objectsWithoutCollisionCheck.size())
+                       //{
+                       m_objectsWithoutCollisionCheck.push_back(co);
+                       //}
+               }
+               else
+               {
+                       m_objectsWithoutCollisionCheck.remove(co);
+               }
+               m_checkCollideWith = m_objectsWithoutCollisionCheck.size() > 0;
+       }
+
+        int getNumObjectsWithoutCollision() const
+       {
+               return m_objectsWithoutCollisionCheck.size();
+       }
+
+       const btCollisionObject* getObjectWithoutCollision(int index)
+       {
+               return m_objectsWithoutCollisionCheck[index];
+       }
+
+       virtual bool checkCollideWithOverride(const btCollisionObject* co) const
+       {
+               int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
+               if (index < m_objectsWithoutCollisionCheck.size())
+               {
+                       return false;
+               }
+               return true;
+       }
+
+       ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
+       ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
+       void* internalGetExtensionPointer() const
+       {
+               return m_extensionPointer;
+       }
+       ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions
+       ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
+       void internalSetExtensionPointer(void* pointer)
+       {
+               m_extensionPointer = pointer;
+       }
+
+       SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1; }
+
+       void setActivationState(int newState) const;
+
+       void setDeactivationTime(btScalar time)
+       {
+               m_deactivationTime = time;
+       }
+       btScalar getDeactivationTime() const
+       {
+               return m_deactivationTime;
+       }
+
+       void forceActivationState(int newState) const;
+
+       void activate(bool forceActivation = false) const;
+
+       SIMD_FORCE_INLINE bool isActive() const
+       {
+               return ((getActivationState() != FIXED_BASE_MULTI_BODY) && (getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION));
+       }
+
+       void setRestitution(btScalar rest)
+       {
+               m_updateRevision++;
+               m_restitution = rest;
+       }
+       btScalar getRestitution() const
+       {
+               return m_restitution;
+       }
+       void setFriction(btScalar frict)
+       {
+               m_updateRevision++;
+               m_friction = frict;
+       }
+       btScalar getFriction() const
+       {
+               return m_friction;
+       }
+
+       void setRollingFriction(btScalar frict)
+       {
+               m_updateRevision++;
+               m_rollingFriction = frict;
+       }
+       btScalar getRollingFriction() const
+       {
+               return m_rollingFriction;
+       }
+       void setSpinningFriction(btScalar frict)
+       {
+               m_updateRevision++;
+               m_spinningFriction = frict;
+       }
+       btScalar getSpinningFriction() const
+       {
+               return m_spinningFriction;
+       }
+       void setContactStiffnessAndDamping(btScalar stiffness, btScalar damping)
+       {
+               m_updateRevision++;
+               m_contactStiffness = stiffness;
+               m_contactDamping = damping;
+
+               m_collisionFlags |= CF_HAS_CONTACT_STIFFNESS_DAMPING;
+
+               //avoid divisions by zero...
+               if (m_contactStiffness < SIMD_EPSILON)
+               {
+                       m_contactStiffness = SIMD_EPSILON;
+               }
+       }
+
+       btScalar getContactStiffness() const
+       {
+               return m_contactStiffness;
+       }
+
+       btScalar getContactDamping() const
+       {
+               return m_contactDamping;
+       }
+
+       ///reserved for Bullet internal usage
+       int getInternalType() const
+       {
+               return m_internalType;
+       }
+
+       btTransform& getWorldTransform()
+       {
+               return m_worldTransform;
+       }
+
+       const btTransform& getWorldTransform() const
+       {
+               return m_worldTransform;
+       }
+
+       void setWorldTransform(const btTransform& worldTrans)
+       {
+               m_updateRevision++;
+               m_worldTransform = worldTrans;
+       }
+
+       SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle()
+       {
+               return m_broadphaseHandle;
+       }
+
+       SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const
+       {
+               return m_broadphaseHandle;
+       }
+
+       void setBroadphaseHandle(btBroadphaseProxy * handle)
+       {
+               m_broadphaseHandle = handle;
+       }
+
+       const btTransform& getInterpolationWorldTransform() const
+       {
+               return m_interpolationWorldTransform;
+       }
+
+       btTransform& getInterpolationWorldTransform()
+       {
+               return m_interpolationWorldTransform;
+       }
+
+       void setInterpolationWorldTransform(const btTransform& trans)
+       {
+               m_updateRevision++;
+               m_interpolationWorldTransform = trans;
+       }
+
+       void setInterpolationLinearVelocity(const btVector3& linvel)
+       {
+               m_updateRevision++;
+               m_interpolationLinearVelocity = linvel;
+       }
+
+       void setInterpolationAngularVelocity(const btVector3& angvel)
+       {
+               m_updateRevision++;
+               m_interpolationAngularVelocity = angvel;
+       }
+
+       const btVector3& getInterpolationLinearVelocity() const
+       {
+               return m_interpolationLinearVelocity;
+       }
+
+       const btVector3& getInterpolationAngularVelocity() const
+       {
+               return m_interpolationAngularVelocity;
+       }
+
+       SIMD_FORCE_INLINE int getIslandTag() const
+       {
+               return m_islandTag1;
+       }
+
+       void setIslandTag(int tag)
+       {
+               m_islandTag1 = tag;
+       }
+
+       SIMD_FORCE_INLINE int getCompanionId() const
+       {
+               return m_companionId;
+       }
+
+       void setCompanionId(int id)
+       {
+               m_companionId = id;
+       }
+
+       SIMD_FORCE_INLINE int getWorldArrayIndex() const
+       {
+               return m_worldArrayIndex;
+       }
+
+       // only should be called by CollisionWorld
+       void setWorldArrayIndex(int ix)
+       {
+               m_worldArrayIndex = ix;
+       }
+
+       SIMD_FORCE_INLINE btScalar getHitFraction() const
+       {
+               return m_hitFraction;
+       }
+
+       void setHitFraction(btScalar hitFraction)
+       {
+               m_hitFraction = hitFraction;
+       }
+
+       SIMD_FORCE_INLINE int getCollisionFlags() const
+       {
+               return m_collisionFlags;
+       }
+
+       void setCollisionFlags(int flags)
+       {
+               m_collisionFlags = flags;
+       }
+
+       ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+       btScalar getCcdSweptSphereRadius() const
+       {
+               return m_ccdSweptSphereRadius;
+       }
+
+       ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+       void setCcdSweptSphereRadius(btScalar radius)
+       {
+               m_ccdSweptSphereRadius = radius;
+       }
+
+       btScalar getCcdMotionThreshold() const
+       {
+               return m_ccdMotionThreshold;
+       }
+
+       btScalar getCcdSquareMotionThreshold() const
+       {
+               return m_ccdMotionThreshold * m_ccdMotionThreshold;
+       }
+
+       /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
+       void setCcdMotionThreshold(btScalar ccdMotionThreshold)
+       {
+               m_ccdMotionThreshold = ccdMotionThreshold;
+       }
+
+       ///users can point to their objects, userPointer is not used by Bullet
+       void* getUserPointer() const
+       {
+               return m_userObjectPointer;
+       }
+
+       int getUserIndex() const
+       {
+               return m_userIndex;
+       }
+
+       int getUserIndex2() const
+       {
+               return m_userIndex2;
+       }
+
+       int getUserIndex3() const
+       {
+               return m_userIndex3;
+       }
+
+       ///users can point to their objects, userPointer is not used by Bullet
+       void setUserPointer(void* userPointer)
+       {
+               m_userObjectPointer = userPointer;
+       }
+
+       ///users can point to their objects, userPointer is not used by Bullet
+       void setUserIndex(int index)
+       {
+               m_userIndex = index;
+       }
+
+       void setUserIndex2(int index)
+       {
+               m_userIndex2 = index;
+       }
+
+       void setUserIndex3(int index)
+       {
+               m_userIndex3 = index;
+       }
+
+       int getUpdateRevisionInternal() const
+       {
+               return m_updateRevision;
+       }
+
+       void setCustomDebugColor(const btVector3& colorRGB)
+       {
+               m_customDebugColorRGB = colorRGB;
+               m_collisionFlags |= CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
+       }
+
+       void removeCustomDebugColor()
+       {
+               m_collisionFlags &= ~CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
+       }
+
+       bool getCustomDebugColor(btVector3 & colorRGB) const
+       {
+               bool hasCustomColor = (0 != (m_collisionFlags & CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR));
+               if (hasCustomColor)
+               {
+                       colorRGB = m_customDebugColorRGB;
+               }
+               return hasCustomColor;
+       }
+
+       inline bool checkCollideWith(const btCollisionObject* co) const
+       {
+               if (m_checkCollideWith)
+                       return checkCollideWithOverride(co);
+
+               return true;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
+
+       virtual void serializeSingleObject(class btSerializer * serializer) const;
+};
+
+// clang-format off
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCollisionObjectDoubleData
+{
+       void                                    *m_broadphaseHandle;
+       void                                    *m_collisionShape;
+       btCollisionShapeData    *m_rootCollisionShape;
+       char                                    *m_name;
+
+       btTransformDoubleData   m_worldTransform;
+       btTransformDoubleData   m_interpolationWorldTransform;
+       btVector3DoubleData             m_interpolationLinearVelocity;
+       btVector3DoubleData             m_interpolationAngularVelocity;
+       btVector3DoubleData             m_anisotropicFriction;
+       double                                  m_contactProcessingThreshold;   
+       double                                  m_deactivationTime;
+       double                                  m_friction;
+       double                                  m_rollingFriction;
+       double                  m_contactDamping;
+       double                  m_contactStiffness;
+       double                                  m_restitution;
+       double                                  m_hitFraction; 
+       double                                  m_ccdSweptSphereRadius;
+       double                                  m_ccdMotionThreshold;
+       int                                             m_hasAnisotropicFriction;
+       int                                             m_collisionFlags;
+       int                                             m_islandTag1;
+       int                                             m_companionId;
+       int                                             m_activationState1;
+       int                                             m_internalType;
+       int                                             m_checkCollideWith;
+       int                                             m_collisionFilterGroup;
+       int                                             m_collisionFilterMask;
+       int                                             m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCollisionObjectFloatData
+{
+       void                                    *m_broadphaseHandle;
+       void                                    *m_collisionShape;
+       btCollisionShapeData    *m_rootCollisionShape;
+       char                                    *m_name;
+
+       btTransformFloatData    m_worldTransform;
+       btTransformFloatData    m_interpolationWorldTransform;
+       btVector3FloatData              m_interpolationLinearVelocity;
+       btVector3FloatData              m_interpolationAngularVelocity;
+       btVector3FloatData              m_anisotropicFriction;
+       float                                   m_contactProcessingThreshold;   
+       float                                   m_deactivationTime;
+       float                                   m_friction;
+       float                                   m_rollingFriction;
+       float                   m_contactDamping;
+    float                   m_contactStiffness;
+       float                                   m_restitution;
+       float                                   m_hitFraction; 
+       float                                   m_ccdSweptSphereRadius;
+       float                                   m_ccdMotionThreshold;
+       int                                             m_hasAnisotropicFriction;
+       int                                             m_collisionFlags;
+       int                                             m_islandTag1;
+       int                                             m_companionId;
+       int                                             m_activationState1;
+       int                                             m_internalType;
+       int                                             m_checkCollideWith;
+       int                                             m_collisionFilterGroup;
+       int                                             m_collisionFilterMask;
+       int                                             m_uniqueId;
+};
+// clang-format on
+
+SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
+{
+       return sizeof(btCollisionObjectData);
+}
+
+#endif  //BT_COLLISION_OBJECT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
new file mode 100644 (file)
index 0000000..56341b7
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef BT_COLLISION_OBJECT_WRAPPER_H
+#define BT_COLLISION_OBJECT_WRAPPER_H
+
+///btCollisionObjectWrapperis an internal data structure.
+///Most users can ignore this and use btCollisionObject and btCollisionShape instead
+class btCollisionShape;
+class btCollisionObject;
+class btTransform;
+#include "LinearMath/btScalar.h"  // for SIMD_FORCE_INLINE definition
+
+#define BT_DECLARE_STACK_ONLY_OBJECT \
+private:                             \
+       void* operator new(size_t size); \
+       void operator delete(void*);
+
+struct btCollisionObjectWrapper;
+struct btCollisionObjectWrapper
+{
+       BT_DECLARE_STACK_ONLY_OBJECT
+
+private:
+       btCollisionObjectWrapper(const btCollisionObjectWrapper&);  // not implemented. Not allowed.
+       btCollisionObjectWrapper* operator=(const btCollisionObjectWrapper&);
+
+public:
+       const btCollisionObjectWrapper* m_parent;
+       const btCollisionShape* m_shape;
+       const btCollisionObject* m_collisionObject;
+       const btTransform& m_worldTransform;
+    const btTransform* m_preTransform;
+       int m_partId;
+       int m_index;
+
+       btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, int partId, int index)
+               : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(NULL), m_partId(partId), m_index(index)
+       {
+       }
+    
+    btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, const btTransform& preTransform, int partId, int index)
+    : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(&preTransform), m_partId(partId), m_index(index)
+    {
+    }
+
+       SIMD_FORCE_INLINE const btTransform& getWorldTransform() const { return m_worldTransform; }
+       SIMD_FORCE_INLINE const btCollisionObject* getCollisionObject() const { return m_collisionObject; }
+       SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_shape; }
+};
+
+#endif  //BT_COLLISION_OBJECT_WRAPPER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
new file mode 100644 (file)
index 0000000..15940f5
--- /dev/null
@@ -0,0 +1,1624 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionWorld.h"
+#include "btCollisionDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"                 //for raycasting
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"        //for raycasting
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"  //for raycasting
+#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.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/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btSerializer.h"
+#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+//#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+
+//#define USE_BRUTEFORCE_RAYBROADPHASE 1
+//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation'  or 'updateAabbs' before using a rayTest
+//#define RECALCULATE_AABB_RAYCAST 1
+
+//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"
+
+///for debug drawing
+
+//for debug rendering
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionShapes/btConeShape.h"
+#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btCylinderShape.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
+       : m_dispatcher1(dispatcher),
+         m_broadphasePairCache(pairCache),
+         m_debugDrawer(0),
+         m_forceUpdateAllAabbs(true)
+{
+}
+
+btCollisionWorld::~btCollisionWorld()
+{
+       //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()->getOverlappingPairCache()->cleanProxyFromPairs(bp, m_dispatcher1);
+                       getBroadphase()->destroyProxy(bp, m_dispatcher1);
+                       collisionObject->setBroadphaseHandle(0);
+               }
+       }
+}
+
+void btCollisionWorld::refreshBroadphaseProxy(btCollisionObject* collisionObject)
+{
+       if (collisionObject->getBroadphaseHandle())
+       {
+               int collisionFilterGroup = collisionObject->getBroadphaseHandle()->m_collisionFilterGroup;
+               int collisionFilterMask = collisionObject->getBroadphaseHandle()->m_collisionFilterMask;
+
+               getBroadphase()->destroyProxy(collisionObject->getBroadphaseHandle(), getDispatcher());
+
+               //calculate new AABB
+               btTransform trans = collisionObject->getWorldTransform();
+
+               btVector3 minAabb;
+               btVector3 maxAabb;
+               collisionObject->getCollisionShape()->getAabb(trans, minAabb, maxAabb);
+
+               int type = collisionObject->getCollisionShape()->getShapeType();
+               collisionObject->setBroadphaseHandle(getBroadphase()->createProxy(
+                       minAabb,
+                       maxAabb,
+                       type,
+                       collisionObject,
+                       collisionFilterGroup,
+                       collisionFilterMask,
+                       m_dispatcher1));
+       }
+}
+
+void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
+{
+       btAssert(collisionObject);
+
+       //check that the object isn't already added
+       btAssert(m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size());
+       btAssert(collisionObject->getWorldArrayIndex() == -1);  // do not add the same object to more than one collision world
+
+       collisionObject->setWorldArrayIndex(m_collisionObjects.size());
+       m_collisionObjects.push_back(collisionObject);
+
+       //calculate new AABB
+       btTransform trans = collisionObject->getWorldTransform();
+
+       btVector3 minAabb;
+       btVector3 maxAabb;
+       collisionObject->getCollisionShape()->getAabb(trans, minAabb, maxAabb);
+
+       int type = collisionObject->getCollisionShape()->getShapeType();
+       collisionObject->setBroadphaseHandle(getBroadphase()->createProxy(
+               minAabb,
+               maxAabb,
+               type,
+               collisionObject,
+               collisionFilterGroup,
+               collisionFilterMask,
+               m_dispatcher1));
+}
+
+void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
+{
+       btVector3 minAabb, maxAabb;
+       colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
+       //need to increase the aabb for contact thresholds
+       btVector3 contactThreshold(gContactBreakingThreshold, gContactBreakingThreshold, gContactBreakingThreshold);
+       minAabb -= contactThreshold;
+       maxAabb += contactThreshold;
+
+       if (getDispatchInfo().m_useContinuous && colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
+       {
+               btVector3 minAabb2, maxAabb2;
+               colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(), minAabb2, maxAabb2);
+               minAabb2 -= contactThreshold;
+               maxAabb2 += contactThreshold;
+               minAabb.setMin(minAabb2);
+               maxAabb.setMax(maxAabb2);
+       }
+
+       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::updateAabbs()
+{
+       BT_PROFILE("updateAabbs");
+
+       for (int i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               btAssert(colObj->getWorldArrayIndex() == i);
+
+               //only update aabb of active objects
+               if (m_forceUpdateAllAabbs || colObj->isActive())
+               {
+                       updateSingleAabb(colObj);
+               }
+       }
+}
+
+void btCollisionWorld::computeOverlappingPairs()
+{
+       BT_PROFILE("calculateOverlappingPairs");
+       m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
+}
+
+void btCollisionWorld::performDiscreteCollisionDetection()
+{
+       BT_PROFILE("performDiscreteCollisionDetection");
+
+       btDispatcherInfo& dispatchInfo = getDispatchInfo();
+
+       updateAabbs();
+
+       computeOverlappingPairs();
+
+       btDispatcher* dispatcher = getDispatcher();
+       {
+               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()->getOverlappingPairCache()->cleanProxyFromPairs(bp, m_dispatcher1);
+                       getBroadphase()->destroyProxy(bp, m_dispatcher1);
+                       collisionObject->setBroadphaseHandle(0);
+               }
+       }
+
+       int iObj = collisionObject->getWorldArrayIndex();
+       //    btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously?
+       if (iObj >= 0 && iObj < m_collisionObjects.size())
+       {
+               btAssert(collisionObject == m_collisionObjects[iObj]);
+               m_collisionObjects.swap(iObj, m_collisionObjects.size() - 1);
+               m_collisionObjects.pop_back();
+               if (iObj < m_collisionObjects.size())
+               {
+                       m_collisionObjects[iObj]->setWorldArrayIndex(iObj);
+               }
+       }
+       else
+       {
+               // slow linear search
+               //swapremove
+               m_collisionObjects.remove(collisionObject);
+       }
+       collisionObject->setWorldArrayIndex(-1);
+}
+
+void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+                                                                        btCollisionObject* collisionObject,
+                                                                        const btCollisionShape* collisionShape,
+                                                                        const btTransform& colObjWorldTransform,
+                                                                        RayResultCallback& resultCallback)
+{
+       btCollisionObjectWrapper colObWrap(0, collisionShape, collisionObject, colObjWorldTransform, -1, -1);
+       btCollisionWorld::rayTestSingleInternal(rayFromTrans, rayToTrans, &colObWrap, resultCallback);
+}
+
+void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+                                                                                        const btCollisionObjectWrapper* collisionObjectWrap,
+                                                                                        RayResultCallback& resultCallback)
+{
+       btSphereShape pointShape(btScalar(0.0));
+       pointShape.setMargin(0.f);
+       const btConvexShape* castShape = &pointShape;
+       const btCollisionShape* collisionShape = collisionObjectWrap->getCollisionShape();
+       const btTransform& colObjWorldTransform = collisionObjectWrap->getWorldTransform();
+
+       if (collisionShape->isConvex())
+       {
+               //              BT_PROFILE("rayTestConvex");
+               btConvexCast::CastResult castResult;
+               castResult.m_fraction = resultCallback.m_closestHitFraction;
+
+               btConvexShape* convexShape = (btConvexShape*)collisionShape;
+               btVoronoiSimplexSolver simplexSolver;
+               btSubsimplexConvexCast subSimplexConvexCaster(castShape, convexShape, &simplexSolver);
+
+               btGjkConvexCast gjkConvexCaster(castShape, convexShape, &simplexSolver);
+
+               //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
+
+               btConvexCast* convexCasterPtr = 0;
+               //use kF_UseSubSimplexConvexCastRaytest by default
+               if (resultCallback.m_flags & btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest)
+                       convexCasterPtr = &gjkConvexCaster;
+               else
+                       convexCasterPtr = &subSimplexConvexCaster;
+
+               btConvexCast& convexCaster = *convexCasterPtr;
+
+               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)
+                               {
+                                       //todo: figure out what this is about. When is rayFromTest.getBasis() not identity?
+#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(
+                                               collisionObjectWrap->getCollisionObject(),
+                                               0,
+                                               castResult.m_normal,
+                                               castResult.m_fraction);
+
+                                       bool normalInWorldSpace = true;
+                                       resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
+                               }
+                       }
+               }
+       }
+       else
+       {
+               if (collisionShape->isConcave())
+               {
+                       //ConvexCast::CastResult
+                       struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+                       {
+                               btCollisionWorld::RayResultCallback* m_resultCallback;
+                               const btCollisionObject* m_collisionObject;
+                               const btConcaveShape* m_triangleMesh;
+
+                               btTransform m_colObjWorldTransform;
+
+                               BridgeTriangleRaycastCallback(const btVector3& from, const btVector3& to,
+                                                                                         btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject, const btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform) :  //@BP Mod
+                                                                                                                                                                                                                                                                                                                                                                                                                                                       btTriangleRaycastCallback(from, to, resultCallback->m_flags),
+                                                                                                                                                                                                                                                                                                                                                                                                                                                       m_resultCallback(resultCallback),
+                                                                                                                                                                                                                                                                                                                                                                                                                                                       m_collisionObject(collisionObject),
+                                                                                                                                                                                                                                                                                                                                                                                                                                                       m_triangleMesh(triangleMesh),
+                                                                                                                                                                                                                                                                                                                                                                                                                                                       m_colObjWorldTransform(colObjWorldTransform)
+                               {
+                               }
+
+                               virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
+                               {
+                                       btCollisionWorld::LocalShapeInfo shapeInfo;
+                                       shapeInfo.m_shapePart = partId;
+                                       shapeInfo.m_triangleIndex = triangleIndex;
+
+                                       btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
+
+                                       btCollisionWorld::LocalRayResult rayResult(m_collisionObject,
+                                                                                                                          &shapeInfo,
+                                                                                                                          hitNormalWorld,
+                                                                                                                          hitFraction);
+
+                                       bool normalInWorldSpace = true;
+                                       return m_resultCallback->addSingleResult(rayResult, normalInWorldSpace);
+                               }
+                       };
+
+                       btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+                       btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+                       btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+                       //                      BT_PROFILE("rayTestConcave");
+                       if (collisionShape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+                       {
+                               ///optimized version for btBvhTriangleMeshShape
+                               btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+
+                               BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
+                               rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+                               triangleMesh->performRaycast(&rcb, rayFromLocal, rayToLocal);
+                       }
+                       else if (collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
+                       {
+                               ///optimized version for btScaledBvhTriangleMeshShape
+                               btScaledBvhTriangleMeshShape* scaledTriangleMesh = (btScaledBvhTriangleMeshShape*)collisionShape;
+                               btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)scaledTriangleMesh->getChildShape();
+
+                               //scale the ray positions
+                               btVector3 scale = scaledTriangleMesh->getLocalScaling();
+                               btVector3 rayFromLocalScaled = rayFromLocal / scale;
+                               btVector3 rayToLocalScaled = rayToLocal / scale;
+
+                               //perform raycast in the underlying btBvhTriangleMeshShape
+                               BridgeTriangleRaycastCallback rcb(rayFromLocalScaled, rayToLocalScaled, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
+                               rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+                               triangleMesh->performRaycast(&rcb, rayFromLocalScaled, rayToLocalScaled);
+                       }
+                       else if (((resultCallback.m_flags&btTriangleRaycastCallback::kF_DisableHeightfieldAccelerator)==0) 
+                               && collisionShape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE 
+                               )
+                       {
+                               ///optimized version for btHeightfieldTerrainShape
+                               btHeightfieldTerrainShape* heightField = (btHeightfieldTerrainShape*)collisionShape;
+                               btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+                               btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+                               btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+                               BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), heightField, colObjWorldTransform);
+                               rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+                               heightField->performRaycast(&rcb, rayFromLocal, rayToLocal);
+                       }
+                       else
+                       {
+                               //generic (slower) case
+                               btConcaveShape* concaveShape = (btConcaveShape*)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;
+                                       const btCollisionObject* m_collisionObject;
+                                       btConcaveShape* m_triangleMesh;
+
+                                       btTransform m_colObjWorldTransform;
+
+                                       BridgeTriangleRaycastCallback(const btVector3& from, const btVector3& to,
+                                                                                                 btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject, btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform) :  //@BP Mod
+                                                                                                                                                                                                                                                                                                                                                                                                                                                 btTriangleRaycastCallback(from, to, resultCallback->m_flags),
+                                                                                                                                                                                                                                                                                                                                                                                                                                                 m_resultCallback(resultCallback),
+                                                                                                                                                                                                                                                                                                                                                                                                                                                 m_collisionObject(collisionObject),
+                                                                                                                                                                                                                                                                                                                                                                                                                                                 m_triangleMesh(triangleMesh),
+                                                                                                                                                                                                                                                                                                                                                                                                                                                 m_colObjWorldTransform(colObjWorldTransform)
+                                       {
+                                       }
+
+                                       virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
+                                       {
+                                               btCollisionWorld::LocalShapeInfo shapeInfo;
+                                               shapeInfo.m_shapePart = partId;
+                                               shapeInfo.m_triangleIndex = triangleIndex;
+
+                                               btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
+
+                                               btCollisionWorld::LocalRayResult rayResult(m_collisionObject,
+                                                                                                                                  &shapeInfo,
+                                                                                                                                  hitNormalWorld,
+                                                                                                                                  hitFraction);
+
+                                               bool normalInWorldSpace = true;
+                                               return m_resultCallback->addSingleResult(rayResult, normalInWorldSpace);
+                                       }
+                               };
+
+                               BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), concaveShape, colObjWorldTransform);
+                               rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+
+                               btVector3 rayAabbMinLocal = rayFromLocal;
+                               rayAabbMinLocal.setMin(rayToLocal);
+                               btVector3 rayAabbMaxLocal = rayFromLocal;
+                               rayAabbMaxLocal.setMax(rayToLocal);
+
+                               concaveShape->processAllTriangles(&rcb, rayAabbMinLocal, rayAabbMaxLocal);
+                       }
+               }
+               else
+               {
+                       //                      BT_PROFILE("rayTestCompound");
+                       if (collisionShape->isCompound())
+                       {
+                               struct LocalInfoAdder2 : public RayResultCallback
+                               {
+                                       RayResultCallback* m_userCallback;
+                                       int m_i;
+
+                                       LocalInfoAdder2(int i, RayResultCallback* user)
+                                               : m_userCallback(user), m_i(i)
+                                       {
+                                               m_closestHitFraction = m_userCallback->m_closestHitFraction;
+                                               m_flags = m_userCallback->m_flags;
+                                       }
+                                       virtual bool needsCollision(btBroadphaseProxy* p) const
+                                       {
+                                               return m_userCallback->needsCollision(p);
+                                       }
+
+                                       virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& r, bool b)
+                                       {
+                                               btCollisionWorld::LocalShapeInfo shapeInfo;
+                                               shapeInfo.m_shapePart = -1;
+                                               shapeInfo.m_triangleIndex = m_i;
+                                               if (r.m_localShapeInfo == NULL)
+                                                       r.m_localShapeInfo = &shapeInfo;
+
+                                               const btScalar result = m_userCallback->addSingleResult(r, b);
+                                               m_closestHitFraction = m_userCallback->m_closestHitFraction;
+                                               return result;
+                                       }
+                               };
+
+                               struct RayTester : btDbvt::ICollide
+                               {
+                                       const btCollisionObject* m_collisionObject;
+                                       const btCompoundShape* m_compoundShape;
+                                       const btTransform& m_colObjWorldTransform;
+                                       const btTransform& m_rayFromTrans;
+                                       const btTransform& m_rayToTrans;
+                                       RayResultCallback& m_resultCallback;
+
+                                       RayTester(const btCollisionObject* collisionObject,
+                                                         const btCompoundShape* compoundShape,
+                                                         const btTransform& colObjWorldTransform,
+                                                         const btTransform& rayFromTrans,
+                                                         const btTransform& rayToTrans,
+                                                         RayResultCallback& resultCallback) : m_collisionObject(collisionObject),
+                                                                                                                                  m_compoundShape(compoundShape),
+                                                                                                                                  m_colObjWorldTransform(colObjWorldTransform),
+                                                                                                                                  m_rayFromTrans(rayFromTrans),
+                                                                                                                                  m_rayToTrans(rayToTrans),
+                                                                                                                                  m_resultCallback(resultCallback)
+                                       {
+                                       }
+
+                                       void ProcessLeaf(int i)
+                                       {
+                                               const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i);
+                                               const btTransform& childTrans = m_compoundShape->getChildTransform(i);
+                                               btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
+
+                                               btCollisionObjectWrapper tmpOb(0, childCollisionShape, m_collisionObject, childWorldTrans, -1, i);
+                                               // replace collision shape so that callback can determine the triangle
+
+                                               LocalInfoAdder2 my_cb(i, &m_resultCallback);
+
+                                               rayTestSingleInternal(
+                                                       m_rayFromTrans,
+                                                       m_rayToTrans,
+                                                       &tmpOb,
+                                                       my_cb);
+                                       }
+
+                                       void Process(const btDbvtNode* leaf)
+                                       {
+                                               ProcessLeaf(leaf->dataAsInt);
+                                       }
+                               };
+
+                               const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
+                               const btDbvt* dbvt = compoundShape->getDynamicAabbTree();
+
+                               RayTester rayCB(
+                                       collisionObjectWrap->getCollisionObject(),
+                                       compoundShape,
+                                       colObjWorldTransform,
+                                       rayFromTrans,
+                                       rayToTrans,
+                                       resultCallback);
+#ifndef DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+                               if (dbvt)
+                               {
+                                       btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin();
+                                       btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin();
+                                       btDbvt::rayTest(dbvt->m_root, localRayFrom, localRayTo, rayCB);
+                               }
+                               else
+#endif  //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+                               {
+                                       for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i)
+                                       {
+                                               rayCB.ProcessLeaf(i);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
+                                                                                btCollisionObject* collisionObject,
+                                                                                const btCollisionShape* collisionShape,
+                                                                                const btTransform& colObjWorldTransform,
+                                                                                ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+{
+       btCollisionObjectWrapper tmpOb(0, collisionShape, collisionObject, colObjWorldTransform, -1, -1);
+       btCollisionWorld::objectQuerySingleInternal(castShape, convexFromTrans, convexToTrans, &tmpOb, resultCallback, allowedPenetration);
+}
+
+void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
+                                                                                                const btCollisionObjectWrapper* colObjWrap,
+                                                                                                ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+{
+       const btCollisionShape* collisionShape = colObjWrap->getCollisionShape();
+       const btTransform& colObjWorldTransform = colObjWrap->getWorldTransform();
+
+       if (collisionShape->isConvex())
+       {
+               //BT_PROFILE("convexSweepConvex");
+               btConvexCast::CastResult castResult;
+               castResult.m_allowedPenetration = allowedPenetration;
+               castResult.m_fraction = resultCallback.m_closestHitFraction;  //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))
+                       {
+                               if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+                               {
+                                       castResult.m_normal.normalize();
+                                       btCollisionWorld::LocalConvexResult localConvexResult(
+                                               colObjWrap->getCollisionObject(),
+                                               0,
+                                               castResult.m_normal,
+                                               castResult.m_hitPoint,
+                                               castResult.m_fraction);
+
+                                       bool normalInWorldSpace = true;
+                                       resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
+                               }
+                       }
+               }
+       }
+       else
+       {
+               if (collisionShape->isConcave())
+               {
+                       if (collisionShape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+                       {
+                               //BT_PROFILE("convexSweepbtBvhTriangleMesh");
+                               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;
+                                       const btCollisionObject* m_collisionObject;
+                                       btTriangleMeshShape* m_triangleMesh;
+
+                                       BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from, const btTransform& to,
+                                                                                                        btCollisionWorld::ConvexResultCallback* resultCallback, const 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)
+                                               {
+                                                       btCollisionWorld::LocalConvexResult convexResult(m_collisionObject,
+                                                                                                                                                        &shapeInfo,
+                                                                                                                                                        hitNormalLocal,
+                                                                                                                                                        hitPointLocal,
+                                                                                                                                                        hitFraction);
+
+                                                       bool normalInWorldSpace = true;
+
+                                                       return m_resultCallback->addSingleResult(convexResult, normalInWorldSpace);
+                                               }
+                                               return hitFraction;
+                                       }
+                               };
+
+                               BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans, convexToTrans, &resultCallback, colObjWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
+                               tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+                               tccb.m_allowedPenetration = allowedPenetration;
+                               btVector3 boxMinLocal, boxMaxLocal;
+                               castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+                               triangleMesh->performConvexcast(&tccb, convexFromLocal, convexToLocal, boxMinLocal, boxMaxLocal);
+                       }
+                       else
+                       {
+                               if (collisionShape->getShapeType() == STATIC_PLANE_PROXYTYPE)
+                               {
+                                       btConvexCast::CastResult castResult;
+                                       castResult.m_allowedPenetration = allowedPenetration;
+                                       castResult.m_fraction = resultCallback.m_closestHitFraction;
+                                       btStaticPlaneShape* planeShape = (btStaticPlaneShape*)collisionShape;
+                                       btContinuousConvexCollision convexCaster1(castShape, planeShape);
+                                       btConvexCast* castPtr = &convexCaster1;
+
+                                       if (castPtr->calcTimeOfImpact(convexFromTrans, convexToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
+                                       {
+                                               //add hit
+                                               if (castResult.m_normal.length2() > btScalar(0.0001))
+                                               {
+                                                       if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+                                                       {
+                                                               castResult.m_normal.normalize();
+                                                               btCollisionWorld::LocalConvexResult localConvexResult(
+                                                                       colObjWrap->getCollisionObject(),
+                                                                       0,
+                                                                       castResult.m_normal,
+                                                                       castResult.m_hitPoint,
+                                                                       castResult.m_fraction);
+
+                                                               bool normalInWorldSpace = true;
+                                                               resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
+                                                       }
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       //BT_PROFILE("convexSweepConcave");
+                                       btConcaveShape* concaveShape = (btConcaveShape*)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;
+                                               const btCollisionObject* m_collisionObject;
+                                               btConcaveShape* m_triangleMesh;
+
+                                               BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from, const btTransform& to,
+                                                                                                                btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject, btConcaveShape* 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)
+                                                       {
+                                                               btCollisionWorld::LocalConvexResult convexResult(m_collisionObject,
+                                                                                                                                                                &shapeInfo,
+                                                                                                                                                                hitNormalLocal,
+                                                                                                                                                                hitPointLocal,
+                                                                                                                                                                hitFraction);
+
+                                                               bool normalInWorldSpace = true;
+
+                                                               return m_resultCallback->addSingleResult(convexResult, normalInWorldSpace);
+                                                       }
+                                                       return hitFraction;
+                                               }
+                                       };
+
+                                       BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans, convexToTrans, &resultCallback, colObjWrap->getCollisionObject(), concaveShape, colObjWorldTransform);
+                                       tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+                                       tccb.m_allowedPenetration = allowedPenetration;
+                                       btVector3 boxMinLocal, boxMaxLocal;
+                                       castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+
+                                       btVector3 rayAabbMinLocal = convexFromLocal;
+                                       rayAabbMinLocal.setMin(convexToLocal);
+                                       btVector3 rayAabbMaxLocal = convexFromLocal;
+                                       rayAabbMaxLocal.setMax(convexToLocal);
+                                       rayAabbMinLocal += boxMinLocal;
+                                       rayAabbMaxLocal += boxMaxLocal;
+                                       concaveShape->processAllTriangles(&tccb, rayAabbMinLocal, rayAabbMaxLocal);
+                               }
+                       }
+               }
+               else
+               {
+                       if (collisionShape->isCompound())
+                       {
+                               struct btCompoundLeafCallback : btDbvt::ICollide
+                               {
+                                       btCompoundLeafCallback(
+                                               const btCollisionObjectWrapper* colObjWrap,
+                                               const btConvexShape* castShape,
+                                               const btTransform& convexFromTrans,
+                                               const btTransform& convexToTrans,
+                                               btScalar allowedPenetration,
+                                               const btCompoundShape* compoundShape,
+                                               const btTransform& colObjWorldTransform,
+                                               ConvexResultCallback& resultCallback)
+                                               : m_colObjWrap(colObjWrap),
+                                                 m_castShape(castShape),
+                                                 m_convexFromTrans(convexFromTrans),
+                                                 m_convexToTrans(convexToTrans),
+                                                 m_allowedPenetration(allowedPenetration),
+                                                 m_compoundShape(compoundShape),
+                                                 m_colObjWorldTransform(colObjWorldTransform),
+                                                 m_resultCallback(resultCallback)
+                                       {
+                                       }
+
+                                       const btCollisionObjectWrapper* m_colObjWrap;
+                                       const btConvexShape* m_castShape;
+                                       const btTransform& m_convexFromTrans;
+                                       const btTransform& m_convexToTrans;
+                                       btScalar m_allowedPenetration;
+                                       const btCompoundShape* m_compoundShape;
+                                       const btTransform& m_colObjWorldTransform;
+                                       ConvexResultCallback& m_resultCallback;
+
+                               public:
+                                       void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape)
+                                       {
+                                               btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
+
+                                               struct LocalInfoAdder : public ConvexResultCallback
+                                               {
+                                                       ConvexResultCallback* m_userCallback;
+                                                       int m_i;
+
+                                                       LocalInfoAdder(int i, ConvexResultCallback* user)
+                                                               : m_userCallback(user), m_i(i)
+                                                       {
+                                                               m_closestHitFraction = m_userCallback->m_closestHitFraction;
+                                                       }
+                                                       virtual bool needsCollision(btBroadphaseProxy* p) const
+                                                       {
+                                                               return m_userCallback->needsCollision(p);
+                                                       }
+                                                       virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b)
+                                                       {
+                                                               btCollisionWorld::LocalShapeInfo shapeInfo;
+                                                               shapeInfo.m_shapePart = -1;
+                                                               shapeInfo.m_triangleIndex = m_i;
+                                                               if (r.m_localShapeInfo == NULL)
+                                                                       r.m_localShapeInfo = &shapeInfo;
+                                                               const btScalar result = m_userCallback->addSingleResult(r, b);
+                                                               m_closestHitFraction = m_userCallback->m_closestHitFraction;
+                                                               return result;
+                                                       }
+                                               };
+
+                                               LocalInfoAdder my_cb(index, &m_resultCallback);
+
+                                               btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index);
+
+                                               objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration);
+                                       }
+
+                                       void Process(const btDbvtNode* leaf)
+                                       {
+                                               // Processing leaf node
+                                               int index = leaf->dataAsInt;
+
+                                               btTransform childTrans = m_compoundShape->getChildTransform(index);
+                                               const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index);
+
+                                               ProcessChild(index, childTrans, childCollisionShape);
+                                       }
+                               };
+
+                               BT_PROFILE("convexSweepCompound");
+                               const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
+
+                               btVector3 fromLocalAabbMin, fromLocalAabbMax;
+                               btVector3 toLocalAabbMin, toLocalAabbMax;
+
+                               castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax);
+                               castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax);
+
+                               fromLocalAabbMin.setMin(toLocalAabbMin);
+                               fromLocalAabbMax.setMax(toLocalAabbMax);
+
+                               btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans,
+                                                                                               allowedPenetration, compoundShape, colObjWorldTransform, resultCallback);
+
+                               const btDbvt* tree = compoundShape->getDynamicAabbTree();
+                               if (tree)
+                               {
+                                       const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax);
+                                       tree->collideTV(tree->m_root, bounds, callback);
+                               }
+                               else
+                               {
+                                       int i;
+                                       for (i = 0; i < compoundShape->getNumChildShapes(); i++)
+                                       {
+                                               const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
+                                               btTransform childTrans = compoundShape->getChildTransform(i);
+                                               callback.ProcessChild(i, childTrans, childCollisionShape);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+struct btSingleRayCallback : public btBroadphaseRayCallback
+{
+       btVector3 m_rayFromWorld;
+       btVector3 m_rayToWorld;
+       btTransform m_rayFromTrans;
+       btTransform m_rayToTrans;
+       btVector3 m_hitNormal;
+
+       const btCollisionWorld* m_world;
+       btCollisionWorld::RayResultCallback& m_resultCallback;
+
+       btSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btCollisionWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
+               : m_rayFromWorld(rayFromWorld),
+                 m_rayToWorld(rayToWorld),
+                 m_world(world),
+                 m_resultCallback(resultCallback)
+       {
+               m_rayFromTrans.setIdentity();
+               m_rayFromTrans.setOrigin(m_rayFromWorld);
+               m_rayToTrans.setIdentity();
+               m_rayToTrans.setOrigin(m_rayToWorld);
+
+               btVector3 rayDir = (rayToWorld - rayFromWorld);
+
+               rayDir.normalize();
+               ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+               m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+               m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+               m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+               m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+               m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+               m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+               m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
+       }
+
+       virtual bool process(const btBroadphaseProxy* proxy)
+       {
+               ///terminate further ray tests, once the closestHitFraction reached zero
+               if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+                       return false;
+
+               btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+               //only perform raycast if filterMask matches
+               if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+               {
+                       //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+                       //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+                       btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+                       collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+                       //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+                       const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+                       const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+                       //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+                       //culling already done by broadphase
+                       //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+                       {
+                               m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
+                                                                          collisionObject,
+                                                                          collisionObject->getCollisionShape(),
+                                                                          collisionObject->getWorldTransform(),
+                                                                          m_resultCallback);
+                       }
+               }
+               return true;
+       }
+};
+
+void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+{
+       //BT_PROFILE("rayTest");
+       /// use the broadphase to accelerate the search for objects, based on their aabb
+       /// and for each object with ray-aabb overlap, perform an exact ray test
+       btSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+       m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
+#else
+       for (int i = 0; i < this->getNumCollisionObjects(); i++)
+       {
+               rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+       }
+#endif  //USE_BRUTEFORCE_RAYBROADPHASE
+}
+
+struct btSingleSweepCallback : public btBroadphaseRayCallback
+{
+       btTransform m_convexFromTrans;
+       btTransform m_convexToTrans;
+       btVector3 m_hitNormal;
+       const btCollisionWorld* m_world;
+       btCollisionWorld::ConvexResultCallback& m_resultCallback;
+       btScalar m_allowedCcdPenetration;
+       const btConvexShape* m_castShape;
+
+       btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans, const btCollisionWorld* world, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+               : m_convexFromTrans(convexFromTrans),
+                 m_convexToTrans(convexToTrans),
+                 m_world(world),
+                 m_resultCallback(resultCallback),
+                 m_allowedCcdPenetration(allowedPenetration),
+                 m_castShape(castShape)
+       {
+               btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin() - m_convexFromTrans.getOrigin());
+               btVector3 rayDir = unnormalizedRayDir.fuzzyZero() ? btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0)) : unnormalizedRayDir.normalized();
+               ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+               m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+               m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+               m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+               m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+               m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+               m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+               m_lambda_max = rayDir.dot(unnormalizedRayDir);
+       }
+
+       virtual bool process(const btBroadphaseProxy* proxy)
+       {
+               ///terminate further convex sweep tests, once the closestHitFraction reached zero
+               if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+                       return false;
+
+               btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+               //only perform raycast if filterMask matches
+               if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+               {
+                       //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+                       m_world->objectQuerySingle(m_castShape, m_convexFromTrans, m_convexToTrans,
+                                                                          collisionObject,
+                                                                          collisionObject->getCollisionShape(),
+                                                                          collisionObject->getWorldTransform(),
+                                                                          m_resultCallback,
+                                                                          m_allowedCcdPenetration);
+               }
+
+               return true;
+       }
+};
+
+void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
+{
+       BT_PROFILE("convexSweepTest");
+       /// use the broadphase to accelerate the search for objects, based on their aabb
+       /// and for each object with ray-aabb overlap, perform an exact ray test
+       /// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical
+
+       btTransform convexFromTrans, convexToTrans;
+       convexFromTrans = convexFromWorld;
+       convexToTrans = convexToWorld;
+       btVector3 castShapeAabbMin, castShapeAabbMax;
+       /* Compute AABB that encompasses angular movement */
+       {
+               btVector3 linVel, angVel;
+               btTransformUtil::calculateVelocity(convexFromTrans, convexToTrans, 1.0f, linVel, angVel);
+               btVector3 zeroLinVel;
+               zeroLinVel.setValue(0, 0, 0);
+               btTransform R;
+               R.setIdentity();
+               R.setRotation(convexFromTrans.getRotation());
+               castShape->calculateTemporalAabb(R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax);
+       }
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+
+       btSingleSweepCallback convexCB(castShape, convexFromWorld, convexToWorld, this, resultCallback, allowedCcdPenetration);
+
+       m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(), convexToTrans.getOrigin(), convexCB, castShapeAabbMin, castShapeAabbMax);
+
+#else
+       /// 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,
+                                                                 allowedCcdPenetration);
+                       }
+               }
+       }
+#endif  //USE_BRUTEFORCE_RAYBROADPHASE
+}
+
+struct btBridgedManifoldResult : public btManifoldResult
+{
+       btCollisionWorld::ContactResultCallback& m_resultCallback;
+
+       btBridgedManifoldResult(const btCollisionObjectWrapper* obj0Wrap, const btCollisionObjectWrapper* obj1Wrap, btCollisionWorld::ContactResultCallback& resultCallback)
+               : btManifoldResult(obj0Wrap, obj1Wrap),
+                 m_resultCallback(resultCallback)
+       {
+       }
+
+       virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
+       {
+               bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
+               btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
+               btVector3 localA;
+               btVector3 localB;
+               if (isSwapped)
+               {
+                       localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
+                       localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
+               }
+               else
+               {
+                       localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
+                       localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
+               }
+
+               btManifoldPoint newPt(localA, localB, normalOnBInWorld, depth);
+               newPt.m_positionWorldOnA = pointA;
+               newPt.m_positionWorldOnB = pointInWorld;
+
+               //BP mod, store contact triangles.
+               if (isSwapped)
+               {
+                       newPt.m_partId0 = m_partId1;
+                       newPt.m_partId1 = m_partId0;
+                       newPt.m_index0 = m_index1;
+                       newPt.m_index1 = m_index0;
+               }
+               else
+               {
+                       newPt.m_partId0 = m_partId0;
+                       newPt.m_partId1 = m_partId1;
+                       newPt.m_index0 = m_index0;
+                       newPt.m_index1 = m_index1;
+               }
+
+               //experimental feature info, for per-triangle material etc.
+               const btCollisionObjectWrapper* obj0Wrap = isSwapped ? m_body1Wrap : m_body0Wrap;
+               const btCollisionObjectWrapper* obj1Wrap = isSwapped ? m_body0Wrap : m_body1Wrap;
+               m_resultCallback.addSingleResult(newPt, obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
+       }
+};
+
+struct btSingleContactCallback : public btBroadphaseAabbCallback
+{
+       btCollisionObject* m_collisionObject;
+       btCollisionWorld* m_world;
+       btCollisionWorld::ContactResultCallback& m_resultCallback;
+
+       btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world, btCollisionWorld::ContactResultCallback& resultCallback)
+               : m_collisionObject(collisionObject),
+                 m_world(world),
+                 m_resultCallback(resultCallback)
+       {
+       }
+
+       virtual bool process(const btBroadphaseProxy* proxy)
+       {
+               btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+               if (collisionObject == m_collisionObject)
+                       return true;
+
+               //only perform raycast if filterMask matches
+               if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+               {
+                       btCollisionObjectWrapper ob0(0, m_collisionObject->getCollisionShape(), m_collisionObject, m_collisionObject->getWorldTransform(), -1, -1);
+                       btCollisionObjectWrapper ob1(0, collisionObject->getCollisionShape(), collisionObject, collisionObject->getWorldTransform(), -1, -1);
+
+                       btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0, &ob1, 0, BT_CLOSEST_POINT_ALGORITHMS);
+                       if (algorithm)
+                       {
+                               btBridgedManifoldResult contactPointResult(&ob0, &ob1, m_resultCallback);
+                               //discrete collision detection query
+
+                               algorithm->processCollision(&ob0, &ob1, m_world->getDispatchInfo(), &contactPointResult);
+
+                               algorithm->~btCollisionAlgorithm();
+                               m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
+                       }
+               }
+               return true;
+       }
+};
+
+///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback.
+///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
+void btCollisionWorld::contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback)
+{
+       btVector3 aabbMin, aabbMax;
+       colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), aabbMin, aabbMax);
+       btSingleContactCallback contactCB(colObj, this, resultCallback);
+
+       m_broadphasePairCache->aabbTest(aabbMin, aabbMax, contactCB);
+}
+
+///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
+///it reports one or more contact points (including the one with deepest penetration)
+void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
+{
+       btCollisionObjectWrapper obA(0, colObjA->getCollisionShape(), colObjA, colObjA->getWorldTransform(), -1, -1);
+       btCollisionObjectWrapper obB(0, colObjB->getCollisionShape(), colObjB, colObjB->getWorldTransform(), -1, -1);
+
+       btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA, &obB, 0, BT_CLOSEST_POINT_ALGORITHMS);
+       if (algorithm)
+       {
+               btBridgedManifoldResult contactPointResult(&obA, &obB, resultCallback);
+               contactPointResult.m_closestPointDistanceThreshold = resultCallback.m_closestDistanceThreshold;
+               //discrete collision detection query
+               algorithm->processCollision(&obA, &obB, getDispatchInfo(), &contactPointResult);
+
+               algorithm->~btCollisionAlgorithm();
+               getDispatcher()->freeCollisionAlgorithm(algorithm);
+       }
+}
+
+class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback
+{
+       btIDebugDraw* m_debugDrawer;
+       btVector3 m_color;
+       btTransform m_worldTrans;
+
+public:
+       DebugDrawcallback(btIDebugDraw* debugDrawer, const btTransform& worldTrans, const btVector3& color) : m_debugDrawer(debugDrawer),
+                                                                                                                                                                                                                 m_color(color),
+                                                                                                                                                                                                                 m_worldTrans(worldTrans)
+       {
+       }
+
+       virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+       {
+               processTriangle(triangle, partId, triangleIndex);
+       }
+
+       virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+       {
+               (void)partId;
+               (void)triangleIndex;
+
+               btVector3 wv0, wv1, wv2;
+               wv0 = m_worldTrans * triangle[0];
+               wv1 = m_worldTrans * triangle[1];
+               wv2 = m_worldTrans * triangle[2];
+               btVector3 center = (wv0 + wv1 + wv2) * btScalar(1. / 3.);
+
+               if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
+               {
+                       btVector3 normal = (wv1 - wv0).cross(wv2 - wv0);
+                       normal.normalize();
+                       btVector3 normalColor(1, 1, 0);
+                       m_debugDrawer->drawLine(center, center + normal, normalColor);
+               }
+               m_debugDrawer->drawTriangle(wv0, wv1, wv2, m_color, 1.0);
+       }
+};
+
+void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color)
+{
+       // Draw a small simplex at the center of the object
+       if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawFrames)
+       {
+               getDebugDrawer()->drawTransform(worldTransform, .1);
+       }
+
+       if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
+       {
+               const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
+               for (int i = compoundShape->getNumChildShapes() - 1; i >= 0; i--)
+               {
+                       btTransform childTrans = compoundShape->getChildTransform(i);
+                       const btCollisionShape* colShape = compoundShape->getChildShape(i);
+                       debugDrawObject(worldTransform * childTrans, colShape, color);
+               }
+       }
+       else
+       {
+               switch (shape->getShapeType())
+               {
+                       case BOX_SHAPE_PROXYTYPE:
+                       {
+                               const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
+                               btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
+                               getDebugDrawer()->drawBox(-halfExtents, halfExtents, worldTransform, color);
+                               break;
+                       }
+
+                       case SPHERE_SHAPE_PROXYTYPE:
+                       {
+                               const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
+                               btScalar radius = sphereShape->getMargin();  //radius doesn't include the margin, so draw with margin
+
+                               getDebugDrawer()->drawSphere(radius, worldTransform, color);
+                               break;
+                       }
+                       case MULTI_SPHERE_SHAPE_PROXYTYPE:
+                       {
+                               const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
+
+                               btTransform childTransform;
+                               childTransform.setIdentity();
+
+                               for (int i = multiSphereShape->getSphereCount() - 1; i >= 0; i--)
+                               {
+                                       childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
+                                       getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform * childTransform, color);
+                               }
+
+                               break;
+                       }
+                       case CAPSULE_SHAPE_PROXYTYPE:
+                       {
+                               const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
+
+                               btScalar radius = capsuleShape->getRadius();
+                               btScalar halfHeight = capsuleShape->getHalfHeight();
+
+                               int upAxis = capsuleShape->getUpAxis();
+                               getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
+                               break;
+                       }
+                       case CONE_SHAPE_PROXYTYPE:
+                       {
+                               const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
+                               btScalar radius = coneShape->getRadius();  //+coneShape->getMargin();
+                               btScalar height = coneShape->getHeight();  //+coneShape->getMargin();
+
+                               int upAxis = coneShape->getConeUpIndex();
+                               getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
+                               break;
+                       }
+                       case CYLINDER_SHAPE_PROXYTYPE:
+                       {
+                               const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
+                               int upAxis = cylinder->getUpAxis();
+                               btScalar radius = cylinder->getRadius();
+                               btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
+                               getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
+                               break;
+                       }
+
+                       case STATIC_PLANE_PROXYTYPE:
+                       {
+                               const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
+                               btScalar planeConst = staticPlaneShape->getPlaneConstant();
+                               const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
+                               getDebugDrawer()->drawPlane(planeNormal, planeConst, worldTransform, color);
+                               break;
+                       }
+                       default:
+                       {
+                               /// for polyhedral shapes
+                               if (shape->isPolyhedral())
+                               {
+                                       btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*)shape;
+
+                                       int i;
+                                       if (polyshape->getConvexPolyhedron())
+                                       {
+                                               const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
+                                               for (i = 0; i < poly->m_faces.size(); i++)
+                                               {
+                                                       btVector3 centroid(0, 0, 0);
+                                                       int numVerts = poly->m_faces[i].m_indices.size();
+                                                       if (numVerts)
+                                                       {
+                                                               int lastV = poly->m_faces[i].m_indices[numVerts - 1];
+                                                               for (int v = 0; v < poly->m_faces[i].m_indices.size(); v++)
+                                                               {
+                                                                       int curVert = poly->m_faces[i].m_indices[v];
+                                                                       centroid += poly->m_vertices[curVert];
+                                                                       getDebugDrawer()->drawLine(worldTransform * poly->m_vertices[lastV], worldTransform * poly->m_vertices[curVert], color);
+                                                                       lastV = curVert;
+                                                               }
+                                                       }
+                                                       centroid *= btScalar(1.f) / btScalar(numVerts);
+                                                       if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
+                                                       {
+                                                               btVector3 normalColor(1, 1, 0);
+                                                               btVector3 faceNormal(poly->m_faces[i].m_plane[0], poly->m_faces[i].m_plane[1], poly->m_faces[i].m_plane[2]);
+                                                               getDebugDrawer()->drawLine(worldTransform * centroid, worldTransform * (centroid + faceNormal), normalColor);
+                                                       }
+                                               }
+                                       }
+                                       else
+                                       {
+                                               for (i = 0; i < polyshape->getNumEdges(); i++)
+                                               {
+                                                       btVector3 a, b;
+                                                       polyshape->getEdge(i, a, b);
+                                                       btVector3 wa = worldTransform * a;
+                                                       btVector3 wb = worldTransform * b;
+                                                       getDebugDrawer()->drawLine(wa, wb, color);
+                                               }
+                                       }
+                               }
+
+                               if (shape->isConcave())
+                               {
+                                       btConcaveShape* concaveMesh = (btConcaveShape*)shape;
+
+                                       ///@todo pass camera, for some culling? no -> we are not a graphics lib
+                                       btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+                                       btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+
+                                       DebugDrawcallback drawCallback(getDebugDrawer(), worldTransform, color);
+                                       concaveMesh->processAllTriangles(&drawCallback, aabbMin, aabbMax);
+                               }
+
+                               if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
+                               {
+                                       btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*)shape;
+                                       //todo: pass camera for some culling
+                                       btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+                                       btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+                                       //DebugDrawcallback drawCallback;
+                                       DebugDrawcallback drawCallback(getDebugDrawer(), worldTransform, color);
+                                       convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback, aabbMin, aabbMax);
+                               }
+                       }
+               }
+       }
+}
+
+void btCollisionWorld::debugDrawWorld()
+{
+       if (getDebugDrawer())
+       {
+               getDebugDrawer()->clearLines();
+
+               btIDebugDraw::DefaultColors defaultColors = getDebugDrawer()->getDefaultColors();
+
+               if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
+               {
+                       if (getDispatcher())
+                       {
+                               int numManifolds = getDispatcher()->getNumManifolds();
+
+                               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(), defaultColors.m_contactPoint);
+                                       }
+                               }
+                       }
+               }
+
+               if ((getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)))
+               {
+                       int i;
+
+                       for (i = 0; i < m_collisionObjects.size(); i++)
+                       {
+                               btCollisionObject* colObj = m_collisionObjects[i];
+                               if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT) == 0)
+                               {
+                                       if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe))
+                                       {
+                                               btVector3 color(btScalar(0.4), btScalar(0.4), btScalar(0.4));
+
+                                               switch (colObj->getActivationState())
+                                               {
+                                                       case ACTIVE_TAG:
+                                                               color = defaultColors.m_activeObject;
+                                                               break;
+                                                       case ISLAND_SLEEPING:
+                                                               color = defaultColors.m_deactivatedObject;
+                                                               break;
+                                                       case WANTS_DEACTIVATION:
+                                                               color = defaultColors.m_wantsDeactivationObject;
+                                                               break;
+                                                       case DISABLE_DEACTIVATION:
+                                                               color = defaultColors.m_disabledDeactivationObject;
+                                                               break;
+                                                       case DISABLE_SIMULATION:
+                                                               color = defaultColors.m_disabledSimulationObject;
+                                                               break;
+                                                       default:
+                                                       {
+                                                               color = btVector3(btScalar(.3), btScalar(0.3), btScalar(0.3));
+                                                       }
+                                               };
+
+                                               colObj->getCustomDebugColor(color);
+
+                                               debugDrawObject(colObj->getWorldTransform(), colObj->getCollisionShape(), color);
+                                       }
+                                       if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+                                       {
+                                               btVector3 minAabb, maxAabb;
+                                               btVector3 colorvec = defaultColors.m_aabb;
+                                               colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
+                                               btVector3 contactThreshold(gContactBreakingThreshold, gContactBreakingThreshold, gContactBreakingThreshold);
+                                               minAabb -= contactThreshold;
+                                               maxAabb += contactThreshold;
+
+                                               btVector3 minAabb2, maxAabb2;
+
+                                               if (getDispatchInfo().m_useContinuous && colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
+                                               {
+                                                       colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(), minAabb2, maxAabb2);
+                                                       minAabb2 -= contactThreshold;
+                                                       maxAabb2 += contactThreshold;
+                                                       minAabb.setMin(minAabb2);
+                                                       maxAabb.setMax(maxAabb2);
+                                               }
+
+                                               m_debugDrawer->drawAabb(minAabb, maxAabb, colorvec);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
+{
+       int i;
+
+       ///keep track of shapes already serialized
+       btHashMap<btHashPtr, btCollisionShape*> serializedShapes;
+
+       for (i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               btCollisionShape* shape = colObj->getCollisionShape();
+
+               if (!serializedShapes.find(shape))
+               {
+                       serializedShapes.insert(shape, shape);
+                       shape->serializeSingleShape(serializer);
+               }
+       }
+
+       //serialize all collision objects
+       for (i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               if (colObj->getInternalType() == btCollisionObject::CO_COLLISION_OBJECT)
+               {
+                       colObj->serializeSingleObject(serializer);
+               }
+       }
+}
+
+void btCollisionWorld::serializeContactManifolds(btSerializer* serializer)
+{
+       if (serializer->getSerializationFlags() & BT_SERIALIZE_CONTACT_MANIFOLDS)
+       {
+               int numManifolds = getDispatcher()->getNumManifolds();
+               for (int i = 0; i < numManifolds; i++)
+               {
+                       const btPersistentManifold* manifold = getDispatcher()->getInternalManifoldPointer()[i];
+                       //don't serialize empty manifolds, they just take space
+                       //(may have to do it anyway if it destroys determinism)
+                       if (manifold->getNumContacts() == 0)
+                               continue;
+
+                       btChunk* chunk = serializer->allocate(manifold->calculateSerializeBufferSize(), 1);
+                       const char* structType = manifold->serialize(manifold, chunk->m_oldPtr, serializer);
+                       serializer->finalizeChunk(chunk, structType, BT_CONTACTMANIFOLD_CODE, (void*)manifold);
+               }
+       }
+}
+
+void btCollisionWorld::serialize(btSerializer* serializer)
+{
+       serializer->startSerialization();
+
+       serializeCollisionObjects(serializer);
+
+       serializeContactManifolds(serializer);
+
+       serializer->finishSerialization();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
new file mode 100644 (file)
index 0000000..fd0e5b9
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * @mainpage Bullet Documentation
+ *
+ * @section intro_sec Introduction
+ * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
+ *
+ * The main documentation is Bullet_User_Manual.pdf, included in the source code distribution.
+ * There is the Physics Forum for feedback and general Collision Detection and Physics discussions.
+ * Please visit http://www.bulletphysics.org
+ *
+ * @section install_sec Installation
+ *
+ * @subsection step1 Step 1: Download
+ * You can download the Bullet Physics Library from the github repository: https://github.com/bulletphysics/bullet3/releases 
+ *
+ * @subsection step2 Step 2: Building
+ * Bullet has multiple build systems, including premake, cmake and autotools. Premake and cmake support all platforms.
+ * Premake is included in the Bullet/build folder for Windows, Mac OSX and Linux. 
+ * Under Windows you can click on Bullet/build/vs2010.bat to create Microsoft Visual Studio projects. 
+ * On Mac OSX and Linux you can open a terminal and generate Makefile, codeblocks or Xcode4 projects:
+ * cd Bullet/build
+ * ./premake4_osx gmake or ./premake4_linux gmake or ./premake4_linux64 gmake or (for Mac) ./premake4_osx xcode4
+ * cd Bullet/build/gmake
+ * make
+ * 
+ * An alternative to premake is cmake. You can download cmake from http://www.cmake.org
+ * cmake can autogenerate projectfiles for Microsoft Visual Studio, Apple Xcode, KDevelop and Unix Makefiles.
+ * The easiest is to run the CMake cmake-gui graphical user interface and choose the options and generate projectfiles.
+ * You can also use cmake in the command-line. Here are some examples for various platforms:
+ * cmake . -G "Visual Studio 9 2008"
+ * cmake . -G Xcode
+ * cmake . -G "Unix Makefiles"
+ * Although cmake is recommended, you can also use autotools for UNIX: ./autogen.sh ./configure to create a Makefile and then run make.
+ * 
+ * @subsection step3 Step 3: Testing demos
+ * Try to run and experiment with BasicDemo executable as a starting point.
+ * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation.
+ * The Dependencies can be seen in this documentation under Directories
+ * 
+ * @subsection step4 Step 4: Integrating in your application, full Rigid Body and Soft Body simulation
+ * Check out BasicDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform.
+ * Check out SoftDemo how to use soft body dynamics, using btSoftRigidDynamicsWorld.
+ * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras)
+ * Bullet Collision Detection can also be used without the Dynamics/Extras.
+ * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo.
+ * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation.
+ * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector.
+ *
+ * @section copyright Copyright
+ * For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf
+ * 
+ */
+
+#ifndef BT_COLLISION_WORLD_H
+#define BT_COLLISION_WORLD_H
+
+class btCollisionShape;
+class btConvexShape;
+class btBroadphaseInterface;
+class btSerializer;
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "btCollisionObject.h"
+#include "btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+///CollisionWorld is interface and container for the collision detection
+class btCollisionWorld
+{
+protected:
+       btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
+
+       btDispatcher* m_dispatcher1;
+
+       btDispatcherInfo m_dispatchInfo;
+
+       btBroadphaseInterface* m_broadphasePairCache;
+
+       btIDebugDraw* m_debugDrawer;
+
+       ///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs
+       ///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB)
+       bool m_forceUpdateAllAabbs;
+
+       void serializeCollisionObjects(btSerializer* serializer);
+
+       void serializeContactManifolds(btSerializer* serializer);
+
+public:
+       //this constructor doesn't own the dispatcher and paircache/broadphase
+       btCollisionWorld(btDispatcher* dispatcher, btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
+
+       virtual ~btCollisionWorld();
+
+       void setBroadphase(btBroadphaseInterface* pairCache)
+       {
+               m_broadphasePairCache = pairCache;
+       }
+
+       const btBroadphaseInterface* getBroadphase() const
+       {
+               return m_broadphasePairCache;
+       }
+
+       btBroadphaseInterface* getBroadphase()
+       {
+               return m_broadphasePairCache;
+       }
+
+       btOverlappingPairCache* getPairCache()
+       {
+               return m_broadphasePairCache->getOverlappingPairCache();
+       }
+
+       btDispatcher* getDispatcher()
+       {
+               return m_dispatcher1;
+       }
+
+       const btDispatcher* getDispatcher() const
+       {
+               return m_dispatcher1;
+       }
+
+       void updateSingleAabb(btCollisionObject* colObj);
+
+       virtual void updateAabbs();
+
+       ///the computeOverlappingPairs is usually already called by performDiscreteCollisionDetection (or stepSimulation)
+       ///it can be useful to use if you perform ray tests without collision detection/simulation
+       virtual void computeOverlappingPairs();
+
+       virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
+       {
+               m_debugDrawer = debugDrawer;
+       }
+
+       virtual btIDebugDraw* getDebugDrawer()
+       {
+               return m_debugDrawer;
+       }
+
+       virtual void debugDrawWorld();
+
+       virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
+
+       ///LocalShapeInfo gives extra information for complex shapes
+       ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
+       struct LocalShapeInfo
+       {
+               int m_shapePart;
+               int m_triangleIndex;
+
+               //const btCollisionShape*       m_shapeTemp;
+               //const btTransform*    m_shapeLocalTransform;
+       };
+
+       struct LocalRayResult
+       {
+               LocalRayResult(const btCollisionObject* collisionObject,
+                                          LocalShapeInfo* localShapeInfo,
+                                          const btVector3& hitNormalLocal,
+                                          btScalar hitFraction)
+                       : m_collisionObject(collisionObject),
+                         m_localShapeInfo(localShapeInfo),
+                         m_hitNormalLocal(hitNormalLocal),
+                         m_hitFraction(hitFraction)
+               {
+               }
+
+               const btCollisionObject* m_collisionObject;
+               LocalShapeInfo* m_localShapeInfo;
+               btVector3 m_hitNormalLocal;
+               btScalar m_hitFraction;
+       };
+
+       ///RayResultCallback is used to report new raycast results
+       struct RayResultCallback
+       {
+               btScalar m_closestHitFraction;
+               const btCollisionObject* m_collisionObject;
+               int m_collisionFilterGroup;
+               int m_collisionFilterMask;
+               //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke.
+               unsigned int m_flags;
+
+               virtual ~RayResultCallback()
+               {
+               }
+               bool hasHit() const
+               {
+                       return (m_collisionObject != 0);
+               }
+
+               RayResultCallback()
+                       : m_closestHitFraction(btScalar(1.)),
+                         m_collisionObject(0),
+                         m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+                         m_collisionFilterMask(btBroadphaseProxy::AllFilter),
+                         //@BP Mod
+                         m_flags(0)
+               {
+               }
+
+               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(LocalRayResult& rayResult, bool normalInWorldSpace) = 0;
+       };
+
+       struct ClosestRayResultCallback : public RayResultCallback
+       {
+               ClosestRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
+                       : m_rayFromWorld(rayFromWorld),
+                         m_rayToWorld(rayToWorld)
+               {
+               }
+
+               btVector3 m_rayFromWorld;  //used to calculate hitPointWorld from hitFraction
+               btVector3 m_rayToWorld;
+
+               btVector3 m_hitNormalWorld;
+               btVector3 m_hitPointWorld;
+
+               virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace)
+               {
+                       //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;
+                       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 AllHitsRayResultCallback : public RayResultCallback
+       {
+               AllHitsRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
+                       : m_rayFromWorld(rayFromWorld),
+                         m_rayToWorld(rayToWorld)
+               {
+               }
+
+               btAlignedObjectArray<const btCollisionObject*> m_collisionObjects;
+
+               btVector3 m_rayFromWorld;  //used to calculate hitPointWorld from hitFraction
+               btVector3 m_rayToWorld;
+
+               btAlignedObjectArray<btVector3> m_hitNormalWorld;
+               btAlignedObjectArray<btVector3> m_hitPointWorld;
+               btAlignedObjectArray<btScalar> m_hitFractions;
+
+               virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace)
+               {
+                       m_collisionObject = rayResult.m_collisionObject;
+                       m_collisionObjects.push_back(rayResult.m_collisionObject);
+                       btVector3 hitNormalWorld;
+                       if (normalInWorldSpace)
+                       {
+                               hitNormalWorld = rayResult.m_hitNormalLocal;
+                       }
+                       else
+                       {
+                               ///need to transform normal into worldspace
+                               hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
+                       }
+                       m_hitNormalWorld.push_back(hitNormalWorld);
+                       btVector3 hitPointWorld;
+                       hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);
+                       m_hitPointWorld.push_back(hitPointWorld);
+                       m_hitFractions.push_back(rayResult.m_hitFraction);
+                       return m_closestHitFraction;
+               }
+       };
+
+       struct LocalConvexResult
+       {
+               LocalConvexResult(const 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)
+               {
+               }
+
+               const 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;
+               int m_collisionFilterGroup;
+               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;
+               const 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;
+               }
+       };
+
+       ///ContactResultCallback is used to report contact points
+       struct ContactResultCallback
+       {
+               int m_collisionFilterGroup;
+               int m_collisionFilterMask;
+               btScalar m_closestDistanceThreshold;
+
+               ContactResultCallback()
+                       : m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+                         m_collisionFilterMask(btBroadphaseProxy::AllFilter),
+                         m_closestDistanceThreshold(0)
+               {
+               }
+
+               virtual ~ContactResultCallback()
+               {
+               }
+
+               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(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1) = 0;
+       };
+
+       int getNumCollisionObjects() const
+       {
+               return int(m_collisionObjects.size());
+       }
+
+       /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
+       /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
+       virtual 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, btScalar allowedCcdPenetration = btScalar(0.)) const;
+
+       ///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback.
+       ///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
+       void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
+
+       ///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
+       ///it reports one or more contact points (including the one with deepest penetration)
+       void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
+
+       /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
+       /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
+       /// This allows more customization.
+       static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+                                                         btCollisionObject* collisionObject,
+                                                         const btCollisionShape* collisionShape,
+                                                         const btTransform& colObjWorldTransform,
+                                                         RayResultCallback& resultCallback);
+
+       static void rayTestSingleInternal(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+                                                                         const btCollisionObjectWrapper* collisionObjectWrap,
+                                                                         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,
+                                                                 ConvexResultCallback& resultCallback, btScalar allowedPenetration);
+
+       static void objectQuerySingleInternal(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
+                                                                                 const btCollisionObjectWrapper* colObjWrap,
+                                                                                 ConvexResultCallback& resultCallback, btScalar allowedPenetration);
+
+       virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
+
+       virtual void refreshBroadphaseProxy(btCollisionObject* collisionObject);
+
+       btCollisionObjectArray& getCollisionObjectArray()
+       {
+               return m_collisionObjects;
+       }
+
+       const btCollisionObjectArray& getCollisionObjectArray() const
+       {
+               return m_collisionObjects;
+       }
+
+       virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+       virtual void performDiscreteCollisionDetection();
+
+       btDispatcherInfo& getDispatchInfo()
+       {
+               return m_dispatchInfo;
+       }
+
+       const btDispatcherInfo& getDispatchInfo() const
+       {
+               return m_dispatchInfo;
+       }
+
+       bool getForceUpdateAllAabbs() const
+       {
+               return m_forceUpdateAllAabbs;
+       }
+       void setForceUpdateAllAabbs(bool forceUpdateAllAabbs)
+       {
+               m_forceUpdateAllAabbs = forceUpdateAllAabbs;
+       }
+
+       ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo)
+       virtual void serialize(btSerializer* serializer);
+};
+
+#endif  //BT_COLLISION_WORLD_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
new file mode 100644 (file)
index 0000000..e56e73d
--- /dev/null
@@ -0,0 +1,1087 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2014 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btCollisionWorldImporter.h"
+#include "btBulletCollisionCommon.h"
+#include "LinearMath/btSerializer.h"  //for btBulletSerializedArrays definition
+
+#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
+#include "BulletCollision/Gimpact/btGImpactShape.h"
+#endif  //SUPPORT_GIMPACT_SHAPE_IMPORT
+
+btCollisionWorldImporter::btCollisionWorldImporter(btCollisionWorld* world)
+       : m_collisionWorld(world),
+         m_verboseMode(0)
+{
+}
+
+btCollisionWorldImporter::~btCollisionWorldImporter()
+{
+}
+
+bool btCollisionWorldImporter::convertAllObjects(btBulletSerializedArrays* arrays)
+{
+       m_shapeMap.clear();
+       m_bodyMap.clear();
+
+       int i;
+
+       for (i = 0; i < arrays->m_bvhsDouble.size(); i++)
+       {
+               btOptimizedBvh* bvh = createOptimizedBvh();
+               btQuantizedBvhDoubleData* bvhData = arrays->m_bvhsDouble[i];
+               bvh->deSerializeDouble(*bvhData);
+               m_bvhMap.insert(arrays->m_bvhsDouble[i], bvh);
+       }
+       for (i = 0; i < arrays->m_bvhsFloat.size(); i++)
+       {
+               btOptimizedBvh* bvh = createOptimizedBvh();
+               btQuantizedBvhFloatData* bvhData = arrays->m_bvhsFloat[i];
+               bvh->deSerializeFloat(*bvhData);
+               m_bvhMap.insert(arrays->m_bvhsFloat[i], bvh);
+       }
+
+       for (i = 0; i < arrays->m_colShapeData.size(); i++)
+       {
+               btCollisionShapeData* shapeData = arrays->m_colShapeData[i];
+               btCollisionShape* shape = convertCollisionShape(shapeData);
+               if (shape)
+               {
+                       //              printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
+                       m_shapeMap.insert(shapeData, shape);
+               }
+
+               if (shape && shapeData->m_name)
+               {
+                       char* newname = duplicateName(shapeData->m_name);
+                       m_objectNameMap.insert(shape, newname);
+                       m_nameShapeMap.insert(newname, shape);
+               }
+       }
+
+       for (i = 0; i < arrays->m_collisionObjectDataDouble.size(); i++)
+       {
+               btCollisionObjectDoubleData* colObjData = arrays->m_collisionObjectDataDouble[i];
+               btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
+               if (shapePtr && *shapePtr)
+               {
+                       btTransform startTransform;
+                       colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
+                       startTransform.deSerializeDouble(colObjData->m_worldTransform);
+
+                       btCollisionShape* shape = (btCollisionShape*)*shapePtr;
+                       btCollisionObject* body = createCollisionObject(startTransform, shape, colObjData->m_name);
+                       body->setFriction(btScalar(colObjData->m_friction));
+                       body->setRestitution(btScalar(colObjData->m_restitution));
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+                       if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+                       {
+                               btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
+                               if (trimesh->getTriangleInfoMap())
+                               {
+                                       body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+                               }
+                       }
+#endif  //USE_INTERNAL_EDGE_UTILITY
+                       m_bodyMap.insert(colObjData, body);
+               }
+               else
+               {
+                       printf("error: no shape found\n");
+               }
+       }
+       for (i = 0; i < arrays->m_collisionObjectDataFloat.size(); i++)
+       {
+               btCollisionObjectFloatData* colObjData = arrays->m_collisionObjectDataFloat[i];
+               btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
+               if (shapePtr && *shapePtr)
+               {
+                       btTransform startTransform;
+                       colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
+                       startTransform.deSerializeFloat(colObjData->m_worldTransform);
+
+                       btCollisionShape* shape = (btCollisionShape*)*shapePtr;
+                       btCollisionObject* body = createCollisionObject(startTransform, shape, colObjData->m_name);
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+                       if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+                       {
+                               btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
+                               if (trimesh->getTriangleInfoMap())
+                               {
+                                       body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+                               }
+                       }
+#endif  //USE_INTERNAL_EDGE_UTILITY
+                       m_bodyMap.insert(colObjData, body);
+               }
+               else
+               {
+                       printf("error: no shape found\n");
+               }
+       }
+
+       return true;
+}
+
+void btCollisionWorldImporter::deleteAllData()
+{
+       int i;
+
+       for (i = 0; i < m_allocatedCollisionObjects.size(); i++)
+       {
+               if (m_collisionWorld)
+                       m_collisionWorld->removeCollisionObject(m_allocatedCollisionObjects[i]);
+               delete m_allocatedCollisionObjects[i];
+       }
+
+       m_allocatedCollisionObjects.clear();
+
+       for (i = 0; i < m_allocatedCollisionShapes.size(); i++)
+       {
+               delete m_allocatedCollisionShapes[i];
+       }
+       m_allocatedCollisionShapes.clear();
+
+       for (i = 0; i < m_allocatedBvhs.size(); i++)
+       {
+               delete m_allocatedBvhs[i];
+       }
+       m_allocatedBvhs.clear();
+
+       for (i = 0; i < m_allocatedTriangleInfoMaps.size(); i++)
+       {
+               delete m_allocatedTriangleInfoMaps[i];
+       }
+       m_allocatedTriangleInfoMaps.clear();
+       for (i = 0; i < m_allocatedTriangleIndexArrays.size(); i++)
+       {
+               delete m_allocatedTriangleIndexArrays[i];
+       }
+       m_allocatedTriangleIndexArrays.clear();
+       for (i = 0; i < m_allocatedNames.size(); i++)
+       {
+               delete[] m_allocatedNames[i];
+       }
+       m_allocatedNames.clear();
+
+       for (i = 0; i < m_allocatedbtStridingMeshInterfaceDatas.size(); i++)
+       {
+               btStridingMeshInterfaceData* curData = m_allocatedbtStridingMeshInterfaceDatas[i];
+
+               for (int a = 0; a < curData->m_numMeshParts; a++)
+               {
+                       btMeshPartData* curPart = &curData->m_meshPartsPtr[a];
+                       if (curPart->m_vertices3f)
+                               delete[] curPart->m_vertices3f;
+
+                       if (curPart->m_vertices3d)
+                               delete[] curPart->m_vertices3d;
+
+                       if (curPart->m_indices32)
+                               delete[] curPart->m_indices32;
+
+                       if (curPart->m_3indices16)
+                               delete[] curPart->m_3indices16;
+
+                       if (curPart->m_indices16)
+                               delete[] curPart->m_indices16;
+
+                       if (curPart->m_3indices8)
+                               delete[] curPart->m_3indices8;
+               }
+               delete[] curData->m_meshPartsPtr;
+               delete curData;
+       }
+       m_allocatedbtStridingMeshInterfaceDatas.clear();
+
+       for (i = 0; i < m_indexArrays.size(); i++)
+       {
+               btAlignedFree(m_indexArrays[i]);
+       }
+       m_indexArrays.clear();
+
+       for (i = 0; i < m_shortIndexArrays.size(); i++)
+       {
+               btAlignedFree(m_shortIndexArrays[i]);
+       }
+       m_shortIndexArrays.clear();
+
+       for (i = 0; i < m_charIndexArrays.size(); i++)
+       {
+               btAlignedFree(m_charIndexArrays[i]);
+       }
+       m_charIndexArrays.clear();
+
+       for (i = 0; i < m_floatVertexArrays.size(); i++)
+       {
+               btAlignedFree(m_floatVertexArrays[i]);
+       }
+       m_floatVertexArrays.clear();
+
+       for (i = 0; i < m_doubleVertexArrays.size(); i++)
+       {
+               btAlignedFree(m_doubleVertexArrays[i]);
+       }
+       m_doubleVertexArrays.clear();
+}
+
+btCollisionShape* btCollisionWorldImporter::convertCollisionShape(btCollisionShapeData* shapeData)
+{
+       btCollisionShape* shape = 0;
+
+       switch (shapeData->m_shapeType)
+       {
+               case STATIC_PLANE_PROXYTYPE:
+               {
+                       btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)shapeData;
+                       btVector3 planeNormal, localScaling;
+                       planeNormal.deSerializeFloat(planeData->m_planeNormal);
+                       localScaling.deSerializeFloat(planeData->m_localScaling);
+                       shape = createPlaneShape(planeNormal, planeData->m_planeConstant);
+                       shape->setLocalScaling(localScaling);
+
+                       break;
+               }
+               case SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE:
+               {
+                       btScaledTriangleMeshShapeData* scaledMesh = (btScaledTriangleMeshShapeData*)shapeData;
+                       btCollisionShapeData* colShapeData = (btCollisionShapeData*)&scaledMesh->m_trimeshShapeData;
+                       colShapeData->m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+                       btCollisionShape* childShape = convertCollisionShape(colShapeData);
+                       btBvhTriangleMeshShape* meshShape = (btBvhTriangleMeshShape*)childShape;
+                       btVector3 localScaling;
+                       localScaling.deSerializeFloat(scaledMesh->m_localScaling);
+
+                       shape = createScaledTrangleMeshShape(meshShape, localScaling);
+                       break;
+               }
+#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
+               case GIMPACT_SHAPE_PROXYTYPE:
+               {
+                       btGImpactMeshShapeData* gimpactData = (btGImpactMeshShapeData*)shapeData;
+                       if (gimpactData->m_gimpactSubType == CONST_GIMPACT_TRIMESH_SHAPE)
+                       {
+                               btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&gimpactData->m_meshInterface);
+                               btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData);
+
+                               btGImpactMeshShape* gimpactShape = createGimpactShape(meshInterface);
+                               btVector3 localScaling;
+                               localScaling.deSerializeFloat(gimpactData->m_localScaling);
+                               gimpactShape->setLocalScaling(localScaling);
+                               gimpactShape->setMargin(btScalar(gimpactData->m_collisionMargin));
+                               gimpactShape->updateBound();
+                               shape = gimpactShape;
+                       }
+                       else
+                       {
+                               printf("unsupported gimpact sub type\n");
+                       }
+                       break;
+               }
+#endif  //SUPPORT_GIMPACT_SHAPE_IMPORT
+               //The btCapsuleShape* API has issue passing the margin/scaling/halfextents unmodified through the API
+               //so deal with this
+               case CAPSULE_SHAPE_PROXYTYPE:
+               {
+                       btCapsuleShapeData* capData = (btCapsuleShapeData*)shapeData;
+
+                       switch (capData->m_upAxis)
+                       {
+                               case 0:
+                               {
+                                       shape = createCapsuleShapeX(1, 1);
+                                       break;
+                               }
+                               case 1:
+                               {
+                                       shape = createCapsuleShapeY(1, 1);
+                                       break;
+                               }
+                               case 2:
+                               {
+                                       shape = createCapsuleShapeZ(1, 1);
+                                       break;
+                               }
+                               default:
+                               {
+                                       printf("error: wrong up axis for btCapsuleShape\n");
+                               }
+                       };
+                       if (shape)
+                       {
+                               btCapsuleShape* cap = (btCapsuleShape*)shape;
+                               cap->deSerializeFloat(capData);
+                       }
+                       break;
+               }
+               case CYLINDER_SHAPE_PROXYTYPE:
+               case CONE_SHAPE_PROXYTYPE:
+               case BOX_SHAPE_PROXYTYPE:
+               case SPHERE_SHAPE_PROXYTYPE:
+               case MULTI_SPHERE_SHAPE_PROXYTYPE:
+               case CONVEX_HULL_SHAPE_PROXYTYPE:
+               {
+                       btConvexInternalShapeData* bsd = (btConvexInternalShapeData*)shapeData;
+                       btVector3 implicitShapeDimensions;
+                       implicitShapeDimensions.deSerializeFloat(bsd->m_implicitShapeDimensions);
+                       btVector3 localScaling;
+                       localScaling.deSerializeFloat(bsd->m_localScaling);
+                       btVector3 margin(bsd->m_collisionMargin, bsd->m_collisionMargin, bsd->m_collisionMargin);
+                       switch (shapeData->m_shapeType)
+                       {
+                               case BOX_SHAPE_PROXYTYPE:
+                               {
+                                       btBoxShape* box = (btBoxShape*)createBoxShape(implicitShapeDimensions / localScaling + margin);
+                                       //box->initializePolyhedralFeatures();
+                                       shape = box;
+
+                                       break;
+                               }
+                               case SPHERE_SHAPE_PROXYTYPE:
+                               {
+                                       shape = createSphereShape(implicitShapeDimensions.getX());
+                                       break;
+                               }
+
+                               case CYLINDER_SHAPE_PROXYTYPE:
+                               {
+                                       btCylinderShapeData* cylData = (btCylinderShapeData*)shapeData;
+                                       btVector3 halfExtents = implicitShapeDimensions + margin;
+                                       switch (cylData->m_upAxis)
+                                       {
+                                               case 0:
+                                               {
+                                                       shape = createCylinderShapeX(halfExtents.getY(), halfExtents.getX());
+                                                       break;
+                                               }
+                                               case 1:
+                                               {
+                                                       shape = createCylinderShapeY(halfExtents.getX(), halfExtents.getY());
+                                                       break;
+                                               }
+                                               case 2:
+                                               {
+                                                       shape = createCylinderShapeZ(halfExtents.getX(), halfExtents.getZ());
+                                                       break;
+                                               }
+                                               default:
+                                               {
+                                                       printf("unknown Cylinder up axis\n");
+                                               }
+                                       };
+
+                                       break;
+                               }
+                               case CONE_SHAPE_PROXYTYPE:
+                               {
+                                       btConeShapeData* conData = (btConeShapeData*)shapeData;
+                                       btVector3 halfExtents = implicitShapeDimensions;  //+margin;
+                                       switch (conData->m_upIndex)
+                                       {
+                                               case 0:
+                                               {
+                                                       shape = createConeShapeX(halfExtents.getY(), halfExtents.getX());
+                                                       break;
+                                               }
+                                               case 1:
+                                               {
+                                                       shape = createConeShapeY(halfExtents.getX(), halfExtents.getY());
+                                                       break;
+                                               }
+                                               case 2:
+                                               {
+                                                       shape = createConeShapeZ(halfExtents.getX(), halfExtents.getZ());
+                                                       break;
+                                               }
+                                               default:
+                                               {
+                                                       printf("unknown Cone up axis\n");
+                                               }
+                                       };
+
+                                       break;
+                               }
+                               case MULTI_SPHERE_SHAPE_PROXYTYPE:
+                               {
+                                       btMultiSphereShapeData* mss = (btMultiSphereShapeData*)bsd;
+                                       int numSpheres = mss->m_localPositionArraySize;
+
+                                       btAlignedObjectArray<btVector3> tmpPos;
+                                       btAlignedObjectArray<btScalar> radii;
+                                       radii.resize(numSpheres);
+                                       tmpPos.resize(numSpheres);
+                                       int i;
+                                       for (i = 0; i < numSpheres; i++)
+                                       {
+                                               tmpPos[i].deSerializeFloat(mss->m_localPositionArrayPtr[i].m_pos);
+                                               radii[i] = mss->m_localPositionArrayPtr[i].m_radius;
+                                       }
+                                       shape = createMultiSphereShape(&tmpPos[0], &radii[0], numSpheres);
+                                       break;
+                               }
+                               case CONVEX_HULL_SHAPE_PROXYTYPE:
+                               {
+                                       //      int sz = sizeof(btConvexHullShapeData);
+                                       //      int sz2 = sizeof(btConvexInternalShapeData);
+                                       //      int sz3 = sizeof(btCollisionShapeData);
+                                       btConvexHullShapeData* convexData = (btConvexHullShapeData*)bsd;
+                                       int numPoints = convexData->m_numUnscaledPoints;
+
+                                       btAlignedObjectArray<btVector3> tmpPoints;
+                                       tmpPoints.resize(numPoints);
+                                       int i;
+                                       for (i = 0; i < numPoints; i++)
+                                       {
+#ifdef BT_USE_DOUBLE_PRECISION
+                                               if (convexData->m_unscaledPointsDoublePtr)
+                                                       tmpPoints[i].deSerialize(convexData->m_unscaledPointsDoublePtr[i]);
+                                               if (convexData->m_unscaledPointsFloatPtr)
+                                                       tmpPoints[i].deSerializeFloat(convexData->m_unscaledPointsFloatPtr[i]);
+#else
+                                               if (convexData->m_unscaledPointsFloatPtr)
+                                                       tmpPoints[i].deSerialize(convexData->m_unscaledPointsFloatPtr[i]);
+                                               if (convexData->m_unscaledPointsDoublePtr)
+                                                       tmpPoints[i].deSerializeDouble(convexData->m_unscaledPointsDoublePtr[i]);
+#endif  //BT_USE_DOUBLE_PRECISION
+                                       }
+                                       btConvexHullShape* hullShape = createConvexHullShape();
+                                       for (i = 0; i < numPoints; i++)
+                                       {
+                                               hullShape->addPoint(tmpPoints[i]);
+                                       }
+                                       hullShape->setMargin(bsd->m_collisionMargin);
+                                       //hullShape->initializePolyhedralFeatures();
+                                       shape = hullShape;
+                                       break;
+                               }
+                               default:
+                               {
+                                       printf("error: cannot create shape type (%d)\n", shapeData->m_shapeType);
+                               }
+                       }
+
+                       if (shape)
+                       {
+                               shape->setMargin(bsd->m_collisionMargin);
+
+                               btVector3 localScaling;
+                               localScaling.deSerializeFloat(bsd->m_localScaling);
+                               shape->setLocalScaling(localScaling);
+                       }
+                       break;
+               }
+               case TRIANGLE_MESH_SHAPE_PROXYTYPE:
+               {
+                       btTriangleMeshShapeData* trimesh = (btTriangleMeshShapeData*)shapeData;
+                       btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&trimesh->m_meshInterface);
+                       btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData);
+                       if (!meshInterface->getNumSubParts())
+                       {
+                               return 0;
+                       }
+
+                       btVector3 scaling;
+                       scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling);
+                       meshInterface->setScaling(scaling);
+
+                       btOptimizedBvh* bvh = 0;
+#if 1
+                       if (trimesh->m_quantizedFloatBvh)
+                       {
+                               btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedFloatBvh);
+                               if (bvhPtr && *bvhPtr)
+                               {
+                                       bvh = *bvhPtr;
+                               }
+                               else
+                               {
+                                       bvh = createOptimizedBvh();
+                                       bvh->deSerializeFloat(*trimesh->m_quantizedFloatBvh);
+                               }
+                       }
+                       if (trimesh->m_quantizedDoubleBvh)
+                       {
+                               btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedDoubleBvh);
+                               if (bvhPtr && *bvhPtr)
+                               {
+                                       bvh = *bvhPtr;
+                               }
+                               else
+                               {
+                                       bvh = createOptimizedBvh();
+                                       bvh->deSerializeDouble(*trimesh->m_quantizedDoubleBvh);
+                               }
+                       }
+#endif
+
+                       btBvhTriangleMeshShape* trimeshShape = createBvhTriangleMeshShape(meshInterface, bvh);
+                       trimeshShape->setMargin(trimesh->m_collisionMargin);
+                       shape = trimeshShape;
+
+                       if (trimesh->m_triangleInfoMap)
+                       {
+                               btTriangleInfoMap* map = createTriangleInfoMap();
+                               map->deSerialize(*trimesh->m_triangleInfoMap);
+                               trimeshShape->setTriangleInfoMap(map);
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+                               gContactAddedCallback = btAdjustInternalEdgeContactsCallback;
+#endif  //USE_INTERNAL_EDGE_UTILITY
+                       }
+
+                       //printf("trimesh->m_collisionMargin=%f\n",trimesh->m_collisionMargin);
+                       break;
+               }
+               case COMPOUND_SHAPE_PROXYTYPE:
+               {
+                       btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData;
+                       btCompoundShape* compoundShape = createCompoundShape();
+
+                       //btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0];
+
+                       btAlignedObjectArray<btCollisionShape*> childShapes;
+                       for (int i = 0; i < compoundData->m_numChildShapes; i++)
+                       {
+                               //btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i];
+
+                               btCollisionShapeData* cd = compoundData->m_childShapePtr[i].m_childShape;
+
+                               btCollisionShape* childShape = convertCollisionShape(cd);
+                               if (childShape)
+                               {
+                                       btTransform localTransform;
+                                       localTransform.deSerializeFloat(compoundData->m_childShapePtr[i].m_transform);
+                                       compoundShape->addChildShape(localTransform, childShape);
+                               }
+                               else
+                               {
+#ifdef _DEBUG
+                                       printf("error: couldn't create childShape for compoundShape\n");
+#endif
+                               }
+                       }
+                       shape = compoundShape;
+
+                       break;
+               }
+               case SOFTBODY_SHAPE_PROXYTYPE:
+               {
+                       return 0;
+               }
+               default:
+               {
+#ifdef _DEBUG
+                       printf("unsupported shape type (%d)\n", shapeData->m_shapeType);
+#endif
+               }
+       }
+
+       return shape;
+}
+
+char* btCollisionWorldImporter::duplicateName(const char* name)
+{
+       if (name)
+       {
+               int l = (int)strlen(name);
+               char* newName = new char[l + 1];
+               memcpy(newName, name, l);
+               newName[l] = 0;
+               m_allocatedNames.push_back(newName);
+               return newName;
+       }
+       return 0;
+}
+
+btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStridingMeshInterfaceData& meshData)
+{
+       btTriangleIndexVertexArray* meshInterface = createTriangleMeshContainer();
+
+       for (int i = 0; i < meshData.m_numMeshParts; i++)
+       {
+               btIndexedMesh meshPart;
+               meshPart.m_numTriangles = meshData.m_meshPartsPtr[i].m_numTriangles;
+               meshPart.m_numVertices = meshData.m_meshPartsPtr[i].m_numVertices;
+
+               if (meshData.m_meshPartsPtr[i].m_indices32)
+               {
+                       meshPart.m_indexType = PHY_INTEGER;
+                       meshPart.m_triangleIndexStride = 3 * sizeof(int);
+                       int* indexArray = (int*)btAlignedAlloc(sizeof(int) * 3 * meshPart.m_numTriangles, 16);
+                       m_indexArrays.push_back(indexArray);
+                       for (int j = 0; j < 3 * meshPart.m_numTriangles; j++)
+                       {
+                               indexArray[j] = meshData.m_meshPartsPtr[i].m_indices32[j].m_value;
+                       }
+                       meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
+               }
+               else
+               {
+                       if (meshData.m_meshPartsPtr[i].m_3indices16)
+                       {
+                               meshPart.m_indexType = PHY_SHORT;
+                               meshPart.m_triangleIndexStride = sizeof(short int) * 3;  //sizeof(btShortIntIndexTripletData);
+
+                               short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int) * 3 * meshPart.m_numTriangles, 16);
+                               m_shortIndexArrays.push_back(indexArray);
+
+                               for (int j = 0; j < meshPart.m_numTriangles; j++)
+                               {
+                                       indexArray[3 * j] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[0];
+                                       indexArray[3 * j + 1] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[1];
+                                       indexArray[3 * j + 2] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[2];
+                               }
+
+                               meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
+                       }
+                       if (meshData.m_meshPartsPtr[i].m_indices16)
+                       {
+                               meshPart.m_indexType = PHY_SHORT;
+                               meshPart.m_triangleIndexStride = 3 * sizeof(short int);
+                               short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int) * 3 * meshPart.m_numTriangles, 16);
+                               m_shortIndexArrays.push_back(indexArray);
+                               for (int j = 0; j < 3 * meshPart.m_numTriangles; j++)
+                               {
+                                       indexArray[j] = meshData.m_meshPartsPtr[i].m_indices16[j].m_value;
+                               }
+
+                               meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
+                       }
+
+                       if (meshData.m_meshPartsPtr[i].m_3indices8)
+                       {
+                               meshPart.m_indexType = PHY_UCHAR;
+                               meshPart.m_triangleIndexStride = sizeof(unsigned char) * 3;
+
+                               unsigned char* indexArray = (unsigned char*)btAlignedAlloc(sizeof(unsigned char) * 3 * meshPart.m_numTriangles, 16);
+                               m_charIndexArrays.push_back(indexArray);
+
+                               for (int j = 0; j < meshPart.m_numTriangles; j++)
+                               {
+                                       indexArray[3 * j] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[0];
+                                       indexArray[3 * j + 1] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[1];
+                                       indexArray[3 * j + 2] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[2];
+                               }
+
+                               meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
+                       }
+               }
+
+               if (meshData.m_meshPartsPtr[i].m_vertices3f)
+               {
+                       meshPart.m_vertexType = PHY_FLOAT;
+                       meshPart.m_vertexStride = sizeof(btVector3FloatData);
+                       btVector3FloatData* vertices = (btVector3FloatData*)btAlignedAlloc(sizeof(btVector3FloatData) * meshPart.m_numVertices, 16);
+                       m_floatVertexArrays.push_back(vertices);
+
+                       for (int j = 0; j < meshPart.m_numVertices; j++)
+                       {
+                               vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[0];
+                               vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[1];
+                               vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[2];
+                               vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[3];
+                       }
+                       meshPart.m_vertexBase = (const unsigned char*)vertices;
+               }
+               else
+               {
+                       meshPart.m_vertexType = PHY_DOUBLE;
+                       meshPart.m_vertexStride = sizeof(btVector3DoubleData);
+
+                       btVector3DoubleData* vertices = (btVector3DoubleData*)btAlignedAlloc(sizeof(btVector3DoubleData) * meshPart.m_numVertices, 16);
+                       m_doubleVertexArrays.push_back(vertices);
+
+                       for (int j = 0; j < meshPart.m_numVertices; j++)
+                       {
+                               vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[0];
+                               vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[1];
+                               vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[2];
+                               vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[3];
+                       }
+                       meshPart.m_vertexBase = (const unsigned char*)vertices;
+               }
+
+               if (meshPart.m_triangleIndexBase && meshPart.m_vertexBase)
+               {
+                       meshInterface->addIndexedMesh(meshPart, meshPart.m_indexType);
+               }
+       }
+
+       return meshInterface;
+}
+
+btStridingMeshInterfaceData* btCollisionWorldImporter::createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData)
+{
+       //create a new btStridingMeshInterfaceData that is an exact copy of shapedata and store it in the WorldImporter
+       btStridingMeshInterfaceData* newData = new btStridingMeshInterfaceData;
+
+       newData->m_scaling = interfaceData->m_scaling;
+       newData->m_numMeshParts = interfaceData->m_numMeshParts;
+       newData->m_meshPartsPtr = new btMeshPartData[newData->m_numMeshParts];
+
+       for (int i = 0; i < newData->m_numMeshParts; i++)
+       {
+               btMeshPartData* curPart = &interfaceData->m_meshPartsPtr[i];
+               btMeshPartData* curNewPart = &newData->m_meshPartsPtr[i];
+
+               curNewPart->m_numTriangles = curPart->m_numTriangles;
+               curNewPart->m_numVertices = curPart->m_numVertices;
+
+               if (curPart->m_vertices3f)
+               {
+                       curNewPart->m_vertices3f = new btVector3FloatData[curNewPart->m_numVertices];
+                       memcpy(curNewPart->m_vertices3f, curPart->m_vertices3f, sizeof(btVector3FloatData) * curNewPart->m_numVertices);
+               }
+               else
+                       curNewPart->m_vertices3f = NULL;
+
+               if (curPart->m_vertices3d)
+               {
+                       curNewPart->m_vertices3d = new btVector3DoubleData[curNewPart->m_numVertices];
+                       memcpy(curNewPart->m_vertices3d, curPart->m_vertices3d, sizeof(btVector3DoubleData) * curNewPart->m_numVertices);
+               }
+               else
+                       curNewPart->m_vertices3d = NULL;
+
+               int numIndices = curNewPart->m_numTriangles * 3;
+               ///the m_3indices8 was not initialized in some Bullet versions, this can cause crashes at loading time
+               ///we catch it by only dealing with m_3indices8 if none of the other indices are initialized
+               bool uninitialized3indices8Workaround = false;
+
+               if (curPart->m_indices32)
+               {
+                       uninitialized3indices8Workaround = true;
+                       curNewPart->m_indices32 = new btIntIndexData[numIndices];
+                       memcpy(curNewPart->m_indices32, curPart->m_indices32, sizeof(btIntIndexData) * numIndices);
+               }
+               else
+                       curNewPart->m_indices32 = NULL;
+
+               if (curPart->m_3indices16)
+               {
+                       uninitialized3indices8Workaround = true;
+                       curNewPart->m_3indices16 = new btShortIntIndexTripletData[curNewPart->m_numTriangles];
+                       memcpy(curNewPart->m_3indices16, curPart->m_3indices16, sizeof(btShortIntIndexTripletData) * curNewPart->m_numTriangles);
+               }
+               else
+                       curNewPart->m_3indices16 = NULL;
+
+               if (curPart->m_indices16)
+               {
+                       uninitialized3indices8Workaround = true;
+                       curNewPart->m_indices16 = new btShortIntIndexData[numIndices];
+                       memcpy(curNewPart->m_indices16, curPart->m_indices16, sizeof(btShortIntIndexData) * numIndices);
+               }
+               else
+                       curNewPart->m_indices16 = NULL;
+
+               if (!uninitialized3indices8Workaround && curPart->m_3indices8)
+               {
+                       curNewPart->m_3indices8 = new btCharIndexTripletData[curNewPart->m_numTriangles];
+                       memcpy(curNewPart->m_3indices8, curPart->m_3indices8, sizeof(btCharIndexTripletData) * curNewPart->m_numTriangles);
+               }
+               else
+                       curNewPart->m_3indices8 = NULL;
+       }
+
+       m_allocatedbtStridingMeshInterfaceDatas.push_back(newData);
+
+       return (newData);
+}
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+extern ContactAddedCallback gContactAddedCallback;
+
+static bool btAdjustInternalEdgeContactsCallback(btManifoldPoint& cp, const btCollisionObject* colObj0, int partId0, int index0, const btCollisionObject* colObj1, int partId1, int index1)
+{
+       btAdjustInternalEdgeContacts(cp, colObj1, colObj0, partId1, index1);
+       //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_BACKFACE_MODE);
+       //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_DOUBLE_SIDED+BT_TRIANGLE_CONCAVE_DOUBLE_SIDED);
+       return true;
+}
+#endif  //USE_INTERNAL_EDGE_UTILITY
+
+/*
+btRigidBody*  btWorldImporter::createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform,btCollisionShape* shape,const char* bodyName)
+{
+       btVector3 localInertia;
+       localInertia.setZero();
+
+       if (mass)
+               shape->calculateLocalInertia(mass,localInertia);
+
+       btRigidBody* body = new btRigidBody(mass,0,shape,localInertia);
+       body->setWorldTransform(startTransform);
+
+       if (m_dynamicsWorld)
+               m_dynamicsWorld->addRigidBody(body);
+
+       if (bodyName)
+       {
+               char* newname = duplicateName(bodyName);
+               m_objectNameMap.insert(body,newname);
+               m_nameBodyMap.insert(newname,body);
+       }
+       m_allocatedRigidBodies.push_back(body);
+       return body;
+
+}
+*/
+
+btCollisionObject* btCollisionWorldImporter::getCollisionObjectByName(const char* name)
+{
+       btCollisionObject** bodyPtr = m_nameColObjMap.find(name);
+       if (bodyPtr && *bodyPtr)
+       {
+               return *bodyPtr;
+       }
+       return 0;
+}
+
+btCollisionObject* btCollisionWorldImporter::createCollisionObject(const btTransform& startTransform, btCollisionShape* shape, const char* bodyName)
+{
+       btCollisionObject* colObj = new btCollisionObject();
+       colObj->setWorldTransform(startTransform);
+       colObj->setCollisionShape(shape);
+       m_collisionWorld->addCollisionObject(colObj);  //todo: flags etc
+
+       if (bodyName)
+       {
+               char* newname = duplicateName(bodyName);
+               m_objectNameMap.insert(colObj, newname);
+               m_nameColObjMap.insert(newname, colObj);
+       }
+       m_allocatedCollisionObjects.push_back(colObj);
+
+       return colObj;
+}
+
+btCollisionShape* btCollisionWorldImporter::createPlaneShape(const btVector3& planeNormal, btScalar planeConstant)
+{
+       btStaticPlaneShape* shape = new btStaticPlaneShape(planeNormal, planeConstant);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+btCollisionShape* btCollisionWorldImporter::createBoxShape(const btVector3& halfExtents)
+{
+       btBoxShape* shape = new btBoxShape(halfExtents);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+btCollisionShape* btCollisionWorldImporter::createSphereShape(btScalar radius)
+{
+       btSphereShape* shape = new btSphereShape(radius);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCapsuleShapeX(btScalar radius, btScalar height)
+{
+       btCapsuleShapeX* shape = new btCapsuleShapeX(radius, height);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCapsuleShapeY(btScalar radius, btScalar height)
+{
+       btCapsuleShape* shape = new btCapsuleShape(radius, height);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCapsuleShapeZ(btScalar radius, btScalar height)
+{
+       btCapsuleShapeZ* shape = new btCapsuleShapeZ(radius, height);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCylinderShapeX(btScalar radius, btScalar height)
+{
+       btCylinderShapeX* shape = new btCylinderShapeX(btVector3(height, radius, radius));
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCylinderShapeY(btScalar radius, btScalar height)
+{
+       btCylinderShape* shape = new btCylinderShape(btVector3(radius, height, radius));
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createCylinderShapeZ(btScalar radius, btScalar height)
+{
+       btCylinderShapeZ* shape = new btCylinderShapeZ(btVector3(radius, radius, height));
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createConeShapeX(btScalar radius, btScalar height)
+{
+       btConeShapeX* shape = new btConeShapeX(radius, height);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createConeShapeY(btScalar radius, btScalar height)
+{
+       btConeShape* shape = new btConeShape(radius, height);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btCollisionShape* btCollisionWorldImporter::createConeShapeZ(btScalar radius, btScalar height)
+{
+       btConeShapeZ* shape = new btConeShapeZ(radius, height);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btTriangleIndexVertexArray* btCollisionWorldImporter::createTriangleMeshContainer()
+{
+       btTriangleIndexVertexArray* in = new btTriangleIndexVertexArray();
+       m_allocatedTriangleIndexArrays.push_back(in);
+       return in;
+}
+
+btOptimizedBvh* btCollisionWorldImporter::createOptimizedBvh()
+{
+       btOptimizedBvh* bvh = new btOptimizedBvh();
+       m_allocatedBvhs.push_back(bvh);
+       return bvh;
+}
+
+btTriangleInfoMap* btCollisionWorldImporter::createTriangleInfoMap()
+{
+       btTriangleInfoMap* tim = new btTriangleInfoMap();
+       m_allocatedTriangleInfoMaps.push_back(tim);
+       return tim;
+}
+
+btBvhTriangleMeshShape* btCollisionWorldImporter::createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh)
+{
+       if (bvh)
+       {
+               btBvhTriangleMeshShape* bvhTriMesh = new btBvhTriangleMeshShape(trimesh, bvh->isQuantized(), false);
+               bvhTriMesh->setOptimizedBvh(bvh);
+               m_allocatedCollisionShapes.push_back(bvhTriMesh);
+               return bvhTriMesh;
+       }
+
+       btBvhTriangleMeshShape* ts = new btBvhTriangleMeshShape(trimesh, true);
+       m_allocatedCollisionShapes.push_back(ts);
+       return ts;
+}
+btCollisionShape* btCollisionWorldImporter::createConvexTriangleMeshShape(btStridingMeshInterface* trimesh)
+{
+       return 0;
+}
+#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
+btGImpactMeshShape* btCollisionWorldImporter::createGimpactShape(btStridingMeshInterface* trimesh)
+{
+       btGImpactMeshShape* shape = new btGImpactMeshShape(trimesh);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+#endif  //SUPPORT_GIMPACT_SHAPE_IMPORT
+
+btConvexHullShape* btCollisionWorldImporter::createConvexHullShape()
+{
+       btConvexHullShape* shape = new btConvexHullShape();
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btCompoundShape* btCollisionWorldImporter::createCompoundShape()
+{
+       btCompoundShape* shape = new btCompoundShape();
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btScaledBvhTriangleMeshShape* btCollisionWorldImporter::createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape, const btVector3& localScaling)
+{
+       btScaledBvhTriangleMeshShape* shape = new btScaledBvhTriangleMeshShape(meshShape, localScaling);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+btMultiSphereShape* btCollisionWorldImporter::createMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres)
+{
+       btMultiSphereShape* shape = new btMultiSphereShape(positions, radi, numSpheres);
+       m_allocatedCollisionShapes.push_back(shape);
+       return shape;
+}
+
+// query for data
+int btCollisionWorldImporter::getNumCollisionShapes() const
+{
+       return m_allocatedCollisionShapes.size();
+}
+
+btCollisionShape* btCollisionWorldImporter::getCollisionShapeByIndex(int index)
+{
+       return m_allocatedCollisionShapes[index];
+}
+
+btCollisionShape* btCollisionWorldImporter::getCollisionShapeByName(const char* name)
+{
+       btCollisionShape** shapePtr = m_nameShapeMap.find(name);
+       if (shapePtr && *shapePtr)
+       {
+               return *shapePtr;
+       }
+       return 0;
+}
+
+const char* btCollisionWorldImporter::getNameForPointer(const void* ptr) const
+{
+       const char* const* namePtr = m_objectNameMap.find(ptr);
+       if (namePtr && *namePtr)
+               return *namePtr;
+       return 0;
+}
+
+int btCollisionWorldImporter::getNumRigidBodies() const
+{
+       return m_allocatedRigidBodies.size();
+}
+
+btCollisionObject* btCollisionWorldImporter::getRigidBodyByIndex(int index) const
+{
+       return m_allocatedRigidBodies[index];
+}
+
+int btCollisionWorldImporter::getNumBvhs() const
+{
+       return m_allocatedBvhs.size();
+}
+btOptimizedBvh* btCollisionWorldImporter::getBvhByIndex(int index) const
+{
+       return m_allocatedBvhs[index];
+}
+
+int btCollisionWorldImporter::getNumTriangleInfoMaps() const
+{
+       return m_allocatedTriangleInfoMaps.size();
+}
+
+btTriangleInfoMap* btCollisionWorldImporter::getTriangleInfoMapByIndex(int index) const
+{
+       return m_allocatedTriangleInfoMaps[index];
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h
new file mode 100644 (file)
index 0000000..5e8bc95
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2014 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_WORLD_IMPORTER_H
+#define BT_COLLISION_WORLD_IMPORTER_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btHashMap.h"
+
+class btCollisionShape;
+class btCollisionObject;
+struct btBulletSerializedArrays;
+
+struct ConstraintInput;
+class btCollisionWorld;
+struct btCollisionShapeData;
+class btTriangleIndexVertexArray;
+class btStridingMeshInterface;
+struct btStridingMeshInterfaceData;
+class btGImpactMeshShape;
+class btOptimizedBvh;
+struct btTriangleInfoMap;
+class btBvhTriangleMeshShape;
+class btPoint2PointConstraint;
+class btHingeConstraint;
+class btConeTwistConstraint;
+class btGeneric6DofConstraint;
+class btGeneric6DofSpringConstraint;
+class btSliderConstraint;
+class btGearConstraint;
+struct btContactSolverInfo;
+
+class btCollisionWorldImporter
+{
+protected:
+       btCollisionWorld* m_collisionWorld;
+
+       int m_verboseMode;
+
+       btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
+       btAlignedObjectArray<btCollisionObject*> m_allocatedRigidBodies;
+
+       btAlignedObjectArray<btOptimizedBvh*> m_allocatedBvhs;
+       btAlignedObjectArray<btTriangleInfoMap*> m_allocatedTriangleInfoMaps;
+       btAlignedObjectArray<btTriangleIndexVertexArray*> m_allocatedTriangleIndexArrays;
+       btAlignedObjectArray<btStridingMeshInterfaceData*> m_allocatedbtStridingMeshInterfaceDatas;
+       btAlignedObjectArray<btCollisionObject*> m_allocatedCollisionObjects;
+
+       btAlignedObjectArray<char*> m_allocatedNames;
+
+       btAlignedObjectArray<int*> m_indexArrays;
+       btAlignedObjectArray<short int*> m_shortIndexArrays;
+       btAlignedObjectArray<unsigned char*> m_charIndexArrays;
+
+       btAlignedObjectArray<btVector3FloatData*> m_floatVertexArrays;
+       btAlignedObjectArray<btVector3DoubleData*> m_doubleVertexArrays;
+
+       btHashMap<btHashPtr, btOptimizedBvh*> m_bvhMap;
+       btHashMap<btHashPtr, btTriangleInfoMap*> m_timMap;
+
+       btHashMap<btHashString, btCollisionShape*> m_nameShapeMap;
+       btHashMap<btHashString, btCollisionObject*> m_nameColObjMap;
+
+       btHashMap<btHashPtr, const char*> m_objectNameMap;
+
+       btHashMap<btHashPtr, btCollisionShape*> m_shapeMap;
+       btHashMap<btHashPtr, btCollisionObject*> m_bodyMap;
+
+       //methods
+
+       char* duplicateName(const char* name);
+
+       btCollisionShape* convertCollisionShape(btCollisionShapeData* shapeData);
+
+public:
+       btCollisionWorldImporter(btCollisionWorld* world);
+
+       virtual ~btCollisionWorldImporter();
+
+       bool convertAllObjects(btBulletSerializedArrays* arrays);
+
+       ///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
+       ///make sure you don't use the dynamics world containing objects after you call this method
+       virtual void deleteAllData();
+
+       void setVerboseMode(int verboseMode)
+       {
+               m_verboseMode = verboseMode;
+       }
+
+       int getVerboseMode() const
+       {
+               return m_verboseMode;
+       }
+
+       // query for data
+       int getNumCollisionShapes() const;
+       btCollisionShape* getCollisionShapeByIndex(int index);
+       int getNumRigidBodies() const;
+       btCollisionObject* getRigidBodyByIndex(int index) const;
+
+       int getNumBvhs() const;
+       btOptimizedBvh* getBvhByIndex(int index) const;
+       int getNumTriangleInfoMaps() const;
+       btTriangleInfoMap* getTriangleInfoMapByIndex(int index) const;
+
+       // queris involving named objects
+       btCollisionShape* getCollisionShapeByName(const char* name);
+       btCollisionObject* getCollisionObjectByName(const char* name);
+
+       const char* getNameForPointer(const void* ptr) const;
+
+       ///those virtuals are called by load and can be overridden by the user
+
+       //bodies
+
+       virtual btCollisionObject* createCollisionObject(const btTransform& startTransform, btCollisionShape* shape, const char* bodyName);
+
+       ///shapes
+
+       virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal, btScalar planeConstant);
+       virtual btCollisionShape* createBoxShape(const btVector3& halfExtents);
+       virtual btCollisionShape* createSphereShape(btScalar radius);
+       virtual btCollisionShape* createCapsuleShapeX(btScalar radius, btScalar height);
+       virtual btCollisionShape* createCapsuleShapeY(btScalar radius, btScalar height);
+       virtual btCollisionShape* createCapsuleShapeZ(btScalar radius, btScalar height);
+
+       virtual btCollisionShape* createCylinderShapeX(btScalar radius, btScalar height);
+       virtual btCollisionShape* createCylinderShapeY(btScalar radius, btScalar height);
+       virtual btCollisionShape* createCylinderShapeZ(btScalar radius, btScalar height);
+       virtual btCollisionShape* createConeShapeX(btScalar radius, btScalar height);
+       virtual btCollisionShape* createConeShapeY(btScalar radius, btScalar height);
+       virtual btCollisionShape* createConeShapeZ(btScalar radius, btScalar height);
+       virtual class btTriangleIndexVertexArray* createTriangleMeshContainer();
+       virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
+       virtual btCollisionShape* createConvexTriangleMeshShape(btStridingMeshInterface* trimesh);
+#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
+       virtual btGImpactMeshShape* createGimpactShape(btStridingMeshInterface* trimesh);
+#endif  //SUPPORT_GIMPACT_SHAPE_IMPORT
+       virtual btStridingMeshInterfaceData* createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData);
+
+       virtual class btConvexHullShape* createConvexHullShape();
+       virtual class btCompoundShape* createCompoundShape();
+       virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape, const btVector3& localScalingbtBvhTriangleMeshShape);
+
+       virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres);
+
+       virtual btTriangleIndexVertexArray* createMeshInterface(btStridingMeshInterfaceData& meshData);
+
+       ///acceleration and connectivity structures
+       virtual btOptimizedBvh* createOptimizedBvh();
+       virtual btTriangleInfoMap* createTriangleInfoMap();
+};
+
+#endif  //BT_WORLD_IMPORTER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..6f7ea01
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+*/
+
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "btManifoldResult.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+btShapePairCallback gCompoundChildShapePairCallback = 0;
+
+btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
+       : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+         m_isSwapped(isSwapped),
+         m_sharedManifold(ci.m_manifold)
+{
+       m_ownsManifold = false;
+
+       const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+       btAssert(colObjWrap->getCollisionShape()->isCompound());
+
+       const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
+       m_compoundShapeRevision = compoundShape->getUpdateRevision();
+
+       preallocateChildAlgorithms(body0Wrap, body1Wrap);
+}
+
+void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+{
+       const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+       const btCollisionObjectWrapper* otherObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
+       btAssert(colObjWrap->getCollisionShape()->isCompound());
+
+       const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
+
+       int numChildren = compoundShape->getNumChildShapes();
+       int i;
+
+       m_childCollisionAlgorithms.resize(numChildren);
+       for (i = 0; i < numChildren; i++)
+       {
+               if (compoundShape->getDynamicAabbTree())
+               {
+                       m_childCollisionAlgorithms[i] = 0;
+               }
+               else
+               {
+                       const btCollisionShape* childShape = compoundShape->getChildShape(i);
+
+                       btCollisionObjectWrapper childWrap(colObjWrap, childShape, colObjWrap->getCollisionObject(), colObjWrap->getWorldTransform(), -1, i);  //wrong child trans, but unused (hopefully)
+                       m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap, otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
+
+                       btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsContact;
+                       btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsClosestPoints;
+               }
+       }
+}
+
+void btCompoundCollisionAlgorithm::removeChildAlgorithms()
+{
+       int numChildren = m_childCollisionAlgorithms.size();
+       int i;
+       for (i = 0; i < numChildren; i++)
+       {
+               if (m_childCollisionAlgorithms[i])
+               {
+                       m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
+                       m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
+               }
+       }
+}
+
+btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
+{
+       removeChildAlgorithms();
+}
+
+struct btCompoundLeafCallback : btDbvt::ICollide
+{
+public:
+       const btCollisionObjectWrapper* m_compoundColObjWrap;
+       const btCollisionObjectWrapper* m_otherObjWrap;
+       btDispatcher* m_dispatcher;
+       const btDispatcherInfo& m_dispatchInfo;
+       btManifoldResult* m_resultOut;
+       btCollisionAlgorithm** m_childCollisionAlgorithms;
+       btPersistentManifold* m_sharedManifold;
+
+       btCompoundLeafCallback(const btCollisionObjectWrapper* compoundObjWrap, const btCollisionObjectWrapper* otherObjWrap, btDispatcher* dispatcher, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut, btCollisionAlgorithm** childCollisionAlgorithms, btPersistentManifold* sharedManifold)
+               : m_compoundColObjWrap(compoundObjWrap), m_otherObjWrap(otherObjWrap), m_dispatcher(dispatcher), m_dispatchInfo(dispatchInfo), m_resultOut(resultOut), m_childCollisionAlgorithms(childCollisionAlgorithms), m_sharedManifold(sharedManifold)
+       {
+       }
+
+       void ProcessChildShape(const btCollisionShape* childShape, int index)
+       {
+               btAssert(index >= 0);
+               const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
+               btAssert(index < compoundShape->getNumChildShapes());
+
+               if (gCompoundChildShapePairCallback)
+               {
+                       if (!gCompoundChildShapePairCallback(m_otherObjWrap->getCollisionShape(), childShape))
+                               return;
+               }
+
+               //backup
+               btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
+
+               const btTransform& childTrans = compoundShape->getChildTransform(index);
+               btTransform newChildWorldTrans = orgTrans * childTrans;
+
+               //perform an AABB check first
+               btVector3 aabbMin0, aabbMax0;
+               childShape->getAabb(newChildWorldTrans, aabbMin0, aabbMax0);
+
+               btVector3 extendAabb(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
+               aabbMin0 -= extendAabb;
+               aabbMax0 += extendAabb;
+
+               btVector3 aabbMin1, aabbMax1;
+               m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(), aabbMin1, aabbMax1);
+
+
+               if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
+               {
+                       btTransform preTransform = childTrans;
+                       if (this->m_compoundColObjWrap->m_preTransform)
+                       {
+                               preTransform = preTransform *(*(this->m_compoundColObjWrap->m_preTransform));
+                       }
+                       btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, preTransform, -1, index);
+
+                       btCollisionAlgorithm* algo = 0;
+                       bool allocatedAlgorithm = false;
+
+                       if (m_resultOut->m_closestPointDistanceThreshold > 0)
+                       {
+                               algo = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
+                               allocatedAlgorithm = true;
+                       }
+                       else
+                       {
+                               //the contactpoint is still projected back using the original inverted worldtrans
+                               if (!m_childCollisionAlgorithms[index])
+                               {
+                                       m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
+                               }
+                               algo = m_childCollisionAlgorithms[index];
+                       }
+
+                       const btCollisionObjectWrapper* tmpWrap = 0;
+
+                       ///detect swapping case
+                       if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
+                       {
+                               tmpWrap = m_resultOut->getBody0Wrap();
+                               m_resultOut->setBody0Wrap(&compoundWrap);
+                               m_resultOut->setShapeIdentifiersA(-1, index);
+                       }
+                       else
+                       {
+                               tmpWrap = m_resultOut->getBody1Wrap();
+                               m_resultOut->setBody1Wrap(&compoundWrap);
+                               m_resultOut->setShapeIdentifiersB(-1, index);
+                       }
+
+                       algo->processCollision(&compoundWrap, m_otherObjWrap, m_dispatchInfo, m_resultOut);
+
+#if 0
+                       if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+                       {
+                               btVector3 worldAabbMin,worldAabbMax;
+                               m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
+                               m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
+                       }
+#endif
+
+                       if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
+                       {
+                               m_resultOut->setBody0Wrap(tmpWrap);
+                       }
+                       else
+                       {
+                               m_resultOut->setBody1Wrap(tmpWrap);
+                       }
+                       if (allocatedAlgorithm)
+                       {
+                               algo->~btCollisionAlgorithm();
+                               m_dispatcher->freeCollisionAlgorithm(algo);
+                       }
+               }
+       }
+       void Process(const btDbvtNode* leaf)
+       {
+               int index = leaf->dataAsInt;
+
+               const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
+               const btCollisionShape* childShape = compoundShape->getChildShape(index);
+
+#if 0
+               if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+               {
+                       btVector3 worldAabbMin,worldAabbMax;
+                       btTransform     orgTrans = m_compoundColObjWrap->getWorldTransform();
+                       btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
+                       m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
+               }
+#endif
+
+               ProcessChildShape(childShape, index);
+       }
+};
+
+void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+       const btCollisionObjectWrapper* otherObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
+
+       btAssert(colObjWrap->getCollisionShape()->isCompound());
+       const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
+
+       ///btCompoundShape might have changed:
+       ////make sure the internal child collision algorithm caches are still valid
+       if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
+       {
+               ///clear and update all
+               removeChildAlgorithms();
+
+               preallocateChildAlgorithms(body0Wrap, body1Wrap);
+               m_compoundShapeRevision = compoundShape->getUpdateRevision();
+       }
+
+       if (m_childCollisionAlgorithms.size() == 0)
+               return;
+
+       const btDbvt* tree = compoundShape->getDynamicAabbTree();
+       //use a dynamic aabb tree to cull potential child-overlaps
+       btCompoundLeafCallback callback(colObjWrap, otherObjWrap, m_dispatcher, dispatchInfo, resultOut, &m_childCollisionAlgorithms[0], m_sharedManifold);
+
+       ///we need to refresh all contact manifolds
+       ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
+       ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
+       {
+               int i;
+               manifoldArray.resize(0);
+               for (i = 0; i < m_childCollisionAlgorithms.size(); i++)
+               {
+                       if (m_childCollisionAlgorithms[i])
+                       {
+                               m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
+                               for (int m = 0; m < manifoldArray.size(); m++)
+                               {
+                                       if (manifoldArray[m]->getNumContacts())
+                                       {
+                                               resultOut->setPersistentManifold(manifoldArray[m]);
+                                               resultOut->refreshContactPoints();
+                                               resultOut->setPersistentManifold(0);  //??necessary?
+                                       }
+                               }
+                               manifoldArray.resize(0);
+                       }
+               }
+       }
+
+       if (tree)
+       {
+               btVector3 localAabbMin, localAabbMax;
+               btTransform otherInCompoundSpace;
+               otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform();
+               otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace, localAabbMin, localAabbMax);
+               btVector3 extraExtends(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
+               localAabbMin -= extraExtends;
+               localAabbMax += extraExtends;
+
+               const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
+               //process all children, that overlap with  the given AABB bounds
+               tree->collideTVNoStackAlloc(tree->m_root, bounds, stack2, callback);
+       }
+       else
+       {
+               //iterate over all children, perform an AABB check inside ProcessChildShape
+               int numChildren = m_childCollisionAlgorithms.size();
+               int i;
+               for (i = 0; i < numChildren; i++)
+               {
+                       callback.ProcessChildShape(compoundShape->getChildShape(i), i);
+               }
+       }
+
+       {
+               //iterate over all children, perform an AABB check inside ProcessChildShape
+               int numChildren = m_childCollisionAlgorithms.size();
+               int i;
+               manifoldArray.resize(0);
+               const btCollisionShape* childShape = 0;
+               btTransform orgTrans;
+
+               btTransform newChildWorldTrans;
+               btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
+
+               for (i = 0; i < numChildren; i++)
+               {
+                       if (m_childCollisionAlgorithms[i])
+                       {
+                               childShape = compoundShape->getChildShape(i);
+                               //if not longer overlapping, remove the algorithm
+                               orgTrans = colObjWrap->getWorldTransform();
+
+                               const btTransform& childTrans = compoundShape->getChildTransform(i);
+                               newChildWorldTrans = orgTrans * childTrans;
+
+                               //perform an AABB check first
+                               childShape->getAabb(newChildWorldTrans, aabbMin0, aabbMax0);
+                               otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(), aabbMin1, aabbMax1);
+
+                               if (!TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
+                               {
+                                       m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
+                                       m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
+                                       m_childCollisionAlgorithms[i] = 0;
+                               }
+                       }
+               }
+       }
+}
+
+btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       btAssert(0);
+       //needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures
+       btCollisionObject* colObj = m_isSwapped ? body1 : body0;
+       btCollisionObject* otherObj = m_isSwapped ? body0 : body1;
+
+       btAssert(colObj->getCollisionShape()->isCompound());
+
+       btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+
+       //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
+       //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
+       //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
+       //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
+       //then use each overlapping node AABB against Tree0
+       //and vise versa.
+
+       btScalar hitFraction = btScalar(1.);
+
+       int numChildren = m_childCollisionAlgorithms.size();
+       int i;
+       btTransform orgTrans;
+       btScalar frac;
+       for (i = 0; i < numChildren; i++)
+       {
+               //btCollisionShape* childShape = compoundShape->getChildShape(i);
+
+               //backup
+               orgTrans = colObj->getWorldTransform();
+
+               const btTransform& childTrans = compoundShape->getChildTransform(i);
+               //btTransform   newChildWorldTrans = orgTrans*childTrans ;
+               colObj->setWorldTransform(orgTrans * childTrans);
+
+               //btCollisionShape* tmpShape = colObj->getCollisionShape();
+               //colObj->internalSetTemporaryCollisionShape( childShape );
+               frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj, otherObj, dispatchInfo, resultOut);
+               if (frac < hitFraction)
+               {
+                       hitFraction = frac;
+               }
+               //revert back
+               //colObj->internalSetTemporaryCollisionShape( tmpShape);
+               colObj->setWorldTransform(orgTrans);
+       }
+       return hitFraction;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..1193bd4
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_COMPOUND_COLLISION_ALGORITHM_H
+#define BT_COMPOUND_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+class btDispatcher;
+class btCollisionObject;
+
+class btCollisionShape;
+typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCollisionShape* pShape1);
+extern btShapePairCallback gCompoundChildShapePairCallback;
+
+/// btCompoundCollisionAlgorithm  supports collision between CompoundCollisionShapes and other collision shapes
+class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+       btNodeStack stack2;
+       btManifoldArray manifoldArray;
+
+protected:
+       btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
+       bool m_isSwapped;
+
+       class btPersistentManifold* m_sharedManifold;
+       bool m_ownsManifold;
+
+       int m_compoundShapeRevision;  //to keep track of changes, so that childAlgorithm array can be updated
+
+       void removeChildAlgorithms();
+
+       void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
+
+public:
+       btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
+
+       virtual ~btCompoundCollisionAlgorithm();
+
+       btCollisionAlgorithm* getChildAlgorithm(int n) const
+       {
+               return m_childCollisionAlgorithms[n];
+       }
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       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++)
+               {
+                       if (m_childCollisionAlgorithms[i])
+                               m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
+               }
+       }
+
+       struct CreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
+                       return new (mem) btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
+               }
+       };
+
+       struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
+                       return new (mem) btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
+               }
+       };
+};
+
+#endif  //BT_COMPOUND_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..044b60d
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btCompoundCompoundCollisionAlgorithm.h"
+#include "LinearMath/btQuickprof.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+//USE_LOCAL_STACK will avoid most (often all) dynamic memory allocations due to resizing in processCollision and MycollideTT
+#define USE_LOCAL_STACK 1
+
+btShapePairCallback gCompoundCompoundChildShapePairCallback = 0;
+
+btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
+       : btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, isSwapped)
+{
+       void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache), 16);
+       m_childCollisionAlgorithmCache = new (ptr) btHashedSimplePairCache();
+
+       const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
+       btAssert(col0ObjWrap->getCollisionShape()->isCompound());
+
+       const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
+       btAssert(col1ObjWrap->getCollisionShape()->isCompound());
+
+       const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
+       m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
+
+       const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
+       m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
+}
+
+btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm()
+{
+       removeChildAlgorithms();
+       m_childCollisionAlgorithmCache->~btHashedSimplePairCache();
+       btAlignedFree(m_childCollisionAlgorithmCache);
+}
+
+void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
+{
+       int i;
+       btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
+       for (i = 0; i < pairs.size(); i++)
+       {
+               if (pairs[i].m_userPointer)
+               {
+                       ((btCollisionAlgorithm*)pairs[i].m_userPointer)->getAllContactManifolds(manifoldArray);
+               }
+       }
+}
+
+void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
+{
+       btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
+
+       int numChildren = pairs.size();
+       int i;
+       for (i = 0; i < numChildren; i++)
+       {
+               if (pairs[i].m_userPointer)
+               {
+                       btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
+                       algo->~btCollisionAlgorithm();
+                       m_dispatcher->freeCollisionAlgorithm(algo);
+               }
+       }
+       m_childCollisionAlgorithmCache->removeAllPairs();
+}
+
+struct btCompoundCompoundLeafCallback : btDbvt::ICollide
+{
+       int m_numOverlapPairs;
+
+       const btCollisionObjectWrapper* m_compound0ColObjWrap;
+       const btCollisionObjectWrapper* m_compound1ColObjWrap;
+       btDispatcher* m_dispatcher;
+       const btDispatcherInfo& m_dispatchInfo;
+       btManifoldResult* m_resultOut;
+
+       class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
+
+       btPersistentManifold* m_sharedManifold;
+
+       btCompoundCompoundLeafCallback(const btCollisionObjectWrapper* compound1ObjWrap,
+                                                                  const btCollisionObjectWrapper* compound0ObjWrap,
+                                                                  btDispatcher* dispatcher,
+                                                                  const btDispatcherInfo& dispatchInfo,
+                                                                  btManifoldResult* resultOut,
+                                                                  btHashedSimplePairCache* childAlgorithmsCache,
+                                                                  btPersistentManifold* sharedManifold)
+               : m_numOverlapPairs(0), m_compound0ColObjWrap(compound1ObjWrap), m_compound1ColObjWrap(compound0ObjWrap), m_dispatcher(dispatcher), m_dispatchInfo(dispatchInfo), m_resultOut(resultOut), m_childCollisionAlgorithmCache(childAlgorithmsCache), m_sharedManifold(sharedManifold)
+       {
+       }
+
+       void Process(const btDbvtNode* leaf0, const btDbvtNode* leaf1)
+       {
+               BT_PROFILE("btCompoundCompoundLeafCallback::Process");
+               m_numOverlapPairs++;
+
+               int childIndex0 = leaf0->dataAsInt;
+               int childIndex1 = leaf1->dataAsInt;
+
+               btAssert(childIndex0 >= 0);
+               btAssert(childIndex1 >= 0);
+
+               const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(m_compound0ColObjWrap->getCollisionShape());
+               btAssert(childIndex0 < compoundShape0->getNumChildShapes());
+
+               const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(m_compound1ColObjWrap->getCollisionShape());
+               btAssert(childIndex1 < compoundShape1->getNumChildShapes());
+
+               const btCollisionShape* childShape0 = compoundShape0->getChildShape(childIndex0);
+               const btCollisionShape* childShape1 = compoundShape1->getChildShape(childIndex1);
+
+               //backup
+               btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform();
+               const btTransform& childTrans0 = compoundShape0->getChildTransform(childIndex0);
+               btTransform newChildWorldTrans0 = orgTrans0 * childTrans0;
+
+               btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform();
+               const btTransform& childTrans1 = compoundShape1->getChildTransform(childIndex1);
+               btTransform newChildWorldTrans1 = orgTrans1 * childTrans1;
+
+               //perform an AABB check first
+               btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
+               childShape0->getAabb(newChildWorldTrans0, aabbMin0, aabbMax0);
+               childShape1->getAabb(newChildWorldTrans1, aabbMin1, aabbMax1);
+
+               btVector3 thresholdVec(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
+
+               aabbMin0 -= thresholdVec;
+               aabbMax0 += thresholdVec;
+
+               if (gCompoundCompoundChildShapePairCallback)
+               {
+                       if (!gCompoundCompoundChildShapePairCallback(childShape0, childShape1))
+                               return;
+               }
+
+               if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
+               {
+                       btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap, childShape0, m_compound0ColObjWrap->getCollisionObject(), newChildWorldTrans0, -1, childIndex0);
+                       btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap, childShape1, m_compound1ColObjWrap->getCollisionObject(), newChildWorldTrans1, -1, childIndex1);
+
+                       btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0, childIndex1);
+                       bool removePair = false;
+                       btCollisionAlgorithm* colAlgo = 0;
+                       if (m_resultOut->m_closestPointDistanceThreshold > 0)
+                       {
+                               colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, 0, BT_CLOSEST_POINT_ALGORITHMS);
+                               removePair = true;
+                       }
+                       else
+                       {
+                               if (pair)
+                               {
+                                       colAlgo = (btCollisionAlgorithm*)pair->m_userPointer;
+                               }
+                               else
+                               {
+                                       colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
+                                       pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0, childIndex1);
+                                       btAssert(pair);
+                                       pair->m_userPointer = colAlgo;
+                               }
+                       }
+
+                       btAssert(colAlgo);
+
+                       const btCollisionObjectWrapper* tmpWrap0 = 0;
+                       const btCollisionObjectWrapper* tmpWrap1 = 0;
+
+                       tmpWrap0 = m_resultOut->getBody0Wrap();
+                       tmpWrap1 = m_resultOut->getBody1Wrap();
+
+                       m_resultOut->setBody0Wrap(&compoundWrap0);
+                       m_resultOut->setBody1Wrap(&compoundWrap1);
+
+                       m_resultOut->setShapeIdentifiersA(-1, childIndex0);
+                       m_resultOut->setShapeIdentifiersB(-1, childIndex1);
+
+                       colAlgo->processCollision(&compoundWrap0, &compoundWrap1, m_dispatchInfo, m_resultOut);
+
+                       m_resultOut->setBody0Wrap(tmpWrap0);
+                       m_resultOut->setBody1Wrap(tmpWrap1);
+
+                       if (removePair)
+                       {
+                               colAlgo->~btCollisionAlgorithm();
+                               m_dispatcher->freeCollisionAlgorithm(colAlgo);
+                       }
+               }
+       }
+};
+
+static DBVT_INLINE bool MyIntersect(const btDbvtAabbMm& a,
+                                                                       const btDbvtAabbMm& b, const btTransform& xform, btScalar distanceThreshold)
+{
+       btVector3 newmin, newmax;
+       btTransformAabb(b.Mins(), b.Maxs(), 0.f, xform, newmin, newmax);
+       newmin -= btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
+       newmax += btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
+       btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin, newmax);
+       return Intersect(a, newb);
+}
+
+static inline void MycollideTT(const btDbvtNode* root0,
+                                                          const btDbvtNode* root1,
+                                                          const btTransform& xform,
+                                                          btCompoundCompoundLeafCallback* callback, btScalar distanceThreshold)
+{
+       if (root0 && root1)
+       {
+               int depth = 1;
+               int treshold = btDbvt::DOUBLE_STACKSIZE - 4;
+               btAlignedObjectArray<btDbvt::sStkNN> stkStack;
+#ifdef USE_LOCAL_STACK
+               ATTRIBUTE_ALIGNED16(btDbvt::sStkNN localStack[btDbvt::DOUBLE_STACKSIZE]);
+               stkStack.initializeFromBuffer(&localStack, btDbvt::DOUBLE_STACKSIZE, btDbvt::DOUBLE_STACKSIZE);
+#else
+               stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
+#endif
+               stkStack[0] = btDbvt::sStkNN(root0, root1);
+               do
+               {
+                       btDbvt::sStkNN p = stkStack[--depth];
+                       if (MyIntersect(p.a->volume, p.b->volume, xform, distanceThreshold))
+                       {
+                               if (depth > treshold)
+                               {
+                                       stkStack.resize(stkStack.size() * 2);
+                                       treshold = stkStack.size() - 4;
+                               }
+                               if (p.a->isinternal())
+                               {
+                                       if (p.b->isinternal())
+                                       {
+                                               stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b->childs[0]);
+                                               stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b->childs[0]);
+                                               stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b->childs[1]);
+                                               stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                               stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b);
+                                               stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b);
+                                       }
+                               }
+                               else
+                               {
+                                       if (p.b->isinternal())
+                                       {
+                                               stkStack[depth++] = btDbvt::sStkNN(p.a, p.b->childs[0]);
+                                               stkStack[depth++] = btDbvt::sStkNN(p.a, p.b->childs[1]);
+                                       }
+                                       else
+                                       {
+                                               callback->Process(p.a, p.b);
+                                       }
+                               }
+                       }
+               } while (depth);
+       }
+}
+
+void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
+       const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
+
+       btAssert(col0ObjWrap->getCollisionShape()->isCompound());
+       btAssert(col1ObjWrap->getCollisionShape()->isCompound());
+       const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
+       const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
+
+       const btDbvt* tree0 = compoundShape0->getDynamicAabbTree();
+       const btDbvt* tree1 = compoundShape1->getDynamicAabbTree();
+       if (!tree0 || !tree1)
+       {
+               return btCompoundCollisionAlgorithm::processCollision(body0Wrap, body1Wrap, dispatchInfo, resultOut);
+       }
+       ///btCompoundShape might have changed:
+       ////make sure the internal child collision algorithm caches are still valid
+       if ((compoundShape0->getUpdateRevision() != m_compoundShapeRevision0) || (compoundShape1->getUpdateRevision() != m_compoundShapeRevision1))
+       {
+               ///clear all
+               removeChildAlgorithms();
+               m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
+               m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
+       }
+
+       ///we need to refresh all contact manifolds
+       ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
+       ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
+       {
+               int i;
+               btManifoldArray manifoldArray;
+#ifdef USE_LOCAL_STACK
+               btPersistentManifold localManifolds[4];
+               manifoldArray.initializeFromBuffer(&localManifolds, 0, 4);
+#endif
+               btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
+               for (i = 0; i < pairs.size(); i++)
+               {
+                       if (pairs[i].m_userPointer)
+                       {
+                               btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
+                               algo->getAllContactManifolds(manifoldArray);
+                               for (int m = 0; m < manifoldArray.size(); m++)
+                               {
+                                       if (manifoldArray[m]->getNumContacts())
+                                       {
+                                               resultOut->setPersistentManifold(manifoldArray[m]);
+                                               resultOut->refreshContactPoints();
+                                               resultOut->setPersistentManifold(0);
+                                       }
+                               }
+                               manifoldArray.resize(0);
+                       }
+               }
+       }
+
+       btCompoundCompoundLeafCallback callback(col0ObjWrap, col1ObjWrap, this->m_dispatcher, dispatchInfo, resultOut, this->m_childCollisionAlgorithmCache, m_sharedManifold);
+
+       const btTransform xform = col0ObjWrap->getWorldTransform().inverse() * col1ObjWrap->getWorldTransform();
+       MycollideTT(tree0->m_root, tree1->m_root, xform, &callback, resultOut->m_closestPointDistanceThreshold);
+
+       //printf("#compound-compound child/leaf overlap =%d                      \r",callback.m_numOverlapPairs);
+
+       //remove non-overlapping child pairs
+
+       {
+               btAssert(m_removePairs.size() == 0);
+
+               //iterate over all children, perform an AABB check inside ProcessChildShape
+               btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
+
+               int i;
+               btManifoldArray manifoldArray;
+
+               btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
+
+               for (i = 0; i < pairs.size(); i++)
+               {
+                       if (pairs[i].m_userPointer)
+                       {
+                               btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
+
+                               {
+                                       const btCollisionShape* childShape0 = 0;
+
+                                       btTransform newChildWorldTrans0;
+                                       childShape0 = compoundShape0->getChildShape(pairs[i].m_indexA);
+                                       const btTransform& childTrans0 = compoundShape0->getChildTransform(pairs[i].m_indexA);
+                                       newChildWorldTrans0 = col0ObjWrap->getWorldTransform() * childTrans0;
+                                       childShape0->getAabb(newChildWorldTrans0, aabbMin0, aabbMax0);
+                               }
+                               btVector3 thresholdVec(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
+                               aabbMin0 -= thresholdVec;
+                               aabbMax0 += thresholdVec;
+                               {
+                                       const btCollisionShape* childShape1 = 0;
+                                       btTransform newChildWorldTrans1;
+
+                                       childShape1 = compoundShape1->getChildShape(pairs[i].m_indexB);
+                                       const btTransform& childTrans1 = compoundShape1->getChildTransform(pairs[i].m_indexB);
+                                       newChildWorldTrans1 = col1ObjWrap->getWorldTransform() * childTrans1;
+                                       childShape1->getAabb(newChildWorldTrans1, aabbMin1, aabbMax1);
+                               }
+
+                               aabbMin1 -= thresholdVec;
+                               aabbMax1 += thresholdVec;
+
+                               if (!TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
+                               {
+                                       algo->~btCollisionAlgorithm();
+                                       m_dispatcher->freeCollisionAlgorithm(algo);
+                                       m_removePairs.push_back(btSimplePair(pairs[i].m_indexA, pairs[i].m_indexB));
+                               }
+                       }
+               }
+               for (int i = 0; i < m_removePairs.size(); i++)
+               {
+                       m_childCollisionAlgorithmCache->removeOverlappingPair(m_removePairs[i].m_indexA, m_removePairs[i].m_indexB);
+               }
+               m_removePairs.clear();
+       }
+}
+
+btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       btAssert(0);
+       return 0.f;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..a940d84
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
+#define BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
+
+#include "btCompoundCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/CollisionDispatch/btHashedSimplePairCache.h"
+class btDispatcher;
+class btCollisionObject;
+
+class btCollisionShape;
+
+extern btShapePairCallback gCompoundCompoundChildShapePairCallback;
+
+/// btCompoundCompoundCollisionAlgorithm  supports collision between two btCompoundCollisionShape shapes
+class btCompoundCompoundCollisionAlgorithm : public btCompoundCollisionAlgorithm
+{
+       class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
+       btSimplePairArray m_removePairs;
+
+       int m_compoundShapeRevision0;  //to keep track of changes, so that childAlgorithm array can be updated
+       int m_compoundShapeRevision1;
+
+       void removeChildAlgorithms();
+
+       //      void    preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
+
+public:
+       btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
+
+       virtual ~btCompoundCompoundCollisionAlgorithm();
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       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, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
+                       return new (mem) btCompoundCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
+               }
+       };
+
+       struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
+                       return new (mem) btCompoundCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
+               }
+       };
+};
+
+#endif  //BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
new file mode 100644 (file)
index 0000000..f9dfc0a
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btConvex2dConvex2dAlgorithm.h"
+
+//#include <stdio.h>
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
+{
+       m_simplexSolver = simplexSolver;
+       m_pdSolver = pdSolver;
+}
+
+btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()
+{
+}
+
+btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int /* numPerturbationIterations */, int /* minimumPointsPerturbationThreshold */)
+       : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+         m_simplexSolver(simplexSolver),
+         m_pdSolver(pdSolver),
+         m_ownManifold(false),
+         m_manifoldPtr(mf),
+         m_lowLevelOfDetail(false)
+{
+       (void)body0Wrap;
+       (void)body1Wrap;
+}
+
+btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
+{
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr)
+                       m_dispatcher->releaseManifold(m_manifoldPtr);
+       }
+}
+
+void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
+{
+       m_lowLevelOfDetail = useLowLevel;
+}
+
+extern btScalar gContactBreakingThreshold;
+
+//
+// Convex-Convex collision algorithm
+//
+void btConvex2dConvex2dAlgorithm ::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       if (!m_manifoldPtr)
+       {
+               //swapped?
+               m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
+               m_ownManifold = true;
+       }
+       resultOut->setPersistentManifold(m_manifoldPtr);
+
+       //comment-out next line to test multi-contact generation
+       //resultOut->getPersistentManifold()->clearManifold();
+
+       const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
+       const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
+
+       btVector3 normalOnB;
+       btVector3 pointOnBWorld;
+
+       {
+               btGjkPairDetector::ClosestPointInput input;
+
+               btGjkPairDetector gjkPairDetector(min0, min1, m_simplexSolver, m_pdSolver);
+               //TODO: if (dispatchInfo.m_useContinuous)
+               gjkPairDetector.setMinkowskiA(min0);
+               gjkPairDetector.setMinkowskiB(min1);
+
+               {
+                       input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
+                       input.m_maximumDistanceSquared *= input.m_maximumDistanceSquared;
+               }
+
+               input.m_transformA = body0Wrap->getWorldTransform();
+               input.m_transformB = body1Wrap->getWorldTransform();
+
+               gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
+
+               btVector3 v0, v1;
+               btVector3 sepNormalWorldSpace;
+       }
+
+       if (m_ownManifold)
+       {
+               resultOut->refreshContactPoints();
+       }
+}
+
+btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       (void)resultOut;
+       (void)dispatchInfo;
+       ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
+
+       ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
+       ///col0->m_worldTransform,
+       btScalar resultFraction = btScalar(1.);
+
+       btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
+       btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
+
+       if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
+               squareMot1 < col1->getCcdSquareMotionThreshold())
+               return resultFraction;
+
+       //An adhoc way of testing the Continuous Collision Detection algorithms
+       //One object is approximated as a sphere, to simplify things
+       //Starting in penetration should report no time of impact
+       //For proper CCD, better accuracy and handling of 'allowed' penetration should be added
+       //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
+
+       /// Convex0 against sphere for Convex1
+       {
+               btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
+
+               btSphereShape sphere1(col1->getCcdSweptSphereRadius());  //todo: allow non-zero sphere sizes, for better approximation
+               btConvexCast::CastResult result;
+               btVoronoiSimplexSolver voronoiSimplex;
+               //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+               ///Simplification, one object is simplified as a sphere
+               btGjkConvexCast ccd1(convex0, &sphere1, &voronoiSimplex);
+               //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+               if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
+                                                                 col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
+               {
+                       //store result.m_fraction in both bodies
+
+                       if (col0->getHitFraction() > result.m_fraction)
+                               col0->setHitFraction(result.m_fraction);
+
+                       if (col1->getHitFraction() > result.m_fraction)
+                               col1->setHitFraction(result.m_fraction);
+
+                       if (resultFraction > result.m_fraction)
+                               resultFraction = result.m_fraction;
+               }
+       }
+
+       /// Sphere (for convex0) against Convex1
+       {
+               btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
+
+               btSphereShape sphere0(col0->getCcdSweptSphereRadius());  //todo: allow non-zero sphere sizes, for better approximation
+               btConvexCast::CastResult result;
+               btVoronoiSimplexSolver voronoiSimplex;
+               //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+               ///Simplification, one object is simplified as a sphere
+               btGjkConvexCast ccd1(&sphere0, convex1, &voronoiSimplex);
+               //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+               if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
+                                                                 col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
+               {
+                       //store result.m_fraction in both bodies
+
+                       if (col0->getHitFraction() > result.m_fraction)
+                               col0->setHitFraction(result.m_fraction);
+
+                       if (col1->getHitFraction() > result.m_fraction)
+                               col1->setHitFraction(result.m_fraction);
+
+                       if (resultFraction > result.m_fraction)
+                               resultFraction = result.m_fraction;
+               }
+       }
+
+       return resultFraction;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
new file mode 100644 (file)
index 0000000..e6a2504
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_2D_CONVEX_2D_ALGORITHM_H
+#define BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "LinearMath/btTransformUtil.h"  //for btConvexSeparatingDistanceUtil
+
+class btConvexPenetrationDepthSolver;
+
+///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape
+///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation
+class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm
+{
+       btSimplexSolverInterface* m_simplexSolver;
+       btConvexPenetrationDepthSolver* m_pdSolver;
+
+       bool m_ownManifold;
+       btPersistentManifold* m_manifoldPtr;
+       bool m_lowLevelOfDetail;
+
+public:
+       btConvex2dConvex2dAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+
+       virtual ~btConvex2dConvex2dAlgorithm();
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       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);
+
+       const btPersistentManifold* getManifold()
+       {
+               return m_manifoldPtr;
+       }
+
+       struct CreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               btConvexPenetrationDepthSolver* m_pdSolver;
+               btSimplexSolverInterface* m_simplexSolver;
+               int m_numPerturbationIterations;
+               int m_minimumPointsPerturbationThreshold;
+
+               CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
+
+               virtual ~CreateFunc();
+
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm));
+                       return new (mem) btConvex2dConvex2dAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_simplexSolver, m_pdSolver, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
+               }
+       };
+};
+
+#endif  //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..95bce9e
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexConcaveCollisionAlgorithm.h"
+#include "LinearMath/btQuickprof.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+#include "BulletCollision/CollisionShapes/btSdfCollisionShape.h"
+
+btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
+       : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+         m_btConvexTriangleCallback(ci.m_dispatcher1, body0Wrap, body1Wrap, isSwapped),
+         m_isSwapped(isSwapped)
+{
+}
+
+btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
+{
+}
+
+void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
+{
+       if (m_btConvexTriangleCallback.m_manifoldPtr)
+       {
+               manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr);
+       }
+}
+
+btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped) : m_dispatcher(dispatcher),
+                                                                                                                                                                                                                                                                                                                                                                        m_dispatchInfoPtr(0)
+{
+       m_convexBodyWrap = isSwapped ? body1Wrap : body0Wrap;
+       m_triBodyWrap = isSwapped ? body0Wrap : body1Wrap;
+
+       //
+       // create the manifold from the dispatcher 'manifold pool'
+       //
+       m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(), m_triBodyWrap->getCollisionObject());
+
+       clearCache();
+}
+
+btConvexTriangleCallback::~btConvexTriangleCallback()
+{
+       clearCache();
+       m_dispatcher->releaseManifold(m_manifoldPtr);
+}
+
+void btConvexTriangleCallback::clearCache()
+{
+       m_dispatcher->clearManifold(m_manifoldPtr);
+}
+
+void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
+{
+       BT_PROFILE("btConvexTriangleCallback::processTriangle");
+
+       if (!TestTriangleAgainstAabb2(triangle, m_aabbMin, m_aabbMax))
+       {
+               return;
+       }
+
+       //just for debugging purposes
+       //printf("triangle %d",m_triangleCount++);
+
+       btCollisionAlgorithmConstructionInfo ci;
+       ci.m_dispatcher1 = m_dispatcher;
+
+#if 0  
+       
+       ///debug drawing of the overlapping triangles
+       if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe ))
+       {
+               const btCollisionObject* ob = const_cast<btCollisionObject*>(m_triBodyWrap->getCollisionObject());
+               btVector3 color(1,1,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);
+       }
+#endif
+
+       if (m_convexBodyWrap->getCollisionShape()->isConvex())
+       {
+#ifdef BT_ENABLE_CONVEX_CONCAVE_EARLY_OUT
+    //todo: check this issue https://github.com/bulletphysics/bullet3/issues/4263
+               //an early out optimisation if the object is separated from the triangle
+               //projected on the triangle normal)
+               {
+                       const btVector3 v0 = m_triBodyWrap->getWorldTransform()*triangle[0];
+                       const btVector3 v1 = m_triBodyWrap->getWorldTransform()*triangle[1];
+                       const btVector3 v2 = m_triBodyWrap->getWorldTransform()*triangle[2];
+
+                       btVector3 triangle_normal_world = ( v1 - v0).cross(v2 - v0);
+                       triangle_normal_world.normalize();
+
+                   btConvexShape* convex = (btConvexShape*)m_convexBodyWrap->getCollisionShape();
+                       
+                       btVector3 localPt = convex->localGetSupportingVertex(m_convexBodyWrap->getWorldTransform().getBasis().inverse()*triangle_normal_world);
+                       btVector3 worldPt = m_convexBodyWrap->getWorldTransform()*localPt;
+                       //now check if this is fully on one side of the triangle
+                       btScalar proj_distPt = triangle_normal_world.dot(worldPt);
+                       btScalar proj_distTr = triangle_normal_world.dot(v0);
+                       btScalar contact_threshold = m_manifoldPtr->getContactBreakingThreshold()+ m_resultOut->m_closestPointDistanceThreshold;
+                       btScalar dist = proj_distTr - proj_distPt;
+                       if (dist > contact_threshold)
+                               return;
+
+                       //also check the other side of the triangle
+                       triangle_normal_world*=-1;
+
+                       localPt = convex->localGetSupportingVertex(m_convexBodyWrap->getWorldTransform().getBasis().inverse()*triangle_normal_world);
+                       worldPt = m_convexBodyWrap->getWorldTransform()*localPt;
+                       //now check if this is fully on one side of the triangle
+                       proj_distPt = triangle_normal_world.dot(worldPt);
+                       proj_distTr = triangle_normal_world.dot(v0);
+                       
+                       dist = proj_distTr - proj_distPt;
+                       if (dist > contact_threshold)
+                               return;
+        }
+#endif //BT_ENABLE_CONVEX_CONCAVE_EARLY_OUT
+
+               btTriangleShape tm(triangle[0], triangle[1], triangle[2]);
+               tm.setMargin(m_collisionMarginTriangle);
+
+               btCollisionObjectWrapper triObWrap(m_triBodyWrap, &tm, m_triBodyWrap->getCollisionObject(), m_triBodyWrap->getWorldTransform(), partId, triangleIndex);  //correct transform?
+               btCollisionAlgorithm* colAlgo = 0;
+
+               if (m_resultOut->m_closestPointDistanceThreshold > 0)
+               {
+                       colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
+               }
+               else
+               {
+                       colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, m_manifoldPtr, BT_CONTACT_POINT_ALGORITHMS);
+               }
+               const btCollisionObjectWrapper* tmpWrap = 0;
+
+               if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
+               {
+                       tmpWrap = m_resultOut->getBody0Wrap();
+                       m_resultOut->setBody0Wrap(&triObWrap);
+                       m_resultOut->setShapeIdentifiersA(partId, triangleIndex);
+               }
+               else
+               {
+                       tmpWrap = m_resultOut->getBody1Wrap();
+                       m_resultOut->setBody1Wrap(&triObWrap);
+                       m_resultOut->setShapeIdentifiersB(partId, triangleIndex);
+               }
+
+               {
+                       BT_PROFILE("processCollision (GJK?)");
+                       colAlgo->processCollision(m_convexBodyWrap, &triObWrap, *m_dispatchInfoPtr, m_resultOut);
+               }
+
+               if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
+               {
+                       m_resultOut->setBody0Wrap(tmpWrap);
+               }
+               else
+               {
+                       m_resultOut->setBody1Wrap(tmpWrap);
+               }
+
+               colAlgo->~btCollisionAlgorithm();
+               ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+       }
+}
+
+void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
+{
+       m_convexBodyWrap = convexBodyWrap;
+       m_triBodyWrap = triBodyWrap;
+
+       m_dispatchInfoPtr = &dispatchInfo;
+       m_collisionMarginTriangle = collisionMarginTriangle;
+       m_resultOut = resultOut;
+
+       //recalc aabbs
+       btTransform convexInTriangleSpace;
+       convexInTriangleSpace = m_triBodyWrap->getWorldTransform().inverse() * m_convexBodyWrap->getWorldTransform();
+       const btCollisionShape* convexShape = static_cast<const btCollisionShape*>(m_convexBodyWrap->getCollisionShape());
+       //CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
+       convexShape->getAabb(convexInTriangleSpace, m_aabbMin, m_aabbMax);
+       btScalar extraMargin = collisionMarginTriangle + resultOut->m_closestPointDistanceThreshold;
+
+       btVector3 extra(extraMargin, extraMargin, extraMargin);
+
+       m_aabbMax += extra;
+       m_aabbMin -= extra;
+}
+
+void btConvexConcaveCollisionAlgorithm::clearCache()
+{
+       m_btConvexTriangleCallback.clearCache();
+}
+
+void btConvexConcaveCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       BT_PROFILE("btConvexConcaveCollisionAlgorithm::processCollision");
+
+       const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap;
+       const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap;
+
+       if (triBodyWrap->getCollisionShape()->isConcave())
+       {
+               if (triBodyWrap->getCollisionShape()->getShapeType() == SDF_SHAPE_PROXYTYPE)
+               {
+                       btSdfCollisionShape* sdfShape = (btSdfCollisionShape*)triBodyWrap->getCollisionShape();
+                       if (convexBodyWrap->getCollisionShape()->isConvex())
+                       {
+                               btConvexShape* convex = (btConvexShape*)convexBodyWrap->getCollisionShape();
+                               btAlignedObjectArray<btVector3> queryVertices;
+
+                               if (convex->isPolyhedral())
+                               {
+                                       btPolyhedralConvexShape* poly = (btPolyhedralConvexShape*)convex;
+                                       for (int v = 0; v < poly->getNumVertices(); v++)
+                                       {
+                                               btVector3 vtx;
+                                               poly->getVertex(v, vtx);
+                                               queryVertices.push_back(vtx);
+                                       }
+                               }
+                               btScalar maxDist = SIMD_EPSILON;
+
+                               if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
+                               {
+                                       queryVertices.push_back(btVector3(0, 0, 0));
+                                       btSphereShape* sphere = (btSphereShape*)convex;
+                                       maxDist = sphere->getRadius() + SIMD_EPSILON;
+                               }
+                               if (queryVertices.size())
+                               {
+                                       resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
+                                       //m_btConvexTriangleCallback.m_manifoldPtr->clearManifold();
+
+                                       btPolyhedralConvexShape* poly = (btPolyhedralConvexShape*)convex;
+                                       for (int v = 0; v < queryVertices.size(); v++)
+                                       {
+                                               const btVector3& vtx = queryVertices[v];
+                                               btVector3 vtxWorldSpace = convexBodyWrap->getWorldTransform() * vtx;
+                                               btVector3 vtxInSdf = triBodyWrap->getWorldTransform().invXform(vtxWorldSpace);
+
+                                               btVector3 normalLocal;
+                                               btScalar dist;
+                                               if (sdfShape->queryPoint(vtxInSdf, dist, normalLocal))
+                                               {
+                                                       if (dist <= maxDist)
+                                                       {
+                                                               normalLocal.safeNormalize();
+                                                               btVector3 normal = triBodyWrap->getWorldTransform().getBasis() * normalLocal;
+
+                                                               if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
+                                                               {
+                                                                       btSphereShape* sphere = (btSphereShape*)convex;
+                                                                       dist -= sphere->getRadius();
+                                                                       vtxWorldSpace -= sphere->getRadius() * normal;
+                                                               }
+                                                               resultOut->addContactPoint(normal, vtxWorldSpace - normal * dist, dist);
+                                                       }
+                                               }
+                                       }
+                                       resultOut->refreshContactPoints();
+                               }
+                       }
+               }
+               else
+               {
+                       const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>(triBodyWrap->getCollisionShape());
+
+                       if (convexBodyWrap->getCollisionShape()->isConvex())
+                       {
+                               btScalar collisionMarginTriangle = concaveShape->getMargin();
+
+                               resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
+                               m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle, dispatchInfo, convexBodyWrap, triBodyWrap, resultOut);
+
+                               m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(), triBodyWrap->getCollisionObject());
+
+                               concaveShape->processAllTriangles(&m_btConvexTriangleCallback, m_btConvexTriangleCallback.getAabbMin(), m_btConvexTriangleCallback.getAabbMax());
+
+                               resultOut->refreshContactPoints();
+
+                               m_btConvexTriangleCallback.clearWrapperData();
+                       }
+               }
+       }
+}
+
+btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       (void)resultOut;
+       (void)dispatchInfo;
+       btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
+       btCollisionObject* triBody = m_isSwapped ? body0 : body1;
+
+       //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
+
+       //only perform CCD above a certain threshold, this prevents blocking on the long run
+       //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
+       btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
+       if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
+       {
+               return btScalar(1.);
+       }
+
+       //const btVector3& from = convexbody->m_worldTransform.getOrigin();
+       //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
+       //todo: only do if the motion exceeds the 'radius'
+
+       btTransform triInv = triBody->getWorldTransform().inverse();
+       btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
+       btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
+
+       struct LocalTriangleSphereCastCallback : public btTriangleCallback
+       {
+               btTransform m_ccdSphereFromTrans;
+               btTransform m_ccdSphereToTrans;
+               btTransform m_meshTransform;
+
+               btScalar m_ccdSphereRadius;
+               btScalar m_hitFraction;
+
+               LocalTriangleSphereCastCallback(const btTransform& from, const btTransform& to, btScalar ccdSphereRadius, btScalar hitFraction)
+                       : m_ccdSphereFromTrans(from),
+                         m_ccdSphereToTrans(to),
+                         m_ccdSphereRadius(ccdSphereRadius),
+                         m_hitFraction(hitFraction)
+               {
+               }
+
+               virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+               {
+                       BT_PROFILE("processTriangle");
+                       (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/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..8d86daf
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
+#define BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "btCollisionCreateFunc.h"
+
+///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
+ATTRIBUTE_ALIGNED16(class)
+btConvexTriangleCallback : public btTriangleCallback
+{
+       btVector3 m_aabbMin;
+       btVector3 m_aabbMax;
+
+       const btCollisionObjectWrapper* m_convexBodyWrap;
+       const btCollisionObjectWrapper* m_triBodyWrap;
+
+       btManifoldResult* m_resultOut;
+       btDispatcher* m_dispatcher;
+       const btDispatcherInfo* m_dispatchInfoPtr;
+       btScalar m_collisionMarginTriangle;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       int m_triangleCount;
+
+       btPersistentManifold* m_manifoldPtr;
+
+       btConvexTriangleCallback(btDispatcher * dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
+
+       void setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut);
+
+       void clearWrapperData()
+       {
+               m_convexBodyWrap = 0;
+               m_triBodyWrap = 0;
+       }
+       virtual ~btConvexTriangleCallback();
+
+       virtual void processTriangle(btVector3 * triangle, int partId, int triangleIndex);
+
+       void clearCache();
+
+       SIMD_FORCE_INLINE const btVector3& getAabbMin() const
+       {
+               return m_aabbMin;
+       }
+       SIMD_FORCE_INLINE const btVector3& getAabbMax() const
+       {
+               return m_aabbMax;
+       }
+};
+
+/// btConvexConcaveCollisionAlgorithm  supports collision between convex shapes and (concave) trianges meshes.
+ATTRIBUTE_ALIGNED16(class)
+btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+       btConvexTriangleCallback m_btConvexTriangleCallback;
+
+       bool m_isSwapped;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
+
+       virtual ~btConvexConcaveCollisionAlgorithm();
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       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, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
+                       return new (mem) btConvexConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
+               }
+       };
+
+       struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
+                       return new (mem) btConvexConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
+               }
+       };
+};
+
+#endif  //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
new file mode 100644 (file)
index 0000000..8031c95
--- /dev/null
@@ -0,0 +1,873 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance
+///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums
+///with reproduction case
+//#define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1
+//#define ZERO_MARGIN
+
+#include "btConvexConvexAlgorithm.h"
+
+//#include <stdio.h>
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+///////////
+
+static SIMD_FORCE_INLINE void segmentsClosestPoints(
+       btVector3& ptsVector,
+       btVector3& offsetA,
+       btVector3& offsetB,
+       btScalar& tA, btScalar& tB,
+       const btVector3& translation,
+       const btVector3& dirA, btScalar hlenA,
+       const btVector3& dirB, btScalar hlenB)
+{
+       // compute the parameters of the closest points on each line segment
+
+       btScalar dirA_dot_dirB = btDot(dirA, dirB);
+       btScalar dirA_dot_trans = btDot(dirA, translation);
+       btScalar dirB_dot_trans = btDot(dirB, translation);
+
+       btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
+
+       if (denom == 0.0f)
+       {
+               tA = 0.0f;
+       }
+       else
+       {
+               tA = (dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB) / denom;
+               if (tA < -hlenA)
+                       tA = -hlenA;
+               else if (tA > hlenA)
+                       tA = hlenA;
+       }
+
+       tB = tA * dirA_dot_dirB - dirB_dot_trans;
+
+       if (tB < -hlenB)
+       {
+               tB = -hlenB;
+               tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+               if (tA < -hlenA)
+                       tA = -hlenA;
+               else if (tA > hlenA)
+                       tA = hlenA;
+       }
+       else if (tB > hlenB)
+       {
+               tB = hlenB;
+               tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+               if (tA < -hlenA)
+                       tA = -hlenA;
+               else if (tA > hlenA)
+                       tA = hlenA;
+       }
+
+       // compute the closest points relative to segment centers.
+
+       offsetA = dirA * tA;
+       offsetB = dirB * tB;
+
+       ptsVector = translation - offsetA + offsetB;
+}
+
+static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance(
+       btVector3& normalOnB,
+       btVector3& pointOnB,
+       btScalar capsuleLengthA,
+       btScalar capsuleRadiusA,
+       btScalar capsuleLengthB,
+       btScalar capsuleRadiusB,
+       int capsuleAxisA,
+       int capsuleAxisB,
+       const btTransform& transformA,
+       const btTransform& transformB,
+       btScalar distanceThreshold)
+{
+       btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA);
+       btVector3 translationA = transformA.getOrigin();
+       btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB);
+       btVector3 translationB = transformB.getOrigin();
+
+       // translation between centers
+
+       btVector3 translation = translationB - translationA;
+
+       // compute the closest points of the capsule line segments
+
+       btVector3 ptsVector;  // the vector between the closest points
+
+       btVector3 offsetA, offsetB;  // offsets from segment centers to their closest points
+       btScalar tA, tB;             // parameters on line segment
+
+       segmentsClosestPoints(ptsVector, offsetA, offsetB, tA, tB, translation,
+                                                 directionA, capsuleLengthA, directionB, capsuleLengthB);
+
+       btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB;
+
+       if (distance > distanceThreshold)
+               return distance;
+
+       btScalar lenSqr = ptsVector.length2();
+       if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
+       {
+               //degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA'
+               btVector3 q;
+               btPlaneSpace1(directionA, normalOnB, q);
+       }
+       else
+       {
+               // compute the contact normal
+               normalOnB = ptsVector * -btRecipSqrt(lenSqr);
+       }
+       pointOnB = transformB.getOrigin() + offsetB + normalOnB * capsuleRadiusB;
+
+       return distance;
+}
+
+//////////
+
+btConvexConvexAlgorithm::CreateFunc::CreateFunc(btConvexPenetrationDepthSolver* pdSolver)
+{
+       m_numPerturbationIterations = 0;
+       m_minimumPointsPerturbationThreshold = 3;
+       m_pdSolver = pdSolver;
+}
+
+btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
+{
+}
+
+btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+       : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+         m_pdSolver(pdSolver),
+         m_ownManifold(false),
+         m_manifoldPtr(mf),
+         m_lowLevelOfDetail(false),
+#ifdef USE_SEPDISTANCE_UTIL2
+         m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(),
+                                       (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()),
+#endif
+         m_numPerturbationIterations(numPerturbationIterations),
+         m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+{
+       (void)body0Wrap;
+       (void)body1Wrap;
+}
+
+btConvexConvexAlgorithm::~btConvexConvexAlgorithm()
+{
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr)
+                       m_dispatcher->releaseManifold(m_manifoldPtr);
+       }
+}
+
+void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
+{
+       m_lowLevelOfDetail = useLowLevel;
+}
+
+struct btPerturbedContactResult : public btManifoldResult
+{
+       btManifoldResult* m_originalManifoldResult;
+       btTransform m_transformA;
+       btTransform m_transformB;
+       btTransform m_unPerturbedTransform;
+       bool m_perturbA;
+       btIDebugDraw* m_debugDrawer;
+
+       btPerturbedContactResult(btManifoldResult* originalResult, const btTransform& transformA, const btTransform& transformB, const btTransform& unPerturbedTransform, bool perturbA, btIDebugDraw* debugDrawer)
+               : m_originalManifoldResult(originalResult),
+                 m_transformA(transformA),
+                 m_transformB(transformB),
+                 m_unPerturbedTransform(unPerturbedTransform),
+                 m_perturbA(perturbA),
+                 m_debugDrawer(debugDrawer)
+       {
+       }
+       virtual ~btPerturbedContactResult()
+       {
+       }
+
+       virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar orgDepth)
+       {
+               btVector3 endPt, startPt;
+               btScalar newDepth;
+               btVector3 newNormal;
+
+               if (m_perturbA)
+               {
+                       btVector3 endPtOrg = pointInWorld + normalOnBInWorld * orgDepth;
+                       endPt = (m_unPerturbedTransform * m_transformA.inverse())(endPtOrg);
+                       newDepth = (endPt - pointInWorld).dot(normalOnBInWorld);
+                       startPt = endPt - normalOnBInWorld * newDepth;
+               }
+               else
+               {
+                       endPt = pointInWorld + normalOnBInWorld * orgDepth;
+                       startPt = (m_unPerturbedTransform * m_transformB.inverse())(pointInWorld);
+                       newDepth = (endPt - startPt).dot(normalOnBInWorld);
+               }
+
+//#define DEBUG_CONTACTS 1
+#ifdef DEBUG_CONTACTS
+               m_debugDrawer->drawLine(startPt, endPt, btVector3(1, 0, 0));
+               m_debugDrawer->drawSphere(startPt, 0.05, btVector3(0, 1, 0));
+               m_debugDrawer->drawSphere(endPt, 0.05, btVector3(0, 0, 1));
+#endif  //DEBUG_CONTACTS
+
+               m_originalManifoldResult->addContactPoint(normalOnBInWorld, startPt, newDepth);
+       }
+};
+
+extern btScalar gContactBreakingThreshold;
+
+//
+// Convex-Convex collision algorithm
+//
+void btConvexConvexAlgorithm ::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       if (!m_manifoldPtr)
+       {
+               //swapped?
+               m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
+               m_ownManifold = true;
+       }
+       resultOut->setPersistentManifold(m_manifoldPtr);
+
+       //comment-out next line to test multi-contact generation
+       //resultOut->getPersistentManifold()->clearManifold();
+
+       const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
+       const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
+
+       btVector3 normalOnB;
+       btVector3 pointOnBWorld;
+#ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
+       if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
+       {
+               //m_manifoldPtr->clearManifold();
+
+               btCapsuleShape* capsuleA = (btCapsuleShape*)min0;
+               btCapsuleShape* capsuleB = (btCapsuleShape*)min1;
+
+               btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
+
+               btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld, capsuleA->getHalfHeight(), capsuleA->getRadius(),
+                                                                                          capsuleB->getHalfHeight(), capsuleB->getRadius(), capsuleA->getUpAxis(), capsuleB->getUpAxis(),
+                                                                                          body0Wrap->getWorldTransform(), body1Wrap->getWorldTransform(), threshold);
+
+               if (dist < threshold)
+               {
+                       btAssert(normalOnB.length2() >= (SIMD_EPSILON * SIMD_EPSILON));
+                       resultOut->addContactPoint(normalOnB, pointOnBWorld, dist);
+               }
+               resultOut->refreshContactPoints();
+               return;
+       }
+
+       if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == SPHERE_SHAPE_PROXYTYPE))
+       {
+               //m_manifoldPtr->clearManifold();
+
+               btCapsuleShape* capsuleA = (btCapsuleShape*)min0;
+               btSphereShape* capsuleB = (btSphereShape*)min1;
+
+               btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
+
+               btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld, capsuleA->getHalfHeight(), capsuleA->getRadius(),
+                                                                                          0., capsuleB->getRadius(), capsuleA->getUpAxis(), 1,
+                                                                                          body0Wrap->getWorldTransform(), body1Wrap->getWorldTransform(), threshold);
+
+               if (dist < threshold)
+               {
+                       btAssert(normalOnB.length2() >= (SIMD_EPSILON * SIMD_EPSILON));
+                       resultOut->addContactPoint(normalOnB, pointOnBWorld, dist);
+               }
+               resultOut->refreshContactPoints();
+               return;
+       }
+
+       if ((min0->getShapeType() == SPHERE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
+       {
+               //m_manifoldPtr->clearManifold();
+
+               btSphereShape* capsuleA = (btSphereShape*)min0;
+               btCapsuleShape* capsuleB = (btCapsuleShape*)min1;
+
+               btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
+
+               btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld, 0., capsuleA->getRadius(),
+                                                                                          capsuleB->getHalfHeight(), capsuleB->getRadius(), 1, capsuleB->getUpAxis(),
+                                                                                          body0Wrap->getWorldTransform(), body1Wrap->getWorldTransform(), threshold);
+
+               if (dist < threshold)
+               {
+                       btAssert(normalOnB.length2() >= (SIMD_EPSILON * SIMD_EPSILON));
+                       resultOut->addContactPoint(normalOnB, pointOnBWorld, dist);
+               }
+               resultOut->refreshContactPoints();
+               return;
+       }
+#endif  //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
+
+#ifdef USE_SEPDISTANCE_UTIL2
+       if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+       {
+               m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(), body1->getWorldTransform());
+       }
+
+       if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance() <= 0.f)
+#endif  //USE_SEPDISTANCE_UTIL2
+
+       {
+               btGjkPairDetector::ClosestPointInput input;
+               btVoronoiSimplexSolver simplexSolver;
+               btGjkPairDetector gjkPairDetector(min0, min1, &simplexSolver, m_pdSolver);
+               //TODO: if (dispatchInfo.m_useContinuous)
+               gjkPairDetector.setMinkowskiA(min0);
+               gjkPairDetector.setMinkowskiB(min1);
+
+#ifdef USE_SEPDISTANCE_UTIL2
+               if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+               {
+                       input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
+               }
+               else
+#endif  //USE_SEPDISTANCE_UTIL2
+               {
+                       //if (dispatchInfo.m_convexMaxDistanceUseCPT)
+                       //{
+                       //      input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold();
+                       //} else
+                       //{
+                       input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold() + resultOut->m_closestPointDistanceThreshold;
+                       //              }
+
+                       input.m_maximumDistanceSquared *= input.m_maximumDistanceSquared;
+               }
+
+               input.m_transformA = body0Wrap->getWorldTransform();
+               input.m_transformB = body1Wrap->getWorldTransform();
+
+#ifdef USE_SEPDISTANCE_UTIL2
+               btScalar sepDist = 0.f;
+               if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+               {
+                       sepDist = gjkPairDetector.getCachedSeparatingDistance();
+                       if (sepDist > SIMD_EPSILON)
+                       {
+                               sepDist += dispatchInfo.m_convexConservativeDistanceThreshold;
+                               //now perturbe directions to get multiple contact points
+                       }
+               }
+#endif  //USE_SEPDISTANCE_UTIL2
+
+               if (min0->isPolyhedral() && min1->isPolyhedral())
+               {
+                       struct btDummyResult : public btDiscreteCollisionDetectorInterface::Result
+                       {
+                               btVector3 m_normalOnBInWorld;
+                               btVector3 m_pointInWorld;
+                               btScalar m_depth;
+                               bool m_hasContact;
+
+                               btDummyResult()
+                                       : m_hasContact(false)
+                               {
+                               }
+
+                               virtual void setShapeIdentifiersA(int partId0, int index0) {}
+                               virtual void setShapeIdentifiersB(int partId1, int index1) {}
+                               virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
+                               {
+                                       m_hasContact = true;
+                                       m_normalOnBInWorld = normalOnBInWorld;
+                                       m_pointInWorld = pointInWorld;
+                                       m_depth = depth;
+                               }
+                       };
+
+                       struct btWithoutMarginResult : public btDiscreteCollisionDetectorInterface::Result
+                       {
+                               btDiscreteCollisionDetectorInterface::Result* m_originalResult;
+                               btVector3 m_reportedNormalOnWorld;
+                               btScalar m_marginOnA;
+                               btScalar m_marginOnB;
+                               btScalar m_reportedDistance;
+
+                               bool m_foundResult;
+                               btWithoutMarginResult(btDiscreteCollisionDetectorInterface::Result* result, btScalar marginOnA, btScalar marginOnB)
+                                       : m_originalResult(result),
+                                         m_marginOnA(marginOnA),
+                                         m_marginOnB(marginOnB),
+                                         m_foundResult(false)
+                               {
+                               }
+
+                               virtual void setShapeIdentifiersA(int partId0, int index0) {}
+                               virtual void setShapeIdentifiersB(int partId1, int index1) {}
+                               virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorldOrg, btScalar depthOrg)
+                               {
+                                       m_reportedDistance = depthOrg;
+                                       m_reportedNormalOnWorld = normalOnBInWorld;
+
+                                       btVector3 adjustedPointB = pointInWorldOrg - normalOnBInWorld * m_marginOnB;
+                                       m_reportedDistance = depthOrg + (m_marginOnA + m_marginOnB);
+                                       if (m_reportedDistance < 0.f)
+                                       {
+                                               m_foundResult = true;
+                                       }
+                                       m_originalResult->addContactPoint(normalOnBInWorld, adjustedPointB, m_reportedDistance);
+                               }
+                       };
+
+                       btDummyResult dummy;
+
+                       ///btBoxShape is an exception: its vertices are created WITH margin so don't subtract it
+
+                       btScalar min0Margin = min0->getShapeType() == BOX_SHAPE_PROXYTYPE ? 0.f : min0->getMargin();
+                       btScalar min1Margin = min1->getShapeType() == BOX_SHAPE_PROXYTYPE ? 0.f : min1->getMargin();
+
+                       btWithoutMarginResult withoutMargin(resultOut, min0Margin, min1Margin);
+
+                       btPolyhedralConvexShape* polyhedronA = (btPolyhedralConvexShape*)min0;
+                       btPolyhedralConvexShape* polyhedronB = (btPolyhedralConvexShape*)min1;
+                       if (polyhedronA->getConvexPolyhedron() && polyhedronB->getConvexPolyhedron())
+                       {
+                               btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
+
+                               btScalar minDist = -1e30f;
+                               btVector3 sepNormalWorldSpace;
+                               bool foundSepAxis = true;
+
+                               if (dispatchInfo.m_enableSatConvex)
+                               {
+                                       foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
+                                               *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+                                               body0Wrap->getWorldTransform(),
+                                               body1Wrap->getWorldTransform(),
+                                               sepNormalWorldSpace, *resultOut);
+                               }
+                               else
+                               {
+#ifdef ZERO_MARGIN
+                                       gjkPairDetector.setIgnoreMargin(true);
+                                       gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
+#else
+
+                                       gjkPairDetector.getClosestPoints(input, withoutMargin, dispatchInfo.m_debugDraw);
+                                       //gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
+#endif  //ZERO_MARGIN
+                                       //btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
+                                       //if (l2>SIMD_EPSILON)
+                                       {
+                                               sepNormalWorldSpace = withoutMargin.m_reportedNormalOnWorld;  //gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
+                                               //minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance();
+                                               minDist = withoutMargin.m_reportedDistance;  //gjkPairDetector.getCachedSeparatingDistance()+min0->getMargin()+min1->getMargin();
+
+#ifdef ZERO_MARGIN
+                                               foundSepAxis = true;  //gjkPairDetector.getCachedSeparatingDistance()<0.f;
+#else
+                                               foundSepAxis = withoutMargin.m_foundResult && minDist < 0;  //-(min0->getMargin()+min1->getMargin());
+#endif
+                                       }
+                               }
+                               if (foundSepAxis)
+                               {
+                                       //                              printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
+
+                                       worldVertsB1.resize(0);
+                                       btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+                                                                                                                                        body0Wrap->getWorldTransform(),
+                                                                                                                                        body1Wrap->getWorldTransform(), minDist - threshold, threshold, worldVertsB1, worldVertsB2,
+                                                                                                                                        *resultOut);
+                               }
+                               if (m_ownManifold)
+                               {
+                                       resultOut->refreshContactPoints();
+                               }
+                               return;
+                       }
+                       else
+                       {
+                               //we can also deal with convex versus triangle (without connectivity data)
+                               if (dispatchInfo.m_enableSatConvex && polyhedronA->getConvexPolyhedron() && polyhedronB->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE)
+                               {
+                                       btVertexArray worldSpaceVertices;
+                                       btTriangleShape* tri = (btTriangleShape*)polyhedronB;
+                                       worldSpaceVertices.push_back(body1Wrap->getWorldTransform() * tri->m_vertices1[0]);
+                                       worldSpaceVertices.push_back(body1Wrap->getWorldTransform() * tri->m_vertices1[1]);
+                                       worldSpaceVertices.push_back(body1Wrap->getWorldTransform() * tri->m_vertices1[2]);
+
+                                       //tri->initializePolyhedralFeatures();
+
+                                       btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
+
+                                       btVector3 sepNormalWorldSpace;
+                                       btScalar minDist = -1e30f;
+                                       btScalar maxDist = threshold;
+
+                                       bool foundSepAxis = false;
+                                       bool useSatSepNormal = true;
+
+                                       if (useSatSepNormal)
+                                       {
+#if 0
+                                       if (0)
+                                       {
+                                               //initializePolyhedralFeatures performs a convex hull computation, not needed for a single triangle
+                                               polyhedronB->initializePolyhedralFeatures();
+                                       } else
+#endif
+                                               {
+                                                       btVector3 uniqueEdges[3] = {tri->m_vertices1[1] - tri->m_vertices1[0],
+                                                                                                               tri->m_vertices1[2] - tri->m_vertices1[1],
+                                                                                                               tri->m_vertices1[0] - tri->m_vertices1[2]};
+
+                                                       uniqueEdges[0].normalize();
+                                                       uniqueEdges[1].normalize();
+                                                       uniqueEdges[2].normalize();
+
+                                                       btConvexPolyhedron polyhedron;
+                                                       polyhedron.m_vertices.push_back(tri->m_vertices1[2]);
+                                                       polyhedron.m_vertices.push_back(tri->m_vertices1[0]);
+                                                       polyhedron.m_vertices.push_back(tri->m_vertices1[1]);
+
+                                                       {
+                                                               btFace combinedFaceA;
+                                                               combinedFaceA.m_indices.push_back(0);
+                                                               combinedFaceA.m_indices.push_back(1);
+                                                               combinedFaceA.m_indices.push_back(2);
+                                                               btVector3 faceNormal = uniqueEdges[0].cross(uniqueEdges[1]);
+                                                               faceNormal.normalize();
+                                                               btScalar planeEq = 1e30f;
+                                                               for (int v = 0; v < combinedFaceA.m_indices.size(); v++)
+                                                               {
+                                                                       btScalar eq = tri->m_vertices1[combinedFaceA.m_indices[v]].dot(faceNormal);
+                                                                       if (planeEq > eq)
+                                                                       {
+                                                                               planeEq = eq;
+                                                                       }
+                                                               }
+                                                               combinedFaceA.m_plane[0] = faceNormal[0];
+                                                               combinedFaceA.m_plane[1] = faceNormal[1];
+                                                               combinedFaceA.m_plane[2] = faceNormal[2];
+                                                               combinedFaceA.m_plane[3] = -planeEq;
+                                                               polyhedron.m_faces.push_back(combinedFaceA);
+                                                       }
+                                                       {
+                                                               btFace combinedFaceB;
+                                                               combinedFaceB.m_indices.push_back(0);
+                                                               combinedFaceB.m_indices.push_back(2);
+                                                               combinedFaceB.m_indices.push_back(1);
+                                                               btVector3 faceNormal = -uniqueEdges[0].cross(uniqueEdges[1]);
+                                                               faceNormal.normalize();
+                                                               btScalar planeEq = 1e30f;
+                                                               for (int v = 0; v < combinedFaceB.m_indices.size(); v++)
+                                                               {
+                                                                       btScalar eq = tri->m_vertices1[combinedFaceB.m_indices[v]].dot(faceNormal);
+                                                                       if (planeEq > eq)
+                                                                       {
+                                                                               planeEq = eq;
+                                                                       }
+                                                               }
+
+                                                               combinedFaceB.m_plane[0] = faceNormal[0];
+                                                               combinedFaceB.m_plane[1] = faceNormal[1];
+                                                               combinedFaceB.m_plane[2] = faceNormal[2];
+                                                               combinedFaceB.m_plane[3] = -planeEq;
+                                                               polyhedron.m_faces.push_back(combinedFaceB);
+                                                       }
+
+                                                       polyhedron.m_uniqueEdges.push_back(uniqueEdges[0]);
+                                                       polyhedron.m_uniqueEdges.push_back(uniqueEdges[1]);
+                                                       polyhedron.m_uniqueEdges.push_back(uniqueEdges[2]);
+                                                       polyhedron.initialize2();
+
+                                                       polyhedronB->setPolyhedralFeatures(polyhedron);
+                                               }
+
+                                               foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
+                                                       *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+                                                       body0Wrap->getWorldTransform(),
+                                                       body1Wrap->getWorldTransform(),
+                                                       sepNormalWorldSpace, *resultOut);
+                                               //       printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
+                                       }
+                                       else
+                                       {
+#ifdef ZERO_MARGIN
+                                               gjkPairDetector.setIgnoreMargin(true);
+                                               gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
+#else
+                                               gjkPairDetector.getClosestPoints(input, dummy, dispatchInfo.m_debugDraw);
+#endif  //ZERO_MARGIN
+
+                                               if (dummy.m_hasContact && dummy.m_depth < 0)
+                                               {
+                                                       if (foundSepAxis)
+                                                       {
+                                                               if (dummy.m_normalOnBInWorld.dot(sepNormalWorldSpace) < 0.99)
+                                                               {
+                                                                       printf("?\n");
+                                                               }
+                                                       }
+                                                       else
+                                                       {
+                                                               printf("!\n");
+                                                       }
+                                                       sepNormalWorldSpace.setValue(0, 0, 1);  // = dummy.m_normalOnBInWorld;
+                                                       //minDist = dummy.m_depth;
+                                                       foundSepAxis = true;
+                                               }
+#if 0
+                                       btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
+                                       if (l2>SIMD_EPSILON)
+                                       {
+                                               sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
+                                               //minDist = gjkPairDetector.getCachedSeparatingDistance();
+                                               //maxDist = threshold;
+                                               minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin();
+                                               foundSepAxis = true;
+                                       }
+#endif
+                                       }
+
+                                       if (foundSepAxis)
+                                       {
+                                               worldVertsB2.resize(0);
+                                               btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(),
+                                                                                                                                                body0Wrap->getWorldTransform(), worldSpaceVertices, worldVertsB2, minDist - threshold, maxDist, *resultOut);
+                                       }
+
+                                       if (m_ownManifold)
+                                       {
+                                               resultOut->refreshContactPoints();
+                                       }
+
+                                       return;
+                               }
+                       }
+               }
+
+               gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
+
+               //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
+
+               //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points
+               if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
+               {
+                       int i;
+                       btVector3 v0, v1;
+                       btVector3 sepNormalWorldSpace;
+                       btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
+
+                       if (l2 > SIMD_EPSILON)
+                       {
+                               sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis() * (1.f / l2);
+
+                               btPlaneSpace1(sepNormalWorldSpace, v0, v1);
+
+                               bool perturbeA = true;
+                               const btScalar angleLimit = 0.125f * SIMD_PI;
+                               btScalar perturbeAngle;
+                               btScalar radiusA = min0->getAngularMotionDisc();
+                               btScalar radiusB = min1->getAngularMotionDisc();
+                               if (radiusA < radiusB)
+                               {
+                                       perturbeAngle = gContactBreakingThreshold / radiusA;
+                                       perturbeA = true;
+                               }
+                               else
+                               {
+                                       perturbeAngle = gContactBreakingThreshold / radiusB;
+                                       perturbeA = false;
+                               }
+                               if (perturbeAngle > angleLimit)
+                                       perturbeAngle = angleLimit;
+
+                               btTransform unPerturbedTransform;
+                               if (perturbeA)
+                               {
+                                       unPerturbedTransform = input.m_transformA;
+                               }
+                               else
+                               {
+                                       unPerturbedTransform = input.m_transformB;
+                               }
+
+                               for (i = 0; i < m_numPerturbationIterations; i++)
+                               {
+                                       if (v0.length2() > SIMD_EPSILON)
+                                       {
+                                               btQuaternion perturbeRot(v0, perturbeAngle);
+                                               btScalar iterationAngle = i * (SIMD_2_PI / btScalar(m_numPerturbationIterations));
+                                               btQuaternion rotq(sepNormalWorldSpace, iterationAngle);
+
+                                               if (perturbeA)
+                                               {
+                                                       input.m_transformA.setBasis(btMatrix3x3(rotq.inverse() * perturbeRot * rotq) * body0Wrap->getWorldTransform().getBasis());
+                                                       input.m_transformB = body1Wrap->getWorldTransform();
+#ifdef DEBUG_CONTACTS
+                                                       dispatchInfo.m_debugDraw->drawTransform(input.m_transformA, 10.0);
+#endif  //DEBUG_CONTACTS
+                                               }
+                                               else
+                                               {
+                                                       input.m_transformA = body0Wrap->getWorldTransform();
+                                                       input.m_transformB.setBasis(btMatrix3x3(rotq.inverse() * perturbeRot * rotq) * body1Wrap->getWorldTransform().getBasis());
+#ifdef DEBUG_CONTACTS
+                                                       dispatchInfo.m_debugDraw->drawTransform(input.m_transformB, 10.0);
+#endif
+                                               }
+
+                                               btPerturbedContactResult perturbedResultOut(resultOut, input.m_transformA, input.m_transformB, unPerturbedTransform, perturbeA, dispatchInfo.m_debugDraw);
+                                               gjkPairDetector.getClosestPoints(input, perturbedResultOut, dispatchInfo.m_debugDraw);
+                                       }
+                               }
+                       }
+               }
+
+#ifdef USE_SEPDISTANCE_UTIL2
+               if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist > SIMD_EPSILON))
+               {
+                       m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(), sepDist, body0->getWorldTransform(), body1->getWorldTransform());
+               }
+#endif  //USE_SEPDISTANCE_UTIL2
+       }
+
+       if (m_ownManifold)
+       {
+               resultOut->refreshContactPoints();
+       }
+}
+
+bool disableCcd = false;
+btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       (void)resultOut;
+       (void)dispatchInfo;
+       ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
+
+       ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
+       ///col0->m_worldTransform,
+       btScalar resultFraction = btScalar(1.);
+
+       btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
+       btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
+
+       if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
+               squareMot1 < col1->getCcdSquareMotionThreshold())
+               return resultFraction;
+
+       if (disableCcd)
+               return btScalar(1.);
+
+       //An adhoc way of testing the Continuous Collision Detection algorithms
+       //One object is approximated as a sphere, to simplify things
+       //Starting in penetration should report no time of impact
+       //For proper CCD, better accuracy and handling of 'allowed' penetration should be added
+       //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
+
+       /// Convex0 against sphere for Convex1
+       {
+               btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
+
+               btSphereShape sphere1(col1->getCcdSweptSphereRadius());  //todo: allow non-zero sphere sizes, for better approximation
+               btConvexCast::CastResult result;
+               btVoronoiSimplexSolver voronoiSimplex;
+               //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+               ///Simplification, one object is simplified as a sphere
+               btGjkConvexCast ccd1(convex0, &sphere1, &voronoiSimplex);
+               //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+               if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
+                                                                 col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
+               {
+                       //store result.m_fraction in both bodies
+
+                       if (col0->getHitFraction() > result.m_fraction)
+                               col0->setHitFraction(result.m_fraction);
+
+                       if (col1->getHitFraction() > result.m_fraction)
+                               col1->setHitFraction(result.m_fraction);
+
+                       if (resultFraction > result.m_fraction)
+                               resultFraction = result.m_fraction;
+               }
+       }
+
+       /// Sphere (for convex0) against Convex1
+       {
+               btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
+
+               btSphereShape sphere0(col0->getCcdSweptSphereRadius());  //todo: allow non-zero sphere sizes, for better approximation
+               btConvexCast::CastResult result;
+               btVoronoiSimplexSolver voronoiSimplex;
+               //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+               ///Simplification, one object is simplified as a sphere
+               btGjkConvexCast ccd1(&sphere0, convex1, &voronoiSimplex);
+               //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+               if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
+                                                                 col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
+               {
+                       //store result.m_fraction in both bodies
+
+                       if (col0->getHitFraction() > result.m_fraction)
+                               col0->setHitFraction(result.m_fraction);
+
+                       if (col1->getHitFraction() > result.m_fraction)
+                               col1->setHitFraction(result.m_fraction);
+
+                       if (resultFraction > result.m_fraction)
+                               resultFraction = result.m_fraction;
+               }
+       }
+
+       return resultFraction;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
new file mode 100644 (file)
index 0000000..9b76162
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_CONVEX_ALGORITHM_H
+#define BT_CONVEX_CONVEX_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.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"
+#include "LinearMath/btTransformUtil.h"  //for btConvexSeparatingDistanceUtil
+#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
+
+class btConvexPenetrationDepthSolver;
+
+///Enabling USE_SEPDISTANCE_UTIL2 requires 100% reliable distance computation. However, when using large size ratios GJK can be imprecise
+///so the distance is not conservative. In that case, enabling this USE_SEPDISTANCE_UTIL2 would result in failing/missing collisions.
+///Either improve GJK for large size ratios (testing a 100 units versus a 0.1 unit object) or only enable the util
+///for certain pairs that have a small size ratio
+
+//#define USE_SEPDISTANCE_UTIL2 1
+
+///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects.
+///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal.
+///This idea was described by Gino van den Bergen in this forum topic http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=4&t=288&p=888#p888
+class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm
+{
+#ifdef USE_SEPDISTANCE_UTIL2
+       btConvexSeparatingDistanceUtil m_sepDistance;
+#endif
+       btConvexPenetrationDepthSolver* m_pdSolver;
+
+       btVertexArray worldVertsB1;
+       btVertexArray worldVertsB2;
+
+       bool m_ownManifold;
+       btPersistentManifold* m_manifoldPtr;
+       bool m_lowLevelOfDetail;
+
+       int m_numPerturbationIterations;
+       int m_minimumPointsPerturbationThreshold;
+
+       ///cache separating vector to speedup collision detection
+
+public:
+       btConvexConvexAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+
+       virtual ~btConvexConvexAlgorithm();
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       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);
+
+       const btPersistentManifold* getManifold()
+       {
+               return m_manifoldPtr;
+       }
+
+       struct CreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               btConvexPenetrationDepthSolver* m_pdSolver;
+               int m_numPerturbationIterations;
+               int m_minimumPointsPerturbationThreshold;
+
+               CreateFunc(btConvexPenetrationDepthSolver* pdSolver);
+
+               virtual ~CreateFunc();
+
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
+                       return new (mem) btConvexConvexAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_pdSolver, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
+               }
+       };
+};
+
+#endif  //BT_CONVEX_CONVEX_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..d91d9c9
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+//#include <stdio.h>
+
+btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+       : btCollisionAlgorithm(ci),
+         m_ownManifold(false),
+         m_manifoldPtr(mf),
+         m_isSwapped(isSwapped),
+         m_numPerturbationIterations(numPerturbationIterations),
+         m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+{
+       const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? col1Wrap : col0Wrap;
+       const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? col0Wrap : col1Wrap;
+
+       if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(), planeObjWrap->getCollisionObject()))
+       {
+               m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(), planeObjWrap->getCollisionObject());
+               m_ownManifold = true;
+       }
+}
+
+btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
+{
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr)
+                       m_dispatcher->releaseManifold(m_manifoldPtr);
+       }
+}
+
+void btConvexPlaneCollisionAlgorithm::collideSingleContact(const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+       const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
+
+       btConvexShape* convexShape = (btConvexShape*)convexObjWrap->getCollisionShape();
+       btStaticPlaneShape* planeShape = (btStaticPlaneShape*)planeObjWrap->getCollisionShape();
+
+       bool hasCollision = false;
+       const btVector3& planeNormal = planeShape->getPlaneNormal();
+       const btScalar& planeConstant = planeShape->getPlaneConstant();
+
+       btTransform convexWorldTransform = convexObjWrap->getWorldTransform();
+       btTransform convexInPlaneTrans;
+       convexInPlaneTrans = planeObjWrap->getWorldTransform().inverse() * convexWorldTransform;
+       //now perturbe the convex-world transform
+       convexWorldTransform.getBasis() *= btMatrix3x3(perturbeRot);
+       btTransform planeInConvex;
+       planeInConvex = convexWorldTransform.inverse() * planeObjWrap->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 = planeObjWrap->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 = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
+               btVector3 pOnB = vtxInPlaneWorld;
+               resultOut->addContactPoint(normalOnSurfaceB, pOnB, distance);
+       }
+}
+
+void btConvexPlaneCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       (void)dispatchInfo;
+       if (!m_manifoldPtr)
+               return;
+
+       const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+       const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
+
+       btConvexShape* convexShape = (btConvexShape*)convexObjWrap->getCollisionShape();
+       btStaticPlaneShape* planeShape = (btStaticPlaneShape*)planeObjWrap->getCollisionShape();
+
+       bool hasCollision = false;
+       const btVector3& planeNormal = planeShape->getPlaneNormal();
+       const btScalar& planeConstant = planeShape->getPlaneConstant();
+       btTransform planeInConvex;
+       planeInConvex = convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform();
+       btTransform convexInPlaneTrans;
+       convexInPlaneTrans = planeObjWrap->getWorldTransform().inverse() * convexObjWrap->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 = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
+
+       hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
+       resultOut->setPersistentManifold(m_manifoldPtr);
+       if (hasCollision)
+       {
+               /// report a contact. internally this will be kept persistent, and contact reduction is done
+               btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
+               btVector3 pOnB = vtxInPlaneWorld;
+               resultOut->addContactPoint(normalOnSurfaceB, pOnB, distance);
+       }
+
+       //the perturbation algorithm doesn't work well with implicit surfaces such as spheres, cylinder and cones:
+       //they keep on rolling forever because of the additional off-center contact points
+       //so only enable the feature for polyhedral shapes (btBoxShape, btConvexHullShape etc)
+       if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
+       {
+               btVector3 v0, v1;
+               btPlaneSpace1(planeNormal, v0, v1);
+               //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
+
+               const btScalar angleLimit = 0.125f * SIMD_PI;
+               btScalar perturbeAngle;
+               btScalar radius = convexShape->getAngularMotionDisc();
+               perturbeAngle = gContactBreakingThreshold / radius;
+               if (perturbeAngle > angleLimit)
+                       perturbeAngle = angleLimit;
+
+               btQuaternion perturbeRot(v0, perturbeAngle);
+               for (int i = 0; i < m_numPerturbationIterations; i++)
+               {
+                       btScalar iterationAngle = i * (SIMD_2_PI / btScalar(m_numPerturbationIterations));
+                       btQuaternion rotq(planeNormal, iterationAngle);
+                       collideSingleContact(rotq.inverse() * perturbeRot * rotq, body0Wrap, body1Wrap, dispatchInfo, resultOut);
+               }
+       }
+
+       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/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..63402d9
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_PLANE_COLLISION_ALGORITHM_H
+#define BT_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;
+       int m_numPerturbationIterations;
+       int m_minimumPointsPerturbationThreshold;
+
+public:
+       btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+
+       virtual ~btConvexPlaneCollisionAlgorithm();
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       void collideSingleContact(const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, 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
+       {
+               int m_numPerturbationIterations;
+               int m_minimumPointsPerturbationThreshold;
+
+               CreateFunc()
+                       : m_numPerturbationIterations(1),
+                         m_minimumPointsPerturbationThreshold(0)
+               {
+               }
+
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
+                       if (!m_swapped)
+                       {
+                               return new (mem) btConvexPlaneCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
+                       }
+                       else
+                       {
+                               return new (mem) btConvexPlaneCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
+                       }
+               }
+       };
+};
+
+#endif  //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
new file mode 100644 (file)
index 0000000..f6e6343
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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/btCompoundCompoundCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#endif  //USE_BUGGY_SPHERE_BOX_ALGORITHM
+#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+
+#include "LinearMath/btPoolAllocator.h"
+
+btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
+//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc*       stackAlloc,btPoolAllocator*     persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
+{
+       void* mem = NULL;
+       if (constructionInfo.m_useEpaPenetrationAlgorithm)
+       {
+               mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver), 16);
+               m_pdSolver = new (mem) btGjkEpaPenetrationDepthSolver;
+       }
+       else
+       {
+               mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver), 16);
+               m_pdSolver = new (mem) btMinkowskiPenetrationDepthSolver;
+       }
+
+       //default CreationFunctions, filling the m_doubleDispatch table
+       mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc), 16);
+       m_convexConvexCreateFunc = new (mem) btConvexConvexAlgorithm::CreateFunc(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(btCompoundCompoundCollisionAlgorithm::CreateFunc), 16);
+       m_compoundCompoundCreateFunc = new (mem) btCompoundCompoundCollisionAlgorithm::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;
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+       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;
+#endif  //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+       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(btCompoundCompoundCollisionAlgorithm);
+
+       int collisionAlgorithmMaxElementSize = btMax(maxSize, constructionInfo.m_customCollisionAlgorithmMaxElementSize);
+       collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize2);
+       collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize3);
+       collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize4);
+
+       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);
+       }
+
+       collisionAlgorithmMaxElementSize = (collisionAlgorithmMaxElementSize + 16) & 0xffffffffffff0;
+       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_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_compoundCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree(m_compoundCompoundCreateFunc);
+
+       m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree(m_swappedCompoundCreateFunc);
+
+       m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree(m_emptyCreateFunc);
+
+       m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree(m_sphereSphereCF);
+
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+       m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree(m_sphereBoxCF);
+       m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
+       btAlignedFree(m_boxSphereCF);
+#endif  //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+       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_pdSolver->~btConvexPenetrationDepthSolver();
+
+       btAlignedFree(m_pdSolver);
+}
+
+btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1)
+{
+       if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
+       {
+               return m_sphereSphereCF;
+       }
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+       if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
+       {
+               return m_sphereBoxCF;
+       }
+
+       if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
+       {
+               return m_boxSphereCF;
+       }
+#endif  //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+       if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE))
+       {
+               return m_sphereTriangleCF;
+       }
+
+       if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
+       {
+               return m_triangleSphereCF;
+       }
+
+       if (btBroadphaseProxy::isConvex(proxyType0) && (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) && btBroadphaseProxy::isCompound(proxyType1))
+       {
+               return m_compoundCompoundCreateFunc;
+       }
+
+       if (btBroadphaseProxy::isCompound(proxyType0))
+       {
+               return m_compoundCreateFunc;
+       }
+       else
+       {
+               if (btBroadphaseProxy::isCompound(proxyType1))
+               {
+                       return m_swappedCompoundCreateFunc;
+               }
+       }
+
+       //failed to find an algorithm
+       return m_emptyCreateFunc;
+}
+
+btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1)
+{
+       if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
+       {
+               return m_sphereSphereCF;
+       }
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+       if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
+       {
+               return m_sphereBoxCF;
+       }
+
+       if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
+       {
+               return m_boxSphereCF;
+       }
+#endif  //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+       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) && btBroadphaseProxy::isCompound(proxyType1))
+       {
+               return m_compoundCompoundCreateFunc;
+       }
+
+       if (btBroadphaseProxy::isCompound(proxyType0))
+       {
+               return m_compoundCreateFunc;
+       }
+       else
+       {
+               if (btBroadphaseProxy::isCompound(proxyType1))
+               {
+                       return m_swappedCompoundCreateFunc;
+               }
+       }
+
+       //failed to find an algorithm
+       return m_emptyCreateFunc;
+}
+
+void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+{
+       btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*)m_convexConvexCreateFunc;
+       convexConvex->m_numPerturbationIterations = numPerturbationIterations;
+       convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
+}
+
+void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+{
+       btConvexPlaneCollisionAlgorithm::CreateFunc* cpCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_convexPlaneCF;
+       cpCF->m_numPerturbationIterations = numPerturbationIterations;
+       cpCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
+
+       btConvexPlaneCollisionAlgorithm::CreateFunc* pcCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_planeConvexCF;
+       pcCF->m_numPerturbationIterations = numPerturbationIterations;
+       pcCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
new file mode 100644 (file)
index 0000000..adab540
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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
+{
+       btPoolAllocator* m_persistentManifoldPool;
+       btPoolAllocator* m_collisionAlgorithmPool;
+       int m_defaultMaxPersistentManifoldPoolSize;
+       int m_defaultMaxCollisionAlgorithmPoolSize;
+       int m_customCollisionAlgorithmMaxElementSize;
+       int m_useEpaPenetrationAlgorithm;
+
+       btDefaultCollisionConstructionInfo()
+               : m_persistentManifoldPool(0),
+                 m_collisionAlgorithmPool(0),
+                 m_defaultMaxPersistentManifoldPoolSize(4096),
+                 m_defaultMaxCollisionAlgorithmPoolSize(4096),
+                 m_customCollisionAlgorithmMaxElementSize(0),
+                 m_useEpaPenetrationAlgorithm(true)
+       {
+       }
+};
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator, pool memory allocators
+///@todo: describe the meaning
+class btDefaultCollisionConfiguration : public btCollisionConfiguration
+{
+protected:
+       int m_persistentManifoldPoolSize;
+
+       btPoolAllocator* m_persistentManifoldPool;
+       bool m_ownsPersistentManifoldPool;
+
+       btPoolAllocator* m_collisionAlgorithmPool;
+       bool m_ownsCollisionAlgorithmPool;
+
+       //default penetration depth solver
+       btConvexPenetrationDepthSolver* m_pdSolver;
+
+       //default CreationFunctions, filling the m_doubleDispatch table
+       btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
+       btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
+       btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
+       btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
+       btCollisionAlgorithmCreateFunc* m_compoundCompoundCreateFunc;
+
+       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 btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1);
+
+       virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1);
+
+       ///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm.
+       ///By default, this feature is disabled for best performance.
+       ///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature.
+       ///@param minimumPointsPerturbationThreshold is the minimum number of points in the contact cache, above which the feature is disabled
+       ///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first.
+       ///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points.
+       ///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection.
+       void setConvexConvexMultipointIterations(int numPerturbationIterations = 3, int minimumPointsPerturbationThreshold = 3);
+
+       void setPlaneConvexMultipointIterations(int numPerturbationIterations = 3, int minimumPointsPerturbationThreshold = 3);
+};
+
+#endif  //BT_DEFAULT_COLLISION_CONFIGURATION
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..6c71dc5
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btEmptyCollisionAlgorithm.h"
+
+btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+       : btCollisionAlgorithm(ci)
+{
+}
+
+void btEmptyAlgorithm::processCollision(const btCollisionObjectWrapper*, const btCollisionObjectWrapper*, const btDispatcherInfo&, btManifoldResult*)
+{
+}
+
+btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject*, btCollisionObject*, const btDispatcherInfo&, btManifoldResult*)
+{
+       return btScalar(1.);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..fef2f27
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_EMPTY_ALGORITH
+#define BT_EMPTY_ALGORITH
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+
+#define ATTRIBUTE_ALIGNED(a)
+
+///EmptyAlgorithm is a stub for unsupported collision pairs.
+///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame.
+class btEmptyAlgorithm : public btCollisionAlgorithm
+{
+public:
+       btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       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, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       (void)body0Wrap;
+                       (void)body1Wrap;
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
+                       return new (mem) btEmptyAlgorithm(ci);
+               }
+       };
+
+} ATTRIBUTE_ALIGNED(16);
+
+#endif  //BT_EMPTY_ALGORITH
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btGhostObject.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btGhostObject.cpp
new file mode 100644 (file)
index 0000000..00f16fd
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+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 "btGhostObject.h"
+#include "btCollisionWorld.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "LinearMath/btAabbUtil2.h"
+
+btGhostObject::btGhostObject()
+{
+       m_internalType = CO_GHOST_OBJECT;
+}
+
+btGhostObject::~btGhostObject()
+{
+       ///btGhostObject should have been removed from the world, so no overlapping objects
+       btAssert(!m_overlappingObjects.size());
+}
+
+void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy)
+{
+       btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+       btAssert(otherObject);
+       ///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
+       int index = m_overlappingObjects.findLinearSearch(otherObject);
+       if (index == m_overlappingObjects.size())
+       {
+               //not found
+               m_overlappingObjects.push_back(otherObject);
+       }
+}
+
+void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy)
+{
+       btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+       btAssert(otherObject);
+       int index = m_overlappingObjects.findLinearSearch(otherObject);
+       if (index < m_overlappingObjects.size())
+       {
+               m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
+               m_overlappingObjects.pop_back();
+       }
+}
+
+btPairCachingGhostObject::btPairCachingGhostObject()
+{
+       m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16)) btHashedOverlappingPairCache();
+}
+
+btPairCachingGhostObject::~btPairCachingGhostObject()
+{
+       m_hashPairCache->~btHashedOverlappingPairCache();
+       btAlignedFree(m_hashPairCache);
+}
+
+void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy)
+{
+       btBroadphaseProxy* actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
+       btAssert(actualThisProxy);
+
+       btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+       btAssert(otherObject);
+       int index = m_overlappingObjects.findLinearSearch(otherObject);
+       if (index == m_overlappingObjects.size())
+       {
+               m_overlappingObjects.push_back(otherObject);
+               m_hashPairCache->addOverlappingPair(actualThisProxy, otherProxy);
+       }
+}
+
+void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy1)
+{
+       btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+       btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle();
+       btAssert(actualThisProxy);
+
+       btAssert(otherObject);
+       int index = m_overlappingObjects.findLinearSearch(otherObject);
+       if (index < m_overlappingObjects.size())
+       {
+               m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
+               m_overlappingObjects.pop_back();
+               m_hashPairCache->removeOverlappingPair(actualThisProxy, otherProxy, dispatcher);
+       }
+}
+
+void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) 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_overlappingObjects.size(); i++)
+       {
+               btCollisionObject* collisionObject = m_overlappingObjects[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))
+                       {
+                               btCollisionWorld::objectQuerySingle(castShape, convexFromTrans, convexToTrans,
+                                                                                                       collisionObject,
+                                                                                                       collisionObject->getCollisionShape(),
+                                                                                                       collisionObject->getWorldTransform(),
+                                                                                                       resultCallback,
+                                                                                                       allowedCcdPenetration);
+                       }
+               }
+       }
+}
+
+void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
+{
+       btTransform rayFromTrans;
+       rayFromTrans.setIdentity();
+       rayFromTrans.setOrigin(rayFromWorld);
+       btTransform rayToTrans;
+       rayToTrans.setIdentity();
+       rayToTrans.setOrigin(rayToWorld);
+
+       int i;
+       for (i = 0; i < m_overlappingObjects.size(); i++)
+       {
+               btCollisionObject* collisionObject = m_overlappingObjects[i];
+               //only perform raycast if filterMask matches
+               if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+               {
+                       btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans,
+                                                                                       collisionObject,
+                                                                                       collisionObject->getCollisionShape(),
+                                                                                       collisionObject->getWorldTransform(),
+                                                                                       resultCallback);
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btGhostObject.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btGhostObject.h
new file mode 100644 (file)
index 0000000..aa7f48d
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+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.
+*/
+
+#ifndef BT_GHOST_OBJECT_H
+#define BT_GHOST_OBJECT_H
+
+#include "btCollisionObject.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "btCollisionWorld.h"
+
+class btConvexShape;
+
+class btDispatcher;
+
+///The btGhostObject can keep track of all objects that are overlapping
+///By default, this overlap is based on the AABB
+///This is useful for creating a character controller, collision sensors/triggers, explosions etc.
+///We plan on adding rayTest and other queries for the btGhostObject
+ATTRIBUTE_ALIGNED16(class)
+btGhostObject : public btCollisionObject
+{
+protected:
+       btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
+
+public:
+       btGhostObject();
+
+       virtual ~btGhostObject();
+
+       void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
+
+       void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
+
+       ///this method is mainly for expert/internal use only.
+       virtual void addOverlappingObjectInternal(btBroadphaseProxy * otherProxy, btBroadphaseProxy* thisProxy = 0);
+       ///this method is mainly for expert/internal use only.
+       virtual void removeOverlappingObjectInternal(btBroadphaseProxy * otherProxy, btDispatcher * dispatcher, btBroadphaseProxy* thisProxy = 0);
+
+       int getNumOverlappingObjects() const
+       {
+               return m_overlappingObjects.size();
+       }
+
+       btCollisionObject* getOverlappingObject(int index)
+       {
+               return m_overlappingObjects[index];
+       }
+
+       const btCollisionObject* getOverlappingObject(int index) const
+       {
+               return m_overlappingObjects[index];
+       }
+
+       btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
+       {
+               return m_overlappingObjects;
+       }
+
+       const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
+       {
+               return m_overlappingObjects;
+       }
+
+       //
+       // internal cast
+       //
+
+       static const btGhostObject* upcast(const btCollisionObject* colObj)
+       {
+               if (colObj->getInternalType() == CO_GHOST_OBJECT)
+                       return (const btGhostObject*)colObj;
+               return 0;
+       }
+       static btGhostObject* upcast(btCollisionObject * colObj)
+       {
+               if (colObj->getInternalType() == CO_GHOST_OBJECT)
+                       return (btGhostObject*)colObj;
+               return 0;
+       }
+};
+
+class btPairCachingGhostObject : public btGhostObject
+{
+       btHashedOverlappingPairCache* m_hashPairCache;
+
+public:
+       btPairCachingGhostObject();
+
+       virtual ~btPairCachingGhostObject();
+
+       ///this method is mainly for expert/internal use only.
+       virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy = 0);
+
+       virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy = 0);
+
+       btHashedOverlappingPairCache* getOverlappingPairCache()
+       {
+               return m_hashPairCache;
+       }
+};
+
+///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject.
+class btGhostPairCallback : public btOverlappingPairCallback
+{
+public:
+       btGhostPairCallback()
+       {
+       }
+
+       virtual ~btGhostPairCallback()
+       {
+       }
+
+       virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+       {
+               btCollisionObject* colObj0 = (btCollisionObject*)proxy0->m_clientObject;
+               btCollisionObject* colObj1 = (btCollisionObject*)proxy1->m_clientObject;
+               btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
+               btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
+               if (ghost0)
+                       ghost0->addOverlappingObjectInternal(proxy1, proxy0);
+               if (ghost1)
+                       ghost1->addOverlappingObjectInternal(proxy0, proxy1);
+               return 0;
+       }
+
+       virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
+       {
+               btCollisionObject* colObj0 = (btCollisionObject*)proxy0->m_clientObject;
+               btCollisionObject* colObj1 = (btCollisionObject*)proxy1->m_clientObject;
+               btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
+               btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
+               if (ghost0)
+                       ghost0->removeOverlappingObjectInternal(proxy1, dispatcher, proxy0);
+               if (ghost1)
+                       ghost1->removeOverlappingObjectInternal(proxy0, dispatcher, proxy1);
+               return 0;
+       }
+
+       virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/, btDispatcher* /*dispatcher*/)
+       {
+               btAssert(0);
+               //need to keep track of all ghost objects and call them here
+               //m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
+       }
+};
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp
new file mode 100644 (file)
index 0000000..18d7dfd
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btHashedSimplePairCache.h"
+
+#include <stdio.h>
+
+#ifdef BT_DEBUG_COLLISION_PAIRS
+int gOverlappingSimplePairs = 0;
+int gRemoveSimplePairs = 0;
+int gAddedSimplePairs = 0;
+int gFindSimplePairs = 0;
+#endif  //BT_DEBUG_COLLISION_PAIRS
+
+btHashedSimplePairCache::btHashedSimplePairCache()
+{
+       int initialAllocatedSize = 2;
+       m_overlappingPairArray.reserve(initialAllocatedSize);
+       growTables();
+}
+
+btHashedSimplePairCache::~btHashedSimplePairCache()
+{
+}
+
+void btHashedSimplePairCache::removeAllPairs()
+{
+       m_overlappingPairArray.clear();
+       m_hashTable.clear();
+       m_next.clear();
+
+       int initialAllocatedSize = 2;
+       m_overlappingPairArray.reserve(initialAllocatedSize);
+       growTables();
+}
+
+btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB)
+{
+#ifdef BT_DEBUG_COLLISION_PAIRS
+       gFindSimplePairs++;
+#endif
+
+       /*if (indexA > indexB) 
+               btSwap(indexA, indexB);*/
+
+       int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
+
+       if (hash >= m_hashTable.size())
+       {
+               return NULL;
+       }
+
+       int index = m_hashTable[hash];
+       while (index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], indexA, indexB) == false)
+       {
+               index = m_next[index];
+       }
+
+       if (index == BT_SIMPLE_NULL_PAIR)
+       {
+               return NULL;
+       }
+
+       btAssert(index < m_overlappingPairArray.size());
+
+       return &m_overlappingPairArray[index];
+}
+
+//#include <stdio.h>
+
+void btHashedSimplePairCache::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_SIMPLE_NULL_PAIR;
+               }
+               for (i = 0; i < newCapacity; ++i)
+               {
+                       m_next[i] = BT_SIMPLE_NULL_PAIR;
+               }
+
+               for (i = 0; i < curHashtableSize; i++)
+               {
+                       const btSimplePair& pair = m_overlappingPairArray[i];
+                       int indexA = pair.m_indexA;
+                       int indexB = pair.m_indexB;
+
+                       int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));  // New hash value with new mask
+                       m_next[i] = m_hashTable[hashValue];
+                       m_hashTable[hashValue] = i;
+               }
+       }
+}
+
+btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB)
+{
+       int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));  // New hash value with new mask
+
+       btSimplePair* pair = internalFindPair(indexA, indexB, hash);
+       if (pair != NULL)
+       {
+               return pair;
+       }
+
+       int count = m_overlappingPairArray.size();
+       int oldCapacity = m_overlappingPairArray.capacity();
+       void* mem = &m_overlappingPairArray.expandNonInitializing();
+
+       int newCapacity = m_overlappingPairArray.capacity();
+
+       if (oldCapacity < newCapacity)
+       {
+               growTables();
+               //hash with new capacity
+               hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
+       }
+
+       pair = new (mem) btSimplePair(indexA, indexB);
+
+       pair->m_userPointer = 0;
+
+       m_next[count] = m_hashTable[hash];
+       m_hashTable[hash] = count;
+
+       return pair;
+}
+
+void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
+{
+#ifdef BT_DEBUG_COLLISION_PAIRS
+       gRemoveSimplePairs++;
+#endif
+
+       /*if (indexA > indexB) 
+               btSwap(indexA, indexB);*/
+
+       int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
+
+       btSimplePair* pair = internalFindPair(indexA, indexB, hash);
+       if (pair == NULL)
+       {
+               return 0;
+       }
+
+       void* userData = pair->m_userPointer;
+
+       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_SIMPLE_NULL_PAIR);
+
+       int previous = BT_SIMPLE_NULL_PAIR;
+       while (index != pairIndex)
+       {
+               previous = index;
+               index = m_next[index];
+       }
+
+       if (previous != BT_SIMPLE_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 btSimplePair* last = &m_overlappingPairArray[lastPairIndex];
+       /* missing swap here too, Nat. */
+       int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_indexA), static_cast<unsigned int>(last->m_indexB)) & (m_overlappingPairArray.capacity() - 1));
+
+       index = m_hashTable[lastHash];
+       btAssert(index != BT_SIMPLE_NULL_PAIR);
+
+       previous = BT_SIMPLE_NULL_PAIR;
+       while (index != lastPairIndex)
+       {
+               previous = index;
+               index = m_next[index];
+       }
+
+       if (previous != BT_SIMPLE_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>
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h
new file mode 100644 (file)
index 0000000..e6acbb8
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_HASHED_SIMPLE_PAIR_CACHE_H
+#define BT_HASHED_SIMPLE_PAIR_CACHE_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+const int BT_SIMPLE_NULL_PAIR = 0xffffffff;
+
+struct btSimplePair
+{
+       btSimplePair(int indexA, int indexB)
+               : m_indexA(indexA),
+                 m_indexB(indexB),
+                 m_userPointer(0)
+       {
+       }
+
+       int m_indexA;
+       int m_indexB;
+       union {
+               void* m_userPointer;
+               int m_userValue;
+       };
+};
+
+typedef btAlignedObjectArray<btSimplePair> btSimplePairArray;
+
+#ifdef BT_DEBUG_COLLISION_PAIRS
+extern int gOverlappingSimplePairs;
+extern int gRemoveSimplePairs;
+extern int gAddedSimplePairs;
+extern int gFindSimplePairs;
+#endif  //BT_DEBUG_COLLISION_PAIRS
+
+class btHashedSimplePairCache
+{
+       btSimplePairArray m_overlappingPairArray;
+
+protected:
+       btAlignedObjectArray<int> m_hashTable;
+       btAlignedObjectArray<int> m_next;
+
+public:
+       btHashedSimplePairCache();
+       virtual ~btHashedSimplePairCache();
+
+       void removeAllPairs();
+
+       virtual void* removeOverlappingPair(int indexA, int indexB);
+
+       // 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 btSimplePair* addOverlappingPair(int indexA, int indexB)
+       {
+#ifdef BT_DEBUG_COLLISION_PAIRS
+               gAddedSimplePairs++;
+#endif
+
+               return internalAddPair(indexA, indexB);
+       }
+
+       virtual btSimplePair* getOverlappingPairArrayPtr()
+       {
+               return &m_overlappingPairArray[0];
+       }
+
+       const btSimplePair* getOverlappingPairArrayPtr() const
+       {
+               return &m_overlappingPairArray[0];
+       }
+
+       btSimplePairArray& getOverlappingPairArray()
+       {
+               return m_overlappingPairArray;
+       }
+
+       const btSimplePairArray& getOverlappingPairArray() const
+       {
+               return m_overlappingPairArray;
+       }
+
+       btSimplePair* findPair(int indexA, int indexB);
+
+       int GetCount() const { return m_overlappingPairArray.size(); }
+
+       int getNumOverlappingPairs() const
+       {
+               return m_overlappingPairArray.size();
+       }
+
+private:
+       btSimplePair* internalAddPair(int indexA, int indexB);
+
+       void growTables();
+
+       SIMD_FORCE_INLINE bool equalsPair(const btSimplePair& pair, int indexA, int indexB)
+       {
+               return pair.m_indexA == indexA && pair.m_indexB == indexB;
+       }
+
+       SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB)
+       {
+               unsigned int key = indexA | (indexB << 16);
+               // Thomas Wang's hash
+
+               key += ~(key << 15);
+               key ^= (key >> 10);
+               key += (key << 3);
+               key ^= (key >> 6);
+               key += ~(key << 11);
+               key ^= (key >> 16);
+               return key;
+       }
+
+       SIMD_FORCE_INLINE btSimplePair* internalFindPair(int proxyIdA, int proxyIdB, int hash)
+       {
+               int index = m_hashTable[hash];
+
+               while (index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyIdA, proxyIdB) == false)
+               {
+                       index = m_next[index];
+               }
+
+               if (index == BT_SIMPLE_NULL_PAIR)
+               {
+                       return NULL;
+               }
+
+               btAssert(index < m_overlappingPairArray.size());
+
+               return &m_overlappingPairArray[index];
+       }
+};
+
+#endif  //BT_HASHED_SIMPLE_PAIR_CACHE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
new file mode 100644 (file)
index 0000000..a71700f
--- /dev/null
@@ -0,0 +1,900 @@
+#include "btInternalEdgeUtility.h"
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
+
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+//#define DEBUG_INTERNAL_EDGE
+
+#ifdef DEBUG_INTERNAL_EDGE
+#include <stdio.h>
+#endif  //DEBUG_INTERNAL_EDGE
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+static btIDebugDraw* gDebugDrawer = 0;
+
+void btSetDebugDrawer(btIDebugDraw* debugDrawer)
+{
+       gDebugDrawer = debugDrawer;
+}
+
+static void btDebugDrawLine(const btVector3& from, const btVector3& to, const btVector3& color)
+{
+       if (gDebugDrawer)
+               gDebugDrawer->drawLine(from, to, color);
+}
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+static int btGetHash(int partId, int triangleIndex)
+{
+       int hash = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+       return hash;
+}
+
+static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA, const btVector3& normalB)
+{
+       const btVector3 refAxis0 = edgeA;
+       const btVector3 refAxis1 = normalA;
+       const btVector3 swingAxis = normalB;
+       btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+       return angle;
+}
+
+struct btConnectivityProcessor : public btTriangleCallback
+{
+       int m_partIdA;
+       int m_triangleIndexA;
+       btVector3* m_triangleVerticesA;
+       btTriangleInfoMap* m_triangleInfoMap;
+
+       virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+       {
+               //skip self-collisions
+               if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex))
+                       return;
+
+               //skip duplicates (disabled for now)
+               //if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex))
+               //      return;
+
+               //search for shared vertices and edges
+               int numshared = 0;
+               int sharedVertsA[3] = {-1, -1, -1};
+               int sharedVertsB[3] = {-1, -1, -1};
+
+               ///skip degenerate triangles
+               btScalar crossBSqr = ((triangle[1] - triangle[0]).cross(triangle[2] - triangle[0])).length2();
+               if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
+                       return;
+
+               btScalar crossASqr = ((m_triangleVerticesA[1] - m_triangleVerticesA[0]).cross(m_triangleVerticesA[2] - m_triangleVerticesA[0])).length2();
+               ///skip degenerate triangles
+               if (crossASqr < m_triangleInfoMap->m_equalVertexThreshold)
+                       return;
+
+#if 0
+               printf("triangle A[0]   =       (%f,%f,%f)\ntriangle A[1]       =       (%f,%f,%f)\ntriangle A[2]       =       (%f,%f,%f)\n",
+                       m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(),
+                       m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(),
+                       m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ());
+
+               printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex);
+               printf("triangle B[0]   =       (%f,%f,%f)\ntriangle B[1]       =       (%f,%f,%f)\ntriangle B[2]       =       (%f,%f,%f)\n",
+                       triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(),
+                       triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(),
+                       triangle[2].getX(),triangle[2].getY(),triangle[2].getZ());
+#endif
+
+               for (int i = 0; i < 3; i++)
+               {
+                       for (int j = 0; j < 3; j++)
+                       {
+                               if ((m_triangleVerticesA[i] - triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
+                               {
+                                       sharedVertsA[numshared] = i;
+                                       sharedVertsB[numshared] = j;
+                                       numshared++;
+                                       ///degenerate case
+                                       if (numshared >= 3)
+                                               return;
+                               }
+                       }
+                       ///degenerate case
+                       if (numshared >= 3)
+                               return;
+               }
+               switch (numshared)
+               {
+                       case 0:
+                       {
+                               break;
+                       }
+                       case 1:
+                       {
+                               //shared vertex
+                               break;
+                       }
+                       case 2:
+                       {
+                               //shared edge
+                               //we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct
+                               if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2)
+                               {
+                                       sharedVertsA[0] = 2;
+                                       sharedVertsA[1] = 0;
+                                       int tmp = sharedVertsB[1];
+                                       sharedVertsB[1] = sharedVertsB[0];
+                                       sharedVertsB[0] = tmp;
+                               }
+
+                               int hash = btGetHash(m_partIdA, m_triangleIndexA);
+
+                               btTriangleInfo* info = m_triangleInfoMap->find(hash);
+                               if (!info)
+                               {
+                                       btTriangleInfo tmp;
+                                       m_triangleInfoMap->insert(hash, tmp);
+                                       info = m_triangleInfoMap->find(hash);
+                               }
+
+                               int sumvertsA = sharedVertsA[0] + sharedVertsA[1];
+                               int otherIndexA = 3 - sumvertsA;
+
+                               btVector3 edge(m_triangleVerticesA[sharedVertsA[1]] - m_triangleVerticesA[sharedVertsA[0]]);
+
+                               btTriangleShape tA(m_triangleVerticesA[0], m_triangleVerticesA[1], m_triangleVerticesA[2]);
+                               int otherIndexB = 3 - (sharedVertsB[0] + sharedVertsB[1]);
+
+                               btTriangleShape tB(triangle[sharedVertsB[1]], triangle[sharedVertsB[0]], triangle[otherIndexB]);
+                               //btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
+
+                               btVector3 normalA;
+                               btVector3 normalB;
+                               tA.calcNormal(normalA);
+                               tB.calcNormal(normalB);
+                               edge.normalize();
+                               btVector3 edgeCrossA = edge.cross(normalA).normalize();
+
+                               {
+                                       btVector3 tmp = m_triangleVerticesA[otherIndexA] - m_triangleVerticesA[sharedVertsA[0]];
+                                       if (edgeCrossA.dot(tmp) < 0)
+                                       {
+                                               edgeCrossA *= -1;
+                                       }
+                               }
+
+                               btVector3 edgeCrossB = edge.cross(normalB).normalize();
+
+                               {
+                                       btVector3 tmp = triangle[otherIndexB] - triangle[sharedVertsB[0]];
+                                       if (edgeCrossB.dot(tmp) < 0)
+                                       {
+                                               edgeCrossB *= -1;
+                                       }
+                               }
+
+                               btScalar angle2 = 0;
+                               btScalar ang4 = 0.f;
+
+                               btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB);
+                               btScalar len2 = calculatedEdge.length2();
+
+                               btScalar correctedAngle(0);
+                               //btVector3 calculatedNormalB = normalA;
+                               bool isConvex = false;
+
+                               if (len2 < m_triangleInfoMap->m_planarEpsilon)
+                               {
+                                       angle2 = 0.f;
+                                       ang4 = 0.f;
+                               }
+                               else
+                               {
+                                       calculatedEdge.normalize();
+                                       btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA);
+                                       calculatedNormalA.normalize();
+                                       angle2 = btGetAngle(calculatedNormalA, edgeCrossA, edgeCrossB);
+                                       ang4 = SIMD_PI - angle2;
+                                       btScalar dotA = normalA.dot(edgeCrossB);
+                                       ///@todo: check if we need some epsilon, due to floating point imprecision
+                                       isConvex = (dotA < 0.);
+
+                                       correctedAngle = isConvex ? ang4 : -ang4;
+                               }
+
+                               //alternatively use
+                               //btVector3 calculatedNormalB2 = quatRotate(orn,normalA);
+
+                               switch (sumvertsA)
+                               {
+                                       case 1:
+                                       {
+                                               btVector3 edge = m_triangleVerticesA[0] - m_triangleVerticesA[1];
+                                               btQuaternion orn(edge, -correctedAngle);
+                                               btVector3 computedNormalB = quatRotate(orn, normalA);
+                                               btScalar bla = computedNormalB.dot(normalB);
+                                               if (bla < 0)
+                                               {
+                                                       computedNormalB *= -1;
+                                                       info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB;
+                                               }
+#ifdef DEBUG_INTERNAL_EDGE
+                                               if ((computedNormalB - normalB).length() > 0.0001)
+                                               {
+                                                       printf("warning: normals not identical\n");
+                                               }
+#endif  //DEBUG_INTERNAL_EDGE
+
+                                               info->m_edgeV0V1Angle = -correctedAngle;
+
+                                               if (isConvex)
+                                                       info->m_flags |= TRI_INFO_V0V1_CONVEX;
+                                               break;
+                                       }
+                                       case 2:
+                                       {
+                                               btVector3 edge = m_triangleVerticesA[2] - m_triangleVerticesA[0];
+                                               btQuaternion orn(edge, -correctedAngle);
+                                               btVector3 computedNormalB = quatRotate(orn, normalA);
+                                               if (computedNormalB.dot(normalB) < 0)
+                                               {
+                                                       computedNormalB *= -1;
+                                                       info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB;
+                                               }
+
+#ifdef DEBUG_INTERNAL_EDGE
+                                               if ((computedNormalB - normalB).length() > 0.0001)
+                                               {
+                                                       printf("warning: normals not identical\n");
+                                               }
+#endif  //DEBUG_INTERNAL_EDGE
+                                               info->m_edgeV2V0Angle = -correctedAngle;
+                                               if (isConvex)
+                                                       info->m_flags |= TRI_INFO_V2V0_CONVEX;
+                                               break;
+                                       }
+                                       case 3:
+                                       {
+                                               btVector3 edge = m_triangleVerticesA[1] - m_triangleVerticesA[2];
+                                               btQuaternion orn(edge, -correctedAngle);
+                                               btVector3 computedNormalB = quatRotate(orn, normalA);
+                                               if (computedNormalB.dot(normalB) < 0)
+                                               {
+                                                       info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB;
+                                                       computedNormalB *= -1;
+                                               }
+#ifdef DEBUG_INTERNAL_EDGE
+                                               if ((computedNormalB - normalB).length() > 0.0001)
+                                               {
+                                                       printf("warning: normals not identical\n");
+                                               }
+#endif  //DEBUG_INTERNAL_EDGE
+                                               info->m_edgeV1V2Angle = -correctedAngle;
+
+                                               if (isConvex)
+                                                       info->m_flags |= TRI_INFO_V1V2_CONVEX;
+                                               break;
+                                       }
+                               }
+
+                               break;
+                       }
+                       default:
+                       {
+                               //                              printf("warning: duplicate triangle\n");
+                       }
+               }
+       }
+};
+
+
+struct b3ProcessAllTrianglesHeightfield: public btTriangleCallback
+{
+       btHeightfieldTerrainShape* m_heightfieldShape;
+       btTriangleInfoMap* m_triangleInfoMap;
+       
+
+       b3ProcessAllTrianglesHeightfield(btHeightfieldTerrainShape* heightFieldShape, btTriangleInfoMap* triangleInfoMap)
+               :m_heightfieldShape(heightFieldShape),
+               m_triangleInfoMap(triangleInfoMap)
+       {
+       }
+       virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+       {
+               btConnectivityProcessor connectivityProcessor;
+               connectivityProcessor.m_partIdA = partId;
+               connectivityProcessor.m_triangleIndexA = triangleIndex;
+               connectivityProcessor.m_triangleVerticesA = triangle;
+               connectivityProcessor.m_triangleInfoMap = m_triangleInfoMap;
+               btVector3 aabbMin, aabbMax;
+               aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+               aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+               aabbMin.setMin(triangle[0]);
+               aabbMax.setMax(triangle[0]);
+               aabbMin.setMin(triangle[1]);
+               aabbMax.setMax(triangle[1]);
+               aabbMin.setMin(triangle[2]);
+               aabbMax.setMax(triangle[2]);
+
+               m_heightfieldShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
+       }
+};
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+
+void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap)
+{
+       //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
+       if (trimeshShape->getTriangleInfoMap())
+               return;
+
+       trimeshShape->setTriangleInfoMap(triangleInfoMap);
+
+       btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface();
+       const btVector3& meshScaling = meshInterface->getScaling();
+
+       for (int partId = 0; partId < meshInterface->getNumSubParts(); partId++)
+       {
+               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;
+               //PHY_ScalarType indexType=0;
+
+               btVector3 triangleVerts[3];
+               meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, partId);
+               btVector3 aabbMin, aabbMax;
+
+               for (int triangleIndex = 0; triangleIndex < numfaces; triangleIndex++)
+               {
+                       unsigned int* gfxbase = (unsigned int*)(indexbase + triangleIndex * indexstride);
+
+                       for (int j = 2; j >= 0; j--)
+                       {
+                               int graphicsindex;
+                                switch (indicestype) {
+                                        case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
+                                        case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
+                                        case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
+                                        default: btAssert(0);
+                                }
+                               if (type == PHY_FLOAT)
+                               {
+                                       float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
+                                       triangleVerts[j] = btVector3(
+                                               graphicsbase[0] * meshScaling.getX(),
+                                               graphicsbase[1] * meshScaling.getY(),
+                                               graphicsbase[2] * meshScaling.getZ());
+                               }
+                               else
+                               {
+                                       double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+                                       triangleVerts[j] = btVector3(btScalar(graphicsbase[0] * meshScaling.getX()), btScalar(graphicsbase[1] * meshScaling.getY()), btScalar(graphicsbase[2] * meshScaling.getZ()));
+                               }
+                       }
+                       aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+                       aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+                       aabbMin.setMin(triangleVerts[0]);
+                       aabbMax.setMax(triangleVerts[0]);
+                       aabbMin.setMin(triangleVerts[1]);
+                       aabbMax.setMax(triangleVerts[1]);
+                       aabbMin.setMin(triangleVerts[2]);
+                       aabbMax.setMax(triangleVerts[2]);
+
+                       btConnectivityProcessor connectivityProcessor;
+                       connectivityProcessor.m_partIdA = partId;
+                       connectivityProcessor.m_triangleIndexA = triangleIndex;
+                       connectivityProcessor.m_triangleVerticesA = &triangleVerts[0];
+                       connectivityProcessor.m_triangleInfoMap = triangleInfoMap;
+
+                       trimeshShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
+               }
+       }
+}
+
+
+void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* heightfieldShape, btTriangleInfoMap* triangleInfoMap)
+{
+
+       //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
+       if (heightfieldShape->getTriangleInfoMap())
+               return;
+
+       heightfieldShape->setTriangleInfoMap(triangleInfoMap);
+
+       //get all the triangles of the heightfield
+
+       btVector3 aabbMin, aabbMax;
+
+       aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+       aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+
+       b3ProcessAllTrianglesHeightfield processHeightfield(heightfieldShape, triangleInfoMap);
+       heightfieldShape->processAllTriangles(&processHeightfield, aabbMin, aabbMax);
+
+}
+
+// Given a point and a line segment (defined by two points), compute the closest point
+// in the line.  Cap the point at the endpoints of the line segment.
+void btNearestPointInLineSegment(const btVector3& point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
+{
+       btVector3 lineDelta = line1 - line0;
+
+       // Handle degenerate lines
+       if (lineDelta.fuzzyZero())
+       {
+               nearestPoint = line0;
+       }
+       else
+       {
+               btScalar delta = (point - line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
+
+               // Clamp the point to conform to the segment's endpoints
+               if (delta < 0)
+                       delta = 0;
+               else if (delta > 1)
+                       delta = 1;
+
+               nearestPoint = line0 + lineDelta * delta;
+       }
+}
+
+bool btClampNormal(const btVector3& edge, const btVector3& tri_normal_org, const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3& clampedLocalNormal)
+{
+       btVector3 tri_normal = tri_normal_org;
+       //we only have a local triangle normal, not a local contact normal -> only normal in world space...
+       //either compute the current angle all in local space, or all in world space
+
+       btVector3 edgeCross = edge.cross(tri_normal).normalize();
+       btScalar curAngle = btGetAngle(edgeCross, tri_normal, localContactNormalOnB);
+
+       if (correctedEdgeAngle < 0)
+       {
+               if (curAngle < correctedEdgeAngle)
+               {
+                       btScalar diffAngle = correctedEdgeAngle - curAngle;
+                       btQuaternion rotation(edge, diffAngle);
+                       clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
+                       return true;
+               }
+       }
+
+       if (correctedEdgeAngle >= 0)
+       {
+               if (curAngle > correctedEdgeAngle)
+               {
+                       btScalar diffAngle = correctedEdgeAngle - curAngle;
+                       btQuaternion rotation(edge, diffAngle);
+                       clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
+                       return true;
+               }
+       }
+       return false;
+}
+
+/// Changes a btManifoldPoint collision normal to the normal from the mesh.
+void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, const btCollisionObjectWrapper* colObj1Wrap, int partId0, int index0, int normalAdjustFlags)
+{
+       //btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
+       if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
+               return;
+
+       
+       btTriangleInfoMap* triangleInfoMapPtr = 0;
+
+       if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
+       {
+               btHeightfieldTerrainShape* heightfield = (btHeightfieldTerrainShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
+               triangleInfoMapPtr = heightfield->getTriangleInfoMap();
+
+//#define USE_HEIGHTFIELD_TRIANGLES
+#ifdef USE_HEIGHTFIELD_TRIANGLES
+               btVector3 newNormal = btVector3(0, 0, 1);
+
+               const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
+               btVector3 tri_normal;
+               tri_shape->calcNormal(tri_normal);
+               newNormal = tri_normal;
+               //                                      cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+               cp.m_normalWorldOnB = newNormal;
+               // Reproject collision point along normal. (what about cp.m_distance1?)
+               cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+               cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+               return;
+#endif
+       }
+
+
+       btBvhTriangleMeshShape* trimesh = 0;
+
+       if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
+       {
+               trimesh = ((btScaledBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape())->getChildShape();
+       }
+       else
+       {
+               if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+               {
+                       trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
+               }
+       }
+       if (trimesh)
+       {
+               triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
+       }
+       
+       
+       if (!triangleInfoMapPtr)
+               return;
+
+       int hash = btGetHash(partId0, index0);
+
+       btTriangleInfo* info = triangleInfoMapPtr->find(hash);
+       if (!info)
+               return;
+
+       btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE) == 0 ? 1.f : -1.f;
+
+       const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
+       btVector3 v0, v1, v2;
+       tri_shape->getVertex(0, v0);
+       tri_shape->getVertex(1, v1);
+       tri_shape->getVertex(2, v2);
+
+       //btVector3 center = (v0+v1+v2)*btScalar(1./3.);
+
+       btVector3 red(1, 0, 0), green(0, 1, 0), blue(0, 0, 1), white(1, 1, 1), black(0, 0, 0);
+       btVector3 tri_normal;
+       tri_shape->calcNormal(tri_normal);
+
+       //btScalar dot = tri_normal.dot(cp.m_normalWorldOnB);
+       btVector3 nearest;
+       btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
+
+       btVector3 contact = cp.m_localPointB;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+       const btTransform& tr = colObj0->getWorldTransform();
+       btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, red);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+       bool isNearEdge = false;
+
+       int numConcaveEdgeHits = 0;
+       int numConvexEdgeHits = 0;
+
+       btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+       localContactNormalOnB.normalize();  //is this necessary?
+
+       // Get closest edge
+       int bestedge = -1;
+       btScalar disttobestedge = BT_LARGE_FLOAT;
+       //
+       // Edge 0 -> 1
+       if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+       {
+               btVector3 nearest;
+               btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
+               btScalar len = (contact - nearest).length();
+               //
+               if (len < disttobestedge)
+               {
+                       bestedge = 0;
+                       disttobestedge = len;
+               }
+       }
+       // Edge 1 -> 2
+       if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+       {
+               btVector3 nearest;
+               btNearestPointInLineSegment(cp.m_localPointB, v1, v2, nearest);
+               btScalar len = (contact - nearest).length();
+               //
+               if (len < disttobestedge)
+               {
+                       bestedge = 1;
+                       disttobestedge = len;
+               }
+       }
+       // Edge 2 -> 0
+       if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+       {
+               btVector3 nearest;
+               btNearestPointInLineSegment(cp.m_localPointB, v2, v0, nearest);
+               btScalar len = (contact - nearest).length();
+               //
+               if (len < disttobestedge)
+               {
+                       bestedge = 2;
+                       disttobestedge = len;
+               }
+       }
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+       btVector3 upfix = tri_normal * btVector3(0.1f, 0.1f, 0.1f);
+       btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red);
+#endif
+       if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+       {
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+               btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
+#endif
+               btScalar len = (contact - nearest).length();
+               if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
+                       if (bestedge == 0)
+                       {
+                               btVector3 edge(v0 - v1);
+                               isNearEdge = true;
+
+                               if (info->m_edgeV0V1Angle == btScalar(0))
+                               {
+                                       numConcaveEdgeHits++;
+                               }
+                               else
+                               {
+                                       bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX);
+                                       btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+                                       btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+                                       btVector3 nA = swapFactor * tri_normal;
+
+                                       btQuaternion orn(edge, info->m_edgeV0V1Angle);
+                                       btVector3 computedNormalB = quatRotate(orn, tri_normal);
+                                       if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
+                                               computedNormalB *= -1;
+                                       btVector3 nB = swapFactor * computedNormalB;
+
+                                       btScalar NdotA = localContactNormalOnB.dot(nA);
+                                       btScalar NdotB = localContactNormalOnB.dot(nB);
+                                       bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
+
+#ifdef DEBUG_INTERNAL_EDGE
+                                       {
+                                               btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
+                                       }
+#endif  //DEBUG_INTERNAL_EDGE
+
+                                       if (backFacingNormal)
+                                       {
+                                               numConcaveEdgeHits++;
+                                       }
+                                       else
+                                       {
+                                               numConvexEdgeHits++;
+                                               btVector3 clampedLocalNormal;
+                                               bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV0V1Angle, clampedLocalNormal);
+                                               if (isClamped)
+                                               {
+                                                       if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
+                                                       {
+                                                               btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
+                                                               //                                      cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+                                                               cp.m_normalWorldOnB = newNormal;
+                                                               // Reproject collision point along normal. (what about cp.m_distance1?)
+                                                               cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+                                                               cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+       }
+
+       btNearestPointInLineSegment(contact, v1, v2, nearest);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+       btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, green);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+       btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix, green);
+#endif
+
+       if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+       {
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+               btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+               btScalar len = (contact - nearest).length();
+               if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
+                       if (bestedge == 1)
+                       {
+                               isNearEdge = true;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+                               btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+                               btVector3 edge(v1 - v2);
+
+                               isNearEdge = true;
+
+                               if (info->m_edgeV1V2Angle == btScalar(0))
+                               {
+                                       numConcaveEdgeHits++;
+                               }
+                               else
+                               {
+                                       bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX) != 0;
+                                       btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+                                       btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+                                       btVector3 nA = swapFactor * tri_normal;
+
+                                       btQuaternion orn(edge, info->m_edgeV1V2Angle);
+                                       btVector3 computedNormalB = quatRotate(orn, tri_normal);
+                                       if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
+                                               computedNormalB *= -1;
+                                       btVector3 nB = swapFactor * computedNormalB;
+
+#ifdef DEBUG_INTERNAL_EDGE
+                                       {
+                                               btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
+                                       }
+#endif  //DEBUG_INTERNAL_EDGE
+
+                                       btScalar NdotA = localContactNormalOnB.dot(nA);
+                                       btScalar NdotB = localContactNormalOnB.dot(nB);
+                                       bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
+
+                                       if (backFacingNormal)
+                                       {
+                                               numConcaveEdgeHits++;
+                                       }
+                                       else
+                                       {
+                                               numConvexEdgeHits++;
+                                               btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+                                               btVector3 clampedLocalNormal;
+                                               bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV1V2Angle, clampedLocalNormal);
+                                               if (isClamped)
+                                               {
+                                                       if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
+                                                       {
+                                                               btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
+                                                               //                                      cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+                                                               cp.m_normalWorldOnB = newNormal;
+                                                               // Reproject collision point along normal.
+                                                               cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+                                                               cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+       }
+
+       btNearestPointInLineSegment(contact, v2, v0, nearest);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+       btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, blue);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+       btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix, blue);
+#endif
+
+       if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+       {
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+               btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+               btScalar len = (contact - nearest).length();
+               if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
+                       if (bestedge == 2)
+                       {
+                               isNearEdge = true;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+                               btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+                               btVector3 edge(v2 - v0);
+
+                               if (info->m_edgeV2V0Angle == btScalar(0))
+                               {
+                                       numConcaveEdgeHits++;
+                               }
+                               else
+                               {
+                                       bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX) != 0;
+                                       btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+                                       btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+                                       btVector3 nA = swapFactor * tri_normal;
+                                       btQuaternion orn(edge, info->m_edgeV2V0Angle);
+                                       btVector3 computedNormalB = quatRotate(orn, tri_normal);
+                                       if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB)
+                                               computedNormalB *= -1;
+                                       btVector3 nB = swapFactor * computedNormalB;
+
+#ifdef DEBUG_INTERNAL_EDGE
+                                       {
+                                               btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
+                                       }
+#endif  //DEBUG_INTERNAL_EDGE
+
+                                       btScalar NdotA = localContactNormalOnB.dot(nA);
+                                       btScalar NdotB = localContactNormalOnB.dot(nB);
+                                       bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
+
+                                       if (backFacingNormal)
+                                       {
+                                               numConcaveEdgeHits++;
+                                       }
+                                       else
+                                       {
+                                               numConvexEdgeHits++;
+                                               //                              printf("hitting convex edge\n");
+
+                                               btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+                                               btVector3 clampedLocalNormal;
+                                               bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV2V0Angle, clampedLocalNormal);
+                                               if (isClamped)
+                                               {
+                                                       if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
+                                                       {
+                                                               btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
+                                                               //                                      cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+                                                               cp.m_normalWorldOnB = newNormal;
+                                                               // Reproject collision point along normal.
+                                                               cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+                                                               cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+       }
+
+#ifdef DEBUG_INTERNAL_EDGE
+       {
+               btVector3 color(0, 1, 1);
+               btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + cp.m_normalWorldOnB * 10, color);
+       }
+#endif  //DEBUG_INTERNAL_EDGE
+
+       if (isNearEdge)
+       {
+               if (numConcaveEdgeHits > 0)
+               {
+                       if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED) != 0)
+                       {
+                               //fix tri_normal so it pointing the same direction as the current local contact normal
+                               if (tri_normal.dot(localContactNormalOnB) < 0)
+                               {
+                                       tri_normal *= -1;
+                               }
+                               cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * tri_normal;
+                       }
+                       else
+                       {
+                               btVector3 newNormal = tri_normal * frontFacing;
+                               //if the tri_normal is pointing opposite direction as the current local contact normal, skip it
+                               btScalar d = newNormal.dot(localContactNormalOnB);
+                               if (d < 0)
+                               {
+                                       return;
+                               }
+                               //modify the normal to be the triangle normal (or backfacing normal)
+                               cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * newNormal;
+                       }
+
+                       // Reproject collision point along normal.
+                       cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+                       cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
new file mode 100644 (file)
index 0000000..cc6d11c
--- /dev/null
@@ -0,0 +1,44 @@
+
+#ifndef BT_INTERNAL_EDGE_UTILITY_H
+#define BT_INTERNAL_EDGE_UTILITY_H
+
+#include "LinearMath/btHashMap.h"
+#include "LinearMath/btVector3.h"
+
+#include "BulletCollision/CollisionShapes/btTriangleInfoMap.h"
+
+///The btInternalEdgeUtility helps to avoid or reduce artifacts due to wrong collision normals caused by internal edges.
+///See also http://code.google.com/p/bullet/issues/detail?id=27
+
+class btBvhTriangleMeshShape;
+class btCollisionObject;
+struct btCollisionObjectWrapper;
+class btManifoldPoint;
+class btIDebugDraw;
+class btHeightfieldTerrainShape;
+
+enum btInternalEdgeAdjustFlags
+{
+       BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1,
+       BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2,  //double sided options are experimental, single sided is recommended
+       BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4
+};
+
+///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
+void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
+
+void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
+
+///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
+///If this info map is missing, or the triangle is not store in this map, nothing will be done
+void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap, const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
+
+///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly.
+///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap
+//#define BT_INTERNAL_EDGE_DEBUG_DRAW
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+void btSetDebugDrawer(btIDebugDraw* debugDrawer);
+#endif  //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+#endif  //BT_INTERNAL_EDGE_UTILITY_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp
new file mode 100644 (file)
index 0000000..64a0f84
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btManifoldResult.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+///This is to allow MaterialCombiner/Custom Friction/Restitution values
+ContactAddedCallback gContactAddedCallback = 0;
+
+CalculateCombinedCallback gCalculateCombinedRestitutionCallback = &btManifoldResult::calculateCombinedRestitution;
+CalculateCombinedCallback gCalculateCombinedFrictionCallback = &btManifoldResult::calculateCombinedFriction;
+CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback = &btManifoldResult::calculateCombinedRollingFriction;
+CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback = &btManifoldResult::calculateCombinedSpinningFriction;
+CalculateCombinedCallback gCalculateCombinedContactDampingCallback = &btManifoldResult::calculateCombinedContactDamping;
+CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback = &btManifoldResult::calculateCombinedContactStiffness;
+
+btScalar btManifoldResult::calculateCombinedRollingFriction(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       btScalar friction = body0->getRollingFriction() * body1->getFriction() + body1->getRollingFriction() * body0->getFriction();
+
+       const btScalar MAX_FRICTION = btScalar(10.);
+       if (friction < -MAX_FRICTION)
+               friction = -MAX_FRICTION;
+       if (friction > MAX_FRICTION)
+               friction = MAX_FRICTION;
+       return friction;
+}
+
+btScalar btManifoldResult::calculateCombinedSpinningFriction(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       btScalar friction = body0->getSpinningFriction() * body1->getFriction() + body1->getSpinningFriction() * body0->getFriction();
+
+       const btScalar MAX_FRICTION = btScalar(10.);
+       if (friction < -MAX_FRICTION)
+               friction = -MAX_FRICTION;
+       if (friction > MAX_FRICTION)
+               friction = MAX_FRICTION;
+       return friction;
+}
+
+///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
+btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       btScalar friction = body0->getFriction() * body1->getFriction();
+
+       const btScalar MAX_FRICTION = btScalar(10.);
+       if (friction < -MAX_FRICTION)
+               friction = -MAX_FRICTION;
+       if (friction > MAX_FRICTION)
+               friction = MAX_FRICTION;
+       return friction;
+}
+
+btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       return body0->getRestitution() * body1->getRestitution();
+}
+
+btScalar btManifoldResult::calculateCombinedContactDamping(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       return body0->getContactDamping() + body1->getContactDamping();
+}
+
+btScalar btManifoldResult::calculateCombinedContactStiffness(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       btScalar s0 = body0->getContactStiffness();
+       btScalar s1 = body1->getContactStiffness();
+
+       btScalar tmp0 = btScalar(1) / s0;
+       btScalar tmp1 = btScalar(1) / s1;
+       btScalar combinedStiffness = btScalar(1) / (tmp0 + tmp1);
+       return combinedStiffness;
+}
+
+btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+       : m_manifoldPtr(0),
+         m_body0Wrap(body0Wrap),
+         m_body1Wrap(body1Wrap)
+         ,
+         m_partId0(-1),
+         m_partId1(-1),
+         m_index0(-1),
+         m_index1(-1)
+         ,
+         m_closestPointDistanceThreshold(0)
+{
+}
+
+void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
+{
+       btAssert(m_manifoldPtr);
+       //order in manifold needs to match
+
+       if (depth > m_manifoldPtr->getContactBreakingThreshold())
+               //      if (depth > m_manifoldPtr->getContactProcessingThreshold())
+               return;
+
+       bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
+       bool isNewCollision = m_manifoldPtr->getNumContacts() == 0;
+
+       btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
+
+       btVector3 localA;
+       btVector3 localB;
+
+       if (isSwapped)
+       {
+               localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
+               localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
+       }
+       else
+       {
+               localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
+               localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
+       }
+
+       btManifoldPoint newPt(localA, localB, normalOnBInWorld, depth);
+       newPt.m_positionWorldOnA = pointA;
+       newPt.m_positionWorldOnB = pointInWorld;
+
+       int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
+
+       newPt.m_combinedFriction = gCalculateCombinedFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+       newPt.m_combinedRestitution = gCalculateCombinedRestitutionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+       newPt.m_combinedRollingFriction = gCalculateCombinedRollingFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+       newPt.m_combinedSpinningFriction = gCalculateCombinedSpinningFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+
+       if ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING) ||
+               (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING))
+       {
+               newPt.m_combinedContactDamping1 = gCalculateCombinedContactDampingCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+               newPt.m_combinedContactStiffness1 = gCalculateCombinedContactStiffnessCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
+               newPt.m_contactPointFlags |= BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING;
+       }
+
+       if ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_FRICTION_ANCHOR) ||
+               (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_FRICTION_ANCHOR))
+       {
+               newPt.m_contactPointFlags |= BT_CONTACT_FLAG_FRICTION_ANCHOR;
+       }
+
+       btPlaneSpace1(newPt.m_normalWorldOnB, newPt.m_lateralFrictionDir1, newPt.m_lateralFrictionDir2);
+
+       //BP mod, store contact triangles.
+       if (isSwapped)
+       {
+               newPt.m_partId0 = m_partId1;
+               newPt.m_partId1 = m_partId0;
+               newPt.m_index0 = m_index1;
+               newPt.m_index1 = m_index0;
+       }
+       else
+       {
+               newPt.m_partId0 = m_partId0;
+               newPt.m_partId1 = m_partId1;
+               newPt.m_index0 = m_index0;
+               newPt.m_index1 = m_index1;
+       }
+       //printf("depth=%f\n",depth);
+       ///@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
+               ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
+                (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
+       {
+               //experimental feature info, for per-triangle material etc.
+               const btCollisionObjectWrapper* obj0Wrap = isSwapped ? m_body1Wrap : m_body0Wrap;
+               const btCollisionObjectWrapper* obj1Wrap = isSwapped ? m_body0Wrap : m_body1Wrap;
+               (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex), obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
+       }
+
+       if (gContactStartedCallback && isNewCollision)
+       {
+               gContactStartedCallback(m_manifoldPtr);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btManifoldResult.h
new file mode 100644 (file)
index 0000000..1a8f46f
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MANIFOLD_RESULT_H
+#define BT_MANIFOLD_RESULT_H
+
+class btCollisionObject;
+struct btCollisionObjectWrapper;
+
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btManifoldPoint;
+
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+#include "LinearMath/btTransform.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1);
+extern ContactAddedCallback gContactAddedCallback;
+
+//#define DEBUG_PART_INDEX 1
+
+/// These callbacks are used to customize the algorith that combine restitution, friction, damping, Stiffness
+typedef btScalar (*CalculateCombinedCallback)(const btCollisionObject* body0, const btCollisionObject* body1);
+
+extern CalculateCombinedCallback gCalculateCombinedRestitutionCallback;
+extern CalculateCombinedCallback gCalculateCombinedFrictionCallback;
+extern CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback;
+extern CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback;
+extern CalculateCombinedCallback gCalculateCombinedContactDampingCallback;
+extern CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback;
+
+///btManifoldResult is a helper class to manage  contact results.
+class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result
+{
+protected:
+       btPersistentManifold* m_manifoldPtr;
+
+       const btCollisionObjectWrapper* m_body0Wrap;
+       const btCollisionObjectWrapper* m_body1Wrap;
+       int m_partId0;
+       int m_partId1;
+       int m_index0;
+       int m_index1;
+
+public:
+       btManifoldResult()
+               :
+#ifdef DEBUG_PART_INDEX
+
+                 m_partId0(-1),
+                 m_partId1(-1),
+                 m_index0(-1),
+                 m_index1(-1)
+#endif  //DEBUG_PART_INDEX
+                         m_closestPointDistanceThreshold(0)
+       {
+       }
+
+       btManifoldResult(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
+
+       virtual ~btManifoldResult(){};
+
+       void setPersistentManifold(btPersistentManifold* manifoldPtr)
+       {
+               m_manifoldPtr = manifoldPtr;
+       }
+
+       const btPersistentManifold* getPersistentManifold() const
+       {
+               return m_manifoldPtr;
+       }
+       btPersistentManifold* getPersistentManifold()
+       {
+               return m_manifoldPtr;
+       }
+
+       virtual void setShapeIdentifiersA(int partId0, int index0)
+       {
+               m_partId0 = partId0;
+               m_index0 = index0;
+       }
+
+       virtual void setShapeIdentifiersB(int partId1, int index1)
+       {
+               m_partId1 = partId1;
+               m_index1 = index1;
+       }
+
+       virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth);
+
+       SIMD_FORCE_INLINE void refreshContactPoints()
+       {
+               btAssert(m_manifoldPtr);
+               if (!m_manifoldPtr->getNumContacts())
+                       return;
+
+               bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
+
+               if (isSwapped)
+               {
+                       m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(), m_body0Wrap->getCollisionObject()->getWorldTransform());
+               }
+               else
+               {
+                       m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(), m_body1Wrap->getCollisionObject()->getWorldTransform());
+               }
+       }
+
+       const btCollisionObjectWrapper* getBody0Wrap() const
+       {
+               return m_body0Wrap;
+       }
+       const btCollisionObjectWrapper* getBody1Wrap() const
+       {
+               return m_body1Wrap;
+       }
+
+       void setBody0Wrap(const btCollisionObjectWrapper* obj0Wrap)
+       {
+               m_body0Wrap = obj0Wrap;
+       }
+
+       void setBody1Wrap(const btCollisionObjectWrapper* obj1Wrap)
+       {
+               m_body1Wrap = obj1Wrap;
+       }
+
+       const btCollisionObject* getBody0Internal() const
+       {
+               return m_body0Wrap->getCollisionObject();
+       }
+
+       const btCollisionObject* getBody1Internal() const
+       {
+               return m_body1Wrap->getCollisionObject();
+       }
+
+       btScalar m_closestPointDistanceThreshold;
+
+       /// in the future we can let the user override the methods to combine restitution and friction
+       static btScalar calculateCombinedRestitution(const btCollisionObject* body0, const btCollisionObject* body1);
+       static btScalar calculateCombinedFriction(const btCollisionObject* body0, const btCollisionObject* body1);
+       static btScalar calculateCombinedRollingFriction(const btCollisionObject* body0, const btCollisionObject* body1);
+       static btScalar calculateCombinedSpinningFriction(const btCollisionObject* body0, const btCollisionObject* body1);
+       static btScalar calculateCombinedContactDamping(const btCollisionObject* body0, const btCollisionObject* body1);
+       static btScalar calculateCombinedContactStiffness(const btCollisionObject* body0, const btCollisionObject* body1);
+};
+
+#endif  //BT_MANIFOLD_RESULT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
new file mode 100644 (file)
index 0000000..6a99e73
--- /dev/null
@@ -0,0 +1,445 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "LinearMath/btScalar.h"
+#include "btSimulationIslandManager.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+
+//#include <stdio.h>
+#include "LinearMath/btQuickprof.h"
+
+btSimulationIslandManager::btSimulationIslandManager() : m_splitIslands(true)
+{
+}
+
+btSimulationIslandManager::~btSimulationIslandManager()
+{
+}
+
+void btSimulationIslandManager::initUnionFind(int n)
+{
+       m_unionFind.reset(n);
+}
+
+void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */, btCollisionWorld* colWorld)
+{
+       {
+               btOverlappingPairCache* pairCachePtr = colWorld->getPairCache();
+               const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs();
+               if (numOverlappingPairs)
+               {
+                       btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
+
+                       for (int i = 0; i < numOverlappingPairs; i++)
+                       {
+                               const btBroadphasePair& collisionPair = pairPtr[i];
+                               btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+                               btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+
+                               if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
+                                       ((colObj1) && ((colObj1)->mergesSimulationIslands())))
+                               {
+                                       m_unionFind.unite((colObj0)->getIslandTag(),
+                                                                         (colObj1)->getIslandTag());
+                               }
+                       }
+               }
+       }
+}
+
+#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION
+void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher)
+{
+       // put the index into m_controllers into m_tag
+       int index = 0;
+       {
+               int i;
+               for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
+               {
+                       btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
+                       //Adding filtering here
+                       if (!collisionObject->isStaticOrKinematicObject())
+                       {
+                               collisionObject->setIslandTag(index++);
+                       }
+                       collisionObject->setCompanionId(-1);
+                       collisionObject->setHitFraction(btScalar(1.));
+               }
+       }
+       // do the union find
+
+       initUnionFind(index);
+
+       findUnions(dispatcher, colWorld);
+}
+
+void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
+{
+       // put the islandId ('find' value) into m_tag
+       {
+               int index = 0;
+               int i;
+               for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
+               {
+                       btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
+                       if (!collisionObject->isStaticOrKinematicObject())
+                       {
+                               collisionObject->setIslandTag(m_unionFind.find(index));
+                               //Set the correct object offset in Collision Object Array
+                               m_unionFind.getElement(index).m_sz = i;
+                               collisionObject->setCompanionId(-1);
+                               index++;
+                       }
+                       else
+                       {
+                               collisionObject->setIslandTag(-1);
+                               collisionObject->setCompanionId(-2);
+                       }
+               }
+       }
+}
+
+#else  //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher)
+{
+       initUnionFind(int(colWorld->getCollisionObjectArray().size()));
+
+       // put the index into m_controllers into m_tag
+       {
+               int index = 0;
+               int i;
+               for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
+               {
+                       btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
+                       collisionObject->setIslandTag(index);
+                       collisionObject->setCompanionId(-1);
+                       collisionObject->setHitFraction(btScalar(1.));
+                       index++;
+               }
+       }
+       // do the union find
+
+       findUnions(dispatcher, colWorld);
+}
+
+void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
+{
+       // put the islandId ('find' value) into m_tag
+       {
+               int index = 0;
+               int i;
+               for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
+               {
+                       btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
+                       if (!collisionObject->isStaticOrKinematicObject())
+                       {
+                               collisionObject->setIslandTag(m_unionFind.find(index));
+                               collisionObject->setCompanionId(-1);
+                       }
+                       else
+                       {
+                               collisionObject->setIslandTag(-1);
+                               collisionObject->setCompanionId(-2);
+                       }
+                       index++;
+               }
+       }
+}
+
+#endif  //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+
+inline int getIslandId(const btPersistentManifold* lhs)
+{
+       int islandId;
+       const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
+       const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
+       islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
+       return islandId;
+}
+
+/// function object that routes calls to operator<
+class btPersistentManifoldSortPredicate
+{
+public:
+       SIMD_FORCE_INLINE bool operator()(const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
+       {
+               return getIslandId(lhs) < getIslandId(rhs);
+       }
+};
+
+class btPersistentManifoldSortPredicateDeterministic
+{
+public:
+       SIMD_FORCE_INLINE bool operator()(const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
+       {
+               return (
+                       (getIslandId(lhs) < getIslandId(rhs)) || ((getIslandId(lhs) == getIslandId(rhs)) && lhs->getBody0()->getBroadphaseHandle()->m_uniqueId < rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) || ((getIslandId(lhs) == getIslandId(rhs)) && (lhs->getBody0()->getBroadphaseHandle()->m_uniqueId == rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) && (lhs->getBody1()->getBroadphaseHandle()->m_uniqueId < rhs->getBody1()->getBroadphaseHandle()->m_uniqueId)));
+       }
+};
+
+void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld)
+{
+       BT_PROFILE("islandUnionFindAndQuickSort");
+
+       btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+
+       m_islandmanifold.resize(0);
+
+       //we are going to sort the unionfind array, and store the element id in the size
+       //afterwards, we clean unionfind, to make sure no-one uses it anymore
+
+       getUnionFind().sortIslands();
+       int numElem = getUnionFind().getNumElements();
+
+       int endIslandIndex = 1;
+       int startIslandIndex;
+
+       //update the sleeping state for bodies, if all are sleeping
+       for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
+       {
+               int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+               for (endIslandIndex = startIslandIndex + 1; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
+               {
+               }
+
+               //int numSleeping = 0;
+
+               bool allSleeping = true;
+
+               int idx;
+               for (idx = startIslandIndex; idx < endIslandIndex; idx++)
+               {
+                       int i = getUnionFind().getElement(idx).m_sz;
+
+                       btCollisionObject* colObj0 = collisionObjects[i];
+                       if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+                       {
+                               //                              printf("error in island management\n");
+                       }
+
+            btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+                       if (colObj0->getIslandTag() == islandId)
+                       {
+                               if (colObj0->getActivationState() == ACTIVE_TAG ||
+                                       colObj0->getActivationState() == DISABLE_DEACTIVATION)
+                               {
+                                       allSleeping = false;
+                                       break;
+                               }
+                       }
+               }
+
+               if (allSleeping)
+               {
+                       int idx;
+                       for (idx = startIslandIndex; idx < endIslandIndex; idx++)
+                       {
+                               int i = getUnionFind().getElement(idx).m_sz;
+                               btCollisionObject* colObj0 = collisionObjects[i];
+                               if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+                               {
+                                       //                                      printf("error in island management\n");
+                               }
+
+                btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+                               if (colObj0->getIslandTag() == islandId)
+                               {
+                                       colObj0->setActivationState(ISLAND_SLEEPING);
+                               }
+                       }
+               }
+               else
+               {
+                       int idx;
+                       for (idx = startIslandIndex; idx < endIslandIndex; idx++)
+                       {
+                               int i = getUnionFind().getElement(idx).m_sz;
+
+                               btCollisionObject* colObj0 = collisionObjects[i];
+                               if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+                               {
+                                       //                                      printf("error in island management\n");
+                               }
+
+                 btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+
+                               if (colObj0->getIslandTag() == islandId)
+                               {
+                                       if (colObj0->getActivationState() == ISLAND_SLEEPING)
+                                       {
+                                               colObj0->setActivationState(WANTS_DEACTIVATION);
+                                               colObj0->setDeactivationTime(0.f);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       int i;
+       int maxNumManifolds = dispatcher->getNumManifolds();
+
+       //#define SPLIT_ISLANDS 1
+       //#ifdef SPLIT_ISLANDS
+
+       //#endif //SPLIT_ISLANDS
+
+       for (i = 0; i < maxNumManifolds; i++)
+       {
+               btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
+               if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
+               {
+                       if (manifold->getNumContacts() == 0)
+                               continue;
+               }
+
+               const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
+               const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
+
+               ///@todo: check sleeping conditions!
+               if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
+                       ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
+               {
+                       //kinematic objects don't merge islands, but wake up all connected objects
+                       if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
+                       {
+                               if (colObj0->hasContactResponse())
+                                       colObj1->activate();
+                       }
+                       if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
+                       {
+                               if (colObj1->hasContactResponse())
+                                       colObj0->activate();
+                       }
+                       if (m_splitIslands)
+                       {
+                               //filtering for response
+                               if (dispatcher->needsResponse(colObj0, colObj1))
+                                       m_islandmanifold.push_back(manifold);
+                       }
+               }
+       }
+}
+
+
+///@todo: this is random access, it can be walked 'cache friendly'!
+void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
+{
+       buildIslands(dispatcher, collisionWorld);
+    processIslands(dispatcher, collisionWorld, callback);
+}
+
+void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
+{
+    btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+       int endIslandIndex = 1;
+       int startIslandIndex;
+       int numElem = getUnionFind().getNumElements();
+
+       BT_PROFILE("processIslands");
+
+       if (!m_splitIslands)
+       {
+               btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
+               int maxNumManifolds = dispatcher->getNumManifolds();
+               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());
+
+               //tried a radix sort, but quicksort/heapsort seems still faster
+               //@todo rewrite island management
+               //btPersistentManifoldSortPredicateDeterministic sorts contact manifolds based on islandid,
+               //but also based on object0 unique id and object1 unique id
+               if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
+               {
+                       m_islandmanifold.quickSort(btPersistentManifoldSortPredicateDeterministic());
+               }
+               else
+               {
+                       m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
+               }
+
+               //m_islandmanifold.heapSort(btPersistentManifoldSortPredicate());
+
+               //now process all active islands (sets of manifolds for now)
+
+               int startManifoldIndex = 0;
+               int endManifoldIndex = 1;
+
+               //int islandId;
+
+               //      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)
+               {
+                       int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+
+                       bool islandSleeping = true;
+
+                       for (endIslandIndex = startIslandIndex; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
+                       {
+                               int i = getUnionFind().getElement(endIslandIndex).m_sz;
+                               btCollisionObject* colObj0 = collisionObjects[i];
+                               m_islandBodies.push_back(colObj0);
+                               if (colObj0->isActive())
+                                       islandSleeping = false;
+                       }
+
+                       //find the accompanying contact manifold for this islandId
+                       int numIslandManifolds = 0;
+                       btPersistentManifold** startManifold = 0;
+
+                       if (startManifoldIndex < numManifolds)
+                       {
+                               int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
+                               if (curIslandId == islandId)
+                               {
+                                       startManifold = &m_islandmanifold[startManifoldIndex];
+
+                                       for (endManifoldIndex = startManifoldIndex + 1; (endManifoldIndex < numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex])); endManifoldIndex++)
+                                       {
+                                       }
+                                       /// Process the actual simulation, only if not sleeping/deactivated
+                                       numIslandManifolds = endManifoldIndex - startManifoldIndex;
+                               }
+                       }
+
+                       if (!islandSleeping)
+                       {
+                               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)
+                       {
+                               startManifoldIndex = endManifoldIndex;
+                       }
+
+                       m_islandBodies.resize(0);
+               }
+       }  // else if(!splitIslands)
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
new file mode 100644 (file)
index 0000000..bd222a1
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SIMULATION_ISLAND_MANAGER_H
+#define BT_SIMULATION_ISLAND_MANAGER_H
+
+#include "BulletCollision/CollisionDispatch/btUnionFind.h"
+#include "btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btCollisionObject.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;
+
+       bool m_splitIslands;
+
+public:
+       btSimulationIslandManager();
+       virtual ~btSimulationIslandManager();
+
+       void initUnionFind(int n);
+
+       btUnionFind& getUnionFind() { return m_unionFind; }
+
+       virtual void updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher);
+       virtual void storeIslandActivationState(btCollisionWorld* world);
+
+       void findUnions(btDispatcher* dispatcher, btCollisionWorld* colWorld);
+
+       struct IslandCallback
+       {
+               virtual ~IslandCallback(){};
+
+               virtual void processIsland(btCollisionObject** bodies, int numBodies, class btPersistentManifold** manifolds, int numManifolds, int islandId) = 0;
+       };
+
+       void buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
+    
+       void buildIslands(btDispatcher* dispatcher, btCollisionWorld* colWorld);
+
+    void processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
+    
+       bool getSplitIslands()
+       {
+               return m_splitIslands;
+       }
+       void setSplitIslands(bool doSplitIslands)
+       {
+               m_splitIslands = doSplitIslands;
+       }
+};
+
+#endif  //BT_SIMULATION_ISLAND_MANAGER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..5ab26f5
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSphereBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+//#include <stdio.h>
+
+btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, bool isSwapped)
+       : btActivatingCollisionAlgorithm(ci, col0Wrap, col1Wrap),
+         m_ownManifold(false),
+         m_manifoldPtr(mf),
+         m_isSwapped(isSwapped)
+{
+       const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped ? col1Wrap : col0Wrap;
+       const btCollisionObjectWrapper* boxObjWrap = m_isSwapped ? col0Wrap : col1Wrap;
+
+       if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(), boxObjWrap->getCollisionObject()))
+       {
+               m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(), boxObjWrap->getCollisionObject());
+               m_ownManifold = true;
+       }
+}
+
+btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
+{
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr)
+                       m_dispatcher->releaseManifold(m_manifoldPtr);
+       }
+}
+
+void btSphereBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       (void)dispatchInfo;
+       (void)resultOut;
+       if (!m_manifoldPtr)
+               return;
+
+       const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
+       const btCollisionObjectWrapper* boxObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
+
+       btVector3 pOnBox;
+
+       btVector3 normalOnSurfaceB;
+       btScalar penetrationDepth;
+       btVector3 sphereCenter = sphereObjWrap->getWorldTransform().getOrigin();
+       const btSphereShape* sphere0 = (const btSphereShape*)sphereObjWrap->getCollisionShape();
+       btScalar radius = sphere0->getRadius();
+       btScalar maxContactDistance = m_manifoldPtr->getContactBreakingThreshold();
+
+       resultOut->setPersistentManifold(m_manifoldPtr);
+
+       if (getSphereDistance(boxObjWrap, pOnBox, normalOnSurfaceB, penetrationDepth, sphereCenter, radius, maxContactDistance))
+       {
+               /// report a contact. internally this will be kept persistent, and contact reduction is done
+               resultOut->addContactPoint(normalOnSurfaceB, pOnBox, penetrationDepth);
+       }
+
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr->getNumContacts())
+               {
+                       resultOut->refreshContactPoints();
+               }
+       }
+}
+
+btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       (void)resultOut;
+       (void)dispatchInfo;
+       (void)col0;
+       (void)col1;
+
+       //not yet
+       return btScalar(1.);
+}
+
+bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance)
+{
+       const btBoxShape* boxShape = (const btBoxShape*)boxObjWrap->getCollisionShape();
+       btVector3 const& boxHalfExtent = boxShape->getHalfExtentsWithoutMargin();
+       btScalar boxMargin = boxShape->getMargin();
+       penetrationDepth = 1.0f;
+
+       // convert the sphere position to the box's local space
+       btTransform const& m44T = boxObjWrap->getWorldTransform();
+       btVector3 sphereRelPos = m44T.invXform(sphereCenter);
+
+       // Determine the closest point to the sphere center in the box
+       btVector3 closestPoint = sphereRelPos;
+       closestPoint.setX(btMin(boxHalfExtent.getX(), closestPoint.getX()));
+       closestPoint.setX(btMax(-boxHalfExtent.getX(), closestPoint.getX()));
+       closestPoint.setY(btMin(boxHalfExtent.getY(), closestPoint.getY()));
+       closestPoint.setY(btMax(-boxHalfExtent.getY(), closestPoint.getY()));
+       closestPoint.setZ(btMin(boxHalfExtent.getZ(), closestPoint.getZ()));
+       closestPoint.setZ(btMax(-boxHalfExtent.getZ(), closestPoint.getZ()));
+
+       btScalar intersectionDist = fRadius + boxMargin;
+       btScalar contactDist = intersectionDist + maxContactDistance;
+       normal = sphereRelPos - closestPoint;
+
+       //if there is no penetration, we are done
+       btScalar dist2 = normal.length2();
+       if (dist2 > contactDist * contactDist)
+       {
+               return false;
+       }
+
+       btScalar distance;
+
+       //special case if the sphere center is inside the box
+       if (dist2 <= SIMD_EPSILON)
+       {
+               distance = -getSpherePenetration(boxHalfExtent, sphereRelPos, closestPoint, normal);
+       }
+       else  //compute the penetration details
+       {
+               distance = normal.length();
+               normal /= distance;
+       }
+
+       pointOnBox = closestPoint + normal * boxMargin;
+       //      v3PointOnSphere = sphereRelPos - (normal * fRadius);
+       penetrationDepth = distance - intersectionDist;
+
+       // transform back in world space
+       btVector3 tmp = m44T(pointOnBox);
+       pointOnBox = tmp;
+       //      tmp = m44T(v3PointOnSphere);
+       //      v3PointOnSphere = tmp;
+       tmp = m44T.getBasis() * normal;
+       normal = tmp;
+
+       return true;
+}
+
+btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& boxHalfExtent, btVector3 const& sphereRelPos, btVector3& closestPoint, btVector3& normal)
+{
+       //project the center of the sphere on the closest face of the box
+       btScalar faceDist = boxHalfExtent.getX() - sphereRelPos.getX();
+       btScalar minDist = faceDist;
+       closestPoint.setX(boxHalfExtent.getX());
+       normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
+
+       faceDist = boxHalfExtent.getX() + sphereRelPos.getX();
+       if (faceDist < minDist)
+       {
+               minDist = faceDist;
+               closestPoint = sphereRelPos;
+               closestPoint.setX(-boxHalfExtent.getX());
+               normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f));
+       }
+
+       faceDist = boxHalfExtent.getY() - sphereRelPos.getY();
+       if (faceDist < minDist)
+       {
+               minDist = faceDist;
+               closestPoint = sphereRelPos;
+               closestPoint.setY(boxHalfExtent.getY());
+               normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f));
+       }
+
+       faceDist = boxHalfExtent.getY() + sphereRelPos.getY();
+       if (faceDist < minDist)
+       {
+               minDist = faceDist;
+               closestPoint = sphereRelPos;
+               closestPoint.setY(-boxHalfExtent.getY());
+               normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f));
+       }
+
+       faceDist = boxHalfExtent.getZ() - sphereRelPos.getZ();
+       if (faceDist < minDist)
+       {
+               minDist = faceDist;
+               closestPoint = sphereRelPos;
+               closestPoint.setZ(boxHalfExtent.getZ());
+               normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f));
+       }
+
+       faceDist = boxHalfExtent.getZ() + sphereRelPos.getZ();
+       if (faceDist < minDist)
+       {
+               minDist = faceDist;
+               closestPoint = sphereRelPos;
+               closestPoint.setZ(-boxHalfExtent.getZ());
+               normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f));
+       }
+
+       return minDist;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..33060e8
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SPHERE_BOX_COLLISION_ALGORITHM_H
+#define BT_SPHERE_BOX_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
+
+/// btSphereBoxCollisionAlgorithm  provides sphere-box collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+       bool m_ownManifold;
+       btPersistentManifold* m_manifoldPtr;
+       bool m_isSwapped;
+
+public:
+       btSphereBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
+
+       virtual ~btSphereBoxCollisionAlgorithm();
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, 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);
+               }
+       }
+
+       bool getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance);
+
+       btScalar getSpherePenetration(btVector3 const& boxHalfExtent, btVector3 const& sphereRelPos, btVector3& closestPoint, btVector3& normal);
+
+       struct CreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
+                       if (!m_swapped)
+                       {
+                               return new (mem) btSphereBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false);
+                       }
+                       else
+                       {
+                               return new (mem) btSphereBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true);
+                       }
+               }
+       };
+};
+
+#endif  //BT_SPHERE_BOX_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..9c35565
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#define CLEAR_MANIFOLD 1
+
+#include "btSphereSphereCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap)
+       : btActivatingCollisionAlgorithm(ci, col0Wrap, col1Wrap),
+         m_ownManifold(false),
+         m_manifoldPtr(mf)
+{
+       if (!m_manifoldPtr)
+       {
+               m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(), col1Wrap->getCollisionObject());
+               m_ownManifold = true;
+       }
+}
+
+btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
+{
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr)
+                       m_dispatcher->releaseManifold(m_manifoldPtr);
+       }
+}
+
+void btSphereSphereCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       (void)dispatchInfo;
+
+       if (!m_manifoldPtr)
+               return;
+
+       resultOut->setPersistentManifold(m_manifoldPtr);
+
+       btSphereShape* sphere0 = (btSphereShape*)col0Wrap->getCollisionShape();
+       btSphereShape* sphere1 = (btSphereShape*)col1Wrap->getCollisionShape();
+
+       btVector3 diff = col0Wrap->getWorldTransform().getOrigin() - col1Wrap->getWorldTransform().getOrigin();
+       btScalar len = diff.length();
+       btScalar radius0 = sphere0->getRadius();
+       btScalar radius1 = sphere1->getRadius();
+
+#ifdef CLEAR_MANIFOLD
+       m_manifoldPtr->clearManifold();  //don't do this, it disables warmstarting
+#endif
+
+       ///iff distance positive, don't generate a new contact
+       if (len > (radius0 + radius1 + resultOut->m_closestPointDistanceThreshold))
+       {
+#ifndef CLEAR_MANIFOLD
+               resultOut->refreshContactPoints();
+#endif  //CLEAR_MANIFOLD
+               return;
+       }
+       ///distance (negative means penetration)
+       btScalar dist = len - (radius0 + radius1);
+
+       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 = col1Wrap->getWorldTransform().getOrigin() + radius1 * normalOnSurfaceB;
+
+       /// report a contact. internally this will be kept persistent, and contact reduction is done
+
+       resultOut->addContactPoint(normalOnSurfaceB, pos1, dist);
+
+#ifndef CLEAR_MANIFOLD
+       resultOut->refreshContactPoints();
+#endif  //CLEAR_MANIFOLD
+}
+
+btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       (void)col0;
+       (void)col1;
+       (void)dispatchInfo;
+       (void)resultOut;
+
+       //not yet
+       return btScalar(1.);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..399c927
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SPHERE_SPHERE_COLLISION_ALGORITHM_H
+#define BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+
+class btPersistentManifold;
+
+/// btSphereSphereCollisionAlgorithm  provides sphere-sphere collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+/// Also provides the most basic sample for custom/user btCollisionAlgorithm
+class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+       bool m_ownManifold;
+       btPersistentManifold* m_manifoldPtr;
+
+public:
+       btSphereSphereCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap);
+
+       btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+               : btActivatingCollisionAlgorithm(ci) {}
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, 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);
+               }
+       }
+
+       virtual ~btSphereSphereCollisionAlgorithm();
+
+       struct CreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
+                       return new (mem) btSphereSphereCollisionAlgorithm(0, ci, col0Wrap, col1Wrap);
+               }
+       };
+};
+
+#endif  //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..21e0d94
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "SphereTriangleDetector.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool swapped)
+       : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
+         m_ownManifold(false),
+         m_manifoldPtr(mf),
+         m_swapped(swapped)
+{
+       if (!m_manifoldPtr)
+       {
+               m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
+               m_ownManifold = true;
+       }
+}
+
+btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
+{
+       if (m_ownManifold)
+       {
+               if (m_manifoldPtr)
+                       m_dispatcher->releaseManifold(m_manifoldPtr);
+       }
+}
+
+void btSphereTriangleCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       if (!m_manifoldPtr)
+               return;
+
+       const btCollisionObjectWrapper* sphereObjWrap = m_swapped ? col1Wrap : col0Wrap;
+       const btCollisionObjectWrapper* triObjWrap = m_swapped ? col0Wrap : col1Wrap;
+
+       btSphereShape* sphere = (btSphereShape*)sphereObjWrap->getCollisionShape();
+       btTriangleShape* triangle = (btTriangleShape*)triObjWrap->getCollisionShape();
+
+       /// report a contact. internally this will be kept persistent, and contact reduction is done
+       resultOut->setPersistentManifold(m_manifoldPtr);
+       SphereTriangleDetector detector(sphere, triangle, m_manifoldPtr->getContactBreakingThreshold() + resultOut->m_closestPointDistanceThreshold);
+
+       btDiscreteCollisionDetectorInterface::ClosestPointInput input;
+       input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);  ///@todo: tighter bounds
+       input.m_transformA = sphereObjWrap->getWorldTransform();
+       input.m_transformB = triObjWrap->getWorldTransform();
+
+       bool swapResults = m_swapped;
+
+       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)
+{
+       (void)resultOut;
+       (void)dispatchInfo;
+       (void)col0;
+       (void)col1;
+
+       //not yet
+       return btScalar(1.);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..73c6fd1
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+#define BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+/// btSphereSphereCollisionAlgorithm  provides sphere-sphere collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+/// Also provides the most basic sample for custom/user btCollisionAlgorithm
+class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+       bool m_ownManifold;
+       btPersistentManifold* m_manifoldPtr;
+       bool m_swapped;
+
+public:
+       btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool swapped);
+
+       btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+               : btActivatingCollisionAlgorithm(ci) {}
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, 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);
+               }
+       }
+
+       virtual ~btSphereTriangleCollisionAlgorithm();
+
+       struct CreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
+
+                       return new (mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_swapped);
+               }
+       };
+};
+
+#endif  //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btUnionFind.cpp
new file mode 100644 (file)
index 0000000..906c331
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btUnionFind.h"
+
+btUnionFind::~btUnionFind()
+{
+       Free();
+}
+
+btUnionFind::btUnionFind()
+{
+}
+
+void btUnionFind::allocate(int N)
+{
+       m_elements.resize(N);
+}
+void btUnionFind::Free()
+{
+       m_elements.clear();
+}
+
+void btUnionFind::reset(int N)
+{
+       allocate(N);
+
+       for (int i = 0; i < N; i++)
+       {
+               m_elements[i].m_id = i;
+               m_elements[i].m_sz = 1;
+       }
+}
+
+class btUnionFindElementSortPredicate
+{
+public:
+       bool operator()(const btElement& lhs, const btElement& rhs) const
+       {
+               return lhs.m_id < rhs.m_id;
+       }
+};
+
+///this is a special operation, destroying the content of btUnionFind.
+///it sorts the elements, based on island id, in order to make it easy to iterate over islands
+void btUnionFind::sortIslands()
+{
+       //first store the original body index, and islandId
+       int numElements = m_elements.size();
+
+       for (int i = 0; i < numElements; i++)
+       {
+               m_elements[i].m_id = find(i);
+#ifndef STATIC_SIMULATION_ISLAND_OPTIMIZATION
+               m_elements[i].m_sz = i;
+#endif  //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+       }
+
+       // Sort the vector using predicate and std::sort
+       //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
+       m_elements.quickSort(btUnionFindElementSortPredicate());
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btUnionFind.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionDispatch/btUnionFind.h
new file mode 100644 (file)
index 0000000..59a30b1
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_UNION_FIND_H
+#define BT_UNION_FIND_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+#define USE_PATH_COMPRESSION 1
+
+///see for discussion of static island optimizations by Vroonsh here: http://code.google.com/p/bullet/issues/detail?id=406
+#define STATIC_SIMULATION_ISLAND_OPTIMIZATION 1
+
+struct btElement
+{
+       int m_id;
+       int m_sz;
+};
+
+///UnionFind calculates connected subsets
+// Implements weighted Quick Union with path compression
+// optimization: could use short ints instead of ints (halving memory, would limit the number of rigid bodies to 64k, sounds reasonable)
+class btUnionFind
+{
+private:
+       btAlignedObjectArray<btElement> m_elements;
+
+public:
+       btUnionFind();
+       ~btUnionFind();
+
+       //this is a special operation, destroying the content of btUnionFind.
+       //it sorts the elements, based on island id, in order to make it easy to iterate over islands
+       void sortIslands();
+
+       void reset(int N);
+
+       SIMD_FORCE_INLINE int getNumElements() const
+       {
+               return int(m_elements.size());
+       }
+       SIMD_FORCE_INLINE bool isRoot(int x) const
+       {
+               return (x == m_elements[x].m_id);
+       }
+
+       btElement& getElement(int index)
+       {
+               return m_elements[index];
+       }
+       const btElement& getElement(int index) const
+       {
+               return m_elements[index];
+       }
+
+       void allocate(int N);
+       void Free();
+
+       int find(int p, int q)
+       {
+               return (find(p) == find(q));
+       }
+
+       void unite(int p, int q)
+       {
+               int i = find(p), j = find(q);
+               if (i == j)
+                       return;
+
+#ifndef USE_PATH_COMPRESSION
+               //weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
+               if (m_elements[i].m_sz < m_elements[j].m_sz)
+               {
+                       m_elements[i].m_id = j;
+                       m_elements[j].m_sz += m_elements[i].m_sz;
+               }
+               else
+               {
+                       m_elements[j].m_id = i;
+                       m_elements[i].m_sz += m_elements[j].m_sz;
+               }
+#else
+               m_elements[i].m_id = j;
+               m_elements[j].m_sz += m_elements[i].m_sz;
+#endif  //USE_PATH_COMPRESSION
+       }
+
+       int find(int x)
+       {
+               //btAssert(x < m_N);
+               //btAssert(x >= 0);
+
+               while (x != m_elements[x].m_id)
+               {
+                       //not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
+
+#ifdef USE_PATH_COMPRESSION
+                       const btElement* elementPtr = &m_elements[m_elements[x].m_id];
+                       m_elements[x].m_id = elementPtr->m_id;
+                       x = elementPtr->m_id;
+#else  //
+                       x = m_elements[x].m_id;
+#endif
+                       //btAssert(x < m_N);
+                       //btAssert(x >= 0);
+               }
+               return x;
+       }
+};
+
+#endif  //BT_UNION_FIND_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBox2dShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBox2dShape.cpp
new file mode 100644 (file)
index 0000000..501890c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btBox2dShape.h"
+
+//{
+
+void btBox2dShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
+}
+
+void btBox2dShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       //btScalar margin = btScalar(0.);
+       btVector3 halfExtents = getHalfExtentsWithMargin();
+
+       btScalar lx = btScalar(2.) * (halfExtents.x());
+       btScalar ly = btScalar(2.) * (halfExtents.y());
+       btScalar lz = btScalar(2.) * (halfExtents.z());
+
+       inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
+                                        mass / (btScalar(12.0)) * (lx * lx + lz * lz),
+                                        mass / (btScalar(12.0)) * (lx * lx + ly * ly));
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBox2dShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBox2dShape.h
new file mode 100644 (file)
index 0000000..6c6e729
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_OBB_BOX_2D_SHAPE_H
+#define BT_OBB_BOX_2D_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMinMax.h"
+
+///The btBox2dShape 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.
+ATTRIBUTE_ALIGNED16(class)
+btBox2dShape : public btPolyhedralConvexShape
+{
+       //btVector3     m_boxHalfExtents1; //use m_implicitShapeDimensions instead
+
+       btVector3 m_centroid;
+       btVector3 m_vertices[4];
+       btVector3 m_normals[4];
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       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 btVector3 localGetSupportingVertex(const btVector3& vec) const
+       {
+               btVector3 halfExtents = getHalfExtentsWithoutMargin();
+               btVector3 margin(getMargin(), getMargin(), getMargin());
+               halfExtents += margin;
+
+               return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+                                                btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+                                                btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+       }
+
+       SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+       {
+               const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+
+               return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+                                                btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+                                                btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+       }
+
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+       {
+               const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+
+               for (int i = 0; i < numVectors; i++)
+               {
+                       const btVector3& vec = vectors[i];
+                       supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+                                                                                  btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+                                                                                  btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+               }
+       }
+
+       ///a btBox2dShape is a flat 2D box in the X-Y plane (Z extents are zero)
+       btBox2dShape(const btVector3& boxHalfExtents)
+               : btPolyhedralConvexShape(),
+                 m_centroid(0, 0, 0)
+       {
+               m_vertices[0].setValue(-boxHalfExtents.getX(), -boxHalfExtents.getY(), 0);
+               m_vertices[1].setValue(boxHalfExtents.getX(), -boxHalfExtents.getY(), 0);
+               m_vertices[2].setValue(boxHalfExtents.getX(), boxHalfExtents.getY(), 0);
+               m_vertices[3].setValue(-boxHalfExtents.getX(), boxHalfExtents.getY(), 0);
+
+               m_normals[0].setValue(0, -1, 0);
+               m_normals[1].setValue(1, 0, 0);
+               m_normals[2].setValue(0, 1, 0);
+               m_normals[3].setValue(-1, 0, 0);
+
+               btScalar minDimension = boxHalfExtents.getX();
+               if (minDimension > boxHalfExtents.getY())
+                       minDimension = boxHalfExtents.getY();
+
+               m_shapeType = BOX_2D_SHAPE_PROXYTYPE;
+               btVector3 margin(getMargin(), getMargin(), getMargin());
+               m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
+
+               setSafeMargin(minDimension);
+       };
+
+       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) const;
+
+       int getVertexCount() const
+       {
+               return 4;
+       }
+
+       virtual int getNumVertices() const
+       {
+               return 4;
+       }
+
+       const btVector3* getVertices() const
+       {
+               return &m_vertices[0];
+       }
+
+       const btVector3* getNormals() const
+       {
+               return &m_normals[0];
+       }
+
+       virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
+       {
+               //this plane might not be aligned...
+               btVector4 plane;
+               getPlaneEquation(plane, i);
+               planeNormal = btVector3(plane.getX(), plane.getY(), plane.getZ());
+               planeSupport = localGetSupportingVertex(-planeNormal);
+       }
+
+       const btVector3& getCentroid() const
+       {
+               return m_centroid;
+       }
+
+       virtual int getNumPlanes() const
+       {
+               return 6;
+       }
+
+       virtual int getNumEdges() const
+       {
+               return 12;
+       }
+
+       virtual void getVertex(int i, btVector3& vtx) const
+       {
+               btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+               vtx = btVector3(
+                       halfExtents.x() * (1 - (i & 1)) - halfExtents.x() * (i & 1),
+                       halfExtents.y() * (1 - ((i & 2) >> 1)) - halfExtents.y() * ((i & 2) >> 1),
+                       halfExtents.z() * (1 - ((i & 4) >> 2)) - halfExtents.z() * ((i & 4) >> 2));
+       }
+
+       virtual void getPlaneEquation(btVector4 & plane, int i) const
+       {
+               btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+               switch (i)
+               {
+                       case 0:
+                               plane.setValue(btScalar(1.), btScalar(0.), btScalar(0.), -halfExtents.x());
+                               break;
+                       case 1:
+                               plane.setValue(btScalar(-1.), btScalar(0.), btScalar(0.), -halfExtents.x());
+                               break;
+                       case 2:
+                               plane.setValue(btScalar(0.), btScalar(1.), btScalar(0.), -halfExtents.y());
+                               break;
+                       case 3:
+                               plane.setValue(btScalar(0.), btScalar(-1.), btScalar(0.), -halfExtents.y());
+                               break;
+                       case 4:
+                               plane.setValue(btScalar(0.), btScalar(0.), btScalar(1.), -halfExtents.z());
+                               break;
+                       case 5:
+                               plane.setValue(btScalar(0.), btScalar(0.), btScalar(-1.), -halfExtents.z());
+                               break;
+                       default:
+                               btAssert(0);
+               }
+       }
+
+       virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
+       //virtual void getEdge(int i,Edge& edge) const
+       {
+               int edgeVert0 = 0;
+               int edgeVert1 = 0;
+
+               switch (i)
+               {
+                       case 0:
+                               edgeVert0 = 0;
+                               edgeVert1 = 1;
+                               break;
+                       case 1:
+                               edgeVert0 = 0;
+                               edgeVert1 = 2;
+                               break;
+                       case 2:
+                               edgeVert0 = 1;
+                               edgeVert1 = 3;
+
+                               break;
+                       case 3:
+                               edgeVert0 = 2;
+                               edgeVert1 = 3;
+                               break;
+                       case 4:
+                               edgeVert0 = 0;
+                               edgeVert1 = 4;
+                               break;
+                       case 5:
+                               edgeVert0 = 1;
+                               edgeVert1 = 5;
+
+                               break;
+                       case 6:
+                               edgeVert0 = 2;
+                               edgeVert1 = 6;
+                               break;
+                       case 7:
+                               edgeVert0 = 3;
+                               edgeVert1 = 7;
+                               break;
+                       case 8:
+                               edgeVert0 = 4;
+                               edgeVert1 = 5;
+                               break;
+                       case 9:
+                               edgeVert0 = 4;
+                               edgeVert1 = 6;
+                               break;
+                       case 10:
+                               edgeVert0 = 5;
+                               edgeVert1 = 7;
+                               break;
+                       case 11:
+                               edgeVert0 = 6;
+                               edgeVert1 = 7;
+                               break;
+                       default:
+                               btAssert(0);
+               }
+
+               getVertex(edgeVert0, pa);
+               getVertex(edgeVert1, pb);
+       }
+
+       virtual bool isInside(const btVector3& pt, btScalar tolerance) const
+       {
+               btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+               //btScalar minDist = 2*tolerance;
+
+               bool result = (pt.x() <= (halfExtents.x() + tolerance)) &&
+                                         (pt.x() >= (-halfExtents.x() - tolerance)) &&
+                                         (pt.y() <= (halfExtents.y() + tolerance)) &&
+                                         (pt.y() >= (-halfExtents.y() - tolerance)) &&
+                                         (pt.z() <= (halfExtents.z() + tolerance)) &&
+                                         (pt.z() >= (-halfExtents.z() - tolerance));
+
+               return result;
+       }
+
+       //debugging
+       virtual const char* getName() const
+       {
+               return "Box2d";
+       }
+
+       virtual int getNumPreferredPenetrationDirections() const
+       {
+               return 6;
+       }
+
+       virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+       {
+               switch (index)
+               {
+                       case 0:
+                               penetrationVector.setValue(btScalar(1.), btScalar(0.), btScalar(0.));
+                               break;
+                       case 1:
+                               penetrationVector.setValue(btScalar(-1.), btScalar(0.), btScalar(0.));
+                               break;
+                       case 2:
+                               penetrationVector.setValue(btScalar(0.), btScalar(1.), btScalar(0.));
+                               break;
+                       case 3:
+                               penetrationVector.setValue(btScalar(0.), btScalar(-1.), btScalar(0.));
+                               break;
+                       case 4:
+                               penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(1.));
+                               break;
+                       case 5:
+                               penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(-1.));
+                               break;
+                       default:
+                               btAssert(0);
+               }
+       }
+};
+
+#endif  //BT_OBB_BOX_2D_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.cpp
new file mode 100644 (file)
index 0000000..cb91d02
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "btBoxShape.h"
+
+btBoxShape::btBoxShape(const btVector3& boxHalfExtents)
+       : btPolyhedralConvexShape()
+{
+       m_shapeType = BOX_SHAPE_PROXYTYPE;
+
+       btVector3 margin(getMargin(), getMargin(), getMargin());
+       m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
+
+       setSafeMargin(boxHalfExtents);
+};
+
+void btBoxShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
+}
+
+void btBoxShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       //btScalar margin = btScalar(0.);
+       btVector3 halfExtents = getHalfExtentsWithMargin();
+
+       btScalar lx = btScalar(2.) * (halfExtents.x());
+       btScalar ly = btScalar(2.) * (halfExtents.y());
+       btScalar lz = btScalar(2.) * (halfExtents.z());
+
+       inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
+                                        mass / (btScalar(12.0)) * (lx * lx + lz * lz),
+                                        mass / (btScalar(12.0)) * (lx * lx + ly * ly));
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.h
new file mode 100644 (file)
index 0000000..3c65505
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_OBB_BOX_MINKOWSKI_H
+#define BT_OBB_BOX_MINKOWSKI_H
+
+#include "btPolyhedralConvexShape.h"
+#include "btCollisionMargin.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMinMax.h"
+
+///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.
+ATTRIBUTE_ALIGNED16(class)
+btBoxShape : public btPolyhedralConvexShape
+{
+       //btVector3     m_boxHalfExtents1; //use m_implicitShapeDimensions instead
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btVector3 getHalfExtentsWithMargin() const
+       {
+               btVector3 halfExtents = getHalfExtentsWithoutMargin();
+               btVector3 margin(getMargin(), getMargin(), getMargin());
+               halfExtents += margin;
+               return halfExtents;
+       }
+
+       const btVector3& getHalfExtentsWithoutMargin() const
+       {
+               return m_implicitShapeDimensions;  //scaling is included, margin is not
+       }
+
+       virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
+       {
+               btVector3 halfExtents = getHalfExtentsWithoutMargin();
+               btVector3 margin(getMargin(), getMargin(), getMargin());
+               halfExtents += margin;
+
+               return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+                                                btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+                                                btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+       }
+
+       SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+       {
+               const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+
+               return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+                                                btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+                                                btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+       }
+
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+       {
+               const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+
+               for (int i = 0; i < numVectors; i++)
+               {
+                       const btVector3& vec = vectors[i];
+                       supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+                                                                                  btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+                                                                                  btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+               }
+       }
+
+       btBoxShape(const btVector3& boxHalfExtents);
+
+       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) const;
+
+       virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
+       {
+               //this plane might not be aligned...
+               btVector4 plane;
+               getPlaneEquation(plane, i);
+               planeNormal = btVector3(plane.getX(), plane.getY(), plane.getZ());
+               planeSupport = localGetSupportingVertex(-planeNormal);
+       }
+
+       virtual int getNumPlanes() const
+       {
+               return 6;
+       }
+
+       virtual int getNumVertices() const
+       {
+               return 8;
+       }
+
+       virtual int getNumEdges() const
+       {
+               return 12;
+       }
+
+       virtual void getVertex(int i, btVector3& vtx) const
+       {
+               btVector3 halfExtents = getHalfExtentsWithMargin();
+
+               vtx = btVector3(
+                       halfExtents.x() * (1 - (i & 1)) - halfExtents.x() * (i & 1),
+                       halfExtents.y() * (1 - ((i & 2) >> 1)) - halfExtents.y() * ((i & 2) >> 1),
+                       halfExtents.z() * (1 - ((i & 4) >> 2)) - halfExtents.z() * ((i & 4) >> 2));
+       }
+
+       virtual void getPlaneEquation(btVector4 & plane, int i) const
+       {
+               btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+               switch (i)
+               {
+                       case 0:
+                               plane.setValue(btScalar(1.), btScalar(0.), btScalar(0.), -halfExtents.x());
+                               break;
+                       case 1:
+                               plane.setValue(btScalar(-1.), btScalar(0.), btScalar(0.), -halfExtents.x());
+                               break;
+                       case 2:
+                               plane.setValue(btScalar(0.), btScalar(1.), btScalar(0.), -halfExtents.y());
+                               break;
+                       case 3:
+                               plane.setValue(btScalar(0.), btScalar(-1.), btScalar(0.), -halfExtents.y());
+                               break;
+                       case 4:
+                               plane.setValue(btScalar(0.), btScalar(0.), btScalar(1.), -halfExtents.z());
+                               break;
+                       case 5:
+                               plane.setValue(btScalar(0.), btScalar(0.), btScalar(-1.), -halfExtents.z());
+                               break;
+                       default:
+                               btAssert(0);
+               }
+       }
+
+       virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
+       //virtual void getEdge(int i,Edge& edge) const
+       {
+               int edgeVert0 = 0;
+               int edgeVert1 = 0;
+
+               switch (i)
+               {
+                       case 0:
+                               edgeVert0 = 0;
+                               edgeVert1 = 1;
+                               break;
+                       case 1:
+                               edgeVert0 = 0;
+                               edgeVert1 = 2;
+                               break;
+                       case 2:
+                               edgeVert0 = 1;
+                               edgeVert1 = 3;
+
+                               break;
+                       case 3:
+                               edgeVert0 = 2;
+                               edgeVert1 = 3;
+                               break;
+                       case 4:
+                               edgeVert0 = 0;
+                               edgeVert1 = 4;
+                               break;
+                       case 5:
+                               edgeVert0 = 1;
+                               edgeVert1 = 5;
+
+                               break;
+                       case 6:
+                               edgeVert0 = 2;
+                               edgeVert1 = 6;
+                               break;
+                       case 7:
+                               edgeVert0 = 3;
+                               edgeVert1 = 7;
+                               break;
+                       case 8:
+                               edgeVert0 = 4;
+                               edgeVert1 = 5;
+                               break;
+                       case 9:
+                               edgeVert0 = 4;
+                               edgeVert1 = 6;
+                               break;
+                       case 10:
+                               edgeVert0 = 5;
+                               edgeVert1 = 7;
+                               break;
+                       case 11:
+                               edgeVert0 = 6;
+                               edgeVert1 = 7;
+                               break;
+                       default:
+                               btAssert(0);
+               }
+
+               getVertex(edgeVert0, pa);
+               getVertex(edgeVert1, pb);
+       }
+
+       virtual bool isInside(const btVector3& pt, btScalar tolerance) const
+       {
+               btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+               //btScalar minDist = 2*tolerance;
+
+               bool result = (pt.x() <= (halfExtents.x() + tolerance)) &&
+                                         (pt.x() >= (-halfExtents.x() - tolerance)) &&
+                                         (pt.y() <= (halfExtents.y() + tolerance)) &&
+                                         (pt.y() >= (-halfExtents.y() - tolerance)) &&
+                                         (pt.z() <= (halfExtents.z() + tolerance)) &&
+                                         (pt.z() >= (-halfExtents.z() - tolerance));
+
+               return result;
+       }
+
+       //debugging
+       virtual const char* getName() const
+       {
+               return "Box";
+       }
+
+       virtual int getNumPreferredPenetrationDirections() const
+       {
+               return 6;
+       }
+
+       virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+       {
+               switch (index)
+               {
+                       case 0:
+                               penetrationVector.setValue(btScalar(1.), btScalar(0.), btScalar(0.));
+                               break;
+                       case 1:
+                               penetrationVector.setValue(btScalar(-1.), btScalar(0.), btScalar(0.));
+                               break;
+                       case 2:
+                               penetrationVector.setValue(btScalar(0.), btScalar(1.), btScalar(0.));
+                               break;
+                       case 3:
+                               penetrationVector.setValue(btScalar(0.), btScalar(-1.), btScalar(0.));
+                               break;
+                       case 4:
+                               penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(1.));
+                               break;
+                       case 5:
+                               penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(-1.));
+                               break;
+                       default:
+                               btAssert(0);
+               }
+       }
+};
+
+#endif  //BT_OBB_BOX_MINKOWSKI_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
new file mode 100644 (file)
index 0000000..c66ce58
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//#define DISABLE_BVH
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
+#include "LinearMath/btSerializer.h"
+
+///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
+///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
+       : btTriangleMeshShape(meshInterface),
+         m_bvh(0),
+         m_triangleInfoMap(0),
+         m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+         m_ownsBvh(false)
+{
+       m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+       //construct bvh from meshInterface
+#ifndef DISABLE_BVH
+
+       if (buildBvh)
+       {
+               buildOptimizedBvh();
+       }
+
+#endif  //DISABLE_BVH
+}
+
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, bool buildBvh)
+       : btTriangleMeshShape(meshInterface),
+         m_bvh(0),
+         m_triangleInfoMap(0),
+         m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+         m_ownsBvh(false)
+{
+       m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+       //construct bvh from meshInterface
+#ifndef DISABLE_BVH
+
+       if (buildBvh)
+       {
+               void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
+               m_bvh = new (mem) btOptimizedBvh();
+
+               m_bvh->build(meshInterface, m_useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax);
+               m_ownsBvh = true;
+       }
+
+#endif  //DISABLE_BVH
+}
+
+void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin, const btVector3& aabbMax)
+{
+       m_bvh->refitPartial(m_meshInterface, aabbMin, aabbMax);
+
+       m_localAabbMin.setMin(aabbMin);
+       m_localAabbMax.setMax(aabbMax);
+}
+
+void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin, const btVector3& aabbMax)
+{
+       m_bvh->refit(m_meshInterface, aabbMin, aabbMax);
+
+       recalcLocalAabb();
+}
+
+btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
+{
+       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);
+
+                       const btVector3& meshScaling = m_meshInterface->getScaling();
+                       for (int j = 2; j >= 0; j--)
+                       {
+                               int graphicsindex;
+                                switch (indicestype) {
+                                        case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
+                                        case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
+                                        case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
+                                        default: btAssert(0);
+                                }
+
+                               if (type == PHY_FLOAT)
+                               {
+                                       float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
+
+                                       m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                               }
+                               else
+                               {
+                                       double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+
+                                       m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(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);
+
+                       const btVector3& meshScaling = m_meshInterface->getScaling();
+                       for (int j = 2; j >= 0; j--)
+                       {
+                               int graphicsindex;
+                                switch (indicestype) {
+                                        case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
+                                        case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
+                                        case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
+                                        default: btAssert(0);
+                                }
+
+                               if (type == PHY_FLOAT)
+                               {
+                                       float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
+
+                                       m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                               }
+                               else
+                               {
+                                       double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+
+                                       m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(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'
+void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+#ifdef DISABLE_BVH
+       //brute force traverse all triangles
+       btTriangleMeshShape::processAllTriangles(callback, aabbMin, aabbMax);
+#else
+
+       //first get all the nodes
+
+       struct MyNodeOverlapCallback : public btNodeOverlapCallback
+       {
+               btStridingMeshInterface* m_meshInterface;
+               btTriangleCallback* m_callback;
+               btVector3 m_triangle[3];
+               int m_numOverlap;
+
+               MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
+                       : m_meshInterface(meshInterface),
+                         m_callback(callback),
+                         m_numOverlap(0)
+               {
+               }
+
+               virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+               {
+                       m_numOverlap++;
+                       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 || indicestype == PHY_UCHAR);
+
+                       const btVector3& meshScaling = m_meshInterface->getScaling();
+                       for (int j = 2; j >= 0; j--)
+                       {
+                               int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : indicestype == PHY_INTEGER ? gfxbase[j] : ((unsigned char*)gfxbase)[j];
+
+#ifdef DEBUG_TRIANGLE_MESH
+                               printf("%d ,", graphicsindex);
+#endif  //DEBUG_TRIANGLE_MESH
+                               if (type == PHY_FLOAT)
+                               {
+                                       float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
+
+                                       m_triangle[j] = btVector3(
+                                               graphicsbase[0] * meshScaling.getX(),
+                                               graphicsbase[1] * meshScaling.getY(),
+                                               graphicsbase[2] * meshScaling.getZ());
+                               }
+                               else
+                               {
+                                       double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+
+                                       m_triangle[j] = btVector3(
+                                               btScalar(graphicsbase[0]) * meshScaling.getX(),
+                                               btScalar(graphicsbase[1]) * meshScaling.getY(),
+                                               btScalar(graphicsbase[2]) * meshScaling.getZ());
+                               }
+#ifdef DEBUG_TRIANGLE_MESH
+                               printf("triangle vertices:%f,%f,%f\n", triangle[j].x(), triangle[j].y(), triangle[j].z());
+#endif  //DEBUG_TRIANGLE_MESH
+                       }
+
+                       m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
+                       m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+               }
+       };
+
+       MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
+
+       m_bvh->reportAabbOverlappingNodex(&myNodeCallback, aabbMin, aabbMax);
+
+#endif  //DISABLE_BVH
+}
+
+void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+       if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
+       {
+               btTriangleMeshShape::setLocalScaling(scaling);
+               buildOptimizedBvh();
+       }
+}
+
+void btBvhTriangleMeshShape::buildOptimizedBvh()
+{
+       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);
+       }
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*)dataBuffer;
+
+       btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
+
+       m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
+
+       trimeshData->m_collisionMargin = float(m_collisionMargin);
+
+       if (m_bvh && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_BVH))
+       {
+               void* chunk = serializer->findPointer(m_bvh);
+               if (chunk)
+               {
+#ifdef BT_USE_DOUBLE_PRECISION
+                       trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
+                       trimeshData->m_quantizedFloatBvh = 0;
+#else
+                       trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
+                       trimeshData->m_quantizedDoubleBvh = 0;
+#endif  //BT_USE_DOUBLE_PRECISION
+               }
+               else
+               {
+#ifdef BT_USE_DOUBLE_PRECISION
+                       trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
+                       trimeshData->m_quantizedFloatBvh = 0;
+#else
+                       trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
+                       trimeshData->m_quantizedDoubleBvh = 0;
+#endif  //BT_USE_DOUBLE_PRECISION
+
+                       int sz = m_bvh->calculateSerializeBufferSizeNew();
+                       btChunk* chunk = serializer->allocate(sz, 1);
+                       const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
+                       serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, m_bvh);
+               }
+       }
+       else
+       {
+               trimeshData->m_quantizedFloatBvh = 0;
+               trimeshData->m_quantizedDoubleBvh = 0;
+       }
+
+       if (m_triangleInfoMap && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_TRIANGLEINFOMAP))
+       {
+               void* chunk = serializer->findPointer(m_triangleInfoMap);
+               if (chunk)
+               {
+                       trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
+               }
+               else
+               {
+                       trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
+                       int sz = m_triangleInfoMap->calculateSerializeBufferSize();
+                       btChunk* chunk = serializer->allocate(sz, 1);
+                       const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
+                       serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, m_triangleInfoMap);
+               }
+       }
+       else
+       {
+               trimeshData->m_triangleInfoMap = 0;
+       }
+
+       // Fill padding with zeros to appease msan.
+       memset(trimeshData->m_pad3, 0, sizeof(trimeshData->m_pad3));
+
+       return "btTriangleMeshShapeData";
+}
+
+void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
+{
+       if (m_bvh)
+       {
+               int len = m_bvh->calculateSerializeBufferSizeNew();  //make sure not to use calculateSerializeBufferSize because it is used for in-place
+               btChunk* chunk = serializer->allocate(len, 1);
+               const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
+               serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, (void*)m_bvh);
+       }
+}
+
+void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
+{
+       if (m_triangleInfoMap)
+       {
+               int len = m_triangleInfoMap->calculateSerializeBufferSize();
+               btChunk* chunk = serializer->allocate(len, 1);
+               const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
+               serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, (void*)m_triangleInfoMap);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
new file mode 100644 (file)
index 0000000..8b2f2ee
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_BVH_TRIANGLE_MESH_SHAPE_H
+#define BT_BVH_TRIANGLE_MESH_SHAPE_H
+
+#include "btTriangleMeshShape.h"
+#include "btOptimizedBvh.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "btTriangleInfoMap.h"
+
+///The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving objects.
+///If you required moving concave triangle meshes, it is recommended to perform convex decomposition
+///using HACD, see Bullet/Demos/ConvexDecompositionDemo.
+///Alternatively, you can use btGimpactMeshShape for moving concave triangle meshes.
+///btBvhTriangleMeshShape has 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;
+       btTriangleInfoMap* m_triangleInfoMap;
+
+       bool m_useQuantizedAabbCompression;
+       bool m_ownsBvh;
+#ifdef __clang__
+       bool m_pad[11] __attribute__((unused));  ////need padding due to alignment
+#else
+       bool m_pad[11];  ////need padding due to alignment
+#endif
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btBvhTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
+
+       ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
+       btBvhTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, bool buildBvh = true);
+
+       virtual ~btBvhTriangleMeshShape();
+
+       bool getOwnsBvh() const
+       {
+               return m_ownsBvh;
+       }
+
+       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(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 const char* getName() const { return "BVHTRIANGLEMESH"; }
+
+       virtual void setLocalScaling(const btVector3& scaling);
+
+       btOptimizedBvh* getOptimizedBvh()
+       {
+               return m_bvh;
+       }
+
+       void setOptimizedBvh(btOptimizedBvh * bvh, const btVector3& localScaling = btVector3(1, 1, 1));
+
+       void buildOptimizedBvh();
+
+       bool usesQuantizedAabbCompression() const
+       {
+               return m_useQuantizedAabbCompression;
+       }
+
+       void setTriangleInfoMap(btTriangleInfoMap * triangleInfoMap)
+       {
+               m_triangleInfoMap = triangleInfoMap;
+       }
+
+       const btTriangleInfoMap* getTriangleInfoMap() const
+       {
+               return m_triangleInfoMap;
+       }
+
+       btTriangleInfoMap* getTriangleInfoMap()
+       {
+               return m_triangleInfoMap;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+       virtual void serializeSingleBvh(btSerializer * serializer) const;
+
+       virtual void serializeSingleTriangleInfoMap(btSerializer * serializer) const;
+};
+
+// clang-format off
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btTriangleMeshShapeData
+{
+       btCollisionShapeData    m_collisionShapeData;
+
+       btStridingMeshInterfaceData m_meshInterface;
+
+       btQuantizedBvhFloatData         *m_quantizedFloatBvh;
+       btQuantizedBvhDoubleData        *m_quantizedDoubleBvh;
+
+       btTriangleInfoMapData   *m_triangleInfoMap;
+       
+       float   m_collisionMargin;
+
+       char m_pad3[4];
+       
+};
+
+// clang-format on
+
+SIMD_FORCE_INLINE int btBvhTriangleMeshShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btTriangleMeshShapeData);
+}
+
+#endif  //BT_BVH_TRIANGLE_MESH_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp
new file mode 100644 (file)
index 0000000..7c33774
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCapsuleShape.h"
+
+#include "LinearMath/btQuaternion.h"
+
+btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape()
+{
+       m_collisionMargin = radius;
+       m_shapeType = CAPSULE_SHAPE_PROXYTYPE;
+       m_upAxis = 1;
+       m_implicitShapeDimensions.setValue(radius, 0.5f * height, radius);
+}
+
+btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
+{
+       btVector3 supVec(0, 0, 0);
+
+       btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+       btVector3 vec = vec0;
+       btScalar lenSqr = vec.length2();
+       if (lenSqr < btScalar(0.0001))
+       {
+               vec.setValue(1, 0, 0);
+       }
+       else
+       {
+               btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
+               vec *= rlen;
+       }
+
+       btVector3 vtx;
+       btScalar newDot;
+
+       {
+               btVector3 pos(0, 0, 0);
+               pos[getUpAxis()] = getHalfHeight();
+
+               vtx = pos;
+               newDot = vec.dot(vtx);
+               if (newDot > maxDot)
+               {
+                       maxDot = newDot;
+                       supVec = vtx;
+               }
+       }
+       {
+               btVector3 pos(0, 0, 0);
+               pos[getUpAxis()] = -getHalfHeight();
+
+               vtx = pos;
+               newDot = vec.dot(vtx);
+               if (newDot > maxDot)
+               {
+                       maxDot = newDot;
+                       supVec = vtx;
+               }
+       }
+
+       return supVec;
+}
+
+void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       for (int j = 0; j < numVectors; j++)
+       {
+               btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+               const btVector3& vec = vectors[j];
+
+               btVector3 vtx;
+               btScalar newDot;
+               {
+                       btVector3 pos(0, 0, 0);
+                       pos[getUpAxis()] = getHalfHeight();
+                       vtx = pos;
+                       newDot = vec.dot(vtx);
+                       if (newDot > maxDot)
+                       {
+                               maxDot = newDot;
+                               supportVerticesOut[j] = vtx;
+                       }
+               }
+               {
+                       btVector3 pos(0, 0, 0);
+                       pos[getUpAxis()] = -getHalfHeight();
+                       vtx = pos;
+                       newDot = vec.dot(vtx);
+                       if (newDot > maxDot)
+                       {
+                               maxDot = newDot;
+                               supportVerticesOut[j] = vtx;
+                       }
+               }
+       }
+}
+
+void btCapsuleShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       //as an approximation, take the inertia of the box that bounds the spheres
+
+       btTransform ident;
+       ident.setIdentity();
+
+       btScalar radius = getRadius();
+
+       btVector3 halfExtents(radius, radius, radius);
+       halfExtents[getUpAxis()] += getHalfHeight();
+
+       btScalar lx = btScalar(2.) * (halfExtents[0]);
+       btScalar ly = btScalar(2.) * (halfExtents[1]);
+       btScalar lz = btScalar(2.) * (halfExtents[2]);
+       const btScalar x2 = lx * lx;
+       const btScalar y2 = ly * ly;
+       const btScalar z2 = lz * lz;
+       const btScalar scaledmass = mass * btScalar(.08333333);
+
+       inertia[0] = scaledmass * (y2 + z2);
+       inertia[1] = scaledmass * (x2 + z2);
+       inertia[2] = scaledmass * (x2 + y2);
+}
+
+btCapsuleShapeX::btCapsuleShapeX(btScalar radius, btScalar height)
+{
+       m_collisionMargin = radius;
+       m_upAxis = 0;
+       m_implicitShapeDimensions.setValue(0.5f * height, radius, radius);
+}
+
+btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius, btScalar height)
+{
+       m_collisionMargin = radius;
+       m_upAxis = 2;
+       m_implicitShapeDimensions.setValue(radius, radius, 0.5f * height);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCapsuleShape.h
new file mode 100644 (file)
index 0000000..138d0c0
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CAPSULE_SHAPE_H
+#define BT_CAPSULE_SHAPE_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+
+///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.
+ATTRIBUTE_ALIGNED16(class)
+btCapsuleShape : public btConvexInternalShape
+{
+protected:
+       int m_upAxis;
+
+protected:
+       ///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
+       btCapsuleShape() : btConvexInternalShape() { m_shapeType = CAPSULE_SHAPE_PROXYTYPE; };
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btCapsuleShape(btScalar radius, btScalar height);
+
+       ///CollisionShape Interface
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       /// btConvexShape Interface
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+       virtual void setMargin(btScalar collisionMargin)
+       {
+               //don't override the margin for capsules, their entire radius == margin
+               (void)collisionMargin;
+       }
+
+       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();
+               btVector3 center = t.getOrigin();
+               btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+
+               aabbMin = center - extent;
+               aabbMax = center + extent;
+       }
+
+       virtual const char* getName() const
+       {
+               return "CapsuleShape";
+       }
+
+       int getUpAxis() const
+       {
+               return m_upAxis;
+       }
+
+       btScalar getRadius() const
+       {
+               int radiusAxis = (m_upAxis + 2) % 3;
+               return m_implicitShapeDimensions[radiusAxis];
+       }
+
+       btScalar getHalfHeight() const
+       {
+               return m_implicitShapeDimensions[m_upAxis];
+       }
+
+       virtual void setLocalScaling(const btVector3& scaling)
+       {
+               btVector3 unScaledImplicitShapeDimensions = m_implicitShapeDimensions / m_localScaling;
+               btConvexInternalShape::setLocalScaling(scaling);
+               m_implicitShapeDimensions = (unScaledImplicitShapeDimensions * scaling);
+               //update m_collisionMargin, since entire radius==margin
+               int radiusAxis = (m_upAxis + 2) % 3;
+               m_collisionMargin = m_implicitShapeDimensions[radiusAxis];
+       }
+
+       virtual btVector3 getAnisotropicRollingFrictionDirection() const
+       {
+               btVector3 aniDir(0, 0, 0);
+               aniDir[getUpAxis()] = 1;
+               return aniDir;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+       SIMD_FORCE_INLINE void deSerializeFloat(struct btCapsuleShapeData * dataBuffer);
+};
+
+///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";
+       }
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCapsuleShapeData
+{
+       btConvexInternalShapeData m_convexInternalShapeData;
+
+       int m_upAxis;
+
+       char m_padding[4];
+};
+
+SIMD_FORCE_INLINE int btCapsuleShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btCapsuleShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btCapsuleShapeData* shapeData = (btCapsuleShapeData*)dataBuffer;
+
+       btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+       shapeData->m_upAxis = m_upAxis;
+
+       // Fill padding with zeros to appease msan.
+       shapeData->m_padding[0] = 0;
+       shapeData->m_padding[1] = 0;
+       shapeData->m_padding[2] = 0;
+       shapeData->m_padding[3] = 0;
+
+       return "btCapsuleShapeData";
+}
+
+SIMD_FORCE_INLINE void btCapsuleShape::deSerializeFloat(btCapsuleShapeData* dataBuffer)
+{
+       m_implicitShapeDimensions.deSerializeFloat(dataBuffer->m_convexInternalShapeData.m_implicitShapeDimensions);
+       m_collisionMargin = dataBuffer->m_convexInternalShapeData.m_collisionMargin;
+       m_localScaling.deSerializeFloat(dataBuffer->m_convexInternalShapeData.m_localScaling);
+       //it is best to already pre-allocate the matching btCapsuleShape*(X/Z) version to match m_upAxis
+       m_upAxis = dataBuffer->m_upAxis;
+}
+
+#endif  //BT_CAPSULE_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCollisionMargin.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCollisionMargin.h
new file mode 100644 (file)
index 0000000..abd8ab3
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MARGIN_H
+#define BT_COLLISION_MARGIN_H
+
+///The CONVEX_DISTANCE_MARGIN is a default collision margin for convex collision shapes derived from btConvexInternalShape.
+///This collision margin is used by Gjk and some other algorithms
+///Note that when creating small objects, you need to make sure to set a smaller collision margin, using the 'setMargin' API
+#define CONVEX_DISTANCE_MARGIN btScalar(0.04)  // btScalar(0.1)//;//btScalar(0.01)
+
+#endif  //BT_COLLISION_MARGIN_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCollisionShape.cpp
new file mode 100644 (file)
index 0000000..0b3640a
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "LinearMath/btSerializer.h"
+
+/*
+  Make sure this dummy function never changes so that it
+  can be used by probes that are checking whether the
+  library is actually installed.
+*/
+extern "C"
+{
+       void btBulletCollisionProbe();
+
+       void btBulletCollisionProbe() {}
+}
+
+void btCollisionShape::getBoundingSphere(btVector3& center, btScalar& radius) const
+{
+       btTransform tr;
+       tr.setIdentity();
+       btVector3 aabbMin, aabbMax;
+
+       getAabb(tr, aabbMin, aabbMax);
+
+       radius = (aabbMax - aabbMin).length() * btScalar(0.5);
+       center = (aabbMin + aabbMax) * btScalar(0.5);
+}
+
+btScalar btCollisionShape::getContactBreakingThreshold(btScalar defaultContactThreshold) const
+{
+       return getAngularMotionDisc() * defaultContactThreshold;
+}
+
+btScalar btCollisionShape::getAngularMotionDisc() const
+{
+       ///@todo cache this value, to improve performance
+       btVector3 center;
+       btScalar disc;
+       getBoundingSphere(center, disc);
+       disc += (center).length();
+       return disc;
+}
+
+void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans, const btVector3& linvel, const btVector3& angvel, btScalar timeStep, btVector3& temporalAabbMin, btVector3& temporalAabbMax) const
+{
+       //start with static aabb
+       getAabb(curTrans, temporalAabbMin, temporalAabbMax);
+
+       btScalar temporalAabbMaxx = temporalAabbMax.getX();
+       btScalar temporalAabbMaxy = temporalAabbMax.getY();
+       btScalar temporalAabbMaxz = temporalAabbMax.getZ();
+       btScalar temporalAabbMinx = temporalAabbMin.getX();
+       btScalar temporalAabbMiny = temporalAabbMin.getY();
+       btScalar temporalAabbMinz = temporalAabbMin.getZ();
+
+       // add linear motion
+       btVector3 linMotion = linvel * timeStep;
+       ///@todo: simd would have a vector max/min operation, instead of per-element access
+       if (linMotion.x() > btScalar(0.))
+               temporalAabbMaxx += linMotion.x();
+       else
+               temporalAabbMinx += linMotion.x();
+       if (linMotion.y() > btScalar(0.))
+               temporalAabbMaxy += linMotion.y();
+       else
+               temporalAabbMiny += linMotion.y();
+       if (linMotion.z() > btScalar(0.))
+               temporalAabbMaxz += linMotion.z();
+       else
+               temporalAabbMinz += linMotion.z();
+
+       //add conservative angular motion
+       btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep;
+       btVector3 angularMotion3d(angularMotion, angularMotion, angularMotion);
+       temporalAabbMin = btVector3(temporalAabbMinx, temporalAabbMiny, temporalAabbMinz);
+       temporalAabbMax = btVector3(temporalAabbMaxx, temporalAabbMaxy, temporalAabbMaxz);
+
+       temporalAabbMin -= angularMotion3d;
+       temporalAabbMax += angularMotion3d;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btCollisionShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btCollisionShapeData* shapeData = (btCollisionShapeData*)dataBuffer;
+       char* name = (char*)serializer->findNameForPointer(this);
+       shapeData->m_name = (char*)serializer->getUniquePointer(name);
+       if (shapeData->m_name)
+       {
+               serializer->serializeName(name);
+       }
+       shapeData->m_shapeType = m_shapeType;
+
+       // Fill padding with zeros to appease msan.
+       memset(shapeData->m_padding, 0, sizeof(shapeData->m_padding));
+
+       return "btCollisionShapeData";
+}
+
+void btCollisionShape::serializeSingleShape(btSerializer* serializer) const
+{
+       int len = calculateSerializeBufferSize();
+       btChunk* chunk = serializer->allocate(len, 1);
+       const char* structType = serialize(chunk->m_oldPtr, serializer);
+       serializer->finalizeChunk(chunk, structType, BT_SHAPE_CODE, (void*)this);
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCollisionShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCollisionShape.h
new file mode 100644 (file)
index 0000000..16f9e0c
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SHAPE_H
+#define BT_COLLISION_SHAPE_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  //for the shape types
+class btSerializer;
+
+///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects.
+ATTRIBUTE_ALIGNED16(class)
+btCollisionShape
+{
+protected:
+       int m_shapeType;
+       void* m_userPointer;
+       int m_userIndex;
+       int m_userIndex2;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btCollisionShape() : m_shapeType(INVALID_SHAPE_PROXYTYPE), m_userPointer(0), m_userIndex(-1), m_userIndex2(-1)
+       {
+       }
+
+       virtual ~btCollisionShape()
+       {
+       }
+
+       ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const = 0;
+
+       virtual void getBoundingSphere(btVector3 & center, btScalar & radius) const;
+
+       ///getAngularMotionDisc returns the maximum radius needed for Conservative Advancement to handle time-of-impact with rotations.
+       virtual btScalar getAngularMotionDisc() const;
+
+       virtual btScalar getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const;
+
+       ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
+       ///result is conservative
+       void calculateTemporalAabb(const btTransform& curTrans, const btVector3& linvel, const btVector3& angvel, btScalar timeStep, btVector3& temporalAabbMin, btVector3& temporalAabbMax) const;
+
+       SIMD_FORCE_INLINE bool isPolyhedral() const
+       {
+               return btBroadphaseProxy::isPolyhedral(getShapeType());
+       }
+
+       SIMD_FORCE_INLINE bool isConvex2d() const
+       {
+               return btBroadphaseProxy::isConvex2d(getShapeType());
+       }
+
+       SIMD_FORCE_INLINE bool isConvex() const
+       {
+               return btBroadphaseProxy::isConvex(getShapeType());
+       }
+       SIMD_FORCE_INLINE bool isNonMoving() const
+       {
+               return btBroadphaseProxy::isNonMoving(getShapeType());
+       }
+       SIMD_FORCE_INLINE bool isConcave() const
+       {
+               return btBroadphaseProxy::isConcave(getShapeType());
+       }
+       SIMD_FORCE_INLINE bool isCompound() const
+       {
+               return btBroadphaseProxy::isCompound(getShapeType());
+       }
+
+       SIMD_FORCE_INLINE bool isSoftBody() const
+       {
+               return btBroadphaseProxy::isSoftBody(getShapeType());
+       }
+
+       ///isInfinite is used to catch simulation error (aabb check)
+       SIMD_FORCE_INLINE bool isInfinite() const
+       {
+               return btBroadphaseProxy::isInfinite(getShapeType());
+       }
+
+#ifndef __SPU__
+       virtual void setLocalScaling(const btVector3& scaling) = 0;
+       virtual const btVector3& getLocalScaling() const = 0;
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const = 0;
+
+       //debugging support
+       virtual const char* getName() const = 0;
+#endif  //__SPU__
+
+       int getShapeType() const
+       {
+               return m_shapeType;
+       }
+
+       ///the getAnisotropicRollingFrictionDirection can be used in combination with setAnisotropicFriction
+       ///See Bullet/Demos/RollingFrictionDemo for an example
+       virtual btVector3 getAnisotropicRollingFrictionDirection() const
+       {
+               return btVector3(1, 1, 1);
+       }
+       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;
+       }
+       void setUserIndex(int index)
+       {
+               m_userIndex = index;
+       }
+
+       int getUserIndex() const
+       {
+               return m_userIndex;
+       }
+
+       void setUserIndex2(int index)
+       {
+               m_userIndex2 = index;
+       }
+
+       int getUserIndex2() const
+       {
+               return m_userIndex2;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+       virtual void serializeSingleShape(btSerializer * serializer) const;
+};
+
+// clang-format off
+// parser needs * with the name
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCollisionShapeData
+{
+       char    *m_name;
+       int             m_shapeType;
+       char    m_padding[4];
+};
+// clang-format on
+SIMD_FORCE_INLINE int btCollisionShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btCollisionShapeData);
+}
+
+#endif  //BT_COLLISION_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCompoundShape.cpp
new file mode 100644 (file)
index 0000000..fd7828b
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCompoundShape.h"
+#include "btCollisionShape.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btSerializer.h"
+
+btCompoundShape::btCompoundShape(bool enableDynamicAabbTree, const int initialChildCapacity)
+       : m_localAabbMin(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT)),
+         m_localAabbMax(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT)),
+         m_dynamicAabbTree(0),
+         m_updateRevision(1),
+         m_collisionMargin(btScalar(0.)),
+         m_localScaling(btScalar(1.), btScalar(1.), btScalar(1.))
+{
+       m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
+
+       if (enableDynamicAabbTree)
+       {
+               void* mem = btAlignedAlloc(sizeof(btDbvt), 16);
+               m_dynamicAabbTree = new (mem) btDbvt();
+               btAssert(mem == m_dynamicAabbTree);
+       }
+
+       m_children.reserve(initialChildCapacity);
+}
+
+btCompoundShape::~btCompoundShape()
+{
+       if (m_dynamicAabbTree)
+       {
+               m_dynamicAabbTree->~btDbvt();
+               btAlignedFree(m_dynamicAabbTree);
+       }
+}
+
+void btCompoundShape::addChildShape(const btTransform& localTransform, btCollisionShape* shape)
+{
+       m_updateRevision++;
+       //m_childTransforms.push_back(localTransform);
+       //m_childShapes.push_back(shape);
+       btCompoundShapeChild child;
+       child.m_node = 0;
+       child.m_transform = localTransform;
+       child.m_childShape = shape;
+       child.m_childShapeType = shape->getShapeType();
+       child.m_childMargin = shape->getMargin();
+
+       //extend the local aabbMin/aabbMax
+       btVector3 localAabbMin, localAabbMax;
+       shape->getAabb(localTransform, localAabbMin, localAabbMax);
+       for (int i = 0; i < 3; i++)
+       {
+               if (m_localAabbMin[i] > localAabbMin[i])
+               {
+                       m_localAabbMin[i] = localAabbMin[i];
+               }
+               if (m_localAabbMax[i] < localAabbMax[i])
+               {
+                       m_localAabbMax[i] = localAabbMax[i];
+               }
+       }
+       if (m_dynamicAabbTree)
+       {
+               const btDbvtVolume bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
+               size_t index = m_children.size();
+               child.m_node = m_dynamicAabbTree->insert(bounds, reinterpret_cast<void*>(index));
+       }
+
+       m_children.push_back(child);
+}
+
+void btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb)
+{
+       m_children[childIndex].m_transform = newChildTransform;
+
+       if (m_dynamicAabbTree)
+       {
+               ///update the dynamic aabb tree
+               btVector3 localAabbMin, localAabbMax;
+               m_children[childIndex].m_childShape->getAabb(newChildTransform, localAabbMin, localAabbMax);
+               ATTRIBUTE_ALIGNED16(btDbvtVolume)
+               bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
+               //int index = m_children.size()-1;
+               m_dynamicAabbTree->update(m_children[childIndex].m_node, bounds);
+       }
+
+       if (shouldRecalculateLocalAabb)
+       {
+               recalculateLocalAabb();
+       }
+}
+
+void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
+{
+       m_updateRevision++;
+       btAssert(childShapeIndex >= 0 && childShapeIndex < m_children.size());
+       if (m_dynamicAabbTree)
+       {
+               m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
+       }
+       m_children.swap(childShapeIndex, m_children.size() - 1);
+       if (m_dynamicAabbTree)
+               m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex;
+       m_children.pop_back();
+}
+
+void btCompoundShape::removeChildShape(btCollisionShape* shape)
+{
+       m_updateRevision++;
+       // Find the children containing the shape specified, and remove those children.
+       //note: there might be multiple children using the same shape!
+       for (int i = m_children.size() - 1; i >= 0; i--)
+       {
+               if (m_children[i].m_childShape == shape)
+               {
+                       removeChildShapeByIndex(i);
+               }
+       }
+
+       recalculateLocalAabb();
+}
+
+void btCompoundShape::recalculateLocalAabb()
+{
+       // Recalculate the local aabb
+       // Brute force, it iterates over all the shapes left.
+
+       m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+       m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+
+       //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);
+       btVector3 localCenter = btScalar(0.5) * (m_localAabbMax + m_localAabbMin);
+
+       //avoid an illegal AABB when there are no children
+       if (!m_children.size())
+       {
+               localHalfExtents.setValue(0, 0, 0);
+               localCenter.setValue(0, 0, 0);
+       }
+       localHalfExtents += btVector3(getMargin(), getMargin(), getMargin());
+
+       btMatrix3x3 abs_b = trans.getBasis().absolute();
+
+       btVector3 center = trans(localCenter);
+
+       btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+       aabbMin = center - extent;
+       aabbMax = center + extent;
+}
+
+void btCompoundShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       //approximation: take the inertia from the aabb for now
+       btTransform ident;
+       ident.setIdentity();
+       btVector3 aabbMin, aabbMax;
+       getAabb(ident, aabbMin, aabbMax);
+
+       btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
+
+       btScalar lx = btScalar(2.) * (halfExtents.x());
+       btScalar ly = btScalar(2.) * (halfExtents.y());
+       btScalar lz = btScalar(2.) * (halfExtents.z());
+
+       inertia[0] = mass / (btScalar(12.0)) * (ly * ly + lz * lz);
+       inertia[1] = mass / (btScalar(12.0)) * (lx * lx + lz * lz);
+       inertia[2] = mass / (btScalar(12.0)) * (lx * lx + ly * ly);
+}
+
+void btCompoundShape::calculatePrincipalAxisTransform(const btScalar* masses, btTransform& principal, btVector3& inertia) const
+{
+       int n = m_children.size();
+
+       btScalar totalMass = 0;
+       btVector3 center(0, 0, 0);
+       int k;
+
+       for (k = 0; k < n; k++)
+       {
+               btAssert(masses[k] > 0);
+               center += m_children[k].m_transform.getOrigin() * masses[k];
+               totalMass += masses[k];
+       }
+
+       btAssert(totalMass > 0);
+
+       center /= totalMass;
+       principal.setOrigin(center);
+
+       btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
+       for (k = 0; k < n; k++)
+       {
+               btVector3 i;
+               m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
+
+               const btTransform& t = m_children[k].m_transform;
+               btVector3 o = t.getOrigin() - center;
+
+               //compute inertia tensor in coordinate system of compound shape
+               btMatrix3x3 j = t.getBasis().transpose();
+               j[0] *= i[0];
+               j[1] *= i[1];
+               j[2] *= i[2];
+               j = t.getBasis() * j;
+
+               //add inertia tensor
+               tensor[0] += j[0];
+               tensor[1] += j[1];
+               tensor[2] += j[2];
+
+               //compute inertia tensor of pointmass at o
+               btScalar o2 = o.length2();
+               j[0].setValue(o2, 0, 0);
+               j[1].setValue(0, o2, 0);
+               j[2].setValue(0, 0, o2);
+               j[0] += o * -o.x();
+               j[1] += o * -o.y();
+               j[2] += o * -o.z();
+
+               //add inertia tensor of pointmass
+               tensor[0] += masses[k] * j[0];
+               tensor[1] += masses[k] * j[1];
+               tensor[2] += masses[k] * j[2];
+       }
+
+       tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
+       inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
+}
+
+void btCompoundShape::setLocalScaling(const btVector3& scaling)
+{
+       for (int i = 0; i < m_children.size(); i++)
+       {
+               btTransform childTrans = getChildTransform(i);
+               btVector3 childScale = m_children[i].m_childShape->getLocalScaling();
+               //              childScale = childScale * (childTrans.getBasis() * scaling);
+               childScale = childScale * scaling / m_localScaling;
+               m_children[i].m_childShape->setLocalScaling(childScale);
+               childTrans.setOrigin((childTrans.getOrigin()) * scaling / m_localScaling);
+               updateChildTransform(i, childTrans, false);
+       }
+
+       m_localScaling = scaling;
+       recalculateLocalAabb();
+}
+
+void btCompoundShape::createAabbTreeFromChildren()
+{
+       if (!m_dynamicAabbTree)
+       {
+               void* mem = btAlignedAlloc(sizeof(btDbvt), 16);
+               m_dynamicAabbTree = new (mem) btDbvt();
+               btAssert(mem == m_dynamicAabbTree);
+
+               for (int index = 0; index < m_children.size(); index++)
+               {
+                       btCompoundShapeChild& child = m_children[index];
+
+                       //extend the local aabbMin/aabbMax
+                       btVector3 localAabbMin, localAabbMax;
+                       child.m_childShape->getAabb(child.m_transform, localAabbMin, localAabbMax);
+
+                       const btDbvtVolume bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
+                       size_t index2 = index;
+                       child.m_node = m_dynamicAabbTree->insert(bounds, reinterpret_cast<void*>(index2));
+               }
+       }
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btCompoundShapeData* shapeData = (btCompoundShapeData*)dataBuffer;
+       btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
+
+       shapeData->m_collisionMargin = float(m_collisionMargin);
+       shapeData->m_numChildShapes = m_children.size();
+       shapeData->m_childShapePtr = 0;
+       if (shapeData->m_numChildShapes)
+       {
+               btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData), shapeData->m_numChildShapes);
+               btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr;
+               shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr);
+
+               for (int i = 0; i < shapeData->m_numChildShapes; i++, memPtr++)
+               {
+                       memPtr->m_childMargin = float(m_children[i].m_childMargin);
+                       memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape);
+                       //don't serialize shapes that already have been serialized
+                       if (!serializer->findPointer(m_children[i].m_childShape))
+                       {
+                               btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(), 1);
+                               const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr, serializer);
+                               serializer->finalizeChunk(chunk, structType, BT_SHAPE_CODE, m_children[i].m_childShape);
+                       }
+
+                       memPtr->m_childShapeType = m_children[i].m_childShapeType;
+                       m_children[i].m_transform.serializeFloat(memPtr->m_transform);
+               }
+               serializer->finalizeChunk(chunk, "btCompoundShapeChildData", BT_ARRAY_CODE, chunk->m_oldPtr);
+       }
+       return "btCompoundShapeData";
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCompoundShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCompoundShape.h
new file mode 100644 (file)
index 0000000..7e2d0eb
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_COMPOUND_SHAPE_H
+#define BT_COMPOUND_SHAPE_H
+
+#include "btCollisionShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+//class btOptimizedBvh;
+struct btDbvt;
+
+ATTRIBUTE_ALIGNED16(struct)
+btCompoundShapeChild
+{
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btTransform m_transform;
+       btCollisionShape* m_childShape;
+       int m_childShapeType;
+       btScalar m_childMargin;
+       struct btDbvtNode* m_node;
+};
+
+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);
+}
+
+/// The btCompoundShape allows to store multiple other btCollisionShapes
+/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape.
+/// It has an (optional) dynamic aabb tree to accelerate early rejection tests.
+/// @todo: This aabb tree can also be use to speed up ray tests on btCompoundShape, see http://code.google.com/p/bullet/issues/detail?id=25
+/// Currently, removal of child shapes is only supported when disabling the aabb tree (pass 'false' in the constructor of btCompoundShape)
+ATTRIBUTE_ALIGNED16(class)
+btCompoundShape : public btCollisionShape
+{
+protected:
+       btAlignedObjectArray<btCompoundShapeChild> m_children;
+       btVector3 m_localAabbMin;
+       btVector3 m_localAabbMax;
+
+       btDbvt* m_dynamicAabbTree;
+
+       ///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated
+       int m_updateRevision;
+
+       btScalar m_collisionMargin;
+
+       btVector3 m_localScaling;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       explicit btCompoundShape(bool enableDynamicAabbTree = true, const int initialChildCapacity = 0);
+
+       virtual ~btCompoundShape();
+
+       void addChildShape(const btTransform& localTransform, btCollisionShape* shape);
+
+       /// Remove all children shapes that contain the specified shape
+       virtual void removeChildShape(btCollisionShape * shape);
+
+       void removeChildShapeByIndex(int childShapeindex);
+
+       int getNumChildShapes() const
+       {
+               return int(m_children.size());
+       }
+
+       btCollisionShape* getChildShape(int index)
+       {
+               return m_children[index].m_childShape;
+       }
+       const btCollisionShape* getChildShape(int index) const
+       {
+               return m_children[index].m_childShape;
+       }
+
+       btTransform& getChildTransform(int index)
+       {
+               return m_children[index].m_transform;
+       }
+       const btTransform& getChildTransform(int index) const
+       {
+               return m_children[index].m_transform;
+       }
+
+       ///set a new transform for a child, and update internal data structures (local aabb and dynamic tree)
+       void updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb = true);
+
+       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);
+
+       virtual const btVector3& getLocalScaling() const
+       {
+               return m_localScaling;
+       }
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       virtual void setMargin(btScalar margin)
+       {
+               m_collisionMargin = margin;
+       }
+       virtual btScalar getMargin() const
+       {
+               return m_collisionMargin;
+       }
+       virtual const char* getName() const
+       {
+               return "Compound";
+       }
+
+       const btDbvt* getDynamicAabbTree() const
+       {
+               return m_dynamicAabbTree;
+       }
+
+       btDbvt* getDynamicAabbTree()
+       {
+               return m_dynamicAabbTree;
+       }
+
+       void createAabbTreeFromChildren();
+
+       ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
+       ///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform
+       ///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound
+       ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
+       ///of the collision object by the principal transform.
+       void calculatePrincipalAxisTransform(const btScalar* masses, btTransform& principal, btVector3& inertia) const;
+
+       int getUpdateRevision() const
+       {
+               return m_updateRevision;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+// clang-format off
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCompoundShapeChildData
+{
+       btTransformFloatData    m_transform;
+       btCollisionShapeData    *m_childShape;
+       int                                             m_childShapeType;
+       float                                   m_childMargin;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCompoundShapeData
+{
+       btCollisionShapeData            m_collisionShapeData;
+
+       btCompoundShapeChildData        *m_childShapePtr;
+
+       int                                                     m_numChildShapes;
+
+       float   m_collisionMargin;
+
+};
+
+// clang-format on
+
+SIMD_FORCE_INLINE int btCompoundShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btCompoundShapeData);
+}
+
+#endif  //BT_COMPOUND_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConcaveShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConcaveShape.cpp
new file mode 100644 (file)
index 0000000..5d39684
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConcaveShape.h"
+
+btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.))
+{
+}
+
+btConcaveShape::~btConcaveShape()
+{
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConcaveShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConcaveShape.h
new file mode 100644 (file)
index 0000000..716624e
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONCAVE_SHAPE_H
+#define BT_CONCAVE_SHAPE_H
+
+#include "btCollisionShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+#include "btTriangleCallback.h"
+
+/// PHY_ScalarType enumerates possible scalar types.
+/// See the btStridingMeshInterface or btHeightfieldTerrainShape for its use
+typedef enum PHY_ScalarType
+{
+       PHY_FLOAT,
+       PHY_DOUBLE,
+       PHY_INTEGER,
+       PHY_SHORT,
+       PHY_FIXEDPOINT88,
+       PHY_UCHAR
+} PHY_ScalarType;
+
+///The btConcaveShape class provides an interface for non-moving (static) concave shapes.
+///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape.
+ATTRIBUTE_ALIGNED16(class)
+btConcaveShape : public btCollisionShape
+{
+protected:
+       btScalar m_collisionMargin;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btConcaveShape();
+
+       virtual ~btConcaveShape();
+
+       virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const = 0;
+
+       virtual btScalar getMargin() const
+       {
+               return m_collisionMargin;
+       }
+       virtual void setMargin(btScalar collisionMargin)
+       {
+               m_collisionMargin = collisionMargin;
+       }
+};
+
+#endif  //BT_CONCAVE_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConeShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConeShape.cpp
new file mode 100644 (file)
index 0000000..64a6f27
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConeShape.h"
+
+btConeShape::btConeShape(btScalar radius, btScalar height) : btConvexInternalShape(),
+                                                                                                                        m_radius(radius),
+                                                                                                                        m_height(height)
+{
+       m_shapeType = CONE_SHAPE_PROXYTYPE;
+       setConeUpIndex(1);
+       btVector3 halfExtents;
+       m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
+}
+
+btConeShapeZ::btConeShapeZ(btScalar radius, btScalar height) : btConeShape(radius, height)
+{
+       setConeUpIndex(2);
+}
+
+btConeShapeX::btConeShapeX(btScalar radius, btScalar height) : btConeShape(radius, height)
+{
+       setConeUpIndex(0);
+}
+
+///choose upAxis index
+void btConeShape::setConeUpIndex(int upIndex)
+{
+       switch (upIndex)
+       {
+               case 0:
+                       m_coneIndices[0] = 1;
+                       m_coneIndices[1] = 0;
+                       m_coneIndices[2] = 2;
+                       break;
+               case 1:
+                       m_coneIndices[0] = 0;
+                       m_coneIndices[1] = 1;
+                       m_coneIndices[2] = 2;
+                       break;
+               case 2:
+                       m_coneIndices[0] = 0;
+                       m_coneIndices[1] = 2;
+                       m_coneIndices[2] = 1;
+                       break;
+               default:
+                       btAssert(0);
+       };
+
+       m_implicitShapeDimensions[m_coneIndices[0]] = m_radius;
+       m_implicitShapeDimensions[m_coneIndices[1]] = m_height;
+       m_implicitShapeDimensions[m_coneIndices[2]] = m_radius;
+}
+
+btVector3 btConeShape::coneLocalSupport(const btVector3& v) const
+{
+       btScalar halfHeight = m_height * btScalar(0.5);
+
+       if (v[m_coneIndices[1]] > v.length() * m_sinAngle)
+       {
+               btVector3 tmp;
+
+               tmp[m_coneIndices[0]] = btScalar(0.);
+               tmp[m_coneIndices[1]] = halfHeight;
+               tmp[m_coneIndices[2]] = btScalar(0.);
+               return tmp;
+       }
+       else
+       {
+               btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]);
+               if (s > SIMD_EPSILON)
+               {
+                       btScalar d = m_radius / s;
+                       btVector3 tmp;
+                       tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d;
+                       tmp[m_coneIndices[1]] = -halfHeight;
+                       tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d;
+                       return tmp;
+               }
+               else
+               {
+                       btVector3 tmp;
+                       tmp[m_coneIndices[0]] = btScalar(0.);
+                       tmp[m_coneIndices[1]] = -halfHeight;
+                       tmp[m_coneIndices[2]] = btScalar(0.);
+                       return tmp;
+               }
+       }
+}
+
+btVector3 btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+       return coneLocalSupport(vec);
+}
+
+void btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       for (int i = 0; i < numVectors; i++)
+       {
+               const btVector3& vec = vectors[i];
+               supportVerticesOut[i] = coneLocalSupport(vec);
+       }
+}
+
+btVector3 btConeShape::localGetSupportingVertex(const btVector3& vec) const
+{
+       btVector3 supVertex = coneLocalSupport(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;
+}
+
+void btConeShape::setLocalScaling(const btVector3& scaling)
+{
+       int axis = m_coneIndices[1];
+       int r1 = m_coneIndices[0];
+       int r2 = m_coneIndices[2];
+       m_height *= scaling[axis] / m_localScaling[axis];
+       m_radius *= (scaling[r1] / m_localScaling[r1] + scaling[r2] / m_localScaling[r2]) / 2;
+       m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
+       btConvexInternalShape::setLocalScaling(scaling);
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConeShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConeShape.h
new file mode 100644 (file)
index 0000000..49f26bc
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONE_MINKOWSKI_H
+#define BT_CONE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+
+///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.
+ATTRIBUTE_ALIGNED16(class)
+btConeShape : public btConvexInternalShape
+
+{
+       btScalar m_sinAngle;
+       btScalar m_radius;
+       btScalar m_height;
+       int m_coneIndices[3];
+       btVector3 coneLocalSupport(const btVector3& v) const;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btConeShape(btScalar radius, btScalar height);
+
+       virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+       btScalar getRadius() const { return m_radius; }
+       btScalar getHeight() const { return m_height; }
+
+       void setRadius(const btScalar radius)
+       {
+               m_radius = radius;
+       }
+       void setHeight(const btScalar height)
+       {
+               m_height = height;
+       }
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const
+       {
+               btTransform identity;
+               identity.setIdentity();
+               btVector3 aabbMin, aabbMax;
+               getAabb(identity, aabbMin, aabbMax);
+
+               btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
+
+               btScalar margin = getMargin();
+
+               btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
+               btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
+               btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
+               const btScalar x2 = lx * lx;
+               const btScalar y2 = ly * ly;
+               const btScalar z2 = lz * lz;
+               const btScalar scaledmass = mass * btScalar(0.08333333);
+
+               inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
+
+               //              inertia.x() = scaledmass * (y2+z2);
+               //              inertia.y() = scaledmass * (x2+z2);
+               //              inertia.z() = scaledmass * (x2+y2);
+       }
+
+       virtual const char* getName() const
+       {
+               return "Cone";
+       }
+
+       ///choose upAxis index
+       void setConeUpIndex(int upIndex);
+
+       int getConeUpIndex() const
+       {
+               return m_coneIndices[1];
+       }
+
+       virtual btVector3 getAnisotropicRollingFrictionDirection() const
+       {
+               return btVector3(0, 1, 0);
+       }
+
+       virtual void setLocalScaling(const btVector3& scaling);
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+///btConeShape implements a Cone shape, around the X axis
+class btConeShapeX : public btConeShape
+{
+public:
+       btConeShapeX(btScalar radius, btScalar height);
+
+       virtual btVector3 getAnisotropicRollingFrictionDirection() const
+       {
+               return btVector3(1, 0, 0);
+       }
+
+       //debugging
+       virtual const char* getName() const
+       {
+               return "ConeX";
+       }
+};
+
+///btConeShapeZ implements a Cone shape, around the Z axis
+class btConeShapeZ : public btConeShape
+{
+public:
+       btConeShapeZ(btScalar radius, btScalar height);
+
+       virtual btVector3 getAnisotropicRollingFrictionDirection() const
+       {
+               return btVector3(0, 0, 1);
+       }
+
+       //debugging
+       virtual const char* getName() const
+       {
+               return "ConeZ";
+       }
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btConeShapeData
+{
+       btConvexInternalShapeData m_convexInternalShapeData;
+
+       int m_upIndex;
+
+       char m_padding[4];
+};
+
+SIMD_FORCE_INLINE int btConeShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btConeShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btConeShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btConeShapeData* shapeData = (btConeShapeData*)dataBuffer;
+
+       btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+       shapeData->m_upIndex = m_coneIndices[1];
+
+       // Fill padding with zeros to appease msan.
+       shapeData->m_padding[0] = 0;
+       shapeData->m_padding[1] = 0;
+       shapeData->m_padding[2] = 0;
+       shapeData->m_padding[3] = 0;
+
+       return "btConeShapeData";
+}
+
+#endif  //BT_CONE_MINKOWSKI_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp
new file mode 100644 (file)
index 0000000..7d3d1d3
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btConvex2dShape.h"
+
+btConvex2dShape::btConvex2dShape(btConvexShape* convexChildShape) : btConvexShape(), m_childConvexShape(convexChildShape)
+{
+       m_shapeType = CONVEX_2D_SHAPE_PROXYTYPE;
+}
+
+btConvex2dShape::~btConvex2dShape()
+{
+}
+
+btVector3 btConvex2dShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+       return m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
+}
+
+void btConvex2dShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors, supportVerticesOut, numVectors);
+}
+
+btVector3 btConvex2dShape::localGetSupportingVertex(const btVector3& vec) const
+{
+       return m_childConvexShape->localGetSupportingVertex(vec);
+}
+
+void btConvex2dShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       ///this linear upscaling is not realistic, but we don't deal with large mass ratios...
+       m_childConvexShape->calculateLocalInertia(mass, inertia);
+}
+
+///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btConvex2dShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       m_childConvexShape->getAabb(t, aabbMin, aabbMax);
+}
+
+void btConvex2dShape::getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       m_childConvexShape->getAabbSlow(t, aabbMin, aabbMax);
+}
+
+void btConvex2dShape::setLocalScaling(const btVector3& scaling)
+{
+       m_childConvexShape->setLocalScaling(scaling);
+}
+
+const btVector3& btConvex2dShape::getLocalScaling() const
+{
+       return m_childConvexShape->getLocalScaling();
+}
+
+void btConvex2dShape::setMargin(btScalar margin)
+{
+       m_childConvexShape->setMargin(margin);
+}
+btScalar btConvex2dShape::getMargin() const
+{
+       return m_childConvexShape->getMargin();
+}
+
+int btConvex2dShape::getNumPreferredPenetrationDirections() const
+{
+       return m_childConvexShape->getNumPreferredPenetrationDirections();
+}
+
+void btConvex2dShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+{
+       m_childConvexShape->getPreferredPenetrationDirection(index, penetrationVector);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvex2dShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvex2dShape.h
new file mode 100644 (file)
index 0000000..cd4f1ef
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_2D_SHAPE_H
+#define BT_CONVEX_2D_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+
+///The btConvex2dShape allows to use arbitrary convex shapes as 2d convex shapes, with the Z component assumed to be 0.
+///For 2d boxes, the btBox2dShape is recommended.
+ATTRIBUTE_ALIGNED16(class)
+btConvex2dShape : public btConvexShape
+{
+       btConvexShape* m_childConvexShape;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btConvex2dShape(btConvexShape * convexChildShape);
+
+       virtual ~btConvex2dShape();
+
+       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;
+
+       btConvexShape* getChildShape()
+       {
+               return m_childConvexShape;
+       }
+
+       const btConvexShape* getChildShape() const
+       {
+               return m_childConvexShape;
+       }
+
+       virtual const char* getName() const
+       {
+               return "Convex2dShape";
+       }
+
+       ///////////////////////////
+
+       ///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_CONVEX_2D_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
new file mode 100644 (file)
index 0000000..703de45
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#if defined(_WIN32) || defined(__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+#include "btConvexHullShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btSerializer.h"
+#include "btConvexPolyhedron.h"
+#include "LinearMath/btConvexHullComputer.h"
+
+btConvexHullShape ::btConvexHullShape(const btScalar* points, int numPoints, int stride) : btPolyhedralConvexAabbCachingShape()
+{
+       m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE;
+       m_unscaledPoints.resize(numPoints);
+
+       unsigned char* pointsAddress = (unsigned char*)points;
+
+       for (int i = 0; i < numPoints; i++)
+       {
+               btScalar* point = (btScalar*)pointsAddress;
+               m_unscaledPoints[i] = btVector3(point[0], point[1], point[2]);
+               pointsAddress += stride;
+       }
+
+       recalcLocalAabb();
+}
+
+void btConvexHullShape::setLocalScaling(const btVector3& scaling)
+{
+       m_localScaling = scaling;
+       recalcLocalAabb();
+}
+
+void btConvexHullShape::addPoint(const btVector3& point, bool recalculateLocalAabb)
+{
+       m_unscaledPoints.push_back(point);
+       if (recalculateLocalAabb)
+               recalcLocalAabb();
+}
+
+btVector3 btConvexHullShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+       btVector3 supVec(btScalar(0.), btScalar(0.), btScalar(0.));
+       btScalar maxDot = btScalar(-BT_LARGE_FLOAT);
+
+       // Here we take advantage of dot(a, b*c) = dot(a*b, c).  Note: This is true mathematically, but not numerically.
+       if (0 < m_unscaledPoints.size())
+       {
+               btVector3 scaled = vec * m_localScaling;
+               int index = (int)scaled.maxDot(&m_unscaledPoints[0], m_unscaledPoints.size(), maxDot);  // FIXME: may violate encapsulation of m_unscaledPoints
+               return m_unscaledPoints[index] * m_localScaling;
+       }
+
+       return supVec;
+}
+
+void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       btScalar newDot;
+       //use 'w' component of supportVerticesOut?
+       {
+               for (int i = 0; i < numVectors; i++)
+               {
+                       supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+               }
+       }
+
+       for (int j = 0; j < numVectors; j++)
+       {
+               btVector3 vec = vectors[j] * m_localScaling;  // dot(a*b,c) = dot(a,b*c)
+               if (0 < m_unscaledPoints.size())
+               {
+                       int i = (int)vec.maxDot(&m_unscaledPoints[0], m_unscaledPoints.size(), newDot);
+                       supportVerticesOut[j] = getScaledPoint(i);
+                       supportVerticesOut[j][3] = newDot;
+               }
+               else
+                       supportVerticesOut[j][3] = -BT_LARGE_FLOAT;
+       }
+}
+
+btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec) const
+{
+       btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+       if (getMargin() != btScalar(0.))
+       {
+               btVector3 vecnorm = vec;
+               if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
+               {
+                       vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+               }
+               vecnorm.normalize();
+               supVertex += getMargin() * vecnorm;
+       }
+       return supVertex;
+}
+
+void btConvexHullShape::optimizeConvexHull()
+{
+       btConvexHullComputer conv;
+       conv.compute(&m_unscaledPoints[0].getX(), sizeof(btVector3), m_unscaledPoints.size(), 0.f, 0.f);
+       int numVerts = conv.vertices.size();
+       m_unscaledPoints.resize(0);
+       for (int i = 0; i < numVerts; i++)
+       {
+               m_unscaledPoints.push_back(conv.vertices[i]);
+       }
+}
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
+int btConvexHullShape::getNumVertices() const
+{
+       return m_unscaledPoints.size();
+}
+
+int btConvexHullShape::getNumEdges() const
+{
+       return m_unscaledPoints.size();
+}
+
+void btConvexHullShape::getEdge(int i, btVector3& pa, btVector3& pb) const
+{
+       int index0 = i % m_unscaledPoints.size();
+       int index1 = (i + 1) % m_unscaledPoints.size();
+       pa = getScaledPoint(index0);
+       pb = getScaledPoint(index1);
+}
+
+void btConvexHullShape::getVertex(int i, btVector3& vtx) const
+{
+       vtx = getScaledPoint(i);
+}
+
+int btConvexHullShape::getNumPlanes() const
+{
+       return 0;
+}
+
+void btConvexHullShape::getPlane(btVector3&, btVector3&, int) const
+{
+       btAssert(0);
+}
+
+//not yet
+bool btConvexHullShape::isInside(const btVector3&, btScalar) const
+{
+       btAssert(0);
+       return false;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       //int szc = sizeof(btConvexHullShapeData);
+       btConvexHullShapeData* shapeData = (btConvexHullShapeData*)dataBuffer;
+       btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+       int numElem = m_unscaledPoints.size();
+       shapeData->m_numUnscaledPoints = numElem;
+#ifdef BT_USE_DOUBLE_PRECISION
+       shapeData->m_unscaledPointsFloatPtr = 0;
+       shapeData->m_unscaledPointsDoublePtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]) : 0;
+#else
+       shapeData->m_unscaledPointsFloatPtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]) : 0;
+       shapeData->m_unscaledPointsDoublePtr = 0;
+#endif
+
+       if (numElem)
+       {
+               int sz = sizeof(btVector3Data);
+               //      int sz2 = sizeof(btVector3DoubleData);
+               //      int sz3 = sizeof(btVector3FloatData);
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               btVector3Data* memPtr = (btVector3Data*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       m_unscaledPoints[i].serialize(*memPtr);
+               }
+               serializer->finalizeChunk(chunk, btVector3DataName, BT_ARRAY_CODE, (void*)&m_unscaledPoints[0]);
+       }
+
+       // Fill padding with zeros to appease msan.
+       memset(shapeData->m_padding3, 0, sizeof(shapeData->m_padding3));
+
+       return "btConvexHullShapeData";
+}
+
+void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const
+{
+#if 1
+       minProj = FLT_MAX;
+       maxProj = -FLT_MAX;
+
+       int numVerts = m_unscaledPoints.size();
+       for (int i = 0; i < numVerts; i++)
+       {
+               btVector3 vtx = m_unscaledPoints[i] * m_localScaling;
+               btVector3 pt = trans * vtx;
+               btScalar dp = pt.dot(dir);
+               if (dp < minProj)
+               {
+                       minProj = dp;
+                       witnesPtMin = pt;
+               }
+               if (dp > maxProj)
+               {
+                       maxProj = dp;
+                       witnesPtMax = pt;
+               }
+       }
+#else
+       btVector3 localAxis = dir * trans.getBasis();
+       witnesPtMin = trans(localGetSupportingVertex(localAxis));
+       witnesPtMax = trans(localGetSupportingVertex(-localAxis));
+
+       minProj = witnesPtMin.dot(dir);
+       maxProj = witnesPtMax.dot(dir);
+#endif
+
+       if (minProj > maxProj)
+       {
+               btSwap(minProj, maxProj);
+               btSwap(witnesPtMin, witnesPtMax);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexHullShape.h
new file mode 100644 (file)
index 0000000..01058a6
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_HULL_SHAPE_H
+#define BT_CONVEX_HULL_SHAPE_H
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+
+///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 btPolyhedralConvexAabbCachingShape
+{
+protected:
+       btAlignedObjectArray<btVector3> m_unscaledPoints;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory.
+       ///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint.
+       ///btConvexHullShape make an internal copy of the points.
+       btConvexHullShape(const btScalar* points = 0, int numPoints = 0, int stride = sizeof(btVector3));
+
+       void addPoint(const btVector3& point, bool recalculateLocalAabb = true);
+
+       btVector3* getUnscaledPoints()
+       {
+               return &m_unscaledPoints[0];
+       }
+
+       const btVector3* getUnscaledPoints() const
+       {
+               return &m_unscaledPoints[0];
+       }
+
+       ///getPoints is obsolete, please use getUnscaledPoints
+       const btVector3* getPoints() const
+       {
+               return getUnscaledPoints();
+       }
+
+       void optimizeConvexHull();
+
+       SIMD_FORCE_INLINE btVector3 getScaledPoint(int i) const
+       {
+               return m_unscaledPoints[i] * m_localScaling;
+       }
+
+       SIMD_FORCE_INLINE int getNumPoints() const
+       {
+               return m_unscaledPoints.size();
+       }
+
+       virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+       virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const;
+
+       //debugging
+       virtual const char* getName() const { return "Convex"; }
+
+       virtual int getNumVertices() const;
+       virtual int getNumEdges() const;
+       virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
+       virtual void getVertex(int i, btVector3& vtx) const;
+       virtual int getNumPlanes() const;
+       virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
+       virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
+
+       ///in case we receive negative scaling
+       virtual void setLocalScaling(const btVector3& scaling);
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+// clang-format off
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btConvexHullShapeData
+{
+       btConvexInternalShapeData       m_convexInternalShapeData;
+
+       btVector3FloatData      *m_unscaledPointsFloatPtr;
+       btVector3DoubleData     *m_unscaledPointsDoublePtr;
+
+       int             m_numUnscaledPoints;
+       char m_padding3[4];
+
+};
+
+// clang-format on
+
+SIMD_FORCE_INLINE int btConvexHullShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btConvexHullShapeData);
+}
+
+#endif  //BT_CONVEX_HULL_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
new file mode 100644 (file)
index 0000000..4d598b1
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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.absolute();
+}
+
+void btConvexInternalShape::getAabbSlow(const btTransform& trans, btVector3& minAabb, btVector3& maxAabb) const
+{
+#ifndef __SPU__
+       //use localGetSupportingVertexWithoutMargin?
+       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;
+       }
+#endif
+}
+
+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
+       btAssert(0);
+       return btVector3(0, 0, 0);
+#endif  //__SPU__
+}
+
+btConvexInternalAabbCachingShape::btConvexInternalAabbCachingShape()
+       : btConvexInternalShape(),
+         m_localAabbMin(1, 1, 1),
+         m_localAabbMax(-1, -1, -1),
+         m_isLocalAabbValid(false)
+{
+}
+
+void btConvexInternalAabbCachingShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       getNonvirtualAabb(trans, aabbMin, aabbMax, getMargin());
+}
+
+void btConvexInternalAabbCachingShape::setLocalScaling(const btVector3& scaling)
+{
+       btConvexInternalShape::setLocalScaling(scaling);
+       recalcLocalAabb();
+}
+
+void btConvexInternalAabbCachingShape::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++)
+       {
+               btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
+               vec[i] = btScalar(1.);
+               btVector3 tmp = localGetSupportingVertex(vec);
+               m_localAabbMax[i] = tmp[i] + m_collisionMargin;
+               vec[i] = btScalar(-1.);
+               tmp = localGetSupportingVertex(vec);
+               m_localAabbMin[i] = tmp[i] - m_collisionMargin;
+       }
+#endif
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
new file mode 100644 (file)
index 0000000..a28c57d
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_INTERNAL_SHAPE_H
+#define BT_CONVEX_INTERNAL_SHAPE_H
+
+#include "btConvexShape.h"
+#include "LinearMath/btAabbUtil2.h"
+
+///The btConvexInternalShape is an internal base class, shared by most convex shape implementations.
+///The btConvexInternalShape uses a default collision margin set to CONVEX_DISTANCE_MARGIN.
+///This collision margin used by Gjk and some other algorithms, see also btCollisionMargin.h
+///Note that when creating small shapes (derived from btConvexInternalShape),
+///you need to make sure to set a smaller collision margin, using the 'setMargin' API
+///There is a automatic mechanism 'setSafeMargin' used by btBoxShape and btCylinderShape
+ATTRIBUTE_ALIGNED16(class)
+btConvexInternalShape : public btConvexShape
+{
+protected:
+       //local scaling. collisionMargin is not scaled !
+       btVector3 m_localScaling;
+
+       btVector3 m_implicitShapeDimensions;
+
+       btScalar m_collisionMargin;
+
+       btScalar m_padding;
+
+       btConvexInternalShape();
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       virtual ~btConvexInternalShape()
+       {
+       }
+
+       virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+
+       const btVector3& getImplicitShapeDimensions() const
+       {
+               return m_implicitShapeDimensions;
+       }
+
+       ///warning: use setImplicitShapeDimensions with care
+       ///changing a collision shape while the body is in the world is not recommended,
+       ///it is best to remove the body from the world, then make the change, and re-add it
+       ///alternatively flush the contact points, see documentation for 'cleanProxyFromPairs'
+       void setImplicitShapeDimensions(const btVector3& dimensions)
+       {
+               m_implicitShapeDimensions = dimensions;
+       }
+
+       void setSafeMargin(btScalar minDimension, btScalar defaultMarginMultiplier = 0.1f)
+       {
+               btScalar safeMargin = defaultMarginMultiplier * minDimension;
+               if (safeMargin < getMargin())
+               {
+                       setMargin(safeMargin);
+               }
+       }
+       void setSafeMargin(const btVector3& halfExtents, btScalar defaultMarginMultiplier = 0.1f)
+       {
+               //see http://code.google.com/p/bullet/issues/detail?id=349
+               //this margin check could could be added to other collision shapes too,
+               //or add some assert/warning somewhere
+               btScalar minDimension = halfExtents[halfExtents.minAxis()];
+               setSafeMargin(minDimension, defaultMarginMultiplier);
+       }
+
+       ///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);
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btConvexInternalShapeData
+{
+       btCollisionShapeData m_collisionShapeData;
+
+       btVector3FloatData m_localScaling;
+
+       btVector3FloatData m_implicitShapeDimensions;
+
+       float m_collisionMargin;
+
+       int m_padding;
+};
+
+SIMD_FORCE_INLINE int btConvexInternalShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btConvexInternalShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btConvexInternalShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btConvexInternalShapeData* shapeData = (btConvexInternalShapeData*)dataBuffer;
+       btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
+
+       m_implicitShapeDimensions.serializeFloat(shapeData->m_implicitShapeDimensions);
+       m_localScaling.serializeFloat(shapeData->m_localScaling);
+       shapeData->m_collisionMargin = float(m_collisionMargin);
+
+       // Fill padding with zeros to appease msan.
+       shapeData->m_padding = 0;
+
+       return "btConvexInternalShapeData";
+}
+
+///btConvexInternalAabbCachingShape adds local aabb caching for convex shapes, to avoid expensive bounding box calculations
+class btConvexInternalAabbCachingShape : public btConvexInternalShape
+{
+       btVector3 m_localAabbMin;
+       btVector3 m_localAabbMax;
+       bool m_isLocalAabbValid;
+
+protected:
+       btConvexInternalAabbCachingShape();
+
+       void setCachedLocalAabb(const btVector3& aabbMin, const btVector3& aabbMax)
+       {
+               m_isLocalAabbValid = true;
+               m_localAabbMin = aabbMin;
+               m_localAabbMax = aabbMax;
+       }
+
+       inline void getCachedLocalAabb(btVector3& aabbMin, btVector3& aabbMax) const
+       {
+               btAssert(m_isLocalAabbValid);
+               aabbMin = m_localAabbMin;
+               aabbMax = m_localAabbMax;
+       }
+
+       inline void getNonvirtualAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax, btScalar margin) const
+       {
+               //lazy evaluation of local aabb
+               btAssert(m_isLocalAabbValid);
+               btTransformAabb(m_localAabbMin, m_localAabbMax, margin, trans, aabbMin, aabbMax);
+       }
+
+public:
+       virtual void setLocalScaling(const btVector3& scaling);
+
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       void recalcLocalAabb();
+};
+
+#endif  //BT_CONVEX_INTERNAL_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
new file mode 100644 (file)
index 0000000..f00a440
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btConvexPointCloudShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+
+void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling)
+{
+       m_localScaling = scaling;
+       recalcLocalAabb();
+}
+
+#ifndef __SPU__
+btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
+{
+       btVector3 supVec(btScalar(0.), btScalar(0.), btScalar(0.));
+       btScalar maxDot = btScalar(-BT_LARGE_FLOAT);
+
+       btVector3 vec = vec0;
+       btScalar lenSqr = vec.length2();
+       if (lenSqr < btScalar(0.0001))
+       {
+               vec.setValue(1, 0, 0);
+       }
+       else
+       {
+               btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
+               vec *= rlen;
+       }
+
+       if (m_numPoints > 0)
+       {
+               // Here we take advantage of dot(a*b, c) = dot( a, b*c) to do less work. Note this transformation is true mathematically, not numerically.
+               //    btVector3 scaled = vec * m_localScaling;
+               int index = (int)vec.maxDot(&m_unscaledPoints[0], m_numPoints, maxDot);  //FIXME: may violate encapsulation of m_unscaledPoints
+               return getScaledPoint(index);
+       }
+
+       return supVec;
+}
+
+void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       for (int j = 0; j < numVectors; j++)
+       {
+               const btVector3& vec = vectors[j] * m_localScaling;  // dot( a*c, b) = dot(a, b*c)
+               btScalar maxDot;
+               int index = (int)vec.maxDot(&m_unscaledPoints[0], m_numPoints, maxDot);
+               supportVerticesOut[j][3] = btScalar(-BT_LARGE_FLOAT);
+               if (0 <= index)
+               {
+                       //WARNING: don't swap next lines, the w component would get overwritten!
+                       supportVerticesOut[j] = getScaledPoint(index);
+                       supportVerticesOut[j][3] = maxDot;
+               }
+       }
+}
+
+btVector3 btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec) const
+{
+       btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+       if (getMargin() != btScalar(0.))
+       {
+               btVector3 vecnorm = vec;
+               if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
+               {
+                       vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+               }
+               vecnorm.normalize();
+               supVertex += getMargin() * vecnorm;
+       }
+       return supVertex;
+}
+
+#endif
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
+int btConvexPointCloudShape::getNumVertices() const
+{
+       return m_numPoints;
+}
+
+int btConvexPointCloudShape::getNumEdges() const
+{
+       return 0;
+}
+
+void btConvexPointCloudShape::getEdge(int i, btVector3& pa, btVector3& pb) const
+{
+       btAssert(0);
+}
+
+void btConvexPointCloudShape::getVertex(int i, btVector3& vtx) const
+{
+       vtx = m_unscaledPoints[i] * m_localScaling;
+}
+
+int btConvexPointCloudShape::getNumPlanes() const
+{
+       return 0;
+}
+
+void btConvexPointCloudShape::getPlane(btVector3&, btVector3&, int) const
+{
+       btAssert(0);
+}
+
+//not yet
+bool btConvexPointCloudShape::isInside(const btVector3&, btScalar) const
+{
+       btAssert(0);
+       return false;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
new file mode 100644 (file)
index 0000000..c7d554a
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_POINT_CLOUD_SHAPE_H
+#define BT_CONVEX_POINT_CLOUD_SHAPE_H
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+
+///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices.
+ATTRIBUTE_ALIGNED16(class)
+btConvexPointCloudShape : public btPolyhedralConvexAabbCachingShape
+{
+       btVector3* m_unscaledPoints;
+       int m_numPoints;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btConvexPointCloudShape()
+       {
+               m_localScaling.setValue(1.f, 1.f, 1.f);
+               m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
+               m_unscaledPoints = 0;
+               m_numPoints = 0;
+       }
+
+       btConvexPointCloudShape(btVector3 * points, int numPoints, const btVector3& localScaling, bool computeAabb = true)
+       {
+               m_localScaling = localScaling;
+               m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
+               m_unscaledPoints = points;
+               m_numPoints = numPoints;
+
+               if (computeAabb)
+                       recalcLocalAabb();
+       }
+
+       void setPoints(btVector3 * points, int numPoints, bool computeAabb = true, const btVector3& localScaling = btVector3(1.f, 1.f, 1.f))
+       {
+               m_unscaledPoints = points;
+               m_numPoints = numPoints;
+               m_localScaling = localScaling;
+
+               if (computeAabb)
+                       recalcLocalAabb();
+       }
+
+       SIMD_FORCE_INLINE btVector3* getUnscaledPoints()
+       {
+               return m_unscaledPoints;
+       }
+
+       SIMD_FORCE_INLINE const btVector3* getUnscaledPoints() const
+       {
+               return m_unscaledPoints;
+       }
+
+       SIMD_FORCE_INLINE int getNumPoints() const
+       {
+               return m_numPoints;
+       }
+
+       SIMD_FORCE_INLINE btVector3 getScaledPoint(int index) const
+       {
+               return m_unscaledPoints[index] * m_localScaling;
+       }
+
+#ifndef __SPU__
+       virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+#endif
+
+       //debugging
+       virtual const char* getName() const { return "ConvexPointCloud"; }
+
+       virtual int getNumVertices() const;
+       virtual int getNumEdges() const;
+       virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
+       virtual void getVertex(int i, btVector3& vtx) const;
+       virtual int getNumPlanes() const;
+       virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
+       virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
+
+       ///in case we receive negative scaling
+       virtual void setLocalScaling(const btVector3& scaling);
+};
+
+#endif  //BT_CONVEX_POINT_CLOUD_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
new file mode 100644 (file)
index 0000000..9694f4d
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+///Separating axis rest based on work from Pierre Terdiman, see
+///And contact clipping based on work from Simon Hobbs
+
+#include "btConvexPolyhedron.h"
+#include "LinearMath/btHashMap.h"
+
+btConvexPolyhedron::btConvexPolyhedron()
+{
+}
+btConvexPolyhedron::~btConvexPolyhedron()
+{
+}
+
+inline bool IsAlmostZero1(const btVector3& v)
+{
+       if (btFabs(v.x()) > 1e-6 || btFabs(v.y()) > 1e-6 || btFabs(v.z()) > 1e-6) return false;
+       return true;
+}
+
+struct btInternalVertexPair
+{
+       btInternalVertexPair(short int v0, short int v1)
+               : m_v0(v0),
+                 m_v1(v1)
+       {
+               if (m_v1 > m_v0)
+                       btSwap(m_v0, m_v1);
+       }
+       short int m_v0;
+       short int m_v1;
+       int getHash() const
+       {
+               return m_v0 + (m_v1 << 16);
+       }
+       bool equals(const btInternalVertexPair& other) const
+       {
+               return m_v0 == other.m_v0 && m_v1 == other.m_v1;
+       }
+};
+
+struct btInternalEdge
+{
+       btInternalEdge()
+               : m_face0(-1),
+                 m_face1(-1)
+       {
+       }
+       short int m_face0;
+       short int m_face1;
+};
+
+//
+
+#ifdef TEST_INTERNAL_OBJECTS
+bool btConvexPolyhedron::testContainment() const
+{
+       for (int p = 0; p < 8; p++)
+       {
+               btVector3 LocalPt;
+               if (p == 0)
+                       LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]);
+               else if (p == 1)
+                       LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]);
+               else if (p == 2)
+                       LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]);
+               else if (p == 3)
+                       LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]);
+               else if (p == 4)
+                       LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]);
+               else if (p == 5)
+                       LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]);
+               else if (p == 6)
+                       LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]);
+               else if (p == 7)
+                       LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]);
+
+               for (int i = 0; i < m_faces.size(); i++)
+               {
+                       const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
+                       const btScalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3];
+                       if (d > 0.0f)
+                               return false;
+               }
+       }
+       return true;
+}
+#endif
+
+void btConvexPolyhedron::initialize()
+{
+       btHashMap<btInternalVertexPair, btInternalEdge> edges;
+
+       for (int i = 0; i < m_faces.size(); i++)
+       {
+               int numVertices = m_faces[i].m_indices.size();
+               int NbTris = numVertices;
+               for (int j = 0; j < NbTris; j++)
+               {
+                       int k = (j + 1) % numVertices;
+                       btInternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
+                       btInternalEdge* edptr = edges.find(vp);
+                       btVector3 edge = m_vertices[vp.m_v1] - m_vertices[vp.m_v0];
+                       edge.normalize();
+
+                       bool found = false;
+
+                       for (int p = 0; p < m_uniqueEdges.size(); p++)
+                       {
+                               if (IsAlmostZero1(m_uniqueEdges[p] - edge) ||
+                                       IsAlmostZero1(m_uniqueEdges[p] + edge))
+                               {
+                                       found = true;
+                                       break;
+                               }
+                       }
+
+                       if (!found)
+                       {
+                               m_uniqueEdges.push_back(edge);
+                       }
+
+                       if (edptr)
+                       {
+                               btAssert(edptr->m_face0 >= 0);
+                               btAssert(edptr->m_face1 < 0);
+                               edptr->m_face1 = i;
+                       }
+                       else
+                       {
+                               btInternalEdge ed;
+                               ed.m_face0 = i;
+                               edges.insert(vp, ed);
+                       }
+               }
+       }
+
+#ifdef USE_CONNECTED_FACES
+       for (int i = 0; i < m_faces.size(); i++)
+       {
+               int numVertices = m_faces[i].m_indices.size();
+               m_faces[i].m_connectedFaces.resize(numVertices);
+
+               for (int j = 0; j < numVertices; j++)
+               {
+                       int k = (j + 1) % numVertices;
+                       btInternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
+                       btInternalEdge* edptr = edges.find(vp);
+                       btAssert(edptr);
+                       btAssert(edptr->m_face0 >= 0);
+                       btAssert(edptr->m_face1 >= 0);
+
+                       int connectedFace = (edptr->m_face0 == i) ? edptr->m_face1 : edptr->m_face0;
+                       m_faces[i].m_connectedFaces[j] = connectedFace;
+               }
+       }
+#endif  //USE_CONNECTED_FACES
+
+       initialize2();
+}
+
+void btConvexPolyhedron::initialize2()
+{
+       m_localCenter.setValue(0, 0, 0);
+       btScalar TotalArea = 0.0f;
+       for (int i = 0; i < m_faces.size(); i++)
+       {
+               int numVertices = m_faces[i].m_indices.size();
+               int NbTris = numVertices - 2;
+
+               const btVector3& p0 = m_vertices[m_faces[i].m_indices[0]];
+               for (int j = 1; j <= NbTris; j++)
+               {
+                       int k = (j + 1) % numVertices;
+                       const btVector3& p1 = m_vertices[m_faces[i].m_indices[j]];
+                       const btVector3& p2 = m_vertices[m_faces[i].m_indices[k]];
+                       btScalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
+                       btVector3 Center = (p0 + p1 + p2) / 3.0f;
+                       m_localCenter += Area * Center;
+                       TotalArea += Area;
+               }
+       }
+       m_localCenter /= TotalArea;
+
+#ifdef TEST_INTERNAL_OBJECTS
+       if (1)
+       {
+               m_radius = FLT_MAX;
+               for (int i = 0; i < m_faces.size(); i++)
+               {
+                       const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
+                       const btScalar dist = btFabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]);
+                       if (dist < m_radius)
+                               m_radius = dist;
+               }
+
+               btScalar MinX = FLT_MAX;
+               btScalar MinY = FLT_MAX;
+               btScalar MinZ = FLT_MAX;
+               btScalar MaxX = -FLT_MAX;
+               btScalar MaxY = -FLT_MAX;
+               btScalar MaxZ = -FLT_MAX;
+               for (int i = 0; i < m_vertices.size(); i++)
+               {
+                       const btVector3& pt = m_vertices[i];
+                       if (pt.x() < MinX) MinX = pt.x();
+                       if (pt.x() > MaxX) MaxX = pt.x();
+                       if (pt.y() < MinY) MinY = pt.y();
+                       if (pt.y() > MaxY) MaxY = pt.y();
+                       if (pt.z() < MinZ) MinZ = pt.z();
+                       if (pt.z() > MaxZ) MaxZ = pt.z();
+               }
+               mC.setValue(MaxX + MinX, MaxY + MinY, MaxZ + MinZ);
+               mE.setValue(MaxX - MinX, MaxY - MinY, MaxZ - MinZ);
+
+               //              const btScalar r = m_radius / sqrtf(2.0f);
+               const btScalar r = m_radius / sqrtf(3.0f);
+               const int LargestExtent = mE.maxAxis();
+               const btScalar Step = (mE[LargestExtent] * 0.5f - r) / 1024.0f;
+               m_extents[0] = m_extents[1] = m_extents[2] = r;
+               m_extents[LargestExtent] = mE[LargestExtent] * 0.5f;
+               bool FoundBox = false;
+               for (int j = 0; j < 1024; j++)
+               {
+                       if (testContainment())
+                       {
+                               FoundBox = true;
+                               break;
+                       }
+
+                       m_extents[LargestExtent] -= Step;
+               }
+               if (!FoundBox)
+               {
+                       m_extents[0] = m_extents[1] = m_extents[2] = r;
+               }
+               else
+               {
+                       // Refine the box
+                       const btScalar Step = (m_radius - r) / 1024.0f;
+                       const int e0 = (1 << LargestExtent) & 3;
+                       const int e1 = (1 << e0) & 3;
+
+                       for (int j = 0; j < 1024; j++)
+                       {
+                               const btScalar Saved0 = m_extents[e0];
+                               const btScalar Saved1 = m_extents[e1];
+                               m_extents[e0] += Step;
+                               m_extents[e1] += Step;
+
+                               if (!testContainment())
+                               {
+                                       m_extents[e0] = Saved0;
+                                       m_extents[e1] = Saved1;
+                                       break;
+                               }
+                       }
+               }
+       }
+#endif
+}
+void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const
+{
+       minProj = FLT_MAX;
+       maxProj = -FLT_MAX;
+       int numVerts = m_vertices.size();
+       for (int i = 0; i < numVerts; i++)
+       {
+               btVector3 pt = trans * m_vertices[i];
+               btScalar dp = pt.dot(dir);
+               if (dp < minProj)
+               {
+                       minProj = dp;
+                       witnesPtMin = pt;
+               }
+               if (dp > maxProj)
+               {
+                       maxProj = dp;
+                       witnesPtMax = pt;
+               }
+       }
+       if (minProj > maxProj)
+       {
+               btSwap(minProj, maxProj);
+               btSwap(witnesPtMin, witnesPtMax);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h
new file mode 100644 (file)
index 0000000..638aa9b
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#ifndef _BT_POLYHEDRAL_FEATURES_H
+#define _BT_POLYHEDRAL_FEATURES_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+#define TEST_INTERNAL_OBJECTS 1
+
+struct btFace
+{
+       btAlignedObjectArray<int> m_indices;
+       //      btAlignedObjectArray<int>       m_connectedFaces;
+       btScalar m_plane[4];
+};
+
+ATTRIBUTE_ALIGNED16(class)
+btConvexPolyhedron
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btConvexPolyhedron();
+       virtual ~btConvexPolyhedron();
+
+       btAlignedObjectArray<btVector3> m_vertices;
+       btAlignedObjectArray<btFace> m_faces;
+       btAlignedObjectArray<btVector3> m_uniqueEdges;
+
+       btVector3 m_localCenter;
+       btVector3 m_extents;
+       btScalar m_radius;
+       btVector3 mC;
+       btVector3 mE;
+
+       void initialize();
+       void initialize2();
+       bool testContainment() const;
+
+       void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const;
+};
+
+#endif  //_BT_POLYHEDRAL_FEATURES_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexShape.cpp
new file mode 100644 (file)
index 0000000..f8fb0aa
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#if defined(_WIN32) || defined(__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+#include "btConvexShape.h"
+#include "btTriangleShape.h"
+#include "btSphereShape.h"
+#include "btCylinderShape.h"
+#include "btConeShape.h"
+#include "btCapsuleShape.h"
+#include "btConvexHullShape.h"
+#include "btConvexPointCloudShape.h"
+
+///not supported on IBM SDK, until we fix the alignment of btVector3
+#if defined(__CELLOS_LV2__) && defined(__SPU__)
+#include <spu_intrinsics.h>
+static inline vec_float4 vec_dot3(vec_float4 vec0, vec_float4 vec1)
+{
+       vec_float4 result;
+       result = spu_mul(vec0, vec1);
+       result = spu_madd(spu_rlqwbyte(vec0, 4), spu_rlqwbyte(vec1, 4), result);
+       return spu_madd(spu_rlqwbyte(vec0, 8), spu_rlqwbyte(vec1, 8), result);
+}
+#endif  //__SPU__
+
+btConvexShape::btConvexShape()
+{
+}
+
+btConvexShape::~btConvexShape()
+{
+}
+
+void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max, btVector3& witnesPtMin, btVector3& witnesPtMax) const
+{
+       btVector3 localAxis = dir * trans.getBasis();
+       btVector3 vtx1 = trans(localGetSupportingVertex(localAxis));
+       btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis));
+
+       min = vtx1.dot(dir);
+       max = vtx2.dot(dir);
+       witnesPtMax = vtx2;
+       witnesPtMin = vtx1;
+
+       if (min > max)
+       {
+               btScalar tmp = min;
+               min = max;
+               max = tmp;
+               witnesPtMax = vtx1;
+               witnesPtMin = vtx2;
+       }
+}
+
+static btVector3 convexHullSupport(const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
+{
+       btVector3 vec = localDirOrg * localScaling;
+
+#if defined(__CELLOS_LV2__) && defined(__SPU__)
+
+       btVector3 localDir = vec;
+
+       vec_float4 v_distMax = {-FLT_MAX, 0, 0, 0};
+       vec_int4 v_idxMax = {-999, 0, 0, 0};
+       int v = 0;
+       int numverts = numPoints;
+
+       for (; v < (int)numverts - 4; v += 4)
+       {
+               vec_float4 p0 = vec_dot3(points[v].get128(), localDir.get128());
+               vec_float4 p1 = vec_dot3(points[v + 1].get128(), localDir.get128());
+               vec_float4 p2 = vec_dot3(points[v + 2].get128(), localDir.get128());
+               vec_float4 p3 = vec_dot3(points[v + 3].get128(), localDir.get128());
+               const vec_int4 i0 = {v, 0, 0, 0};
+               const vec_int4 i1 = {v + 1, 0, 0, 0};
+               const vec_int4 i2 = {v + 2, 0, 0, 0};
+               const vec_int4 i3 = {v + 3, 0, 0, 0};
+               vec_uint4 retGt01 = spu_cmpgt(p0, p1);
+               vec_float4 pmax01 = spu_sel(p1, p0, retGt01);
+               vec_int4 imax01 = spu_sel(i1, i0, retGt01);
+               vec_uint4 retGt23 = spu_cmpgt(p2, p3);
+               vec_float4 pmax23 = spu_sel(p3, p2, retGt23);
+               vec_int4 imax23 = spu_sel(i3, i2, retGt23);
+               vec_uint4 retGt0123 = spu_cmpgt(pmax01, pmax23);
+               vec_float4 pmax0123 = spu_sel(pmax23, pmax01, retGt0123);
+               vec_int4 imax0123 = spu_sel(imax23, imax01, retGt0123);
+               vec_uint4 retGtMax = spu_cmpgt(v_distMax, pmax0123);
+               v_distMax = spu_sel(pmax0123, v_distMax, retGtMax);
+               v_idxMax = spu_sel(imax0123, v_idxMax, retGtMax);
+       }
+       for (; v < (int)numverts; v++)
+       {
+               vec_float4 p = vec_dot3(points[v].get128(), localDir.get128());
+               const vec_int4 i = {v, 0, 0, 0};
+               vec_uint4 retGtMax = spu_cmpgt(v_distMax, p);
+               v_distMax = spu_sel(p, v_distMax, retGtMax);
+               v_idxMax = spu_sel(i, v_idxMax, retGtMax);
+       }
+       int ptIndex = spu_extract(v_idxMax, 0);
+       const btVector3& supVec = points[ptIndex] * localScaling;
+       return supVec;
+#else
+
+       btScalar maxDot;
+       long ptIndex = vec.maxDot(points, numPoints, maxDot);
+       btAssert(ptIndex >= 0);
+       if (ptIndex < 0)
+       {
+               ptIndex = 0;
+       }
+       btVector3 supVec = points[ptIndex] * localScaling;
+       return supVec;
+#endif  //__SPU__
+}
+
+btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual(const btVector3& localDir) const
+{
+       switch (m_shapeType)
+       {
+               case SPHERE_SHAPE_PROXYTYPE:
+               {
+                       return btVector3(0, 0, 0);
+               }
+               case BOX_SHAPE_PROXYTYPE:
+               {
+                       btBoxShape* convexShape = (btBoxShape*)this;
+                       const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
+
+#if defined(__APPLE__) && (defined(BT_USE_SSE) || defined(BT_USE_NEON))
+#if defined(BT_USE_SSE)
+                       return btVector3(_mm_xor_ps(_mm_and_ps(localDir.mVec128, (__m128){-0.0f, -0.0f, -0.0f, -0.0f}), halfExtents.mVec128));
+#elif defined(BT_USE_NEON)
+                       return btVector3((float32x4_t)(((uint32x4_t)localDir.mVec128 & (uint32x4_t){0x80000000, 0x80000000, 0x80000000, 0x80000000}) ^ (uint32x4_t)halfExtents.mVec128));
+#else
+#error unknown vector arch
+#endif
+#else
+                       return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
+                                                        btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
+                                                        btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
+#endif
+               }
+               case TRIANGLE_SHAPE_PROXYTYPE:
+               {
+                       btTriangleShape* triangleShape = (btTriangleShape*)this;
+                       btVector3 dir(localDir.getX(), localDir.getY(), localDir.getZ());
+                       btVector3* vertices = &triangleShape->m_vertices1[0];
+                       btVector3 dots = dir.dot3(vertices[0], vertices[1], vertices[2]);
+                       btVector3 sup = vertices[dots.maxAxis()];
+                       return btVector3(sup.getX(), sup.getY(), sup.getZ());
+               }
+               case CYLINDER_SHAPE_PROXYTYPE:
+               {
+                       btCylinderShape* cylShape = (btCylinderShape*)this;
+                       //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
+
+                       btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
+                       btVector3 v(localDir.getX(), localDir.getY(), localDir.getZ());
+                       int cylinderUpAxis = cylShape->getUpAxis();
+                       int XX(1), YY(0), ZZ(2);
+
+                       switch (cylinderUpAxis)
+                       {
+                               case 0:
+                               {
+                                       XX = 1;
+                                       YY = 0;
+                                       ZZ = 2;
+                               }
+                               break;
+                               case 1:
+                               {
+                                       XX = 0;
+                                       YY = 1;
+                                       ZZ = 2;
+                               }
+                               break;
+                               case 2:
+                               {
+                                       XX = 0;
+                                       YY = 2;
+                                       ZZ = 1;
+                               }
+                               break;
+                               default:
+                                       btAssert(0);
+                                       break;
+                       };
+
+                       btScalar radius = halfExtents[XX];
+                       btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+                       btVector3 tmp;
+                       btScalar d;
+
+                       btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+                       if (s != btScalar(0.0))
+                       {
+                               d = radius / s;
+                               tmp[XX] = v[XX] * d;
+                               tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+                               tmp[ZZ] = v[ZZ] * d;
+                               return btVector3(tmp.getX(), tmp.getY(), tmp.getZ());
+                       }
+                       else
+                       {
+                               tmp[XX] = radius;
+                               tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+                               tmp[ZZ] = btScalar(0.0);
+                               return btVector3(tmp.getX(), tmp.getY(), tmp.getZ());
+                       }
+               }
+               case CAPSULE_SHAPE_PROXYTYPE:
+               {
+                       btVector3 vec0(localDir.getX(), localDir.getY(), localDir.getZ());
+
+                       btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+                       btScalar halfHeight = capsuleShape->getHalfHeight();
+                       int capsuleUpAxis = capsuleShape->getUpAxis();
+
+                       btVector3 supVec(0, 0, 0);
+
+                       btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+                       btVector3 vec = vec0;
+                       btScalar lenSqr = vec.length2();
+                       if (lenSqr < SIMD_EPSILON * SIMD_EPSILON)
+                       {
+                               vec.setValue(1, 0, 0);
+                       }
+                       else
+                       {
+                               btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
+                               vec *= rlen;
+                       }
+                       btVector3 vtx;
+                       btScalar newDot;
+                       {
+                               btVector3 pos(0, 0, 0);
+                               pos[capsuleUpAxis] = halfHeight;
+
+                               vtx = pos;
+                               newDot = vec.dot(vtx);
+
+                               if (newDot > maxDot)
+                               {
+                                       maxDot = newDot;
+                                       supVec = vtx;
+                               }
+                       }
+                       {
+                               btVector3 pos(0, 0, 0);
+                               pos[capsuleUpAxis] = -halfHeight;
+
+                               vtx = pos;
+                               newDot = vec.dot(vtx);
+                               if (newDot > maxDot)
+                               {
+                                       maxDot = newDot;
+                                       supVec = vtx;
+                               }
+                       }
+                       return btVector3(supVec.getX(), supVec.getY(), supVec.getZ());
+               }
+               case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+               {
+                       btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
+                       btVector3* points = convexPointCloudShape->getUnscaledPoints();
+                       int numPoints = convexPointCloudShape->getNumPoints();
+                       return convexHullSupport(localDir, points, numPoints, convexPointCloudShape->getLocalScalingNV());
+               }
+               case CONVEX_HULL_SHAPE_PROXYTYPE:
+               {
+                       btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
+                       btVector3* points = convexHullShape->getUnscaledPoints();
+                       int numPoints = convexHullShape->getNumPoints();
+                       return convexHullSupport(localDir, points, numPoints, convexHullShape->getLocalScalingNV());
+               }
+               default:
+#ifndef __SPU__
+                       return this->localGetSupportingVertexWithoutMargin(localDir);
+#else
+                       btAssert(0);
+#endif
+       }
+
+       // should never reach here
+       btAssert(0);
+       return btVector3(btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
+}
+
+btVector3 btConvexShape::localGetSupportVertexNonVirtual(const btVector3& localDir) const
+{
+       btVector3 localDirNorm = localDir;
+       if (localDirNorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
+       {
+               localDirNorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+       }
+       localDirNorm.normalize();
+
+       return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm) + getMarginNonVirtual() * localDirNorm;
+}
+
+/* TODO: This should be bumped up to btCollisionShape () */
+btScalar btConvexShape::getMarginNonVirtual() const
+{
+       switch (m_shapeType)
+       {
+               case SPHERE_SHAPE_PROXYTYPE:
+               {
+                       btSphereShape* sphereShape = (btSphereShape*)this;
+                       return sphereShape->getRadius();
+               }
+               case BOX_SHAPE_PROXYTYPE:
+               {
+                       btBoxShape* convexShape = (btBoxShape*)this;
+                       return convexShape->getMarginNV();
+               }
+               case TRIANGLE_SHAPE_PROXYTYPE:
+               {
+                       btTriangleShape* triangleShape = (btTriangleShape*)this;
+                       return triangleShape->getMarginNV();
+               }
+               case CYLINDER_SHAPE_PROXYTYPE:
+               {
+                       btCylinderShape* cylShape = (btCylinderShape*)this;
+                       return cylShape->getMarginNV();
+               }
+               case CONE_SHAPE_PROXYTYPE:
+               {
+                       btConeShape* conShape = (btConeShape*)this;
+                       return conShape->getMarginNV();
+               }
+               case CAPSULE_SHAPE_PROXYTYPE:
+               {
+                       btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+                       return capsuleShape->getMarginNV();
+               }
+               case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+               /* fall through */
+               case CONVEX_HULL_SHAPE_PROXYTYPE:
+               {
+                       btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
+                       return convexHullShape->getMarginNV();
+               }
+               default:
+#ifndef __SPU__
+                       return this->getMargin();
+#else
+                       btAssert(0);
+#endif
+       }
+
+       // should never reach here
+       btAssert(0);
+       return btScalar(0.0f);
+}
+#ifndef __SPU__
+void btConvexShape::getAabbNonVirtual(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       switch (m_shapeType)
+       {
+               case SPHERE_SHAPE_PROXYTYPE:
+               {
+                       btSphereShape* sphereShape = (btSphereShape*)this;
+                       btScalar radius = sphereShape->getImplicitShapeDimensions().getX();  // * convexShape->getLocalScaling().getX();
+                       btScalar margin = radius + sphereShape->getMarginNonVirtual();
+                       const btVector3& center = t.getOrigin();
+                       btVector3 extent(margin, margin, margin);
+                       aabbMin = center - extent;
+                       aabbMax = center + extent;
+               }
+               break;
+               case CYLINDER_SHAPE_PROXYTYPE:
+               /* fall through */
+               case BOX_SHAPE_PROXYTYPE:
+               {
+                       btBoxShape* convexShape = (btBoxShape*)this;
+                       btScalar margin = convexShape->getMarginNonVirtual();
+                       btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
+                       halfExtents += btVector3(margin, margin, margin);
+                       btMatrix3x3 abs_b = t.getBasis().absolute();
+                       btVector3 center = t.getOrigin();
+                       btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+
+                       aabbMin = center - extent;
+                       aabbMax = center + extent;
+                       break;
+               }
+               case TRIANGLE_SHAPE_PROXYTYPE:
+               {
+                       btTriangleShape* triangleShape = (btTriangleShape*)this;
+                       btScalar margin = triangleShape->getMarginNonVirtual();
+                       for (int i = 0; i < 3; i++)
+                       {
+                               btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
+                               vec[i] = btScalar(1.);
+
+                               btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec * t.getBasis());
+
+                               btVector3 tmp = t(sv);
+                               aabbMax[i] = tmp[i] + margin;
+                               vec[i] = btScalar(-1.);
+                               tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec * t.getBasis()));
+                               aabbMin[i] = tmp[i] - margin;
+                       }
+               }
+               break;
+               case CAPSULE_SHAPE_PROXYTYPE:
+               {
+                       btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+                       btVector3 halfExtents(capsuleShape->getRadius(), capsuleShape->getRadius(), capsuleShape->getRadius());
+                       int m_upAxis = capsuleShape->getUpAxis();
+                       halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
+                       btMatrix3x3 abs_b = t.getBasis().absolute();
+                       btVector3 center = t.getOrigin();
+                       btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+                       aabbMin = center - extent;
+                       aabbMax = center + extent;
+               }
+               break;
+               case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+               case CONVEX_HULL_SHAPE_PROXYTYPE:
+               {
+                       btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this;
+                       btScalar margin = convexHullShape->getMarginNonVirtual();
+                       convexHullShape->getNonvirtualAabb(t, aabbMin, aabbMax, margin);
+               }
+               break;
+               default:
+#ifndef __SPU__
+                       this->getAabb(t, aabbMin, aabbMax);
+#else
+                       btAssert(0);
+#endif
+                       break;
+       }
+
+       // should never reach here
+       btAssert(0);
+}
+
+#endif  //__SPU__
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexShape.h
new file mode 100644 (file)
index 0000000..d3b3ed8
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_SHAPE_INTERFACE1
+#define BT_CONVEX_SHAPE_INTERFACE1
+
+#include "btCollisionShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10
+
+/// 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
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btConvexShape();
+
+       virtual ~btConvexShape();
+
+       virtual btVector3 localGetSupportingVertex(const btVector3& vec) const = 0;
+
+////////
+#ifndef __SPU__
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const = 0;
+#endif  //#ifndef __SPU__
+
+       btVector3 localGetSupportVertexWithoutMarginNonVirtual(const btVector3& vec) const;
+       btVector3 localGetSupportVertexNonVirtual(const btVector3& vec) const;
+       btScalar getMarginNonVirtual() const;
+       void getAabbNonVirtual(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const;
+
+       //notice that the vectors should be unit length
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const = 0;
+
+       ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+       void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const = 0;
+
+       virtual void getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const = 0;
+
+       virtual void setLocalScaling(const btVector3& scaling) = 0;
+       virtual const btVector3& getLocalScaling() const = 0;
+
+       virtual void setMargin(btScalar margin) = 0;
+
+       virtual btScalar getMargin() const = 0;
+
+       virtual int getNumPreferredPenetrationDirections() const = 0;
+
+       virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const = 0;
+};
+
+#endif  //BT_CONVEX_SHAPE_INTERFACE1
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
new file mode 100644 (file)
index 0000000..f6987cc
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
+
+btConvexTriangleMeshShape ::btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb)
+       : btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface)
+{
+       m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE;
+       if (calcAabb)
+               recalcLocalAabb();
+}
+
+///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
+///but then we are duplicating
+class LocalSupportVertexCallback : public btInternalTriangleIndexCallback
+{
+       btVector3 m_supportVertexLocal;
+
+public:
+       btScalar m_maxDot;
+       btVector3 m_supportVecLocal;
+
+       LocalSupportVertexCallback(const btVector3& supportVecLocal)
+               : m_supportVertexLocal(btScalar(0.), btScalar(0.), btScalar(0.)),
+                 m_maxDot(btScalar(-BT_LARGE_FLOAT)),
+                 m_supportVecLocal(supportVecLocal)
+       {
+       }
+
+       virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+       {
+               (void)triangleIndex;
+               (void)partId;
+
+               for (int i = 0; i < 3; i++)
+               {
+                       btScalar dot = m_supportVecLocal.dot(triangle[i]);
+                       if (dot > m_maxDot)
+                       {
+                               m_maxDot = dot;
+                               m_supportVertexLocal = triangle[i];
+                       }
+               }
+       }
+
+       btVector3 GetSupportVertexLocal()
+       {
+               return m_supportVertexLocal;
+       }
+};
+
+btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
+{
+       btVector3 supVec(btScalar(0.), btScalar(0.), btScalar(0.));
+
+       btVector3 vec = vec0;
+       btScalar lenSqr = vec.length2();
+       if (lenSqr < btScalar(0.0001))
+       {
+               vec.setValue(1, 0, 0);
+       }
+       else
+       {
+               btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
+               vec *= rlen;
+       }
+
+       LocalSupportVertexCallback supportCallback(vec);
+       btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+       m_stridingMesh->InternalProcessAllTriangles(&supportCallback, -aabbMax, aabbMax);
+       supVec = supportCallback.GetSupportVertexLocal();
+
+       return supVec;
+}
+
+void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       //use 'w' component of supportVerticesOut?
+       {
+               for (int i = 0; i < numVectors; i++)
+               {
+                       supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+               }
+       }
+
+       ///@todo: could do the batch inside the callback!
+
+       for (int j = 0; j < numVectors; j++)
+       {
+               const btVector3& vec = vectors[j];
+               LocalSupportVertexCallback supportCallback(vec);
+               btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+               m_stridingMesh->InternalProcessAllTriangles(&supportCallback, -aabbMax, aabbMax);
+               supportVerticesOut[j] = supportCallback.GetSupportVertexLocal();
+       }
+}
+
+btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const
+{
+       btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+       if (getMargin() != btScalar(0.))
+       {
+               btVector3 vecnorm = vec;
+               if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
+               {
+                       vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
+               }
+               vecnorm.normalize();
+               supVertex += getMargin() * vecnorm;
+       }
+       return supVertex;
+}
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
+int btConvexTriangleMeshShape::getNumVertices() const
+{
+       //cache this?
+       return 0;
+}
+
+int btConvexTriangleMeshShape::getNumEdges() const
+{
+       return 0;
+}
+
+void btConvexTriangleMeshShape::getEdge(int, btVector3&, btVector3&) const
+{
+       btAssert(0);
+}
+
+void btConvexTriangleMeshShape::getVertex(int, btVector3&) const
+{
+       btAssert(0);
+}
+
+int btConvexTriangleMeshShape::getNumPlanes() const
+{
+       return 0;
+}
+
+void btConvexTriangleMeshShape::getPlane(btVector3&, btVector3&, int) const
+{
+       btAssert(0);
+}
+
+//not yet
+bool btConvexTriangleMeshShape::isInside(const btVector3&, btScalar) const
+{
+       btAssert(0);
+       return false;
+}
+
+void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+       m_stridingMesh->setScaling(scaling);
+
+       recalcLocalAabb();
+}
+
+const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
+{
+       return m_stridingMesh->getScaling();
+}
+
+void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
+{
+       class CenterCallback : public btInternalTriangleIndexCallback
+       {
+               bool first;
+               btVector3 ref;
+               btVector3 sum;
+               btScalar volume;
+
+       public:
+               CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
+               {
+               }
+
+               virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+               {
+                       (void)triangleIndex;
+                       (void)partId;
+                       if (first)
+                       {
+                               ref = triangle[0];
+                               first = false;
+                       }
+                       else
+                       {
+                               btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
+                               sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
+                               volume += vol;
+                       }
+               }
+
+               btVector3 getCenter()
+               {
+                       return (volume > 0) ? sum / volume : ref;
+               }
+
+               btScalar getVolume()
+               {
+                       return volume * btScalar(1. / 6);
+               }
+       };
+
+       class InertiaCallback : public btInternalTriangleIndexCallback
+       {
+               btMatrix3x3 sum;
+               btVector3 center;
+
+       public:
+               InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
+               {
+               }
+
+               virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+               {
+                       (void)triangleIndex;
+                       (void)partId;
+                       btMatrix3x3 i;
+                       btVector3 a = triangle[0] - center;
+                       btVector3 b = triangle[1] - center;
+                       btVector3 c = triangle[2] - center;
+                       btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
+                       for (int j = 0; j < 3; j++)
+                       {
+                               for (int k = 0; k <= j; k++)
+                               {
+                                       i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
+                               }
+                       }
+                       btScalar i00 = -i[0][0];
+                       btScalar i11 = -i[1][1];
+                       btScalar i22 = -i[2][2];
+                       i[0][0] = i11 + i22;
+                       i[1][1] = i22 + i00;
+                       i[2][2] = i00 + i11;
+                       sum[0] += i[0];
+                       sum[1] += i[1];
+                       sum[2] += i[2];
+               }
+
+               btMatrix3x3& getInertia()
+               {
+                       return sum;
+               }
+       };
+
+       CenterCallback centerCallback;
+       btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+       m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
+       btVector3 center = centerCallback.getCenter();
+       principal.setOrigin(center);
+       volume = centerCallback.getVolume();
+
+       InertiaCallback inertiaCallback(center);
+       m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
+
+       btMatrix3x3& i = inertiaCallback.getInertia();
+       i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
+       inertia.setValue(i[0][0], i[1][1], i[2][2]);
+       inertia /= volume;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
new file mode 100644 (file)
index 0000000..6dac9ff
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_TRIANGLEMESH_SHAPE_H
+#define BT_CONVEX_TRIANGLEMESH_SHAPE_H
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+
+/// 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.
+ATTRIBUTE_ALIGNED16(class)
+btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape
+{
+       class btStridingMeshInterface* m_stridingMesh;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btConvexTriangleMeshShape(btStridingMeshInterface * meshInterface, bool calcAabb = true);
+
+       class btStridingMeshInterface* getMeshInterface()
+       {
+               return m_stridingMesh;
+       }
+       const class btStridingMeshInterface* getMeshInterface() const
+       {
+               return m_stridingMesh;
+       }
+
+       virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+       //debugging
+       virtual const char* getName() const { return "ConvexTrimesh"; }
+
+       virtual int getNumVertices() const;
+       virtual int getNumEdges() const;
+       virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
+       virtual void getVertex(int i, btVector3& vtx) const;
+       virtual int getNumPlanes() const;
+       virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
+       virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
+
+       virtual void setLocalScaling(const btVector3& scaling);
+       virtual const btVector3& getLocalScaling() const;
+
+       ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
+       ///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia"
+       ///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the
+       ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
+       ///of the collision object by the principal transform. This method also computes the volume of the convex mesh.
+       void calculatePrincipalAxisTransform(btTransform & principal, btVector3 & inertia, btScalar & volume) const;
+};
+
+#endif  //BT_CONVEX_TRIANGLEMESH_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCylinderShape.cpp
new file mode 100644 (file)
index 0000000..66dbb8e
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCylinderShape.h"
+
+btCylinderShape::btCylinderShape(const btVector3& halfExtents)
+       : btConvexInternalShape(),
+         m_upAxis(1)
+{
+       btVector3 margin(getMargin(), getMargin(), getMargin());
+       m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin;
+
+       setSafeMargin(halfExtents);
+
+       m_shapeType = CYLINDER_SHAPE_PROXYTYPE;
+}
+
+btCylinderShapeX::btCylinderShapeX(const btVector3& halfExtents)
+       : btCylinderShape(halfExtents)
+{
+       m_upAxis = 0;
+}
+
+btCylinderShapeZ::btCylinderShapeZ(const btVector3& halfExtents)
+       : btCylinderShape(halfExtents)
+{
+       m_upAxis = 2;
+}
+
+void btCylinderShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
+}
+
+void btCylinderShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+//Until Bullet 2.77 a box approximation was used, so uncomment this if you need backwards compatibility
+//#define USE_BOX_INERTIA_APPROXIMATION 1
+#ifndef USE_BOX_INERTIA_APPROXIMATION
+
+       /*
+       cylinder is defined as following:
+       *
+       * - principle axis aligned along y by default, radius in x, z-value not used
+       * - for btCylinderShapeX: principle axis aligned along x, radius in y direction, z-value not used
+       * - for btCylinderShapeZ: principle axis aligned along z, radius in x direction, y-value not used
+       *
+       */
+
+       btScalar radius2;                                    // square of cylinder radius
+       btScalar height2;                                    // square of cylinder height
+       btVector3 halfExtents = getHalfExtentsWithMargin();  // get cylinder dimension
+       btScalar div12 = mass / 12.f;
+       btScalar div4 = mass / 4.f;
+       btScalar div2 = mass / 2.f;
+       int idxRadius, idxHeight;
+
+       switch (m_upAxis)  // get indices of radius and height of cylinder
+       {
+               case 0:  // cylinder is aligned along x
+                       idxRadius = 1;
+                       idxHeight = 0;
+                       break;
+               case 2:  // cylinder is aligned along z
+                       idxRadius = 0;
+                       idxHeight = 2;
+                       break;
+               default:  // cylinder is aligned along y
+                       idxRadius = 0;
+                       idxHeight = 1;
+       }
+
+       // calculate squares
+       radius2 = halfExtents[idxRadius] * halfExtents[idxRadius];
+       height2 = btScalar(4.) * halfExtents[idxHeight] * halfExtents[idxHeight];
+
+       // calculate tensor terms
+       btScalar t1 = div12 * height2 + div4 * radius2;
+       btScalar t2 = div2 * radius2;
+
+       switch (m_upAxis)  // set diagonal elements of inertia tensor
+       {
+               case 0:  // cylinder is aligned along x
+                       inertia.setValue(t2, t1, t1);
+                       break;
+               case 2:  // cylinder is aligned along z
+                       inertia.setValue(t1, t1, t2);
+                       break;
+               default:  // cylinder is aligned along y
+                       inertia.setValue(t1, t2, t1);
+       }
+#else   //USE_BOX_INERTIA_APPROXIMATION
+       //approximation of box shape
+       btVector3 halfExtents = getHalfExtentsWithMargin();
+
+       btScalar lx = btScalar(2.) * (halfExtents.x());
+       btScalar ly = btScalar(2.) * (halfExtents.y());
+       btScalar lz = btScalar(2.) * (halfExtents.z());
+
+       inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
+                                        mass / (btScalar(12.0)) * (lx * lx + lz * lz),
+                                        mass / (btScalar(12.0)) * (lx * lx + ly * ly));
+#endif  //USE_BOX_INERTIA_APPROXIMATION
+}
+
+SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents, const btVector3& v)
+{
+       const int cylinderUpAxis = 0;
+       const int XX = 1;
+       const int YY = 0;
+       const int ZZ = 2;
+
+       //mapping depends on how cylinder local orientation is
+       // extents of the cylinder is: X,Y is for radius, and Z for height
+
+       btScalar radius = halfExtents[XX];
+       btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+       btVector3 tmp;
+       btScalar d;
+
+       btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+       if (s != btScalar(0.0))
+       {
+               d = radius / s;
+               tmp[XX] = v[XX] * d;
+               tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+               tmp[ZZ] = v[ZZ] * d;
+               return tmp;
+       }
+       else
+       {
+               tmp[XX] = radius;
+               tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+               tmp[ZZ] = btScalar(0.0);
+               return tmp;
+       }
+}
+
+inline btVector3 CylinderLocalSupportY(const btVector3& halfExtents, const btVector3& v)
+{
+       const int cylinderUpAxis = 1;
+       const int XX = 0;
+       const int YY = 1;
+       const int ZZ = 2;
+
+       btScalar radius = halfExtents[XX];
+       btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+       btVector3 tmp;
+       btScalar d;
+
+       btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+       if (s != btScalar(0.0))
+       {
+               d = radius / s;
+               tmp[XX] = v[XX] * d;
+               tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+               tmp[ZZ] = v[ZZ] * d;
+               return tmp;
+       }
+       else
+       {
+               tmp[XX] = radius;
+               tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+               tmp[ZZ] = btScalar(0.0);
+               return tmp;
+       }
+}
+
+inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents, const btVector3& v)
+{
+       const int cylinderUpAxis = 2;
+       const int XX = 0;
+       const int YY = 2;
+       const int ZZ = 1;
+
+       //mapping depends on how cylinder local orientation is
+       // extents of the cylinder is: X,Y is for radius, and Z for height
+
+       btScalar radius = halfExtents[XX];
+       btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+       btVector3 tmp;
+       btScalar d;
+
+       btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+       if (s != btScalar(0.0))
+       {
+               d = radius / s;
+               tmp[XX] = v[XX] * d;
+               tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+               tmp[ZZ] = v[ZZ] * d;
+               return tmp;
+       }
+       else
+       {
+               tmp[XX] = radius;
+               tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+               tmp[ZZ] = btScalar(0.0);
+               return tmp;
+       }
+}
+
+btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+       return CylinderLocalSupportX(getHalfExtentsWithoutMargin(), vec);
+}
+
+btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+       return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(), vec);
+}
+btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+       return CylinderLocalSupportY(getHalfExtentsWithoutMargin(), vec);
+}
+
+void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       for (int i = 0; i < numVectors; i++)
+       {
+               supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtentsWithoutMargin(), vectors[i]);
+       }
+}
+
+void btCylinderShapeZ::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       for (int i = 0; i < numVectors; i++)
+       {
+               supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtentsWithoutMargin(), vectors[i]);
+       }
+}
+
+void btCylinderShapeX::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       for (int i = 0; i < numVectors; i++)
+       {
+               supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtentsWithoutMargin(), vectors[i]);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCylinderShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btCylinderShape.h
new file mode 100644 (file)
index 0000000..d3f6450
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CYLINDER_MINKOWSKI_H
+#define BT_CYLINDER_MINKOWSKI_H
+
+#include "btBoxShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+#include "LinearMath/btVector3.h"
+
+/// 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.
+ATTRIBUTE_ALIGNED16(class)
+btCylinderShape : public btConvexInternalShape
+
+{
+protected:
+       int m_upAxis;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       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
+       }
+
+       btCylinderShape(const btVector3& halfExtents);
+
+       void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+       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 btVector3 localGetSupportingVertex(const btVector3& vec) const
+       {
+               btVector3 supVertex;
+               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;
+       }
+
+       //use box inertia
+       //      virtual void    calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+       int getUpAxis() const
+       {
+               return m_upAxis;
+       }
+
+       virtual btVector3 getAnisotropicRollingFrictionDirection() const
+       {
+               btVector3 aniDir(0, 0, 0);
+               aniDir[getUpAxis()] = 1;
+               return aniDir;
+       }
+
+       virtual btScalar getRadius() const
+       {
+               return getHalfExtentsWithMargin().getX();
+       }
+
+       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;
+       }
+
+       //debugging
+       virtual const char* getName() const
+       {
+               return "CylinderY";
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+class btCylinderShapeX : public btCylinderShape
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btCylinderShapeX(const btVector3& halfExtents);
+
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+       //debugging
+       virtual const char* getName() const
+       {
+               return "CylinderX";
+       }
+
+       virtual btScalar getRadius() const
+       {
+               return getHalfExtentsWithMargin().getY();
+       }
+};
+
+class btCylinderShapeZ : public btCylinderShape
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btCylinderShapeZ(const btVector3& halfExtents);
+
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+       //debugging
+       virtual const char* getName() const
+       {
+               return "CylinderZ";
+       }
+
+       virtual btScalar getRadius() const
+       {
+               return getHalfExtentsWithMargin().getX();
+       }
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCylinderShapeData
+{
+       btConvexInternalShapeData m_convexInternalShapeData;
+
+       int m_upAxis;
+
+       char m_padding[4];
+};
+
+SIMD_FORCE_INLINE int btCylinderShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btCylinderShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btCylinderShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btCylinderShapeData* shapeData = (btCylinderShapeData*)dataBuffer;
+
+       btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+       shapeData->m_upAxis = m_upAxis;
+
+       // Fill padding with zeros to appease msan.
+       shapeData->m_padding[0] = 0;
+       shapeData->m_padding[1] = 0;
+       shapeData->m_padding[2] = 0;
+       shapeData->m_padding[3] = 0;
+
+       return "btCylinderShapeData";
+}
+
+#endif  //BT_CYLINDER_MINKOWSKI_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btEmptyShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btEmptyShape.cpp
new file mode 100644 (file)
index 0000000..4699555
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btEmptyShape.h"
+
+#include "btCollisionShape.h"
+
+btEmptyShape::btEmptyShape() : btConcaveShape()
+{
+       m_shapeType = EMPTY_SHAPE_PROXYTYPE;
+}
+
+btEmptyShape::~btEmptyShape()
+{
+}
+
+///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btEmptyShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       btVector3 margin(getMargin(), getMargin(), getMargin());
+
+       aabbMin = t.getOrigin() - margin;
+
+       aabbMax = t.getOrigin() + margin;
+}
+
+void btEmptyShape::calculateLocalInertia(btScalar, btVector3&) const
+{
+       btAssert(0);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btEmptyShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btEmptyShape.h
new file mode 100644 (file)
index 0000000..d2e2117
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_EMPTY_SHAPE_H
+#define BT_EMPTY_SHAPE_H
+
+#include "btConcaveShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+
+/// 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.
+ATTRIBUTE_ALIGNED16(class)
+btEmptyShape : public btConcaveShape
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btEmptyShape();
+
+       virtual ~btEmptyShape();
+
+       ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+       void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       virtual void setLocalScaling(const btVector3& scaling)
+       {
+               m_localScaling = scaling;
+       }
+       virtual const btVector3& getLocalScaling() const
+       {
+               return m_localScaling;
+       }
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       virtual const char* getName() const
+       {
+               return "Empty";
+       }
+
+       virtual void processAllTriangles(btTriangleCallback*, const btVector3&, const btVector3&) const
+       {
+       }
+
+protected:
+       btVector3 m_localScaling;
+};
+
+#endif  //BT_EMPTY_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
new file mode 100644 (file)
index 0000000..5b1c23d
--- /dev/null
@@ -0,0 +1,951 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btHeightfieldTerrainShape.h"
+
+#include "LinearMath/btTransformUtil.h"
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(
+       int heightStickWidth, int heightStickLength,
+       const float* heightfieldData, btScalar minHeight, btScalar maxHeight,
+       int upAxis, bool flipQuadEdges)
+       : m_userValue3(0), m_triangleInfoMap(0)
+{
+       initialize(heightStickWidth, heightStickLength, heightfieldData,
+                          /*heightScale=*/1, minHeight, maxHeight, upAxis, PHY_FLOAT,
+                          flipQuadEdges);
+}
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(
+       int heightStickWidth, int heightStickLength, const double* heightfieldData,
+       btScalar minHeight, btScalar maxHeight, int upAxis, bool flipQuadEdges)
+       : m_userValue3(0), m_triangleInfoMap(0)
+{
+       initialize(heightStickWidth, heightStickLength, heightfieldData,
+                          /*heightScale=*/1, minHeight, maxHeight, upAxis, PHY_DOUBLE,
+                          flipQuadEdges);
+}
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(
+       int heightStickWidth, int heightStickLength, const short* heightfieldData, btScalar heightScale,
+       btScalar minHeight, btScalar maxHeight, int upAxis, bool flipQuadEdges)
+       : m_userValue3(0), m_triangleInfoMap(0)
+{
+       initialize(heightStickWidth, heightStickLength, heightfieldData,
+                          heightScale, minHeight, maxHeight, upAxis, PHY_SHORT,
+                          flipQuadEdges);
+}
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(
+       int heightStickWidth, int heightStickLength, const unsigned char* heightfieldData, btScalar heightScale,
+       btScalar minHeight, btScalar maxHeight, int upAxis, bool flipQuadEdges)
+       : m_userValue3(0), m_triangleInfoMap(0)
+{
+       initialize(heightStickWidth, heightStickLength, heightfieldData,
+                          heightScale, minHeight, maxHeight, upAxis, PHY_UCHAR,
+                          flipQuadEdges);
+}
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(
+       int heightStickWidth, int heightStickLength, const void* heightfieldData,
+       btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
+       PHY_ScalarType hdt, bool flipQuadEdges)
+       :m_userValue3(0),
+       m_triangleInfoMap(0)
+{
+       // legacy constructor: Assumes PHY_FLOAT means btScalar.
+#ifdef BT_USE_DOUBLE_PRECISION
+       if (hdt == PHY_FLOAT) hdt = PHY_DOUBLE;
+#endif
+       initialize(heightStickWidth, heightStickLength, heightfieldData,
+                          heightScale, minHeight, maxHeight, upAxis, hdt,
+                          flipQuadEdges);
+}
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges)
+       :       m_userValue3(0),
+       m_triangleInfoMap(0)
+{
+       // legacy constructor: support only btScalar or unsigned char data,
+       // and min height is zero.
+       PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
+#ifdef BT_USE_DOUBLE_PRECISION
+       if (hdt == PHY_FLOAT) hdt = PHY_DOUBLE;
+#endif
+       btScalar minHeight = 0.0f;
+
+       // previously, height = uchar * maxHeight / 65535.
+       // So to preserve legacy behavior, heightScale = maxHeight / 65535
+       btScalar heightScale = maxHeight / 65535;
+
+       initialize(heightStickWidth, heightStickLength, heightfieldData,
+                          heightScale, minHeight, maxHeight, upAxis, hdt,
+                          flipQuadEdges);
+}
+
+void btHeightfieldTerrainShape::initialize(
+       int heightStickWidth, int heightStickLength, const void* heightfieldData,
+       btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
+       PHY_ScalarType hdt, bool flipQuadEdges)
+{
+       // validation
+       btAssert(heightStickWidth > 1);   // && "bad width");
+       btAssert(heightStickLength > 1);  // && "bad length");
+       btAssert(heightfieldData);        // && "null heightfield data");
+       // btAssert(heightScale) -- do we care?  Trust caller here
+       btAssert(minHeight <= maxHeight);                                    // && "bad min/max height");
+       btAssert(upAxis >= 0 && upAxis < 3);                                 // && "bad upAxis--should be in range [0,2]");
+       btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_DOUBLE || hdt != PHY_SHORT);  // && "Bad height data type enum");
+
+       // initialize member variables
+       m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
+       m_heightStickWidth = heightStickWidth;
+       m_heightStickLength = heightStickLength;
+       m_minHeight = minHeight;
+       m_maxHeight = maxHeight;
+       m_width = (btScalar)(heightStickWidth - 1);
+       m_length = (btScalar)(heightStickLength - 1);
+       m_heightScale = heightScale;
+       m_heightfieldDataUnknown = heightfieldData;
+       m_heightDataType = hdt;
+       m_flipQuadEdges = flipQuadEdges;
+       m_useDiamondSubdivision = false;
+       m_useZigzagSubdivision = false;
+       m_flipTriangleWinding = false;
+       m_upAxis = upAxis;
+       m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
+       
+       m_vboundsChunkSize = 0;
+       m_vboundsGridWidth = 0;
+       m_vboundsGridLength = 0;
+
+       // determine min/max axis-aligned bounding box (aabb) values
+       switch (m_upAxis)
+       {
+               case 0:
+               {
+                       m_localAabbMin.setValue(m_minHeight, 0, 0);
+                       m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
+                       break;
+               }
+               case 1:
+               {
+                       m_localAabbMin.setValue(0, m_minHeight, 0);
+                       m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
+                       break;
+               };
+               case 2:
+               {
+                       m_localAabbMin.setValue(0, 0, m_minHeight);
+                       m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
+                       break;
+               }
+               default:
+               {
+                       //need to get valid m_upAxis
+                       btAssert(0);  // && "Bad m_upAxis");
+               }
+       }
+
+       // remember origin (defined as exact middle of aabb)
+       m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
+}
+
+btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
+{
+       clearAccelerator();
+}
+
+void btHeightfieldTerrainShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       btVector3 halfExtents = (m_localAabbMax - m_localAabbMin) * m_localScaling * btScalar(0.5);
+
+       btVector3 localOrigin(0, 0, 0);
+       localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
+       localOrigin *= m_localScaling;
+
+       btMatrix3x3 abs_b = t.getBasis().absolute();
+       btVector3 center = t.getOrigin();
+       btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+       extent += btVector3(getMargin(), getMargin(), getMargin());
+
+       aabbMin = center - extent;
+       aabbMax = center + extent;
+}
+
+/// This returns the "raw" (user's initial) height, not the actual height.
+/// The actual height needs to be adjusted to be relative to the center
+///   of the heightfield's AABB.
+btScalar
+btHeightfieldTerrainShape::getRawHeightFieldValue(int x, int y) const
+{
+       btScalar val = 0.f;
+       switch (m_heightDataType)
+       {
+               case PHY_FLOAT:
+               {
+                       val = m_heightfieldDataFloat[(y * m_heightStickWidth) + x];
+                       break;
+               }
+
+               case PHY_DOUBLE:
+               {
+                       val = m_heightfieldDataDouble[(y * m_heightStickWidth) + x];
+                       break;
+               }
+
+               case PHY_UCHAR:
+               {
+                       unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y * m_heightStickWidth) + x];
+                       val = heightFieldValue * m_heightScale;
+                       break;
+               }
+
+               case PHY_SHORT:
+               {
+                       short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
+                       val = hfValue * m_heightScale;
+                       break;
+               }
+
+               default:
+               {
+                       btAssert(!"Bad m_heightDataType");
+               }
+       }
+
+       return val;
+}
+
+/// this returns the vertex in bullet-local coordinates
+void btHeightfieldTerrainShape::getVertex(int x, int y, btVector3& vertex) const
+{
+       btAssert(x >= 0);
+       btAssert(y >= 0);
+       btAssert(x < m_heightStickWidth);
+       btAssert(y < m_heightStickLength);
+
+       btScalar height = getRawHeightFieldValue(x, y);
+
+       switch (m_upAxis)
+       {
+               case 0:
+               {
+                       vertex.setValue(
+                               height - m_localOrigin.getX(),
+                               (-m_width / btScalar(2.0)) + x,
+                               (-m_length / btScalar(2.0)) + y);
+                       break;
+               }
+               case 1:
+               {
+                       vertex.setValue(
+                               (-m_width / btScalar(2.0)) + x,
+                               height - m_localOrigin.getY(),
+                               (-m_length / btScalar(2.0)) + y);
+                       break;
+               };
+               case 2:
+               {
+                       vertex.setValue(
+                               (-m_width / btScalar(2.0)) + x,
+                               (-m_length / btScalar(2.0)) + y,
+                               height - m_localOrigin.getZ());
+                       break;
+               }
+               default:
+               {
+                       //need to get valid m_upAxis
+                       btAssert(0);
+               }
+       }
+
+       vertex *= m_localScaling;
+}
+
+static inline int
+getQuantized(
+       btScalar x)
+{
+       if (x < 0.0)
+       {
+               return (int)(x - 0.5);
+       }
+       return (int)(x + 0.5);
+}
+
+// Equivalent to std::minmax({a, b, c}).
+// Performs at most 3 comparisons.
+static btHeightfieldTerrainShape::Range minmaxRange(btScalar a, btScalar b, btScalar c)
+{
+       if (a > b)
+       {
+               if (b > c)
+                       return btHeightfieldTerrainShape::Range(c, a);
+               else if (a > c)
+                       return btHeightfieldTerrainShape::Range(b, a);
+               else
+                       return btHeightfieldTerrainShape::Range(b, c);
+       }
+       else
+       {
+               if (a > c)
+                       return btHeightfieldTerrainShape::Range(c, b);
+               else if (b > c)
+                       return btHeightfieldTerrainShape::Range(a, b);
+               else
+                       return btHeightfieldTerrainShape::Range(a, c);
+       }
+}
+
+/// given input vector, return quantized version
+/**
+  This routine is basically determining the gridpoint indices for a given
+  input vector, answering the question: "which gridpoint is closest to the
+  provided point?".
+
+  "with clamp" means that we restrict the point to be in the heightfield's
+  axis-aligned bounding box.
+ */
+void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point, int /*isMax*/) const
+{
+       btVector3 clampedPoint(point);
+       clampedPoint.setMax(m_localAabbMin);
+       clampedPoint.setMin(m_localAabbMax);
+
+       out[0] = getQuantized(clampedPoint.getX());
+       out[1] = getQuantized(clampedPoint.getY());
+       out[2] = getQuantized(clampedPoint.getZ());
+}
+
+/// process all triangles within the provided axis-aligned bounding box
+/**
+  basic algorithm:
+    - convert input aabb to local coordinates (scale down and shift for local origin)
+    - convert input aabb to a range of heightfield grid points (quantize)
+    - iterate over all triangles in that subset of the grid
+ */
+void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+       // scale down the input aabb's so they are in local (non-scaled) coordinates
+       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]);
+
+       // account for local origin
+       localAabbMin += m_localOrigin;
+       localAabbMax += m_localOrigin;
+
+       //quantize the aabbMin and aabbMax, and adjust the start/end ranges
+       int quantizedAabbMin[3];
+       int quantizedAabbMax[3];
+       quantizeWithClamp(quantizedAabbMin, localAabbMin, 0);
+       quantizeWithClamp(quantizedAabbMax, localAabbMax, 1);
+
+       // expand the min/max quantized values
+       // this is to catch the case where the input aabb falls between grid points!
+       for (int i = 0; i < 3; ++i)
+       {
+               quantizedAabbMin[i]--;
+               quantizedAabbMax[i]++;
+       }
+
+       int startX = 0;
+       int endX = m_heightStickWidth - 1;
+       int startJ = 0;
+       int endJ = m_heightStickLength - 1;
+
+       switch (m_upAxis)
+       {
+               case 0:
+               {
+                       if (quantizedAabbMin[1] > startX)
+                               startX = quantizedAabbMin[1];
+                       if (quantizedAabbMax[1] < endX)
+                               endX = quantizedAabbMax[1];
+                       if (quantizedAabbMin[2] > startJ)
+                               startJ = quantizedAabbMin[2];
+                       if (quantizedAabbMax[2] < endJ)
+                               endJ = quantizedAabbMax[2];
+                       break;
+               }
+               case 1:
+               {
+                       if (quantizedAabbMin[0] > startX)
+                               startX = quantizedAabbMin[0];
+                       if (quantizedAabbMax[0] < endX)
+                               endX = quantizedAabbMax[0];
+                       if (quantizedAabbMin[2] > startJ)
+                               startJ = quantizedAabbMin[2];
+                       if (quantizedAabbMax[2] < endJ)
+                               endJ = quantizedAabbMax[2];
+                       break;
+               };
+               case 2:
+               {
+                       if (quantizedAabbMin[0] > startX)
+                               startX = quantizedAabbMin[0];
+                       if (quantizedAabbMax[0] < endX)
+                               endX = quantizedAabbMax[0];
+                       if (quantizedAabbMin[1] > startJ)
+                               startJ = quantizedAabbMin[1];
+                       if (quantizedAabbMax[1] < endJ)
+                               endJ = quantizedAabbMax[1];
+                       break;
+               }
+               default:
+               {
+                       //need to get valid m_upAxis
+                       btAssert(0);
+               }
+       }
+
+       // TODO If m_vboundsGrid is available, use it to determine if we really need to process this area
+       
+       const Range aabbUpRange(aabbMin[m_upAxis], aabbMax[m_upAxis]);
+       for (int j = startJ; j < endJ; j++)
+       {
+               for (int x = startX; x < endX; x++)
+               {
+                       btVector3 vertices[3];
+                       int indices[3] = { 0, 1, 2 };
+                       if (m_flipTriangleWinding)
+                       {
+                               indices[0] = 2;
+                               indices[2] = 0;
+                       }
+
+                       if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j + x) & 1)) || (m_useZigzagSubdivision && !(j & 1)))
+                       {
+                               getVertex(x, j, vertices[indices[0]]);
+                               getVertex(x, j + 1, vertices[indices[1]]);
+                               getVertex(x + 1, j + 1, vertices[indices[2]]);
+
+                               // Skip triangle processing if the triangle is out-of-AABB.
+                               Range upRange = minmaxRange(vertices[0][m_upAxis], vertices[1][m_upAxis], vertices[2][m_upAxis]);
+
+                               if (upRange.overlaps(aabbUpRange))
+                                       callback->processTriangle(vertices, 2 * x, j);
+                       
+                               // already set: getVertex(x, j, vertices[indices[0]])
+
+                               // equivalent to: getVertex(x + 1, j + 1, vertices[indices[1]]);
+                               vertices[indices[1]] = vertices[indices[2]];
+
+                               getVertex(x + 1, j, vertices[indices[2]]);
+                               upRange.min = btMin(upRange.min, vertices[indices[2]][m_upAxis]);
+                               upRange.max = btMax(upRange.max, vertices[indices[2]][m_upAxis]);
+
+                               if (upRange.overlaps(aabbUpRange))
+                                       callback->processTriangle(vertices, 2 * x + 1, j);
+                       }
+                       else
+                       {
+                               getVertex(x, j, vertices[indices[0]]);
+                               getVertex(x, j + 1, vertices[indices[1]]);
+                               getVertex(x + 1, j, vertices[indices[2]]);
+
+                               // Skip triangle processing if the triangle is out-of-AABB.
+                               Range upRange = minmaxRange(vertices[0][m_upAxis], vertices[1][m_upAxis], vertices[2][m_upAxis]);
+
+                               if (upRange.overlaps(aabbUpRange))
+                                       callback->processTriangle(vertices, 2 * x, j);
+
+                               // already set: getVertex(x, j + 1, vertices[indices[1]]);
+
+                               // equivalent to: getVertex(x + 1, j, vertices[indices[0]]);
+                               vertices[indices[0]] = vertices[indices[2]];
+
+                               getVertex(x + 1, j + 1, vertices[indices[2]]);
+                               upRange.min = btMin(upRange.min, vertices[indices[2]][m_upAxis]);
+                               upRange.max = btMax(upRange.max, vertices[indices[2]][m_upAxis]);
+
+                               if (upRange.overlaps(aabbUpRange))
+                                       callback->processTriangle(vertices, 2 * x + 1, j);
+                       }
+               }
+       }
+}
+
+void btHeightfieldTerrainShape::calculateLocalInertia(btScalar, btVector3& inertia) const
+{
+       //moving concave objects not supported
+
+       inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+}
+
+void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
+{
+       m_localScaling = scaling;
+}
+const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
+{
+       return m_localScaling;
+}
+
+namespace
+{
+       struct GridRaycastState
+       {
+               int x;  // Next quad coords
+               int z;
+               int prev_x;  // Previous quad coords
+               int prev_z;
+               btScalar param;      // Exit param for previous quad
+               btScalar prevParam;  // Enter param for previous quad
+               btScalar maxDistanceFlat;
+               btScalar maxDistance3d;
+       };
+}
+
+// TODO Does it really need to take 3D vectors?
+/// Iterates through a virtual 2D grid of unit-sized square cells,
+/// and executes an action on each cell intersecting the given segment, ordered from begin to end.
+/// Initially inspired by http://www.cse.yorku.ca/~amana/research/grid.pdf
+template <typename Action_T>
+void gridRaycast(Action_T& quadAction, const btVector3& beginPos, const btVector3& endPos, int indices[3])
+{
+       GridRaycastState rs;
+       rs.maxDistance3d = beginPos.distance(endPos);
+       if (rs.maxDistance3d < 0.0001)
+       {
+               // Consider the ray is too small to hit anything
+               return;
+       }
+       
+
+       btScalar rayDirectionFlatX = endPos[indices[0]] - beginPos[indices[0]];
+       btScalar rayDirectionFlatZ = endPos[indices[2]] - beginPos[indices[2]];
+       rs.maxDistanceFlat = btSqrt(rayDirectionFlatX * rayDirectionFlatX + rayDirectionFlatZ * rayDirectionFlatZ);
+
+       if (rs.maxDistanceFlat < 0.0001)
+       {
+               // Consider the ray vertical
+               rayDirectionFlatX = 0;
+               rayDirectionFlatZ = 0;
+       }
+       else
+       {
+               rayDirectionFlatX /= rs.maxDistanceFlat;
+               rayDirectionFlatZ /= rs.maxDistanceFlat;
+       }
+
+       const int xiStep = rayDirectionFlatX > 0 ? 1 : rayDirectionFlatX < 0 ? -1 : 0;
+       const int ziStep = rayDirectionFlatZ > 0 ? 1 : rayDirectionFlatZ < 0 ? -1 : 0;
+
+       const float infinite = 9999999;
+       const btScalar paramDeltaX = xiStep != 0 ? 1.f / btFabs(rayDirectionFlatX) : infinite;
+       const btScalar paramDeltaZ = ziStep != 0 ? 1.f / btFabs(rayDirectionFlatZ) : infinite;
+
+       // pos = param * dir
+       btScalar paramCrossX;  // At which value of `param` we will cross a x-axis lane?
+       btScalar paramCrossZ;  // At which value of `param` we will cross a z-axis lane?
+
+       // paramCrossX and paramCrossZ are initialized as being the first cross
+       // X initialization
+       if (xiStep != 0)
+       {
+               if (xiStep == 1)
+               {
+                       paramCrossX = (ceil(beginPos[indices[0]]) - beginPos[indices[0]]) * paramDeltaX;
+               }
+               else
+               {
+                       paramCrossX = (beginPos[indices[0]] - floor(beginPos[indices[0]])) * paramDeltaX;
+               }
+       }
+       else
+       {
+               paramCrossX = infinite;  // Will never cross on X
+       }
+
+       // Z initialization
+       if (ziStep != 0)
+       {
+               if (ziStep == 1)
+               {
+                       paramCrossZ = (ceil(beginPos[indices[2]]) - beginPos[indices[2]]) * paramDeltaZ;
+               }
+               else
+               {
+                       paramCrossZ = (beginPos[indices[2]] - floor(beginPos[indices[2]])) * paramDeltaZ;
+               }
+       }
+       else
+       {
+               paramCrossZ = infinite;  // Will never cross on Z
+       }
+
+       rs.x = static_cast<int>(floor(beginPos[indices[0]]));
+       rs.z = static_cast<int>(floor(beginPos[indices[2]]));
+
+       // Workaround cases where the ray starts at an integer position
+       if (paramCrossX == 0.0)
+       {
+               paramCrossX += paramDeltaX;
+               // If going backwards, we should ignore the position we would get by the above flooring,
+               // because the ray is not heading in that direction
+               if (xiStep == -1)
+               {
+                       rs.x -= 1;
+               }
+       }
+
+       if (paramCrossZ == 0.0)
+       {
+               paramCrossZ += paramDeltaZ;
+               if (ziStep == -1)
+                       rs.z -= 1;
+       }
+
+       rs.prev_x = rs.x;
+       rs.prev_z = rs.z;
+       rs.param = 0;
+
+       while (true)
+       {
+               rs.prev_x = rs.x;
+               rs.prev_z = rs.z;
+               rs.prevParam = rs.param;
+
+               if (paramCrossX < paramCrossZ)
+               {
+                       // X lane
+                       rs.x += xiStep;
+                       // Assign before advancing the param,
+                       // to be in sync with the initialization step
+                       rs.param = paramCrossX;
+                       paramCrossX += paramDeltaX;
+               }
+               else
+               {
+                       // Z lane
+                       rs.z += ziStep;
+                       rs.param = paramCrossZ;
+                       paramCrossZ += paramDeltaZ;
+               }
+
+               if (rs.param > rs.maxDistanceFlat)
+               {
+                       rs.param = rs.maxDistanceFlat;
+                       quadAction(rs);
+                       break;
+               }
+               else
+               {
+                       quadAction(rs);
+               }
+       }
+}
+
+struct ProcessTrianglesAction
+{
+       const btHeightfieldTerrainShape* shape;
+       bool flipQuadEdges;
+       bool useDiamondSubdivision;
+       int width;
+       int length;
+       btTriangleCallback* callback;
+
+       void exec(int x, int z) const
+       {
+               if (x < 0 || z < 0 || x >= width || z >= length)
+               {
+                       return;
+               }
+
+               btVector3 vertices[3];
+
+               // TODO Since this is for raycasts, we could greatly benefit from an early exit on the first hit
+
+               // Check quad
+               if (flipQuadEdges || (useDiamondSubdivision && (((z + x) & 1) > 0)))
+               {
+                       // First triangle
+                       shape->getVertex(x, z, vertices[0]);
+                       shape->getVertex(x + 1, z, vertices[1]);
+                       shape->getVertex(x + 1, z + 1, vertices[2]);
+                       callback->processTriangle(vertices, x, z);
+
+                       // Second triangle
+                       shape->getVertex(x, z, vertices[0]);
+                       shape->getVertex(x + 1, z + 1, vertices[1]);
+                       shape->getVertex(x, z + 1, vertices[2]);
+                       callback->processTriangle(vertices, x, z);
+               }
+               else
+               {
+                       // First triangle
+                       shape->getVertex(x, z, vertices[0]);
+                       shape->getVertex(x, z + 1, vertices[1]);
+                       shape->getVertex(x + 1, z, vertices[2]);
+                       callback->processTriangle(vertices, x, z);
+
+                       // Second triangle
+                       shape->getVertex(x + 1, z, vertices[0]);
+                       shape->getVertex(x, z + 1, vertices[1]);
+                       shape->getVertex(x + 1, z + 1, vertices[2]);
+                       callback->processTriangle(vertices, x, z);
+               }
+       }
+
+       void operator()(const GridRaycastState& bs) const
+       {
+               exec(bs.prev_x, bs.prev_z);
+       }
+};
+
+struct ProcessVBoundsAction
+{
+       const btAlignedObjectArray<btHeightfieldTerrainShape::Range>& vbounds;
+       int width;
+       int length;
+       int chunkSize;
+
+       btVector3 rayBegin;
+       btVector3 rayEnd;
+       btVector3 rayDir;
+
+       int* m_indices;
+       ProcessTrianglesAction processTriangles;
+
+       ProcessVBoundsAction(const btAlignedObjectArray<btHeightfieldTerrainShape::Range>& bnd, int* indices)
+               : vbounds(bnd),
+               m_indices(indices)
+       {
+       }
+       void operator()(const GridRaycastState& rs) const
+       {
+               int x = rs.prev_x;
+               int z = rs.prev_z;
+
+               if (x < 0 || z < 0 || x >= width || z >= length)
+               {
+                       return;
+               }
+
+               const btHeightfieldTerrainShape::Range chunk = vbounds[x + z * width];
+
+               btVector3 enterPos;
+               btVector3 exitPos;
+
+               if (rs.maxDistanceFlat > 0.0001)
+               {
+                       btScalar flatTo3d = chunkSize * rs.maxDistance3d / rs.maxDistanceFlat;
+                       btScalar enterParam3d = rs.prevParam * flatTo3d;
+                       btScalar exitParam3d = rs.param * flatTo3d;
+                       enterPos = rayBegin + rayDir * enterParam3d;
+                       exitPos = rayBegin + rayDir * exitParam3d;
+
+                       // We did enter the flat projection of the AABB,
+                       // but we have to check if we intersect it on the vertical axis
+                       if (enterPos[1] > chunk.max && exitPos[m_indices[1]] > chunk.max)
+                       {
+                               return;
+                       }
+                       if (enterPos[1] < chunk.min && exitPos[m_indices[1]] < chunk.min)
+                       {
+                               return;
+                       }
+               }
+               else
+               {
+                       // Consider the ray vertical
+                       // (though we shouldn't reach this often because there is an early check up-front)
+                       enterPos = rayBegin;
+                       exitPos = rayEnd;
+               }
+
+               gridRaycast(processTriangles, enterPos, exitPos, m_indices);
+               // Note: it could be possible to have more than one grid at different levels,
+               // to do this there would be a branch using a pointer to another ProcessVBoundsAction
+       }
+};
+
+// TODO How do I interrupt the ray when there is a hit? `callback` does not return any result
+/// Performs a raycast using a hierarchical Bresenham algorithm.
+/// Does not allocate any memory by itself.
+void btHeightfieldTerrainShape::performRaycast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) const
+{
+       // Transform to cell-local
+       btVector3 beginPos = raySource / m_localScaling;
+       btVector3 endPos = rayTarget / m_localScaling;
+       beginPos += m_localOrigin;
+       endPos += m_localOrigin;
+
+       ProcessTrianglesAction processTriangles;
+       processTriangles.shape = this;
+       processTriangles.flipQuadEdges = m_flipQuadEdges;
+       processTriangles.useDiamondSubdivision = m_useDiamondSubdivision;
+       processTriangles.callback = callback;
+       processTriangles.width = m_heightStickWidth - 1;
+       processTriangles.length = m_heightStickLength - 1;
+
+       // TODO Transform vectors to account for m_upAxis
+       int indices[3] = { 0, 1, 2 };
+       if (m_upAxis == 2)
+       {
+               indices[1] = 2;
+               indices[2] = 1;
+       }
+       int iBeginX = static_cast<int>(floor(beginPos[indices[0]]));
+       int iBeginZ = static_cast<int>(floor(beginPos[indices[2]]));
+       int iEndX = static_cast<int>(floor(endPos[indices[0]]));
+       int iEndZ = static_cast<int>(floor(endPos[indices[2]]));
+
+       if (iBeginX == iEndX && iBeginZ == iEndZ)
+       {
+               // The ray will never cross quads within the plane,
+               // so directly process triangles within one quad
+               // (typically, vertical rays should end up here)
+               processTriangles.exec(iBeginX, iEndZ);
+               return;
+       }
+
+       
+
+       if (m_vboundsGrid.size()==0)
+       {
+               // Process all quads intersecting the flat projection of the ray
+               gridRaycast(processTriangles, beginPos, endPos, &indices[0]);
+       }
+       else
+       {
+               btVector3 rayDiff = endPos - beginPos;
+               btScalar flatDistance2 = rayDiff[indices[0]] * rayDiff[indices[0]] + rayDiff[indices[2]] * rayDiff[indices[2]];
+               if (flatDistance2 < m_vboundsChunkSize * m_vboundsChunkSize)
+               {
+                       // Don't use chunks, the ray is too short in the plane
+                       gridRaycast(processTriangles, beginPos, endPos, &indices[0]);
+                       return;
+               }
+
+               ProcessVBoundsAction processVBounds(m_vboundsGrid, &indices[0]);
+               processVBounds.width = m_vboundsGridWidth;
+               processVBounds.length = m_vboundsGridLength;
+               processVBounds.rayBegin = beginPos;
+               processVBounds.rayEnd = endPos;
+               processVBounds.rayDir = rayDiff.normalized();
+               processVBounds.processTriangles = processTriangles;
+               processVBounds.chunkSize = m_vboundsChunkSize;
+               // The ray is long, run raycast on a higher-level grid
+               gridRaycast(processVBounds, beginPos / m_vboundsChunkSize, endPos / m_vboundsChunkSize, indices);
+       }
+}
+
+/// Builds a grid data structure storing the min and max heights of the terrain in chunks.
+/// if chunkSize is zero, that accelerator is removed.
+/// If you modify the heights, you need to rebuild this accelerator.
+void btHeightfieldTerrainShape::buildAccelerator(int chunkSize)
+{
+       if (chunkSize <= 0)
+       {
+               clearAccelerator();
+               return;
+       }
+
+       m_vboundsChunkSize = chunkSize;
+       int nChunksX = m_heightStickWidth / chunkSize;
+       int nChunksZ = m_heightStickLength / chunkSize;
+
+       if (m_heightStickWidth % chunkSize > 0)
+       {
+               ++nChunksX;  // In case terrain size isn't dividable by chunk size
+       }
+       if (m_heightStickLength % chunkSize > 0)
+       {
+               ++nChunksZ;
+       }
+
+       if (m_vboundsGridWidth != nChunksX || m_vboundsGridLength != nChunksZ)
+       {
+               clearAccelerator();
+               m_vboundsGridWidth = nChunksX;
+               m_vboundsGridLength = nChunksZ;
+       }
+
+       if (nChunksX == 0 || nChunksZ == 0)
+       {
+               return;
+       }
+
+       // This data structure is only reallocated if the required size changed
+       m_vboundsGrid.resize(nChunksX * nChunksZ);
+       
+       // Compute min and max height for all chunks
+       for (int cz = 0; cz < nChunksZ; ++cz)
+       {
+               int z0 = cz * chunkSize;
+
+               for (int cx = 0; cx < nChunksX; ++cx)
+               {
+                       int x0 = cx * chunkSize;
+
+                       Range r;
+
+                       r.min = getRawHeightFieldValue(x0, z0);
+                       r.max = r.min;
+
+                       // Compute min and max height for this chunk.
+                       // We have to include one extra cell to account for neighbors.
+                       // Here is why:
+                       // Say we have a flat terrain, and a plateau that fits a chunk perfectly.
+                       //
+                       //   Left        Right
+                       // 0---0---0---1---1---1
+                       // |   |   |   |   |   |
+                       // 0---0---0---1---1---1
+                       // |   |   |   |   |   |
+                       // 0---0---0---1---1---1
+                       //           x
+                       //
+                       // If the AABB for the Left chunk did not share vertices with the Right,
+                       // then we would fail collision tests at x due to a gap.
+                       //
+                       for (int z = z0; z < z0 + chunkSize + 1; ++z)
+                       {
+                               if (z >= m_heightStickLength)
+                               {
+                                       continue;
+                               }
+
+                               for (int x = x0; x < x0 + chunkSize + 1; ++x)
+                               {
+                                       if (x >= m_heightStickWidth)
+                                       {
+                                               continue;
+                                       }
+
+                                       btScalar height = getRawHeightFieldValue(x, z);
+
+                                       if (height < r.min)
+                                       {
+                                               r.min = height;
+                                       }
+                                       else if (height > r.max)
+                                       {
+                                               r.max = height;
+                                       }
+                               }
+                       }
+
+                       m_vboundsGrid[cx + cz * nChunksX] = r;
+               }
+       }
+}
+
+void btHeightfieldTerrainShape::clearAccelerator()
+{
+       m_vboundsGrid.clear();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
new file mode 100644 (file)
index 0000000..7e251fa
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_HEIGHTFIELD_TERRAIN_SHAPE_H
+#define BT_HEIGHTFIELD_TERRAIN_SHAPE_H
+
+#include "btConcaveShape.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+///btHeightfieldTerrainShape simulates a 2D heightfield terrain
+/**
+  The caller is responsible for maintaining the heightfield array; this
+  class does not make a copy.
+
+  The heightfield can be dynamic so long as the min/max height values
+  capture the extremes (heights must always be in that range).
+
+  The local origin of the heightfield is assumed to be the exact
+  center (as determined by width and length and height, with each
+  axis multiplied by the localScaling).
+
+  \b NOTE: be careful with coordinates.  If you have a heightfield with a local
+  min height of -100m, and a max height of +500m, you may be tempted to place it
+  at the origin (0,0) and expect the heights in world coordinates to be
+  -100 to +500 meters.
+  Actually, the heights will be -300 to +300m, because bullet will re-center
+  the heightfield based on its AABB (which is determined by the min/max
+  heights).  So keep in mind that once you create a btHeightfieldTerrainShape
+  object, the heights will be adjusted relative to the center of the AABB.  This
+  is different to the behavior of many rendering engines, but is useful for
+  physics engines.
+
+  Most (but not all) rendering and heightfield libraries assume upAxis = 1
+  (that is, the y-axis is "up").  This class allows any of the 3 coordinates
+  to be "up".  Make sure your choice of axis is consistent with your rendering
+  system.
+
+  The heightfield heights are determined from the data type used for the
+  heightfieldData array.  
+
+   - unsigned char: height at a point is the uchar value at the
+       grid point, multipled by heightScale.  uchar isn't recommended
+       because of its inability to deal with negative values, and
+       low resolution (8-bit).
+
+   - short: height at a point is the short int value at that grid
+       point, multipled by heightScale.
+
+   - float or dobule: height at a point is the value at that grid point.
+
+  Whatever the caller specifies as minHeight and maxHeight will be honored.
+  The class will not inspect the heightfield to discover the actual minimum
+  or maximum heights.  These values are used to determine the heightfield's
+  axis-aligned bounding box, multiplied by localScaling.
+
+  For usage and testing see the TerrainDemo.
+ */
+ATTRIBUTE_ALIGNED16(class)
+btHeightfieldTerrainShape : public btConcaveShape
+{
+public:
+       struct Range
+       {
+               Range() {}
+               Range(btScalar min, btScalar max) : min(min), max(max) {}
+
+               bool overlaps(const Range& other) const
+               {
+                       return !(min > other.max || max < other.min);
+               }
+
+               btScalar min;
+               btScalar max;
+       };
+
+protected:
+       btVector3 m_localAabbMin;
+       btVector3 m_localAabbMax;
+       btVector3 m_localOrigin;
+
+       ///terrain data
+       int m_heightStickWidth;
+       int m_heightStickLength;
+       btScalar m_minHeight;
+       btScalar m_maxHeight;
+       btScalar m_width;
+       btScalar m_length;
+       btScalar m_heightScale;
+       union {
+               const unsigned char* m_heightfieldDataUnsignedChar;
+               const short* m_heightfieldDataShort;
+               const float* m_heightfieldDataFloat;
+               const double* m_heightfieldDataDouble;
+               const void* m_heightfieldDataUnknown;
+       };
+
+       PHY_ScalarType m_heightDataType;
+       bool m_flipQuadEdges;
+       bool m_useDiamondSubdivision;
+       bool m_useZigzagSubdivision;
+       bool m_flipTriangleWinding;
+       int m_upAxis;
+
+       btVector3 m_localScaling;
+
+       // Accelerator
+       btAlignedObjectArray<Range> m_vboundsGrid;
+       int m_vboundsGridWidth;
+       int m_vboundsGridLength;
+       int m_vboundsChunkSize;
+
+       
+       btScalar m_userValue3;
+
+       struct btTriangleInfoMap* m_triangleInfoMap;
+
+       virtual btScalar getRawHeightFieldValue(int x, int y) const;
+       void quantizeWithClamp(int* out, const btVector3& point, int isMax) const;
+
+       /// protected initialization
+       /**
+         Handles the work of constructors so that public constructors can be
+         backwards-compatible without a lot of copy/paste.
+        */
+       void initialize(int heightStickWidth, int heightStickLength,
+                                       const void* heightfieldData, btScalar heightScale,
+                                       btScalar minHeight, btScalar maxHeight, int upAxis,
+                                       PHY_ScalarType heightDataType, bool flipQuadEdges);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       /// preferred constructors
+       btHeightfieldTerrainShape(
+               int heightStickWidth, int heightStickLength,
+               const float* heightfieldData, btScalar minHeight, btScalar maxHeight,
+               int upAxis, bool flipQuadEdges);
+       btHeightfieldTerrainShape(
+               int heightStickWidth, int heightStickLength,
+               const double* heightfieldData, btScalar minHeight, btScalar maxHeight,
+               int upAxis, bool flipQuadEdges);
+       btHeightfieldTerrainShape(
+               int heightStickWidth, int heightStickLength,
+               const short* heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight,
+               int upAxis, bool flipQuadEdges);
+       btHeightfieldTerrainShape(
+               int heightStickWidth, int heightStickLength,
+               const unsigned char* heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight,
+               int upAxis, bool flipQuadEdges);
+
+       /// legacy constructor
+       /**
+         This constructor supports a range of heightfield
+         data types, and allows for a non-zero minimum height value.
+         heightScale is needed for any integer-based heightfield data types.
+
+         This legacy constructor considers `PHY_FLOAT` to mean `btScalar`.
+         With `BT_USE_DOUBLE_PRECISION`, it will expect `heightfieldData`
+         to be double-precision.
+        */
+       btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,
+                                                         const void* heightfieldData, btScalar heightScale,
+                                                         btScalar minHeight, btScalar maxHeight,
+                                                         int upAxis, PHY_ScalarType heightDataType,
+                                                         bool flipQuadEdges);
+
+       /// legacy constructor
+       /**
+         The legacy constructor assumes the heightfield has a minimum height
+         of zero.  Only unsigned char or btScalar data are supported.  For legacy
+         compatibility reasons, heightScale is calculated as maxHeight / 65535 
+         (and is only used when useFloatData = false).
+        */
+       btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges);
+
+       virtual ~btHeightfieldTerrainShape();
+
+       void setUseDiamondSubdivision(bool useDiamondSubdivision = true) { m_useDiamondSubdivision = useDiamondSubdivision; }
+
+       ///could help compatibility with Ogre heightfields. See https://code.google.com/p/bullet/issues/detail?id=625
+       void setUseZigzagSubdivision(bool useZigzagSubdivision = true) { m_useZigzagSubdivision = useZigzagSubdivision; }
+
+       void setFlipTriangleWinding(bool flipTriangleWinding)
+       {
+               m_flipTriangleWinding = flipTriangleWinding;
+       }
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       virtual void setLocalScaling(const btVector3& scaling);
+
+       virtual const btVector3& getLocalScaling() const;
+
+       void getVertex(int x, int y, btVector3& vertex) const;
+
+       void performRaycast(btTriangleCallback * callback, const btVector3& raySource, const btVector3& rayTarget) const;
+
+       void buildAccelerator(int chunkSize = 16);
+       void clearAccelerator();
+
+       int getUpAxis() const
+       {
+               return m_upAxis;
+       }
+       //debugging
+       virtual const char* getName() const { return "HEIGHTFIELD"; }
+
+       
+       void setUserValue3(btScalar value)
+       {
+               m_userValue3 = value;
+       }
+       btScalar getUserValue3() const
+       {
+               return m_userValue3;
+       }
+       const struct btTriangleInfoMap* getTriangleInfoMap() const
+       {
+               return m_triangleInfoMap;
+       }
+       struct btTriangleInfoMap* getTriangleInfoMap()
+       {
+               return m_triangleInfoMap;
+       }
+       void setTriangleInfoMap(btTriangleInfoMap* map)
+       {
+               m_triangleInfoMap = map;
+       }
+       const unsigned char* getHeightfieldRawData() const
+       {
+               return m_heightfieldDataUnsignedChar;
+       }
+};
+
+#endif  //BT_HEIGHTFIELD_TERRAIN_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMaterial.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMaterial.h
new file mode 100644 (file)
index 0000000..c9a436b
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MATERIAL_H
+#define BT_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  // BT_MATERIAL_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMiniSDF.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMiniSDF.cpp
new file mode 100644 (file)
index 0000000..13c0a34
--- /dev/null
@@ -0,0 +1,522 @@
+#include "btMiniSDF.h"
+
+//
+//Based on code from DiscreGrid, https://github.com/InteractiveComputerGraphics/Discregrid
+//example:
+//GenerateSDF.exe -r "32 32 32" -d "-1.6 -1.6 -.6 1.6 1.6 .6" concave_box.obj
+//The MIT License (MIT)
+//
+//Copyright (c) 2017 Dan Koschier
+//
+
+#include <limits.h>
+#include <string.h>  //memcpy
+
+struct btSdfDataStream
+{
+       const char* m_data;
+       int m_size;
+
+       int m_currentOffset;
+
+       btSdfDataStream(const char* data, int size)
+               : m_data(data),
+                 m_size(size),
+                 m_currentOffset(0)
+       {
+       }
+
+       template <class T>
+       bool read(T& val)
+       {
+               int bytes = sizeof(T);
+               if (m_currentOffset + bytes <= m_size)
+               {
+                       char* dest = (char*)&val;
+                       memcpy(dest, &m_data[m_currentOffset], bytes);
+                       m_currentOffset += bytes;
+                       return true;
+               }
+               btAssert(0);
+               return false;
+       }
+};
+
+bool btMiniSDF::load(const char* data, int size)
+{
+       int fileSize = -1;
+
+       btSdfDataStream ds(data, size);
+       {
+               double buf[6];
+               ds.read(buf);
+               m_domain.m_min[0] = buf[0];
+               m_domain.m_min[1] = buf[1];
+               m_domain.m_min[2] = buf[2];
+               m_domain.m_min[3] = 0;
+               m_domain.m_max[0] = buf[3];
+               m_domain.m_max[1] = buf[4];
+               m_domain.m_max[2] = buf[5];
+               m_domain.m_max[3] = 0;
+       }
+       {
+               unsigned int buf2[3];
+               ds.read(buf2);
+               m_resolution[0] = buf2[0];
+               m_resolution[1] = buf2[1];
+               m_resolution[2] = buf2[2];
+       }
+       {
+               double buf[3];
+               ds.read(buf);
+               m_cell_size[0] = buf[0];
+               m_cell_size[1] = buf[1];
+               m_cell_size[2] = buf[2];
+       }
+       {
+               double buf[3];
+               ds.read(buf);
+               m_inv_cell_size[0] = buf[0];
+               m_inv_cell_size[1] = buf[1];
+               m_inv_cell_size[2] = buf[2];
+       }
+       {
+               unsigned long long int cells;
+               ds.read(cells);
+               m_n_cells = cells;
+       }
+       {
+               unsigned long long int fields;
+               ds.read(fields);
+               m_n_fields = fields;
+       }
+
+       unsigned long long int nodes0;
+       std::size_t n_nodes0;
+       ds.read(nodes0);
+       n_nodes0 = nodes0;
+       if (n_nodes0 > 1024 * 1024 * 1024)
+       {
+               return m_isValid;
+       }
+       m_nodes.resize(n_nodes0);
+       for (unsigned int i = 0; i < n_nodes0; i++)
+       {
+               unsigned long long int n_nodes1;
+               ds.read(n_nodes1);
+               btAlignedObjectArray<double>& nodes = m_nodes[i];
+               nodes.resize(n_nodes1);
+               for (int j = 0; j < nodes.size(); j++)
+               {
+                       double& node = nodes[j];
+                       ds.read(node);
+               }
+       }
+
+       unsigned long long int n_cells0;
+       ds.read(n_cells0);
+       m_cells.resize(n_cells0);
+       for (int i = 0; i < n_cells0; i++)
+       {
+               unsigned long long int n_cells1;
+               btAlignedObjectArray<btCell32>& cells = m_cells[i];
+               ds.read(n_cells1);
+               cells.resize(n_cells1);
+               for (int j = 0; j < n_cells1; j++)
+               {
+                       btCell32& cell = cells[j];
+                       ds.read(cell);
+               }
+       }
+
+       {
+               unsigned long long int n_cell_maps0;
+               ds.read(n_cell_maps0);
+
+               m_cell_map.resize(n_cell_maps0);
+               for (int i = 0; i < n_cell_maps0; i++)
+               {
+                       unsigned long long int n_cell_maps1;
+                       btAlignedObjectArray<unsigned int>& cell_maps = m_cell_map[i];
+                       ds.read(n_cell_maps1);
+                       cell_maps.resize(n_cell_maps1);
+                       for (int j = 0; j < n_cell_maps1; j++)
+                       {
+                               unsigned int& cell_map = cell_maps[j];
+                               ds.read(cell_map);
+                       }
+               }
+       }
+
+       m_isValid = (ds.m_currentOffset == ds.m_size);
+       return m_isValid;
+}
+
+unsigned int btMiniSDF::multiToSingleIndex(btMultiIndex const& ijk) const
+{
+       return m_resolution[1] * m_resolution[0] * ijk.ijk[2] + m_resolution[0] * ijk.ijk[1] + ijk.ijk[0];
+}
+
+btAlignedBox3d
+btMiniSDF::subdomain(btMultiIndex const& ijk) const
+{
+       btAssert(m_isValid);
+       btVector3 tmp;
+       tmp.m_floats[0] = m_cell_size[0] * (double)ijk.ijk[0];
+       tmp.m_floats[1] = m_cell_size[1] * (double)ijk.ijk[1];
+       tmp.m_floats[2] = m_cell_size[2] * (double)ijk.ijk[2];
+
+       btVector3 origin = m_domain.min() + tmp;
+
+       btAlignedBox3d box = btAlignedBox3d(origin, origin + m_cell_size);
+       return box;
+}
+
+btMultiIndex
+btMiniSDF::singleToMultiIndex(unsigned int l) const
+{
+       btAssert(m_isValid);
+       unsigned int n01 = m_resolution[0] * m_resolution[1];
+       unsigned int k = l / n01;
+       unsigned int temp = l % n01;
+       unsigned int j = temp / m_resolution[0];
+       unsigned int i = temp % m_resolution[0];
+       btMultiIndex mi;
+       mi.ijk[0] = i;
+       mi.ijk[1] = j;
+       mi.ijk[2] = k;
+       return mi;
+}
+
+btAlignedBox3d
+btMiniSDF::subdomain(unsigned int l) const
+{
+       btAssert(m_isValid);
+       return subdomain(singleToMultiIndex(l));
+}
+
+btShapeMatrix
+btMiniSDF::shape_function_(btVector3 const& xi, btShapeGradients* gradient) const
+{
+       btAssert(m_isValid);
+       btShapeMatrix res;
+
+       btScalar x = xi[0];
+       btScalar y = xi[1];
+       btScalar z = xi[2];
+
+       btScalar x2 = x * x;
+       btScalar y2 = y * y;
+       btScalar z2 = z * z;
+
+       btScalar _1mx = 1.0 - x;
+       btScalar _1my = 1.0 - y;
+       btScalar _1mz = 1.0 - z;
+
+       btScalar _1px = 1.0 + x;
+       btScalar _1py = 1.0 + y;
+       btScalar _1pz = 1.0 + z;
+
+       btScalar _1m3x = 1.0 - 3.0 * x;
+       btScalar _1m3y = 1.0 - 3.0 * y;
+       btScalar _1m3z = 1.0 - 3.0 * z;
+
+       btScalar _1p3x = 1.0 + 3.0 * x;
+       btScalar _1p3y = 1.0 + 3.0 * y;
+       btScalar _1p3z = 1.0 + 3.0 * z;
+
+       btScalar _1mxt1my = _1mx * _1my;
+       btScalar _1mxt1py = _1mx * _1py;
+       btScalar _1pxt1my = _1px * _1my;
+       btScalar _1pxt1py = _1px * _1py;
+
+       btScalar _1mxt1mz = _1mx * _1mz;
+       btScalar _1mxt1pz = _1mx * _1pz;
+       btScalar _1pxt1mz = _1px * _1mz;
+       btScalar _1pxt1pz = _1px * _1pz;
+
+       btScalar _1myt1mz = _1my * _1mz;
+       btScalar _1myt1pz = _1my * _1pz;
+       btScalar _1pyt1mz = _1py * _1mz;
+       btScalar _1pyt1pz = _1py * _1pz;
+
+       btScalar _1mx2 = 1.0 - x2;
+       btScalar _1my2 = 1.0 - y2;
+       btScalar _1mz2 = 1.0 - z2;
+
+       // Corner nodes.
+       btScalar fac = 1.0 / 64.0 * (9.0 * (x2 + y2 + z2) - 19.0);
+       res[0] = fac * _1mxt1my * _1mz;
+       res[1] = fac * _1pxt1my * _1mz;
+       res[2] = fac * _1mxt1py * _1mz;
+       res[3] = fac * _1pxt1py * _1mz;
+       res[4] = fac * _1mxt1my * _1pz;
+       res[5] = fac * _1pxt1my * _1pz;
+       res[6] = fac * _1mxt1py * _1pz;
+       res[7] = fac * _1pxt1py * _1pz;
+
+       // Edge nodes.
+
+       fac = 9.0 / 64.0 * _1mx2;
+       btScalar fact1m3x = fac * _1m3x;
+       btScalar fact1p3x = fac * _1p3x;
+       res[8] = fact1m3x * _1myt1mz;
+       res[9] = fact1p3x * _1myt1mz;
+       res[10] = fact1m3x * _1myt1pz;
+       res[11] = fact1p3x * _1myt1pz;
+       res[12] = fact1m3x * _1pyt1mz;
+       res[13] = fact1p3x * _1pyt1mz;
+       res[14] = fact1m3x * _1pyt1pz;
+       res[15] = fact1p3x * _1pyt1pz;
+
+       fac = 9.0 / 64.0 * _1my2;
+       btScalar fact1m3y = fac * _1m3y;
+       btScalar fact1p3y = fac * _1p3y;
+       res[16] = fact1m3y * _1mxt1mz;
+       res[17] = fact1p3y * _1mxt1mz;
+       res[18] = fact1m3y * _1pxt1mz;
+       res[19] = fact1p3y * _1pxt1mz;
+       res[20] = fact1m3y * _1mxt1pz;
+       res[21] = fact1p3y * _1mxt1pz;
+       res[22] = fact1m3y * _1pxt1pz;
+       res[23] = fact1p3y * _1pxt1pz;
+
+       fac = 9.0 / 64.0 * _1mz2;
+       btScalar fact1m3z = fac * _1m3z;
+       btScalar fact1p3z = fac * _1p3z;
+       res[24] = fact1m3z * _1mxt1my;
+       res[25] = fact1p3z * _1mxt1my;
+       res[26] = fact1m3z * _1mxt1py;
+       res[27] = fact1p3z * _1mxt1py;
+       res[28] = fact1m3z * _1pxt1my;
+       res[29] = fact1p3z * _1pxt1my;
+       res[30] = fact1m3z * _1pxt1py;
+       res[31] = fact1p3z * _1pxt1py;
+
+       if (gradient)
+       {
+               btShapeGradients& dN = *gradient;
+
+               btScalar _9t3x2py2pz2m19 = 9.0 * (3.0 * x2 + y2 + z2) - 19.0;
+               btScalar _9tx2p3y2pz2m19 = 9.0 * (x2 + 3.0 * y2 + z2) - 19.0;
+               btScalar _9tx2py2p3z2m19 = 9.0 * (x2 + y2 + 3.0 * z2) - 19.0;
+               btScalar _18x = 18.0 * x;
+               btScalar _18y = 18.0 * y;
+               btScalar _18z = 18.0 * z;
+
+               btScalar _3m9x2 = 3.0 - 9.0 * x2;
+               btScalar _3m9y2 = 3.0 - 9.0 * y2;
+               btScalar _3m9z2 = 3.0 - 9.0 * z2;
+
+               btScalar _2x = 2.0 * x;
+               btScalar _2y = 2.0 * y;
+               btScalar _2z = 2.0 * z;
+
+               btScalar _18xm9t3x2py2pz2m19 = _18x - _9t3x2py2pz2m19;
+               btScalar _18xp9t3x2py2pz2m19 = _18x + _9t3x2py2pz2m19;
+               btScalar _18ym9tx2p3y2pz2m19 = _18y - _9tx2p3y2pz2m19;
+               btScalar _18yp9tx2p3y2pz2m19 = _18y + _9tx2p3y2pz2m19;
+               btScalar _18zm9tx2py2p3z2m19 = _18z - _9tx2py2p3z2m19;
+               btScalar _18zp9tx2py2p3z2m19 = _18z + _9tx2py2p3z2m19;
+
+               dN(0, 0) = _18xm9t3x2py2pz2m19 * _1myt1mz;
+               dN(0, 1) = _1mxt1mz * _18ym9tx2p3y2pz2m19;
+               dN(0, 2) = _1mxt1my * _18zm9tx2py2p3z2m19;
+               dN(1, 0) = _18xp9t3x2py2pz2m19 * _1myt1mz;
+               dN(1, 1) = _1pxt1mz * _18ym9tx2p3y2pz2m19;
+               dN(1, 2) = _1pxt1my * _18zm9tx2py2p3z2m19;
+               dN(2, 0) = _18xm9t3x2py2pz2m19 * _1pyt1mz;
+               dN(2, 1) = _1mxt1mz * _18yp9tx2p3y2pz2m19;
+               dN(2, 2) = _1mxt1py * _18zm9tx2py2p3z2m19;
+               dN(3, 0) = _18xp9t3x2py2pz2m19 * _1pyt1mz;
+               dN(3, 1) = _1pxt1mz * _18yp9tx2p3y2pz2m19;
+               dN(3, 2) = _1pxt1py * _18zm9tx2py2p3z2m19;
+               dN(4, 0) = _18xm9t3x2py2pz2m19 * _1myt1pz;
+               dN(4, 1) = _1mxt1pz * _18ym9tx2p3y2pz2m19;
+               dN(4, 2) = _1mxt1my * _18zp9tx2py2p3z2m19;
+               dN(5, 0) = _18xp9t3x2py2pz2m19 * _1myt1pz;
+               dN(5, 1) = _1pxt1pz * _18ym9tx2p3y2pz2m19;
+               dN(5, 2) = _1pxt1my * _18zp9tx2py2p3z2m19;
+               dN(6, 0) = _18xm9t3x2py2pz2m19 * _1pyt1pz;
+               dN(6, 1) = _1mxt1pz * _18yp9tx2p3y2pz2m19;
+               dN(6, 2) = _1mxt1py * _18zp9tx2py2p3z2m19;
+               dN(7, 0) = _18xp9t3x2py2pz2m19 * _1pyt1pz;
+               dN(7, 1) = _1pxt1pz * _18yp9tx2p3y2pz2m19;
+               dN(7, 2) = _1pxt1py * _18zp9tx2py2p3z2m19;
+
+               dN.topRowsDivide(8, 64.0);
+
+               btScalar _m3m9x2m2x = -_3m9x2 - _2x;
+               btScalar _p3m9x2m2x = _3m9x2 - _2x;
+               btScalar _1mx2t1m3x = _1mx2 * _1m3x;
+               btScalar _1mx2t1p3x = _1mx2 * _1p3x;
+               dN(8, 0) = _m3m9x2m2x * _1myt1mz,
+                         dN(8, 1) = -_1mx2t1m3x * _1mz,
+                         dN(8, 2) = -_1mx2t1m3x * _1my;
+               dN(9, 0) = _p3m9x2m2x * _1myt1mz,
+                         dN(9, 1) = -_1mx2t1p3x * _1mz,
+                         dN(9, 2) = -_1mx2t1p3x * _1my;
+               dN(10, 0) = _m3m9x2m2x * _1myt1pz,
+                          dN(10, 1) = -_1mx2t1m3x * _1pz,
+                          dN(10, 2) = _1mx2t1m3x * _1my;
+               dN(11, 0) = _p3m9x2m2x * _1myt1pz,
+                          dN(11, 1) = -_1mx2t1p3x * _1pz,
+                          dN(11, 2) = _1mx2t1p3x * _1my;
+               dN(12, 0) = _m3m9x2m2x * _1pyt1mz,
+                          dN(12, 1) = _1mx2t1m3x * _1mz,
+                          dN(12, 2) = -_1mx2t1m3x * _1py;
+               dN(13, 0) = _p3m9x2m2x * _1pyt1mz,
+                          dN(13, 1) = _1mx2t1p3x * _1mz,
+                          dN(13, 2) = -_1mx2t1p3x * _1py;
+               dN(14, 0) = _m3m9x2m2x * _1pyt1pz,
+                          dN(14, 1) = _1mx2t1m3x * _1pz,
+                          dN(14, 2) = _1mx2t1m3x * _1py;
+               dN(15, 0) = _p3m9x2m2x * _1pyt1pz,
+                          dN(15, 1) = _1mx2t1p3x * _1pz,
+                          dN(15, 2) = _1mx2t1p3x * _1py;
+
+               btScalar _m3m9y2m2y = -_3m9y2 - _2y;
+               btScalar _p3m9y2m2y = _3m9y2 - _2y;
+               btScalar _1my2t1m3y = _1my2 * _1m3y;
+               btScalar _1my2t1p3y = _1my2 * _1p3y;
+               dN(16, 0) = -_1my2t1m3y * _1mz,
+                          dN(16, 1) = _m3m9y2m2y * _1mxt1mz,
+                          dN(16, 2) = -_1my2t1m3y * _1mx;
+               dN(17, 0) = -_1my2t1p3y * _1mz,
+                          dN(17, 1) = _p3m9y2m2y * _1mxt1mz,
+                          dN(17, 2) = -_1my2t1p3y * _1mx;
+               dN(18, 0) = _1my2t1m3y * _1mz,
+                          dN(18, 1) = _m3m9y2m2y * _1pxt1mz,
+                          dN(18, 2) = -_1my2t1m3y * _1px;
+               dN(19, 0) = _1my2t1p3y * _1mz,
+                          dN(19, 1) = _p3m9y2m2y * _1pxt1mz,
+                          dN(19, 2) = -_1my2t1p3y * _1px;
+               dN(20, 0) = -_1my2t1m3y * _1pz,
+                          dN(20, 1) = _m3m9y2m2y * _1mxt1pz,
+                          dN(20, 2) = _1my2t1m3y * _1mx;
+               dN(21, 0) = -_1my2t1p3y * _1pz,
+                          dN(21, 1) = _p3m9y2m2y * _1mxt1pz,
+                          dN(21, 2) = _1my2t1p3y * _1mx;
+               dN(22, 0) = _1my2t1m3y * _1pz,
+                          dN(22, 1) = _m3m9y2m2y * _1pxt1pz,
+                          dN(22, 2) = _1my2t1m3y * _1px;
+               dN(23, 0) = _1my2t1p3y * _1pz,
+                          dN(23, 1) = _p3m9y2m2y * _1pxt1pz,
+                          dN(23, 2) = _1my2t1p3y * _1px;
+
+               btScalar _m3m9z2m2z = -_3m9z2 - _2z;
+               btScalar _p3m9z2m2z = _3m9z2 - _2z;
+               btScalar _1mz2t1m3z = _1mz2 * _1m3z;
+               btScalar _1mz2t1p3z = _1mz2 * _1p3z;
+               dN(24, 0) = -_1mz2t1m3z * _1my,
+                          dN(24, 1) = -_1mz2t1m3z * _1mx,
+                          dN(24, 2) = _m3m9z2m2z * _1mxt1my;
+               dN(25, 0) = -_1mz2t1p3z * _1my,
+                          dN(25, 1) = -_1mz2t1p3z * _1mx,
+                          dN(25, 2) = _p3m9z2m2z * _1mxt1my;
+               dN(26, 0) = -_1mz2t1m3z * _1py,
+                          dN(26, 1) = _1mz2t1m3z * _1mx,
+                          dN(26, 2) = _m3m9z2m2z * _1mxt1py;
+               dN(27, 0) = -_1mz2t1p3z * _1py,
+                          dN(27, 1) = _1mz2t1p3z * _1mx,
+                          dN(27, 2) = _p3m9z2m2z * _1mxt1py;
+               dN(28, 0) = _1mz2t1m3z * _1my,
+                          dN(28, 1) = -_1mz2t1m3z * _1px,
+                          dN(28, 2) = _m3m9z2m2z * _1pxt1my;
+               dN(29, 0) = _1mz2t1p3z * _1my,
+                          dN(29, 1) = -_1mz2t1p3z * _1px,
+                          dN(29, 2) = _p3m9z2m2z * _1pxt1my;
+               dN(30, 0) = _1mz2t1m3z * _1py,
+                          dN(30, 1) = _1mz2t1m3z * _1px,
+                          dN(30, 2) = _m3m9z2m2z * _1pxt1py;
+               dN(31, 0) = _1mz2t1p3z * _1py,
+                          dN(31, 1) = _1mz2t1p3z * _1px,
+                          dN(31, 2) = _p3m9z2m2z * _1pxt1py;
+
+               dN.bottomRowsMul(32u - 8u, 9.0 / 64.0);
+       }
+
+       return res;
+}
+
+bool btMiniSDF::interpolate(unsigned int field_id, double& dist, btVector3 const& x,
+                                                       btVector3* gradient) const
+{
+       btAssert(m_isValid);
+       if (!m_isValid)
+               return false;
+
+       if (!m_domain.contains(x))
+               return false;
+
+       btVector3 tmpmi = ((x - m_domain.min()) * (m_inv_cell_size));  //.cast<unsigned int>().eval();
+       unsigned int mi[3] = {(unsigned int)tmpmi[0], (unsigned int)tmpmi[1], (unsigned int)tmpmi[2]};
+       if (mi[0] >= m_resolution[0])
+               mi[0] = m_resolution[0] - 1;
+       if (mi[1] >= m_resolution[1])
+               mi[1] = m_resolution[1] - 1;
+       if (mi[2] >= m_resolution[2])
+               mi[2] = m_resolution[2] - 1;
+       btMultiIndex mui;
+       mui.ijk[0] = mi[0];
+       mui.ijk[1] = mi[1];
+       mui.ijk[2] = mi[2];
+       int i = multiToSingleIndex(mui);
+       unsigned int i_ = m_cell_map[field_id][i];
+       if (i_ == UINT_MAX)
+               return false;
+
+       btAlignedBox3d sd = subdomain(i);
+       i = i_;
+       btVector3 d = sd.m_max - sd.m_min;  //.diagonal().eval();
+
+       btVector3 denom = (sd.max() - sd.min());
+       btVector3 c0 = btVector3(2.0, 2.0, 2.0) / denom;
+       btVector3 c1 = (sd.max() + sd.min()) / denom;
+       btVector3 xi = (c0 * x - c1);
+
+       btCell32 const& cell = m_cells[field_id][i];
+       if (!gradient)
+       {
+               //auto phi = m_coefficients[field_id][i].dot(shape_function_(xi, 0));
+               double phi = 0.0;
+               btShapeMatrix N = shape_function_(xi, 0);
+               for (unsigned int j = 0u; j < 32u; ++j)
+               {
+                       unsigned int v = cell.m_cells[j];
+                       double c = m_nodes[field_id][v];
+                       if (c == DBL_MAX)
+                       {
+                               return false;
+                               ;
+                       }
+                       phi += c * N[j];
+               }
+
+               dist = phi;
+               return true;
+       }
+
+       btShapeGradients dN;
+       btShapeMatrix N = shape_function_(xi, &dN);
+
+       double phi = 0.0;
+       gradient->setZero();
+       for (unsigned int j = 0u; j < 32u; ++j)
+       {
+               unsigned int v = cell.m_cells[j];
+               double c = m_nodes[field_id][v];
+               if (c == DBL_MAX)
+               {
+                       gradient->setZero();
+                       return false;
+               }
+               phi += c * N[j];
+               (*gradient)[0] += c * dN(j, 0);
+               (*gradient)[1] += c * dN(j, 1);
+               (*gradient)[2] += c * dN(j, 2);
+       }
+       (*gradient) *= c0;
+       dist = phi;
+       return true;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMiniSDF.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMiniSDF.h
new file mode 100644 (file)
index 0000000..b60fd10
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef MINISDF_H
+#define MINISDF_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct btMultiIndex
+{
+       unsigned int ijk[3];
+};
+
+struct btAlignedBox3d
+{
+       btVector3 m_min;
+       btVector3 m_max;
+
+       const btVector3& min() const
+       {
+               return m_min;
+       }
+
+       const btVector3& max() const
+       {
+               return m_max;
+       }
+
+       bool contains(const btVector3& x) const
+       {
+               return TestPointAgainstAabb2(m_min, m_max, x);
+       }
+
+       btAlignedBox3d(const btVector3& mn, const btVector3& mx)
+               : m_min(mn),
+                 m_max(mx)
+       {
+       }
+
+       btAlignedBox3d()
+       {
+       }
+};
+
+struct btShapeMatrix
+{
+       double m_vec[32];
+
+       inline double& operator[](int i)
+       {
+               return m_vec[i];
+       }
+
+       inline const double& operator[](int i) const
+       {
+               return m_vec[i];
+       }
+};
+
+struct btShapeGradients
+{
+       btVector3 m_vec[32];
+
+       void topRowsDivide(int row, double denom)
+       {
+               for (int i = 0; i < row; i++)
+               {
+                       m_vec[i] /= denom;
+               }
+       }
+
+       void bottomRowsMul(int row, double val)
+       {
+               for (int i = 32 - row; i < 32; i++)
+               {
+                       m_vec[i] *= val;
+               }
+       }
+
+       inline btScalar& operator()(int i, int j)
+       {
+               return m_vec[i][j];
+       }
+};
+
+struct btCell32
+{
+       unsigned int m_cells[32];
+};
+
+struct btMiniSDF
+{
+       btAlignedBox3d m_domain;
+       unsigned int m_resolution[3];
+       btVector3 m_cell_size;
+       btVector3 m_inv_cell_size;
+       std::size_t m_n_cells;
+       std::size_t m_n_fields;
+       bool m_isValid;
+
+       btAlignedObjectArray<btAlignedObjectArray<double> > m_nodes;
+       btAlignedObjectArray<btAlignedObjectArray<btCell32> > m_cells;
+       btAlignedObjectArray<btAlignedObjectArray<unsigned int> > m_cell_map;
+
+       btMiniSDF()
+               : m_isValid(false)
+       {
+       }
+       bool load(const char* data, int size);
+       bool isValid() const
+       {
+               return m_isValid;
+       }
+       unsigned int multiToSingleIndex(btMultiIndex const& ijk) const;
+
+       btAlignedBox3d subdomain(btMultiIndex const& ijk) const;
+
+       btMultiIndex singleToMultiIndex(unsigned int l) const;
+
+       btAlignedBox3d subdomain(unsigned int l) const;
+
+       btShapeMatrix
+       shape_function_(btVector3 const& xi, btShapeGradients* gradient = 0) const;
+
+       bool interpolate(unsigned int field_id, double& dist, btVector3 const& x, btVector3* gradient) const;
+};
+
+#endif  //MINISDF_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
new file mode 100644 (file)
index 0000000..d4b6a65
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btMinkowskiSumShape.h"
+
+btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA, const btConvexShape* shapeB)
+       : btConvexInternalShape(),
+         m_shapeA(shapeA),
+         m_shapeB(shapeB)
+{
+       m_shapeType = MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE;
+       m_transA.setIdentity();
+       m_transB.setIdentity();
+}
+
+btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+       btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec * m_transA.getBasis()));
+       btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(-vec * m_transB.getBasis()));
+       return supVertexA - supVertexB;
+}
+
+void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       ///@todo: could make recursive use of batching. probably this shape is not used frequently.
+       for (int i = 0; i < numVectors; i++)
+       {
+               supportVerticesOut[i] = localGetSupportingVertexWithoutMargin(vectors[i]);
+       }
+}
+
+btScalar btMinkowskiSumShape::getMargin() const
+{
+       return m_shapeA->getMargin() + m_shapeB->getMargin();
+}
+
+void btMinkowskiSumShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       (void)mass;
+       //inertia of the AABB of the Minkowski sum
+       btTransform identity;
+       identity.setIdentity();
+       btVector3 aabbMin, aabbMax;
+       getAabb(identity, aabbMin, aabbMax);
+
+       btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
+
+       btScalar margin = getMargin();
+
+       btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
+       btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
+       btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
+       const btScalar x2 = lx * lx;
+       const btScalar y2 = ly * ly;
+       const btScalar z2 = lz * lz;
+       const btScalar scaledmass = mass * btScalar(0.08333333);
+
+       inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
new file mode 100644 (file)
index 0000000..f5763f6
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MINKOWSKI_SUM_SHAPE_H
+#define BT_MINKOWSKI_SUM_SHAPE_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+
+/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes.
+ATTRIBUTE_ALIGNED16(class)
+btMinkowskiSumShape : public btConvexInternalShape
+{
+       btTransform m_transA;
+       btTransform m_transB;
+       const btConvexShape* m_shapeA;
+       const btConvexShape* m_shapeB;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btMinkowskiSumShape(const btConvexShape* shapeA, const btConvexShape* shapeB);
+
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       void setTransformA(const btTransform& transA) { m_transA = transA; }
+       void setTransformB(const btTransform& transB) { m_transB = transB; }
+
+       const btTransform& getTransformA() const { return m_transA; }
+       const btTransform& getTransformB() const { return m_transB; }
+
+       // keep this for backward compatibility
+       const btTransform& GetTransformB() const { return m_transB; }
+
+       virtual btScalar getMargin() const;
+
+       const btConvexShape* getShapeA() const { return m_shapeA; }
+       const btConvexShape* getShapeB() const { return m_shapeB; }
+
+       virtual const char* getName() const
+       {
+               return "MinkowskiSum";
+       }
+};
+
+#endif  //BT_MINKOWSKI_SUM_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
new file mode 100644 (file)
index 0000000..c0cc55d
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#if defined(_WIN32) || defined(__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+#include "btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btSerializer.h"
+
+btMultiSphereShape::btMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres)
+       : btConvexInternalAabbCachingShape()
+{
+       m_shapeType = MULTI_SPHERE_SHAPE_PROXYTYPE;
+       //btScalar startMargin = btScalar(BT_LARGE_FLOAT);
+
+       m_localPositionArray.resize(numSpheres);
+       m_radiArray.resize(numSpheres);
+       for (int i = 0; i < numSpheres; i++)
+       {
+               m_localPositionArray[i] = positions[i];
+               m_radiArray[i] = radi[i];
+       }
+
+       recalcLocalAabb();
+}
+
+#ifndef MIN
+#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+btVector3 btMultiSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
+{
+       btVector3 supVec(0, 0, 0);
+
+       btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+       btVector3 vec = vec0;
+       btScalar lenSqr = vec.length2();
+       if (lenSqr < (SIMD_EPSILON * SIMD_EPSILON))
+       {
+               vec.setValue(1, 0, 0);
+       }
+       else
+       {
+               btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
+               vec *= rlen;
+       }
+
+       btVector3 vtx;
+       btScalar newDot;
+
+       const btVector3* pos = &m_localPositionArray[0];
+       const btScalar* rad = &m_radiArray[0];
+       int numSpheres = m_localPositionArray.size();
+
+       for (int k = 0; k < numSpheres; k += 128)
+       {
+               btVector3 temp[128];
+               int inner_count = MIN(numSpheres - k, 128);
+               for (long i = 0; i < inner_count; i++)
+               {
+                       temp[i] = (*pos) * m_localScaling + vec * m_localScaling * (*rad) - vec * getMargin();
+                       pos++;
+                       rad++;
+               }
+               long i = vec.maxDot(temp, inner_count, newDot);
+               if (newDot > maxDot)
+               {
+                       maxDot = newDot;
+                       supVec = temp[i];
+               }
+       }
+
+       return supVec;
+}
+
+void btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       for (int j = 0; j < numVectors; j++)
+       {
+               btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+               const btVector3& vec = vectors[j];
+
+               btVector3 vtx;
+               btScalar newDot;
+
+               const btVector3* pos = &m_localPositionArray[0];
+               const btScalar* rad = &m_radiArray[0];
+               int numSpheres = m_localPositionArray.size();
+
+               for (int k = 0; k < numSpheres; k += 128)
+               {
+                       btVector3 temp[128];
+                       int inner_count = MIN(numSpheres - k, 128);
+                       for (long i = 0; i < inner_count; i++)
+                       {
+                               temp[i] = (*pos) * m_localScaling + vec * m_localScaling * (*rad) - vec * getMargin();
+                               pos++;
+                               rad++;
+                       }
+                       long i = vec.maxDot(temp, inner_count, newDot);
+                       if (newDot > maxDot)
+                       {
+                               maxDot = newDot;
+                               supportVerticesOut[j] = temp[i];
+                       }
+               }
+       }
+}
+
+void btMultiSphereShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       //as an approximation, take the inertia of the box that bounds the spheres
+
+       btVector3 localAabbMin, localAabbMax;
+       getCachedLocalAabb(localAabbMin, localAabbMax);
+       btVector3 halfExtents = (localAabbMax - localAabbMin) * btScalar(0.5);
+
+       btScalar lx = btScalar(2.) * (halfExtents.x());
+       btScalar ly = btScalar(2.) * (halfExtents.y());
+       btScalar lz = btScalar(2.) * (halfExtents.z());
+
+       inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
+                                        mass / (btScalar(12.0)) * (lx * lx + lz * lz),
+                                        mass / (btScalar(12.0)) * (lx * lx + ly * ly));
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btMultiSphereShapeData* shapeData = (btMultiSphereShapeData*)dataBuffer;
+       btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+       int numElem = m_localPositionArray.size();
+       shapeData->m_localPositionArrayPtr = numElem ? (btPositionAndRadius*)serializer->getUniquePointer((void*)&m_localPositionArray[0]) : 0;
+
+       shapeData->m_localPositionArraySize = numElem;
+       if (numElem)
+       {
+               btChunk* chunk = serializer->allocate(sizeof(btPositionAndRadius), numElem);
+               btPositionAndRadius* memPtr = (btPositionAndRadius*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       m_localPositionArray[i].serializeFloat(memPtr->m_pos);
+                       memPtr->m_radius = float(m_radiArray[i]);
+               }
+               serializer->finalizeChunk(chunk, "btPositionAndRadius", BT_ARRAY_CODE, (void*)&m_localPositionArray[0]);
+       }
+
+       // Fill padding with zeros to appease msan.
+       memset(shapeData->m_padding, 0, sizeof(shapeData->m_padding));
+
+       return "btMultiSphereShapeData";
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultiSphereShape.h
new file mode 100644 (file)
index 0000000..2d79c07
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SPHERE_MINKOWSKI_H
+#define BT_MULTI_SPHERE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btAabbUtil2.h"
+
+///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, but call 'recalcLocalAabb' after changing any sphere position/radius
+ATTRIBUTE_ALIGNED16(class)
+btMultiSphereShape : public btConvexInternalAabbCachingShape
+{
+       btAlignedObjectArray<btVector3> m_localPositionArray;
+       btAlignedObjectArray<btScalar> m_radiArray;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres);
+
+       ///CollisionShape Interface
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       /// btConvexShape Interface
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+       int getSphereCount() const
+       {
+               return m_localPositionArray.size();
+       }
+
+       const btVector3& getSpherePosition(int index) const
+       {
+               return m_localPositionArray[index];
+       }
+
+       btScalar getSphereRadius(int index) const
+       {
+               return m_radiArray[index];
+       }
+
+       virtual const char* getName() const
+       {
+               return "MultiSphere";
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+struct btPositionAndRadius
+{
+       btVector3FloatData m_pos;
+       float m_radius;
+};
+
+// clang-format off
+
+struct btMultiSphereShapeData
+{
+       btConvexInternalShapeData       m_convexInternalShapeData;
+
+       btPositionAndRadius     *m_localPositionArrayPtr;
+       int                             m_localPositionArraySize;
+       char    m_padding[4];
+};
+
+// clang-format on
+
+SIMD_FORCE_INLINE int btMultiSphereShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btMultiSphereShapeData);
+}
+
+#endif  //BT_MULTI_SPHERE_MINKOWSKI_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
new file mode 100644 (file)
index 0000000..30108c9
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
new file mode 100644 (file)
index 0000000..d1d42f8
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+#define BT_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;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btMultimaterialTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true) : btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
+       {
+               m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+
+               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)
+       {
+               m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+
+               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;
+*/
+       }
+       //debugging
+       virtual const char *getName() const { return "MULTIMATERIALTRIANGLEMESH"; }
+
+       ///Obtains the material for a specific triangle
+       const btMaterial *getMaterialProperties(int partID, int triIndex);
+};
+
+#endif  //BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
new file mode 100644 (file)
index 0000000..863ea6d
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btOptimizedBvh.h"
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+
+btOptimizedBvh::btOptimizedBvh()
+{
+}
+
+btOptimizedBvh::~btOptimizedBvh()
+{
+}
+
+void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax)
+{
+       m_useQuantization = useQuantizedAabbCompression;
+
+       // NodeArray    triangleNodes;
+
+       struct NodeTriangleCallback : public btInternalTriangleIndexCallback
+       {
+               NodeArray& m_triangleNodes;
+
+               NodeTriangleCallback& operator=(NodeTriangleCallback& other)
+               {
+                       m_triangleNodes.copyFromArray(other.m_triangleNodes);
+                       return *this;
+               }
+
+               NodeTriangleCallback(NodeArray& triangleNodes)
+                       : m_triangleNodes(triangleNodes)
+               {
+               }
+
+               virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+               {
+                       btOptimizedBvhNode node;
+                       btVector3 aabbMin, aabbMax;
+                       aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+                       aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+                       aabbMin.setMin(triangle[0]);
+                       aabbMax.setMax(triangle[0]);
+                       aabbMin.setMin(triangle[1]);
+                       aabbMax.setMax(triangle[1]);
+                       aabbMin.setMin(triangle[2]);
+                       aabbMax.setMax(triangle[2]);
+
+                       //with quantization?
+                       node.m_aabbMinOrg = aabbMin;
+                       node.m_aabbMaxOrg = aabbMax;
+
+                       node.m_escapeIndex = -1;
+
+                       //for child nodes
+                       node.m_subPart = partId;
+                       node.m_triangleIndex = triangleIndex;
+                       m_triangleNodes.push_back(node);
+               }
+       };
+       struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
+       {
+               QuantizedNodeArray& m_triangleNodes;
+               const btQuantizedBvh* m_optimizedTree;  // for quantization
+
+               QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
+               {
+                       m_triangleNodes.copyFromArray(other.m_triangleNodes);
+                       m_optimizedTree = other.m_optimizedTree;
+                       return *this;
+               }
+
+               QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes, const btQuantizedBvh* tree)
+                       : m_triangleNodes(triangleNodes), m_optimizedTree(tree)
+               {
+               }
+
+               virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+               {
+                       // 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);
+
+                       btQuantizedBvhNode node;
+                       btVector3 aabbMin, aabbMax;
+                       aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+                       aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+                       aabbMin.setMin(triangle[0]);
+                       aabbMax.setMax(triangle[0]);
+                       aabbMin.setMin(triangle[1]);
+                       aabbMax.setMax(triangle[1]);
+                       aabbMin.setMin(triangle[2]);
+                       aabbMax.setMax(triangle[2]);
+
+                       //PCK: add these checks for zero dimensions of aabb
+                       const btScalar MIN_AABB_DIMENSION = btScalar(0.002);
+                       const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001);
+                       if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION)
+                       {
+                               aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION);
+                               aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION);
+                       }
+                       if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION)
+                       {
+                               aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION);
+                               aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION);
+                       }
+                       if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION)
+                       {
+                               aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION);
+                               aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION);
+                       }
+
+                       m_optimizedTree->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);
+               }
+       };
+
+       int numLeafNodes = 0;
+
+       if (m_useQuantization)
+       {
+               //initialize quantization values
+               setQuantizationValues(bvhAabbMin, bvhAabbMax);
+
+               QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes, this);
+
+               triangles->InternalProcessAllTriangles(&callback, m_bvhAabbMin, m_bvhAabbMax);
+
+               //now we have an array of leafnodes in m_leafNodes
+               numLeafNodes = m_quantizedLeafNodes.size();
+
+               m_quantizedContiguousNodes.resize(2 * numLeafNodes);
+       }
+       else
+       {
+               NodeTriangleCallback callback(m_leafNodes);
+
+               btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+               btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+
+               triangles->InternalProcessAllTriangles(&callback, aabbMin, aabbMax);
+
+               //now we have an array of leafnodes in m_leafNodes
+               numLeafNodes = m_leafNodes.size();
+
+               m_contiguousNodes.resize(2 * numLeafNodes);
+       }
+
+       m_curNodeIndex = 0;
+
+       buildTree(0, numLeafNodes);
+
+       ///if the entire tree is small then subtree size, we need to create a header info for the tree
+       if (m_useQuantization && !m_SubtreeHeaders.size())
+       {
+               btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+               subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+               subtree.m_rootNodeIndex = 0;
+               subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+       }
+
+       //PCK: update the copy of the size
+       m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+       //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+       m_quantizedLeafNodes.clear();
+       m_leafNodes.clear();
+}
+
+void btOptimizedBvh::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
+       btAssert(m_useQuantization);
+
+       btAssert(aabbMin.getX() > m_bvhAabbMin.getX());
+       btAssert(aabbMin.getY() > m_bvhAabbMin.getY());
+       btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ());
+
+       btAssert(aabbMax.getX() < m_bvhAabbMax.getX());
+       btAssert(aabbMax.getY() < m_bvhAabbMax.getY());
+       btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ());
+
+       ///we should update all quantization values, using updateBvhNodes(meshInterface);
+       ///but we only update chunks that overlap the given aabb
+
+       unsigned short quantizedQueryAabbMin[3];
+       unsigned short quantizedQueryAabbMax[3];
+
+       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];
+
+               //PCK: unsigned instead of bool
+               unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
+               if (overlap != 0)
+               {
+                       updateBvhNodes(meshInterface, subtree.m_rootNodeIndex, subtree.m_rootNodeIndex + subtree.m_subtreeSize, i);
+
+                       subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+               }
+       }
+}
+
+void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface, int firstNode, int endNode, int index)
+{
+       (void)index;
+
+       btAssert(m_useQuantization);
+
+       int curNodeSubPart = -1;
+
+       //get access info to trianglemesh data
+       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;
+       const btVector3& meshScaling = meshInterface->getScaling();
+
+       int i;
+       for (i = endNode - 1; i >= firstNode; i--)
+       {
+               btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
+               if (curNode.isLeafNode())
+               {
+                       //recalc aabb from triangle data
+                       int 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);
+
+                               curNodeSubPart = nodeSubPart;
+                       }
+                       //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
+
+                       unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
+
+                       for (int j = 2; j >= 0; j--)
+                       {
+                               int graphicsindex;
+                                switch (indicestype) {
+                                        case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
+                                        case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
+                                        case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
+                                        default: btAssert(0);
+                                }
+                               if (type == PHY_FLOAT)
+                               {
+                                       float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
+                                       triangleVerts[j] = btVector3(
+                                               graphicsbase[0] * meshScaling.getX(),
+                                               graphicsbase[1] * meshScaling.getY(),
+                                               graphicsbase[2] * meshScaling.getZ());
+                               }
+                               else
+                               {
+                                       double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
+                                       triangleVerts[j] = btVector3(btScalar(graphicsbase[0] * meshScaling.getX()), btScalar(graphicsbase[1] * meshScaling.getY()), btScalar(graphicsbase[2] * meshScaling.getZ()));
+                               }
+                       }
+
+                       aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+                       aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+                       aabbMin.setMin(triangleVerts[0]);
+                       aabbMax.setMax(triangleVerts[0]);
+                       aabbMin.setMin(triangleVerts[1]);
+                       aabbMax.setMax(triangleVerts[1]);
+                       aabbMin.setMin(triangleVerts[2]);
+                       aabbMax.setMax(triangleVerts[2]);
+
+                       quantize(&curNode.m_quantizedAabbMin[0], aabbMin, 0);
+                       quantize(&curNode.m_quantizedAabbMax[0], aabbMax, 1);
+               }
+               else
+               {
+                       //combine aabb from both children
+
+                       btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i + 1];
+
+                       btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i + 2] : &m_quantizedContiguousNodes[i + 1 + leftChildNode->getEscapeIndex()];
+
+                       {
+                               for (int i = 0; i < 3; i++)
+                               {
+                                       curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
+                                       if (curNode.m_quantizedAabbMin[i] > rightChildNode->m_quantizedAabbMin[i])
+                                               curNode.m_quantizedAabbMin[i] = rightChildNode->m_quantizedAabbMin[i];
+
+                                       curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
+                                       if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
+                                               curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
+                               }
+                       }
+               }
+       }
+
+       if (curNodeSubPart >= 0)
+               meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+}
+
+///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)
+{
+       btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
+
+       //we don't add additional data so just do a static upcast
+       return static_cast<btOptimizedBvh*>(bvh);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btOptimizedBvh.h
new file mode 100644 (file)
index 0000000..22f131c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///Contains contributions from Disney Studio's
+
+#ifndef BT_OPTIMIZED_BVH_H
+#define BT_OPTIMIZED_BVH_H
+
+#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h"
+
+class btStridingMeshInterface;
+
+///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
+ATTRIBUTE_ALIGNED16(class)
+btOptimizedBvh : public btQuantizedBvh
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+protected:
+public:
+       btOptimizedBvh();
+
+       virtual ~btOptimizedBvh();
+
+       void build(btStridingMeshInterface * triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
+
+       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 serializeInPlace(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
+       {
+               return btQuantizedBvh::serialize(o_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
+       }
+
+       ///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  //BT_OPTIMIZED_BVH_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
new file mode 100644 (file)
index 0000000..521ecfc
--- /dev/null
@@ -0,0 +1,549 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#if defined(_WIN32) || defined(__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "btConvexPolyhedron.h"
+#include "LinearMath/btConvexHullComputer.h"
+#include <new>
+#include "LinearMath/btGeometryUtil.h"
+#include "LinearMath/btGrahamScan2dConvexHull.h"
+
+btPolyhedralConvexShape::btPolyhedralConvexShape() : btConvexInternalShape(),
+                                                                                                        m_polyhedron(0)
+{
+}
+
+btPolyhedralConvexShape::~btPolyhedralConvexShape()
+{
+       if (m_polyhedron)
+       {
+               m_polyhedron->~btConvexPolyhedron();
+               btAlignedFree(m_polyhedron);
+       }
+}
+
+void btPolyhedralConvexShape::setPolyhedralFeatures(btConvexPolyhedron& polyhedron)
+{
+       if (m_polyhedron)
+       {
+               *m_polyhedron = polyhedron;
+       }
+       else
+       {
+               void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron), 16);
+               m_polyhedron = new (mem) btConvexPolyhedron(polyhedron);
+       }
+}
+
+bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMargin)
+{
+       if (m_polyhedron)
+       {
+               m_polyhedron->~btConvexPolyhedron();
+               btAlignedFree(m_polyhedron);
+       }
+
+       void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron), 16);
+       m_polyhedron = new (mem) btConvexPolyhedron;
+
+       btAlignedObjectArray<btVector3> orgVertices;
+
+       for (int i = 0; i < getNumVertices(); i++)
+       {
+               btVector3& newVertex = orgVertices.expand();
+               getVertex(i, newVertex);
+       }
+
+       btConvexHullComputer conv;
+
+       if (shiftVerticesByMargin)
+       {
+               btAlignedObjectArray<btVector3> planeEquations;
+               btGeometryUtil::getPlaneEquationsFromVertices(orgVertices, planeEquations);
+
+               btAlignedObjectArray<btVector3> shiftedPlaneEquations;
+               for (int p = 0; p < planeEquations.size(); p++)
+               {
+                       btVector3 plane = planeEquations[p];
+                       //         btScalar margin = getMargin();
+                       plane[3] -= getMargin();
+                       shiftedPlaneEquations.push_back(plane);
+               }
+
+               btAlignedObjectArray<btVector3> tmpVertices;
+
+               btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations, tmpVertices);
+
+               conv.compute(&tmpVertices[0].getX(), sizeof(btVector3), tmpVertices.size(), 0.f, 0.f);
+       }
+       else
+       {
+               conv.compute(&orgVertices[0].getX(), sizeof(btVector3), orgVertices.size(), 0.f, 0.f);
+       }
+
+#ifndef BT_RECONSTRUCT_FACES
+
+       int numVertices = conv.vertices.size();
+       m_polyhedron->m_vertices.resize(numVertices);
+       for (int p = 0; p < numVertices; p++)
+       {
+               m_polyhedron->m_vertices[p] = conv.vertices[p];
+       }
+
+       int v0, v1;
+       for (int j = 0; j < conv.faces.size(); j++)
+       {
+               btVector3 edges[3];
+               int numEdges = 0;
+               btFace combinedFace;
+               const btConvexHullComputer::Edge* edge = &conv.edges[conv.faces[j]];
+               v0 = edge->getSourceVertex();
+               int prevVertex = v0;
+               combinedFace.m_indices.push_back(v0);
+               v1 = edge->getTargetVertex();
+               while (v1 != v0)
+               {
+                       btVector3 wa = conv.vertices[prevVertex];
+                       btVector3 wb = conv.vertices[v1];
+                       btVector3 newEdge = wb - wa;
+                       newEdge.normalize();
+                       if (numEdges < 2)
+                               edges[numEdges++] = newEdge;
+
+                       //face->addIndex(v1);
+                       combinedFace.m_indices.push_back(v1);
+                       edge = edge->getNextEdgeOfFace();
+                       prevVertex = v1;
+                       int v01 = edge->getSourceVertex();
+                       v1 = edge->getTargetVertex();
+               }
+
+               btAssert(combinedFace.m_indices.size() > 2);
+
+               btVector3 faceNormal = edges[0].cross(edges[1]);
+               faceNormal.normalize();
+
+               btScalar planeEq = 1e30f;
+
+               for (int v = 0; v < combinedFace.m_indices.size(); v++)
+               {
+                       btScalar eq = m_polyhedron->m_vertices[combinedFace.m_indices[v]].dot(faceNormal);
+                       if (planeEq > eq)
+                       {
+                               planeEq = eq;
+                       }
+               }
+               combinedFace.m_plane[0] = faceNormal.getX();
+               combinedFace.m_plane[1] = faceNormal.getY();
+               combinedFace.m_plane[2] = faceNormal.getZ();
+               combinedFace.m_plane[3] = -planeEq;
+
+               m_polyhedron->m_faces.push_back(combinedFace);
+       }
+
+#else  //BT_RECONSTRUCT_FACES
+
+       btAlignedObjectArray<btVector3> faceNormals;
+       int numFaces = conv.faces.size();
+       faceNormals.resize(numFaces);
+       btConvexHullComputer* convexUtil = &conv;
+
+       btAlignedObjectArray<btFace> tmpFaces;
+       tmpFaces.resize(numFaces);
+
+       int numVertices = convexUtil->vertices.size();
+       m_polyhedron->m_vertices.resize(numVertices);
+       for (int p = 0; p < numVertices; p++)
+       {
+               m_polyhedron->m_vertices[p] = convexUtil->vertices[p];
+       }
+
+       for (int i = 0; i < numFaces; i++)
+       {
+               int face = convexUtil->faces[i];
+               //printf("face=%d\n",face);
+               const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face];
+               const btConvexHullComputer::Edge* edge = firstEdge;
+
+               btVector3 edges[3];
+               int numEdges = 0;
+               //compute face normals
+
+               do
+               {
+                       int src = edge->getSourceVertex();
+                       tmpFaces[i].m_indices.push_back(src);
+                       int targ = edge->getTargetVertex();
+                       btVector3 wa = convexUtil->vertices[src];
+
+                       btVector3 wb = convexUtil->vertices[targ];
+                       btVector3 newEdge = wb - wa;
+                       newEdge.normalize();
+                       if (numEdges < 2)
+                               edges[numEdges++] = newEdge;
+
+                       edge = edge->getNextEdgeOfFace();
+               } while (edge != firstEdge);
+
+               btScalar planeEq = 1e30f;
+
+               if (numEdges == 2)
+               {
+                       faceNormals[i] = edges[0].cross(edges[1]);
+                       faceNormals[i].normalize();
+                       tmpFaces[i].m_plane[0] = faceNormals[i].getX();
+                       tmpFaces[i].m_plane[1] = faceNormals[i].getY();
+                       tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
+                       tmpFaces[i].m_plane[3] = planeEq;
+               }
+               else
+               {
+                       btAssert(0);  //degenerate?
+                       faceNormals[i].setZero();
+               }
+
+               for (int v = 0; v < tmpFaces[i].m_indices.size(); v++)
+               {
+                       btScalar eq = m_polyhedron->m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
+                       if (planeEq > eq)
+                       {
+                               planeEq = eq;
+                       }
+               }
+               tmpFaces[i].m_plane[3] = -planeEq;
+       }
+
+       //merge coplanar faces and copy them to m_polyhedron
+
+       btScalar faceWeldThreshold = 0.999f;
+       btAlignedObjectArray<int> todoFaces;
+       for (int i = 0; i < tmpFaces.size(); i++)
+               todoFaces.push_back(i);
+
+       while (todoFaces.size())
+       {
+               btAlignedObjectArray<int> coplanarFaceGroup;
+               int refFace = todoFaces[todoFaces.size() - 1];
+
+               coplanarFaceGroup.push_back(refFace);
+               btFace& faceA = tmpFaces[refFace];
+               todoFaces.pop_back();
+
+               btVector3 faceNormalA(faceA.m_plane[0], faceA.m_plane[1], faceA.m_plane[2]);
+               for (int j = todoFaces.size() - 1; j >= 0; j--)
+               {
+                       int i = todoFaces[j];
+                       btFace& faceB = tmpFaces[i];
+                       btVector3 faceNormalB(faceB.m_plane[0], faceB.m_plane[1], faceB.m_plane[2]);
+                       if (faceNormalA.dot(faceNormalB) > faceWeldThreshold)
+                       {
+                               coplanarFaceGroup.push_back(i);
+                               todoFaces.remove(i);
+                       }
+               }
+
+               bool did_merge = false;
+               if (coplanarFaceGroup.size() > 1)
+               {
+                       //do the merge: use Graham Scan 2d convex hull
+
+                       btAlignedObjectArray<GrahamVector3> orgpoints;
+                       btVector3 averageFaceNormal(0, 0, 0);
+
+                       for (int i = 0; i < coplanarFaceGroup.size(); i++)
+                       {
+                               //                              m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
+
+                               btFace& face = tmpFaces[coplanarFaceGroup[i]];
+                               btVector3 faceNormal(face.m_plane[0], face.m_plane[1], face.m_plane[2]);
+                               averageFaceNormal += faceNormal;
+                               for (int f = 0; f < face.m_indices.size(); f++)
+                               {
+                                       int orgIndex = face.m_indices[f];
+                                       btVector3 pt = m_polyhedron->m_vertices[orgIndex];
+
+                                       bool found = false;
+
+                                       for (int i = 0; i < orgpoints.size(); i++)
+                                       {
+                                               //if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
+                                               if (orgpoints[i].m_orgIndex == orgIndex)
+                                               {
+                                                       found = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found)
+                                               orgpoints.push_back(GrahamVector3(pt, orgIndex));
+                               }
+                       }
+
+                       btFace combinedFace;
+                       for (int i = 0; i < 4; i++)
+                               combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];
+
+                       btAlignedObjectArray<GrahamVector3> hull;
+
+                       averageFaceNormal.normalize();
+                       GrahamScanConvexHull2D(orgpoints, hull, averageFaceNormal);
+
+                       for (int i = 0; i < hull.size(); i++)
+                       {
+                               combinedFace.m_indices.push_back(hull[i].m_orgIndex);
+                               for (int k = 0; k < orgpoints.size(); k++)
+                               {
+                                       if (orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
+                                       {
+                                               orgpoints[k].m_orgIndex = -1;  // invalidate...
+                                               break;
+                                       }
+                               }
+                       }
+
+                       // are there rejected vertices?
+                       bool reject_merge = false;
+
+                       for (int i = 0; i < orgpoints.size(); i++)
+                       {
+                               if (orgpoints[i].m_orgIndex == -1)
+                                       continue;  // this is in the hull...
+                               // this vertex is rejected -- is anybody else using this vertex?
+                               for (int j = 0; j < tmpFaces.size(); j++)
+                               {
+                                       btFace& face = tmpFaces[j];
+                                       // is this a face of the current coplanar group?
+                                       bool is_in_current_group = false;
+                                       for (int k = 0; k < coplanarFaceGroup.size(); k++)
+                                       {
+                                               if (coplanarFaceGroup[k] == j)
+                                               {
+                                                       is_in_current_group = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (is_in_current_group)  // ignore this face...
+                                               continue;
+                                       // does this face use this rejected vertex?
+                                       for (int v = 0; v < face.m_indices.size(); v++)
+                                       {
+                                               if (face.m_indices[v] == orgpoints[i].m_orgIndex)
+                                               {
+                                                       // this rejected vertex is used in another face -- reject merge
+                                                       reject_merge = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (reject_merge)
+                                               break;
+                               }
+                               if (reject_merge)
+                                       break;
+                       }
+
+                       if (!reject_merge)
+                       {
+                               // do this merge!
+                               did_merge = true;
+                               m_polyhedron->m_faces.push_back(combinedFace);
+                       }
+               }
+               if (!did_merge)
+               {
+                       for (int i = 0; i < coplanarFaceGroup.size(); i++)
+                       {
+                               btFace face = tmpFaces[coplanarFaceGroup[i]];
+                               m_polyhedron->m_faces.push_back(face);
+                       }
+               }
+       }
+
+#endif  //BT_RECONSTRUCT_FACES
+
+       m_polyhedron->initialize();
+
+       return true;
+}
+
+#ifndef MIN
+#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
+{
+       btVector3 supVec(0, 0, 0);
+#ifndef __SPU__
+       int i;
+       btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+       btVector3 vec = vec0;
+       btScalar lenSqr = vec.length2();
+       if (lenSqr < btScalar(0.0001))
+       {
+               vec.setValue(1, 0, 0);
+       }
+       else
+       {
+               btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
+               vec *= rlen;
+       }
+
+       btVector3 vtx;
+       btScalar newDot;
+
+       for (int k = 0; k < getNumVertices(); k += 128)
+       {
+               btVector3 temp[128];
+               int inner_count = MIN(getNumVertices() - k, 128);
+               for (i = 0; i < inner_count; i++)
+                       getVertex(i, temp[i]);
+               i = (int)vec.maxDot(temp, inner_count, newDot);
+               if (newDot > maxDot)
+               {
+                       maxDot = newDot;
+                       supVec = temp[i];
+               }
+       }
+
+#endif  //__SPU__
+       return supVec;
+}
+
+void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+#ifndef __SPU__
+       int i;
+
+       btVector3 vtx;
+       btScalar newDot;
+
+       for (i = 0; i < numVectors; i++)
+       {
+               supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+       }
+
+       for (int j = 0; j < numVectors; j++)
+       {
+               const btVector3& vec = vectors[j];
+
+               for (int k = 0; k < getNumVertices(); k += 128)
+               {
+                       btVector3 temp[128];
+                       int inner_count = MIN(getNumVertices() - k, 128);
+                       for (i = 0; i < inner_count; i++)
+                               getVertex(i, temp[i]);
+                       i = (int)vec.maxDot(temp, inner_count, newDot);
+                       if (newDot > supportVerticesOut[j][3])
+                       {
+                               supportVerticesOut[j] = temp[i];
+                               supportVerticesOut[j][3] = newDot;
+                       }
+               }
+       }
+
+#endif  //__SPU__
+}
+
+void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+#ifndef __SPU__
+       //not yet, return box inertia
+
+       btScalar margin = getMargin();
+
+       btTransform ident;
+       ident.setIdentity();
+       btVector3 aabbMin, aabbMax;
+       getAabb(ident, aabbMin, aabbMax);
+       btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
+
+       btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
+       btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
+       btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
+       const btScalar x2 = lx * lx;
+       const btScalar y2 = ly * ly;
+       const btScalar z2 = lz * lz;
+       const btScalar scaledmass = mass * btScalar(0.08333333);
+
+       inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
+#endif  //__SPU__
+}
+
+void btPolyhedralConvexAabbCachingShape::setLocalScaling(const btVector3& scaling)
+{
+       btConvexInternalShape::setLocalScaling(scaling);
+       recalcLocalAabb();
+}
+
+btPolyhedralConvexAabbCachingShape::btPolyhedralConvexAabbCachingShape()
+       : btPolyhedralConvexShape(),
+         m_localAabbMin(1, 1, 1),
+         m_localAabbMax(-1, -1, -1),
+         m_isLocalAabbValid(false)
+{
+}
+
+void btPolyhedralConvexAabbCachingShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       getNonvirtualAabb(trans, aabbMin, aabbMax, getMargin());
+}
+
+void btPolyhedralConvexAabbCachingShape::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++)
+       {
+               btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
+               vec[i] = btScalar(1.);
+               btVector3 tmp = localGetSupportingVertex(vec);
+               m_localAabbMax[i] = tmp[i];
+               vec[i] = btScalar(-1.);
+               tmp = localGetSupportingVertex(vec);
+               m_localAabbMin[i] = tmp[i];
+       }
+#endif
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
new file mode 100644 (file)
index 0000000..b3ffab7
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_POLYHEDRAL_CONVEX_SHAPE_H
+#define BT_POLYHEDRAL_CONVEX_SHAPE_H
+
+#include "LinearMath/btMatrix3x3.h"
+#include "btConvexInternalShape.h"
+class btConvexPolyhedron;
+
+///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
+ATTRIBUTE_ALIGNED16(class)
+btPolyhedralConvexShape : public btConvexInternalShape
+{
+protected:
+       btConvexPolyhedron* m_polyhedron;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btPolyhedralConvexShape();
+
+       virtual ~btPolyhedralConvexShape();
+
+       ///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges)
+       ///experimental/work-in-progress
+       virtual bool initializePolyhedralFeatures(int shiftVerticesByMargin = 0);
+
+       virtual void setPolyhedralFeatures(btConvexPolyhedron & polyhedron);
+
+       const btConvexPolyhedron* getConvexPolyhedron() const
+       {
+               return m_polyhedron;
+       }
+
+       //brute force implementations
+
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       virtual int getNumVertices() const = 0;
+       virtual int getNumEdges() const = 0;
+       virtual void getEdge(int i, btVector3& pa, btVector3& pb) const = 0;
+       virtual void getVertex(int i, btVector3& vtx) const = 0;
+       virtual int getNumPlanes() const = 0;
+       virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const = 0;
+       //      virtual int getIndex(int i) const = 0 ;
+
+       virtual bool isInside(const btVector3& pt, btScalar tolerance) const = 0;
+};
+
+///The btPolyhedralConvexAabbCachingShape adds aabb caching to the btPolyhedralConvexShape
+class btPolyhedralConvexAabbCachingShape : public btPolyhedralConvexShape
+{
+       btVector3 m_localAabbMin;
+       btVector3 m_localAabbMax;
+       bool m_isLocalAabbValid;
+
+protected:
+       void setCachedLocalAabb(const btVector3& aabbMin, const btVector3& aabbMax)
+       {
+               m_isLocalAabbValid = true;
+               m_localAabbMin = aabbMin;
+               m_localAabbMax = aabbMax;
+       }
+
+       inline void getCachedLocalAabb(btVector3& aabbMin, btVector3& aabbMax) const
+       {
+               btAssert(m_isLocalAabbValid);
+               aabbMin = m_localAabbMin;
+               aabbMax = m_localAabbMax;
+       }
+
+protected:
+       btPolyhedralConvexAabbCachingShape();
+
+public:
+       inline void getNonvirtualAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax, btScalar margin) const
+       {
+               //lazy evaluation of local aabb
+               btAssert(m_isLocalAabbValid);
+               btTransformAabb(m_localAabbMin, m_localAabbMax, margin, trans, aabbMin, aabbMax);
+       }
+
+       virtual void setLocalScaling(const btVector3& scaling);
+
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       void recalcLocalAabb();
+};
+
+#endif  //BT_POLYHEDRAL_CONVEX_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
new file mode 100644 (file)
index 0000000..f427319
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btScaledBvhTriangleMeshShape.h"
+
+btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape, const btVector3& localScaling)
+       : m_localScaling(localScaling), m_bvhTriMeshShape(childShape)
+{
+       m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
+}
+
+btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape()
+{
+}
+
+class btScaledTriangleCallback : public btTriangleCallback
+{
+       btTriangleCallback* m_originalCallback;
+
+       btVector3 m_localScaling;
+
+public:
+       btScaledTriangleCallback(btTriangleCallback* originalCallback, const btVector3& localScaling)
+               : m_originalCallback(originalCallback),
+                 m_localScaling(localScaling)
+       {
+       }
+
+       virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+       {
+               btVector3 newTriangle[3];
+               newTriangle[0] = triangle[0] * m_localScaling;
+               newTriangle[1] = triangle[1] * m_localScaling;
+               newTriangle[2] = triangle[2] * m_localScaling;
+               m_originalCallback->processTriangle(&newTriangle[0], partId, triangleIndex);
+       }
+};
+
+void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+       btScaledTriangleCallback scaledCallback(callback, m_localScaling);
+
+       btVector3 invLocalScaling(1.f / m_localScaling.getX(), 1.f / m_localScaling.getY(), 1.f / m_localScaling.getZ());
+       btVector3 scaledAabbMin, scaledAabbMax;
+
+       ///support negative scaling
+       scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
+       scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
+       scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
+       scaledAabbMin[3] = 0.f;
+
+       scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
+       scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
+       scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
+       scaledAabbMax[3] = 0.f;
+
+       m_bvhTriMeshShape->processAllTriangles(&scaledCallback, scaledAabbMin, scaledAabbMax);
+}
+
+void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin();
+       btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax();
+
+       btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling;
+       btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling;
+
+       localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
+       localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
+       localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
+       localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
+       localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
+       localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
+
+       btVector3 localHalfExtents = btScalar(0.5) * (localAabbMax - localAabbMin);
+       btScalar margin = m_bvhTriMeshShape->getMargin();
+       localHalfExtents += btVector3(margin, margin, margin);
+       btVector3 localCenter = btScalar(0.5) * (localAabbMax + localAabbMin);
+
+       btMatrix3x3 abs_b = trans.getBasis().absolute();
+
+       btVector3 center = trans(localCenter);
+
+       btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+       aabbMin = center - extent;
+       aabbMax = center + extent;
+}
+
+void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+       m_localScaling = scaling;
+}
+
+const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const
+{
+       return m_localScaling;
+}
+
+void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       ///don't make this a movable object!
+       //      btAssert(0);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
new file mode 100644 (file)
index 0000000..4d6feb6
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
+#define BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+
+///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape.
+///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling'
+ATTRIBUTE_ALIGNED16(class)
+btScaledBvhTriangleMeshShape : public btConcaveShape
+{
+       btVector3 m_localScaling;
+
+       btBvhTriangleMeshShape* m_bvhTriMeshShape;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape * childShape, const btVector3& localScaling);
+
+       virtual ~btScaledBvhTriangleMeshShape();
+
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+       virtual void setLocalScaling(const btVector3& scaling);
+       virtual const btVector3& getLocalScaling() const;
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+
+       btBvhTriangleMeshShape* getChildShape()
+       {
+               return m_bvhTriMeshShape;
+       }
+
+       const btBvhTriangleMeshShape* getChildShape() const
+       {
+               return m_bvhTriMeshShape;
+       }
+
+       //debugging
+       virtual const char* getName() const { return "SCALEDBVHTRIANGLEMESH"; }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btScaledTriangleMeshShapeData
+{
+       btTriangleMeshShapeData m_trimeshShapeData;
+
+       btVector3FloatData m_localScaling;
+};
+
+SIMD_FORCE_INLINE int btScaledBvhTriangleMeshShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btScaledTriangleMeshShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btScaledBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btScaledTriangleMeshShapeData* scaledMeshData = (btScaledTriangleMeshShapeData*)dataBuffer;
+       m_bvhTriMeshShape->serialize(&scaledMeshData->m_trimeshShapeData, serializer);
+       scaledMeshData->m_trimeshShapeData.m_collisionShapeData.m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
+       m_localScaling.serializeFloat(scaledMeshData->m_localScaling);
+       return "btScaledTriangleMeshShapeData";
+}
+
+#endif  //BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp
new file mode 100644 (file)
index 0000000..23c95ad
--- /dev/null
@@ -0,0 +1,95 @@
+#include "btSdfCollisionShape.h"
+#include "btMiniSDF.h"
+#include "LinearMath/btAabbUtil2.h"
+
+ATTRIBUTE_ALIGNED16(struct)
+btSdfCollisionShapeInternalData
+{
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btVector3 m_localScaling;
+       btScalar m_margin;
+       btMiniSDF m_sdf;
+
+       btSdfCollisionShapeInternalData()
+               : m_localScaling(1, 1, 1),
+                 m_margin(0)
+       {
+       }
+};
+
+bool btSdfCollisionShape::initializeSDF(const char* sdfData, int sizeInBytes)
+{
+       bool valid = m_data->m_sdf.load(sdfData, sizeInBytes);
+       return valid;
+}
+btSdfCollisionShape::btSdfCollisionShape()
+{
+       m_shapeType = SDF_SHAPE_PROXYTYPE;
+       m_data = new btSdfCollisionShapeInternalData();
+
+       //"E:/develop/bullet3/data/toys/ground_hole64_64_8.cdf");//ground_cube.cdf");
+       /*unsigned int field_id=0;
+       Eigen::Vector3d x (1,10,1);
+       Eigen::Vector3d gradient;
+       double dist = m_data->m_sdf.interpolate(field_id, x, &gradient);
+       printf("dist=%g\n", dist);
+       */
+}
+btSdfCollisionShape::~btSdfCollisionShape()
+{
+       delete m_data;
+}
+
+void btSdfCollisionShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       btAssert(m_data->m_sdf.isValid());
+       btVector3 localAabbMin = m_data->m_sdf.m_domain.m_min;
+       btVector3 localAabbMax = m_data->m_sdf.m_domain.m_max;
+       btScalar margin(0);
+       btTransformAabb(localAabbMin, localAabbMax, margin, t, aabbMin, aabbMax);
+}
+
+void btSdfCollisionShape::setLocalScaling(const btVector3& scaling)
+{
+       m_data->m_localScaling = scaling;
+}
+const btVector3& btSdfCollisionShape::getLocalScaling() const
+{
+       return m_data->m_localScaling;
+}
+void btSdfCollisionShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       inertia.setValue(0, 0, 0);
+}
+const char* btSdfCollisionShape::getName() const
+{
+       return "btSdfCollisionShape";
+}
+void btSdfCollisionShape::setMargin(btScalar margin)
+{
+       m_data->m_margin = margin;
+}
+btScalar btSdfCollisionShape::getMargin() const
+{
+       return m_data->m_margin;
+}
+
+void btSdfCollisionShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+       //not yet
+}
+
+bool btSdfCollisionShape::queryPoint(const btVector3& ptInSDF, btScalar& distOut, btVector3& normal)
+{
+       int field = 0;
+       btVector3 grad;
+       double dist;
+       bool hasResult = m_data->m_sdf.interpolate(field, dist, ptInSDF, &grad);
+       if (hasResult)
+       {
+               normal.setValue(grad[0], grad[1], grad[2]);
+               distOut = dist;
+       }
+       return hasResult;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSdfCollisionShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSdfCollisionShape.h
new file mode 100644 (file)
index 0000000..3989d62
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef BT_SDF_COLLISION_SHAPE_H
+#define BT_SDF_COLLISION_SHAPE_H
+
+#include "btConcaveShape.h"
+
+class btSdfCollisionShape : public btConcaveShape
+{
+       struct btSdfCollisionShapeInternalData* m_data;
+
+public:
+       btSdfCollisionShape();
+       virtual ~btSdfCollisionShape();
+
+       bool initializeSDF(const char* sdfData, int sizeInBytes);
+
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+       virtual void setLocalScaling(const btVector3& scaling);
+       virtual const btVector3& getLocalScaling() const;
+       virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
+       virtual const char* getName() const;
+       virtual void setMargin(btScalar margin);
+       virtual btScalar getMargin() const;
+
+       virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+
+       bool queryPoint(const btVector3& ptInSDF, btScalar& distOut, btVector3& normal);
+};
+
+#endif  //BT_SDF_COLLISION_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btShapeHull.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btShapeHull.cpp
new file mode 100644 (file)
index 0000000..a2c490f
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//btShapeHull was implemented by John McCutchan.
+
+#include "btShapeHull.h"
+#include "LinearMath/btConvexHull.h"
+
+#define NUM_UNITSPHERE_POINTS 42
+#define NUM_UNITSPHERE_POINTS_HIGHRES 256
+
+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 highres)
+{
+       
+       int numSampleDirections = highres ? NUM_UNITSPHERE_POINTS_HIGHRES : NUM_UNITSPHERE_POINTS;
+       btVector3 supportPoints[NUM_UNITSPHERE_POINTS_HIGHRES + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+       int i;
+       for (i = 0; i < numSampleDirections; i++)
+       {
+               supportPoints[i] = m_shape->localGetSupportingVertex(getUnitSpherePoints(highres)[i]);
+       }
+
+       int numPDA = m_shape->getNumPreferredPenetrationDirections();
+       if (numPDA)
+       {
+               for (int s = 0; s < numPDA; s++)
+               {
+                       btVector3 norm;
+                       m_shape->getPreferredPenetrationDirection(s, norm);
+                       supportPoints[i++] = m_shape->localGetSupportingVertex(norm);
+                       numSampleDirections++;
+               }
+       }
+       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);
+}
+
+btVector3* btShapeHull::getUnitSpherePoints(int highres)
+{
+       static btVector3 sUnitSpherePointsHighres[NUM_UNITSPHERE_POINTS_HIGHRES + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2] =
+               {
+                       btVector3(btScalar(0.997604), btScalar(0.067004), btScalar(0.017144)),
+                       btVector3(btScalar(0.984139), btScalar(-0.086784), btScalar(-0.154427)),
+                       btVector3(btScalar(0.971065), btScalar(0.124164), btScalar(-0.203224)),
+                       btVector3(btScalar(0.955844), btScalar(0.291173), btScalar(-0.037704)),
+                       btVector3(btScalar(0.957405), btScalar(0.212238), btScalar(0.195157)),
+                       btVector3(btScalar(0.971650), btScalar(-0.012709), btScalar(0.235561)),
+                       btVector3(btScalar(0.984920), btScalar(-0.161831), btScalar(0.059695)),
+                       btVector3(btScalar(0.946673), btScalar(-0.299288), btScalar(-0.117536)),
+                       btVector3(btScalar(0.922670), btScalar(-0.219186), btScalar(-0.317019)),
+                       btVector3(btScalar(0.928134), btScalar(-0.007265), btScalar(-0.371867)),
+                       btVector3(btScalar(0.875642), btScalar(0.198434), btScalar(-0.439988)),
+                       btVector3(btScalar(0.908035), btScalar(0.325975), btScalar(-0.262562)),
+                       btVector3(btScalar(0.864519), btScalar(0.488706), btScalar(-0.116755)),
+                       btVector3(btScalar(0.893009), btScalar(0.428046), btScalar(0.137185)),
+                       btVector3(btScalar(0.857494), btScalar(0.362137), btScalar(0.364776)),
+                       btVector3(btScalar(0.900815), btScalar(0.132524), btScalar(0.412987)),
+                       btVector3(btScalar(0.934964), btScalar(-0.241739), btScalar(0.259179)),
+                       btVector3(btScalar(0.894570), btScalar(-0.103504), btScalar(0.434263)),
+                       btVector3(btScalar(0.922085), btScalar(-0.376668), btScalar(0.086241)),
+                       btVector3(btScalar(0.862177), btScalar(-0.499154), btScalar(-0.085330)),
+                       btVector3(btScalar(0.861982), btScalar(-0.420218), btScalar(-0.282861)),
+                       btVector3(btScalar(0.818076), btScalar(-0.328256), btScalar(-0.471804)),
+                       btVector3(btScalar(0.762657), btScalar(-0.179329), btScalar(-0.621124)),
+                       btVector3(btScalar(0.826857), btScalar(0.019760), btScalar(-0.561786)),
+                       btVector3(btScalar(0.731434), btScalar(0.206599), btScalar(-0.649817)),
+                       btVector3(btScalar(0.769486), btScalar(0.379052), btScalar(-0.513770)),
+                       btVector3(btScalar(0.796806), btScalar(0.507176), btScalar(-0.328145)),
+                       btVector3(btScalar(0.679722), btScalar(0.684101), btScalar(-0.264123)),
+                       btVector3(btScalar(0.786854), btScalar(0.614886), btScalar(0.050912)),
+                       btVector3(btScalar(0.769486), btScalar(0.571141), btScalar(0.285139)),
+                       btVector3(btScalar(0.707432), btScalar(0.492789), btScalar(0.506288)),
+                       btVector3(btScalar(0.774560), btScalar(0.268037), btScalar(0.572652)),
+                       btVector3(btScalar(0.796220), btScalar(0.031230), btScalar(0.604077)),
+                       btVector3(btScalar(0.837395), btScalar(-0.320285), btScalar(0.442461)),
+                       btVector3(btScalar(0.848127), btScalar(-0.450548), btScalar(0.278307)),
+                       btVector3(btScalar(0.775536), btScalar(-0.206354), btScalar(0.596465)),
+                       btVector3(btScalar(0.816320), btScalar(-0.567007), btScalar(0.109469)),
+                       btVector3(btScalar(0.741191), btScalar(-0.668690), btScalar(-0.056832)),
+                       btVector3(btScalar(0.755632), btScalar(-0.602975), btScalar(-0.254949)),
+                       btVector3(btScalar(0.720311), btScalar(-0.521318), btScalar(-0.457165)),
+                       btVector3(btScalar(0.670746), btScalar(-0.386583), btScalar(-0.632835)),
+                       btVector3(btScalar(0.587031), btScalar(-0.219769), btScalar(-0.778836)),
+                       btVector3(btScalar(0.676015), btScalar(-0.003182), btScalar(-0.736676)),
+                       btVector3(btScalar(0.566932), btScalar(0.186963), btScalar(-0.802064)),
+                       btVector3(btScalar(0.618254), btScalar(0.398105), btScalar(-0.677533)),
+                       btVector3(btScalar(0.653964), btScalar(0.575224), btScalar(-0.490933)),
+                       btVector3(btScalar(0.525367), btScalar(0.743205), btScalar(-0.414028)),
+                       btVector3(btScalar(0.506439), btScalar(0.836528), btScalar(-0.208885)),
+                       btVector3(btScalar(0.651427), btScalar(0.756426), btScalar(-0.056247)),
+                       btVector3(btScalar(0.641670), btScalar(0.745149), btScalar(0.180908)),
+                       btVector3(btScalar(0.602643), btScalar(0.687211), btScalar(0.405180)),
+                       btVector3(btScalar(0.516586), btScalar(0.596999), btScalar(0.613447)),
+                       btVector3(btScalar(0.602252), btScalar(0.387801), btScalar(0.697573)),
+                       btVector3(btScalar(0.646549), btScalar(0.153911), btScalar(0.746956)),
+                       btVector3(btScalar(0.650842), btScalar(-0.087756), btScalar(0.753983)),
+                       btVector3(btScalar(0.740411), btScalar(-0.497404), btScalar(0.451830)),
+                       btVector3(btScalar(0.726946), btScalar(-0.619890), btScalar(0.295093)),
+                       btVector3(btScalar(0.637768), btScalar(-0.313092), btScalar(0.703624)),
+                       btVector3(btScalar(0.678942), btScalar(-0.722934), btScalar(0.126645)),
+                       btVector3(btScalar(0.489072), btScalar(-0.867195), btScalar(-0.092942)),
+                       btVector3(btScalar(0.622742), btScalar(-0.757541), btScalar(-0.194636)),
+                       btVector3(btScalar(0.596788), btScalar(-0.693576), btScalar(-0.403098)),
+                       btVector3(btScalar(0.550150), btScalar(-0.582172), btScalar(-0.598287)),
+                       btVector3(btScalar(0.474436), btScalar(-0.429745), btScalar(-0.768101)),
+                       btVector3(btScalar(0.372574), btScalar(-0.246016), btScalar(-0.894583)),
+                       btVector3(btScalar(0.480095), btScalar(-0.026513), btScalar(-0.876626)),
+                       btVector3(btScalar(0.352474), btScalar(0.177242), btScalar(-0.918787)),
+                       btVector3(btScalar(0.441848), btScalar(0.374386), btScalar(-0.814946)),
+                       btVector3(btScalar(0.492389), btScalar(0.582223), btScalar(-0.646693)),
+                       btVector3(btScalar(0.343498), btScalar(0.866080), btScalar(-0.362693)),
+                       btVector3(btScalar(0.362036), btScalar(0.745149), btScalar(-0.559639)),
+                       btVector3(btScalar(0.334131), btScalar(0.937044), btScalar(-0.099774)),
+                       btVector3(btScalar(0.486925), btScalar(0.871718), btScalar(0.052473)),
+                       btVector3(btScalar(0.452776), btScalar(0.845665), btScalar(0.281820)),
+                       btVector3(btScalar(0.399503), btScalar(0.771785), btScalar(0.494576)),
+                       btVector3(btScalar(0.296469), btScalar(0.673018), btScalar(0.677469)),
+                       btVector3(btScalar(0.392088), btScalar(0.479179), btScalar(0.785213)),
+                       btVector3(btScalar(0.452190), btScalar(0.252094), btScalar(0.855286)),
+                       btVector3(btScalar(0.478339), btScalar(0.013149), btScalar(0.877928)),
+                       btVector3(btScalar(0.481656), btScalar(-0.219380), btScalar(0.848259)),
+                       btVector3(btScalar(0.615327), btScalar(-0.494293), btScalar(0.613837)),
+                       btVector3(btScalar(0.594642), btScalar(-0.650414), btScalar(0.472325)),
+                       btVector3(btScalar(0.562249), btScalar(-0.771345), btScalar(0.297631)),
+                       btVector3(btScalar(0.467411), btScalar(-0.437133), btScalar(0.768231)),
+                       btVector3(btScalar(0.519513), btScalar(-0.847947), btScalar(0.103808)),
+                       btVector3(btScalar(0.297640), btScalar(-0.938159), btScalar(-0.176288)),
+                       btVector3(btScalar(0.446727), btScalar(-0.838615), btScalar(-0.311359)),
+                       btVector3(btScalar(0.331790), btScalar(-0.942437), btScalar(0.040762)),
+                       btVector3(btScalar(0.413358), btScalar(-0.748403), btScalar(-0.518259)),
+                       btVector3(btScalar(0.347596), btScalar(-0.621640), btScalar(-0.701737)),
+                       btVector3(btScalar(0.249831), btScalar(-0.456186), btScalar(-0.853984)),
+                       btVector3(btScalar(0.131772), btScalar(-0.262931), btScalar(-0.955678)),
+                       btVector3(btScalar(0.247099), btScalar(-0.042261), btScalar(-0.967975)),
+                       btVector3(btScalar(0.113624), btScalar(0.165965), btScalar(-0.979491)),
+                       btVector3(btScalar(0.217438), btScalar(0.374580), btScalar(-0.901220)),
+                       btVector3(btScalar(0.307983), btScalar(0.554615), btScalar(-0.772786)),
+                       btVector3(btScalar(0.166702), btScalar(0.953181), btScalar(-0.252021)),
+                       btVector3(btScalar(0.172751), btScalar(0.844499), btScalar(-0.506743)),
+                       btVector3(btScalar(0.177630), btScalar(0.711125), btScalar(-0.679876)),
+                       btVector3(btScalar(0.120064), btScalar(0.992260), btScalar(-0.030482)),
+                       btVector3(btScalar(0.289640), btScalar(0.949098), btScalar(0.122546)),
+                       btVector3(btScalar(0.239879), btScalar(0.909047), btScalar(0.340377)),
+                       btVector3(btScalar(0.181142), btScalar(0.821363), btScalar(0.540641)),
+                       btVector3(btScalar(0.066986), btScalar(0.719097), btScalar(0.691327)),
+                       btVector3(btScalar(0.156750), btScalar(0.545478), btScalar(0.823079)),
+                       btVector3(btScalar(0.236172), btScalar(0.342306), btScalar(0.909353)),
+                       btVector3(btScalar(0.277541), btScalar(0.112693), btScalar(0.953856)),
+                       btVector3(btScalar(0.295299), btScalar(-0.121974), btScalar(0.947415)),
+                       btVector3(btScalar(0.287883), btScalar(-0.349254), btScalar(0.891591)),
+                       btVector3(btScalar(0.437165), btScalar(-0.634666), btScalar(0.636869)),
+                       btVector3(btScalar(0.407113), btScalar(-0.784954), btScalar(0.466664)),
+                       btVector3(btScalar(0.375111), btScalar(-0.888193), btScalar(0.264839)),
+                       btVector3(btScalar(0.275394), btScalar(-0.560591), btScalar(0.780723)),
+                       btVector3(btScalar(0.122015), btScalar(-0.992209), btScalar(-0.024821)),
+                       btVector3(btScalar(0.087866), btScalar(-0.966156), btScalar(-0.241676)),
+                       btVector3(btScalar(0.239489), btScalar(-0.885665), btScalar(-0.397437)),
+                       btVector3(btScalar(0.167287), btScalar(-0.965184), btScalar(0.200817)),
+                       btVector3(btScalar(0.201632), btScalar(-0.776789), btScalar(-0.596335)),
+                       btVector3(btScalar(0.122015), btScalar(-0.637971), btScalar(-0.760098)),
+                       btVector3(btScalar(0.008054), btScalar(-0.464741), btScalar(-0.885214)),
+                       btVector3(btScalar(-0.116054), btScalar(-0.271096), btScalar(-0.955482)),
+                       btVector3(btScalar(-0.000727), btScalar(-0.056065), btScalar(-0.998424)),
+                       btVector3(btScalar(-0.134007), btScalar(0.152939), btScalar(-0.978905)),
+                       btVector3(btScalar(-0.025900), btScalar(0.366026), btScalar(-0.930108)),
+                       btVector3(btScalar(0.081231), btScalar(0.557337), btScalar(-0.826072)),
+                       btVector3(btScalar(-0.002874), btScalar(0.917213), btScalar(-0.398023)),
+                       btVector3(btScalar(-0.050683), btScalar(0.981761), btScalar(-0.182534)),
+                       btVector3(btScalar(-0.040536), btScalar(0.710153), btScalar(-0.702713)),
+                       btVector3(btScalar(-0.139081), btScalar(0.827973), btScalar(-0.543048)),
+                       btVector3(btScalar(-0.101029), btScalar(0.994010), btScalar(0.041152)),
+                       btVector3(btScalar(0.069328), btScalar(0.978067), btScalar(0.196133)),
+                       btVector3(btScalar(0.023860), btScalar(0.911380), btScalar(0.410645)),
+                       btVector3(btScalar(-0.153521), btScalar(0.736789), btScalar(0.658145)),
+                       btVector3(btScalar(-0.070002), btScalar(0.591750), btScalar(0.802780)),
+                       btVector3(btScalar(0.002590), btScalar(0.312948), btScalar(0.949562)),
+                       btVector3(btScalar(0.090988), btScalar(-0.020680), btScalar(0.995627)),
+                       btVector3(btScalar(0.088842), btScalar(-0.250099), btScalar(0.964006)),
+                       btVector3(btScalar(0.083378), btScalar(-0.470185), btScalar(0.878318)),
+                       btVector3(btScalar(0.240074), btScalar(-0.749764), btScalar(0.616374)),
+                       btVector3(btScalar(0.210803), btScalar(-0.885860), btScalar(0.412987)),
+                       btVector3(btScalar(0.077524), btScalar(-0.660524), btScalar(0.746565)),
+                       btVector3(btScalar(-0.096736), btScalar(-0.990070), btScalar(-0.100945)),
+                       btVector3(btScalar(-0.052634), btScalar(-0.990264), btScalar(0.127426)),
+                       btVector3(btScalar(-0.106102), btScalar(-0.938354), btScalar(-0.328340)),
+                       btVector3(btScalar(0.013323), btScalar(-0.863112), btScalar(-0.504596)),
+                       btVector3(btScalar(-0.002093), btScalar(-0.936993), btScalar(0.349161)),
+                       btVector3(btScalar(-0.106297), btScalar(-0.636610), btScalar(-0.763612)),
+                       btVector3(btScalar(-0.229430), btScalar(-0.463769), btScalar(-0.855546)),
+                       btVector3(btScalar(-0.245236), btScalar(-0.066175), btScalar(-0.966999)),
+                       btVector3(btScalar(-0.351587), btScalar(-0.270513), btScalar(-0.896145)),
+                       btVector3(btScalar(-0.370906), btScalar(0.133108), btScalar(-0.918982)),
+                       btVector3(btScalar(-0.264360), btScalar(0.346000), btScalar(-0.900049)),
+                       btVector3(btScalar(-0.151375), btScalar(0.543728), btScalar(-0.825291)),
+                       btVector3(btScalar(-0.218697), btScalar(0.912741), btScalar(-0.344346)),
+                       btVector3(btScalar(-0.274507), btScalar(0.953764), btScalar(-0.121635)),
+                       btVector3(btScalar(-0.259677), btScalar(0.692266), btScalar(-0.673044)),
+                       btVector3(btScalar(-0.350416), btScalar(0.798810), btScalar(-0.488786)),
+                       btVector3(btScalar(-0.320170), btScalar(0.941127), btScalar(0.108297)),
+                       btVector3(btScalar(-0.147667), btScalar(0.952792), btScalar(0.265034)),
+                       btVector3(btScalar(-0.188061), btScalar(0.860636), btScalar(0.472910)),
+                       btVector3(btScalar(-0.370906), btScalar(0.739900), btScalar(0.560941)),
+                       btVector3(btScalar(-0.297143), btScalar(0.585334), btScalar(0.754178)),
+                       btVector3(btScalar(-0.189622), btScalar(0.428241), btScalar(0.883393)),
+                       btVector3(btScalar(-0.091272), btScalar(0.098695), btScalar(0.990747)),
+                       btVector3(btScalar(-0.256945), btScalar(0.228375), btScalar(0.938827)),
+                       btVector3(btScalar(-0.111761), btScalar(-0.133251), btScalar(0.984696)),
+                       btVector3(btScalar(-0.118006), btScalar(-0.356253), btScalar(0.926725)),
+                       btVector3(btScalar(-0.119372), btScalar(-0.563896), btScalar(0.817029)),
+                       btVector3(btScalar(0.041228), btScalar(-0.833949), btScalar(0.550010)),
+                       btVector3(btScalar(-0.121909), btScalar(-0.736543), btScalar(0.665172)),
+                       btVector3(btScalar(-0.307681), btScalar(-0.931160), btScalar(-0.195026)),
+                       btVector3(btScalar(-0.283679), btScalar(-0.957990), btScalar(0.041348)),
+                       btVector3(btScalar(-0.227284), btScalar(-0.935243), btScalar(0.270890)),
+                       btVector3(btScalar(-0.293436), btScalar(-0.858252), btScalar(-0.420860)),
+                       btVector3(btScalar(-0.175767), btScalar(-0.780677), btScalar(-0.599262)),
+                       btVector3(btScalar(-0.170108), btScalar(-0.858835), btScalar(0.482865)),
+                       btVector3(btScalar(-0.332854), btScalar(-0.635055), btScalar(-0.696857)),
+                       btVector3(btScalar(-0.447791), btScalar(-0.445299), btScalar(-0.775128)),
+                       btVector3(btScalar(-0.470622), btScalar(-0.074146), btScalar(-0.879164)),
+                       btVector3(btScalar(-0.639417), btScalar(-0.340505), btScalar(-0.689049)),
+                       btVector3(btScalar(-0.598438), btScalar(0.104722), btScalar(-0.794256)),
+                       btVector3(btScalar(-0.488575), btScalar(0.307699), btScalar(-0.816313)),
+                       btVector3(btScalar(-0.379882), btScalar(0.513592), btScalar(-0.769077)),
+                       btVector3(btScalar(-0.425740), btScalar(0.862775), btScalar(-0.272516)),
+                       btVector3(btScalar(-0.480769), btScalar(0.875412), btScalar(-0.048439)),
+                       btVector3(btScalar(-0.467890), btScalar(0.648716), btScalar(-0.600043)),
+                       btVector3(btScalar(-0.543799), btScalar(0.730956), btScalar(-0.411881)),
+                       btVector3(btScalar(-0.516284), btScalar(0.838277), btScalar(0.174076)),
+                       btVector3(btScalar(-0.353343), btScalar(0.876384), btScalar(0.326519)),
+                       btVector3(btScalar(-0.572875), btScalar(0.614497), btScalar(0.542007)),
+                       btVector3(btScalar(-0.503600), btScalar(0.497261), btScalar(0.706161)),
+                       btVector3(btScalar(-0.530920), btScalar(0.754870), btScalar(0.384685)),
+                       btVector3(btScalar(-0.395884), btScalar(0.366414), btScalar(0.841818)),
+                       btVector3(btScalar(-0.300656), btScalar(0.001678), btScalar(0.953661)),
+                       btVector3(btScalar(-0.461060), btScalar(0.146912), btScalar(0.875000)),
+                       btVector3(btScalar(-0.315486), btScalar(-0.232212), btScalar(0.919893)),
+                       btVector3(btScalar(-0.323682), btScalar(-0.449187), btScalar(0.832644)),
+                       btVector3(btScalar(-0.318999), btScalar(-0.639527), btScalar(0.699134)),
+                       btVector3(btScalar(-0.496771), btScalar(-0.866029), btScalar(-0.055271)),
+                       btVector3(btScalar(-0.496771), btScalar(-0.816257), btScalar(-0.294377)),
+                       btVector3(btScalar(-0.456377), btScalar(-0.869528), btScalar(0.188130)),
+                       btVector3(btScalar(-0.380858), btScalar(-0.827144), btScalar(0.412792)),
+                       btVector3(btScalar(-0.449352), btScalar(-0.727405), btScalar(-0.518259)),
+                       btVector3(btScalar(-0.570533), btScalar(-0.551064), btScalar(-0.608632)),
+                       btVector3(btScalar(-0.656394), btScalar(-0.118280), btScalar(-0.744874)),
+                       btVector3(btScalar(-0.756696), btScalar(-0.438105), btScalar(-0.484882)),
+                       btVector3(btScalar(-0.801773), btScalar(-0.204798), btScalar(-0.561005)),
+                       btVector3(btScalar(-0.785186), btScalar(0.038618), btScalar(-0.617805)),
+                       btVector3(btScalar(-0.709082), btScalar(0.262399), btScalar(-0.654306)),
+                       btVector3(btScalar(-0.583412), btScalar(0.462265), btScalar(-0.667383)),
+                       btVector3(btScalar(-0.616001), btScalar(0.761286), btScalar(-0.201272)),
+                       btVector3(btScalar(-0.660687), btScalar(0.750204), btScalar(0.020072)),
+                       btVector3(btScalar(-0.744987), btScalar(0.435823), btScalar(-0.504791)),
+                       btVector3(btScalar(-0.713765), btScalar(0.605554), btScalar(-0.351373)),
+                       btVector3(btScalar(-0.686251), btScalar(0.687600), btScalar(0.236927)),
+                       btVector3(btScalar(-0.680201), btScalar(0.429407), btScalar(0.593732)),
+                       btVector3(btScalar(-0.733474), btScalar(0.546450), btScalar(0.403814)),
+                       btVector3(btScalar(-0.591023), btScalar(0.292923), btScalar(0.751445)),
+                       btVector3(btScalar(-0.500283), btScalar(-0.080757), btScalar(0.861922)),
+                       btVector3(btScalar(-0.643710), btScalar(0.070115), btScalar(0.761985)),
+                       btVector3(btScalar(-0.506332), btScalar(-0.308425), btScalar(0.805122)),
+                       btVector3(btScalar(-0.503015), btScalar(-0.509847), btScalar(0.697573)),
+                       btVector3(btScalar(-0.482525), btScalar(-0.682105), btScalar(0.549229)),
+                       btVector3(btScalar(-0.680396), btScalar(-0.716323), btScalar(-0.153451)),
+                       btVector3(btScalar(-0.658346), btScalar(-0.746264), btScalar(0.097562)),
+                       btVector3(btScalar(-0.653272), btScalar(-0.646915), btScalar(-0.392948)),
+                       btVector3(btScalar(-0.590828), btScalar(-0.732655), btScalar(0.337645)),
+                       btVector3(btScalar(-0.819140), btScalar(-0.518013), btScalar(-0.246166)),
+                       btVector3(btScalar(-0.900513), btScalar(-0.282178), btScalar(-0.330487)),
+                       btVector3(btScalar(-0.914953), btScalar(-0.028652), btScalar(-0.402122)),
+                       btVector3(btScalar(-0.859924), btScalar(0.220209), btScalar(-0.459898)),
+                       btVector3(btScalar(-0.777185), btScalar(0.613720), btScalar(-0.137836)),
+                       btVector3(btScalar(-0.805285), btScalar(0.586889), btScalar(0.082728)),
+                       btVector3(btScalar(-0.872413), btScalar(0.406077), btScalar(-0.271735)),
+                       btVector3(btScalar(-0.859339), btScalar(0.448072), btScalar(0.246101)),
+                       btVector3(btScalar(-0.757671), btScalar(0.216320), btScalar(0.615594)),
+                       btVector3(btScalar(-0.826165), btScalar(0.348139), btScalar(0.442851)),
+                       btVector3(btScalar(-0.671810), btScalar(-0.162803), btScalar(0.722557)),
+                       btVector3(btScalar(-0.796504), btScalar(-0.004543), btScalar(0.604468)),
+                       btVector3(btScalar(-0.676298), btScalar(-0.378223), btScalar(0.631794)),
+                       btVector3(btScalar(-0.668883), btScalar(-0.558258), btScalar(0.490673)),
+                       btVector3(btScalar(-0.821287), btScalar(-0.570118), btScalar(0.006994)),
+                       btVector3(btScalar(-0.767428), btScalar(-0.587810), btScalar(0.255470)),
+                       btVector3(btScalar(-0.933296), btScalar(-0.349837), btScalar(-0.079865)),
+                       btVector3(btScalar(-0.982667), btScalar(-0.100393), btScalar(-0.155208)),
+                       btVector3(btScalar(-0.961396), btScalar(0.160910), btScalar(-0.222938)),
+                       btVector3(btScalar(-0.934858), btScalar(0.354555), btScalar(-0.006864)),
+                       btVector3(btScalar(-0.941687), btScalar(0.229736), btScalar(0.245711)),
+                       btVector3(btScalar(-0.884317), btScalar(0.131552), btScalar(0.447536)),
+                       btVector3(btScalar(-0.810359), btScalar(-0.219769), btScalar(0.542788)),
+                       btVector3(btScalar(-0.915929), btScalar(-0.210048), btScalar(0.341743)),
+                       btVector3(btScalar(-0.816799), btScalar(-0.407192), btScalar(0.408303)),
+                       btVector3(btScalar(-0.903050), btScalar(-0.392416), btScalar(0.174076)),
+                       btVector3(btScalar(-0.980325), btScalar(-0.170969), btScalar(0.096586)),
+                       btVector3(btScalar(-0.995936), btScalar(0.084891), btScalar(0.029441)),
+                       btVector3(btScalar(-0.960031), btScalar(0.002650), btScalar(0.279283)),
+               };
+       static btVector3 sUnitSpherePoints[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))};
+       if (highres)
+               return sUnitSpherePointsHighres;
+       return sUnitSpherePoints;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btShapeHull.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btShapeHull.h
new file mode 100644 (file)
index 0000000..54439f9
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btShapeHull implemented by John McCutchan.
+
+#ifndef BT_SHAPE_HULL_H
+#define BT_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.
+ATTRIBUTE_ALIGNED16(class)
+btShapeHull
+{
+protected:
+       btAlignedObjectArray<btVector3> m_vertices;
+       btAlignedObjectArray<unsigned int> m_indices;
+       unsigned int m_numIndices;
+       const btConvexShape* m_shape;
+
+       static btVector3* getUnitSpherePoints(int highres = 0);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btShapeHull(const btConvexShape* shape);
+       ~btShapeHull();
+
+       bool buildHull(btScalar margin, int highres = 0);
+
+       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];
+       }
+};
+
+#endif  //BT_SHAPE_HULL_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSphereShape.cpp
new file mode 100644 (file)
index 0000000..027db2e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+
+btVector3 btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+       (void)vec;
+       return btVector3(btScalar(0.), btScalar(0.), btScalar(0.));
+}
+
+void btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+{
+       (void)vectors;
+
+       for (int i = 0; i < numVectors; i++)
+       {
+               supportVerticesOut[i].setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+       }
+}
+
+btVector3 btSphereShape::localGetSupportingVertex(const btVector3& vec) const
+{
+       btVector3 supVertex;
+       supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+       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;
+}
+
+//broken due to scaling
+void btSphereShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       const btVector3& center = t.getOrigin();
+       btVector3 extent(getMargin(), getMargin(), getMargin());
+       aabbMin = center - extent;
+       aabbMax = center + extent;
+}
+
+void btSphereShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       btScalar elem = btScalar(0.4) * mass * getMargin() * getMargin();
+       inertia.setValue(elem, elem, elem);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSphereShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btSphereShape.h
new file mode 100644 (file)
index 0000000..75e4fd8
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SPHERE_MINKOWSKI_H
+#define BT_SPHERE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"  // for the types
+
+///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) : btConvexInternalShape()
+       {
+               m_shapeType = SPHERE_SHAPE_PROXYTYPE;
+               m_localScaling.setValue(1.0, 1.0, 1.0);
+               m_implicitShapeDimensions.setZero();
+               m_implicitShapeDimensions.setX(radius);
+               m_collisionMargin = radius;
+               m_padding = 0;
+       }
+
+       virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+       //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;
+
+       btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX(); }
+
+       void setUnscaledRadius(btScalar radius)
+       {
+               m_implicitShapeDimensions.setX(radius);
+               btConvexInternalShape::setMargin(radius);
+       }
+
+       //debugging
+       virtual const char* getName() const { return "SPHERE"; }
+
+       virtual void setMargin(btScalar 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 getRadius();
+       }
+};
+
+#endif  //BT_SPHERE_MINKOWSKI_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
new file mode 100644 (file)
index 0000000..9238c91
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btStaticPlaneShape.h"
+
+#include "LinearMath/btTransformUtil.h"
+
+btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal, btScalar planeConstant)
+       : btConcaveShape(), m_planeNormal(planeNormal.normalized()), m_planeConstant(planeConstant), m_localScaling(btScalar(1.), btScalar(1.), btScalar(1.))
+{
+       m_shapeType = STATIC_PLANE_PROXYTYPE;
+       //      btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) );
+}
+
+btStaticPlaneShape::~btStaticPlaneShape()
+{
+}
+
+void btStaticPlaneShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       (void)t;
+       /*
+       btVector3 infvec (btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+
+       btVector3 center = m_planeNormal*m_planeConstant;
+       aabbMin = center + infvec*m_planeNormal;
+       aabbMax = aabbMin;
+       aabbMin.setMin(center - infvec*m_planeNormal);
+       aabbMax.setMax(center - infvec*m_planeNormal); 
+       */
+
+       aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+       aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+}
+
+void btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+       btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
+       btScalar radius = halfExtents.length();
+       btVector3 center = (aabbMax + aabbMin) * btScalar(0.5);
+
+       //this is where the triangles are generated, given AABB and plane equation (normal/constant)
+
+       btVector3 tangentDir0, tangentDir1;
+
+       //tangentDir0/tangentDir1 can be precalculated
+       btPlaneSpace1(m_planeNormal, tangentDir0, tangentDir1);
+
+       btVector3 projectedCenter = center - (m_planeNormal.dot(center) - m_planeConstant) * m_planeNormal;
+
+       btVector3 triangle[3];
+       triangle[0] = projectedCenter + tangentDir0 * radius + tangentDir1 * radius;
+       triangle[1] = projectedCenter + tangentDir0 * radius - tangentDir1 * radius;
+       triangle[2] = projectedCenter - tangentDir0 * radius - tangentDir1 * radius;
+
+       callback->processTriangle(triangle, 0, 0);
+
+       triangle[0] = projectedCenter - tangentDir0 * radius - tangentDir1 * radius;
+       triangle[1] = projectedCenter - tangentDir0 * radius + tangentDir1 * radius;
+       triangle[2] = projectedCenter + tangentDir0 * radius + tangentDir1 * radius;
+
+       callback->processTriangle(triangle, 0, 1);
+}
+
+void btStaticPlaneShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       (void)mass;
+
+       //moving concave objects not supported
+
+       inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+}
+
+void btStaticPlaneShape::setLocalScaling(const btVector3& scaling)
+{
+       m_localScaling = scaling;
+}
+const btVector3& btStaticPlaneShape::getLocalScaling() const
+{
+       return m_localScaling;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h
new file mode 100644 (file)
index 0000000..1cda8bb
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_STATIC_PLANE_SHAPE_H
+#define BT_STATIC_PLANE_SHAPE_H
+
+#include "btConcaveShape.h"
+
+///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane.
+ATTRIBUTE_ALIGNED16(class)
+btStaticPlaneShape : public btConcaveShape
+{
+protected:
+       btVector3 m_localAabbMin;
+       btVector3 m_localAabbMax;
+
+       btVector3 m_planeNormal;
+       btScalar m_planeConstant;
+       btVector3 m_localScaling;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btStaticPlaneShape(const btVector3& planeNormal, btScalar planeConstant);
+
+       virtual ~btStaticPlaneShape();
+
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       virtual void setLocalScaling(const btVector3& scaling);
+       virtual const btVector3& getLocalScaling() const;
+
+       const btVector3& getPlaneNormal() const
+       {
+               return m_planeNormal;
+       }
+
+       const btScalar& getPlaneConstant() const
+       {
+               return m_planeConstant;
+       }
+
+       //debugging
+       virtual const char* getName() const { return "STATICPLANE"; }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btStaticPlaneShapeData
+{
+       btCollisionShapeData m_collisionShapeData;
+
+       btVector3FloatData m_localScaling;
+       btVector3FloatData m_planeNormal;
+       float m_planeConstant;
+       char m_pad[4];
+};
+
+SIMD_FORCE_INLINE int btStaticPlaneShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btStaticPlaneShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btStaticPlaneShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)dataBuffer;
+       btCollisionShape::serialize(&planeData->m_collisionShapeData, serializer);
+
+       m_localScaling.serializeFloat(planeData->m_localScaling);
+       m_planeNormal.serializeFloat(planeData->m_planeNormal);
+       planeData->m_planeConstant = float(m_planeConstant);
+
+       // Fill padding with zeros to appease msan.
+       planeData->m_pad[0] = 0;
+       planeData->m_pad[1] = 0;
+       planeData->m_pad[2] = 0;
+       planeData->m_pad[3] = 0;
+
+       return "btStaticPlaneShapeData";
+}
+
+#endif  //BT_STATIC_PLANE_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
new file mode 100644 (file)
index 0000000..eb288e9
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btSerializer.h"
+
+btStridingMeshInterface::~btStridingMeshInterface()
+{
+}
+
+void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+       (void)aabbMin;
+       (void)aabbMax;
+       int numtotalphysicsverts = 0;
+       int part, graphicssubparts = getNumSubParts();
+       const unsigned char* vertexbase;
+       const unsigned char* indexbase;
+       int indexstride;
+       PHY_ScalarType type;
+       PHY_ScalarType gfxindextype;
+       int stride, numverts, numtriangles;
+       int gfxindex;
+       btVector3 triangle[3];
+
+       btVector3 meshScaling = getScaling();
+
+       ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
+       for (part = 0; part < graphicssubparts; part++)
+       {
+               getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
+               numtotalphysicsverts += numtriangles * 3;  //upper bound
+
+               ///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
+               ///so disable this feature by default
+               ///see patch http://code.google.com/p/bullet/issues/detail?id=213
+
+               switch (type)
+               {
+                       case PHY_FLOAT:
+                       {
+                               float* graphicsbase;
+
+                               switch (gfxindextype)
+                               {
+                                       case PHY_INTEGER:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       case PHY_SHORT:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       case PHY_UCHAR:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       default:
+                                               btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+                               }
+                               break;
+                       }
+
+                       case PHY_DOUBLE:
+                       {
+                               double* graphicsbase;
+
+                               switch (gfxindextype)
+                               {
+                                       case PHY_INTEGER:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       case PHY_SHORT:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       case PHY_UCHAR:
+                                       {
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
+                                                       triangle[0].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
+                                                       triangle[1].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+                                                       graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
+                                                       triangle[2].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
+                                                       callback->internalProcessTriangleIndex(triangle, part, gfxindex);
+                                               }
+                                               break;
+                                       }
+                                       default:
+                                               btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+                               }
+                               break;
+                       }
+                       default:
+                               btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+               }
+
+               unLockReadOnlyVertexBase(part);
+       }
+}
+
+void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin, btVector3& aabbMax)
+{
+       struct AabbCalculationCallback : public btInternalTriangleIndexCallback
+       {
+               btVector3 m_aabbMin;
+               btVector3 m_aabbMax;
+
+               AabbCalculationCallback()
+               {
+                       m_aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+                       m_aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+               }
+
+               virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+               {
+                       (void)partId;
+                       (void)triangleIndex;
+
+                       m_aabbMin.setMin(triangle[0]);
+                       m_aabbMax.setMax(triangle[0]);
+                       m_aabbMin.setMin(triangle[1]);
+                       m_aabbMax.setMax(triangle[1]);
+                       m_aabbMin.setMin(triangle[2]);
+                       m_aabbMax.setMax(triangle[2]);
+               }
+       };
+
+       //first calculate the total aabb for all triangles
+       AabbCalculationCallback aabbCallback;
+       aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
+       aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+       InternalProcessAllTriangles(&aabbCallback, aabbMin, aabbMax);
+
+       aabbMin = aabbCallback.m_aabbMin;
+       aabbMax = aabbCallback.m_aabbMax;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btStridingMeshInterfaceData* trimeshData = (btStridingMeshInterfaceData*)dataBuffer;
+
+       trimeshData->m_numMeshParts = getNumSubParts();
+
+       //void* uniquePtr = 0;
+
+       trimeshData->m_meshPartsPtr = 0;
+
+       if (trimeshData->m_numMeshParts)
+       {
+               btChunk* chunk = serializer->allocate(sizeof(btMeshPartData), trimeshData->m_numMeshParts);
+               btMeshPartData* memPtr = (btMeshPartData*)chunk->m_oldPtr;
+               trimeshData->m_meshPartsPtr = (btMeshPartData*)serializer->getUniquePointer(memPtr);
+
+               //      int numtotalphysicsverts = 0;
+               int part, graphicssubparts = getNumSubParts();
+               const unsigned char* vertexbase;
+               const unsigned char* indexbase;
+               int indexstride;
+               PHY_ScalarType type;
+               PHY_ScalarType gfxindextype;
+               int stride, numverts, numtriangles;
+               int gfxindex;
+               //      btVector3 triangle[3];
+
+               //      btVector3 meshScaling = getScaling();
+
+               ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
+               for (part = 0; part < graphicssubparts; part++, memPtr++)
+               {
+                       getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
+                       memPtr->m_numTriangles = numtriangles;  //indices = 3*numtriangles
+                       memPtr->m_numVertices = numverts;
+                       memPtr->m_indices16 = 0;
+                       memPtr->m_indices32 = 0;
+                       memPtr->m_3indices16 = 0;
+                       memPtr->m_3indices8 = 0;
+                       memPtr->m_vertices3f = 0;
+                       memPtr->m_vertices3d = 0;
+
+                       switch (gfxindextype)
+                       {
+                               case PHY_INTEGER:
+                               {
+                                       int numindices = numtriangles * 3;
+
+                                       if (numindices)
+                                       {
+                                               btChunk* chunk = serializer->allocate(sizeof(btIntIndexData), numindices);
+                                               btIntIndexData* tmpIndices = (btIntIndexData*)chunk->m_oldPtr;
+                                               memPtr->m_indices32 = (btIntIndexData*)serializer->getUniquePointer(tmpIndices);
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
+                                                       tmpIndices[gfxindex * 3].m_value = tri_indices[0];
+                                                       tmpIndices[gfxindex * 3 + 1].m_value = tri_indices[1];
+                                                       tmpIndices[gfxindex * 3 + 2].m_value = tri_indices[2];
+                                               }
+                                               serializer->finalizeChunk(chunk, "btIntIndexData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
+                                       }
+                                       break;
+                               }
+                               case PHY_SHORT:
+                               {
+                                       if (numtriangles)
+                                       {
+                                               btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData), numtriangles);
+                                               btShortIntIndexTripletData* tmpIndices = (btShortIntIndexTripletData*)chunk->m_oldPtr;
+                                               memPtr->m_3indices16 = (btShortIntIndexTripletData*)serializer->getUniquePointer(tmpIndices);
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
+                                                       tmpIndices[gfxindex].m_values[0] = tri_indices[0];
+                                                       tmpIndices[gfxindex].m_values[1] = tri_indices[1];
+                                                       tmpIndices[gfxindex].m_values[2] = tri_indices[2];
+                                                       // Fill padding with zeros to appease msan.
+                                                       tmpIndices[gfxindex].m_pad[0] = 0;
+                                                       tmpIndices[gfxindex].m_pad[1] = 0;
+                                               }
+                                               serializer->finalizeChunk(chunk, "btShortIntIndexTripletData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
+                                       }
+                                       break;
+                               }
+                               case PHY_UCHAR:
+                               {
+                                       if (numtriangles)
+                                       {
+                                               btChunk* chunk = serializer->allocate(sizeof(btCharIndexTripletData), numtriangles);
+                                               btCharIndexTripletData* tmpIndices = (btCharIndexTripletData*)chunk->m_oldPtr;
+                                               memPtr->m_3indices8 = (btCharIndexTripletData*)serializer->getUniquePointer(tmpIndices);
+                                               for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
+                                               {
+                                                       unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
+                                                       tmpIndices[gfxindex].m_values[0] = tri_indices[0];
+                                                       tmpIndices[gfxindex].m_values[1] = tri_indices[1];
+                                                       tmpIndices[gfxindex].m_values[2] = tri_indices[2];
+                                                       // Fill padding with zeros to appease msan.
+                                                       tmpIndices[gfxindex].m_pad = 0;
+                                               }
+                                               serializer->finalizeChunk(chunk, "btCharIndexTripletData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
+                                       }
+                                       break;
+                               }
+                               default:
+                               {
+                                       btAssert(0);
+                                       //unknown index type
+                               }
+                       }
+
+                       switch (type)
+                       {
+                               case PHY_FLOAT:
+                               {
+                                       float* graphicsbase;
+
+                                       if (numverts)
+                                       {
+                                               btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData), numverts);
+                                               btVector3FloatData* tmpVertices = (btVector3FloatData*)chunk->m_oldPtr;
+                                               memPtr->m_vertices3f = (btVector3FloatData*)serializer->getUniquePointer(tmpVertices);
+                                               for (int i = 0; i < numverts; i++)
+                                               {
+                                                       graphicsbase = (float*)(vertexbase + i * stride);
+                                                       tmpVertices[i].m_floats[0] = graphicsbase[0];
+                                                       tmpVertices[i].m_floats[1] = graphicsbase[1];
+                                                       tmpVertices[i].m_floats[2] = graphicsbase[2];
+                                               }
+                                               serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
+                                       }
+                                       break;
+                               }
+
+                               case PHY_DOUBLE:
+                               {
+                                       if (numverts)
+                                       {
+                                               btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData), numverts);
+                                               btVector3DoubleData* tmpVertices = (btVector3DoubleData*)chunk->m_oldPtr;
+                                               memPtr->m_vertices3d = (btVector3DoubleData*)serializer->getUniquePointer(tmpVertices);
+                                               for (int i = 0; i < numverts; i++)
+                                               {
+                                                       double* graphicsbase = (double*)(vertexbase + i * stride);  //for now convert to float, might leave it at double
+                                                       tmpVertices[i].m_floats[0] = graphicsbase[0];
+                                                       tmpVertices[i].m_floats[1] = graphicsbase[1];
+                                                       tmpVertices[i].m_floats[2] = graphicsbase[2];
+                                               }
+                                               serializer->finalizeChunk(chunk, "btVector3DoubleData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
+                                       }
+                                       break;
+                               }
+
+                               default:
+                                       btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+                       }
+
+                       unLockReadOnlyVertexBase(part);
+               }
+
+               serializer->finalizeChunk(chunk, "btMeshPartData", BT_ARRAY_CODE, chunk->m_oldPtr);
+       }
+
+       // Fill padding with zeros to appease msan.
+       memset(trimeshData->m_padding, 0, sizeof(trimeshData->m_padding));
+
+       m_scaling.serializeFloat(trimeshData->m_scaling);
+       return "btStridingMeshInterfaceData";
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h
new file mode 100644 (file)
index 0000000..68a41df
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_STRIDING_MESHINTERFACE_H
+#define BT_STRIDING_MESHINTERFACE_H
+
+#include "LinearMath/btVector3.h"
+#include "btTriangleCallback.h"
+#include "btConcaveShape.h"
+
+///    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.
+ATTRIBUTE_ALIGNED16(class)
+btStridingMeshInterface
+{
+protected:
+       btVector3 m_scaling;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btStridingMeshInterface() : m_scaling(btScalar(1.), btScalar(1.), btScalar(1.))
+       {
+       }
+
+       virtual ~btStridingMeshInterface();
+
+       virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+
+       ///brute force method to calculate aabb
+       void calculateAabbBruteForce(btVector3 & aabbMin, btVector3 & aabbMax);
+
+       /// get read and write access to a subpart of a triangle mesh
+       /// this subpart has a continuous array of vertices and indices
+       /// in this way the mesh can be handled as chunks of memory with striding
+       /// very similar to OpenGL vertexarray support
+       /// make a call to unLockVertexBase when the read and write access is finished
+       virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) = 0;
+
+       virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const = 0;
+
+       /// unLockVertexBase finishes the access to a subpart of the triangle mesh
+       /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+       virtual void unLockVertexBase(int subpart) = 0;
+
+       virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
+
+       /// getNumSubParts returns the number of separate subparts
+       /// each subpart has a continuous array of vertices and indices
+       virtual int getNumSubParts() const = 0;
+
+       virtual void preallocateVertices(int numverts) = 0;
+       virtual void preallocateIndices(int numindices) = 0;
+
+       virtual bool hasPremadeAabb() const { return false; }
+       virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax) const
+       {
+               (void)aabbMin;
+               (void)aabbMax;
+       }
+       virtual void getPremadeAabb(btVector3 * aabbMin, btVector3 * aabbMax) const
+       {
+               (void)aabbMin;
+               (void)aabbMax;
+       }
+
+       const btVector3& getScaling() const
+       {
+               return m_scaling;
+       }
+       void setScaling(const btVector3& scaling)
+       {
+               m_scaling = scaling;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+struct btIntIndexData
+{
+       int m_value;
+};
+
+struct btShortIntIndexData
+{
+       short m_value;
+       char m_pad[2];
+};
+
+struct btShortIntIndexTripletData
+{
+       short m_values[3];
+       char m_pad[2];
+};
+
+struct btCharIndexTripletData
+{
+       unsigned char m_values[3];
+       char m_pad;
+};
+
+// clang-format off
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btMeshPartData
+{
+       btVector3FloatData                      *m_vertices3f;
+       btVector3DoubleData                     *m_vertices3d;
+
+       btIntIndexData                          *m_indices32;
+       btShortIntIndexTripletData      *m_3indices16;
+       btCharIndexTripletData          *m_3indices8;
+
+       btShortIntIndexData                     *m_indices16;//backwards compatibility
+
+       int                     m_numTriangles;//length of m_indices = m_numTriangles
+       int                     m_numVertices;
+};
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btStridingMeshInterfaceData
+{
+       btMeshPartData  *m_meshPartsPtr;
+       btVector3FloatData      m_scaling;
+       int     m_numMeshParts;
+       char m_padding[4];
+};
+
+// clang-format on
+
+SIMD_FORCE_INLINE int btStridingMeshInterface::calculateSerializeBufferSize() const
+{
+       return sizeof(btStridingMeshInterfaceData);
+}
+
+#endif  //BT_STRIDING_MESHINTERFACE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
new file mode 100644 (file)
index 0000000..c4d33c4
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTetrahedronShape.h"
+#include "LinearMath/btMatrix3x3.h"
+
+btBU_Simplex1to4::btBU_Simplex1to4() : btPolyhedralConvexAabbCachingShape(),
+                                                                          m_numVertices(0)
+{
+       m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0) : btPolyhedralConvexAabbCachingShape(),
+                                                                                                                  m_numVertices(0)
+{
+       m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+       addVertex(pt0);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1) : btPolyhedralConvexAabbCachingShape(),
+                                                                                                                                                                m_numVertices(0)
+{
+       m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+       addVertex(pt0);
+       addVertex(pt1);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2) : btPolyhedralConvexAabbCachingShape(),
+                                                                                                                                                                                                          m_numVertices(0)
+{
+       m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+       addVertex(pt0);
+       addVertex(pt1);
+       addVertex(pt2);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2, const btVector3& pt3) : btPolyhedralConvexAabbCachingShape(),
+                                                                                                                                                                                                                                                        m_numVertices(0)
+{
+       m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+       addVertex(pt0);
+       addVertex(pt1);
+       addVertex(pt2);
+       addVertex(pt3);
+}
+
+void btBU_Simplex1to4::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+#if 1
+       btPolyhedralConvexAabbCachingShape::getAabb(t, aabbMin, aabbMax);
+#else
+       aabbMin.setValue(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
+       aabbMax.setValue(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT);
+
+       //just transform the vertices in worldspace, and take their AABB
+       for (int i = 0; i < m_numVertices; i++)
+       {
+               btVector3 worldVertex = t(m_vertices[i]);
+               aabbMin.setMin(worldVertex);
+               aabbMax.setMax(worldVertex);
+       }
+#endif
+}
+
+void btBU_Simplex1to4::addVertex(const btVector3& pt)
+{
+       m_vertices[m_numVertices++] = pt;
+       recalcLocalAabb();
+}
+
+int btBU_Simplex1to4::getNumVertices() const
+{
+       return m_numVertices;
+}
+
+int btBU_Simplex1to4::getNumEdges() const
+{
+       //euler formula, F-E+V = 2, so E = F+V-2
+
+       switch (m_numVertices)
+       {
+               case 0:
+                       return 0;
+               case 1:
+                       return 0;
+               case 2:
+                       return 1;
+               case 3:
+                       return 3;
+               case 4:
+                       return 6;
+       }
+
+       return 0;
+}
+
+void btBU_Simplex1to4::getEdge(int i, btVector3& pa, btVector3& pb) const
+{
+       switch (m_numVertices)
+       {
+               case 2:
+                       pa = m_vertices[0];
+                       pb = m_vertices[1];
+                       break;
+               case 3:
+                       switch (i)
+                       {
+                               case 0:
+                                       pa = m_vertices[0];
+                                       pb = m_vertices[1];
+                                       break;
+                               case 1:
+                                       pa = m_vertices[1];
+                                       pb = m_vertices[2];
+                                       break;
+                               case 2:
+                                       pa = m_vertices[2];
+                                       pb = m_vertices[0];
+                                       break;
+                       }
+                       break;
+               case 4:
+                       switch (i)
+                       {
+                               case 0:
+                                       pa = m_vertices[0];
+                                       pb = m_vertices[1];
+                                       break;
+                               case 1:
+                                       pa = m_vertices[1];
+                                       pb = m_vertices[2];
+                                       break;
+                               case 2:
+                                       pa = m_vertices[2];
+                                       pb = m_vertices[0];
+                                       break;
+                               case 3:
+                                       pa = m_vertices[0];
+                                       pb = m_vertices[3];
+                                       break;
+                               case 4:
+                                       pa = m_vertices[1];
+                                       pb = m_vertices[3];
+                                       break;
+                               case 5:
+                                       pa = m_vertices[2];
+                                       pb = m_vertices[3];
+                                       break;
+                       }
+       }
+}
+
+void btBU_Simplex1to4::getVertex(int i, btVector3& vtx) const
+{
+       vtx = m_vertices[i];
+}
+
+int btBU_Simplex1to4::getNumPlanes() const
+{
+       switch (m_numVertices)
+       {
+               case 0:
+                       return 0;
+               case 1:
+                       return 0;
+               case 2:
+                       return 0;
+               case 3:
+                       return 2;
+               case 4:
+                       return 4;
+               default:
+               {
+               }
+       }
+       return 0;
+}
+
+void btBU_Simplex1to4::getPlane(btVector3&, btVector3&, int) const
+{
+}
+
+int btBU_Simplex1to4::getIndex(int) const
+{
+       return 0;
+}
+
+bool btBU_Simplex1to4::isInside(const btVector3&, btScalar) const
+{
+       return false;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTetrahedronShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTetrahedronShape.h
new file mode 100644 (file)
index 0000000..f5e2209
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SIMPLEX_1TO4_SHAPE
+#define BT_SIMPLEX_1TO4_SHAPE
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+
+///The btBU_Simplex1to4 implements tetrahedron, triangle, line, vertex collision shapes. In most cases it is better to use btConvexHullShape instead.
+ATTRIBUTE_ALIGNED16(class)
+btBU_Simplex1to4 : public btPolyhedralConvexAabbCachingShape
+{
+protected:
+       int m_numVertices;
+       btVector3 m_vertices[4];
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btBU_Simplex1to4();
+
+       btBU_Simplex1to4(const btVector3& pt0);
+       btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1);
+       btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2);
+       btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2, const btVector3& pt3);
+
+       void reset()
+       {
+               m_numVertices = 0;
+       }
+
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       void addVertex(const btVector3& pt);
+
+       //PolyhedralConvexShape interface
+
+       virtual int getNumVertices() const;
+
+       virtual int getNumEdges() const;
+
+       virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
+
+       virtual void getVertex(int i, btVector3& vtx) const;
+
+       virtual int getNumPlanes() const;
+
+       virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
+
+       virtual int getIndex(int i) const;
+
+       virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
+
+       ///getName is for debugging
+       virtual const char* getName() const { return "btBU_Simplex1to4"; }
+};
+
+#endif  //BT_SIMPLEX_1TO4_SHAPE
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
new file mode 100644 (file)
index 0000000..3b6db2b
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleBuffer.h"
+
+void btTriangleBuffer::processTriangle(btVector3* triangle, int partId, int triangleIndex)
+{
+       btTriangle tri;
+       tri.m_vertex0 = triangle[0];
+       tri.m_vertex1 = triangle[1];
+       tri.m_vertex2 = triangle[2];
+       tri.m_partId = partId;
+       tri.m_triangleIndex = triangleIndex;
+
+       m_triangleBuffer.push_back(tri);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleBuffer.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleBuffer.h
new file mode 100644 (file)
index 0000000..a89b9cd
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_BUFFER_H
+#define BT_TRIANGLE_BUFFER_H
+
+#include "btTriangleCallback.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct btTriangle
+{
+       btVector3 m_vertex0;
+       btVector3 m_vertex1;
+       btVector3 m_vertex2;
+       int m_partId;
+       int m_triangleIndex;
+};
+
+///The btTriangleBuffer callback 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
+{
+       btAlignedObjectArray<btTriangle> m_triangleBuffer;
+
+public:
+       virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+
+       int getNumTriangles() const
+       {
+               return int(m_triangleBuffer.size());
+       }
+
+       const btTriangle& getTriangle(int index) const
+       {
+               return m_triangleBuffer[index];
+       }
+
+       void clearBuffer()
+       {
+               m_triangleBuffer.clear();
+       }
+};
+
+#endif  //BT_TRIANGLE_BUFFER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp
new file mode 100644 (file)
index 0000000..5bd2c59
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleCallback.h"
+
+btTriangleCallback::~btTriangleCallback()
+{
+}
+
+btInternalTriangleIndexCallback::~btInternalTriangleIndexCallback()
+{
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleCallback.h
new file mode 100644 (file)
index 0000000..d364489
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_CALLBACK_H
+#define BT_TRIANGLE_CALLBACK_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:
+       virtual ~btTriangleCallback();
+       virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) = 0;
+};
+
+class btInternalTriangleIndexCallback
+{
+public:
+       virtual ~btInternalTriangleIndexCallback();
+       virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) = 0;
+};
+
+#endif  //BT_TRIANGLE_CALLBACK_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
new file mode 100644 (file)
index 0000000..dae4255
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleIndexVertexArray.h"
+
+btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, btScalar* vertexBase, int vertexStride)
+       : m_hasAabb(0)
+{
+       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;
+
+       type = mesh.m_vertexType;
+
+       vertexStride = mesh.m_vertexStride;
+
+       numfaces = mesh.m_numTriangles;
+
+       (*indexbase) = (unsigned char*)mesh.m_triangleIndexBase;
+       indexstride = mesh.m_triangleIndexStride;
+       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
+{
+       const btIndexedMesh& mesh = m_indexedMeshes[subpart];
+
+       numverts = mesh.m_numVertices;
+       (*vertexbase) = (const unsigned char*)mesh.m_vertexBase;
+
+       type = mesh.m_vertexType;
+
+       vertexStride = mesh.m_vertexStride;
+
+       numfaces = mesh.m_numTriangles;
+       (*indexbase) = (const unsigned char*)mesh.m_triangleIndexBase;
+       indexstride = mesh.m_triangleIndexStride;
+       indicestype = mesh.m_indexType;
+}
+
+bool btTriangleIndexVertexArray::hasPremadeAabb() const
+{
+       return (m_hasAabb == 1);
+}
+
+void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+       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/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
new file mode 100644 (file)
index 0000000..556aa3f
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
+
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btScalar.h"
+
+///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;
+       // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
+       int m_triangleIndexStride;
+       int m_numVertices;
+       const unsigned char* m_vertexBase;
+       // Size of a vertex, in bytes
+       int m_vertexStride;
+
+       // The index type is set when adding an indexed mesh to the
+       // btTriangleIndexVertexArray, do not set it manually
+       PHY_ScalarType m_indexType;
+
+       // The vertex type has a default type similar to Bullet's precision mode (float or double)
+       // but can be set manually if you for example run Bullet with double precision but have
+       // mesh data in single precision..
+       PHY_ScalarType m_vertexType;
+
+       btIndexedMesh()
+               : m_indexType(PHY_INTEGER),
+#ifdef BT_USE_DOUBLE_PRECISION
+                 m_vertexType(PHY_DOUBLE)
+#else   // BT_USE_DOUBLE_PRECISION
+                 m_vertexType(PHY_FLOAT)
+#endif  // BT_USE_DOUBLE_PRECISION
+       {
+       }
+};
+
+typedef btAlignedObjectArray<btIndexedMesh> IndexedMeshArray;
+
+///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
+///Additional meshes can be added using addIndexedMesh
+///No duplicate 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[2];
+       mutable int m_hasAabb;  // using int instead of bool to maintain alignment
+       mutable btVector3 m_aabbMin;
+       mutable btVector3 m_aabbMax;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btTriangleIndexVertexArray() : m_hasAabb(0)
+       {
+       }
+
+       virtual ~btTriangleIndexVertexArray();
+
+       //just to be backwards compatible
+       btTriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, btScalar* vertexBase, int vertexStride);
+
+       void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
+       {
+               m_indexedMeshes.push_back(mesh);
+               m_indexedMeshes[m_indexedMeshes.size() - 1].m_indexType = indexType;
+       }
+
+       virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0);
+
+       virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const;
+
+       /// unLockVertexBase finishes the access to a subpart of the triangle mesh
+       /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+       virtual void unLockVertexBase(int subpart) { (void)subpart; }
+
+       virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
+
+       /// getNumSubParts returns the number of separate subparts
+       /// each subpart has a continuous array of vertices and indices
+       virtual int getNumSubParts() const
+       {
+               return (int)m_indexedMeshes.size();
+       }
+
+       IndexedMeshArray& getIndexedMeshArray()
+       {
+               return m_indexedMeshes;
+       }
+
+       const IndexedMeshArray& getIndexedMeshArray() const
+       {
+               return m_indexedMeshes;
+       }
+
+       virtual void preallocateVertices(int numverts) { (void)numverts; }
+       virtual void preallocateIndices(int numindices) { (void)numindices; }
+
+       virtual bool hasPremadeAabb() const;
+       virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax) const;
+       virtual void getPremadeAabb(btVector3 * aabbMin, btVector3 * aabbMax) const;
+};
+
+#endif  //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
new file mode 100644 (file)
index 0000000..4bf133d
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
new file mode 100644 (file)
index 0000000..315b1e2
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h
new file mode 100644 (file)
index 0000000..8ee35ef
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2010 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _BT_TRIANGLE_INFO_MAP_H
+#define _BT_TRIANGLE_INFO_MAP_H
+
+#include "LinearMath/btHashMap.h"
+#include "LinearMath/btSerializer.h"
+
+///for btTriangleInfo m_flags
+#define TRI_INFO_V0V1_CONVEX 1
+#define TRI_INFO_V1V2_CONVEX 2
+#define TRI_INFO_V2V0_CONVEX 4
+
+#define TRI_INFO_V0V1_SWAP_NORMALB 8
+#define TRI_INFO_V1V2_SWAP_NORMALB 16
+#define TRI_INFO_V2V0_SWAP_NORMALB 32
+
+///The btTriangleInfo structure stores information to adjust collision normals to avoid collisions against internal edges
+///it can be generated using
+struct btTriangleInfo
+{
+       btTriangleInfo()
+       {
+               m_edgeV0V1Angle = SIMD_2_PI;
+               m_edgeV1V2Angle = SIMD_2_PI;
+               m_edgeV2V0Angle = SIMD_2_PI;
+               m_flags = 0;
+       }
+
+       int m_flags;
+
+       btScalar m_edgeV0V1Angle;
+       btScalar m_edgeV1V2Angle;
+       btScalar m_edgeV2V0Angle;
+};
+
+typedef btHashMap<btHashInt, btTriangleInfo> btInternalTriangleInfoMap;
+
+///The btTriangleInfoMap stores edge angle information for some triangles. You can compute this information yourself or using btGenerateInternalEdgeInfo.
+struct btTriangleInfoMap : public btInternalTriangleInfoMap
+{
+       btScalar m_convexEpsilon;          ///used to determine if an edge or contact normal is convex, using the dot product
+       btScalar m_planarEpsilon;          ///used to determine if a triangle edge is planar with zero angle
+       btScalar m_equalVertexThreshold;   ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared'
+       btScalar m_edgeDistanceThreshold;  ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge"
+       btScalar m_maxEdgeAngleThreshold;  //ignore edges that connect triangles at an angle larger than this m_maxEdgeAngleThreshold
+       btScalar m_zeroAreaThreshold;      ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold)
+
+       btTriangleInfoMap()
+       {
+               m_convexEpsilon = 0.00f;
+               m_planarEpsilon = 0.0001f;
+               m_equalVertexThreshold = btScalar(0.0001) * btScalar(0.0001);
+               m_edgeDistanceThreshold = btScalar(0.1);
+               m_zeroAreaThreshold = btScalar(0.0001) * btScalar(0.0001);
+               m_maxEdgeAngleThreshold = SIMD_2_PI;
+       }
+       virtual ~btTriangleInfoMap() {}
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+       void deSerialize(struct btTriangleInfoMapData& data);
+};
+
+// clang-format off
+
+///those fields have to be float and not btScalar for the serialization to work properly
+struct btTriangleInfoData
+{
+       int                     m_flags;
+       float   m_edgeV0V1Angle;
+       float   m_edgeV1V2Angle;
+       float   m_edgeV2V0Angle;
+};
+
+struct btTriangleInfoMapData
+{
+       int                                     *m_hashTablePtr;
+       int                                     *m_nextPtr;
+       btTriangleInfoData      *m_valueArrayPtr;
+       int                                     *m_keyArrayPtr;
+
+       float   m_convexEpsilon;
+       float   m_planarEpsilon;
+       float   m_equalVertexThreshold; 
+       float   m_edgeDistanceThreshold;
+       float   m_zeroAreaThreshold;
+
+       int             m_nextSize;
+       int             m_hashTableSize;
+       int             m_numValues;
+       int             m_numKeys;
+       char    m_padding[4];
+};
+
+// clang-format on
+
+SIMD_FORCE_INLINE int btTriangleInfoMap::calculateSerializeBufferSize() const
+{
+       return sizeof(btTriangleInfoMapData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*)dataBuffer;
+       tmapData->m_convexEpsilon = (float)m_convexEpsilon;
+       tmapData->m_planarEpsilon = (float)m_planarEpsilon;
+       tmapData->m_equalVertexThreshold = (float)m_equalVertexThreshold;
+       tmapData->m_edgeDistanceThreshold = (float)m_edgeDistanceThreshold;
+       tmapData->m_zeroAreaThreshold = (float)m_zeroAreaThreshold;
+
+       tmapData->m_hashTableSize = m_hashTable.size();
+
+       tmapData->m_hashTablePtr = tmapData->m_hashTableSize ? (int*)serializer->getUniquePointer((void*)&m_hashTable[0]) : 0;
+       if (tmapData->m_hashTablePtr)
+       {
+               //serialize an int buffer
+               int sz = sizeof(int);
+               int numElem = tmapData->m_hashTableSize;
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               int* memPtr = (int*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       *memPtr = m_hashTable[i];
+               }
+               serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_hashTable[0]);
+       }
+
+       tmapData->m_nextSize = m_next.size();
+       tmapData->m_nextPtr = tmapData->m_nextSize ? (int*)serializer->getUniquePointer((void*)&m_next[0]) : 0;
+       if (tmapData->m_nextPtr)
+       {
+               int sz = sizeof(int);
+               int numElem = tmapData->m_nextSize;
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               int* memPtr = (int*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       *memPtr = m_next[i];
+               }
+               serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_next[0]);
+       }
+
+       tmapData->m_numValues = m_valueArray.size();
+       tmapData->m_valueArrayPtr = tmapData->m_numValues ? (btTriangleInfoData*)serializer->getUniquePointer((void*)&m_valueArray[0]) : 0;
+       if (tmapData->m_valueArrayPtr)
+       {
+               int sz = sizeof(btTriangleInfoData);
+               int numElem = tmapData->m_numValues;
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               btTriangleInfoData* memPtr = (btTriangleInfoData*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       memPtr->m_edgeV0V1Angle = (float)m_valueArray[i].m_edgeV0V1Angle;
+                       memPtr->m_edgeV1V2Angle = (float)m_valueArray[i].m_edgeV1V2Angle;
+                       memPtr->m_edgeV2V0Angle = (float)m_valueArray[i].m_edgeV2V0Angle;
+                       memPtr->m_flags = m_valueArray[i].m_flags;
+               }
+               serializer->finalizeChunk(chunk, "btTriangleInfoData", BT_ARRAY_CODE, (void*)&m_valueArray[0]);
+       }
+
+       tmapData->m_numKeys = m_keyArray.size();
+       tmapData->m_keyArrayPtr = tmapData->m_numKeys ? (int*)serializer->getUniquePointer((void*)&m_keyArray[0]) : 0;
+       if (tmapData->m_keyArrayPtr)
+       {
+               int sz = sizeof(int);
+               int numElem = tmapData->m_numValues;
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               int* memPtr = (int*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       *memPtr = m_keyArray[i].getUid1();
+               }
+               serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_keyArray[0]);
+       }
+
+       // Fill padding with zeros to appease msan.
+       tmapData->m_padding[0] = 0;
+       tmapData->m_padding[1] = 0;
+       tmapData->m_padding[2] = 0;
+       tmapData->m_padding[3] = 0;
+
+       return "btTriangleInfoMapData";
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE void btTriangleInfoMap::deSerialize(btTriangleInfoMapData& tmapData)
+{
+       m_convexEpsilon = tmapData.m_convexEpsilon;
+       m_planarEpsilon = tmapData.m_planarEpsilon;
+       m_equalVertexThreshold = tmapData.m_equalVertexThreshold;
+       m_edgeDistanceThreshold = tmapData.m_edgeDistanceThreshold;
+       m_zeroAreaThreshold = tmapData.m_zeroAreaThreshold;
+       m_hashTable.resize(tmapData.m_hashTableSize);
+       int i = 0;
+       for (i = 0; i < tmapData.m_hashTableSize; i++)
+       {
+               m_hashTable[i] = tmapData.m_hashTablePtr[i];
+       }
+       m_next.resize(tmapData.m_nextSize);
+       for (i = 0; i < tmapData.m_nextSize; i++)
+       {
+               m_next[i] = tmapData.m_nextPtr[i];
+       }
+       m_valueArray.resize(tmapData.m_numValues);
+       for (i = 0; i < tmapData.m_numValues; i++)
+       {
+               m_valueArray[i].m_edgeV0V1Angle = tmapData.m_valueArrayPtr[i].m_edgeV0V1Angle;
+               m_valueArray[i].m_edgeV1V2Angle = tmapData.m_valueArrayPtr[i].m_edgeV1V2Angle;
+               m_valueArray[i].m_edgeV2V0Angle = tmapData.m_valueArrayPtr[i].m_edgeV2V0Angle;
+               m_valueArray[i].m_flags = tmapData.m_valueArrayPtr[i].m_flags;
+       }
+
+       m_keyArray.resize(tmapData.m_numKeys, btHashInt(0));
+       for (i = 0; i < tmapData.m_numKeys; i++)
+       {
+               m_keyArray[i].setUid1(tmapData.m_keyArrayPtr[i]);
+       }
+}
+
+#endif  //_BT_TRIANGLE_INFO_MAP_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp
new file mode 100644 (file)
index 0000000..abd8c22
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleMesh.h"
+
+btTriangleMesh::btTriangleMesh(bool use32bitIndices, bool use4componentVertices)
+       : m_use32bitIndices(use32bitIndices),
+         m_use4componentVertices(use4componentVertices),
+         m_weldingThreshold(0.0)
+{
+       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 = 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 = 0;
+               m_indexedMeshes[0].m_indexType = PHY_SHORT;
+               m_indexedMeshes[0].m_triangleIndexStride = 3 * sizeof(short int);
+       }
+
+       if (m_use4componentVertices)
+       {
+               m_indexedMeshes[0].m_numVertices = m_4componentVertices.size();
+               m_indexedMeshes[0].m_vertexBase = 0;
+               m_indexedMeshes[0].m_vertexStride = sizeof(btVector3);
+       }
+       else
+       {
+               m_indexedMeshes[0].m_numVertices = m_3componentVertices.size() / 3;
+               m_indexedMeshes[0].m_vertexBase = 0;
+               m_indexedMeshes[0].m_vertexStride = 3 * sizeof(btScalar);
+       }
+}
+
+void btTriangleMesh::addIndex(int index)
+{
+       if (m_use32bitIndices)
+       {
+               m_32bitIndices.push_back(index);
+               m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*)&m_32bitIndices[0];
+       }
+       else
+       {
+               m_16bitIndices.push_back(index);
+               m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*)&m_16bitIndices[0];
+       }
+}
+
+void btTriangleMesh::addTriangleIndices(int index1, int index2, int index3)
+{
+       m_indexedMeshes[0].m_numTriangles++;
+       addIndex(index1);
+       addIndex(index2);
+       addIndex(index3);
+}
+
+int btTriangleMesh::findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices)
+{
+       //return index of new/existing vertex
+       ///@todo: could use acceleration structure for this
+       if (m_use4componentVertices)
+       {
+               if (removeDuplicateVertices)
+               {
+                       for (int i = 0; i < m_4componentVertices.size(); i++)
+                       {
+                               if ((m_4componentVertices[i] - vertex).length2() <= m_weldingThreshold)
+                               {
+                                       return i;
+                               }
+                       }
+               }
+               m_indexedMeshes[0].m_numVertices++;
+               m_4componentVertices.push_back(vertex);
+               m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];
+
+               return m_4componentVertices.size() - 1;
+       }
+       else
+       {
+               if (removeDuplicateVertices)
+               {
+                       for (int i = 0; i < m_3componentVertices.size(); i += 3)
+                       {
+                               btVector3 vtx(m_3componentVertices[i], m_3componentVertices[i + 1], m_3componentVertices[i + 2]);
+                               if ((vtx - vertex).length2() <= m_weldingThreshold)
+                               {
+                                       return i / 3;
+                               }
+                       }
+               }
+               m_3componentVertices.push_back(vertex.getX());
+               m_3componentVertices.push_back(vertex.getY());
+               m_3componentVertices.push_back(vertex.getZ());
+               m_indexedMeshes[0].m_numVertices++;
+               m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];
+               return (m_3componentVertices.size() / 3) - 1;
+       }
+}
+
+void btTriangleMesh::addTriangle(const btVector3& vertex0, const btVector3& vertex1, const btVector3& vertex2, bool removeDuplicateVertices)
+{
+       m_indexedMeshes[0].m_numTriangles++;
+       addIndex(findOrAddVertex(vertex0, removeDuplicateVertices));
+       addIndex(findOrAddVertex(vertex1, removeDuplicateVertices));
+       addIndex(findOrAddVertex(vertex2, removeDuplicateVertices));
+}
+
+int btTriangleMesh::getNumTriangles() const
+{
+       if (m_use32bitIndices)
+       {
+               return m_32bitIndices.size() / 3;
+       }
+       return m_16bitIndices.size() / 3;
+}
+
+void btTriangleMesh::preallocateVertices(int numverts)
+{
+       if (m_use4componentVertices)
+       {
+               m_4componentVertices.reserve(numverts);
+       }
+       else
+       {
+               m_3componentVertices.reserve(numverts);
+       }
+}
+
+void btTriangleMesh::preallocateIndices(int numindices)
+{
+       if (m_use32bitIndices)
+       {
+               m_32bitIndices.reserve(numindices);
+       }
+       else
+       {
+               m_16bitIndices.reserve(numindices);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMesh.h
new file mode 100644 (file)
index 0000000..a8a3623
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_MESH_H
+#define BT_TRIANGLE_MESH_H
+
+#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_4componentVertices;
+       btAlignedObjectArray<btScalar> m_3componentVertices;
+
+       btAlignedObjectArray<unsigned int> m_32bitIndices;
+       btAlignedObjectArray<unsigned short int> m_16bitIndices;
+       bool m_use32bitIndices;
+       bool m_use4componentVertices;
+
+public:
+       btScalar m_weldingThreshold;
+
+       btTriangleMesh(bool use32bitIndices = true, bool use4componentVertices = true);
+
+       bool getUse32bitIndices() const
+       {
+               return m_use32bitIndices;
+       }
+
+       bool getUse4componentVertices() const
+       {
+               return m_use4componentVertices;
+       }
+       ///By default addTriangle won't search for duplicate vertices, because the search is very slow for large triangle meshes.
+       ///In general it is better to directly use btTriangleIndexVertexArray instead.
+       void addTriangle(const btVector3& vertex0, const btVector3& vertex1, const btVector3& vertex2, bool removeDuplicateVertices = false);
+
+       ///Add a triangle using its indices. Make sure the indices are pointing within the vertices array, so add the vertices first (and to be sure, avoid removal of duplicate vertices)
+       void addTriangleIndices(int index1, int index2, int index3);
+
+       int getNumTriangles() const;
+
+       virtual void preallocateVertices(int numverts);
+       virtual void preallocateIndices(int numindices);
+
+       ///findOrAddVertex is an internal method, use addTriangle instead
+       int findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices);
+       ///addIndex is an internal method, use addTriangle instead
+       void addIndex(int index);
+};
+
+#endif  //BT_TRIANGLE_MESH_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
new file mode 100644 (file)
index 0000000..aec2390
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleMeshShape.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btQuaternion.h"
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface)
+       : btConcaveShape(), m_meshInterface(meshInterface)
+{
+       m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+       if (meshInterface->hasPremadeAabb())
+       {
+               meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax);
+       }
+       else
+       {
+               recalcLocalAabb();
+       }
+}
+
+btTriangleMeshShape::~btTriangleMeshShape()
+{
+}
+
+void btTriangleMeshShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       btVector3 localHalfExtents = btScalar(0.5) * (m_localAabbMax - m_localAabbMin);
+       localHalfExtents += btVector3(getMargin(), getMargin(), getMargin());
+       btVector3 localCenter = btScalar(0.5) * (m_localAabbMax + m_localAabbMin);
+
+       btMatrix3x3 abs_b = trans.getBasis().absolute();
+
+       btVector3 center = trans(localCenter);
+
+       btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+       aabbMin = center - extent;
+       aabbMax = center + extent;
+}
+
+void btTriangleMeshShape::recalcLocalAabb()
+{
+       for (int i = 0; i < 3; i++)
+       {
+               btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
+               vec[i] = btScalar(1.);
+               btVector3 tmp = localGetSupportingVertex(vec);
+               m_localAabbMax[i] = tmp[i] + m_collisionMargin;
+               vec[i] = btScalar(-1.);
+               tmp = localGetSupportingVertex(vec);
+               m_localAabbMin[i] = tmp[i] - m_collisionMargin;
+       }
+}
+
+class SupportVertexCallback : public btTriangleCallback
+{
+       btVector3 m_supportVertexLocal;
+
+public:
+       btTransform m_worldTrans;
+       btScalar m_maxDot;
+       btVector3 m_supportVecLocal;
+
+       SupportVertexCallback(const btVector3& supportVecWorld, const btTransform& trans)
+               : m_supportVertexLocal(btScalar(0.), btScalar(0.), btScalar(0.)), m_worldTrans(trans), m_maxDot(btScalar(-BT_LARGE_FLOAT))
+
+       {
+               m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis();
+       }
+
+       virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+       {
+               (void)partId;
+               (void)triangleIndex;
+               for (int i = 0; i < 3; i++)
+               {
+                       btScalar dot = m_supportVecLocal.dot(triangle[i]);
+                       if (dot > m_maxDot)
+                       {
+                               m_maxDot = dot;
+                               m_supportVertexLocal = triangle[i];
+                       }
+               }
+       }
+
+       btVector3 GetSupportVertexWorldSpace()
+       {
+               return m_worldTrans(m_supportVertexLocal);
+       }
+
+       btVector3 GetSupportVertexLocal()
+       {
+               return m_supportVertexLocal;
+       }
+};
+
+void btTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+       m_meshInterface->setScaling(scaling);
+       recalcLocalAabb();
+}
+
+const btVector3& btTriangleMeshShape::getLocalScaling() const
+{
+       return m_meshInterface->getScaling();
+}
+
+//#define DEBUG_TRIANGLE_MESH
+
+void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+       struct FilteredCallback : public btInternalTriangleIndexCallback
+       {
+               btTriangleCallback* m_callback;
+               btVector3 m_aabbMin;
+               btVector3 m_aabbMax;
+
+               FilteredCallback(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax)
+                       : m_callback(callback),
+                         m_aabbMin(aabbMin),
+                         m_aabbMax(aabbMax)
+               {
+               }
+
+               virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+               {
+                       if (TestTriangleAgainstAabb2(&triangle[0], m_aabbMin, m_aabbMax))
+                       {
+                               //check aabb in triangle-space, before doing this
+                               m_callback->processTriangle(triangle, partId, triangleIndex);
+                       }
+               }
+       };
+
+       FilteredCallback filterCallback(callback, aabbMin, aabbMax);
+
+       m_meshInterface->InternalProcessAllTriangles(&filterCallback, aabbMin, aabbMax);
+}
+
+void btTriangleMeshShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       (void)mass;
+       //moving concave objects not supported
+       btAssert(0);
+       inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+}
+
+btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const
+{
+       btVector3 supportVertex;
+
+       btTransform ident;
+       ident.setIdentity();
+
+       SupportVertexCallback supportCallback(vec, ident);
+
+       btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+
+       processAllTriangles(&supportCallback, -aabbMax, aabbMax);
+
+       supportVertex = supportCallback.GetSupportVertexLocal();
+
+       return supportVertex;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h
new file mode 100644 (file)
index 0000000..4a70e28
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_MESH_SHAPE_H
+#define BT_TRIANGLE_MESH_SHAPE_H
+
+#include "btConcaveShape.h"
+#include "btStridingMeshInterface.h"
+
+///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead.
+ATTRIBUTE_ALIGNED16(class)
+btTriangleMeshShape : public btConcaveShape
+{
+protected:
+       btVector3 m_localAabbMin;
+       btVector3 m_localAabbMax;
+       btStridingMeshInterface* m_meshInterface;
+
+       ///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class.
+       ///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead!
+       btTriangleMeshShape(btStridingMeshInterface * meshInterface);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       virtual ~btTriangleMeshShape();
+
+       virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+
+       virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+       {
+               btAssert(0);
+               return localGetSupportingVertex(vec);
+       }
+
+       void recalcLocalAabb();
+
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+       virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
+
+       virtual void setLocalScaling(const btVector3& scaling);
+       virtual const btVector3& getLocalScaling() const;
+
+       btStridingMeshInterface* getMeshInterface()
+       {
+               return m_meshInterface;
+       }
+
+       const btStridingMeshInterface* getMeshInterface() const
+       {
+               return m_meshInterface;
+       }
+
+       const btVector3& getLocalAabbMin() const
+       {
+               return m_localAabbMin;
+       }
+       const btVector3& getLocalAabbMax() const
+       {
+               return m_localAabbMax;
+       }
+
+       //debugging
+       virtual const char* getName() const { return "TRIANGLEMESH"; }
+};
+
+#endif  //BT_TRIANGLE_MESH_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btTriangleShape.h
new file mode 100644 (file)
index 0000000..190cbda
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_OBB_TRIANGLE_MINKOWSKI_H
+#define BT_OBB_TRIANGLE_MINKOWSKI_H
+
+#include "btConvexShape.h"
+#include "btBoxShape.h"
+
+ATTRIBUTE_ALIGNED16(class)
+btTriangleShape : public btPolyhedralConvexShape
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btVector3 m_vertices1[3];
+
+       virtual int getNumVertices() const
+       {
+               return 3;
+       }
+
+       btVector3& getVertexPtr(int index)
+       {
+               return m_vertices1[index];
+       }
+
+       const btVector3& getVertexPtr(int index) const
+       {
+               return m_vertices1[index];
+       }
+       virtual void getVertex(int index, btVector3& vert) const
+       {
+               vert = m_vertices1[index];
+       }
+
+       virtual int getNumEdges() const
+       {
+               return 3;
+       }
+
+       virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
+       {
+               getVertex(i, pa);
+               getVertex((i + 1) % 3, pb);
+       }
+
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+       {
+               //              btAssert(0);
+               getAabbSlow(t, aabbMin, aabbMax);
+       }
+
+       btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir) const
+       {
+               btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
+               return m_vertices1[dots.maxAxis()];
+       }
+
+       virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
+       {
+               for (int i = 0; i < numVectors; i++)
+               {
+                       const btVector3& dir = vectors[i];
+                       btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
+                       supportVerticesOut[i] = m_vertices1[dots.maxAxis()];
+               }
+       }
+
+       btTriangleShape() : btPolyhedralConvexShape()
+       {
+               m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
+       }
+
+       btTriangleShape(const btVector3& p0, const btVector3& p1, const btVector3& p2) : btPolyhedralConvexShape()
+       {
+               m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
+               m_vertices1[0] = p0;
+               m_vertices1[1] = p1;
+               m_vertices1[2] = p2;
+       }
+
+       virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
+       {
+               getPlaneEquation(i, planeNormal, planeSupport);
+       }
+
+       virtual int getNumPlanes() const
+       {
+               return 1;
+       }
+
+       void calcNormal(btVector3 & normal) const
+       {
+               normal = (m_vertices1[1] - m_vertices1[0]).cross(m_vertices1[2] - m_vertices1[0]);
+               normal.normalize();
+       }
+
+       virtual void getPlaneEquation(int i, btVector3& planeNormal, btVector3& planeSupport) const
+       {
+               (void)i;
+               calcNormal(planeNormal);
+               planeSupport = m_vertices1[0];
+       }
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const
+       {
+               (void)mass;
+               btAssert(0);
+               inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+       }
+
+       virtual bool isInside(const btVector3& pt, btScalar tolerance) const
+       {
+               btVector3 normal;
+               calcNormal(normal);
+               //distance to plane
+               btScalar dist = pt.dot(normal);
+               btScalar planeconst = m_vertices1[0].dot(normal);
+               dist -= planeconst;
+               if (dist >= -tolerance && dist <= tolerance)
+               {
+                       //inside check on edge-planes
+                       int i;
+                       for (i = 0; i < 3; i++)
+                       {
+                               btVector3 pa, pb;
+                               getEdge(i, pa, pb);
+                               btVector3 edge = pb - pa;
+                               btVector3 edgeNormal = edge.cross(normal);
+                               edgeNormal.normalize();
+                               btScalar dist = pt.dot(edgeNormal);
+                               btScalar edgeConst = pa.dot(edgeNormal);
+                               dist -= edgeConst;
+                               if (dist < -tolerance)
+                                       return false;
+                       }
+
+                       return true;
+               }
+
+               return false;
+       }
+       //debugging
+       virtual const char* getName() const
+       {
+               return "Triangle";
+       }
+
+       virtual int getNumPreferredPenetrationDirections() const
+       {
+               return 2;
+       }
+
+       virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+       {
+               calcNormal(penetrationVector);
+               if (index)
+                       penetrationVector *= btScalar(-1.);
+       }
+};
+
+#endif  //BT_OBB_TRIANGLE_MINKOWSKI_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
new file mode 100644 (file)
index 0000000..ed3cd2d
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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) : btConvexShape(), m_childConvexShape(convexChildShape), m_uniformScalingFactor(uniformScalingFactor)
+{
+       m_shapeType = UNIFORM_SCALING_SHAPE_PROXYTYPE;
+}
+
+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& trans, btVector3& aabbMin, btVector3& aabbMax) const
+{
+       getAabbSlow(trans, aabbMin, aabbMax);
+}
+
+void btUniformScalingShape::getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+#if 1
+       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.)};
+
+       for (int i = 0; i < 6; i++)
+       {
+               _directions[i] = _directions[i] * t.getBasis();
+       }
+
+       batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
+
+       btVector3 aabbMin1(0, 0, 0), aabbMax1(0, 0, 0);
+
+       for (int i = 0; i < 3; ++i)
+       {
+               aabbMax1[i] = t(_supporting[i])[i];
+               aabbMin1[i] = t(_supporting[i + 3])[i];
+       }
+       btVector3 marginVec(getMargin(), getMargin(), getMargin());
+       aabbMin = aabbMin1 - marginVec;
+       aabbMax = aabbMax1 + marginVec;
+
+#else
+
+       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 * t.getBasis());
+               btVector3 tmp = t(sv);
+               aabbMax[i] = tmp[i] + margin;
+               vec[i] = btScalar(-1.);
+               sv = localGetSupportingVertex(vec * t.getBasis());
+               tmp = t(sv);
+               aabbMin[i] = tmp[i] - margin;
+       }
+
+#endif
+}
+
+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/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/CollisionShapes/btUniformScalingShape.h
new file mode 100644 (file)
index 0000000..4dfe34e
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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.
+ATTRIBUTE_ALIGNED16(class)
+btUniformScalingShape : public btConvexShape
+{
+       btConvexShape* m_childConvexShape;
+
+       btScalar m_uniformScalingFactor;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       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";
+       }
+
+       ///////////////////////////
+
+       ///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/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btBoxCollision.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btBoxCollision.h
new file mode 100644 (file)
index 0000000..941dcc6
--- /dev/null
@@ -0,0 +1,632 @@
+#ifndef BT_BOX_COLLISION_H_INCLUDED
+#define BT_BOX_COLLISION_H_INCLUDED
+
+/*! \file gim_box_collision.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "LinearMath/btTransform.h"
+
+///Swap numbers
+#define BT_SWAP_NUMBERS(a, b) \
+       {                         \
+               a = a + b;            \
+               b = a - b;            \
+               a = a - b;            \
+       }
+
+#define BT_MAX(a, b) (a < b ? b : a)
+#define BT_MIN(a, b) (a > b ? b : a)
+
+#define BT_GREATER(x, y) btFabs(x) > (y)
+
+#define BT_MAX3(a, b, c) BT_MAX(a, BT_MAX(b, c))
+#define BT_MIN3(a, b, c) BT_MIN(a, BT_MIN(b, c))
+
+enum eBT_PLANE_INTERSECTION_TYPE
+{
+       BT_CONST_BACK_PLANE = 0,
+       BT_CONST_COLLIDE_PLANE,
+       BT_CONST_FRONT_PLANE
+};
+
+//SIMD_FORCE_INLINE bool test_cross_edge_box(
+//     const btVector3 & edge,
+//     const btVector3 & absolute_edge,
+//     const btVector3 & pointa,
+//     const btVector3 & pointb, const btVector3 & extend,
+//     int dir_index0,
+//     int dir_index1
+//     int component_index0,
+//     int component_index1)
+//{
+//     // dir coords are -z and y
+//
+//     const btScalar dir0 = -edge[dir_index0];
+//     const btScalar dir1 = edge[dir_index1];
+//     btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
+//     btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
+//     //find minmax
+//     if(pmin>pmax)
+//     {
+//             BT_SWAP_NUMBERS(pmin,pmax);
+//     }
+//     //find extends
+//     const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
+//                                     extend[component_index1] * absolute_edge[dir_index1];
+//
+//     if(pmin>rad || -rad>pmax) return false;
+//     return true;
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
+//     const btVector3 & edge,
+//     const btVector3 & absolute_edge,
+//     const btVector3 & pointa,
+//     const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//     return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
+//}
+//
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
+//     const btVector3 & edge,
+//     const btVector3 & absolute_edge,
+//     const btVector3 & pointa,
+//     const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//     return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
+//     const btVector3 & edge,
+//     const btVector3 & absolute_edge,
+//     const btVector3 & pointa,
+//     const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//     return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
+//}
+
+#define TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, i_dir_0, i_dir_1, i_comp_0, i_comp_1) \
+       {                                                                                                               \
+               const btScalar dir0 = -edge[i_dir_0];                                                                       \
+               const btScalar dir1 = edge[i_dir_1];                                                                        \
+               btScalar pmin = pointa[i_comp_0] * dir0 + pointa[i_comp_1] * dir1;                                          \
+               btScalar pmax = pointb[i_comp_0] * dir0 + pointb[i_comp_1] * dir1;                                          \
+               if (pmin > pmax)                                                                                            \
+               {                                                                                                           \
+                       BT_SWAP_NUMBERS(pmin, pmax);                                                                            \
+               }                                                                                                           \
+               const btScalar abs_dir0 = absolute_edge[i_dir_0];                                                           \
+               const btScalar abs_dir1 = absolute_edge[i_dir_1];                                                           \
+               const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;                           \
+               if (pmin > rad || -rad > pmax) return false;                                                                \
+       }
+
+#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend)       \
+       {                                                                                      \
+               TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 2, 1, 1, 2); \
+       }
+
+#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend)       \
+       {                                                                                      \
+               TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 0, 2, 2, 0); \
+       }
+
+#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend)       \
+       {                                                                                      \
+               TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 1, 0, 0, 1); \
+       }
+
+//! Returns the dot product between a vec3f and the col of a matrix
+SIMD_FORCE_INLINE btScalar bt_mat3_dot_col(
+       const btMatrix3x3 &mat, const btVector3 &vec3, int colindex)
+{
+       return vec3[0] * mat[0][colindex] + vec3[1] * mat[1][colindex] + vec3[2] * mat[2][colindex];
+}
+
+//!  Class for transforming a model1 to the space of model0
+ATTRIBUTE_ALIGNED16(class)
+BT_BOX_BOX_TRANSFORM_CACHE
+{
+public:
+       btVector3 m_T1to0;    //!< Transforms translation of model1 to model 0
+       btMatrix3x3 m_R1to0;  //!< Transforms Rotation of model1 to model 0, equal  to R0' * R1
+       btMatrix3x3 m_AR;     //!< Absolute value of m_R1to0
+
+       SIMD_FORCE_INLINE void calc_absolute_matrix()
+       {
+               //              static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
+               //              m_AR[0] = vepsi + m_R1to0[0].absolute();
+               //              m_AR[1] = vepsi + m_R1to0[1].absolute();
+               //              m_AR[2] = vepsi + m_R1to0[2].absolute();
+
+               int i, j;
+
+               for (i = 0; i < 3; i++)
+               {
+                       for (j = 0; j < 3; j++)
+                       {
+                               m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]);
+                       }
+               }
+       }
+
+       BT_BOX_BOX_TRANSFORM_CACHE()
+       {
+       }
+
+       //! Calc the transformation relative  1 to 0. Inverts matrics by transposing
+       SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform &trans0, const btTransform &trans1)
+       {
+               btTransform temp_trans = trans0.inverse();
+               temp_trans = temp_trans * trans1;
+
+               m_T1to0 = temp_trans.getOrigin();
+               m_R1to0 = temp_trans.getBasis();
+
+               calc_absolute_matrix();
+       }
+
+       //! Calcs the full invertion of the matrices. Useful for scaling matrices
+       SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform &trans0, const btTransform &trans1)
+       {
+               m_R1to0 = trans0.getBasis().inverse();
+               m_T1to0 = m_R1to0 * (-trans0.getOrigin());
+
+               m_T1to0 += m_R1to0 * trans1.getOrigin();
+               m_R1to0 *= trans1.getBasis();
+
+               calc_absolute_matrix();
+       }
+
+       SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
+       {
+               return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0;
+       }
+};
+
+#define BOX_PLANE_EPSILON 0.000001f
+
+//! Axis aligned box
+ATTRIBUTE_ALIGNED16(class)
+btAABB
+{
+public:
+       btVector3 m_min;
+       btVector3 m_max;
+
+       btAABB()
+       {
+       }
+
+       btAABB(const btVector3 &V1,
+                  const btVector3 &V2,
+                  const btVector3 &V3)
+       {
+               m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
+               m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
+               m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
+               m_min[3] = 0.f;
+
+               m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
+               m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
+               m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
+               m_max[3] = 0.f;
+       }
+
+       btAABB(const btVector3 &V1,
+                  const btVector3 &V2,
+                  const btVector3 &V3,
+                  btScalar margin)
+       {
+               m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
+               m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
+               m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
+               m_min[3] = 0.f;
+
+               m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
+               m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
+               m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
+               m_max[3] = 0.f;
+
+               m_min[0] -= margin;
+               m_min[1] -= margin;
+               m_min[2] -= margin;
+               m_max[0] += margin;
+               m_max[1] += margin;
+               m_max[2] += margin;
+       }
+
+       btAABB(const btAABB &other) : m_min(other.m_min), m_max(other.m_max)
+       {
+       }
+
+       btAABB(const btAABB &other, btScalar margin) : m_min(other.m_min), m_max(other.m_max)
+       {
+               m_min[0] -= margin;
+               m_min[1] -= margin;
+               m_min[2] -= margin;
+               m_max[0] += margin;
+               m_max[1] += margin;
+               m_max[2] += margin;
+       }
+
+       SIMD_FORCE_INLINE void invalidate()
+       {
+               m_min[0] = SIMD_INFINITY;
+               m_min[1] = SIMD_INFINITY;
+               m_min[2] = SIMD_INFINITY;
+               m_min[3] = 0.f;
+               m_max[0] = -SIMD_INFINITY;
+               m_max[1] = -SIMD_INFINITY;
+               m_max[2] = -SIMD_INFINITY;
+               m_max[3] = 0.f;
+       }
+
+       SIMD_FORCE_INLINE void increment_margin(btScalar margin)
+       {
+               m_min[0] -= margin;
+               m_min[1] -= margin;
+               m_min[2] -= margin;
+               m_max[0] += margin;
+               m_max[1] += margin;
+               m_max[2] += margin;
+       }
+
+       SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin)
+       {
+               m_min[0] = other.m_min[0] - margin;
+               m_min[1] = other.m_min[1] - margin;
+               m_min[2] = other.m_min[2] - margin;
+               m_min[3] = 0.f;
+
+               m_max[0] = other.m_max[0] + margin;
+               m_max[1] = other.m_max[1] + margin;
+               m_max[2] = other.m_max[2] + margin;
+               m_max[3] = 0.f;
+       }
+
+       template <typename CLASS_POINT>
+       SIMD_FORCE_INLINE void calc_from_triangle(
+               const CLASS_POINT &V1,
+               const CLASS_POINT &V2,
+               const CLASS_POINT &V3)
+       {
+               m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
+               m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
+               m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
+               m_min[3] = 0.f;
+
+               m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
+               m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
+               m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
+               m_max[3] = 0.f;
+       }
+
+       template <typename CLASS_POINT>
+       SIMD_FORCE_INLINE void calc_from_triangle_margin(
+               const CLASS_POINT &V1,
+               const CLASS_POINT &V2,
+               const CLASS_POINT &V3, btScalar margin)
+       {
+               m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
+               m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
+               m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
+               m_min[3] = 0.f;
+
+               m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
+               m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
+               m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
+               m_max[3] = 0.f;
+
+               m_min[0] -= margin;
+               m_min[1] -= margin;
+               m_min[2] -= margin;
+               m_max[0] += margin;
+               m_max[1] += margin;
+               m_max[2] += margin;
+       }
+
+       //! Apply a transform to an AABB
+       SIMD_FORCE_INLINE void appy_transform(const btTransform &trans)
+       {
+               btVector3 center = (m_max + m_min) * 0.5f;
+               btVector3 extends = m_max - center;
+               // Compute new center
+               center = trans(center);
+
+               btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
+                                                                                 trans.getBasis().getRow(1).absolute(),
+                                                                                 trans.getBasis().getRow(2).absolute());
+
+               m_min = center - textends;
+               m_max = center + textends;
+       }
+
+       //! Apply a transform to an AABB
+       SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE &trans)
+       {
+               btVector3 center = (m_max + m_min) * 0.5f;
+               btVector3 extends = m_max - center;
+               // Compute new center
+               center = trans.transform(center);
+
+               btVector3 textends = extends.dot3(trans.m_R1to0.getRow(0).absolute(),
+                                                                                 trans.m_R1to0.getRow(1).absolute(),
+                                                                                 trans.m_R1to0.getRow(2).absolute());
+
+               m_min = center - textends;
+               m_max = center + textends;
+       }
+
+       //! Merges a Box
+       SIMD_FORCE_INLINE void merge(const btAABB &box)
+       {
+               m_min[0] = BT_MIN(m_min[0], box.m_min[0]);
+               m_min[1] = BT_MIN(m_min[1], box.m_min[1]);
+               m_min[2] = BT_MIN(m_min[2], box.m_min[2]);
+
+               m_max[0] = BT_MAX(m_max[0], box.m_max[0]);
+               m_max[1] = BT_MAX(m_max[1], box.m_max[1]);
+               m_max[2] = BT_MAX(m_max[2], box.m_max[2]);
+       }
+
+       //! Merges a point
+       template <typename CLASS_POINT>
+       SIMD_FORCE_INLINE void merge_point(const CLASS_POINT &point)
+       {
+               m_min[0] = BT_MIN(m_min[0], point[0]);
+               m_min[1] = BT_MIN(m_min[1], point[1]);
+               m_min[2] = BT_MIN(m_min[2], point[2]);
+
+               m_max[0] = BT_MAX(m_max[0], point[0]);
+               m_max[1] = BT_MAX(m_max[1], point[1]);
+               m_max[2] = BT_MAX(m_max[2], point[2]);
+       }
+
+       //! Gets the extend and center
+       SIMD_FORCE_INLINE void get_center_extend(btVector3 & center, btVector3 & extend) const
+       {
+               center = (m_max + m_min) * 0.5f;
+               extend = m_max - center;
+       }
+
+       //! Finds the intersecting box between this box and the other.
+       SIMD_FORCE_INLINE void find_intersection(const btAABB &other, btAABB &intersection) const
+       {
+               intersection.m_min[0] = BT_MAX(other.m_min[0], m_min[0]);
+               intersection.m_min[1] = BT_MAX(other.m_min[1], m_min[1]);
+               intersection.m_min[2] = BT_MAX(other.m_min[2], m_min[2]);
+
+               intersection.m_max[0] = BT_MIN(other.m_max[0], m_max[0]);
+               intersection.m_max[1] = BT_MIN(other.m_max[1], m_max[1]);
+               intersection.m_max[2] = BT_MIN(other.m_max[2], m_max[2]);
+       }
+
+       SIMD_FORCE_INLINE bool has_collision(const btAABB &other) const
+       {
+               if (m_min[0] > other.m_max[0] ||
+                       m_max[0] < other.m_min[0] ||
+                       m_min[1] > other.m_max[1] ||
+                       m_max[1] < other.m_min[1] ||
+                       m_min[2] > other.m_max[2] ||
+                       m_max[2] < other.m_min[2])
+               {
+                       return false;
+               }
+               return true;
+       }
+
+       /*! \brief Finds the Ray intersection parameter.
+       \param aabb Aligned box
+       \param vorigin A vec3f with the origin of the ray
+       \param vdir A vec3f with the direction of the ray
+       */
+       SIMD_FORCE_INLINE bool collide_ray(const btVector3 &vorigin, const btVector3 &vdir) const
+       {
+               btVector3 extents, center;
+               this->get_center_extend(center, extents);
+               ;
+
+               btScalar Dx = vorigin[0] - center[0];
+               if (BT_GREATER(Dx, extents[0]) && Dx * vdir[0] >= 0.0f) return false;
+               btScalar Dy = vorigin[1] - center[1];
+               if (BT_GREATER(Dy, extents[1]) && Dy * vdir[1] >= 0.0f) return false;
+               btScalar Dz = vorigin[2] - center[2];
+               if (BT_GREATER(Dz, extents[2]) && Dz * vdir[2] >= 0.0f) return false;
+
+               btScalar f = vdir[1] * Dz - vdir[2] * Dy;
+               if (btFabs(f) > extents[1] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[1])) return false;
+               f = vdir[2] * Dx - vdir[0] * Dz;
+               if (btFabs(f) > extents[0] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[0])) return false;
+               f = vdir[0] * Dy - vdir[1] * Dx;
+               if (btFabs(f) > extents[0] * btFabs(vdir[1]) + extents[1] * btFabs(vdir[0])) return false;
+               return true;
+       }
+
+       SIMD_FORCE_INLINE void projection_interval(const btVector3 &direction, btScalar &vmin, btScalar &vmax) const
+       {
+               btVector3 center = (m_max + m_min) * 0.5f;
+               btVector3 extend = m_max - center;
+
+               btScalar _fOrigin = direction.dot(center);
+               btScalar _fMaximumExtent = extend.dot(direction.absolute());
+               vmin = _fOrigin - _fMaximumExtent;
+               vmax = _fOrigin + _fMaximumExtent;
+       }
+
+       SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
+       {
+               btScalar _fmin, _fmax;
+               this->projection_interval(plane, _fmin, _fmax);
+
+               if (plane[3] > _fmax + BOX_PLANE_EPSILON)
+               {
+                       return BT_CONST_BACK_PLANE;  // 0
+               }
+
+               if (plane[3] + BOX_PLANE_EPSILON >= _fmin)
+               {
+                       return BT_CONST_COLLIDE_PLANE;  //1
+               }
+               return BT_CONST_FRONT_PLANE;  //2
+       }
+
+       SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB &box, btTransform &trans1_to_0) const
+       {
+               btAABB tbox = box;
+               tbox.appy_transform(trans1_to_0);
+               return has_collision(tbox);
+       }
+
+       SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB &box,
+                                                                                                                  const BT_BOX_BOX_TRANSFORM_CACHE &trans1_to_0) const
+       {
+               btAABB tbox = box;
+               tbox.appy_transform_trans_cache(trans1_to_0);
+               return has_collision(tbox);
+       }
+
+       //! transcache is the transformation cache from box to this AABB
+       SIMD_FORCE_INLINE bool overlapping_trans_cache(
+               const btAABB &box, const BT_BOX_BOX_TRANSFORM_CACHE &transcache, bool fulltest) const
+       {
+               //Taken from OPCODE
+               btVector3 ea, eb;  //extends
+               btVector3 ca, cb;  //extends
+               get_center_extend(ca, ea);
+               box.get_center_extend(cb, eb);
+
+               btVector3 T;
+               btScalar t, t2;
+               int i;
+
+               // Class I : A's basis vectors
+               for (i = 0; i < 3; i++)
+               {
+                       T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
+                       t = transcache.m_AR[i].dot(eb) + ea[i];
+                       if (BT_GREATER(T[i], t)) return false;
+               }
+               // Class II : B's basis vectors
+               for (i = 0; i < 3; i++)
+               {
+                       t = bt_mat3_dot_col(transcache.m_R1to0, T, i);
+                       t2 = bt_mat3_dot_col(transcache.m_AR, ea, i) + eb[i];
+                       if (BT_GREATER(t, t2)) return false;
+               }
+               // Class III : 9 cross products
+               if (fulltest)
+               {
+                       int j, m, n, o, p, q, r;
+                       for (i = 0; i < 3; i++)
+                       {
+                               m = (i + 1) % 3;
+                               n = (i + 2) % 3;
+                               o = i == 0 ? 1 : 0;
+                               p = i == 2 ? 1 : 2;
+                               for (j = 0; j < 3; j++)
+                               {
+                                       q = j == 2 ? 1 : 2;
+                                       r = j == 0 ? 1 : 0;
+                                       t = T[n] * transcache.m_R1to0[m][j] - T[m] * transcache.m_R1to0[n][j];
+                                       t2 = ea[o] * transcache.m_AR[p][j] + ea[p] * transcache.m_AR[o][j] +
+                                                eb[r] * transcache.m_AR[i][q] + eb[q] * transcache.m_AR[i][r];
+                                       if (BT_GREATER(t, t2)) return false;
+                               }
+                       }
+               }
+               return true;
+       }
+
+       //! Simple test for planes.
+       SIMD_FORCE_INLINE bool collide_plane(
+               const btVector4 &plane) const
+       {
+               eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane);
+               return (classify == BT_CONST_COLLIDE_PLANE);
+       }
+
+       //! test for a triangle, with edges
+       SIMD_FORCE_INLINE bool collide_triangle_exact(
+               const btVector3 &p1,
+               const btVector3 &p2,
+               const btVector3 &p3,
+               const btVector4 &triangle_plane) const
+       {
+               if (!collide_plane(triangle_plane)) return false;
+
+               btVector3 center, extends;
+               this->get_center_extend(center, extends);
+
+               const btVector3 v1(p1 - center);
+               const btVector3 v2(p2 - center);
+               const btVector3 v3(p3 - center);
+
+               //First axis
+               btVector3 diff(v2 - v1);
+               btVector3 abs_diff = diff.absolute();
+               //Test With X axis
+               TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v1, v3, extends);
+               //Test With Y axis
+               TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v1, v3, extends);
+               //Test With Z axis
+               TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v1, v3, extends);
+
+               diff = v3 - v2;
+               abs_diff = diff.absolute();
+               //Test With X axis
+               TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v2, v1, extends);
+               //Test With Y axis
+               TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v2, v1, extends);
+               //Test With Z axis
+               TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v2, v1, extends);
+
+               diff = v1 - v3;
+               abs_diff = diff.absolute();
+               //Test With X axis
+               TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v3, v2, extends);
+               //Test With Y axis
+               TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v3, v2, extends);
+               //Test With Z axis
+               TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v3, v2, extends);
+
+               return true;
+       }
+};
+
+//! Compairison of transformation objects
+SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform &t1, const btTransform &t2)
+{
+       if (!(t1.getOrigin() == t2.getOrigin())) return false;
+
+       if (!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0))) return false;
+       if (!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1))) return false;
+       if (!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2))) return false;
+       return true;
+}
+
+#endif  // GIM_BOX_COLLISION_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btClipPolygon.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btClipPolygon.h
new file mode 100644 (file)
index 0000000..38c23e2
--- /dev/null
@@ -0,0 +1,173 @@
+#ifndef BT_CLIP_POLYGON_H_INCLUDED
+#define BT_CLIP_POLYGON_H_INCLUDED
+
+/*! \file btClipPolygon.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "LinearMath/btTransform.h"
+#include "LinearMath/btGeometryUtil.h"
+
+SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 &plane, const btVector3 &point)
+{
+       return point.dot(plane) - plane[3];
+}
+
+/*! Vector blending
+Takes two vectors a, b, blends them together*/
+SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va, const btVector3 &vb, btScalar blend_factor)
+{
+       vr = (1 - blend_factor) * va + blend_factor * vb;
+}
+
+//! This function calcs the distance from a 3D plane
+SIMD_FORCE_INLINE void bt_plane_clip_polygon_collect(
+       const btVector3 &point0,
+       const btVector3 &point1,
+       btScalar dist0,
+       btScalar dist1,
+       btVector3 *clipped,
+       int &clipped_count)
+{
+       bool _prevclassif = (dist0 > SIMD_EPSILON);
+       bool _classif = (dist1 > SIMD_EPSILON);
+       if (_classif != _prevclassif)
+       {
+               btScalar blendfactor = -dist0 / (dist1 - dist0);
+               bt_vec_blend(clipped[clipped_count], point0, point1, blendfactor);
+               clipped_count++;
+       }
+       if (!_classif)
+       {
+               clipped[clipped_count] = point1;
+               clipped_count++;
+       }
+}
+
+//! Clips a polygon by a plane
+/*!
+*\return The count of the clipped counts
+*/
+SIMD_FORCE_INLINE int bt_plane_clip_polygon(
+       const btVector4 &plane,
+       const btVector3 *polygon_points,
+       int polygon_point_count,
+       btVector3 *clipped)
+{
+       int clipped_count = 0;
+
+       //clip first point
+       btScalar firstdist = bt_distance_point_plane(plane, polygon_points[0]);
+       ;
+       if (!(firstdist > SIMD_EPSILON))
+       {
+               clipped[clipped_count] = polygon_points[0];
+               clipped_count++;
+       }
+
+       btScalar olddist = firstdist;
+       for (int i = 1; i < polygon_point_count; i++)
+       {
+               btScalar dist = bt_distance_point_plane(plane, polygon_points[i]);
+
+               bt_plane_clip_polygon_collect(
+                       polygon_points[i - 1], polygon_points[i],
+                       olddist,
+                       dist,
+                       clipped,
+                       clipped_count);
+
+               olddist = dist;
+       }
+
+       //RETURN TO FIRST  point
+
+       bt_plane_clip_polygon_collect(
+               polygon_points[polygon_point_count - 1], polygon_points[0],
+               olddist,
+               firstdist,
+               clipped,
+               clipped_count);
+
+       return clipped_count;
+}
+
+//! Clips a polygon by a plane
+/*!
+*\param clipped must be an array of 16 points.
+*\return The count of the clipped counts
+*/
+SIMD_FORCE_INLINE int bt_plane_clip_triangle(
+       const btVector4 &plane,
+       const btVector3 &point0,
+       const btVector3 &point1,
+       const btVector3 &point2,
+       btVector3 *clipped  // an allocated array of 16 points at least
+)
+{
+       int clipped_count = 0;
+
+       //clip first point0
+       btScalar firstdist = bt_distance_point_plane(plane, point0);
+       ;
+       if (!(firstdist > SIMD_EPSILON))
+       {
+               clipped[clipped_count] = point0;
+               clipped_count++;
+       }
+
+       // point 1
+       btScalar olddist = firstdist;
+       btScalar dist = bt_distance_point_plane(plane, point1);
+
+       bt_plane_clip_polygon_collect(
+               point0, point1,
+               olddist,
+               dist,
+               clipped,
+               clipped_count);
+
+       olddist = dist;
+
+       // point 2
+       dist = bt_distance_point_plane(plane, point2);
+
+       bt_plane_clip_polygon_collect(
+               point1, point2,
+               olddist,
+               dist,
+               clipped,
+               clipped_count);
+       olddist = dist;
+
+       //RETURN TO FIRST  point0
+       bt_plane_clip_polygon_collect(
+               point2, point0,
+               olddist,
+               firstdist,
+               clipped,
+               clipped_count);
+
+       return clipped_count;
+}
+
+#endif  // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btCompoundFromGimpact.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btCompoundFromGimpact.h
new file mode 100644 (file)
index 0000000..ede59e8
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef BT_COMPOUND_FROM_GIMPACT
+#define BT_COMPOUND_FROM_GIMPACT
+
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "btGImpactShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+
+ATTRIBUTE_ALIGNED16(class)
+btCompoundFromGimpactShape : public btCompoundShape
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       virtual ~btCompoundFromGimpactShape()
+       {
+               /*delete all the btBU_Simplex1to4 ChildShapes*/
+               for (int i = 0; i < m_children.size(); i++)
+               {
+                       delete m_children[i].m_childShape;
+               }
+       }
+};
+
+struct MyCallback : public btTriangleRaycastCallback
+{
+       int m_ignorePart;
+       int m_ignoreTriangleIndex;
+
+       MyCallback(const btVector3& from, const btVector3& to, int ignorePart, int ignoreTriangleIndex)
+               : btTriangleRaycastCallback(from, to),
+                 m_ignorePart(ignorePart),
+                 m_ignoreTriangleIndex(ignoreTriangleIndex)
+       {
+       }
+       virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
+       {
+               if (partId != m_ignorePart || triangleIndex != m_ignoreTriangleIndex)
+               {
+                       if (hitFraction < m_hitFraction)
+                               return hitFraction;
+               }
+
+               return m_hitFraction;
+       }
+};
+struct MyInternalTriangleIndexCallback : public btInternalTriangleIndexCallback
+{
+       const btGImpactMeshShape* m_gimpactShape;
+       btCompoundShape* m_colShape;
+       btScalar m_depth;
+
+       MyInternalTriangleIndexCallback(btCompoundShape* colShape, const btGImpactMeshShape* meshShape, btScalar depth)
+               : m_colShape(colShape),
+                 m_gimpactShape(meshShape),
+                 m_depth(depth)
+       {
+       }
+
+       virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+       {
+               btVector3 scale = m_gimpactShape->getLocalScaling();
+               btVector3 v0 = triangle[0] * scale;
+               btVector3 v1 = triangle[1] * scale;
+               btVector3 v2 = triangle[2] * scale;
+
+               btVector3 centroid = (v0 + v1 + v2) / 3;
+               btVector3 normal = (v1 - v0).cross(v2 - v0);
+               normal.normalize();
+               btVector3 rayFrom = centroid;
+               btVector3 rayTo = centroid - normal * m_depth;
+
+               MyCallback cb(rayFrom, rayTo, partId, triangleIndex);
+
+               m_gimpactShape->processAllTrianglesRay(&cb, rayFrom, rayTo);
+               if (cb.m_hitFraction < 1)
+               {
+                       rayTo.setInterpolate3(cb.m_from, cb.m_to, cb.m_hitFraction);
+                       //rayTo = cb.m_from;
+                       //rayTo = rayTo.lerp(cb.m_to,cb.m_hitFraction);
+                       //gDebugDraw.drawLine(tr(centroid),tr(centroid+normal),btVector3(1,0,0));
+               }
+
+               btBU_Simplex1to4* tet = new btBU_Simplex1to4(v0, v1, v2, rayTo);
+               btTransform ident;
+               ident.setIdentity();
+               m_colShape->addChildShape(ident, tet);
+       }
+};
+
+btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimpactMesh, btScalar depth)
+{
+       btCompoundShape* colShape = new btCompoundFromGimpactShape();
+
+       btTransform tr;
+       tr.setIdentity();
+
+       MyInternalTriangleIndexCallback cb(colShape, gimpactMesh, depth);
+       btVector3 aabbMin, aabbMax;
+       gimpactMesh->getAabb(tr, aabbMin, aabbMax);
+       gimpactMesh->getMeshInterface()->InternalProcessAllTriangles(&cb, aabbMin, aabbMax);
+
+       return colShape;
+}
+
+#endif  //BT_COMPOUND_FROM_GIMPACT
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btContactProcessing.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btContactProcessing.cpp
new file mode 100644 (file)
index 0000000..f2e3e18
--- /dev/null
@@ -0,0 +1,175 @@
+
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "btContactProcessing.h"
+
+#define MAX_COINCIDENT 8
+
+struct CONTACT_KEY_TOKEN
+{
+       unsigned int m_key;
+       int m_value;
+       CONTACT_KEY_TOKEN()
+       {
+       }
+
+       CONTACT_KEY_TOKEN(unsigned int key, int token)
+       {
+               m_key = key;
+               m_value = token;
+       }
+
+       CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken)
+       {
+               m_key = rtoken.m_key;
+               m_value = rtoken.m_value;
+       }
+
+       inline bool operator<(const CONTACT_KEY_TOKEN& other) const
+       {
+               return (m_key < other.m_key);
+       }
+
+       inline bool operator>(const CONTACT_KEY_TOKEN& other) const
+       {
+               return (m_key > other.m_key);
+       }
+};
+
+class CONTACT_KEY_TOKEN_COMP
+{
+public:
+       bool operator()(const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b) const
+       {
+               return (a < b);
+       }
+};
+
+void btContactArray::merge_contacts(
+       const btContactArray& contacts, bool normal_contact_average)
+{
+       clear();
+
+       int i;
+       if (contacts.size() == 0) return;
+
+       if (contacts.size() == 1)
+       {
+               push_back(contacts[0]);
+               return;
+       }
+
+       btAlignedObjectArray<CONTACT_KEY_TOKEN> keycontacts;
+
+       keycontacts.reserve(contacts.size());
+
+       //fill key contacts
+
+       for (i = 0; i < contacts.size(); i++)
+       {
+               keycontacts.push_back(CONTACT_KEY_TOKEN(contacts[i].calc_key_contact(), i));
+       }
+
+       //sort keys
+       keycontacts.quickSort(CONTACT_KEY_TOKEN_COMP());
+
+       // Merge contacts
+       int coincident_count = 0;
+       btVector3 coincident_normals[MAX_COINCIDENT];
+
+       unsigned int last_key = keycontacts[0].m_key;
+       unsigned int key = 0;
+
+       push_back(contacts[keycontacts[0].m_value]);
+
+       GIM_CONTACT* pcontact = &(*this)[0];
+
+       for (i = 1; i < keycontacts.size(); i++)
+       {
+               key = keycontacts[i].m_key;
+               const GIM_CONTACT* scontact = &contacts[keycontacts[i].m_value];
+
+               if (last_key == key)  //same points
+               {
+                       //merge contact
+                       if (pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)  //)
+                       {
+                               *pcontact = *scontact;
+                               coincident_count = 0;
+                       }
+                       else if (normal_contact_average)
+                       {
+                               if (btFabs(pcontact->m_depth - scontact->m_depth) < CONTACT_DIFF_EPSILON)
+                               {
+                                       if (coincident_count < MAX_COINCIDENT)
+                                       {
+                                               coincident_normals[coincident_count] = scontact->m_normal;
+                                               coincident_count++;
+                                       }
+                               }
+                       }
+               }
+               else
+               {  //add new contact
+
+                       if (normal_contact_average && coincident_count > 0)
+                       {
+                               pcontact->interpolate_normals(coincident_normals, coincident_count);
+                               coincident_count = 0;
+                       }
+
+                       push_back(*scontact);
+                       pcontact = &(*this)[this->size() - 1];
+               }
+               last_key = key;
+       }
+}
+
+void btContactArray::merge_contacts_unique(const btContactArray& contacts)
+{
+       clear();
+
+       if (contacts.size() == 0) return;
+
+       if (contacts.size() == 1)
+       {
+               push_back(contacts[0]);
+               return;
+       }
+
+       GIM_CONTACT average_contact = contacts[0];
+
+       for (int i = 1; i < contacts.size(); i++)
+       {
+               average_contact.m_point += contacts[i].m_point;
+               average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
+       }
+
+       //divide
+       btScalar divide_average = 1.0f / ((btScalar)contacts.size());
+
+       average_contact.m_point *= divide_average;
+
+       average_contact.m_normal *= divide_average;
+
+       average_contact.m_depth = average_contact.m_normal.length();
+
+       average_contact.m_normal /= average_contact.m_depth;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btContactProcessing.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btContactProcessing.h
new file mode 100644 (file)
index 0000000..4ff09d7
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef BT_CONTACT_H_INCLUDED
+#define BT_CONTACT_H_INCLUDED
+
+/*! \file gim_contact.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btTriangleShapeEx.h"
+#include "btContactProcessingStructs.h"
+
+class btContactArray : public btAlignedObjectArray<GIM_CONTACT>
+{
+public:
+       btContactArray()
+       {
+               reserve(64);
+       }
+
+       SIMD_FORCE_INLINE void push_contact(
+               const btVector3 &point, const btVector3 &normal,
+               btScalar depth, int feature1, int feature2)
+       {
+               push_back(GIM_CONTACT(point, normal, depth, feature1, feature2));
+       }
+
+       SIMD_FORCE_INLINE void push_triangle_contacts(
+               const GIM_TRIANGLE_CONTACT &tricontact,
+               int feature1, int feature2)
+       {
+               for (int i = 0; i < tricontact.m_point_count; i++)
+               {
+                       push_contact(
+                               tricontact.m_points[i],
+                               tricontact.m_separating_normal,
+                               tricontact.m_penetration_depth, feature1, feature2);
+               }
+       }
+
+       void merge_contacts(const btContactArray &contacts, bool normal_contact_average = true);
+
+       void merge_contacts_unique(const btContactArray &contacts);
+};
+
+#endif  // GIM_CONTACT_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btContactProcessingStructs.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btContactProcessingStructs.h
new file mode 100644 (file)
index 0000000..bc8a709
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef BT_CONTACT_H_STRUCTS_INCLUDED
+#define BT_CONTACT_H_STRUCTS_INCLUDED
+
+/*! \file gim_contact.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btTriangleShapeEx.h"
+
+/**
+Configuration var for applying interpolation of  contact normals
+*/
+#define NORMAL_CONTACT_AVERAGE 1
+
+#define CONTACT_DIFF_EPSILON 0.00001f
+
+///The GIM_CONTACT is an internal GIMPACT structure, similar to btManifoldPoint.
+///@todo: remove and replace GIM_CONTACT by btManifoldPoint.
+class GIM_CONTACT
+{
+public:
+       btVector3 m_point;
+       btVector3 m_normal;
+       btScalar m_depth;     //Positive value indicates interpenetration
+       btScalar m_distance;  //Padding not for use
+       int m_feature1;       //Face number
+       int m_feature2;       //Face number
+public:
+       GIM_CONTACT()
+       {
+       }
+
+       GIM_CONTACT(const GIM_CONTACT &contact) : m_point(contact.m_point),
+                                                                                         m_normal(contact.m_normal),
+                                                                                         m_depth(contact.m_depth),
+                                                                                         m_feature1(contact.m_feature1),
+                                                                                         m_feature2(contact.m_feature2)
+       {
+       }
+
+       GIM_CONTACT(const btVector3 &point, const btVector3 &normal,
+                               btScalar depth, int feature1, int feature2) : m_point(point),
+                                                                                                                         m_normal(normal),
+                                                                                                                         m_depth(depth),
+                                                                                                                         m_feature1(feature1),
+                                                                                                                         m_feature2(feature2)
+       {
+       }
+
+       //! Calcs key for coord classification
+       SIMD_FORCE_INLINE unsigned int calc_key_contact() const
+       {
+               int _coords[] = {
+                       (int)(m_point[0] * 1000.0f + 1.0f),
+                       (int)(m_point[1] * 1333.0f),
+                       (int)(m_point[2] * 2133.0f + 3.0f)};
+               unsigned int _hash = 0;
+               unsigned int *_uitmp = (unsigned int *)(&_coords[0]);
+               _hash = *_uitmp;
+               _uitmp++;
+               _hash += (*_uitmp) << 4;
+               _uitmp++;
+               _hash += (*_uitmp) << 8;
+               return _hash;
+       }
+
+       SIMD_FORCE_INLINE void interpolate_normals(btVector3 *normals, int normal_count)
+       {
+               btVector3 vec_sum(m_normal);
+               for (int i = 0; i < normal_count; i++)
+               {
+                       vec_sum += normals[i];
+               }
+
+               btScalar vec_sum_len = vec_sum.length2();
+               if (vec_sum_len < CONTACT_DIFF_EPSILON) return;
+
+               //GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
+
+               m_normal = vec_sum / btSqrt(vec_sum_len);
+       }
+};
+
+#endif  // BT_CONTACT_H_STRUCTS_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactBvh.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactBvh.cpp
new file mode 100644 (file)
index 0000000..bb520e0
--- /dev/null
@@ -0,0 +1,464 @@
+/*! \file gim_box_set.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "btGImpactBvh.h"
+#include "LinearMath/btQuickprof.h"
+
+#ifdef TRI_COLLISION_PROFILING
+
+btClock g_tree_clock;
+
+float g_accum_tree_collision_time = 0;
+int g_count_traversing = 0;
+
+void bt_begin_gim02_tree_time()
+{
+       g_tree_clock.reset();
+}
+
+void bt_end_gim02_tree_time()
+{
+       g_accum_tree_collision_time += g_tree_clock.getTimeMicroseconds();
+       g_count_traversing++;
+}
+
+//! Gets the average time in miliseconds of tree collisions
+float btGImpactBvh::getAverageTreeCollisionTime()
+{
+       if (g_count_traversing == 0) return 0;
+
+       float avgtime = g_accum_tree_collision_time;
+       avgtime /= (float)g_count_traversing;
+
+       g_accum_tree_collision_time = 0;
+       g_count_traversing = 0;
+       return avgtime;
+
+       //      float avgtime = g_count_traversing;
+       //      g_count_traversing = 0;
+       //      return avgtime;
+}
+
+#endif  //TRI_COLLISION_PROFILING
+
+/////////////////////// btBvhTree /////////////////////////////////
+
+int btBvhTree::_calc_splitting_axis(
+       GIM_BVH_DATA_ARRAY& primitive_boxes, 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) * (primitive_boxes[i].m_bound.m_max +
+                                                                                       primitive_boxes[i].m_bound.m_min);
+               means += center;
+       }
+       means *= (btScalar(1.) / (btScalar)numIndices);
+
+       for (i = startIndex; i < endIndex; i++)
+       {
+               btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+                                                                                       primitive_boxes[i].m_bound.m_min);
+               btVector3 diff2 = center - means;
+               diff2 = diff2 * diff2;
+               variance += diff2;
+       }
+       variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
+
+       return variance.maxAxis();
+}
+
+int btBvhTree::_sort_and_calc_splitting_index(
+       GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex,
+       int endIndex, int splitAxis)
+{
+       int i;
+       int splitIndex = startIndex;
+       int numIndices = endIndex - startIndex;
+
+       // average of centers
+       btScalar splitValue = 0.0f;
+
+       btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
+       for (i = startIndex; i < endIndex; i++)
+       {
+               btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+                                                                                       primitive_boxes[i].m_bound.m_min);
+               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) * (primitive_boxes[i].m_bound.m_max +
+                                                                                       primitive_boxes[i].m_bound.m_min);
+               if (center[splitAxis] > splitValue)
+               {
+                       //swap
+                       primitive_boxes.swap(i, splitIndex);
+                       //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);
+       }
+
+       btAssert(!((splitIndex == startIndex) || (splitIndex == (endIndex))));
+
+       return splitIndex;
+}
+
+void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex)
+{
+       int curIndex = m_num_nodes;
+       m_num_nodes++;
+
+       btAssert((endIndex - startIndex) > 0);
+
+       if ((endIndex - startIndex) == 1)
+       {
+               //We have a leaf node
+               setNodeBound(curIndex, primitive_boxes[startIndex].m_bound);
+               m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
+
+               return;
+       }
+       //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+       //split axis
+       int splitIndex = _calc_splitting_axis(primitive_boxes, startIndex, endIndex);
+
+       splitIndex = _sort_and_calc_splitting_index(
+               primitive_boxes, startIndex, endIndex,
+               splitIndex  //split axis
+       );
+
+       //calc this node bounding box
+
+       btAABB node_bound;
+       node_bound.invalidate();
+
+       for (int i = startIndex; i < endIndex; i++)
+       {
+               node_bound.merge(primitive_boxes[i].m_bound);
+       }
+
+       setNodeBound(curIndex, node_bound);
+
+       //build left branch
+       _build_sub_tree(primitive_boxes, startIndex, splitIndex);
+
+       //build right branch
+       _build_sub_tree(primitive_boxes, splitIndex, endIndex);
+
+       m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
+}
+
+//! stackless build tree
+void btBvhTree::build_tree(
+       GIM_BVH_DATA_ARRAY& primitive_boxes)
+{
+       // initialize node count to 0
+       m_num_nodes = 0;
+       // allocate nodes
+       m_node_array.resize(primitive_boxes.size() * 2);
+
+       _build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
+}
+
+////////////////////////////////////class btGImpactBvh
+
+void btGImpactBvh::refit()
+{
+       int nodecount = getNodeCount();
+       while (nodecount--)
+       {
+               if (isLeafNode(nodecount))
+               {
+                       btAABB leafbox;
+                       m_primitive_manager->get_primitive_box(getNodeData(nodecount), leafbox);
+                       setNodeBound(nodecount, leafbox);
+               }
+               else
+               {
+                       //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
+                       //get left bound
+                       btAABB bound;
+                       bound.invalidate();
+
+                       btAABB temp_box;
+
+                       int child_node = getLeftNode(nodecount);
+                       if (child_node)
+                       {
+                               getNodeBound(child_node, temp_box);
+                               bound.merge(temp_box);
+                       }
+
+                       child_node = getRightNode(nodecount);
+                       if (child_node)
+                       {
+                               getNodeBound(child_node, temp_box);
+                               bound.merge(temp_box);
+                       }
+
+                       setNodeBound(nodecount, bound);
+               }
+       }
+}
+
+//! this rebuild the entire set
+void btGImpactBvh::buildSet()
+{
+       //obtain primitive boxes
+       GIM_BVH_DATA_ARRAY primitive_boxes;
+       primitive_boxes.resize(m_primitive_manager->get_primitive_count());
+
+       for (int i = 0; i < primitive_boxes.size(); i++)
+       {
+               m_primitive_manager->get_primitive_box(i, primitive_boxes[i].m_bound);
+               primitive_boxes[i].m_data = i;
+       }
+
+       m_box_tree.build_tree(primitive_boxes);
+}
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactBvh::boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const
+{
+       int curIndex = 0;
+       int numNodes = getNodeCount();
+
+       while (curIndex < numNodes)
+       {
+               btAABB bound;
+               getNodeBound(curIndex, bound);
+
+               //catch bugs in tree data
+
+               bool aabbOverlap = bound.has_collision(box);
+               bool isleafnode = isLeafNode(curIndex);
+
+               if (isleafnode && aabbOverlap)
+               {
+                       collided_results.push_back(getNodeData(curIndex));
+               }
+
+               if (aabbOverlap || isleafnode)
+               {
+                       //next subnode
+                       curIndex++;
+               }
+               else
+               {
+                       //skip node
+                       curIndex += getEscapeNodeIndex(curIndex);
+               }
+       }
+       if (collided_results.size() > 0) return true;
+       return false;
+}
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactBvh::rayQuery(
+       const btVector3& ray_dir, const btVector3& ray_origin,
+       btAlignedObjectArray<int>& collided_results) const
+{
+       int curIndex = 0;
+       int numNodes = getNodeCount();
+
+       while (curIndex < numNodes)
+       {
+               btAABB bound;
+               getNodeBound(curIndex, bound);
+
+               //catch bugs in tree data
+
+               bool aabbOverlap = bound.collide_ray(ray_origin, ray_dir);
+               bool isleafnode = isLeafNode(curIndex);
+
+               if (isleafnode && aabbOverlap)
+               {
+                       collided_results.push_back(getNodeData(curIndex));
+               }
+
+               if (aabbOverlap || isleafnode)
+               {
+                       //next subnode
+                       curIndex++;
+               }
+               else
+               {
+                       //skip node
+                       curIndex += getEscapeNodeIndex(curIndex);
+               }
+       }
+       if (collided_results.size() > 0) return true;
+       return false;
+}
+
+SIMD_FORCE_INLINE bool _node_collision(
+       btGImpactBvh* boxset0, btGImpactBvh* boxset1,
+       const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
+       int node0, int node1, bool complete_primitive_tests)
+{
+       btAABB box0;
+       boxset0->getNodeBound(node0, box0);
+       btAABB box1;
+       boxset1->getNodeBound(node1, box1);
+
+       return box0.overlapping_trans_cache(box1, trans_cache_1to0, complete_primitive_tests);
+       //      box1.appy_transform_trans_cache(trans_cache_1to0);
+       //      return box0.has_collision(box1);
+}
+
+//stackless recursive collision routine
+static void _find_collision_pairs_recursive(
+       btGImpactBvh* boxset0, btGImpactBvh* boxset1,
+       btPairSet* collision_pairs,
+       const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
+       int node0, int node1, bool complete_primitive_tests)
+{
+       if (_node_collision(
+                       boxset0, boxset1, trans_cache_1to0,
+                       node0, node1, complete_primitive_tests) == false) return;  //avoid colliding internal nodes
+
+       if (boxset0->isLeafNode(node0))
+       {
+               if (boxset1->isLeafNode(node1))
+               {
+                       // collision result
+                       collision_pairs->push_pair(
+                               boxset0->getNodeData(node0), boxset1->getNodeData(node1));
+                       return;
+               }
+               else
+               {
+                       //collide left recursive
+
+                       _find_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               node0, boxset1->getLeftNode(node1), false);
+
+                       //collide right recursive
+                       _find_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               node0, boxset1->getRightNode(node1), false);
+               }
+       }
+       else
+       {
+               if (boxset1->isLeafNode(node1))
+               {
+                       //collide left recursive
+                       _find_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getLeftNode(node0), node1, false);
+
+                       //collide right recursive
+
+                       _find_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getRightNode(node0), node1, false);
+               }
+               else
+               {
+                       //collide left0 left1
+
+                       _find_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getLeftNode(node0), boxset1->getLeftNode(node1), false);
+
+                       //collide left0 right1
+
+                       _find_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getLeftNode(node0), boxset1->getRightNode(node1), false);
+
+                       //collide right0 left1
+
+                       _find_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getRightNode(node0), boxset1->getLeftNode(node1), false);
+
+                       //collide right0 right1
+
+                       _find_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getRightNode(node0), boxset1->getRightNode(node1), false);
+
+               }  // else if node1 is not a leaf
+       }      // else if node0 is not a leaf
+}
+
+void btGImpactBvh::find_collision(btGImpactBvh* boxset0, const btTransform& trans0,
+                                                                 btGImpactBvh* boxset1, const btTransform& trans1,
+                                                                 btPairSet& collision_pairs)
+{
+       if (boxset0->getNodeCount() == 0 || boxset1->getNodeCount() == 0) return;
+
+       BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
+
+       trans_cache_1to0.calc_from_homogenic(trans0, trans1);
+
+#ifdef TRI_COLLISION_PROFILING
+       bt_begin_gim02_tree_time();
+#endif  //TRI_COLLISION_PROFILING
+
+       _find_collision_pairs_recursive(
+               boxset0, boxset1,
+               &collision_pairs, trans_cache_1to0, 0, 0, true);
+#ifdef TRI_COLLISION_PROFILING
+       bt_end_gim02_tree_time();
+#endif  //TRI_COLLISION_PROFILING
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactBvh.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactBvh.h
new file mode 100644 (file)
index 0000000..3cd8fa2
--- /dev/null
@@ -0,0 +1,309 @@
+#ifndef BT_GIMPACT_BVH_H_INCLUDED
+#define BT_GIMPACT_BVH_H_INCLUDED
+
+/*! \file gim_box_set.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "LinearMath/btAlignedObjectArray.h"
+
+#include "btBoxCollision.h"
+#include "btTriangleShapeEx.h"
+#include "btGImpactBvhStructs.h"
+
+//! A pairset array
+class btPairSet : public btAlignedObjectArray<GIM_PAIR>
+{
+public:
+       btPairSet()
+       {
+               reserve(32);
+       }
+       inline void push_pair(int index1, int index2)
+       {
+               push_back(GIM_PAIR(index1, index2));
+       }
+
+       inline void push_pair_inv(int index1, int index2)
+       {
+               push_back(GIM_PAIR(index2, index1));
+       }
+};
+
+class GIM_BVH_DATA_ARRAY : public btAlignedObjectArray<GIM_BVH_DATA>
+{
+};
+
+class GIM_BVH_TREE_NODE_ARRAY : public btAlignedObjectArray<GIM_BVH_TREE_NODE>
+{
+};
+
+//! Basic Box tree structure
+class btBvhTree
+{
+protected:
+       int m_num_nodes;
+       GIM_BVH_TREE_NODE_ARRAY m_node_array;
+
+protected:
+       int _sort_and_calc_splitting_index(
+               GIM_BVH_DATA_ARRAY& primitive_boxes,
+               int startIndex, int endIndex, int splitAxis);
+
+       int _calc_splitting_axis(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
+
+       void _build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
+
+public:
+       btBvhTree()
+       {
+               m_num_nodes = 0;
+       }
+
+       //! prototype functions for box tree management
+       //!@{
+       void build_tree(GIM_BVH_DATA_ARRAY& primitive_boxes);
+
+       SIMD_FORCE_INLINE void clearNodes()
+       {
+               m_node_array.clear();
+               m_num_nodes = 0;
+       }
+
+       //! node count
+       SIMD_FORCE_INLINE int getNodeCount() const
+       {
+               return m_num_nodes;
+       }
+
+       //! tells if the node is a leaf
+       SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+       {
+               return m_node_array[nodeindex].isLeafNode();
+       }
+
+       SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+       {
+               return m_node_array[nodeindex].getDataIndex();
+       }
+
+       SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
+       {
+               bound = m_node_array[nodeindex].m_bound;
+       }
+
+       SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
+       {
+               m_node_array[nodeindex].m_bound = bound;
+       }
+
+       SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+       {
+               return nodeindex + 1;
+       }
+
+       SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+       {
+               if (m_node_array[nodeindex + 1].isLeafNode()) return nodeindex + 2;
+               return nodeindex + 1 + m_node_array[nodeindex + 1].getEscapeIndex();
+       }
+
+       SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+       {
+               return m_node_array[nodeindex].getEscapeIndex();
+       }
+
+       SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE* get_node_pointer(int index = 0) const
+       {
+               return &m_node_array[index];
+       }
+
+       //!@}
+};
+
+//! Prototype Base class for primitive classification
+/*!
+This class is a wrapper for primitive collections.
+This tells relevant info for the Bounding Box set classes, which take care of space classification.
+This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the  Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
+*/
+class btPrimitiveManagerBase
+{
+public:
+       virtual ~btPrimitiveManagerBase() {}
+
+       //! determines if this manager consist on only triangles, which special case will be optimized
+       virtual bool is_trimesh() const = 0;
+       virtual int get_primitive_count() const = 0;
+       virtual void get_primitive_box(int prim_index, btAABB& primbox) const = 0;
+       //! retrieves only the points of the triangle, and the collision margin
+       virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const = 0;
+};
+
+//! Structure for containing Boxes
+/*!
+This class offers an structure for managing a box tree of primitives.
+Requires a Primitive prototype (like btPrimitiveManagerBase )
+*/
+class btGImpactBvh
+{
+protected:
+       btBvhTree m_box_tree;
+       btPrimitiveManagerBase* m_primitive_manager;
+
+protected:
+       //stackless refit
+       void refit();
+
+public:
+       //! this constructor doesn't build the tree. you must call      buildSet
+       btGImpactBvh()
+       {
+               m_primitive_manager = NULL;
+       }
+
+       //! this constructor doesn't build the tree. you must call      buildSet
+       btGImpactBvh(btPrimitiveManagerBase* primitive_manager)
+       {
+               m_primitive_manager = primitive_manager;
+       }
+
+       SIMD_FORCE_INLINE btAABB getGlobalBox() const
+       {
+               btAABB totalbox;
+               getNodeBound(0, totalbox);
+               return totalbox;
+       }
+
+       SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase* primitive_manager)
+       {
+               m_primitive_manager = primitive_manager;
+       }
+
+       SIMD_FORCE_INLINE btPrimitiveManagerBase* getPrimitiveManager() const
+       {
+               return m_primitive_manager;
+       }
+
+       //! node manager prototype functions
+       ///@{
+
+       //! this attemps to refit the box set.
+       SIMD_FORCE_INLINE void update()
+       {
+               refit();
+       }
+
+       //! this rebuild the entire set
+       void buildSet();
+
+       //! returns the indices of the primitives in the m_primitive_manager
+       bool boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const;
+
+       //! returns the indices of the primitives in the m_primitive_manager
+       SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB& box,
+                                                                                const btTransform& transform, btAlignedObjectArray<int>& collided_results) const
+       {
+               btAABB transbox = box;
+               transbox.appy_transform(transform);
+               return boxQuery(transbox, collided_results);
+       }
+
+       //! returns the indices of the primitives in the m_primitive_manager
+       bool rayQuery(
+               const btVector3& ray_dir, const btVector3& ray_origin,
+               btAlignedObjectArray<int>& collided_results) const;
+
+       //! tells if this set has hierarcht
+       SIMD_FORCE_INLINE bool hasHierarchy() const
+       {
+               return true;
+       }
+
+       //! tells if this set is a trimesh
+       SIMD_FORCE_INLINE bool isTrimesh() const
+       {
+               return m_primitive_manager->is_trimesh();
+       }
+
+       //! node count
+       SIMD_FORCE_INLINE int getNodeCount() const
+       {
+               return m_box_tree.getNodeCount();
+       }
+
+       //! tells if the node is a leaf
+       SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+       {
+               return m_box_tree.isLeafNode(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+       {
+               return m_box_tree.getNodeData(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
+       {
+               m_box_tree.getNodeBound(nodeindex, bound);
+       }
+
+       SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
+       {
+               m_box_tree.setNodeBound(nodeindex, bound);
+       }
+
+       SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+       {
+               return m_box_tree.getLeftNode(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+       {
+               return m_box_tree.getRightNode(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+       {
+               return m_box_tree.getEscapeNodeIndex(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex, btPrimitiveTriangle& triangle) const
+       {
+               m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex), triangle);
+       }
+
+       SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE* get_node_pointer(int index = 0) const
+       {
+               return m_box_tree.get_node_pointer(index);
+       }
+
+#ifdef TRI_COLLISION_PROFILING
+       static float getAverageTreeCollisionTime();
+#endif  //TRI_COLLISION_PROFILING
+
+       static void find_collision(btGImpactBvh* boxset1, const btTransform& trans1,
+                                                          btGImpactBvh* boxset2, const btTransform& trans2,
+                                                          btPairSet& collision_pairs);
+};
+
+#endif  // BT_GIMPACT_BVH_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactBvhStructs.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactBvhStructs.h
new file mode 100644 (file)
index 0000000..8f78c23
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef GIM_BOX_SET_STRUCT_H_INCLUDED
+#define GIM_BOX_SET_STRUCT_H_INCLUDED
+
+/*! \file gim_box_set.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "LinearMath/btAlignedObjectArray.h"
+
+#include "btBoxCollision.h"
+#include "btTriangleShapeEx.h"
+#include "gim_pair.h" //for GIM_PAIR
+
+///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box
+struct GIM_BVH_DATA
+{
+       btAABB m_bound;
+       int m_data;
+};
+
+//! Node Structure for trees
+class GIM_BVH_TREE_NODE
+{
+public:
+       btAABB m_bound;
+
+protected:
+       int m_escapeIndexOrDataIndex;
+
+public:
+       GIM_BVH_TREE_NODE()
+       {
+               m_escapeIndexOrDataIndex = 0;
+       }
+
+       SIMD_FORCE_INLINE bool isLeafNode() const
+       {
+               //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+               return (m_escapeIndexOrDataIndex >= 0);
+       }
+
+       SIMD_FORCE_INLINE int getEscapeIndex() const
+       {
+               //btAssert(m_escapeIndexOrDataIndex < 0);
+               return -m_escapeIndexOrDataIndex;
+       }
+
+       SIMD_FORCE_INLINE void setEscapeIndex(int index)
+       {
+               m_escapeIndexOrDataIndex = -index;
+       }
+
+       SIMD_FORCE_INLINE int getDataIndex() const
+       {
+               //btAssert(m_escapeIndexOrDataIndex >= 0);
+
+               return m_escapeIndexOrDataIndex;
+       }
+
+       SIMD_FORCE_INLINE void setDataIndex(int index)
+       {
+               m_escapeIndexOrDataIndex = index;
+       }
+};
+
+#endif  // GIM_BOXPRUNING_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..73e3db1
--- /dev/null
@@ -0,0 +1,866 @@
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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.
+*/
+/*
+Author: Francisco Leon Najera
+Concave-Concave Collision
+
+*/
+
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "btGImpactCollisionAlgorithm.h"
+#include "btContactProcessing.h"
+#include "LinearMath/btQuickprof.h"
+
+//! Class for accessing the plane equation
+class btPlaneShape : public btStaticPlaneShape
+{
+public:
+       btPlaneShape(const btVector3& v, float f)
+               : btStaticPlaneShape(v, f)
+       {
+       }
+
+       void get_plane_equation(btVector4& equation)
+       {
+               equation[0] = m_planeNormal[0];
+               equation[1] = m_planeNormal[1];
+               equation[2] = m_planeNormal[2];
+               equation[3] = m_planeConstant;
+       }
+
+       void get_plane_equation_transformed(const btTransform& trans, btVector4& equation) const
+       {
+               const btVector3 normal = trans.getBasis() * m_planeNormal;
+               equation[0] = normal[0];
+               equation[1] = normal[1];
+               equation[2] = normal[2];
+               equation[3] = normal.dot(trans * (m_planeConstant * m_planeNormal));
+       }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef TRI_COLLISION_PROFILING
+
+btClock g_triangle_clock;
+
+float g_accum_triangle_collision_time = 0;
+int g_count_triangle_collision = 0;
+
+void bt_begin_gim02_tri_time()
+{
+       g_triangle_clock.reset();
+}
+
+void bt_end_gim02_tri_time()
+{
+       g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
+       g_count_triangle_collision++;
+}
+#endif  //TRI_COLLISION_PROFILING
+//! Retrieving shapes shapes
+/*!
+Declared here due of insuficent space on Pool allocators
+*/
+//!@{
+class GIM_ShapeRetriever
+{
+public:
+       const btGImpactShapeInterface* m_gim_shape;
+       btTriangleShapeEx m_trishape;
+       btTetrahedronShapeEx m_tetrashape;
+
+public:
+       class ChildShapeRetriever
+       {
+       public:
+               GIM_ShapeRetriever* m_parent;
+               virtual const btCollisionShape* getChildShape(int index)
+               {
+                       return m_parent->m_gim_shape->getChildShape(index);
+               }
+               virtual ~ChildShapeRetriever() {}
+       };
+
+       class TriangleShapeRetriever : public ChildShapeRetriever
+       {
+       public:
+               virtual btCollisionShape* getChildShape(int index)
+               {
+                       m_parent->m_gim_shape->getBulletTriangle(index, m_parent->m_trishape);
+                       return &m_parent->m_trishape;
+               }
+               virtual ~TriangleShapeRetriever() {}
+       };
+
+       class TetraShapeRetriever : public ChildShapeRetriever
+       {
+       public:
+               virtual btCollisionShape* getChildShape(int index)
+               {
+                       m_parent->m_gim_shape->getBulletTetrahedron(index, m_parent->m_tetrashape);
+                       return &m_parent->m_tetrashape;
+               }
+       };
+
+public:
+       ChildShapeRetriever m_child_retriever;
+       TriangleShapeRetriever m_tri_retriever;
+       TetraShapeRetriever m_tetra_retriever;
+       ChildShapeRetriever* m_current_retriever;
+
+       GIM_ShapeRetriever(const btGImpactShapeInterface* gim_shape)
+       {
+               m_gim_shape = gim_shape;
+               //select retriever
+               if (m_gim_shape->needsRetrieveTriangles())
+               {
+                       m_current_retriever = &m_tri_retriever;
+               }
+               else if (m_gim_shape->needsRetrieveTetrahedrons())
+               {
+                       m_current_retriever = &m_tetra_retriever;
+               }
+               else
+               {
+                       m_current_retriever = &m_child_retriever;
+               }
+
+               m_current_retriever->m_parent = this;
+       }
+
+       const btCollisionShape* getChildShape(int index)
+       {
+               return m_current_retriever->getChildShape(index);
+       }
+};
+
+//!@}
+
+#ifdef TRI_COLLISION_PROFILING
+
+//! Gets the average time in miliseconds of tree collisions
+float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
+{
+       return btGImpactBoxSet::getAverageTreeCollisionTime();
+}
+
+//! Gets the average time in miliseconds of triangle collisions
+float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
+{
+       if (g_count_triangle_collision == 0) return 0;
+
+       float avgtime = g_accum_triangle_collision_time;
+       avgtime /= (float)g_count_triangle_collision;
+
+       g_accum_triangle_collision_time = 0;
+       g_count_triangle_collision = 0;
+
+       return avgtime;
+}
+
+#endif  //TRI_COLLISION_PROFILING
+
+btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+       : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap)
+{
+       m_manifoldPtr = NULL;
+       m_convex_algorithm = NULL;
+}
+
+btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
+{
+       clearCache();
+}
+
+void btGImpactCollisionAlgorithm::addContactPoint(const btCollisionObjectWrapper* body0Wrap,
+                                                                                                 const btCollisionObjectWrapper* body1Wrap,
+                                                                                                 const btVector3& point,
+                                                                                                 const btVector3& normal,
+                                                                                                 btScalar distance)
+{
+       m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
+       m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
+       checkManifold(body0Wrap, body1Wrap);
+       m_resultOut->addContactPoint(normal, point, distance);
+}
+
+void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
+       const btCollisionObjectWrapper* body0Wrap,
+       const btCollisionObjectWrapper* body1Wrap,
+       const btCollisionShape* shape0,
+       const btCollisionShape* shape1)
+{
+       {
+               btCollisionAlgorithm* algor = newAlgorithm(body0Wrap, body1Wrap);
+               // post :       checkManifold is called
+
+               m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
+               m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
+
+               algor->processCollision(body0Wrap, body1Wrap, *m_dispatchInfo, m_resultOut);
+
+               algor->~btCollisionAlgorithm();
+               m_dispatcher->freeCollisionAlgorithm(algor);
+       }
+}
+
+void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
+       const btCollisionObjectWrapper* body0Wrap,
+       const btCollisionObjectWrapper* body1Wrap,
+       const btCollisionShape* shape0,
+       const btCollisionShape* shape1)
+{
+       m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
+       m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
+
+       btCollisionObjectWrapper ob0(body0Wrap, shape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
+       btCollisionObjectWrapper ob1(body1Wrap, shape1, body1Wrap->getCollisionObject(), body1Wrap->getWorldTransform(), m_part1, m_triface1);
+       checkConvexAlgorithm(&ob0, &ob1);
+       m_convex_algorithm->processCollision(&ob0, &ob1, *m_dispatchInfo, m_resultOut);
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
+       const btTransform& trans0,
+       const btTransform& trans1,
+       const btGImpactShapeInterface* shape0,
+       const btGImpactShapeInterface* shape1, btPairSet& pairset)
+{
+       if (shape0->hasBoxSet() && shape1->hasBoxSet())
+       {
+               btGImpactBoxSet::find_collision(shape0->getBoxSet(), trans0, shape1->getBoxSet(), trans1, pairset);
+       }
+       else
+       {
+               btAABB boxshape0;
+               btAABB boxshape1;
+               int i = shape0->getNumChildShapes();
+
+               while (i--)
+               {
+                       shape0->getChildAabb(i, trans0, boxshape0.m_min, boxshape0.m_max);
+
+                       int j = shape1->getNumChildShapes();
+                       while (j--)
+                       {
+                               shape1->getChildAabb(i, trans1, boxshape1.m_min, boxshape1.m_max);
+
+                               if (boxshape1.has_collision(boxshape0))
+                               {
+                                       pairset.push_pair(i, j);
+                               }
+                       }
+               }
+       }
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
+       const btTransform& trans0,
+       const btTransform& trans1,
+       const btGImpactShapeInterface* shape0,
+       const btCollisionShape* shape1,
+       btAlignedObjectArray<int>& collided_primitives)
+{
+       btAABB boxshape;
+
+       if (shape0->hasBoxSet())
+       {
+               btTransform trans1to0 = trans0.inverse();
+               trans1to0 *= trans1;
+
+               shape1->getAabb(trans1to0, boxshape.m_min, boxshape.m_max);
+
+               shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
+       }
+       else
+       {
+               shape1->getAabb(trans1, boxshape.m_min, boxshape.m_max);
+
+               btAABB boxshape0;
+               int i = shape0->getNumChildShapes();
+
+               while (i--)
+               {
+                       shape0->getChildAabb(i, trans0, boxshape0.m_min, boxshape0.m_max);
+
+                       if (boxshape.has_collision(boxshape0))
+                       {
+                               collided_primitives.push_back(i);
+                       }
+               }
+       }
+}
+
+void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
+                                                                                                               const btCollisionObjectWrapper* body1Wrap,
+                                                                                                               const btGImpactMeshShapePart* shape0,
+                                                                                                               const btGImpactMeshShapePart* shape1,
+                                                                                                               const int* pairs, int pair_count)
+{
+       btTriangleShapeEx tri0;
+       btTriangleShapeEx tri1;
+
+       shape0->lockChildShapes();
+       shape1->lockChildShapes();
+
+       const int* pair_pointer = pairs;
+
+       while (pair_count--)
+       {
+               m_triface0 = *(pair_pointer);
+               m_triface1 = *(pair_pointer + 1);
+               pair_pointer += 2;
+
+               shape0->getBulletTriangle(m_triface0, tri0);
+               shape1->getBulletTriangle(m_triface1, tri1);
+
+               //collide two convex shapes
+               if (tri0.overlap_test_conservative(tri1))
+               {
+                       convex_vs_convex_collision(body0Wrap, body1Wrap, &tri0, &tri1);
+               }
+       }
+
+       shape0->unlockChildShapes();
+       shape1->unlockChildShapes();
+}
+
+void btGImpactCollisionAlgorithm::collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
+                                                                                                               const btCollisionObjectWrapper* body1Wrap,
+                                                                                                               const btGImpactMeshShapePart* shape0,
+                                                                                                               const btGImpactMeshShapePart* shape1,
+                                                                                                               const int* pairs, int pair_count)
+{
+       btTransform orgtrans0 = body0Wrap->getWorldTransform();
+       btTransform orgtrans1 = body1Wrap->getWorldTransform();
+
+       btPrimitiveTriangle ptri0;
+       btPrimitiveTriangle ptri1;
+       GIM_TRIANGLE_CONTACT contact_data;
+
+       shape0->lockChildShapes();
+       shape1->lockChildShapes();
+
+       const int* pair_pointer = pairs;
+
+       while (pair_count--)
+       {
+               m_triface0 = *(pair_pointer);
+               m_triface1 = *(pair_pointer + 1);
+               pair_pointer += 2;
+
+               shape0->getPrimitiveTriangle(m_triface0, ptri0);
+               shape1->getPrimitiveTriangle(m_triface1, ptri1);
+
+#ifdef TRI_COLLISION_PROFILING
+               bt_begin_gim02_tri_time();
+#endif
+
+               ptri0.applyTransform(orgtrans0);
+               ptri1.applyTransform(orgtrans1);
+
+               //build planes
+               ptri0.buildTriPlane();
+               ptri1.buildTriPlane();
+               // test conservative
+
+               if (ptri0.overlap_test_conservative(ptri1))
+               {
+                       if (ptri0.find_triangle_collision_clip_method(ptri1, contact_data))
+                       {
+                               int j = contact_data.m_point_count;
+                               while (j--)
+                               {
+                                       addContactPoint(body0Wrap, body1Wrap,
+                                                                       contact_data.m_points[j],
+                                                                       contact_data.m_separating_normal,
+                                                                       -contact_data.m_penetration_depth);
+                               }
+                       }
+               }
+
+#ifdef TRI_COLLISION_PROFILING
+               bt_end_gim02_tri_time();
+#endif
+       }
+
+       shape0->unlockChildShapes();
+       shape1->unlockChildShapes();
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
+       const btCollisionObjectWrapper* body0Wrap,
+       const btCollisionObjectWrapper* body1Wrap,
+       const btGImpactShapeInterface* shape0,
+       const btGImpactShapeInterface* shape1)
+{
+       if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
+       {
+               const btGImpactMeshShape* meshshape0 = static_cast<const btGImpactMeshShape*>(shape0);
+               m_part0 = meshshape0->getMeshPartCount();
+
+               while (m_part0--)
+               {
+                       gimpact_vs_gimpact(body0Wrap, body1Wrap, meshshape0->getMeshPart(m_part0), shape1);
+               }
+
+               return;
+       }
+
+       if (shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
+       {
+               const btGImpactMeshShape* meshshape1 = static_cast<const btGImpactMeshShape*>(shape1);
+               m_part1 = meshshape1->getMeshPartCount();
+
+               while (m_part1--)
+               {
+                       gimpact_vs_gimpact(body0Wrap, body1Wrap, shape0, meshshape1->getMeshPart(m_part1));
+               }
+
+               return;
+       }
+
+       btTransform orgtrans0 = body0Wrap->getWorldTransform();
+       btTransform orgtrans1 = body1Wrap->getWorldTransform();
+
+       btPairSet pairset;
+
+       gimpact_vs_gimpact_find_pairs(orgtrans0, orgtrans1, shape0, shape1, pairset);
+
+       if (pairset.size() == 0) return;
+
+       if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
+               shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
+       {
+               const btGImpactMeshShapePart* shapepart0 = static_cast<const btGImpactMeshShapePart*>(shape0);
+               const btGImpactMeshShapePart* shapepart1 = static_cast<const btGImpactMeshShapePart*>(shape1);
+//specialized function
+#ifdef BULLET_TRIANGLE_COLLISION
+               collide_gjk_triangles(body0Wrap, body1Wrap, shapepart0, shapepart1, &pairset[0].m_index1, pairset.size());
+#else
+               collide_sat_triangles(body0Wrap, body1Wrap, shapepart0, shapepart1, &pairset[0].m_index1, pairset.size());
+#endif
+
+               return;
+       }
+
+       //general function
+
+       shape0->lockChildShapes();
+       shape1->lockChildShapes();
+
+       GIM_ShapeRetriever retriever0(shape0);
+       GIM_ShapeRetriever retriever1(shape1);
+
+       bool child_has_transform0 = shape0->childrenHasTransform();
+       bool child_has_transform1 = shape1->childrenHasTransform();
+
+       int i = pairset.size();
+       while (i--)
+       {
+               GIM_PAIR* pair = &pairset[i];
+               m_triface0 = pair->m_index1;
+               m_triface1 = pair->m_index2;
+               const btCollisionShape* colshape0 = retriever0.getChildShape(m_triface0);
+               const btCollisionShape* colshape1 = retriever1.getChildShape(m_triface1);
+
+               btTransform tr0 = body0Wrap->getWorldTransform();
+               btTransform tr1 = body1Wrap->getWorldTransform();
+
+               if (child_has_transform0)
+               {
+                       tr0 = orgtrans0 * shape0->getChildTransform(m_triface0);
+               }
+
+               if (child_has_transform1)
+               {
+                       tr1 = orgtrans1 * shape1->getChildTransform(m_triface1);
+               }
+
+               btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), tr0, m_part0, m_triface0);
+               btCollisionObjectWrapper ob1(body1Wrap, colshape1, body1Wrap->getCollisionObject(), tr1, m_part1, m_triface1);
+
+               //collide two convex shapes
+               convex_vs_convex_collision(&ob0, &ob1, colshape0, colshape1);
+       }
+
+       shape0->unlockChildShapes();
+       shape1->unlockChildShapes();
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
+                                                                                                  const btCollisionObjectWrapper* body1Wrap,
+                                                                                                  const btGImpactShapeInterface* shape0,
+                                                                                                  const btCollisionShape* shape1, bool swapped)
+{
+       if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
+       {
+               const btGImpactMeshShape* meshshape0 = static_cast<const btGImpactMeshShape*>(shape0);
+               int& part = swapped ? m_part1 : m_part0;
+               part = meshshape0->getMeshPartCount();
+
+               while (part--)
+               {
+                       gimpact_vs_shape(body0Wrap,
+                                                        body1Wrap,
+                                                        meshshape0->getMeshPart(part),
+                                                        shape1, swapped);
+               }
+
+               return;
+       }
+
+#ifdef GIMPACT_VS_PLANE_COLLISION
+       if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
+               shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
+       {
+               const btGImpactMeshShapePart* shapepart = static_cast<const btGImpactMeshShapePart*>(shape0);
+               const btStaticPlaneShape* planeshape = static_cast<const btStaticPlaneShape*>(shape1);
+               gimpacttrimeshpart_vs_plane_collision(body0Wrap, body1Wrap, shapepart, planeshape, swapped);
+               return;
+       }
+
+#endif
+
+       if (shape1->isCompound())
+       {
+               const btCompoundShape* compoundshape = static_cast<const btCompoundShape*>(shape1);
+               gimpact_vs_compoundshape(body0Wrap, body1Wrap, shape0, compoundshape, swapped);
+               return;
+       }
+       else if (shape1->isConcave())
+       {
+               const btConcaveShape* concaveshape = static_cast<const btConcaveShape*>(shape1);
+               gimpact_vs_concave(body0Wrap, body1Wrap, shape0, concaveshape, swapped);
+               return;
+       }
+
+       btTransform orgtrans0 = body0Wrap->getWorldTransform();
+
+       btTransform orgtrans1 = body1Wrap->getWorldTransform();
+
+       btAlignedObjectArray<int> collided_results;
+
+       gimpact_vs_shape_find_pairs(orgtrans0, orgtrans1, shape0, shape1, collided_results);
+
+       if (collided_results.size() == 0) return;
+
+       shape0->lockChildShapes();
+
+       GIM_ShapeRetriever retriever0(shape0);
+
+       bool child_has_transform0 = shape0->childrenHasTransform();
+
+       int i = collided_results.size();
+
+       while (i--)
+       {
+               int child_index = collided_results[i];
+               if (swapped)
+                       m_triface1 = child_index;
+               else
+                       m_triface0 = child_index;
+
+               const btCollisionShape* colshape0 = retriever0.getChildShape(child_index);
+
+               btTransform tr0 = body0Wrap->getWorldTransform();
+
+               if (child_has_transform0)
+               {
+                       tr0 = orgtrans0 * shape0->getChildTransform(child_index);
+               }
+
+               btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
+               const btCollisionObjectWrapper* prevObj;
+
+               if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
+               {
+                       prevObj = m_resultOut->getBody0Wrap();
+                       m_resultOut->setBody0Wrap(&ob0);
+               }
+               else
+               {
+                       prevObj = m_resultOut->getBody1Wrap();
+                       m_resultOut->setBody1Wrap(&ob0);
+               }
+
+               //collide two shapes
+               if (swapped)
+               {
+                       shape_vs_shape_collision(body1Wrap, &ob0, shape1, colshape0);
+               }
+               else
+               {
+                       shape_vs_shape_collision(&ob0, body1Wrap, colshape0, shape1);
+               }
+
+               if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
+               {
+                       m_resultOut->setBody0Wrap(prevObj);
+               }
+               else
+               {
+                       m_resultOut->setBody1Wrap(prevObj);
+               }
+       }
+
+       shape0->unlockChildShapes();
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
+                                                                                                                  const btCollisionObjectWrapper* body1Wrap,
+                                                                                                                  const btGImpactShapeInterface* shape0,
+                                                                                                                  const btCompoundShape* shape1, bool swapped)
+{
+       btTransform orgtrans1 = body1Wrap->getWorldTransform();
+
+       int i = shape1->getNumChildShapes();
+       while (i--)
+       {
+               const btCollisionShape* colshape1 = shape1->getChildShape(i);
+               btTransform childtrans1 = orgtrans1 * shape1->getChildTransform(i);
+
+               btCollisionObjectWrapper ob1(body1Wrap, colshape1, body1Wrap->getCollisionObject(), childtrans1, -1, i);
+
+               const btCollisionObjectWrapper* tmp = 0;
+               if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob1.getCollisionObject())
+               {
+                       tmp = m_resultOut->getBody0Wrap();
+                       m_resultOut->setBody0Wrap(&ob1);
+               }
+               else
+               {
+                       tmp = m_resultOut->getBody1Wrap();
+                       m_resultOut->setBody1Wrap(&ob1);
+               }
+               //collide child shape
+               gimpact_vs_shape(body0Wrap, &ob1,
+                                                shape0, colshape1, swapped);
+
+               if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob1.getCollisionObject())
+               {
+                       m_resultOut->setBody0Wrap(tmp);
+               }
+               else
+               {
+                       m_resultOut->setBody1Wrap(tmp);
+               }
+       }
+}
+
+void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
+       const btCollisionObjectWrapper* body0Wrap,
+       const btCollisionObjectWrapper* body1Wrap,
+       const btGImpactMeshShapePart* shape0,
+       const btStaticPlaneShape* shape1, bool swapped)
+{
+       btTransform orgtrans0 = body0Wrap->getWorldTransform();
+       btTransform orgtrans1 = body1Wrap->getWorldTransform();
+
+       const btPlaneShape* planeshape = static_cast<const btPlaneShape*>(shape1);
+       btVector4 plane;
+       planeshape->get_plane_equation_transformed(orgtrans1, plane);
+
+       //test box against plane
+
+       btAABB tribox;
+       shape0->getAabb(orgtrans0, tribox.m_min, tribox.m_max);
+       tribox.increment_margin(planeshape->getMargin());
+
+       if (tribox.plane_classify(plane) != BT_CONST_COLLIDE_PLANE) return;
+
+       shape0->lockChildShapes();
+
+       btScalar margin = shape0->getMargin() + planeshape->getMargin();
+
+       btVector3 vertex;
+       int vi = shape0->getVertexCount();
+       while (vi--)
+       {
+               shape0->getVertex(vi, vertex);
+               vertex = orgtrans0(vertex);
+
+               btScalar distance = vertex.dot(plane) - plane[3] - margin;
+
+               if (distance < 0.0)  //add contact
+               {
+                       if (swapped)
+                       {
+                               addContactPoint(body1Wrap, body0Wrap,
+                                                               vertex,
+                                                               -plane,
+                                                               distance);
+                       }
+                       else
+                       {
+                               addContactPoint(body0Wrap, body1Wrap,
+                                                               vertex,
+                                                               plane,
+                                                               distance);
+                       }
+               }
+       }
+
+       shape0->unlockChildShapes();
+}
+
+class btGImpactTriangleCallback : public btTriangleCallback
+{
+public:
+       btGImpactCollisionAlgorithm* algorithm;
+       const btCollisionObjectWrapper* body0Wrap;
+       const btCollisionObjectWrapper* body1Wrap;
+       const btGImpactShapeInterface* gimpactshape0;
+       bool swapped;
+       btScalar margin;
+
+       virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+       {
+               btTriangleShapeEx tri1(triangle[0], triangle[1], triangle[2]);
+               tri1.setMargin(margin);
+               if (swapped)
+               {
+                       algorithm->setPart0(partId);
+                       algorithm->setFace0(triangleIndex);
+               }
+               else
+               {
+                       algorithm->setPart1(partId);
+                       algorithm->setFace1(triangleIndex);
+               }
+
+               btCollisionObjectWrapper ob1Wrap(body1Wrap, &tri1, body1Wrap->getCollisionObject(), body1Wrap->getWorldTransform(), partId, triangleIndex);
+               const btCollisionObjectWrapper* tmp = 0;
+
+               if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject() == ob1Wrap.getCollisionObject())
+               {
+                       tmp = algorithm->internalGetResultOut()->getBody0Wrap();
+                       algorithm->internalGetResultOut()->setBody0Wrap(&ob1Wrap);
+               }
+               else
+               {
+                       tmp = algorithm->internalGetResultOut()->getBody1Wrap();
+                       algorithm->internalGetResultOut()->setBody1Wrap(&ob1Wrap);
+               }
+
+               algorithm->gimpact_vs_shape(
+                       body0Wrap, &ob1Wrap, gimpactshape0, &tri1, swapped);
+
+               if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject() == ob1Wrap.getCollisionObject())
+               {
+                       algorithm->internalGetResultOut()->setBody0Wrap(tmp);
+               }
+               else
+               {
+                       algorithm->internalGetResultOut()->setBody1Wrap(tmp);
+               }
+       }
+};
+
+void btGImpactCollisionAlgorithm::gimpact_vs_concave(
+       const btCollisionObjectWrapper* body0Wrap,
+       const btCollisionObjectWrapper* body1Wrap,
+       const btGImpactShapeInterface* shape0,
+       const btConcaveShape* shape1, bool swapped)
+{
+       //create the callback
+       btGImpactTriangleCallback tricallback;
+       tricallback.algorithm = this;
+       tricallback.body0Wrap = body0Wrap;
+       tricallback.body1Wrap = body1Wrap;
+       tricallback.gimpactshape0 = shape0;
+       tricallback.swapped = swapped;
+       tricallback.margin = shape1->getMargin();
+
+       //getting the trimesh AABB
+       btTransform gimpactInConcaveSpace;
+
+       gimpactInConcaveSpace = body1Wrap->getWorldTransform().inverse() * body0Wrap->getWorldTransform();
+
+       btVector3 minAABB, maxAABB;
+       shape0->getAabb(gimpactInConcaveSpace, minAABB, maxAABB);
+
+       shape1->processAllTriangles(&tricallback, minAABB, maxAABB);
+}
+
+void btGImpactCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       clearCache();
+
+       m_resultOut = resultOut;
+       m_dispatchInfo = &dispatchInfo;
+       const btGImpactShapeInterface* gimpactshape0;
+       const btGImpactShapeInterface* gimpactshape1;
+
+       if (body0Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
+       {
+               gimpactshape0 = static_cast<const btGImpactShapeInterface*>(body0Wrap->getCollisionShape());
+
+               if (body1Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
+               {
+                       gimpactshape1 = static_cast<const btGImpactShapeInterface*>(body1Wrap->getCollisionShape());
+
+                       gimpact_vs_gimpact(body0Wrap, body1Wrap, gimpactshape0, gimpactshape1);
+               }
+               else
+               {
+                       gimpact_vs_shape(body0Wrap, body1Wrap, gimpactshape0, body1Wrap->getCollisionShape(), false);
+               }
+       }
+       else if (body1Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
+       {
+               gimpactshape1 = static_cast<const btGImpactShapeInterface*>(body1Wrap->getCollisionShape());
+
+               gimpact_vs_shape(body1Wrap, body0Wrap, gimpactshape1, body0Wrap->getCollisionShape(), true);
+       }
+
+       // Ensure that gContactProcessedCallback is called for concave shapes.
+       if (getLastManifold())
+       {
+               m_resultOut->refreshContactPoints();
+       }
+}
+
+btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       return 1.f;
+}
+
+///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
+
+//! Use this function for register the algorithm externally
+void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher* dispatcher)
+{
+       static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf;
+
+       int i;
+
+       for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
+       {
+               dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE, i, &s_gimpact_cf);
+       }
+
+       for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
+       {
+               dispatcher->registerCollisionCreateFunc(i, GIMPACT_SHAPE_PROXYTYPE, &s_gimpact_cf);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..a368c8a
--- /dev/null
@@ -0,0 +1,288 @@
+/*! \file btGImpactShape.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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.
+*/
+
+#ifndef BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
+#define BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+#include "btGImpactShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+//! Collision Algorithm for GImpact Shapes
+/*!
+For register this algorithm in Bullet, proceed as following:
+ \code
+btCollisionDispatcher * dispatcher = static_cast<btCollisionDispatcher *>(m_dynamicsWorld ->getDispatcher());
+btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
+ \endcode
+*/
+class btGImpactCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+protected:
+       btCollisionAlgorithm* m_convex_algorithm;
+       btPersistentManifold* m_manifoldPtr;
+       btManifoldResult* m_resultOut;
+       const btDispatcherInfo* m_dispatchInfo;
+       int m_triface0;
+       int m_part0;
+       int m_triface1;
+       int m_part1;
+
+       //! Creates a new contact point
+       SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(const btCollisionObject* body0, const btCollisionObject* body1)
+       {
+               m_manifoldPtr = m_dispatcher->getNewManifold(body0, body1);
+               return m_manifoldPtr;
+       }
+
+       SIMD_FORCE_INLINE void destroyConvexAlgorithm()
+       {
+               if (m_convex_algorithm)
+               {
+                       m_convex_algorithm->~btCollisionAlgorithm();
+                       m_dispatcher->freeCollisionAlgorithm(m_convex_algorithm);
+                       m_convex_algorithm = NULL;
+               }
+       }
+
+       SIMD_FORCE_INLINE void destroyContactManifolds()
+       {
+               if (m_manifoldPtr == NULL) return;
+               m_dispatcher->releaseManifold(m_manifoldPtr);
+               m_manifoldPtr = NULL;
+       }
+
+       SIMD_FORCE_INLINE void clearCache()
+       {
+               destroyContactManifolds();
+               destroyConvexAlgorithm();
+
+               m_triface0 = -1;
+               m_part0 = -1;
+               m_triface1 = -1;
+               m_part1 = -1;
+       }
+
+       SIMD_FORCE_INLINE btPersistentManifold* getLastManifold()
+       {
+               return m_manifoldPtr;
+       }
+
+       // Call before process collision
+       SIMD_FORCE_INLINE void checkManifold(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+       {
+               if (getLastManifold() == 0)
+               {
+                       newContactManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
+               }
+
+               m_resultOut->setPersistentManifold(getLastManifold());
+       }
+
+       // Call before process collision
+       SIMD_FORCE_INLINE btCollisionAlgorithm* newAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+       {
+               checkManifold(body0Wrap, body1Wrap);
+
+               btCollisionAlgorithm* convex_algorithm = m_dispatcher->findAlgorithm(
+                       body0Wrap, body1Wrap, getLastManifold(), BT_CONTACT_POINT_ALGORITHMS);
+               return convex_algorithm;
+       }
+
+       // Call before process collision
+       SIMD_FORCE_INLINE void checkConvexAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+       {
+               if (m_convex_algorithm) return;
+               m_convex_algorithm = newAlgorithm(body0Wrap, body1Wrap);
+       }
+
+       void addContactPoint(const btCollisionObjectWrapper* body0Wrap,
+                                                const btCollisionObjectWrapper* body1Wrap,
+                                                const btVector3& point,
+                                                const btVector3& normal,
+                                                btScalar distance);
+
+       //! Collision routines
+       //!@{
+
+       void collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
+                                                          const btCollisionObjectWrapper* body1Wrap,
+                                                          const btGImpactMeshShapePart* shape0,
+                                                          const btGImpactMeshShapePart* shape1,
+                                                          const int* pairs, int pair_count);
+
+       void collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
+                                                          const btCollisionObjectWrapper* body1Wrap,
+                                                          const btGImpactMeshShapePart* shape0,
+                                                          const btGImpactMeshShapePart* shape1,
+                                                          const int* pairs, int pair_count);
+
+       void shape_vs_shape_collision(
+               const btCollisionObjectWrapper* body0,
+               const btCollisionObjectWrapper* body1,
+               const btCollisionShape* shape0,
+               const btCollisionShape* shape1);
+
+       void convex_vs_convex_collision(const btCollisionObjectWrapper* body0Wrap,
+                                                                       const btCollisionObjectWrapper* body1Wrap,
+                                                                       const btCollisionShape* shape0,
+                                                                       const btCollisionShape* shape1);
+
+       void gimpact_vs_gimpact_find_pairs(
+               const btTransform& trans0,
+               const btTransform& trans1,
+               const btGImpactShapeInterface* shape0,
+               const btGImpactShapeInterface* shape1, btPairSet& pairset);
+
+       void gimpact_vs_shape_find_pairs(
+               const btTransform& trans0,
+               const btTransform& trans1,
+               const btGImpactShapeInterface* shape0,
+               const btCollisionShape* shape1,
+               btAlignedObjectArray<int>& collided_primitives);
+
+       void gimpacttrimeshpart_vs_plane_collision(
+               const btCollisionObjectWrapper* body0Wrap,
+               const btCollisionObjectWrapper* body1Wrap,
+               const btGImpactMeshShapePart* shape0,
+               const btStaticPlaneShape* shape1, bool swapped);
+
+public:
+       btGImpactCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
+
+       virtual ~btGImpactCollisionAlgorithm();
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
+
+       virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+       {
+               if (m_manifoldPtr)
+                       manifoldArray.push_back(m_manifoldPtr);
+       }
+
+       btManifoldResult* internalGetResultOut()
+       {
+               return m_resultOut;
+       }
+
+       struct CreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm));
+                       return new (mem) btGImpactCollisionAlgorithm(ci, body0Wrap, body1Wrap);
+               }
+       };
+
+       //! Use this function for register the algorithm externally
+       static void registerAlgorithm(btCollisionDispatcher* dispatcher);
+#ifdef TRI_COLLISION_PROFILING
+       //! Gets the average time in miliseconds of tree collisions
+       static float getAverageTreeCollisionTime();
+
+       //! Gets the average time in miliseconds of triangle collisions
+       static float getAverageTriangleCollisionTime();
+#endif  //TRI_COLLISION_PROFILING
+
+       //! Collides two gimpact shapes
+       /*!
+       \pre shape0 and shape1 couldn't be btGImpactMeshShape objects
+       */
+
+       void gimpact_vs_gimpact(const btCollisionObjectWrapper* body0Wrap,
+                                                       const btCollisionObjectWrapper* body1Wrap,
+                                                       const btGImpactShapeInterface* shape0,
+                                                       const btGImpactShapeInterface* shape1);
+
+       void gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
+                                                 const btCollisionObjectWrapper* body1Wrap,
+                                                 const btGImpactShapeInterface* shape0,
+                                                 const btCollisionShape* shape1, bool swapped);
+
+       void gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
+                                                                 const btCollisionObjectWrapper* body1Wrap,
+                                                                 const btGImpactShapeInterface* shape0,
+                                                                 const btCompoundShape* shape1, bool swapped);
+
+       void gimpact_vs_concave(
+               const btCollisionObjectWrapper* body0Wrap,
+               const btCollisionObjectWrapper* body1Wrap,
+               const btGImpactShapeInterface* shape0,
+               const btConcaveShape* shape1, bool swapped);
+
+       /// Accessor/Mutator pairs for Part and triangleID
+       void setFace0(int value)
+       {
+               m_triface0 = value;
+       }
+       int getFace0()
+       {
+               return m_triface0;
+       }
+       void setFace1(int value)
+       {
+               m_triface1 = value;
+       }
+       int getFace1()
+       {
+               return m_triface1;
+       }
+       void setPart0(int value)
+       {
+               m_part0 = value;
+       }
+       int getPart0()
+       {
+               return m_part0;
+       }
+       void setPart1(int value)
+       {
+               m_part1 = value;
+       }
+       int getPart1()
+       {
+               return m_part1;
+       }
+};
+
+//algorithm details
+//#define BULLET_TRIANGLE_COLLISION 1
+#define GIMPACT_VS_PLANE_COLLISION 1
+
+#endif  //BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactMassUtil.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactMassUtil.h
new file mode 100644 (file)
index 0000000..1cde46e
--- /dev/null
@@ -0,0 +1,56 @@
+/*! \file btGImpactMassUtil.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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.
+*/
+
+#ifndef GIMPACT_MASS_UTIL_H
+#define GIMPACT_MASS_UTIL_H
+
+#include "LinearMath/btTransform.h"
+
+SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed(
+       const btVector3& source_inertia, const btVector3& added_inertia, const btTransform& transform)
+{
+       btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose();
+
+       btScalar x2 = transform.getOrigin()[0];
+       x2 *= x2;
+       btScalar y2 = transform.getOrigin()[1];
+       y2 *= y2;
+       btScalar z2 = transform.getOrigin()[2];
+       z2 *= z2;
+
+       btScalar ix = rotatedTensor[0][0] * (y2 + z2);
+       btScalar iy = rotatedTensor[1][1] * (x2 + z2);
+       btScalar iz = rotatedTensor[2][2] * (x2 + y2);
+
+       return btVector3(source_inertia[0] + ix, source_inertia[1] + iy, source_inertia[2] + iz);
+}
+
+SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3& point, btScalar mass)
+{
+       btScalar x2 = point[0] * point[0];
+       btScalar y2 = point[1] * point[1];
+       btScalar z2 = point[2] * point[2];
+       return btVector3(mass * (y2 + z2), mass * (x2 + z2), mass * (x2 + y2));
+}
+
+#endif  //GIMPACT_MESH_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
new file mode 100644 (file)
index 0000000..b81fc97
--- /dev/null
@@ -0,0 +1,486 @@
+/*! \file gim_box_set.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "btGImpactQuantizedBvh.h"
+#include "LinearMath/btQuickprof.h"
+
+#ifdef TRI_COLLISION_PROFILING
+btClock g_q_tree_clock;
+
+float g_q_accum_tree_collision_time = 0;
+int g_q_count_traversing = 0;
+
+void bt_begin_gim02_q_tree_time()
+{
+       g_q_tree_clock.reset();
+}
+
+void bt_end_gim02_q_tree_time()
+{
+       g_q_accum_tree_collision_time += g_q_tree_clock.getTimeMicroseconds();
+       g_q_count_traversing++;
+}
+
+//! Gets the average time in miliseconds of tree collisions
+float btGImpactQuantizedBvh::getAverageTreeCollisionTime()
+{
+       if (g_q_count_traversing == 0) return 0;
+
+       float avgtime = g_q_accum_tree_collision_time;
+       avgtime /= (float)g_q_count_traversing;
+
+       g_q_accum_tree_collision_time = 0;
+       g_q_count_traversing = 0;
+       return avgtime;
+
+       //      float avgtime = g_q_count_traversing;
+       //      g_q_count_traversing = 0;
+       //      return avgtime;
+}
+
+#endif  //TRI_COLLISION_PROFILING
+
+/////////////////////// btQuantizedBvhTree /////////////////////////////////
+
+void btQuantizedBvhTree::calc_quantization(
+       GIM_BVH_DATA_ARRAY& primitive_boxes, btScalar boundMargin)
+{
+       //calc globa box
+       btAABB global_bound;
+       global_bound.invalidate();
+
+       for (int i = 0; i < primitive_boxes.size(); i++)
+       {
+               global_bound.merge(primitive_boxes[i].m_bound);
+       }
+
+       bt_calc_quantization_parameters(
+               m_global_bound.m_min, m_global_bound.m_max, m_bvhQuantization, global_bound.m_min, global_bound.m_max, boundMargin);
+}
+
+int btQuantizedBvhTree::_calc_splitting_axis(
+       GIM_BVH_DATA_ARRAY& primitive_boxes, 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) * (primitive_boxes[i].m_bound.m_max +
+                                                                                       primitive_boxes[i].m_bound.m_min);
+               means += center;
+       }
+       means *= (btScalar(1.) / (btScalar)numIndices);
+
+       for (i = startIndex; i < endIndex; i++)
+       {
+               btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+                                                                                       primitive_boxes[i].m_bound.m_min);
+               btVector3 diff2 = center - means;
+               diff2 = diff2 * diff2;
+               variance += diff2;
+       }
+       variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
+
+       return variance.maxAxis();
+}
+
+int btQuantizedBvhTree::_sort_and_calc_splitting_index(
+       GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex,
+       int endIndex, int splitAxis)
+{
+       int i;
+       int splitIndex = startIndex;
+       int numIndices = endIndex - startIndex;
+
+       // average of centers
+       btScalar splitValue = 0.0f;
+
+       btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
+       for (i = startIndex; i < endIndex; i++)
+       {
+               btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+                                                                                       primitive_boxes[i].m_bound.m_min);
+               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) * (primitive_boxes[i].m_bound.m_max +
+                                                                                       primitive_boxes[i].m_bound.m_min);
+               if (center[splitAxis] > splitValue)
+               {
+                       //swap
+                       primitive_boxes.swap(i, splitIndex);
+                       //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);
+       }
+
+       btAssert(!((splitIndex == startIndex) || (splitIndex == (endIndex))));
+
+       return splitIndex;
+}
+
+void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex)
+{
+       int curIndex = m_num_nodes;
+       m_num_nodes++;
+
+       btAssert((endIndex - startIndex) > 0);
+
+       if ((endIndex - startIndex) == 1)
+       {
+               //We have a leaf node
+               setNodeBound(curIndex, primitive_boxes[startIndex].m_bound);
+               m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
+
+               return;
+       }
+       //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+       //split axis
+       int splitIndex = _calc_splitting_axis(primitive_boxes, startIndex, endIndex);
+
+       splitIndex = _sort_and_calc_splitting_index(
+               primitive_boxes, startIndex, endIndex,
+               splitIndex  //split axis
+       );
+
+       //calc this node bounding box
+
+       btAABB node_bound;
+       node_bound.invalidate();
+
+       for (int i = startIndex; i < endIndex; i++)
+       {
+               node_bound.merge(primitive_boxes[i].m_bound);
+       }
+
+       setNodeBound(curIndex, node_bound);
+
+       //build left branch
+       _build_sub_tree(primitive_boxes, startIndex, splitIndex);
+
+       //build right branch
+       _build_sub_tree(primitive_boxes, splitIndex, endIndex);
+
+       m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
+}
+
+//! stackless build tree
+void btQuantizedBvhTree::build_tree(
+       GIM_BVH_DATA_ARRAY& primitive_boxes)
+{
+       calc_quantization(primitive_boxes);
+       // initialize node count to 0
+       m_num_nodes = 0;
+       // allocate nodes
+       m_node_array.resize(primitive_boxes.size() * 2);
+
+       _build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
+}
+
+////////////////////////////////////class btGImpactQuantizedBvh
+
+void btGImpactQuantizedBvh::refit()
+{
+       int nodecount = getNodeCount();
+       while (nodecount--)
+       {
+               if (isLeafNode(nodecount))
+               {
+                       btAABB leafbox;
+                       m_primitive_manager->get_primitive_box(getNodeData(nodecount), leafbox);
+                       setNodeBound(nodecount, leafbox);
+               }
+               else
+               {
+                       //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
+                       //get left bound
+                       btAABB bound;
+                       bound.invalidate();
+
+                       btAABB temp_box;
+
+                       int child_node = getLeftNode(nodecount);
+                       if (child_node)
+                       {
+                               getNodeBound(child_node, temp_box);
+                               bound.merge(temp_box);
+                       }
+
+                       child_node = getRightNode(nodecount);
+                       if (child_node)
+                       {
+                               getNodeBound(child_node, temp_box);
+                               bound.merge(temp_box);
+                       }
+
+                       setNodeBound(nodecount, bound);
+               }
+       }
+}
+
+//! this rebuild the entire set
+void btGImpactQuantizedBvh::buildSet()
+{
+       //obtain primitive boxes
+       GIM_BVH_DATA_ARRAY primitive_boxes;
+       primitive_boxes.resize(m_primitive_manager->get_primitive_count());
+
+       for (int i = 0; i < primitive_boxes.size(); i++)
+       {
+               m_primitive_manager->get_primitive_box(i, primitive_boxes[i].m_bound);
+               primitive_boxes[i].m_data = i;
+       }
+
+       m_box_tree.build_tree(primitive_boxes);
+}
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactQuantizedBvh::boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const
+{
+       int curIndex = 0;
+       int numNodes = getNodeCount();
+
+       //quantize box
+
+       unsigned short quantizedMin[3];
+       unsigned short quantizedMax[3];
+
+       m_box_tree.quantizePoint(quantizedMin, box.m_min);
+       m_box_tree.quantizePoint(quantizedMax, box.m_max);
+
+       while (curIndex < numNodes)
+       {
+               //catch bugs in tree data
+
+               bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin, quantizedMax);
+               bool isleafnode = isLeafNode(curIndex);
+
+               if (isleafnode && aabbOverlap)
+               {
+                       collided_results.push_back(getNodeData(curIndex));
+               }
+
+               if (aabbOverlap || isleafnode)
+               {
+                       //next subnode
+                       curIndex++;
+               }
+               else
+               {
+                       //skip node
+                       curIndex += getEscapeNodeIndex(curIndex);
+               }
+       }
+       if (collided_results.size() > 0) return true;
+       return false;
+}
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactQuantizedBvh::rayQuery(
+       const btVector3& ray_dir, const btVector3& ray_origin,
+       btAlignedObjectArray<int>& collided_results) const
+{
+       int curIndex = 0;
+       int numNodes = getNodeCount();
+
+       while (curIndex < numNodes)
+       {
+               btAABB bound;
+               getNodeBound(curIndex, bound);
+
+               //catch bugs in tree data
+
+               bool aabbOverlap = bound.collide_ray(ray_origin, ray_dir);
+               bool isleafnode = isLeafNode(curIndex);
+
+               if (isleafnode && aabbOverlap)
+               {
+                       collided_results.push_back(getNodeData(curIndex));
+               }
+
+               if (aabbOverlap || isleafnode)
+               {
+                       //next subnode
+                       curIndex++;
+               }
+               else
+               {
+                       //skip node
+                       curIndex += getEscapeNodeIndex(curIndex);
+               }
+       }
+       if (collided_results.size() > 0) return true;
+       return false;
+}
+
+SIMD_FORCE_INLINE bool _quantized_node_collision(
+       const btGImpactQuantizedBvh* boxset0, const btGImpactQuantizedBvh* boxset1,
+       const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
+       int node0, int node1, bool complete_primitive_tests)
+{
+       btAABB box0;
+       boxset0->getNodeBound(node0, box0);
+       btAABB box1;
+       boxset1->getNodeBound(node1, box1);
+
+       return box0.overlapping_trans_cache(box1, trans_cache_1to0, complete_primitive_tests);
+       //      box1.appy_transform_trans_cache(trans_cache_1to0);
+       //      return box0.has_collision(box1);
+}
+
+//stackless recursive collision routine
+static void _find_quantized_collision_pairs_recursive(
+       const btGImpactQuantizedBvh* boxset0, const btGImpactQuantizedBvh* boxset1,
+       btPairSet* collision_pairs,
+       const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
+       int node0, int node1, bool complete_primitive_tests)
+{
+       if (_quantized_node_collision(
+                       boxset0, boxset1, trans_cache_1to0,
+                       node0, node1, complete_primitive_tests) == false) return;  //avoid colliding internal nodes
+
+       if (boxset0->isLeafNode(node0))
+       {
+               if (boxset1->isLeafNode(node1))
+               {
+                       // collision result
+                       collision_pairs->push_pair(
+                               boxset0->getNodeData(node0), boxset1->getNodeData(node1));
+                       return;
+               }
+               else
+               {
+                       //collide left recursive
+
+                       _find_quantized_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               node0, boxset1->getLeftNode(node1), false);
+
+                       //collide right recursive
+                       _find_quantized_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               node0, boxset1->getRightNode(node1), false);
+               }
+       }
+       else
+       {
+               if (boxset1->isLeafNode(node1))
+               {
+                       //collide left recursive
+                       _find_quantized_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getLeftNode(node0), node1, false);
+
+                       //collide right recursive
+
+                       _find_quantized_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getRightNode(node0), node1, false);
+               }
+               else
+               {
+                       //collide left0 left1
+
+                       _find_quantized_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getLeftNode(node0), boxset1->getLeftNode(node1), false);
+
+                       //collide left0 right1
+
+                       _find_quantized_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getLeftNode(node0), boxset1->getRightNode(node1), false);
+
+                       //collide right0 left1
+
+                       _find_quantized_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getRightNode(node0), boxset1->getLeftNode(node1), false);
+
+                       //collide right0 right1
+
+                       _find_quantized_collision_pairs_recursive(
+                               boxset0, boxset1,
+                               collision_pairs, trans_cache_1to0,
+                               boxset0->getRightNode(node0), boxset1->getRightNode(node1), false);
+
+               }  // else if node1 is not a leaf
+       }      // else if node0 is not a leaf
+}
+
+void btGImpactQuantizedBvh::find_collision(const btGImpactQuantizedBvh* boxset0, const btTransform& trans0,
+                                                                                  const btGImpactQuantizedBvh* boxset1, const btTransform& trans1,
+                                                                                  btPairSet& collision_pairs)
+{
+       if (boxset0->getNodeCount() == 0 || boxset1->getNodeCount() == 0) return;
+
+       BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
+
+       trans_cache_1to0.calc_from_homogenic(trans0, trans1);
+
+#ifdef TRI_COLLISION_PROFILING
+       bt_begin_gim02_q_tree_time();
+#endif  //TRI_COLLISION_PROFILING
+
+       _find_quantized_collision_pairs_recursive(
+               boxset0, boxset1,
+               &collision_pairs, trans_cache_1to0, 0, 0, true);
+#ifdef TRI_COLLISION_PROFILING
+       bt_end_gim02_q_tree_time();
+#endif  //TRI_COLLISION_PROFILING
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
new file mode 100644 (file)
index 0000000..b231c1e
--- /dev/null
@@ -0,0 +1,298 @@
+#ifndef GIM_QUANTIZED_SET_H_INCLUDED
+#define GIM_QUANTIZED_SET_H_INCLUDED
+
+/*! \file btGImpactQuantizedBvh.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "btGImpactBvh.h"
+#include "btQuantization.h"
+#include "btGImpactQuantizedBvhStructs.h"
+
+class GIM_QUANTIZED_BVH_NODE_ARRAY : public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE>
+{
+};
+
+//! Basic Box tree structure
+class btQuantizedBvhTree
+{
+protected:
+       int m_num_nodes;
+       GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array;
+       btAABB m_global_bound;
+       btVector3 m_bvhQuantization;
+
+protected:
+       void calc_quantization(GIM_BVH_DATA_ARRAY& primitive_boxes, btScalar boundMargin = btScalar(1.0));
+
+       int _sort_and_calc_splitting_index(
+               GIM_BVH_DATA_ARRAY& primitive_boxes,
+               int startIndex, int endIndex, int splitAxis);
+
+       int _calc_splitting_axis(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
+
+       void _build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
+
+public:
+       btQuantizedBvhTree()
+       {
+               m_num_nodes = 0;
+       }
+
+       //! prototype functions for box tree management
+       //!@{
+       void build_tree(GIM_BVH_DATA_ARRAY& primitive_boxes);
+
+       SIMD_FORCE_INLINE void quantizePoint(
+               unsigned short* quantizedpoint, const btVector3& point) const
+       {
+               bt_quantize_clamp(quantizedpoint, point, m_global_bound.m_min, m_global_bound.m_max, m_bvhQuantization);
+       }
+
+       SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
+               int node_index,
+               unsigned short* quantizedMin, unsigned short* quantizedMax) const
+       {
+               return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin, quantizedMax);
+       }
+
+       SIMD_FORCE_INLINE void clearNodes()
+       {
+               m_node_array.clear();
+               m_num_nodes = 0;
+       }
+
+       //! node count
+       SIMD_FORCE_INLINE int getNodeCount() const
+       {
+               return m_num_nodes;
+       }
+
+       //! tells if the node is a leaf
+       SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+       {
+               return m_node_array[nodeindex].isLeafNode();
+       }
+
+       SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+       {
+               return m_node_array[nodeindex].getDataIndex();
+       }
+
+       SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
+       {
+               bound.m_min = bt_unquantize(
+                       m_node_array[nodeindex].m_quantizedAabbMin,
+                       m_global_bound.m_min, m_bvhQuantization);
+
+               bound.m_max = bt_unquantize(
+                       m_node_array[nodeindex].m_quantizedAabbMax,
+                       m_global_bound.m_min, m_bvhQuantization);
+       }
+
+       SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
+       {
+               bt_quantize_clamp(m_node_array[nodeindex].m_quantizedAabbMin,
+                                                 bound.m_min,
+                                                 m_global_bound.m_min,
+                                                 m_global_bound.m_max,
+                                                 m_bvhQuantization);
+
+               bt_quantize_clamp(m_node_array[nodeindex].m_quantizedAabbMax,
+                                                 bound.m_max,
+                                                 m_global_bound.m_min,
+                                                 m_global_bound.m_max,
+                                                 m_bvhQuantization);
+       }
+
+       SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+       {
+               return nodeindex + 1;
+       }
+
+       SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+       {
+               if (m_node_array[nodeindex + 1].isLeafNode()) return nodeindex + 2;
+               return nodeindex + 1 + m_node_array[nodeindex + 1].getEscapeIndex();
+       }
+
+       SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+       {
+               return m_node_array[nodeindex].getEscapeIndex();
+       }
+
+       SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE* get_node_pointer(int index = 0) const
+       {
+               return &m_node_array[index];
+       }
+
+       //!@}
+};
+
+//! Structure for containing Boxes
+/*!
+This class offers an structure for managing a box tree of primitives.
+Requires a Primitive prototype (like btPrimitiveManagerBase )
+*/
+class btGImpactQuantizedBvh
+{
+protected:
+       btQuantizedBvhTree m_box_tree;
+       btPrimitiveManagerBase* m_primitive_manager;
+
+protected:
+       //stackless refit
+       void refit();
+
+public:
+       //! this constructor doesn't build the tree. you must call      buildSet
+       btGImpactQuantizedBvh()
+       {
+               m_primitive_manager = NULL;
+       }
+
+       //! this constructor doesn't build the tree. you must call      buildSet
+       btGImpactQuantizedBvh(btPrimitiveManagerBase* primitive_manager)
+       {
+               m_primitive_manager = primitive_manager;
+       }
+
+       SIMD_FORCE_INLINE btAABB getGlobalBox() const
+       {
+               btAABB totalbox;
+               getNodeBound(0, totalbox);
+               return totalbox;
+       }
+
+       SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase* primitive_manager)
+       {
+               m_primitive_manager = primitive_manager;
+       }
+
+       SIMD_FORCE_INLINE btPrimitiveManagerBase* getPrimitiveManager() const
+       {
+               return m_primitive_manager;
+       }
+
+       //! node manager prototype functions
+       ///@{
+
+       //! this attemps to refit the box set.
+       SIMD_FORCE_INLINE void update()
+       {
+               refit();
+       }
+
+       //! this rebuild the entire set
+       void buildSet();
+
+       //! returns the indices of the primitives in the m_primitive_manager
+       bool boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const;
+
+       //! returns the indices of the primitives in the m_primitive_manager
+       SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB& box,
+                                                                                const btTransform& transform, btAlignedObjectArray<int>& collided_results) const
+       {
+               btAABB transbox = box;
+               transbox.appy_transform(transform);
+               return boxQuery(transbox, collided_results);
+       }
+
+       //! returns the indices of the primitives in the m_primitive_manager
+       bool rayQuery(
+               const btVector3& ray_dir, const btVector3& ray_origin,
+               btAlignedObjectArray<int>& collided_results) const;
+
+       //! tells if this set has hierarcht
+       SIMD_FORCE_INLINE bool hasHierarchy() const
+       {
+               return true;
+       }
+
+       //! tells if this set is a trimesh
+       SIMD_FORCE_INLINE bool isTrimesh() const
+       {
+               return m_primitive_manager->is_trimesh();
+       }
+
+       //! node count
+       SIMD_FORCE_INLINE int getNodeCount() const
+       {
+               return m_box_tree.getNodeCount();
+       }
+
+       //! tells if the node is a leaf
+       SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+       {
+               return m_box_tree.isLeafNode(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+       {
+               return m_box_tree.getNodeData(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
+       {
+               m_box_tree.getNodeBound(nodeindex, bound);
+       }
+
+       SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
+       {
+               m_box_tree.setNodeBound(nodeindex, bound);
+       }
+
+       SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+       {
+               return m_box_tree.getLeftNode(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+       {
+               return m_box_tree.getRightNode(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+       {
+               return m_box_tree.getEscapeNodeIndex(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex, btPrimitiveTriangle& triangle) const
+       {
+               m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex), triangle);
+       }
+
+       SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE* get_node_pointer(int index = 0) const
+       {
+               return m_box_tree.get_node_pointer(index);
+       }
+
+#ifdef TRI_COLLISION_PROFILING
+       static float getAverageTreeCollisionTime();
+#endif  //TRI_COLLISION_PROFILING
+
+       static void find_collision(const btGImpactQuantizedBvh* boxset1, const btTransform& trans1,
+                                                          const btGImpactQuantizedBvh* boxset2, const btTransform& trans2,
+                                                          btPairSet& collision_pairs);
+};
+
+#endif  // GIM_BOXPRUNING_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h
new file mode 100644 (file)
index 0000000..bd50cb5
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
+#define GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
+
+/*! \file btGImpactQuantizedBvh.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "btGImpactBvh.h"
+#include "btQuantization.h"
+
+///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)
+BT_QUANTIZED_BVH_NODE
+{
+       //12 bytes
+       unsigned short int m_quantizedAabbMin[3];
+       unsigned short int m_quantizedAabbMax[3];
+       //4 bytes
+       int m_escapeIndexOrDataIndex;
+
+       BT_QUANTIZED_BVH_NODE()
+       {
+               m_escapeIndexOrDataIndex = 0;
+       }
+
+       SIMD_FORCE_INLINE bool isLeafNode() const
+       {
+               //skipindex is negative (internal node), triangleindex >=0 (leafnode)
+               return (m_escapeIndexOrDataIndex >= 0);
+       }
+
+       SIMD_FORCE_INLINE int getEscapeIndex() const
+       {
+               //btAssert(m_escapeIndexOrDataIndex < 0);
+               return -m_escapeIndexOrDataIndex;
+       }
+
+       SIMD_FORCE_INLINE void setEscapeIndex(int index)
+       {
+               m_escapeIndexOrDataIndex = -index;
+       }
+
+       SIMD_FORCE_INLINE int getDataIndex() const
+       {
+               //btAssert(m_escapeIndexOrDataIndex >= 0);
+
+               return m_escapeIndexOrDataIndex;
+       }
+
+       SIMD_FORCE_INLINE void setDataIndex(int index)
+       {
+               m_escapeIndexOrDataIndex = index;
+       }
+
+       SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
+               unsigned short* quantizedMin, unsigned short* quantizedMax) const
+       {
+               if (m_quantizedAabbMin[0] > quantizedMax[0] ||
+                       m_quantizedAabbMax[0] < quantizedMin[0] ||
+                       m_quantizedAabbMin[1] > quantizedMax[1] ||
+                       m_quantizedAabbMax[1] < quantizedMin[1] ||
+                       m_quantizedAabbMin[2] > quantizedMax[2] ||
+                       m_quantizedAabbMax[2] < quantizedMin[2])
+               {
+                       return false;
+               }
+               return true;
+       }
+};
+
+#endif  // GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactShape.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactShape.cpp
new file mode 100644 (file)
index 0000000..34c229a
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "btGImpactShape.h"
+#include "btGImpactMassUtil.h"
+
+btGImpactMeshShapePart::btGImpactMeshShapePart(btStridingMeshInterface* meshInterface, int part)
+{
+       // moved from .h to .cpp because of conditional compilation
+       // (The setting of BT_THREADSAFE may differ between various cpp files, so it is best to
+       // avoid using it in h files)
+       m_primitive_manager.m_meshInterface = meshInterface;
+       m_primitive_manager.m_part = part;
+       m_box_set.setPrimitiveManager(&m_primitive_manager);
+#if BT_THREADSAFE
+       // If threadsafe is requested, this object uses a different lock/unlock
+       //  model with the btStridingMeshInterface -- lock once when the object is constructed
+       //  and unlock once in the destructor.
+       // The other way of locking and unlocking for each collision check in the narrowphase
+       // is not threadsafe.  Note these are not thread-locks, they are calls to the meshInterface's
+       // getLockedReadOnlyVertexIndexBase virtual function, which by default just returns a couple of
+       // pointers.  In theory a client could override the lock function to do all sorts of
+       // things like reading data from GPU memory, or decompressing data on the fly, but such things
+       // do not seem all that likely or useful, given the performance cost.
+       m_primitive_manager.lock();
+#endif
+}
+
+btGImpactMeshShapePart::~btGImpactMeshShapePart()
+{
+       // moved from .h to .cpp because of conditional compilation
+#if BT_THREADSAFE
+       m_primitive_manager.unlock();
+#endif
+}
+
+void btGImpactMeshShapePart::lockChildShapes() const
+{
+       // moved from .h to .cpp because of conditional compilation
+#if !BT_THREADSAFE
+       // called in the narrowphase -- not threadsafe!
+       void* dummy = (void*)(m_box_set.getPrimitiveManager());
+       TrimeshPrimitiveManager* dummymanager = static_cast<TrimeshPrimitiveManager*>(dummy);
+       dummymanager->lock();
+#endif
+}
+
+void btGImpactMeshShapePart::unlockChildShapes() const
+{
+       // moved from .h to .cpp because of conditional compilation
+#if !BT_THREADSAFE
+       // called in the narrowphase -- not threadsafe!
+       void* dummy = (void*)(m_box_set.getPrimitiveManager());
+       TrimeshPrimitiveManager* dummymanager = static_cast<TrimeshPrimitiveManager*>(dummy);
+       dummymanager->unlock();
+#endif
+}
+
+#define CALC_EXACT_INERTIA 1
+
+void btGImpactCompoundShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       lockChildShapes();
+#ifdef CALC_EXACT_INERTIA
+       inertia.setValue(0.f, 0.f, 0.f);
+
+       int i = this->getNumChildShapes();
+       btScalar shapemass = mass / btScalar(i);
+
+       while (i--)
+       {
+               btVector3 temp_inertia;
+               m_childShapes[i]->calculateLocalInertia(shapemass, temp_inertia);
+               if (childrenHasTransform())
+               {
+                       inertia = gim_inertia_add_transformed(inertia, temp_inertia, m_childTransforms[i]);
+               }
+               else
+               {
+                       inertia = gim_inertia_add_transformed(inertia, temp_inertia, btTransform::getIdentity());
+               }
+       }
+
+#else
+
+       // Calc box inertia
+
+       btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
+       btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
+       btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
+       const btScalar x2 = lx * lx;
+       const btScalar y2 = ly * ly;
+       const btScalar z2 = lz * lz;
+       const btScalar scaledmass = mass * btScalar(0.08333333);
+
+       inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
+
+#endif
+       unlockChildShapes();
+}
+
+void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+       lockChildShapes();
+
+#ifdef CALC_EXACT_INERTIA
+       inertia.setValue(0.f, 0.f, 0.f);
+
+       int i = this->getVertexCount();
+       btScalar pointmass = mass / btScalar(i);
+
+       while (i--)
+       {
+               btVector3 pointintertia;
+               this->getVertex(i, pointintertia);
+               pointintertia = gim_get_point_inertia(pointintertia, pointmass);
+               inertia += pointintertia;
+       }
+
+#else
+
+       // Calc box inertia
+
+       btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
+       btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
+       btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
+       const btScalar x2 = lx * lx;
+       const btScalar y2 = ly * ly;
+       const btScalar z2 = lz * lz;
+       const btScalar scaledmass = mass * btScalar(0.08333333);
+
+       inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
+
+#endif
+
+       unlockChildShapes();
+}
+
+void btGImpactMeshShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
+{
+#ifdef CALC_EXACT_INERTIA
+       inertia.setValue(0.f, 0.f, 0.f);
+
+       int i = this->getMeshPartCount();
+       btScalar partmass = mass / btScalar(i);
+
+       while (i--)
+       {
+               btVector3 partinertia;
+               getMeshPart(i)->calculateLocalInertia(partmass, partinertia);
+               inertia += partinertia;
+       }
+
+#else
+
+       // Calc box inertia
+
+       btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
+       btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
+       btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
+       const btScalar x2 = lx * lx;
+       const btScalar y2 = ly * ly;
+       const btScalar z2 = lz * lz;
+       const btScalar scaledmass = mass * btScalar(0.08333333);
+
+       inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
+
+#endif
+}
+
+void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
+{
+}
+
+void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const
+{
+       lockChildShapes();
+
+       btAlignedObjectArray<int> collided;
+       btVector3 rayDir(rayTo - rayFrom);
+       rayDir.normalize();
+       m_box_set.rayQuery(rayDir, rayFrom, collided);
+
+       if (collided.size() == 0)
+       {
+               unlockChildShapes();
+               return;
+       }
+
+       int part = (int)getPart();
+       btPrimitiveTriangle triangle;
+       int i = collided.size();
+       while (i--)
+       {
+               getPrimitiveTriangle(collided[i], triangle);
+               callback->processTriangle(triangle.m_vertices, part, collided[i]);
+       }
+       unlockChildShapes();
+}
+
+void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+       lockChildShapes();
+       btAABB box;
+       box.m_min = aabbMin;
+       box.m_max = aabbMax;
+
+       btAlignedObjectArray<int> collided;
+       m_box_set.boxQuery(box, collided);
+
+       if (collided.size() == 0)
+       {
+               unlockChildShapes();
+               return;
+       }
+
+       int part = (int)getPart();
+       btPrimitiveTriangle triangle;
+       int i = collided.size();
+       while (i--)
+       {
+               this->getPrimitiveTriangle(collided[i], triangle);
+               callback->processTriangle(triangle.m_vertices, part, collided[i]);
+       }
+       unlockChildShapes();
+}
+
+void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
+{
+       int i = m_mesh_parts.size();
+       while (i--)
+       {
+               m_mesh_parts[i]->processAllTriangles(callback, aabbMin, aabbMax);
+       }
+}
+
+void btGImpactMeshShape::processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const
+{
+       int i = m_mesh_parts.size();
+       while (i--)
+       {
+               m_mesh_parts[i]->processAllTrianglesRay(callback, rayFrom, rayTo);
+       }
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btGImpactMeshShapeData* trimeshData = (btGImpactMeshShapeData*)dataBuffer;
+
+       btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
+
+       m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
+
+       trimeshData->m_collisionMargin = float(m_collisionMargin);
+
+       localScaling.serializeFloat(trimeshData->m_localScaling);
+
+       trimeshData->m_gimpactSubType = int(getGImpactShapeType());
+
+       return "btGImpactMeshShapeData";
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactShape.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGImpactShape.h
new file mode 100644 (file)
index 0000000..cc91079
--- /dev/null
@@ -0,0 +1,1115 @@
+/*! \file btGImpactShape.h
+\author Francisco Le\7fn Nßjera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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.
+*/
+
+#ifndef GIMPACT_SHAPE_H
+#define GIMPACT_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+#include "btGImpactQuantizedBvh.h"  // box tree class
+
+//! declare Quantized trees, (you can change to float based trees)
+typedef btGImpactQuantizedBvh btGImpactBoxSet;
+
+enum eGIMPACT_SHAPE_TYPE
+{
+       CONST_GIMPACT_COMPOUND_SHAPE = 0,
+       CONST_GIMPACT_TRIMESH_SHAPE_PART,
+       CONST_GIMPACT_TRIMESH_SHAPE
+};
+
+//! Helper class for tetrahedrons
+class btTetrahedronShapeEx : public btBU_Simplex1to4
+{
+public:
+       btTetrahedronShapeEx()
+       {
+               m_numVertices = 4;
+       }
+
+       SIMD_FORCE_INLINE void setVertices(
+               const btVector3& v0, const btVector3& v1,
+               const btVector3& v2, const btVector3& v3)
+       {
+               m_vertices[0] = v0;
+               m_vertices[1] = v1;
+               m_vertices[2] = v2;
+               m_vertices[3] = v3;
+               recalcLocalAabb();
+       }
+};
+
+//! Base class for gimpact shapes
+class btGImpactShapeInterface : public btConcaveShape
+{
+protected:
+       btAABB m_localAABB;
+       bool m_needs_update;
+       btVector3 localScaling;
+       btGImpactBoxSet m_box_set;  // optionally boxset
+
+       //! use this function for perfofm refit in bounding boxes
+       //! use this function for perfofm refit in bounding boxes
+       virtual void calcLocalAABB()
+       {
+               lockChildShapes();
+               if (m_box_set.getNodeCount() == 0)
+               {
+                       m_box_set.buildSet();
+               }
+               else
+               {
+                       m_box_set.update();
+               }
+               unlockChildShapes();
+
+               m_localAABB = m_box_set.getGlobalBox();
+       }
+
+public:
+       btGImpactShapeInterface()
+       {
+               m_shapeType = GIMPACT_SHAPE_PROXYTYPE;
+               m_localAABB.invalidate();
+               m_needs_update = true;
+               localScaling.setValue(1.f, 1.f, 1.f);
+       }
+
+       //! performs refit operation
+       /*!
+       Updates the entire Box set of this shape.
+       \pre postUpdate() must be called for attemps to calculating the box set, else this function
+               will does nothing.
+       \post if m_needs_update == true, then it calls calcLocalAABB();
+       */
+       SIMD_FORCE_INLINE void updateBound()
+       {
+               if (!m_needs_update) return;
+               calcLocalAABB();
+               m_needs_update = false;
+       }
+
+       //! If the Bounding box is not updated, then this class attemps to calculate it.
+       /*!
+    \post Calls updateBound() for update the box set.
+    */
+       void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+       {
+               btAABB transformedbox = m_localAABB;
+               transformedbox.appy_transform(t);
+               aabbMin = transformedbox.m_min;
+               aabbMax = transformedbox.m_max;
+       }
+
+       //! Tells to this object that is needed to refit the box set
+       virtual void postUpdate()
+       {
+               m_needs_update = true;
+       }
+
+       //! Obtains the local box, which is the global calculated box of the total of subshapes
+       SIMD_FORCE_INLINE const btAABB& getLocalBox()
+       {
+               return m_localAABB;
+       }
+
+       virtual int getShapeType() const
+       {
+               return GIMPACT_SHAPE_PROXYTYPE;
+       }
+
+       /*!
+       \post You must call updateBound() for update the box set.
+       */
+       virtual void setLocalScaling(const btVector3& scaling)
+       {
+               localScaling = scaling;
+               postUpdate();
+       }
+
+       virtual const btVector3& getLocalScaling() const
+       {
+               return localScaling;
+       }
+
+       virtual void setMargin(btScalar margin)
+       {
+               m_collisionMargin = margin;
+               int i = getNumChildShapes();
+               while (i--)
+               {
+                       btCollisionShape* child = getChildShape(i);
+                       child->setMargin(margin);
+               }
+
+               m_needs_update = true;
+       }
+
+       //! Subshape member functions
+       //!@{
+
+       //! Base method for determinig which kind of GIMPACT shape we get
+       virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0;
+
+       //! gets boxset
+       SIMD_FORCE_INLINE const btGImpactBoxSet* getBoxSet() const
+       {
+               return &m_box_set;
+       }
+
+       //! Determines if this class has a hierarchy structure for sorting its primitives
+       SIMD_FORCE_INLINE bool hasBoxSet() const
+       {
+               if (m_box_set.getNodeCount() == 0) return false;
+               return true;
+       }
+
+       //! Obtains the primitive manager
+       virtual const btPrimitiveManagerBase* getPrimitiveManager() const = 0;
+
+       //! Gets the number of children
+       virtual int getNumChildShapes() const = 0;
+
+       //! if true, then its children must get transforms.
+       virtual bool childrenHasTransform() const = 0;
+
+       //! Determines if this shape has triangles
+       virtual bool needsRetrieveTriangles() const = 0;
+
+       //! Determines if this shape has tetrahedrons
+       virtual bool needsRetrieveTetrahedrons() const = 0;
+
+       virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const = 0;
+
+       virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const = 0;
+
+       //! call when reading child shapes
+       virtual void lockChildShapes() const
+       {
+       }
+
+       virtual void unlockChildShapes() const
+       {
+       }
+
+       //! if this trimesh
+       SIMD_FORCE_INLINE void getPrimitiveTriangle(int index, btPrimitiveTriangle& triangle) const
+       {
+               getPrimitiveManager()->get_primitive_triangle(index, triangle);
+       }
+
+       //! Retrieves the bound from a child
+       /*!
+    */
+       virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+       {
+               btAABB child_aabb;
+               getPrimitiveManager()->get_primitive_box(child_index, child_aabb);
+               child_aabb.appy_transform(t);
+               aabbMin = child_aabb.m_min;
+               aabbMax = child_aabb.m_max;
+       }
+
+       //! Gets the children
+       virtual btCollisionShape* getChildShape(int index) = 0;
+
+       //! Gets the child
+       virtual const btCollisionShape* getChildShape(int index) const = 0;
+
+       //! Gets the children transform
+       virtual btTransform getChildTransform(int index) const = 0;
+
+       //! Sets the children transform
+       /*!
+       \post You must call updateBound() for update the box set.
+       */
+       virtual void setChildTransform(int index, const btTransform& transform) = 0;
+
+       //!@}
+
+       //! virtual method for ray collision
+       virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
+       {
+               (void)rayFrom;
+               (void)rayTo;
+               (void)resultCallback;
+       }
+
+       //! Function for retrieve triangles.
+       /*!
+       It gives the triangles in local space
+       */
+       virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
+       {
+               (void)callback;
+               (void)aabbMin;
+               (void)aabbMax;
+       }
+
+       //! Function for retrieve triangles.
+       /*!
+       It gives the triangles in local space
+       */
+       virtual void processAllTrianglesRay(btTriangleCallback* /*callback*/, const btVector3& /*rayFrom*/, const btVector3& /*rayTo*/) const
+       {
+       }
+
+       //!@}
+};
+
+//! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once
+/*!
+This class only can manage Convex subshapes
+*/
+class btGImpactCompoundShape : public btGImpactShapeInterface
+{
+public:
+       //! compound primitive manager
+       class CompoundPrimitiveManager : public btPrimitiveManagerBase
+       {
+       public:
+               virtual ~CompoundPrimitiveManager() {}
+               btGImpactCompoundShape* m_compoundShape;
+
+               CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
+                       : btPrimitiveManagerBase()
+               {
+                       m_compoundShape = compound.m_compoundShape;
+               }
+
+               CompoundPrimitiveManager(btGImpactCompoundShape* compoundShape)
+               {
+                       m_compoundShape = compoundShape;
+               }
+
+               CompoundPrimitiveManager()
+               {
+                       m_compoundShape = NULL;
+               }
+
+               virtual bool is_trimesh() const
+               {
+                       return false;
+               }
+
+               virtual int get_primitive_count() const
+               {
+                       return (int)m_compoundShape->getNumChildShapes();
+               }
+
+               virtual void get_primitive_box(int prim_index, btAABB& primbox) const
+               {
+                       btTransform prim_trans;
+                       if (m_compoundShape->childrenHasTransform())
+                       {
+                               prim_trans = m_compoundShape->getChildTransform(prim_index);
+                       }
+                       else
+                       {
+                               prim_trans.setIdentity();
+                       }
+                       const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index);
+                       shape->getAabb(prim_trans, primbox.m_min, primbox.m_max);
+               }
+
+               virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const
+               {
+                       btAssert(0);
+                       (void)prim_index;
+                       (void)triangle;
+               }
+       };
+
+protected:
+       CompoundPrimitiveManager m_primitive_manager;
+       btAlignedObjectArray<btTransform> m_childTransforms;
+       btAlignedObjectArray<btCollisionShape*> m_childShapes;
+
+public:
+       btGImpactCompoundShape(bool children_has_transform = true)
+       {
+               (void)children_has_transform;
+               m_primitive_manager.m_compoundShape = this;
+               m_box_set.setPrimitiveManager(&m_primitive_manager);
+       }
+
+       virtual ~btGImpactCompoundShape()
+       {
+       }
+
+       //! if true, then its children must get transforms.
+       virtual bool childrenHasTransform() const
+       {
+               if (m_childTransforms.size() == 0) return false;
+               return true;
+       }
+
+       //! Obtains the primitive manager
+       virtual const btPrimitiveManagerBase* getPrimitiveManager() const
+       {
+               return &m_primitive_manager;
+       }
+
+       //! Obtains the compopund primitive manager
+       SIMD_FORCE_INLINE CompoundPrimitiveManager* getCompoundPrimitiveManager()
+       {
+               return &m_primitive_manager;
+       }
+
+       //! Gets the number of children
+       virtual int getNumChildShapes() const
+       {
+               return m_childShapes.size();
+       }
+
+       //! Use this method for adding children. Only Convex shapes are allowed.
+       void addChildShape(const btTransform& localTransform, btCollisionShape* shape)
+       {
+               btAssert(shape->isConvex());
+               m_childTransforms.push_back(localTransform);
+               m_childShapes.push_back(shape);
+       }
+
+       //! Use this method for adding children. Only Convex shapes are allowed.
+       void addChildShape(btCollisionShape* shape)
+       {
+               btAssert(shape->isConvex());
+               m_childShapes.push_back(shape);
+       }
+
+       //! Gets the children
+       virtual btCollisionShape* getChildShape(int index)
+       {
+               return m_childShapes[index];
+       }
+
+       //! Gets the children
+       virtual const btCollisionShape* getChildShape(int index) const
+       {
+               return m_childShapes[index];
+       }
+
+       //! Retrieves the bound from a child
+       /*!
+    */
+       virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+       {
+               if (childrenHasTransform())
+               {
+                       m_childShapes[child_index]->getAabb(t * m_childTransforms[child_index], aabbMin, aabbMax);
+               }
+               else
+               {
+                       m_childShapes[child_index]->getAabb(t, aabbMin, aabbMax);
+               }
+       }
+
+       //! Gets the children transform
+       virtual btTransform getChildTransform(int index) const
+       {
+               btAssert(m_childTransforms.size() == m_childShapes.size());
+               return m_childTransforms[index];
+       }
+
+       //! Sets the children transform
+       /*!
+       \post You must call updateBound() for update the box set.
+       */
+       virtual void setChildTransform(int index, const btTransform& transform)
+       {
+               btAssert(m_childTransforms.size() == m_childShapes.size());
+               m_childTransforms[index] = transform;
+               postUpdate();
+       }
+
+       //! Determines if this shape has triangles
+       virtual bool needsRetrieveTriangles() const
+       {
+               return false;
+       }
+
+       //! Determines if this shape has tetrahedrons
+       virtual bool needsRetrieveTetrahedrons() const
+       {
+               return false;
+       }
+
+       virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
+       {
+               (void)prim_index;
+               (void)triangle;
+               btAssert(0);
+       }
+
+       virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
+       {
+               (void)prim_index;
+               (void)tetrahedron;
+               btAssert(0);
+       }
+
+       //! Calculates the exact inertia tensor for this shape
+       virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
+
+       virtual const char* getName() const
+       {
+               return "GImpactCompound";
+       }
+
+       virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
+       {
+               return CONST_GIMPACT_COMPOUND_SHAPE;
+       }
+};
+
+//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface.
+/*!
+- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh
+- When making operations with this shape, you must call <b>lock</b> before accessing to the trimesh primitives, and then call <b>unlock</b>
+- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
+
+*/
+class btGImpactMeshShapePart : public btGImpactShapeInterface
+{
+public:
+       //! Trimesh primitive manager
+       /*!
+       Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism
+       */
+       class TrimeshPrimitiveManager : public btPrimitiveManagerBase
+       {
+       public:
+               btScalar m_margin;
+               btStridingMeshInterface* m_meshInterface;
+               btVector3 m_scale;
+               int m_part;
+               int m_lock_count;
+               const unsigned char* vertexbase;
+               int numverts;
+               PHY_ScalarType type;
+               int stride;
+               const unsigned char* indexbase;
+               int indexstride;
+               int numfaces;
+               PHY_ScalarType indicestype;
+
+               TrimeshPrimitiveManager()
+               {
+                       m_meshInterface = NULL;
+                       m_part = 0;
+                       m_margin = 0.01f;
+                       m_scale = btVector3(1.f, 1.f, 1.f);
+                       m_lock_count = 0;
+                       vertexbase = 0;
+                       numverts = 0;
+                       stride = 0;
+                       indexbase = 0;
+                       indexstride = 0;
+                       numfaces = 0;
+               }
+
+               TrimeshPrimitiveManager(const TrimeshPrimitiveManager& manager)
+                       : btPrimitiveManagerBase()
+               {
+                       m_meshInterface = manager.m_meshInterface;
+                       m_part = manager.m_part;
+                       m_margin = manager.m_margin;
+                       m_scale = manager.m_scale;
+                       m_lock_count = 0;
+                       vertexbase = 0;
+                       numverts = 0;
+                       stride = 0;
+                       indexbase = 0;
+                       indexstride = 0;
+                       numfaces = 0;
+               }
+
+               TrimeshPrimitiveManager(
+                       btStridingMeshInterface* meshInterface, int part)
+               {
+                       m_meshInterface = meshInterface;
+                       m_part = part;
+                       m_scale = m_meshInterface->getScaling();
+                       m_margin = 0.1f;
+                       m_lock_count = 0;
+                       vertexbase = 0;
+                       numverts = 0;
+                       stride = 0;
+                       indexbase = 0;
+                       indexstride = 0;
+                       numfaces = 0;
+               }
+
+               virtual ~TrimeshPrimitiveManager() {}
+
+               void lock()
+               {
+                       if (m_lock_count > 0)
+                       {
+                               m_lock_count++;
+                               return;
+                       }
+                       m_meshInterface->getLockedReadOnlyVertexIndexBase(
+                               &vertexbase, numverts,
+                               type, stride, &indexbase, indexstride, numfaces, indicestype, m_part);
+
+                       m_lock_count = 1;
+               }
+
+               void unlock()
+               {
+                       if (m_lock_count == 0) return;
+                       if (m_lock_count > 1)
+                       {
+                               --m_lock_count;
+                               return;
+                       }
+                       m_meshInterface->unLockReadOnlyVertexBase(m_part);
+                       vertexbase = NULL;
+                       m_lock_count = 0;
+               }
+
+               virtual bool is_trimesh() const
+               {
+                       return true;
+               }
+
+               virtual int get_primitive_count() const
+               {
+                       return (int)numfaces;
+               }
+
+               SIMD_FORCE_INLINE int get_vertex_count() const
+               {
+                       return (int)numverts;
+               }
+
+               SIMD_FORCE_INLINE void get_indices(int face_index, unsigned int& i0, unsigned int& i1, unsigned int& i2) const
+               {
+                       if (indicestype == PHY_SHORT)
+                       {
+                               unsigned short* s_indices = (unsigned short*)(indexbase + face_index * indexstride);
+                               i0 = s_indices[0];
+                               i1 = s_indices[1];
+                               i2 = s_indices[2];
+                       }
+                       else if (indicestype == PHY_INTEGER)
+                       {
+                               unsigned int* i_indices = (unsigned int*)(indexbase + face_index * indexstride);
+                               i0 = i_indices[0];
+                               i1 = i_indices[1];
+                               i2 = i_indices[2];
+                       }
+                       else
+                       {
+                               btAssert(indicestype == PHY_UCHAR);
+                               unsigned char* i_indices = (unsigned char*)(indexbase + face_index * indexstride);
+                               i0 = i_indices[0];
+                               i1 = i_indices[1];
+                               i2 = i_indices[2];
+                       }
+               }
+
+               SIMD_FORCE_INLINE void get_vertex(unsigned int vertex_index, btVector3& vertex) const
+               {
+                       if (type == PHY_DOUBLE)
+                       {
+                               double* dvertices = (double*)(vertexbase + vertex_index * stride);
+                               vertex[0] = btScalar(dvertices[0] * m_scale[0]);
+                               vertex[1] = btScalar(dvertices[1] * m_scale[1]);
+                               vertex[2] = btScalar(dvertices[2] * m_scale[2]);
+                       }
+                       else
+                       {
+                               float* svertices = (float*)(vertexbase + vertex_index * stride);
+                               vertex[0] = svertices[0] * m_scale[0];
+                               vertex[1] = svertices[1] * m_scale[1];
+                               vertex[2] = svertices[2] * m_scale[2];
+                       }
+               }
+
+               virtual void get_primitive_box(int prim_index, btAABB& primbox) const
+               {
+                       btPrimitiveTriangle triangle;
+                       get_primitive_triangle(prim_index, triangle);
+                       primbox.calc_from_triangle_margin(
+                               triangle.m_vertices[0],
+                               triangle.m_vertices[1], triangle.m_vertices[2], triangle.m_margin);
+               }
+
+               virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const
+               {
+                       unsigned int indices[3];
+                       get_indices(prim_index, indices[0], indices[1], indices[2]);
+                       get_vertex(indices[0], triangle.m_vertices[0]);
+                       get_vertex(indices[1], triangle.m_vertices[1]);
+                       get_vertex(indices[2], triangle.m_vertices[2]);
+                       triangle.m_margin = m_margin;
+               }
+
+               SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index, btTriangleShapeEx& triangle) const
+               {
+                       unsigned int indices[3];
+                       get_indices(prim_index, indices[0], indices[1], indices[2]);
+                       get_vertex(indices[0], triangle.m_vertices1[0]);
+                       get_vertex(indices[1], triangle.m_vertices1[1]);
+                       get_vertex(indices[2], triangle.m_vertices1[2]);
+                       triangle.setMargin(m_margin);
+               }
+       };
+
+protected:
+       TrimeshPrimitiveManager m_primitive_manager;
+
+public:
+       btGImpactMeshShapePart()
+       {
+               m_box_set.setPrimitiveManager(&m_primitive_manager);
+       }
+
+       btGImpactMeshShapePart(btStridingMeshInterface* meshInterface, int part);
+       virtual ~btGImpactMeshShapePart();
+
+       //! if true, then its children must get transforms.
+       virtual bool childrenHasTransform() const
+       {
+               return false;
+       }
+
+       //! call when reading child shapes
+       virtual void lockChildShapes() const;
+       virtual void unlockChildShapes() const;
+
+       //! Gets the number of children
+       virtual int getNumChildShapes() const
+       {
+               return m_primitive_manager.get_primitive_count();
+       }
+
+       //! Gets the children
+       virtual btCollisionShape* getChildShape(int index)
+       {
+               (void)index;
+               btAssert(0);
+               return NULL;
+       }
+
+       //! Gets the child
+       virtual const btCollisionShape* getChildShape(int index) const
+       {
+               (void)index;
+               btAssert(0);
+               return NULL;
+       }
+
+       //! Gets the children transform
+       virtual btTransform getChildTransform(int index) const
+       {
+               (void)index;
+               btAssert(0);
+               return btTransform();
+       }
+
+       //! Sets the children transform
+       /*!
+       \post You must call updateBound() for update the box set.
+       */
+       virtual void setChildTransform(int index, const btTransform& transform)
+       {
+               (void)index;
+               (void)transform;
+               btAssert(0);
+       }
+
+       //! Obtains the primitive manager
+       virtual const btPrimitiveManagerBase* getPrimitiveManager() const
+       {
+               return &m_primitive_manager;
+       }
+
+       SIMD_FORCE_INLINE TrimeshPrimitiveManager* getTrimeshPrimitiveManager()
+       {
+               return &m_primitive_manager;
+       }
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
+
+       virtual const char* getName() const
+       {
+               return "GImpactMeshShapePart";
+       }
+
+       virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
+       {
+               return CONST_GIMPACT_TRIMESH_SHAPE_PART;
+       }
+
+       //! Determines if this shape has triangles
+       virtual bool needsRetrieveTriangles() const
+       {
+               return true;
+       }
+
+       //! Determines if this shape has tetrahedrons
+       virtual bool needsRetrieveTetrahedrons() const
+       {
+               return false;
+       }
+
+       virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
+       {
+               m_primitive_manager.get_bullet_triangle(prim_index, triangle);
+       }
+
+       virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
+       {
+               (void)prim_index;
+               (void)tetrahedron;
+               btAssert(0);
+       }
+
+       SIMD_FORCE_INLINE int getVertexCount() const
+       {
+               return m_primitive_manager.get_vertex_count();
+       }
+
+       SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3& vertex) const
+       {
+               m_primitive_manager.get_vertex(vertex_index, vertex);
+       }
+
+       SIMD_FORCE_INLINE void setMargin(btScalar margin)
+       {
+               m_primitive_manager.m_margin = margin;
+               postUpdate();
+       }
+
+       SIMD_FORCE_INLINE btScalar getMargin() const
+       {
+               return m_primitive_manager.m_margin;
+       }
+
+       virtual void setLocalScaling(const btVector3& scaling)
+       {
+               m_primitive_manager.m_scale = scaling;
+               postUpdate();
+       }
+
+       virtual const btVector3& getLocalScaling() const
+       {
+               return m_primitive_manager.m_scale;
+       }
+
+       SIMD_FORCE_INLINE int getPart() const
+       {
+               return (int)m_primitive_manager.m_part;
+       }
+
+       virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+       virtual void processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const;
+};
+
+//! This class manages a mesh supplied by the btStridingMeshInterface interface.
+/*!
+Set of btGImpactMeshShapePart parts
+- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh
+
+- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
+
+*/
+class btGImpactMeshShape : public btGImpactShapeInterface
+{
+       btStridingMeshInterface* m_meshInterface;
+
+protected:
+       btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts;
+       void buildMeshParts(btStridingMeshInterface* meshInterface)
+       {
+               for (int i = 0; i < meshInterface->getNumSubParts(); ++i)
+               {
+                       btGImpactMeshShapePart* newpart = new btGImpactMeshShapePart(meshInterface, i);
+                       m_mesh_parts.push_back(newpart);
+               }
+       }
+
+       //! use this function for perfofm refit in bounding boxes
+       virtual void calcLocalAABB()
+       {
+               m_localAABB.invalidate();
+               int i = m_mesh_parts.size();
+               while (i--)
+               {
+                       m_mesh_parts[i]->updateBound();
+                       m_localAABB.merge(m_mesh_parts[i]->getLocalBox());
+               }
+       }
+
+public:
+       btGImpactMeshShape(btStridingMeshInterface* meshInterface)
+       {
+               m_meshInterface = meshInterface;
+               buildMeshParts(meshInterface);
+       }
+
+       virtual ~btGImpactMeshShape()
+       {
+               int i = m_mesh_parts.size();
+               while (i--)
+               {
+                       btGImpactMeshShapePart* part = m_mesh_parts[i];
+                       delete part;
+               }
+               m_mesh_parts.clear();
+       }
+
+       btStridingMeshInterface* getMeshInterface()
+       {
+               return m_meshInterface;
+       }
+
+       const btStridingMeshInterface* getMeshInterface() const
+       {
+               return m_meshInterface;
+       }
+
+       int getMeshPartCount() const
+       {
+               return m_mesh_parts.size();
+       }
+
+       btGImpactMeshShapePart* getMeshPart(int index)
+       {
+               return m_mesh_parts[index];
+       }
+
+       const btGImpactMeshShapePart* getMeshPart(int index) const
+       {
+               return m_mesh_parts[index];
+       }
+
+       virtual void setLocalScaling(const btVector3& scaling)
+       {
+               localScaling = scaling;
+
+               int i = m_mesh_parts.size();
+               while (i--)
+               {
+                       btGImpactMeshShapePart* part = m_mesh_parts[i];
+                       part->setLocalScaling(scaling);
+               }
+
+               m_needs_update = true;
+       }
+
+       virtual void setMargin(btScalar margin)
+       {
+               m_collisionMargin = margin;
+
+               int i = m_mesh_parts.size();
+               while (i--)
+               {
+                       btGImpactMeshShapePart* part = m_mesh_parts[i];
+                       part->setMargin(margin);
+               }
+
+               m_needs_update = true;
+       }
+
+       //! Tells to this object that is needed to refit all the meshes
+       virtual void postUpdate()
+       {
+               int i = m_mesh_parts.size();
+               while (i--)
+               {
+                       btGImpactMeshShapePart* part = m_mesh_parts[i];
+                       part->postUpdate();
+               }
+
+               m_needs_update = true;
+       }
+
+       virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
+
+       //! Obtains the primitive manager
+       virtual const btPrimitiveManagerBase* getPrimitiveManager() const
+       {
+               btAssert(0);
+               return NULL;
+       }
+
+       //! Gets the number of children
+       virtual int getNumChildShapes() const
+       {
+               btAssert(0);
+               return 0;
+       }
+
+       //! if true, then its children must get transforms.
+       virtual bool childrenHasTransform() const
+       {
+               btAssert(0);
+               return false;
+       }
+
+       //! Determines if this shape has triangles
+       virtual bool needsRetrieveTriangles() const
+       {
+               btAssert(0);
+               return false;
+       }
+
+       //! Determines if this shape has tetrahedrons
+       virtual bool needsRetrieveTetrahedrons() const
+       {
+               btAssert(0);
+               return false;
+       }
+
+       virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
+       {
+               (void)prim_index;
+               (void)triangle;
+               btAssert(0);
+       }
+
+       virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
+       {
+               (void)prim_index;
+               (void)tetrahedron;
+               btAssert(0);
+       }
+
+       //! call when reading child shapes
+       virtual void lockChildShapes() const
+       {
+               btAssert(0);
+       }
+
+       virtual void unlockChildShapes() const
+       {
+               btAssert(0);
+       }
+
+       //! Retrieves the bound from a child
+       /*!
+    */
+       virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+       {
+               (void)child_index;
+               (void)t;
+               (void)aabbMin;
+               (void)aabbMax;
+               btAssert(0);
+       }
+
+       //! Gets the children
+       virtual btCollisionShape* getChildShape(int index)
+       {
+               (void)index;
+               btAssert(0);
+               return NULL;
+       }
+
+       //! Gets the child
+       virtual const btCollisionShape* getChildShape(int index) const
+       {
+               (void)index;
+               btAssert(0);
+               return NULL;
+       }
+
+       //! Gets the children transform
+       virtual btTransform getChildTransform(int index) const
+       {
+               (void)index;
+               btAssert(0);
+               return btTransform();
+       }
+
+       //! Sets the children transform
+       /*!
+       \post You must call updateBound() for update the box set.
+       */
+       virtual void setChildTransform(int index, const btTransform& transform)
+       {
+               (void)index;
+               (void)transform;
+               btAssert(0);
+       }
+
+       virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
+       {
+               return CONST_GIMPACT_TRIMESH_SHAPE;
+       }
+
+       virtual const char* getName() const
+       {
+               return "GImpactMesh";
+       }
+
+       virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
+
+       //! Function for retrieve triangles.
+       /*!
+       It gives the triangles in local space
+       */
+       virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
+
+       virtual void processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const;
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btGImpactMeshShapeData
+{
+       btCollisionShapeData m_collisionShapeData;
+
+       btStridingMeshInterfaceData m_meshInterface;
+
+       btVector3FloatData m_localScaling;
+
+       float m_collisionMargin;
+
+       int m_gimpactSubType;
+};
+
+SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const
+{
+       return sizeof(btGImpactMeshShapeData);
+}
+
+#endif  //GIMPACT_MESH_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp
new file mode 100644 (file)
index 0000000..f81f04b
--- /dev/null
@@ -0,0 +1,266 @@
+/*! \file btGenericPoolAllocator.cpp
+\author Francisco Leon Najera. email projectileman@yahoo.com
+
+General purpose allocator class
+*/
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btGenericPoolAllocator.h"
+
+/// *************** btGenericMemoryPool ******************///////////
+
+size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements)
+{
+       size_t ptr = BT_UINT_MAX;
+
+       if (m_free_nodes_count == 0) return BT_UINT_MAX;
+       // find an avaliable free node with the correct size
+       size_t revindex = m_free_nodes_count;
+
+       while (revindex-- && ptr == BT_UINT_MAX)
+       {
+               if (m_allocated_sizes[m_free_nodes[revindex]] >= num_elements)
+               {
+                       ptr = revindex;
+               }
+       }
+       if (ptr == BT_UINT_MAX) return BT_UINT_MAX;  // not found
+
+       revindex = ptr;
+       ptr = m_free_nodes[revindex];
+       // post: ptr contains the node index, and revindex the index in m_free_nodes
+
+       size_t finalsize = m_allocated_sizes[ptr];
+       finalsize -= num_elements;
+
+       m_allocated_sizes[ptr] = num_elements;
+
+       // post: finalsize>=0, m_allocated_sizes[ptr] has the requested size
+
+       if (finalsize > 0)  // preserve free node, there are some free memory
+       {
+               m_free_nodes[revindex] = ptr + num_elements;
+               m_allocated_sizes[ptr + num_elements] = finalsize;
+       }
+       else  // delete free node
+       {
+               // swap with end
+               m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count - 1];
+               m_free_nodes_count--;
+       }
+
+       return ptr;
+}
+
+size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements)
+{
+       if (m_allocated_count + num_elements > m_max_element_count) return BT_UINT_MAX;
+
+       size_t ptr = m_allocated_count;
+
+       m_allocated_sizes[m_allocated_count] = num_elements;
+       m_allocated_count += num_elements;
+
+       return ptr;
+}
+
+void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count)
+{
+       m_allocated_count = 0;
+       m_free_nodes_count = 0;
+
+       m_element_size = element_size;
+       m_max_element_count = element_count;
+
+       m_pool = (unsigned char *)btAlignedAlloc(m_element_size * m_max_element_count, 16);
+       m_free_nodes = (size_t *)btAlignedAlloc(sizeof(size_t) * m_max_element_count, 16);
+       m_allocated_sizes = (size_t *)btAlignedAlloc(sizeof(size_t) * m_max_element_count, 16);
+
+       for (size_t i = 0; i < m_max_element_count; i++)
+       {
+               m_allocated_sizes[i] = 0;
+       }
+}
+
+void btGenericMemoryPool::end_pool()
+{
+       btAlignedFree(m_pool);
+       btAlignedFree(m_free_nodes);
+       btAlignedFree(m_allocated_sizes);
+       m_allocated_count = 0;
+       m_free_nodes_count = 0;
+}
+
+//! Allocates memory in pool
+/*!
+\param size_bytes size in bytes of the buffer
+*/
+void *btGenericMemoryPool::allocate(size_t size_bytes)
+{
+       size_t module = size_bytes % m_element_size;
+       size_t element_count = size_bytes / m_element_size;
+       if (module > 0) element_count++;
+
+       size_t alloc_pos = allocate_from_free_nodes(element_count);
+       // a free node is found
+       if (alloc_pos != BT_UINT_MAX)
+       {
+               return get_element_data(alloc_pos);
+       }
+       // allocate directly on pool
+       alloc_pos = allocate_from_pool(element_count);
+
+       if (alloc_pos == BT_UINT_MAX) return NULL;  // not space
+       return get_element_data(alloc_pos);
+}
+
+bool btGenericMemoryPool::freeMemory(void *pointer)
+{
+       unsigned char *pointer_pos = (unsigned char *)pointer;
+       unsigned char *pool_pos = (unsigned char *)m_pool;
+       // calc offset
+       if (pointer_pos < pool_pos) return false;  //other pool
+       size_t offset = size_t(pointer_pos - pool_pos);
+       if (offset >= get_pool_capacity()) return false;  // far away
+
+       // find free position
+       m_free_nodes[m_free_nodes_count] = offset / m_element_size;
+       m_free_nodes_count++;
+       return true;
+}
+
+/// *******************! btGenericPoolAllocator *******************!///
+
+btGenericPoolAllocator::~btGenericPoolAllocator()
+{
+       // destroy pools
+       size_t i;
+       for (i = 0; i < m_pool_count; i++)
+       {
+               m_pools[i]->end_pool();
+               btAlignedFree(m_pools[i]);
+       }
+}
+
+// creates a pool
+btGenericMemoryPool *btGenericPoolAllocator::push_new_pool()
+{
+       if (m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL;
+
+       btGenericMemoryPool *newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool), 16);
+
+       m_pools[m_pool_count] = newptr;
+
+       m_pools[m_pool_count]->init_pool(m_pool_element_size, m_pool_element_count);
+
+       m_pool_count++;
+       return newptr;
+}
+
+void *btGenericPoolAllocator::failback_alloc(size_t size_bytes)
+{
+       btGenericMemoryPool *pool = NULL;
+
+       if (size_bytes <= get_pool_capacity())
+       {
+               pool = push_new_pool();
+       }
+
+       if (pool == NULL)  // failback
+       {
+               return btAlignedAlloc(size_bytes, 16);
+       }
+
+       return pool->allocate(size_bytes);
+}
+
+bool btGenericPoolAllocator::failback_free(void *pointer)
+{
+       btAlignedFree(pointer);
+       return true;
+}
+
+//! Allocates memory in pool
+/*!
+\param size_bytes size in bytes of the buffer
+*/
+void *btGenericPoolAllocator::allocate(size_t size_bytes)
+{
+       void *ptr = NULL;
+
+       size_t i = 0;
+       while (i < m_pool_count && ptr == NULL)
+       {
+               ptr = m_pools[i]->allocate(size_bytes);
+               ++i;
+       }
+
+       if (ptr) return ptr;
+
+       return failback_alloc(size_bytes);
+}
+
+bool btGenericPoolAllocator::freeMemory(void *pointer)
+{
+       bool result = false;
+
+       size_t i = 0;
+       while (i < m_pool_count && result == false)
+       {
+               result = m_pools[i]->freeMemory(pointer);
+               ++i;
+       }
+
+       if (result) return true;
+
+       return failback_free(pointer);
+}
+
+/// ************** STANDARD ALLOCATOR ***************************///
+
+#define BT_DEFAULT_POOL_SIZE 32768
+#define BT_DEFAULT_POOL_ELEMENT_SIZE 8
+
+// main allocator
+class GIM_STANDARD_ALLOCATOR : public btGenericPoolAllocator
+{
+public:
+       GIM_STANDARD_ALLOCATOR() : btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE, BT_DEFAULT_POOL_SIZE)
+       {
+       }
+};
+
+// global allocator
+GIM_STANDARD_ALLOCATOR g_main_allocator;
+
+void *btPoolAlloc(size_t size)
+{
+       return g_main_allocator.allocate(size);
+}
+
+void *btPoolRealloc(void *ptr, size_t oldsize, size_t newsize)
+{
+       void *newptr = btPoolAlloc(newsize);
+       size_t copysize = oldsize < newsize ? oldsize : newsize;
+       memcpy(newptr, ptr, copysize);
+       btPoolFree(ptr);
+       return newptr;
+}
+
+void btPoolFree(void *ptr)
+{
+       g_main_allocator.freeMemory(ptr);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGenericPoolAllocator.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGenericPoolAllocator.h
new file mode 100644 (file)
index 0000000..197af4f
--- /dev/null
@@ -0,0 +1,153 @@
+/*! \file btGenericPoolAllocator.h
+\author Francisco Leon Najera. email projectileman@yahoo.com
+
+General purpose allocator class
+*/
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_GENERIC_POOL_ALLOCATOR_H
+#define BT_GENERIC_POOL_ALLOCATOR_H
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include "LinearMath/btAlignedAllocator.h"
+
+#define BT_UINT_MAX UINT_MAX
+#define BT_DEFAULT_MAX_POOLS 16
+
+//! Generic Pool class
+class btGenericMemoryPool
+{
+public:
+       unsigned char *m_pool;      //[m_element_size*m_max_element_count];
+       size_t *m_free_nodes;       //[m_max_element_count];//! free nodes
+       size_t *m_allocated_sizes;  //[m_max_element_count];//! Number of elements allocated per node
+       size_t m_allocated_count;
+       size_t m_free_nodes_count;
+
+protected:
+       size_t m_element_size;
+       size_t m_max_element_count;
+
+       size_t allocate_from_free_nodes(size_t num_elements);
+       size_t allocate_from_pool(size_t num_elements);
+
+public:
+       void init_pool(size_t element_size, size_t element_count);
+
+       void end_pool();
+
+       btGenericMemoryPool(size_t element_size, size_t element_count)
+       {
+               init_pool(element_size, element_count);
+       }
+
+       ~btGenericMemoryPool()
+       {
+               end_pool();
+       }
+
+       inline size_t get_pool_capacity()
+       {
+               return m_element_size * m_max_element_count;
+       }
+
+       inline size_t gem_element_size()
+       {
+               return m_element_size;
+       }
+
+       inline size_t get_max_element_count()
+       {
+               return m_max_element_count;
+       }
+
+       inline size_t get_allocated_count()
+       {
+               return m_allocated_count;
+       }
+
+       inline size_t get_free_positions_count()
+       {
+               return m_free_nodes_count;
+       }
+
+       inline void *get_element_data(size_t element_index)
+       {
+               return &m_pool[element_index * m_element_size];
+       }
+
+       //! Allocates memory in pool
+       /*!
+       \param size_bytes size in bytes of the buffer
+       */
+       void *allocate(size_t size_bytes);
+
+       bool freeMemory(void *pointer);
+};
+
+//! Generic Allocator with pools
+/*!
+General purpose Allocator which can create Memory Pools dynamiacally as needed.
+*/
+class btGenericPoolAllocator
+{
+protected:
+       size_t m_pool_element_size;
+       size_t m_pool_element_count;
+
+public:
+       btGenericMemoryPool *m_pools[BT_DEFAULT_MAX_POOLS];
+       size_t m_pool_count;
+
+       inline size_t get_pool_capacity()
+       {
+               return m_pool_element_size * m_pool_element_count;
+       }
+
+protected:
+       // creates a pool
+       btGenericMemoryPool *push_new_pool();
+
+       void *failback_alloc(size_t size_bytes);
+
+       bool failback_free(void *pointer);
+
+public:
+       btGenericPoolAllocator(size_t pool_element_size, size_t pool_element_count)
+       {
+               m_pool_count = 0;
+               m_pool_element_size = pool_element_size;
+               m_pool_element_count = pool_element_count;
+       }
+
+       virtual ~btGenericPoolAllocator();
+
+       //! Allocates memory in pool
+       /*!
+       \param size_bytes size in bytes of the buffer
+       */
+       void *allocate(size_t size_bytes);
+
+       bool freeMemory(void *pointer);
+};
+
+void *btPoolAlloc(size_t size);
+void *btPoolRealloc(void *ptr, size_t oldsize, size_t newsize);
+void btPoolFree(void *ptr);
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGeometryOperations.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btGeometryOperations.h
new file mode 100644 (file)
index 0000000..6a1ee6d
--- /dev/null
@@ -0,0 +1,198 @@
+#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+
+/*! \file btGeometryOperations.h
+*\author Francisco Leon Najera
+
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "btBoxCollision.h"
+
+#define PLANEDIREPSILON 0.0000001f
+#define PARALELENORMALS 0.000001f
+
+#define BT_CLAMP(number, minval, maxval) (number < minval ? minval : (number > maxval ? maxval : number))
+
+/// Calc a plane from a triangle edge an a normal. plane is a vec4f
+SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 &e1, const btVector3 &e2, const btVector3 &normal, btVector4 &plane)
+{
+       btVector3 planenormal = (e2 - e1).cross(normal);
+       planenormal.normalize();
+       plane.setValue(planenormal[0], planenormal[1], planenormal[2], e2.dot(planenormal));
+}
+
+//***************** SEGMENT and LINE FUNCTIONS **********************************///
+
+/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
+ */
+SIMD_FORCE_INLINE void bt_closest_point_on_segment(
+       btVector3 &cp, const btVector3 &v,
+       const btVector3 &e1, const btVector3 &e2)
+{
+       btVector3 n = e2 - e1;
+       cp = v - e1;
+       btScalar _scalar = cp.dot(n) / n.dot(n);
+       if (_scalar < 0.0f)
+       {
+               cp = e1;
+       }
+       else if (_scalar > 1.0f)
+       {
+               cp = e2;
+       }
+       else
+       {
+               cp = _scalar * n + e1;
+       }
+}
+
+//! line plane collision
+/*!
+*\return
+       -0  if the ray never intersects
+       -1 if the ray collides in front
+       -2 if the ray collides in back
+*/
+
+SIMD_FORCE_INLINE int bt_line_plane_collision(
+       const btVector4 &plane,
+       const btVector3 &vDir,
+       const btVector3 &vPoint,
+       btVector3 &pout,
+       btScalar &tparam,
+       btScalar tmin, btScalar tmax)
+{
+       btScalar _dotdir = vDir.dot(plane);
+
+       if (btFabs(_dotdir) < PLANEDIREPSILON)
+       {
+               tparam = tmax;
+               return 0;
+       }
+
+       btScalar _dis = bt_distance_point_plane(plane, vPoint);
+       char returnvalue = _dis < 0.0f ? 2 : 1;
+       tparam = -_dis / _dotdir;
+
+       if (tparam < tmin)
+       {
+               returnvalue = 0;
+               tparam = tmin;
+       }
+       else if (tparam > tmax)
+       {
+               returnvalue = 0;
+               tparam = tmax;
+       }
+       pout = tparam * vDir + vPoint;
+       return returnvalue;
+}
+
+//! Find closest points on segments
+SIMD_FORCE_INLINE void bt_segment_collision(
+       const btVector3 &vA1,
+       const btVector3 &vA2,
+       const btVector3 &vB1,
+       const btVector3 &vB2,
+       btVector3 &vPointA,
+       btVector3 &vPointB)
+{
+       btVector3 AD = vA2 - vA1;
+       btVector3 BD = vB2 - vB1;
+       btVector3 N = AD.cross(BD);
+       btScalar tp = N.length2();
+
+       btVector4 _M;  //plane
+
+       if (tp < SIMD_EPSILON)  //ARE PARALELE
+       {
+               //project B over A
+               bool invert_b_order = false;
+               _M[0] = vB1.dot(AD);
+               _M[1] = vB2.dot(AD);
+
+               if (_M[0] > _M[1])
+               {
+                       invert_b_order = true;
+                       BT_SWAP_NUMBERS(_M[0], _M[1]);
+               }
+               _M[2] = vA1.dot(AD);
+               _M[3] = vA2.dot(AD);
+               //mid points
+               N[0] = (_M[0] + _M[1]) * 0.5f;
+               N[1] = (_M[2] + _M[3]) * 0.5f;
+
+               if (N[0] < N[1])
+               {
+                       if (_M[1] < _M[2])
+                       {
+                               vPointB = invert_b_order ? vB1 : vB2;
+                               vPointA = vA1;
+                       }
+                       else if (_M[1] < _M[3])
+                       {
+                               vPointB = invert_b_order ? vB1 : vB2;
+                               bt_closest_point_on_segment(vPointA, vPointB, vA1, vA2);
+                       }
+                       else
+                       {
+                               vPointA = vA2;
+                               bt_closest_point_on_segment(vPointB, vPointA, vB1, vB2);
+                       }
+               }
+               else
+               {
+                       if (_M[3] < _M[0])
+                       {
+                               vPointB = invert_b_order ? vB2 : vB1;
+                               vPointA = vA2;
+                       }
+                       else if (_M[3] < _M[1])
+                       {
+                               vPointA = vA2;
+                               bt_closest_point_on_segment(vPointB, vPointA, vB1, vB2);
+                       }
+                       else
+                       {
+                               vPointB = invert_b_order ? vB1 : vB2;
+                               bt_closest_point_on_segment(vPointA, vPointB, vA1, vA2);
+                       }
+               }
+               return;
+       }
+
+       N = N.cross(BD);
+       _M.setValue(N[0], N[1], N[2], vB1.dot(N));
+
+       // get point A as the plane collision point
+       bt_line_plane_collision(_M, AD, vA1, vPointA, tp, btScalar(0), btScalar(1));
+
+       /*Closest point on segment*/
+       vPointB = vPointA - vB1;
+       tp = vPointB.dot(BD);
+       tp /= BD.dot(BD);
+       tp = BT_CLAMP(tp, 0.0f, 1.0f);
+
+       vPointB = tp * BD + vB1;
+}
+
+#endif  // GIM_VECTOR_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btQuantization.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btQuantization.h
new file mode 100644 (file)
index 0000000..19a02a2
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef BT_GIMPACT_QUANTIZATION_H_INCLUDED
+#define BT_GIMPACT_QUANTIZATION_H_INCLUDED
+
+/*! \file btQuantization.h
+*\author Francisco Leon Najera
+
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "LinearMath/btTransform.h"
+
+SIMD_FORCE_INLINE void bt_calc_quantization_parameters(
+       btVector3& outMinBound,
+       btVector3& outMaxBound,
+       btVector3& bvhQuantization,
+       const btVector3& srcMinBound, const btVector3& srcMaxBound,
+       btScalar quantizationMargin)
+{
+       //enlarge the AABB to avoid division by zero when initializing the quantization values
+       btVector3 clampValue(quantizationMargin, quantizationMargin, quantizationMargin);
+       outMinBound = srcMinBound - clampValue;
+       outMaxBound = srcMaxBound + clampValue;
+       btVector3 aabbSize = outMaxBound - outMinBound;
+       bvhQuantization = btVector3(btScalar(65535.0),
+                                                               btScalar(65535.0),
+                                                               btScalar(65535.0)) /
+                                         aabbSize;
+}
+
+SIMD_FORCE_INLINE void bt_quantize_clamp(
+       unsigned short* out,
+       const btVector3& point,
+       const btVector3& min_bound,
+       const btVector3& max_bound,
+       const btVector3& bvhQuantization)
+{
+       btVector3 clampedPoint(point);
+       clampedPoint.setMax(min_bound);
+       clampedPoint.setMin(max_bound);
+
+       btVector3 v = (clampedPoint - min_bound) * 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);
+}
+
+SIMD_FORCE_INLINE btVector3 bt_unquantize(
+       const unsigned short* vecIn,
+       const btVector3& offset,
+       const btVector3& bvhQuantization)
+{
+       btVector3 vecOut;
+       vecOut.setValue(
+               (btScalar)(vecIn[0]) / (bvhQuantization.getX()),
+               (btScalar)(vecIn[1]) / (bvhQuantization.getY()),
+               (btScalar)(vecIn[2]) / (bvhQuantization.getZ()));
+       vecOut += offset;
+       return vecOut;
+}
+
+#endif  // BT_GIMPACT_QUANTIZATION_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp
new file mode 100644 (file)
index 0000000..292ef8c
--- /dev/null
@@ -0,0 +1,203 @@
+/*! \file btGImpactTriangleShape.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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 "btTriangleShapeEx.h"
+
+void GIM_TRIANGLE_CONTACT::merge_points(const btVector4& plane,
+                                                                               btScalar margin, const btVector3* points, int point_count)
+{
+       m_point_count = 0;
+       m_penetration_depth = -1000.0f;
+
+       int point_indices[MAX_TRI_CLIPPING];
+
+       int _k;
+
+       for (_k = 0; _k < point_count; _k++)
+       {
+               btScalar _dist = -bt_distance_point_plane(plane, points[_k]) + margin;
+
+               if (_dist >= 0.0f)
+               {
+                       if (_dist > m_penetration_depth)
+                       {
+                               m_penetration_depth = _dist;
+                               point_indices[0] = _k;
+                               m_point_count = 1;
+                       }
+                       else if ((_dist + SIMD_EPSILON) >= m_penetration_depth)
+                       {
+                               point_indices[m_point_count] = _k;
+                               m_point_count++;
+                       }
+               }
+       }
+
+       for (_k = 0; _k < m_point_count; _k++)
+       {
+               m_points[_k] = points[point_indices[_k]];
+       }
+}
+
+///class btPrimitiveTriangle
+bool btPrimitiveTriangle::overlap_test_conservative(const btPrimitiveTriangle& other)
+{
+       btScalar total_margin = m_margin + other.m_margin;
+       // classify points on other triangle
+       btScalar dis0 = bt_distance_point_plane(m_plane, other.m_vertices[0]) - total_margin;
+
+       btScalar dis1 = bt_distance_point_plane(m_plane, other.m_vertices[1]) - total_margin;
+
+       btScalar dis2 = bt_distance_point_plane(m_plane, other.m_vertices[2]) - total_margin;
+
+       if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
+
+       // classify points on this triangle
+       dis0 = bt_distance_point_plane(other.m_plane, m_vertices[0]) - total_margin;
+
+       dis1 = bt_distance_point_plane(other.m_plane, m_vertices[1]) - total_margin;
+
+       dis2 = bt_distance_point_plane(other.m_plane, m_vertices[2]) - total_margin;
+
+       if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
+
+       return true;
+}
+
+int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle& other, btVector3* clipped_points)
+{
+       // edge 0
+
+       btVector3 temp_points[MAX_TRI_CLIPPING];
+
+       btVector4 edgeplane;
+
+       get_edge_plane(0, edgeplane);
+
+       int clipped_count = bt_plane_clip_triangle(
+               edgeplane, other.m_vertices[0], other.m_vertices[1], other.m_vertices[2], temp_points);
+
+       if (clipped_count == 0) return 0;
+
+       btVector3 temp_points1[MAX_TRI_CLIPPING];
+
+       // edge 1
+       get_edge_plane(1, edgeplane);
+
+       clipped_count = bt_plane_clip_polygon(edgeplane, temp_points, clipped_count, temp_points1);
+
+       if (clipped_count == 0) return 0;
+
+       // edge 2
+       get_edge_plane(2, edgeplane);
+
+       clipped_count = bt_plane_clip_polygon(
+               edgeplane, temp_points1, clipped_count, clipped_points);
+
+       return clipped_count;
+}
+
+bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle& other, GIM_TRIANGLE_CONTACT& contacts)
+{
+       btScalar margin = m_margin + other.m_margin;
+
+       btVector3 clipped_points[MAX_TRI_CLIPPING];
+       int clipped_count;
+       //create planes
+       // plane v vs U points
+
+       GIM_TRIANGLE_CONTACT contacts1;
+
+       contacts1.m_separating_normal = m_plane;
+
+       clipped_count = clip_triangle(other, clipped_points);
+
+       if (clipped_count == 0)
+       {
+               return false;  //Reject
+       }
+
+       //find most deep interval face1
+       contacts1.merge_points(contacts1.m_separating_normal, margin, clipped_points, clipped_count);
+       if (contacts1.m_point_count == 0) return false;  // too far
+       //Normal pointing to this triangle
+       contacts1.m_separating_normal *= -1.f;
+
+       //Clip tri1 by tri2 edges
+       GIM_TRIANGLE_CONTACT contacts2;
+       contacts2.m_separating_normal = other.m_plane;
+
+       clipped_count = other.clip_triangle(*this, clipped_points);
+
+       if (clipped_count == 0)
+       {
+               return false;  //Reject
+       }
+
+       //find most deep interval face1
+       contacts2.merge_points(contacts2.m_separating_normal, margin, clipped_points, clipped_count);
+       if (contacts2.m_point_count == 0) return false;  // too far
+
+       ////check most dir for contacts
+       if (contacts2.m_penetration_depth < contacts1.m_penetration_depth)
+       {
+               contacts.copy_from(contacts2);
+       }
+       else
+       {
+               contacts.copy_from(contacts1);
+       }
+       return true;
+}
+
+///class btTriangleShapeEx: public btTriangleShape
+
+bool btTriangleShapeEx::overlap_test_conservative(const btTriangleShapeEx& other)
+{
+       btScalar total_margin = getMargin() + other.getMargin();
+
+       btVector4 plane0;
+       buildTriPlane(plane0);
+       btVector4 plane1;
+       other.buildTriPlane(plane1);
+
+       // classify points on other triangle
+       btScalar dis0 = bt_distance_point_plane(plane0, other.m_vertices1[0]) - total_margin;
+
+       btScalar dis1 = bt_distance_point_plane(plane0, other.m_vertices1[1]) - total_margin;
+
+       btScalar dis2 = bt_distance_point_plane(plane0, other.m_vertices1[2]) - total_margin;
+
+       if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
+
+       // classify points on this triangle
+       dis0 = bt_distance_point_plane(plane1, m_vertices1[0]) - total_margin;
+
+       dis1 = bt_distance_point_plane(plane1, m_vertices1[1]) - total_margin;
+
+       dis2 = bt_distance_point_plane(plane1, m_vertices1[2]) - total_margin;
+
+       if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
+
+       return true;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btTriangleShapeEx.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/btTriangleShapeEx.h
new file mode 100644 (file)
index 0000000..568a1ce
--- /dev/null
@@ -0,0 +1,169 @@
+/*! \file btGImpactShape.h
+\author Francisco Leon Najera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.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.
+*/
+
+#ifndef GIMPACT_TRIANGLE_SHAPE_EX_H
+#define GIMPACT_TRIANGLE_SHAPE_EX_H
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "btBoxCollision.h"
+#include "btClipPolygon.h"
+#include "btGeometryOperations.h"
+
+#define MAX_TRI_CLIPPING 16
+
+//! Structure for collision
+struct GIM_TRIANGLE_CONTACT
+{
+       btScalar m_penetration_depth;
+       int m_point_count;
+       btVector4 m_separating_normal;
+       btVector3 m_points[MAX_TRI_CLIPPING];
+
+       SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT& other)
+       {
+               m_penetration_depth = other.m_penetration_depth;
+               m_separating_normal = other.m_separating_normal;
+               m_point_count = other.m_point_count;
+               int i = m_point_count;
+               while (i--)
+               {
+                       m_points[i] = other.m_points[i];
+               }
+       }
+
+       GIM_TRIANGLE_CONTACT()
+       {
+       }
+
+       GIM_TRIANGLE_CONTACT(const GIM_TRIANGLE_CONTACT& other)
+       {
+               copy_from(other);
+       }
+
+       //! classify points that are closer
+       void merge_points(const btVector4& plane,
+                                         btScalar margin, const btVector3* points, int point_count);
+};
+
+class btPrimitiveTriangle
+{
+public:
+       btVector3 m_vertices[3];
+       btVector4 m_plane;
+       btScalar m_margin;
+       btScalar m_dummy;
+       btPrimitiveTriangle() : m_margin(0.01f)
+       {
+       }
+
+       SIMD_FORCE_INLINE void buildTriPlane()
+       {
+               btVector3 normal = (m_vertices[1] - m_vertices[0]).cross(m_vertices[2] - m_vertices[0]);
+               normal.normalize();
+               m_plane.setValue(normal[0], normal[1], normal[2], m_vertices[0].dot(normal));
+       }
+
+       //! Test if triangles could collide
+       bool overlap_test_conservative(const btPrimitiveTriangle& other);
+
+       //! Calcs the plane which is paralele to the edge and perpendicular to the triangle plane
+       /*!
+       \pre this triangle must have its plane calculated.
+       */
+       SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4& plane) const
+       {
+               const btVector3& e0 = m_vertices[edge_index];
+               const btVector3& e1 = m_vertices[(edge_index + 1) % 3];
+               bt_edge_plane(e0, e1, m_plane, plane);
+       }
+
+       void applyTransform(const btTransform& t)
+       {
+               m_vertices[0] = t(m_vertices[0]);
+               m_vertices[1] = t(m_vertices[1]);
+               m_vertices[2] = t(m_vertices[2]);
+       }
+
+       //! Clips the triangle against this
+       /*!
+       \pre clipped_points must have MAX_TRI_CLIPPING size, and this triangle must have its plane calculated.
+       \return the number of clipped points
+       */
+       int clip_triangle(btPrimitiveTriangle& other, btVector3* clipped_points);
+
+       //! Find collision using the clipping method
+       /*!
+       \pre this triangle and other must have their triangles calculated
+       */
+       bool find_triangle_collision_clip_method(btPrimitiveTriangle& other, GIM_TRIANGLE_CONTACT& contacts);
+};
+
+//! Helper class for colliding Bullet Triangle Shapes
+/*!
+This class implements a better getAabb method than the previous btTriangleShape class
+*/
+class btTriangleShapeEx : public btTriangleShape
+{
+public:
+       btTriangleShapeEx() : btTriangleShape(btVector3(0, 0, 0), btVector3(0, 0, 0), btVector3(0, 0, 0))
+       {
+       }
+
+       btTriangleShapeEx(const btVector3& p0, const btVector3& p1, const btVector3& p2) : btTriangleShape(p0, p1, p2)
+       {
+       }
+
+       btTriangleShapeEx(const btTriangleShapeEx& other) : btTriangleShape(other.m_vertices1[0], other.m_vertices1[1], other.m_vertices1[2])
+       {
+       }
+
+       virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+       {
+               btVector3 tv0 = t(m_vertices1[0]);
+               btVector3 tv1 = t(m_vertices1[1]);
+               btVector3 tv2 = t(m_vertices1[2]);
+
+               btAABB trianglebox(tv0, tv1, tv2, m_collisionMargin);
+               aabbMin = trianglebox.m_min;
+               aabbMax = trianglebox.m_max;
+       }
+
+       void applyTransform(const btTransform& t)
+       {
+               m_vertices1[0] = t(m_vertices1[0]);
+               m_vertices1[1] = t(m_vertices1[1]);
+               m_vertices1[2] = t(m_vertices1[2]);
+       }
+
+       SIMD_FORCE_INLINE void buildTriPlane(btVector4& plane) const
+       {
+               btVector3 normal = (m_vertices1[1] - m_vertices1[0]).cross(m_vertices1[2] - m_vertices1[0]);
+               normal.normalize();
+               plane.setValue(normal[0], normal[1], normal[2], m_vertices1[0].dot(normal));
+       }
+
+       bool overlap_test_conservative(const btTriangleShapeEx& other);
+};
+
+#endif  //GIMPACT_TRIANGLE_MESH_SHAPE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_array.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_array.h
new file mode 100644 (file)
index 0000000..fc2dc38
--- /dev/null
@@ -0,0 +1,318 @@
+#ifndef GIM_ARRAY_H_INCLUDED
+#define GIM_ARRAY_H_INCLUDED
+/*! \file gim_array.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_memory.h"
+
+#define GIM_ARRAY_GROW_INCREMENT 2
+#define GIM_ARRAY_GROW_FACTOR 2
+
+//!    Very simple array container with fast access and simd memory
+template <typename T>
+class gim_array
+{
+public:
+       //! properties
+       //!@{
+       T* m_data;
+       GUINT m_size;
+       GUINT m_allocated_size;
+       //!@}
+       //! protected operations
+       //!@{
+
+       inline void destroyData()
+       {
+               m_allocated_size = 0;
+               if (m_data == NULL) return;
+               gim_free(m_data);
+               m_data = NULL;
+       }
+
+       inline bool resizeData(GUINT newsize)
+       {
+               if (newsize == 0)
+               {
+                       destroyData();
+                       return true;
+               }
+
+               if (m_size > 0)
+               {
+                       m_data = (T*)gim_realloc(m_data, m_size * sizeof(T), newsize * sizeof(T));
+               }
+               else
+               {
+                       m_data = (T*)gim_alloc(newsize * sizeof(T));
+               }
+               m_allocated_size = newsize;
+               return true;
+       }
+
+       inline bool growingCheck()
+       {
+               if (m_allocated_size <= m_size)
+               {
+                       GUINT requestsize = m_size;
+                       m_size = m_allocated_size;
+                       if (resizeData((requestsize + GIM_ARRAY_GROW_INCREMENT) * GIM_ARRAY_GROW_FACTOR) == false) return false;
+               }
+               return true;
+       }
+
+       //!@}
+       //! public operations
+       //!@{
+       inline bool reserve(GUINT size)
+       {
+               if (m_allocated_size >= size) return false;
+               return resizeData(size);
+       }
+
+       inline void clear_range(GUINT start_range)
+       {
+               while (m_size > start_range)
+               {
+                       m_data[--m_size].~T();
+               }
+       }
+
+       inline void clear()
+       {
+               if (m_size == 0) return;
+               clear_range(0);
+       }
+
+       inline void clear_memory()
+       {
+               clear();
+               destroyData();
+       }
+
+       gim_array()
+       {
+               m_data = 0;
+               m_size = 0;
+               m_allocated_size = 0;
+       }
+
+       gim_array(GUINT reservesize)
+       {
+               m_data = 0;
+               m_size = 0;
+
+               m_allocated_size = 0;
+               reserve(reservesize);
+       }
+
+       ~gim_array()
+       {
+               clear_memory();
+       }
+
+       inline GUINT size() const
+       {
+               return m_size;
+       }
+
+       inline GUINT max_size() const
+       {
+               return m_allocated_size;
+       }
+
+       inline T& operator[](size_t i)
+       {
+               return m_data[i];
+       }
+       inline const T& operator[](size_t i) const
+       {
+               return m_data[i];
+       }
+
+       inline T* pointer() { return m_data; }
+       inline const T* pointer() const
+       {
+               return m_data;
+       }
+
+       inline T* get_pointer_at(GUINT i)
+       {
+               return m_data + i;
+       }
+
+       inline const T* get_pointer_at(GUINT i) const
+       {
+               return m_data + i;
+       }
+
+       inline T& at(GUINT i)
+       {
+               return m_data[i];
+       }
+
+       inline const T& at(GUINT i) const
+       {
+               return m_data[i];
+       }
+
+       inline T& front()
+       {
+               return *m_data;
+       }
+
+       inline const T& front() const
+       {
+               return *m_data;
+       }
+
+       inline T& back()
+       {
+               return m_data[m_size - 1];
+       }
+
+       inline const T& back() const
+       {
+               return m_data[m_size - 1];
+       }
+
+       inline void swap(GUINT i, GUINT j)
+       {
+               gim_swap_elements(m_data, i, j);
+       }
+
+       inline void push_back(const T& obj)
+       {
+               this->growingCheck();
+               m_data[m_size] = obj;
+               m_size++;
+       }
+
+       //!Simply increase the m_size, doesn't call the new element constructor
+       inline void push_back_mem()
+       {
+               this->growingCheck();
+               m_size++;
+       }
+
+       inline void push_back_memcpy(const T& obj)
+       {
+               this->growingCheck();
+               gim_simd_memcpy(&m_data[m_size], &obj, sizeof(T));
+               m_size++;
+       }
+
+       inline void pop_back()
+       {
+               m_size--;
+               m_data[m_size].~T();
+       }
+
+       //!Simply decrease the m_size, doesn't call the deleted element destructor
+       inline void pop_back_mem()
+       {
+               m_size--;
+       }
+
+       //! fast erase
+       inline void erase(GUINT index)
+       {
+               if (index < m_size - 1)
+               {
+                       swap(index, m_size - 1);
+               }
+               pop_back();
+       }
+
+       inline void erase_sorted_mem(GUINT index)
+       {
+               m_size--;
+               for (GUINT i = index; i < m_size; i++)
+               {
+                       gim_simd_memcpy(m_data + i, m_data + i + 1, sizeof(T));
+               }
+       }
+
+       inline void erase_sorted(GUINT index)
+       {
+               m_data[index].~T();
+               erase_sorted_mem(index);
+       }
+
+       inline void insert_mem(GUINT index)
+       {
+               this->growingCheck();
+               for (GUINT i = m_size; i > index; i--)
+               {
+                       gim_simd_memcpy(m_data + i, m_data + i - 1, sizeof(T));
+               }
+               m_size++;
+       }
+
+       inline void insert(const T& obj, GUINT index)
+       {
+               insert_mem(index);
+               m_data[index] = obj;
+       }
+
+       inline void resize(GUINT size, bool call_constructor = true, const T& fillData = T())
+       {
+               if (size > m_size)
+               {
+                       reserve(size);
+                       if (call_constructor)
+                       {
+                               while (m_size < size)
+                               {
+                                       m_data[m_size] = fillData;
+                                       m_size++;
+                               }
+                       }
+                       else
+                       {
+                               m_size = size;
+                       }
+               }
+               else if (size < m_size)
+               {
+                       if (call_constructor) clear_range(size);
+                       m_size = size;
+               }
+       }
+
+       inline void refit()
+       {
+               resizeData(m_size);
+       }
+};
+
+#endif  // GIM_CONTAINERS_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h
new file mode 100644 (file)
index 0000000..7ab7836
--- /dev/null
@@ -0,0 +1,536 @@
+#ifndef GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+#define GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+
+/*! \file gim_basic_geometry_operations.h
+*\author Francisco Leon Najera
+type independant geometry routines
+
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_linear_math.h"
+
+#ifndef PLANEDIREPSILON
+#define PLANEDIREPSILON 0.0000001f
+#endif
+
+#ifndef PARALELENORMALS
+#define PARALELENORMALS 0.000001f
+#endif
+
+#define TRIANGLE_NORMAL(v1, v2, v3, n) \
+       {                                  \
+               vec3f _dif1, _dif2;            \
+               VEC_DIFF(_dif1, v2, v1);       \
+               VEC_DIFF(_dif2, v3, v1);       \
+               VEC_CROSS(n, _dif1, _dif2);    \
+               VEC_NORMALIZE(n);              \
+       }
+
+#define TRIANGLE_NORMAL_FAST(v1, v2, v3, n) \
+       {                                       \
+               vec3f _dif1, _dif2;                 \
+               VEC_DIFF(_dif1, v2, v1);            \
+               VEC_DIFF(_dif2, v3, v1);            \
+               VEC_CROSS(n, _dif1, _dif2);         \
+       }
+
+/// plane is a vec4f
+#define TRIANGLE_PLANE(v1, v2, v3, plane)   \
+       {                                       \
+               TRIANGLE_NORMAL(v1, v2, v3, plane); \
+               plane[3] = VEC_DOT(v1, plane);      \
+       }
+
+/// plane is a vec4f
+#define TRIANGLE_PLANE_FAST(v1, v2, v3, plane)   \
+       {                                            \
+               TRIANGLE_NORMAL_FAST(v1, v2, v3, plane); \
+               plane[3] = VEC_DOT(v1, plane);           \
+       }
+
+/// Calc a plane from an edge an a normal. plane is a vec4f
+#define EDGE_PLANE(e1, e2, n, plane)   \
+       {                                  \
+               vec3f _dif;                    \
+               VEC_DIFF(_dif, e2, e1);        \
+               VEC_CROSS(plane, _dif, n);     \
+               VEC_NORMALIZE(plane);          \
+               plane[3] = VEC_DOT(e1, plane); \
+       }
+
+#define DISTANCE_PLANE_POINT(plane, point) (VEC_DOT(plane, point) - plane[3])
+
+#define PROJECT_POINT_PLANE(point, plane, projected) \
+       {                                                \
+               GREAL _dis;                                  \
+               _dis = DISTANCE_PLANE_POINT(plane, point);   \
+               VEC_SCALE(projected, -_dis, plane);          \
+               VEC_SUM(projected, projected, point);        \
+       }
+
+//! Verifies if a point is in the plane hull
+template <typename CLASS_POINT, typename CLASS_PLANE>
+SIMD_FORCE_INLINE bool POINT_IN_HULL(
+       const CLASS_POINT &point, const CLASS_PLANE *planes, GUINT plane_count)
+{
+       GREAL _dis;
+       for (GUINT _i = 0; _i < plane_count; ++_i)
+       {
+               _dis = DISTANCE_PLANE_POINT(planes[_i], point);
+               if (_dis > 0.0f) return false;
+       }
+       return true;
+}
+
+template <typename CLASS_POINT, typename CLASS_PLANE>
+SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT(
+       const CLASS_POINT &s1,
+       const CLASS_POINT &s2, const CLASS_PLANE &plane, CLASS_POINT &clipped)
+{
+       GREAL _dis1, _dis2;
+       _dis1 = DISTANCE_PLANE_POINT(plane, s1);
+       VEC_DIFF(clipped, s2, s1);
+       _dis2 = VEC_DOT(clipped, plane);
+       VEC_SCALE(clipped, -_dis1 / _dis2, clipped);
+       VEC_SUM(clipped, clipped, s1);
+}
+
+enum ePLANE_INTERSECTION_TYPE
+{
+       G_BACK_PLANE = 0,
+       G_COLLIDE_PLANE,
+       G_FRONT_PLANE
+};
+
+enum eLINE_PLANE_INTERSECTION_TYPE
+{
+       G_FRONT_PLANE_S1 = 0,
+       G_FRONT_PLANE_S2,
+       G_BACK_PLANE_S1,
+       G_BACK_PLANE_S2,
+       G_COLLIDE_PLANE_S1,
+       G_COLLIDE_PLANE_S2
+};
+
+//! Confirms if the plane intersect the edge or nor
+/*!
+intersection type must have the following values
+<ul>
+<li> 0 : Segment in front of plane, s1 closest
+<li> 1 : Segment in front of plane, s2 closest
+<li> 2 : Segment in back of plane, s1 closest
+<li> 3 : Segment in back of plane, s2 closest
+<li> 4 : Segment collides plane, s1 in back
+<li> 5 : Segment collides plane, s2 in back
+</ul>
+*/
+
+template <typename CLASS_POINT, typename CLASS_PLANE>
+SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2(
+       const CLASS_POINT &s1,
+       const CLASS_POINT &s2,
+       const CLASS_PLANE &plane, CLASS_POINT &clipped)
+{
+       GREAL _dis1 = DISTANCE_PLANE_POINT(plane, s1);
+       GREAL _dis2 = DISTANCE_PLANE_POINT(plane, s2);
+       if (_dis1 > -G_EPSILON && _dis2 > -G_EPSILON)
+       {
+               if (_dis1 < _dis2) return G_FRONT_PLANE_S1;
+               return G_FRONT_PLANE_S2;
+       }
+       else if (_dis1 < G_EPSILON && _dis2 < G_EPSILON)
+       {
+               if (_dis1 > _dis2) return G_BACK_PLANE_S1;
+               return G_BACK_PLANE_S2;
+       }
+
+       VEC_DIFF(clipped, s2, s1);
+       _dis2 = VEC_DOT(clipped, plane);
+       VEC_SCALE(clipped, -_dis1 / _dis2, clipped);
+       VEC_SUM(clipped, clipped, s1);
+       if (_dis1 < _dis2) return G_COLLIDE_PLANE_S1;
+       return G_COLLIDE_PLANE_S2;
+}
+
+//! Confirms if the plane intersect the edge or not
+/*!
+clipped1 and clipped2 are the vertices behind the plane.
+clipped1 is the closest
+
+intersection_type must have the following values
+<ul>
+<li> 0 : Segment in front of plane, s1 closest
+<li> 1 : Segment in front of plane, s2 closest
+<li> 2 : Segment in back of plane, s1 closest
+<li> 3 : Segment in back of plane, s2 closest
+<li> 4 : Segment collides plane, s1 in back
+<li> 5 : Segment collides plane, s2 in back
+</ul>
+*/
+template <typename CLASS_POINT, typename CLASS_PLANE>
+SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
+       const CLASS_POINT &s1,
+       const CLASS_POINT &s2,
+       const CLASS_PLANE &plane,
+       CLASS_POINT &clipped1, CLASS_POINT &clipped2)
+{
+       eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1, s2, plane, clipped1);
+       switch (intersection_type)
+       {
+               case G_FRONT_PLANE_S1:
+                       VEC_COPY(clipped1, s1);
+                       VEC_COPY(clipped2, s2);
+                       break;
+               case G_FRONT_PLANE_S2:
+                       VEC_COPY(clipped1, s2);
+                       VEC_COPY(clipped2, s1);
+                       break;
+               case G_BACK_PLANE_S1:
+                       VEC_COPY(clipped1, s1);
+                       VEC_COPY(clipped2, s2);
+                       break;
+               case G_BACK_PLANE_S2:
+                       VEC_COPY(clipped1, s2);
+                       VEC_COPY(clipped2, s1);
+                       break;
+               case G_COLLIDE_PLANE_S1:
+                       VEC_COPY(clipped2, s1);
+                       break;
+               case G_COLLIDE_PLANE_S2:
+                       VEC_COPY(clipped2, s2);
+                       break;
+       }
+       return intersection_type;
+}
+
+//! Finds the 2 smallest cartesian coordinates of a plane normal
+#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1)
+
+//! Ray plane collision in one way
+/*!
+Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).<br/>
+It uses the PLANEDIREPSILON constant.
+*/
+template <typename T, typename CLASS_POINT, typename CLASS_PLANE>
+SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
+       const CLASS_PLANE &plane,
+       const CLASS_POINT &vDir,
+       const CLASS_POINT &vPoint,
+       CLASS_POINT &pout, T &tparam)
+{
+       GREAL _dis, _dotdir;
+       _dotdir = VEC_DOT(plane, vDir);
+       if (_dotdir < PLANEDIREPSILON)
+       {
+               return false;
+       }
+       _dis = DISTANCE_PLANE_POINT(plane, vPoint);
+       tparam = -_dis / _dotdir;
+       VEC_SCALE(pout, tparam, vDir);
+       VEC_SUM(pout, vPoint, pout);
+       return true;
+}
+
+//! line collision
+/*!
+*\return
+       -0  if the ray never intersects
+       -1 if the ray collides in front
+       -2 if the ray collides in back
+*/
+template <typename T, typename CLASS_POINT, typename CLASS_PLANE>
+SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
+       const CLASS_PLANE &plane,
+       const CLASS_POINT &vDir,
+       const CLASS_POINT &vPoint,
+       CLASS_POINT &pout,
+       T &tparam,
+       T tmin, T tmax)
+{
+       GREAL _dis, _dotdir;
+       _dotdir = VEC_DOT(plane, vDir);
+       if (btFabs(_dotdir) < PLANEDIREPSILON)
+       {
+               tparam = tmax;
+               return 0;
+       }
+       _dis = DISTANCE_PLANE_POINT(plane, vPoint);
+       char returnvalue = _dis < 0.0f ? 2 : 1;
+       tparam = -_dis / _dotdir;
+
+       if (tparam < tmin)
+       {
+               returnvalue = 0;
+               tparam = tmin;
+       }
+       else if (tparam > tmax)
+       {
+               returnvalue = 0;
+               tparam = tmax;
+       }
+
+       VEC_SCALE(pout, tparam, vDir);
+       VEC_SUM(pout, vPoint, pout);
+       return returnvalue;
+}
+
+/*! \brief Returns the Ray on which 2 planes intersect if they do.
+    Written by Rodrigo Hernandez on ODE convex collision
+
+  \param p1 Plane 1
+  \param p2 Plane 2
+  \param p Contains the origin of the ray upon returning if planes intersect
+  \param d Contains the direction of the ray upon returning if planes intersect
+  \return true if the planes intersect, 0 if paralell.
+
+*/
+template <typename CLASS_POINT, typename CLASS_PLANE>
+SIMD_FORCE_INLINE bool INTERSECT_PLANES(
+       const CLASS_PLANE &p1,
+       const CLASS_PLANE &p2,
+       CLASS_POINT &p,
+       CLASS_POINT &d)
+{
+       VEC_CROSS(d, p1, p2);
+       GREAL denom = VEC_DOT(d, d);
+       if (GIM_IS_ZERO(denom)) return false;
+       vec3f _n;
+       _n[0] = p1[3] * p2[0] - p2[3] * p1[0];
+       _n[1] = p1[3] * p2[1] - p2[3] * p1[1];
+       _n[2] = p1[3] * p2[2] - p2[3] * p1[2];
+       VEC_CROSS(p, _n, d);
+       p[0] /= denom;
+       p[1] /= denom;
+       p[2] /= denom;
+       return true;
+}
+
+//***************** SEGMENT and LINE FUNCTIONS **********************************///
+
+/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
+ */
+template <typename CLASS_POINT>
+SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
+       CLASS_POINT &cp, const CLASS_POINT &v,
+       const CLASS_POINT &e1, const CLASS_POINT &e2)
+{
+       vec3f _n;
+       VEC_DIFF(_n, e2, e1);
+       VEC_DIFF(cp, v, e1);
+       GREAL _scalar = VEC_DOT(cp, _n);
+       _scalar /= VEC_DOT(_n, _n);
+       if (_scalar < 0.0f)
+       {
+               VEC_COPY(cp, e1);
+       }
+       else if (_scalar > 1.0f)
+       {
+               VEC_COPY(cp, e2);
+       }
+       else
+       {
+               VEC_SCALE(cp, _scalar, _n);
+               VEC_SUM(cp, cp, e1);
+       }
+}
+
+/*! \brief Finds the line params where these lines intersect.
+
+\param dir1 Direction of line 1
+\param point1 Point of line 1
+\param dir2 Direction of line 2
+\param point2 Point of line 2
+\param t1 Result Parameter for line 1
+\param t2 Result Parameter for line 2
+\param dointersect  0  if the lines won't intersect, else 1
+
+*/
+template <typename T, typename CLASS_POINT>
+SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS(
+       const CLASS_POINT &dir1,
+       CLASS_POINT &point1,
+       const CLASS_POINT &dir2,
+       CLASS_POINT &point2,
+       T &t1, T &t2)
+{
+       GREAL det;
+       GREAL e1e1 = VEC_DOT(dir1, dir1);
+       GREAL e1e2 = VEC_DOT(dir1, dir2);
+       GREAL e2e2 = VEC_DOT(dir2, dir2);
+       vec3f p1p2;
+       VEC_DIFF(p1p2, point1, point2);
+       GREAL p1p2e1 = VEC_DOT(p1p2, dir1);
+       GREAL p1p2e2 = VEC_DOT(p1p2, dir2);
+       det = e1e2 * e1e2 - e1e1 * e2e2;
+       if (GIM_IS_ZERO(det)) return false;
+       t1 = (e1e2 * p1p2e2 - e2e2 * p1p2e1) / det;
+       t2 = (e1e1 * p1p2e2 - e1e2 * p1p2e1) / det;
+       return true;
+}
+
+//! Find closest points on segments
+template <typename CLASS_POINT>
+SIMD_FORCE_INLINE void SEGMENT_COLLISION(
+       const CLASS_POINT &vA1,
+       const CLASS_POINT &vA2,
+       const CLASS_POINT &vB1,
+       const CLASS_POINT &vB2,
+       CLASS_POINT &vPointA,
+       CLASS_POINT &vPointB)
+{
+       CLASS_POINT _AD, _BD, n;
+       vec4f _M;  //plane
+       VEC_DIFF(_AD, vA2, vA1);
+       VEC_DIFF(_BD, vB2, vB1);
+       VEC_CROSS(n, _AD, _BD);
+       GREAL _tp = VEC_DOT(n, n);
+       if (_tp < G_EPSILON)  //ARE PARALELE
+       {
+               //project B over A
+               bool invert_b_order = false;
+               _M[0] = VEC_DOT(vB1, _AD);
+               _M[1] = VEC_DOT(vB2, _AD);
+               if (_M[0] > _M[1])
+               {
+                       invert_b_order = true;
+                       GIM_SWAP_NUMBERS(_M[0], _M[1]);
+               }
+               _M[2] = VEC_DOT(vA1, _AD);
+               _M[3] = VEC_DOT(vA2, _AD);
+               //mid points
+               n[0] = (_M[0] + _M[1]) * 0.5f;
+               n[1] = (_M[2] + _M[3]) * 0.5f;
+
+               if (n[0] < n[1])
+               {
+                       if (_M[1] < _M[2])
+                       {
+                               vPointB = invert_b_order ? vB1 : vB2;
+                               vPointA = vA1;
+                       }
+                       else if (_M[1] < _M[3])
+                       {
+                               vPointB = invert_b_order ? vB1 : vB2;
+                               CLOSEST_POINT_ON_SEGMENT(vPointA, vPointB, vA1, vA2);
+                       }
+                       else
+                       {
+                               vPointA = vA2;
+                               CLOSEST_POINT_ON_SEGMENT(vPointB, vPointA, vB1, vB2);
+                       }
+               }
+               else
+               {
+                       if (_M[3] < _M[0])
+                       {
+                               vPointB = invert_b_order ? vB2 : vB1;
+                               vPointA = vA2;
+                       }
+                       else if (_M[3] < _M[1])
+                       {
+                               vPointA = vA2;
+                               CLOSEST_POINT_ON_SEGMENT(vPointB, vPointA, vB1, vB2);
+                       }
+                       else
+                       {
+                               vPointB = invert_b_order ? vB1 : vB2;
+                               CLOSEST_POINT_ON_SEGMENT(vPointA, vPointB, vA1, vA2);
+                       }
+               }
+               return;
+       }
+
+       VEC_CROSS(_M, n, _BD);
+       _M[3] = VEC_DOT(_M, vB1);
+
+       LINE_PLANE_COLLISION(_M, _AD, vA1, vPointA, _tp, btScalar(0), btScalar(1));
+       /*Closest point on segment*/
+       VEC_DIFF(vPointB, vPointA, vB1);
+       _tp = VEC_DOT(vPointB, _BD);
+       _tp /= VEC_DOT(_BD, _BD);
+       _tp = GIM_CLAMP(_tp, 0.0f, 1.0f);
+       VEC_SCALE(vPointB, _tp, _BD);
+       VEC_SUM(vPointB, vPointB, vB1);
+}
+
+//! Line box intersection in one dimension
+/*!
+
+*\param pos Position of the ray
+*\param dir Projection of the Direction of the ray
+*\param bmin Minimum bound of the box
+*\param bmax Maximum bound of the box
+*\param tfirst the minimum projection. Assign to 0 at first.
+*\param tlast the maximum projection. Assign to INFINITY at first.
+*\return true if there is an intersection.
+*/
+template <typename T>
+SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir, T bmin, T bmax, T &tfirst, T &tlast)
+{
+       if (GIM_IS_ZERO(dir))
+       {
+               return !(pos < bmin || pos > bmax);
+       }
+       GREAL a0 = (bmin - pos) / dir;
+       GREAL a1 = (bmax - pos) / dir;
+       if (a0 > a1) GIM_SWAP_NUMBERS(a0, a1);
+       tfirst = GIM_MAX(a0, tfirst);
+       tlast = GIM_MIN(a1, tlast);
+       if (tlast < tfirst) return false;
+       return true;
+}
+
+//! Sorts 3 componets
+template <typename T>
+SIMD_FORCE_INLINE void SORT_3_INDICES(
+       const T *values,
+       GUINT *order_indices)
+{
+       //get minimum
+       order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
+
+       //get second and third
+       GUINT i0 = (order_indices[0] + 1) % 3;
+       GUINT i1 = (i0 + 1) % 3;
+
+       if (values[i0] < values[i1])
+       {
+               order_indices[1] = i0;
+               order_indices[2] = i1;
+       }
+       else
+       {
+               order_indices[1] = i1;
+               order_indices[2] = i0;
+       }
+}
+
+#endif  // GIM_VECTOR_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_bitset.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_bitset.h
new file mode 100644 (file)
index 0000000..c1fb41a
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef GIM_BITSET_H_INCLUDED
+#define GIM_BITSET_H_INCLUDED
+/*! \file gim_bitset.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_array.h"
+
+#define GUINT_BIT_COUNT 32
+#define GUINT_EXPONENT 5
+
+class gim_bitset
+{
+public:
+       gim_array<GUINT> m_container;
+
+       gim_bitset()
+       {
+       }
+
+       gim_bitset(GUINT bits_count)
+       {
+               resize(bits_count);
+       }
+
+       ~gim_bitset()
+       {
+       }
+
+       inline bool resize(GUINT newsize)
+       {
+               GUINT oldsize = m_container.size();
+               m_container.resize(newsize / GUINT_BIT_COUNT + 1, false);
+               while (oldsize < m_container.size())
+               {
+                       m_container[oldsize] = 0;
+               }
+               return true;
+       }
+
+       inline GUINT size()
+       {
+               return m_container.size() * GUINT_BIT_COUNT;
+       }
+
+       inline void set_all()
+       {
+               for (GUINT i = 0; i < m_container.size(); ++i)
+               {
+                       m_container[i] = 0xffffffff;
+               }
+       }
+
+       inline void clear_all()
+       {
+               for (GUINT i = 0; i < m_container.size(); ++i)
+               {
+                       m_container[i] = 0;
+               }
+       }
+
+       inline void set(GUINT bit_index)
+       {
+               if (bit_index >= size())
+               {
+                       resize(bit_index);
+               }
+               m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT - 1)));
+       }
+
+       ///Return 0 or 1
+       inline char get(GUINT bit_index)
+       {
+               if (bit_index >= size())
+               {
+                       return 0;
+               }
+               char value = m_container[bit_index >> GUINT_EXPONENT] &
+                                        (1 << (bit_index & (GUINT_BIT_COUNT - 1)));
+               return value;
+       }
+
+       inline void clear(GUINT bit_index)
+       {
+               m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT - 1)));
+       }
+};
+
+#endif  // GIM_CONTAINERS_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_box_collision.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_box_collision.h
new file mode 100644 (file)
index 0000000..9f7cbe7
--- /dev/null
@@ -0,0 +1,578 @@
+#ifndef GIM_BOX_COLLISION_H_INCLUDED
+#define GIM_BOX_COLLISION_H_INCLUDED
+
+/*! \file gim_box_collision.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+#include "gim_basic_geometry_operations.h"
+#include "LinearMath/btTransform.h"
+
+//SIMD_FORCE_INLINE bool test_cross_edge_box(
+//     const btVector3 & edge,
+//     const btVector3 & absolute_edge,
+//     const btVector3 & pointa,
+//     const btVector3 & pointb, const btVector3 & extend,
+//     int dir_index0,
+//     int dir_index1
+//     int component_index0,
+//     int component_index1)
+//{
+//     // dir coords are -z and y
+//
+//     const btScalar dir0 = -edge[dir_index0];
+//     const btScalar dir1 = edge[dir_index1];
+//     btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
+//     btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
+//     //find minmax
+//     if(pmin>pmax)
+//     {
+//             GIM_SWAP_NUMBERS(pmin,pmax);
+//     }
+//     //find extends
+//     const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
+//                                     extend[component_index1] * absolute_edge[dir_index1];
+//
+//     if(pmin>rad || -rad>pmax) return false;
+//     return true;
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
+//     const btVector3 & edge,
+//     const btVector3 & absolute_edge,
+//     const btVector3 & pointa,
+//     const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//     return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
+//}
+//
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
+//     const btVector3 & edge,
+//     const btVector3 & absolute_edge,
+//     const btVector3 & pointa,
+//     const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//     return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
+//     const btVector3 & edge,
+//     const btVector3 & absolute_edge,
+//     const btVector3 & pointa,
+//     const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//     return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
+//}
+
+#ifndef TEST_CROSS_EDGE_BOX_MCR
+
+#define TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, i_dir_0, i_dir_1, i_comp_0, i_comp_1) \
+       {                                                                                                               \
+               const btScalar dir0 = -edge[i_dir_0];                                                                       \
+               const btScalar dir1 = edge[i_dir_1];                                                                        \
+               btScalar pmin = pointa[i_comp_0] * dir0 + pointa[i_comp_1] * dir1;                                          \
+               btScalar pmax = pointb[i_comp_0] * dir0 + pointb[i_comp_1] * dir1;                                          \
+               if (pmin > pmax)                                                                                            \
+               {                                                                                                           \
+                       GIM_SWAP_NUMBERS(pmin, pmax);                                                                           \
+               }                                                                                                           \
+               const btScalar abs_dir0 = absolute_edge[i_dir_0];                                                           \
+               const btScalar abs_dir1 = absolute_edge[i_dir_1];                                                           \
+               const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;                           \
+               if (pmin > rad || -rad > pmax) return false;                                                                \
+       }
+
+#endif
+
+#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend)       \
+       {                                                                                      \
+               TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 2, 1, 1, 2); \
+       }
+
+#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend)       \
+       {                                                                                      \
+               TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 0, 2, 2, 0); \
+       }
+
+#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend)       \
+       {                                                                                      \
+               TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 1, 0, 0, 1); \
+       }
+
+//!  Class for transforming a model1 to the space of model0
+class GIM_BOX_BOX_TRANSFORM_CACHE
+{
+public:
+       btVector3 m_T1to0;    //!< Transforms translation of model1 to model 0
+       btMatrix3x3 m_R1to0;  //!< Transforms Rotation of model1 to model 0, equal  to R0' * R1
+       btMatrix3x3 m_AR;     //!< Absolute value of m_R1to0
+
+       SIMD_FORCE_INLINE void calc_absolute_matrix()
+       {
+               static const btVector3 vepsi(1e-6f, 1e-6f, 1e-6f);
+               m_AR[0] = vepsi + m_R1to0[0].absolute();
+               m_AR[1] = vepsi + m_R1to0[1].absolute();
+               m_AR[2] = vepsi + m_R1to0[2].absolute();
+       }
+
+       GIM_BOX_BOX_TRANSFORM_CACHE()
+       {
+       }
+
+       GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0)
+       {
+               COPY_MATRIX_3X3(m_R1to0, trans1_to_0)
+               MAT_GET_TRANSLATION(trans1_to_0, m_T1to0)
+               calc_absolute_matrix();
+       }
+
+       //! Calc the transformation relative  1 to 0. Inverts matrics by transposing
+       SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform &trans0, const btTransform &trans1)
+       {
+               m_R1to0 = trans0.getBasis().transpose();
+               m_T1to0 = m_R1to0 * (-trans0.getOrigin());
+
+               m_T1to0 += m_R1to0 * trans1.getOrigin();
+               m_R1to0 *= trans1.getBasis();
+
+               calc_absolute_matrix();
+       }
+
+       //! Calcs the full invertion of the matrices. Useful for scaling matrices
+       SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform &trans0, const btTransform &trans1)
+       {
+               m_R1to0 = trans0.getBasis().inverse();
+               m_T1to0 = m_R1to0 * (-trans0.getOrigin());
+
+               m_T1to0 += m_R1to0 * trans1.getOrigin();
+               m_R1to0 *= trans1.getBasis();
+
+               calc_absolute_matrix();
+       }
+
+       SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point)
+       {
+               return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0;
+       }
+};
+
+#ifndef BOX_PLANE_EPSILON
+#define BOX_PLANE_EPSILON 0.000001f
+#endif
+
+//! Axis aligned box
+class GIM_AABB
+{
+public:
+       btVector3 m_min;
+       btVector3 m_max;
+
+       GIM_AABB()
+       {
+       }
+
+       GIM_AABB(const btVector3 &V1,
+                        const btVector3 &V2,
+                        const btVector3 &V3)
+       {
+               m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
+               m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
+               m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
+
+               m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
+               m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
+               m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
+       }
+
+       GIM_AABB(const btVector3 &V1,
+                        const btVector3 &V2,
+                        const btVector3 &V3,
+                        GREAL margin)
+       {
+               m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
+               m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
+               m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
+
+               m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
+               m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
+               m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
+
+               m_min[0] -= margin;
+               m_min[1] -= margin;
+               m_min[2] -= margin;
+               m_max[0] += margin;
+               m_max[1] += margin;
+               m_max[2] += margin;
+       }
+
+       GIM_AABB(const GIM_AABB &other) : m_min(other.m_min), m_max(other.m_max)
+       {
+       }
+
+       GIM_AABB(const GIM_AABB &other, btScalar margin) : m_min(other.m_min), m_max(other.m_max)
+       {
+               m_min[0] -= margin;
+               m_min[1] -= margin;
+               m_min[2] -= margin;
+               m_max[0] += margin;
+               m_max[1] += margin;
+               m_max[2] += margin;
+       }
+
+       SIMD_FORCE_INLINE void invalidate()
+       {
+               m_min[0] = G_REAL_INFINITY;
+               m_min[1] = G_REAL_INFINITY;
+               m_min[2] = G_REAL_INFINITY;
+               m_max[0] = -G_REAL_INFINITY;
+               m_max[1] = -G_REAL_INFINITY;
+               m_max[2] = -G_REAL_INFINITY;
+       }
+
+       SIMD_FORCE_INLINE void increment_margin(btScalar margin)
+       {
+               m_min[0] -= margin;
+               m_min[1] -= margin;
+               m_min[2] -= margin;
+               m_max[0] += margin;
+               m_max[1] += margin;
+               m_max[2] += margin;
+       }
+
+       SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin)
+       {
+               m_min[0] = other.m_min[0] - margin;
+               m_min[1] = other.m_min[1] - margin;
+               m_min[2] = other.m_min[2] - margin;
+
+               m_max[0] = other.m_max[0] + margin;
+               m_max[1] = other.m_max[1] + margin;
+               m_max[2] = other.m_max[2] + margin;
+       }
+
+       template <typename CLASS_POINT>
+       SIMD_FORCE_INLINE void calc_from_triangle(
+               const CLASS_POINT &V1,
+               const CLASS_POINT &V2,
+               const CLASS_POINT &V3)
+       {
+               m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
+               m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
+               m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
+
+               m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
+               m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
+               m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
+       }
+
+       template <typename CLASS_POINT>
+       SIMD_FORCE_INLINE void calc_from_triangle_margin(
+               const CLASS_POINT &V1,
+               const CLASS_POINT &V2,
+               const CLASS_POINT &V3, btScalar margin)
+       {
+               m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
+               m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
+               m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
+
+               m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
+               m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
+               m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
+
+               m_min[0] -= margin;
+               m_min[1] -= margin;
+               m_min[2] -= margin;
+               m_max[0] += margin;
+               m_max[1] += margin;
+               m_max[2] += margin;
+       }
+
+       //! Apply a transform to an AABB
+       SIMD_FORCE_INLINE void appy_transform(const btTransform &trans)
+       {
+               btVector3 center = (m_max + m_min) * 0.5f;
+               btVector3 extends = m_max - center;
+               // Compute new center
+               center = trans(center);
+
+               btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
+                                                                                 trans.getBasis().getRow(1).absolute(),
+                                                                                 trans.getBasis().getRow(2).absolute());
+
+               m_min = center - textends;
+               m_max = center + textends;
+       }
+
+       //! Merges a Box
+       SIMD_FORCE_INLINE void merge(const GIM_AABB &box)
+       {
+               m_min[0] = GIM_MIN(m_min[0], box.m_min[0]);
+               m_min[1] = GIM_MIN(m_min[1], box.m_min[1]);
+               m_min[2] = GIM_MIN(m_min[2], box.m_min[2]);
+
+               m_max[0] = GIM_MAX(m_max[0], box.m_max[0]);
+               m_max[1] = GIM_MAX(m_max[1], box.m_max[1]);
+               m_max[2] = GIM_MAX(m_max[2], box.m_max[2]);
+       }
+
+       //! Merges a point
+       template <typename CLASS_POINT>
+       SIMD_FORCE_INLINE void merge_point(const CLASS_POINT &point)
+       {
+               m_min[0] = GIM_MIN(m_min[0], point[0]);
+               m_min[1] = GIM_MIN(m_min[1], point[1]);
+               m_min[2] = GIM_MIN(m_min[2], point[2]);
+
+               m_max[0] = GIM_MAX(m_max[0], point[0]);
+               m_max[1] = GIM_MAX(m_max[1], point[1]);
+               m_max[2] = GIM_MAX(m_max[2], point[2]);
+       }
+
+       //! Gets the extend and center
+       SIMD_FORCE_INLINE void get_center_extend(btVector3 &center, btVector3 &extend) const
+       {
+               center = (m_max + m_min) * 0.5f;
+               extend = m_max - center;
+       }
+
+       //! Finds the intersecting box between this box and the other.
+       SIMD_FORCE_INLINE void find_intersection(const GIM_AABB &other, GIM_AABB &intersection) const
+       {
+               intersection.m_min[0] = GIM_MAX(other.m_min[0], m_min[0]);
+               intersection.m_min[1] = GIM_MAX(other.m_min[1], m_min[1]);
+               intersection.m_min[2] = GIM_MAX(other.m_min[2], m_min[2]);
+
+               intersection.m_max[0] = GIM_MIN(other.m_max[0], m_max[0]);
+               intersection.m_max[1] = GIM_MIN(other.m_max[1], m_max[1]);
+               intersection.m_max[2] = GIM_MIN(other.m_max[2], m_max[2]);
+       }
+
+       SIMD_FORCE_INLINE bool has_collision(const GIM_AABB &other) const
+       {
+               if (m_min[0] > other.m_max[0] ||
+                       m_max[0] < other.m_min[0] ||
+                       m_min[1] > other.m_max[1] ||
+                       m_max[1] < other.m_min[1] ||
+                       m_min[2] > other.m_max[2] ||
+                       m_max[2] < other.m_min[2])
+               {
+                       return false;
+               }
+               return true;
+       }
+
+       /*! \brief Finds the Ray intersection parameter.
+       \param aabb Aligned box
+       \param vorigin A vec3f with the origin of the ray
+       \param vdir A vec3f with the direction of the ray
+       */
+       SIMD_FORCE_INLINE bool collide_ray(const btVector3 &vorigin, const btVector3 &vdir)
+       {
+               btVector3 extents, center;
+               this->get_center_extend(center, extents);
+               ;
+
+               btScalar Dx = vorigin[0] - center[0];
+               if (GIM_GREATER(Dx, extents[0]) && Dx * vdir[0] >= 0.0f) return false;
+               btScalar Dy = vorigin[1] - center[1];
+               if (GIM_GREATER(Dy, extents[1]) && Dy * vdir[1] >= 0.0f) return false;
+               btScalar Dz = vorigin[2] - center[2];
+               if (GIM_GREATER(Dz, extents[2]) && Dz * vdir[2] >= 0.0f) return false;
+
+               btScalar f = vdir[1] * Dz - vdir[2] * Dy;
+               if (btFabs(f) > extents[1] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[1])) return false;
+               f = vdir[2] * Dx - vdir[0] * Dz;
+               if (btFabs(f) > extents[0] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[0])) return false;
+               f = vdir[0] * Dy - vdir[1] * Dx;
+               if (btFabs(f) > extents[0] * btFabs(vdir[1]) + extents[1] * btFabs(vdir[0])) return false;
+               return true;
+       }
+
+       SIMD_FORCE_INLINE void projection_interval(const btVector3 &direction, btScalar &vmin, btScalar &vmax) const
+       {
+               btVector3 center = (m_max + m_min) * 0.5f;
+               btVector3 extend = m_max - center;
+
+               btScalar _fOrigin = direction.dot(center);
+               btScalar _fMaximumExtent = extend.dot(direction.absolute());
+               vmin = _fOrigin - _fMaximumExtent;
+               vmax = _fOrigin + _fMaximumExtent;
+       }
+
+       SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
+       {
+               btScalar _fmin, _fmax;
+               this->projection_interval(plane, _fmin, _fmax);
+
+               if (plane[3] > _fmax + BOX_PLANE_EPSILON)
+               {
+                       return G_BACK_PLANE;  // 0
+               }
+
+               if (plane[3] + BOX_PLANE_EPSILON >= _fmin)
+               {
+                       return G_COLLIDE_PLANE;  //1
+               }
+               return G_FRONT_PLANE;  //2
+       }
+
+       SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB &box, btTransform &trans1_to_0)
+       {
+               GIM_AABB tbox = box;
+               tbox.appy_transform(trans1_to_0);
+               return has_collision(tbox);
+       }
+
+       //! transcache is the transformation cache from box to this AABB
+       SIMD_FORCE_INLINE bool overlapping_trans_cache(
+               const GIM_AABB &box, const GIM_BOX_BOX_TRANSFORM_CACHE &transcache, bool fulltest)
+       {
+               //Taken from OPCODE
+               btVector3 ea, eb;  //extends
+               btVector3 ca, cb;  //extends
+               get_center_extend(ca, ea);
+               box.get_center_extend(cb, eb);
+
+               btVector3 T;
+               btScalar t, t2;
+               int i;
+
+               // Class I : A's basis vectors
+               for (i = 0; i < 3; i++)
+               {
+                       T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
+                       t = transcache.m_AR[i].dot(eb) + ea[i];
+                       if (GIM_GREATER(T[i], t)) return false;
+               }
+               // Class II : B's basis vectors
+               for (i = 0; i < 3; i++)
+               {
+                       t = MAT_DOT_COL(transcache.m_R1to0, T, i);
+                       t2 = MAT_DOT_COL(transcache.m_AR, ea, i) + eb[i];
+                       if (GIM_GREATER(t, t2)) return false;
+               }
+               // Class III : 9 cross products
+               if (fulltest)
+               {
+                       int j, m, n, o, p, q, r;
+                       for (i = 0; i < 3; i++)
+                       {
+                               m = (i + 1) % 3;
+                               n = (i + 2) % 3;
+                               o = i == 0 ? 1 : 0;
+                               p = i == 2 ? 1 : 2;
+                               for (j = 0; j < 3; j++)
+                               {
+                                       q = j == 2 ? 1 : 2;
+                                       r = j == 0 ? 1 : 0;
+                                       t = T[n] * transcache.m_R1to0[m][j] - T[m] * transcache.m_R1to0[n][j];
+                                       t2 = ea[o] * transcache.m_AR[p][j] + ea[p] * transcache.m_AR[o][j] +
+                                                eb[r] * transcache.m_AR[i][q] + eb[q] * transcache.m_AR[i][r];
+                                       if (GIM_GREATER(t, t2)) return false;
+                               }
+                       }
+               }
+               return true;
+       }
+
+       //! Simple test for planes.
+       SIMD_FORCE_INLINE bool collide_plane(
+               const btVector4 &plane)
+       {
+               ePLANE_INTERSECTION_TYPE classify = plane_classify(plane);
+               return (classify == G_COLLIDE_PLANE);
+       }
+
+       //! test for a triangle, with edges
+       SIMD_FORCE_INLINE bool collide_triangle_exact(
+               const btVector3 &p1,
+               const btVector3 &p2,
+               const btVector3 &p3,
+               const btVector4 &triangle_plane)
+       {
+               if (!collide_plane(triangle_plane)) return false;
+
+               btVector3 center, extends;
+               this->get_center_extend(center, extends);
+
+               const btVector3 v1(p1 - center);
+               const btVector3 v2(p2 - center);
+               const btVector3 v3(p3 - center);
+
+               //First axis
+               btVector3 diff(v2 - v1);
+               btVector3 abs_diff = diff.absolute();
+               //Test With X axis
+               TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v1, v3, extends);
+               //Test With Y axis
+               TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v1, v3, extends);
+               //Test With Z axis
+               TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v1, v3, extends);
+
+               diff = v3 - v2;
+               abs_diff = diff.absolute();
+               //Test With X axis
+               TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v2, v1, extends);
+               //Test With Y axis
+               TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v2, v1, extends);
+               //Test With Z axis
+               TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v2, v1, extends);
+
+               diff = v1 - v3;
+               abs_diff = diff.absolute();
+               //Test With X axis
+               TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v3, v2, extends);
+               //Test With Y axis
+               TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v3, v2, extends);
+               //Test With Z axis
+               TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v3, v2, extends);
+
+               return true;
+       }
+};
+
+#ifndef BT_BOX_COLLISION_H_INCLUDED
+//! Compairison of transformation objects
+SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform &t1, const btTransform &t2)
+{
+       if (!(t1.getOrigin() == t2.getOrigin())) return false;
+
+       if (!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0))) return false;
+       if (!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1))) return false;
+       if (!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2))) return false;
+       return true;
+}
+#endif
+
+#endif  // GIM_BOX_COLLISION_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_box_set.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_box_set.cpp
new file mode 100644 (file)
index 0000000..0c7a6b7
--- /dev/null
@@ -0,0 +1,176 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_box_set.h"
+
+GUINT GIM_BOX_TREE::_calc_splitting_axis(
+       gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex)
+{
+       GUINT i;
+
+       btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
+       btVector3 variance(btScalar(0.), btScalar(0.), btScalar(0.));
+       GUINT numIndices = endIndex - startIndex;
+
+       for (i = startIndex; i < endIndex; i++)
+       {
+               btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+                                                                                       primitive_boxes[i].m_bound.m_min);
+               means += center;
+       }
+       means *= (btScalar(1.) / (btScalar)numIndices);
+
+       for (i = startIndex; i < endIndex; i++)
+       {
+               btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
+                                                                                       primitive_boxes[i].m_bound.m_min);
+               btVector3 diff2 = center - means;
+               diff2 = diff2 * diff2;
+               variance += diff2;
+       }
+       variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
+
+       return variance.maxAxis();
+}
+
+GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index(
+       gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex,
+       GUINT endIndex, GUINT splitAxis)
+{
+       GUINT i;
+       GUINT splitIndex = startIndex;
+       GUINT numIndices = endIndex - startIndex;
+
+       // average of centers
+       btScalar splitValue = 0.0f;
+       for (i = startIndex; i < endIndex; i++)
+       {
+               splitValue += 0.5f * (primitive_boxes[i].m_bound.m_max[splitAxis] +
+                                                         primitive_boxes[i].m_bound.m_min[splitAxis]);
+       }
+       splitValue /= (btScalar)numIndices;
+
+       //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+       for (i = startIndex; i < endIndex; i++)
+       {
+               btScalar center = 0.5f * (primitive_boxes[i].m_bound.m_max[splitAxis] +
+                                                                 primitive_boxes[i].m_bound.m_min[splitAxis]);
+               if (center > splitValue)
+               {
+                       //swap
+                       primitive_boxes.swap(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:
+       GUINT rangeBalancedIndices = numIndices / 3;
+       bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
+
+       if (unbalanced)
+       {
+               splitIndex = startIndex + (numIndices >> 1);
+       }
+
+       btAssert(!((splitIndex == startIndex) || (splitIndex == (endIndex))));
+
+       return splitIndex;
+}
+
+void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex)
+{
+       GUINT current_index = m_num_nodes++;
+
+       btAssert((endIndex - startIndex) > 0);
+
+       if ((endIndex - startIndex) == 1)  //we got a leaf
+       {
+               m_node_array[current_index].m_left = 0;
+               m_node_array[current_index].m_right = 0;
+               m_node_array[current_index].m_escapeIndex = 0;
+
+               m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound;
+               m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data;
+               return;
+       }
+
+       //configure inner node
+
+       GUINT splitIndex;
+
+       //calc this node bounding box
+       m_node_array[current_index].m_bound.invalidate();
+       for (splitIndex = startIndex; splitIndex < endIndex; splitIndex++)
+       {
+               m_node_array[current_index].m_bound.merge(primitive_boxes[splitIndex].m_bound);
+       }
+
+       //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+       //split axis
+       splitIndex = _calc_splitting_axis(primitive_boxes, startIndex, endIndex);
+
+       splitIndex = _sort_and_calc_splitting_index(
+               primitive_boxes, startIndex, endIndex, splitIndex);
+
+       //configure this inner node : the left node index
+       m_node_array[current_index].m_left = m_num_nodes;
+       //build left child tree
+       _build_sub_tree(primitive_boxes, startIndex, splitIndex);
+
+       //configure this inner node : the right node index
+       m_node_array[current_index].m_right = m_num_nodes;
+
+       //build right child tree
+       _build_sub_tree(primitive_boxes, splitIndex, endIndex);
+
+       //configure this inner node : the escape index
+       m_node_array[current_index].m_escapeIndex = m_num_nodes - current_index;
+}
+
+//! stackless build tree
+void GIM_BOX_TREE::build_tree(
+       gim_array<GIM_AABB_DATA>& primitive_boxes)
+{
+       // initialize node count to 0
+       m_num_nodes = 0;
+       // allocate nodes
+       m_node_array.resize(primitive_boxes.size() * 2);
+
+       _build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_box_set.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_box_set.h
new file mode 100644 (file)
index 0000000..afc591d
--- /dev/null
@@ -0,0 +1,640 @@
+#ifndef GIM_BOX_SET_H_INCLUDED
+#define GIM_BOX_SET_H_INCLUDED
+
+/*! \file gim_box_set.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_array.h"
+#include "gim_radixsort.h"
+#include "gim_box_collision.h"
+#include "gim_tri_collision.h"
+#include "gim_pair.h"
+
+//! A pairset array
+class gim_pair_set : public gim_array<GIM_PAIR>
+{
+public:
+       gim_pair_set() : gim_array<GIM_PAIR>(32)
+       {
+       }
+       inline void push_pair(GUINT index1, GUINT index2)
+       {
+               push_back(GIM_PAIR(index1, index2));
+       }
+
+       inline void push_pair_inv(GUINT index1, GUINT index2)
+       {
+               push_back(GIM_PAIR(index2, index1));
+       }
+};
+
+//! Prototype Base class for primitive classification
+/*!
+This class is a wrapper for primitive collections.
+This tells relevant info for the Bounding Box set classes, which take care of space classification.
+This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the  Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
+*/
+class GIM_PRIMITIVE_MANAGER_PROTOTYPE
+{
+public:
+       virtual ~GIM_PRIMITIVE_MANAGER_PROTOTYPE() {}
+       //! determines if this manager consist on only triangles, which special case will be optimized
+       virtual bool is_trimesh() = 0;
+       virtual GUINT get_primitive_count() = 0;
+       virtual void get_primitive_box(GUINT prim_index, GIM_AABB& primbox) = 0;
+       virtual void get_primitive_triangle(GUINT prim_index, GIM_TRIANGLE& triangle) = 0;
+};
+
+struct GIM_AABB_DATA
+{
+       GIM_AABB m_bound;
+       GUINT m_data;
+};
+
+//! Node Structure for trees
+struct GIM_BOX_TREE_NODE
+{
+       GIM_AABB m_bound;
+       GUINT m_left;         //!< Left subtree
+       GUINT m_right;        //!< Right subtree
+       GUINT m_escapeIndex;  //!< Scape index for traversing
+       GUINT m_data;         //!< primitive index if apply
+
+       GIM_BOX_TREE_NODE()
+       {
+               m_left = 0;
+               m_right = 0;
+               m_escapeIndex = 0;
+               m_data = 0;
+       }
+
+       SIMD_FORCE_INLINE bool is_leaf_node() const
+       {
+               return (!m_left && !m_right);
+       }
+};
+
+//! Basic Box tree structure
+class GIM_BOX_TREE
+{
+protected:
+       GUINT m_num_nodes;
+       gim_array<GIM_BOX_TREE_NODE> m_node_array;
+
+protected:
+       GUINT _sort_and_calc_splitting_index(
+               gim_array<GIM_AABB_DATA>& primitive_boxes,
+               GUINT startIndex, GUINT endIndex, GUINT splitAxis);
+
+       GUINT _calc_splitting_axis(gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex);
+
+       void _build_sub_tree(gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex);
+
+public:
+       GIM_BOX_TREE()
+       {
+               m_num_nodes = 0;
+       }
+
+       //! prototype functions for box tree management
+       //!@{
+       void build_tree(gim_array<GIM_AABB_DATA>& primitive_boxes);
+
+       SIMD_FORCE_INLINE void clearNodes()
+       {
+               m_node_array.clear();
+               m_num_nodes = 0;
+       }
+
+       //! node count
+       SIMD_FORCE_INLINE GUINT getNodeCount() const
+       {
+               return m_num_nodes;
+       }
+
+       //! tells if the node is a leaf
+       SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
+       {
+               return m_node_array[nodeindex].is_leaf_node();
+       }
+
+       SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
+       {
+               return m_node_array[nodeindex].m_data;
+       }
+
+       SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB& bound) const
+       {
+               bound = m_node_array[nodeindex].m_bound;
+       }
+
+       SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB& bound)
+       {
+               m_node_array[nodeindex].m_bound = bound;
+       }
+
+       SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
+       {
+               return m_node_array[nodeindex].m_left;
+       }
+
+       SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
+       {
+               return m_node_array[nodeindex].m_right;
+       }
+
+       SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
+       {
+               return m_node_array[nodeindex].m_escapeIndex;
+       }
+
+       //!@}
+};
+
+//! Generic Box Tree Template
+/*!
+This class offers an structure for managing a box tree of primitives.
+Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and
+a Box tree structure ( like GIM_BOX_TREE).
+*/
+template <typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE, typename _GIM_BOX_TREE_PROTOTYPE>
+class GIM_BOX_TREE_TEMPLATE_SET
+{
+protected:
+       _GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager;
+       _GIM_BOX_TREE_PROTOTYPE m_box_tree;
+
+protected:
+       //stackless refit
+       SIMD_FORCE_INLINE void refit()
+       {
+               GUINT nodecount = getNodeCount();
+               while (nodecount--)
+               {
+                       if (isLeafNode(nodecount))
+                       {
+                               GIM_AABB leafbox;
+                               m_primitive_manager.get_primitive_box(getNodeData(nodecount), leafbox);
+                               setNodeBound(nodecount, leafbox);
+                       }
+                       else
+                       {
+                               //get left bound
+                               GUINT childindex = getLeftNodeIndex(nodecount);
+                               GIM_AABB bound;
+                               getNodeBound(childindex, bound);
+                               //get right bound
+                               childindex = getRightNodeIndex(nodecount);
+                               GIM_AABB bound2;
+                               getNodeBound(childindex, bound2);
+                               bound.merge(bound2);
+
+                               setNodeBound(nodecount, bound);
+                       }
+               }
+       }
+
+public:
+       GIM_BOX_TREE_TEMPLATE_SET()
+       {
+       }
+
+       SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const
+       {
+               GIM_AABB totalbox;
+               getNodeBound(0, totalbox);
+               return totalbox;
+       }
+
+       SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE& primitive_manager)
+       {
+               m_primitive_manager = primitive_manager;
+       }
+
+       const _GIM_PRIMITIVE_MANAGER_PROTOTYPE& getPrimitiveManager() const
+       {
+               return m_primitive_manager;
+       }
+
+       _GIM_PRIMITIVE_MANAGER_PROTOTYPE& getPrimitiveManager()
+       {
+               return m_primitive_manager;
+       }
+
+       //! node manager prototype functions
+       ///@{
+
+       //! this attemps to refit the box set.
+       SIMD_FORCE_INLINE void update()
+       {
+               refit();
+       }
+
+       //! this rebuild the entire set
+       SIMD_FORCE_INLINE void buildSet()
+       {
+               //obtain primitive boxes
+               gim_array<GIM_AABB_DATA> primitive_boxes;
+               primitive_boxes.resize(m_primitive_manager.get_primitive_count(), false);
+
+               for (GUINT i = 0; i < primitive_boxes.size(); i++)
+               {
+                       m_primitive_manager.get_primitive_box(i, primitive_boxes[i].m_bound);
+                       primitive_boxes[i].m_data = i;
+               }
+
+               m_box_tree.build_tree(primitive_boxes);
+       }
+
+       //! returns the indices of the primitives in the m_primitive_manager
+       SIMD_FORCE_INLINE bool boxQuery(const GIM_AABB& box, gim_array<GUINT>& collided_results) const
+       {
+               GUINT curIndex = 0;
+               GUINT numNodes = getNodeCount();
+
+               while (curIndex < numNodes)
+               {
+                       GIM_AABB bound;
+                       getNodeBound(curIndex, bound);
+
+                       //catch bugs in tree data
+
+                       bool aabbOverlap = bound.has_collision(box);
+                       bool isleafnode = isLeafNode(curIndex);
+
+                       if (isleafnode && aabbOverlap)
+                       {
+                               collided_results.push_back(getNodeData(curIndex));
+                       }
+
+                       if (aabbOverlap || isleafnode)
+                       {
+                               //next subnode
+                               curIndex++;
+                       }
+                       else
+                       {
+                               //skip node
+                               curIndex += getScapeNodeIndex(curIndex);
+                       }
+               }
+               if (collided_results.size() > 0) return true;
+               return false;
+       }
+
+       //! returns the indices of the primitives in the m_primitive_manager
+       SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB& box,
+                                                                                const btTransform& transform, gim_array<GUINT>& collided_results) const
+       {
+               GIM_AABB transbox = box;
+               transbox.appy_transform(transform);
+               return boxQuery(transbox, collided_results);
+       }
+
+       //! returns the indices of the primitives in the m_primitive_manager
+       SIMD_FORCE_INLINE bool rayQuery(
+               const btVector3& ray_dir, const btVector3& ray_origin,
+               gim_array<GUINT>& collided_results) const
+       {
+               GUINT curIndex = 0;
+               GUINT numNodes = getNodeCount();
+
+               while (curIndex < numNodes)
+               {
+                       GIM_AABB bound;
+                       getNodeBound(curIndex, bound);
+
+                       //catch bugs in tree data
+
+                       bool aabbOverlap = bound.collide_ray(ray_origin, ray_dir);
+                       bool isleafnode = isLeafNode(curIndex);
+
+                       if (isleafnode && aabbOverlap)
+                       {
+                               collided_results.push_back(getNodeData(curIndex));
+                       }
+
+                       if (aabbOverlap || isleafnode)
+                       {
+                               //next subnode
+                               curIndex++;
+                       }
+                       else
+                       {
+                               //skip node
+                               curIndex += getScapeNodeIndex(curIndex);
+                       }
+               }
+               if (collided_results.size() > 0) return true;
+               return false;
+       }
+
+       //! tells if this set has hierarcht
+       SIMD_FORCE_INLINE bool hasHierarchy() const
+       {
+               return true;
+       }
+
+       //! tells if this set is a trimesh
+       SIMD_FORCE_INLINE bool isTrimesh() const
+       {
+               return m_primitive_manager.is_trimesh();
+       }
+
+       //! node count
+       SIMD_FORCE_INLINE GUINT getNodeCount() const
+       {
+               return m_box_tree.getNodeCount();
+       }
+
+       //! tells if the node is a leaf
+       SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
+       {
+               return m_box_tree.isLeafNode(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
+       {
+               return m_box_tree.getNodeData(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB& bound) const
+       {
+               m_box_tree.getNodeBound(nodeindex, bound);
+       }
+
+       SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB& bound)
+       {
+               m_box_tree.setNodeBound(nodeindex, bound);
+       }
+
+       SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
+       {
+               return m_box_tree.getLeftNodeIndex(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
+       {
+               return m_box_tree.getRightNodeIndex(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
+       {
+               return m_box_tree.getScapeNodeIndex(nodeindex);
+       }
+
+       SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex, GIM_TRIANGLE& triangle) const
+       {
+               m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex), triangle);
+       }
+};
+
+//! Class for Box Tree Sets
+/*!
+this has the GIM_BOX_TREE implementation for bounding boxes.
+*/
+template <typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE>
+class GIM_BOX_TREE_SET : public GIM_BOX_TREE_TEMPLATE_SET<_GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE>
+{
+public:
+};
+
+/// GIM_BOX_SET collision methods
+template <typename BOX_SET_CLASS0, typename BOX_SET_CLASS1>
+class GIM_TREE_TREE_COLLIDER
+{
+public:
+       gim_pair_set* m_collision_pairs;
+       BOX_SET_CLASS0* m_boxset0;
+       BOX_SET_CLASS1* m_boxset1;
+       GUINT current_node0;
+       GUINT current_node1;
+       bool node0_is_leaf;
+       bool node1_is_leaf;
+       bool t0_is_trimesh;
+       bool t1_is_trimesh;
+       bool node0_has_triangle;
+       bool node1_has_triangle;
+       GIM_AABB m_box0;
+       GIM_AABB m_box1;
+       GIM_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
+       btTransform trans_cache_0to1;
+       GIM_TRIANGLE m_tri0;
+       btVector4 m_tri0_plane;
+       GIM_TRIANGLE m_tri1;
+       btVector4 m_tri1_plane;
+
+public:
+       GIM_TREE_TREE_COLLIDER()
+       {
+               current_node0 = G_UINT_INFINITY;
+               current_node1 = G_UINT_INFINITY;
+       }
+
+protected:
+       SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0)
+       {
+               if (node0_has_triangle) return;
+               m_boxset0->getNodeTriangle(node0, m_tri0);
+               //transform triangle
+               m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]);
+               m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]);
+               m_tri0.m_vertices[2] = trans_cache_0to1(m_tri0.m_vertices[2]);
+               m_tri0.get_plane(m_tri0_plane);
+
+               node0_has_triangle = true;
+       }
+
+       SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1)
+       {
+               if (node1_has_triangle) return;
+               m_boxset1->getNodeTriangle(node1, m_tri1);
+               //transform triangle
+               m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]);
+               m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]);
+               m_tri1.m_vertices[2] = trans_cache_1to0.transform(m_tri1.m_vertices[2]);
+               m_tri1.get_plane(m_tri1_plane);
+
+               node1_has_triangle = true;
+       }
+
+       SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0)
+       {
+               if (node0 == current_node0) return;
+               m_boxset0->getNodeBound(node0, m_box0);
+               node0_is_leaf = m_boxset0->isLeafNode(node0);
+               node0_has_triangle = false;
+               current_node0 = node0;
+       }
+
+       SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1)
+       {
+               if (node1 == current_node1) return;
+               m_boxset1->getNodeBound(node1, m_box1);
+               node1_is_leaf = m_boxset1->isLeafNode(node1);
+               node1_has_triangle = false;
+               current_node1 = node1;
+       }
+
+       SIMD_FORCE_INLINE bool node_collision(GUINT node0, GUINT node1)
+       {
+               retrieve_node0_info(node0);
+               retrieve_node1_info(node1);
+               bool result = m_box0.overlapping_trans_cache(m_box1, trans_cache_1to0, true);
+               if (!result) return false;
+
+               if (t0_is_trimesh && node0_is_leaf)
+               {
+                       //perform primitive vs box collision
+                       retrieve_node0_triangle(node0);
+                       //do triangle vs box collision
+                       m_box1.increment_margin(m_tri0.m_margin);
+
+                       result = m_box1.collide_triangle_exact(
+                               m_tri0.m_vertices[0], m_tri0.m_vertices[1], m_tri0.m_vertices[2], m_tri0_plane);
+
+                       m_box1.increment_margin(-m_tri0.m_margin);
+
+                       if (!result) return false;
+                       return true;
+               }
+               else if (t1_is_trimesh && node1_is_leaf)
+               {
+                       //perform primitive vs box collision
+                       retrieve_node1_triangle(node1);
+                       //do triangle vs box collision
+                       m_box0.increment_margin(m_tri1.m_margin);
+
+                       result = m_box0.collide_triangle_exact(
+                               m_tri1.m_vertices[0], m_tri1.m_vertices[1], m_tri1.m_vertices[2], m_tri1_plane);
+
+                       m_box0.increment_margin(-m_tri1.m_margin);
+
+                       if (!result) return false;
+                       return true;
+               }
+               return true;
+       }
+
+       //stackless collision routine
+       void find_collision_pairs()
+       {
+               gim_pair_set stack_collisions;
+               stack_collisions.reserve(32);
+
+               //add the first pair
+               stack_collisions.push_pair(0, 0);
+
+               while (stack_collisions.size())
+               {
+                       //retrieve the last pair and pop
+                       GUINT node0 = stack_collisions.back().m_index1;
+                       GUINT node1 = stack_collisions.back().m_index2;
+                       stack_collisions.pop_back();
+                       if (node_collision(node0, node1))  // a collision is found
+                       {
+                               if (node0_is_leaf)
+                               {
+                                       if (node1_is_leaf)
+                                       {
+                                               m_collision_pairs->push_pair(m_boxset0->getNodeData(node0), m_boxset1->getNodeData(node1));
+                                       }
+                                       else
+                                       {
+                                               //collide left
+                                               stack_collisions.push_pair(node0, m_boxset1->getLeftNodeIndex(node1));
+
+                                               //collide right
+                                               stack_collisions.push_pair(node0, m_boxset1->getRightNodeIndex(node1));
+                                       }
+                               }
+                               else
+                               {
+                                       if (node1_is_leaf)
+                                       {
+                                               //collide left
+                                               stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0), node1);
+                                               //collide right
+                                               stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0), node1);
+                                       }
+                                       else
+                                       {
+                                               GUINT left0 = m_boxset0->getLeftNodeIndex(node0);
+                                               GUINT right0 = m_boxset0->getRightNodeIndex(node0);
+                                               GUINT left1 = m_boxset1->getLeftNodeIndex(node1);
+                                               GUINT right1 = m_boxset1->getRightNodeIndex(node1);
+                                               //collide left
+                                               stack_collisions.push_pair(left0, left1);
+                                               //collide right
+                                               stack_collisions.push_pair(left0, right1);
+                                               //collide left
+                                               stack_collisions.push_pair(right0, left1);
+                                               //collide right
+                                               stack_collisions.push_pair(right0, right1);
+
+                                       }  // else if node1 is not a leaf
+                               }      // else if node0 is not a leaf
+
+                       }  // if(node_collision(node0,node1))
+               }      //while(stack_collisions.size())
+       }
+
+public:
+       void find_collision(BOX_SET_CLASS0* boxset1, const btTransform& trans1,
+                                               BOX_SET_CLASS1* boxset2, const btTransform& trans2,
+                                               gim_pair_set& collision_pairs, bool complete_primitive_tests = true)
+       {
+               m_collision_pairs = &collision_pairs;
+               m_boxset0 = boxset1;
+               m_boxset1 = boxset2;
+
+               trans_cache_1to0.calc_from_homogenic(trans1, trans2);
+
+               trans_cache_0to1 = trans2.inverse();
+               trans_cache_0to1 *= trans1;
+
+               if (complete_primitive_tests)
+               {
+                       t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh();
+                       t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh();
+               }
+               else
+               {
+                       t0_is_trimesh = false;
+                       t1_is_trimesh = false;
+               }
+
+               find_collision_pairs();
+       }
+};
+
+#endif  // GIM_BOXPRUNING_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_clip_polygon.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_clip_polygon.h
new file mode 100644 (file)
index 0000000..57b9c5c
--- /dev/null
@@ -0,0 +1,199 @@
+#ifndef GIM_CLIP_POLYGON_H_INCLUDED
+#define GIM_CLIP_POLYGON_H_INCLUDED
+
+/*! \file gim_tri_collision.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+//! This function calcs the distance from a 3D plane
+class DISTANCE_PLANE_3D_FUNC
+{
+public:
+       template <typename CLASS_POINT, typename CLASS_PLANE>
+       inline GREAL operator()(const CLASS_PLANE& plane, const CLASS_POINT& point)
+       {
+               return DISTANCE_PLANE_POINT(plane, point);
+       }
+};
+
+template <typename CLASS_POINT>
+SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT(
+       const CLASS_POINT& point0,
+       const CLASS_POINT& point1,
+       GREAL dist0,
+       GREAL dist1,
+       CLASS_POINT* clipped,
+       GUINT& clipped_count)
+{
+       GUINT _prevclassif = (dist0 > G_EPSILON);
+       GUINT _classif = (dist1 > G_EPSILON);
+       if (_classif != _prevclassif)
+       {
+               GREAL blendfactor = -dist0 / (dist1 - dist0);
+               VEC_BLEND(clipped[clipped_count], point0, point1, blendfactor);
+               clipped_count++;
+       }
+       if (!_classif)
+       {
+               VEC_COPY(clipped[clipped_count], point1);
+               clipped_count++;
+       }
+}
+
+//! Clips a polygon by a plane
+/*!
+*\return The count of the clipped counts
+*/
+template <typename CLASS_POINT, typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC(
+       const CLASS_PLANE& plane,
+       const CLASS_POINT* polygon_points,
+       GUINT polygon_point_count,
+       CLASS_POINT* clipped, DISTANCE_PLANE_FUNC distance_func)
+{
+       GUINT clipped_count = 0;
+
+       //clip first point
+       GREAL firstdist = distance_func(plane, polygon_points[0]);
+       ;
+       if (!(firstdist > G_EPSILON))
+       {
+               VEC_COPY(clipped[clipped_count], polygon_points[0]);
+               clipped_count++;
+       }
+
+       GREAL olddist = firstdist;
+       for (GUINT _i = 1; _i < polygon_point_count; _i++)
+       {
+               GREAL dist = distance_func(plane, polygon_points[_i]);
+
+               PLANE_CLIP_POLYGON_COLLECT(
+                       polygon_points[_i - 1], polygon_points[_i],
+                       olddist,
+                       dist,
+                       clipped,
+                       clipped_count);
+
+               olddist = dist;
+       }
+
+       //RETURN TO FIRST  point
+
+       PLANE_CLIP_POLYGON_COLLECT(
+               polygon_points[polygon_point_count - 1], polygon_points[0],
+               olddist,
+               firstdist,
+               clipped,
+               clipped_count);
+
+       return clipped_count;
+}
+
+//! Clips a polygon by a plane
+/*!
+*\return The count of the clipped counts
+*/
+template <typename CLASS_POINT, typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC(
+       const CLASS_PLANE& plane,
+       const CLASS_POINT& point0,
+       const CLASS_POINT& point1,
+       const CLASS_POINT& point2,
+       CLASS_POINT* clipped, DISTANCE_PLANE_FUNC distance_func)
+{
+       GUINT clipped_count = 0;
+
+       //clip first point
+       GREAL firstdist = distance_func(plane, point0);
+       ;
+       if (!(firstdist > G_EPSILON))
+       {
+               VEC_COPY(clipped[clipped_count], point0);
+               clipped_count++;
+       }
+
+       // point 1
+       GREAL olddist = firstdist;
+       GREAL dist = distance_func(plane, point1);
+
+       PLANE_CLIP_POLYGON_COLLECT(
+               point0, point1,
+               olddist,
+               dist,
+               clipped,
+               clipped_count);
+
+       olddist = dist;
+
+       // point 2
+       dist = distance_func(plane, point2);
+
+       PLANE_CLIP_POLYGON_COLLECT(
+               point1, point2,
+               olddist,
+               dist,
+               clipped,
+               clipped_count);
+       olddist = dist;
+
+       //RETURN TO FIRST  point
+       PLANE_CLIP_POLYGON_COLLECT(
+               point2, point0,
+               olddist,
+               firstdist,
+               clipped,
+               clipped_count);
+
+       return clipped_count;
+}
+
+template <typename CLASS_POINT, typename CLASS_PLANE>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D(
+       const CLASS_PLANE& plane,
+       const CLASS_POINT* polygon_points,
+       GUINT polygon_point_count,
+       CLASS_POINT* clipped)
+{
+       return PLANE_CLIP_POLYGON_GENERIC<CLASS_POINT, CLASS_PLANE>(plane, polygon_points, polygon_point_count, clipped, DISTANCE_PLANE_3D_FUNC());
+}
+
+template <typename CLASS_POINT, typename CLASS_PLANE>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D(
+       const CLASS_PLANE& plane,
+       const CLASS_POINT& point0,
+       const CLASS_POINT& point1,
+       const CLASS_POINT& point2,
+       CLASS_POINT* clipped)
+{
+       return PLANE_CLIP_TRIANGLE_GENERIC<CLASS_POINT, CLASS_PLANE>(plane, point0, point1, point2, clipped, DISTANCE_PLANE_3D_FUNC());
+}
+
+#endif  // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_contact.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_contact.cpp
new file mode 100644 (file)
index 0000000..3902257
--- /dev/null
@@ -0,0 +1,142 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_contact.h"
+
+#define MAX_COINCIDENT 8
+
+void gim_contact_array::merge_contacts(
+       const gim_contact_array& contacts, bool normal_contact_average)
+{
+       clear();
+
+       if (contacts.size() == 1)
+       {
+               push_back(contacts.back());
+               return;
+       }
+
+       gim_array<GIM_RSORT_TOKEN> keycontacts(contacts.size());
+       keycontacts.resize(contacts.size(), false);
+
+       //fill key contacts
+
+       GUINT i;
+
+       for (i = 0; i < contacts.size(); i++)
+       {
+               keycontacts[i].m_key = contacts[i].calc_key_contact();
+               keycontacts[i].m_value = i;
+       }
+
+       //sort keys
+       gim_heap_sort(keycontacts.pointer(), keycontacts.size(), GIM_RSORT_TOKEN_COMPARATOR());
+
+       // Merge contacts
+
+       GUINT coincident_count = 0;
+       btVector3 coincident_normals[MAX_COINCIDENT];
+
+       GUINT last_key = keycontacts[0].m_key;
+       GUINT key = 0;
+
+       push_back(contacts[keycontacts[0].m_value]);
+       GIM_CONTACT* pcontact = &back();
+
+       for (i = 1; i < keycontacts.size(); i++)
+       {
+               key = keycontacts[i].m_key;
+               const GIM_CONTACT* scontact = &contacts[keycontacts[i].m_value];
+
+               if (last_key == key)  //same points
+               {
+                       //merge contact
+                       if (pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)  //)
+                       {
+                               *pcontact = *scontact;
+                               coincident_count = 0;
+                       }
+                       else if (normal_contact_average)
+                       {
+                               if (btFabs(pcontact->m_depth - scontact->m_depth) < CONTACT_DIFF_EPSILON)
+                               {
+                                       if (coincident_count < MAX_COINCIDENT)
+                                       {
+                                               coincident_normals[coincident_count] = scontact->m_normal;
+                                               coincident_count++;
+                                       }
+                               }
+                       }
+               }
+               else
+               {  //add new contact
+
+                       if (normal_contact_average && coincident_count > 0)
+                       {
+                               pcontact->interpolate_normals(coincident_normals, coincident_count);
+                               coincident_count = 0;
+                       }
+
+                       push_back(*scontact);
+                       pcontact = &back();
+               }
+               last_key = key;
+       }
+}
+
+void gim_contact_array::merge_contacts_unique(const gim_contact_array& contacts)
+{
+       clear();
+
+       if (contacts.size() == 1)
+       {
+               push_back(contacts.back());
+               return;
+       }
+
+       GIM_CONTACT average_contact = contacts.back();
+
+       for (GUINT i = 1; i < contacts.size(); i++)
+       {
+               average_contact.m_point += contacts[i].m_point;
+               average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
+       }
+
+       //divide
+       GREAL divide_average = 1.0f / ((GREAL)contacts.size());
+
+       average_contact.m_point *= divide_average;
+
+       average_contact.m_normal *= divide_average;
+
+       average_contact.m_depth = average_contact.m_normal.length();
+
+       average_contact.m_normal /= average_contact.m_depth;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_contact.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_contact.h
new file mode 100644 (file)
index 0000000..9deb28a
--- /dev/null
@@ -0,0 +1,168 @@
+#ifndef GIM_CONTACT_H_INCLUDED
+#define GIM_CONTACT_H_INCLUDED
+
+/*! \file gim_contact.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+#include "gim_geometry.h"
+#include "gim_radixsort.h"
+#include "gim_array.h"
+
+/**
+Configuration var for applying interpolation of  contact normals
+*/
+#ifndef NORMAL_CONTACT_AVERAGE
+#define NORMAL_CONTACT_AVERAGE 1
+#endif
+
+#ifndef CONTACT_DIFF_EPSILON
+#define CONTACT_DIFF_EPSILON 0.00001f
+#endif
+
+#ifndef BT_CONTACT_H_STRUCTS_INCLUDED
+
+/// Structure for collision results
+///Functions for managing and sorting contacts resulting from a collision query.
+///Contact lists must be create by calling \ref GIM_CREATE_CONTACT_LIST
+///After querys, contact lists must be destroy by calling \ref GIM_DYNARRAY_DESTROY
+///Contacts can be merge for avoid duplicate results by calling \ref gim_merge_contacts
+class GIM_CONTACT
+{
+public:
+       btVector3 m_point;
+       btVector3 m_normal;
+       GREAL m_depth;     //Positive value indicates interpenetration
+       GREAL m_distance;  //Padding not for use
+       GUINT m_feature1;  //Face number
+       GUINT m_feature2;  //Face number
+public:
+       GIM_CONTACT()
+       {
+       }
+
+       GIM_CONTACT(const GIM_CONTACT &contact) : m_point(contact.m_point),
+                                                                                         m_normal(contact.m_normal),
+                                                                                         m_depth(contact.m_depth),
+                                                                                         m_feature1(contact.m_feature1),
+                                                                                         m_feature2(contact.m_feature2)
+       {
+               m_point = contact.m_point;
+               m_normal = contact.m_normal;
+               m_depth = contact.m_depth;
+               m_feature1 = contact.m_feature1;
+               m_feature2 = contact.m_feature2;
+       }
+
+       GIM_CONTACT(const btVector3 &point, const btVector3 &normal,
+                               GREAL depth, GUINT feature1, GUINT feature2) : m_point(point),
+                                                                                                                          m_normal(normal),
+                                                                                                                          m_depth(depth),
+                                                                                                                          m_feature1(feature1),
+                                                                                                                          m_feature2(feature2)
+       {
+       }
+
+       //! Calcs key for coord classification
+       SIMD_FORCE_INLINE GUINT calc_key_contact() const
+       {
+               GINT _coords[] = {
+                       (GINT)(m_point[0] * 1000.0f + 1.0f),
+                       (GINT)(m_point[1] * 1333.0f),
+                       (GINT)(m_point[2] * 2133.0f + 3.0f)};
+               GUINT _hash = 0;
+               GUINT *_uitmp = (GUINT *)(&_coords[0]);
+               _hash = *_uitmp;
+               _uitmp++;
+               _hash += (*_uitmp) << 4;
+               _uitmp++;
+               _hash += (*_uitmp) << 8;
+               return _hash;
+       }
+
+       SIMD_FORCE_INLINE void interpolate_normals(btVector3 *normals, GUINT normal_count)
+       {
+               btVector3 vec_sum(m_normal);
+               for (GUINT i = 0; i < normal_count; i++)
+               {
+                       vec_sum += normals[i];
+               }
+
+               GREAL vec_sum_len = vec_sum.length2();
+               if (vec_sum_len < CONTACT_DIFF_EPSILON) return;
+
+               GIM_INV_SQRT(vec_sum_len, vec_sum_len);  // 1/sqrt(vec_sum_len)
+
+               m_normal = vec_sum * vec_sum_len;
+       }
+};
+
+#endif
+
+class gim_contact_array : public gim_array<GIM_CONTACT>
+{
+public:
+       gim_contact_array() : gim_array<GIM_CONTACT>(64)
+       {
+       }
+
+       SIMD_FORCE_INLINE void push_contact(const btVector3 &point, const btVector3 &normal,
+                                                                               GREAL depth, GUINT feature1, GUINT feature2)
+       {
+               push_back_mem();
+               GIM_CONTACT &newele = back();
+               newele.m_point = point;
+               newele.m_normal = normal;
+               newele.m_depth = depth;
+               newele.m_feature1 = feature1;
+               newele.m_feature2 = feature2;
+       }
+
+       SIMD_FORCE_INLINE void push_triangle_contacts(
+               const GIM_TRIANGLE_CONTACT_DATA &tricontact,
+               GUINT feature1, GUINT feature2)
+       {
+               for (GUINT i = 0; i < tricontact.m_point_count; i++)
+               {
+                       push_back_mem();
+                       GIM_CONTACT &newele = back();
+                       newele.m_point = tricontact.m_points[i];
+                       newele.m_normal = tricontact.m_separating_normal;
+                       newele.m_depth = tricontact.m_penetration_depth;
+                       newele.m_feature1 = feature1;
+                       newele.m_feature2 = feature2;
+               }
+       }
+
+       void merge_contacts(const gim_contact_array &contacts, bool normal_contact_average = true);
+       void merge_contacts_unique(const gim_contact_array &contacts);
+};
+
+#endif  // GIM_CONTACT_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_geom_types.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_geom_types.h
new file mode 100644 (file)
index 0000000..9dc48f3
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef GIM_GEOM_TYPES_H_INCLUDED
+#define GIM_GEOM_TYPES_H_INCLUDED
+
+/*! \file gim_geom_types.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_math.h"
+
+//! Short Integer vector 2D
+typedef GSHORT vec2s[2];
+//! Integer vector 3D
+typedef GSHORT vec3s[3];
+//! Integer vector 4D
+typedef GSHORT vec4s[4];
+
+//! Short Integer vector 2D
+typedef GUSHORT vec2us[2];
+//! Integer vector 3D
+typedef GUSHORT vec3us[3];
+//! Integer vector 4D
+typedef GUSHORT vec4us[4];
+
+//! Integer vector 2D
+typedef GINT vec2i[2];
+//! Integer vector 3D
+typedef GINT vec3i[3];
+//! Integer vector 4D
+typedef GINT vec4i[4];
+
+//! Unsigned Integer vector 2D
+typedef GUINT vec2ui[2];
+//! Unsigned Integer vector 3D
+typedef GUINT vec3ui[3];
+//! Unsigned Integer vector 4D
+typedef GUINT vec4ui[4];
+
+//! Float vector 2D
+typedef GREAL vec2f[2];
+//! Float vector 3D
+typedef GREAL vec3f[3];
+//! Float vector 4D
+typedef GREAL vec4f[4];
+
+//! Double vector 2D
+typedef GREAL2 vec2d[2];
+//! Float vector 3D
+typedef GREAL2 vec3d[3];
+//! Float vector 4D
+typedef GREAL2 vec4d[4];
+
+//! Matrix 2D, row ordered
+typedef GREAL mat2f[2][2];
+//! Matrix 3D, row ordered
+typedef GREAL mat3f[3][3];
+//! Matrix 4D, row ordered
+typedef GREAL mat4f[4][4];
+
+//! Quaternion
+typedef GREAL quatf[4];
+
+//typedef struct _aabb3f aabb3f;
+
+#endif  // GIM_GEOM_TYPES_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_geometry.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_geometry.h
new file mode 100644 (file)
index 0000000..4a7ac3c
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef GIM_GEOMETRY_H_INCLUDED
+#define GIM_GEOMETRY_H_INCLUDED
+
+/*! \file gim_geometry.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+///Additional Headers for Collision
+#include "gim_basic_geometry_operations.h"
+#include "gim_clip_polygon.h"
+#include "gim_box_collision.h"
+#include "gim_tri_collision.h"
+
+#endif  // GIM_VECTOR_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_hash_table.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_hash_table.h
new file mode 100644 (file)
index 0000000..abf88d3
--- /dev/null
@@ -0,0 +1,857 @@
+#ifndef GIM_HASH_TABLE_H_INCLUDED
+#define GIM_HASH_TABLE_H_INCLUDED
+/*! \file gim_trimesh_data.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_radixsort.h"
+
+#define GIM_INVALID_HASH 0xffffffff  //!< A very very high value
+#define GIM_DEFAULT_HASH_TABLE_SIZE 380
+#define GIM_DEFAULT_HASH_TABLE_NODE_SIZE 4
+#define GIM_HASH_TABLE_GROW_FACTOR 2
+
+#define GIM_MIN_RADIX_SORT_SIZE 860  //!< calibrated on a PIII
+
+template <typename T>
+struct GIM_HASH_TABLE_NODE
+{
+       GUINT m_key;
+       T m_data;
+       GIM_HASH_TABLE_NODE()
+       {
+       }
+
+       GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE& value)
+       {
+               m_key = value.m_key;
+               m_data = value.m_data;
+       }
+
+       GIM_HASH_TABLE_NODE(GUINT key, const T& data)
+       {
+               m_key = key;
+               m_data = data;
+       }
+
+       bool operator<(const GIM_HASH_TABLE_NODE<T>& other) const
+       {
+               ///inverse order, further objects are first
+               if (m_key < other.m_key) return true;
+               return false;
+       }
+
+       bool operator>(const GIM_HASH_TABLE_NODE<T>& other) const
+       {
+               ///inverse order, further objects are first
+               if (m_key > other.m_key) return true;
+               return false;
+       }
+
+       bool operator==(const GIM_HASH_TABLE_NODE<T>& other) const
+       {
+               ///inverse order, further objects are first
+               if (m_key == other.m_key) return true;
+               return false;
+       }
+};
+
+///Macro for getting the key
+class GIM_HASH_NODE_GET_KEY
+{
+public:
+       template <class T>
+       inline GUINT operator()(const T& a)
+       {
+               return a.m_key;
+       }
+};
+
+///Macro for comparing the key and the element
+class GIM_HASH_NODE_CMP_KEY_MACRO
+{
+public:
+       template <class T>
+       inline int operator()(const T& a, GUINT key)
+       {
+               return ((int)(a.m_key - key));
+       }
+};
+
+///Macro for comparing Hash nodes
+class GIM_HASH_NODE_CMP_MACRO
+{
+public:
+       template <class T>
+       inline int operator()(const T& a, const T& b)
+       {
+               return ((int)(a.m_key - b.m_key));
+       }
+};
+
+//! Sorting for hash table
+/*!
+switch automatically between quicksort and radixsort
+*/
+template <typename T>
+void gim_sort_hash_node_array(T* array, GUINT array_count)
+{
+       if (array_count < GIM_MIN_RADIX_SORT_SIZE)
+       {
+               gim_heap_sort(array, array_count, GIM_HASH_NODE_CMP_MACRO());
+       }
+       else
+       {
+               memcopy_elements_func cmpfunc;
+               gim_radix_sort(array, array_count, GIM_HASH_NODE_GET_KEY(), cmpfunc);
+       }
+}
+
+// Note: assumes long is at least 32 bits.
+#define GIM_NUM_PRIME 28
+
+static const GUINT gim_prime_list[GIM_NUM_PRIME] =
+       {
+               53ul, 97ul, 193ul, 389ul, 769ul,
+               1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
+               49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
+               1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
+               50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
+               1610612741ul, 3221225473ul, 4294967291ul};
+
+inline GUINT gim_next_prime(GUINT number)
+{
+       //Find nearest upper prime
+       GUINT result_ind = 0;
+       gim_binary_search(gim_prime_list, 0, (GIM_NUM_PRIME - 2), number, result_ind);
+
+       // inv: result_ind < 28
+       return gim_prime_list[result_ind];
+}
+
+//! A compact hash table implementation
+/*!
+A memory aligned compact hash table that coud be treated as an array.
+It could be a simple sorted array without the overhead of the hash key bucked, or could
+be a formely hash table with an array of keys.
+You can use switch_to_hashtable() and switch_to_sorted_array for saving space or increase speed.
+</br>
+
+<ul>
+<li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
+When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
+<li> If node_size != 0, then this container becomes a hash table for ever
+</ul>
+
+*/
+template <class T>
+class gim_hash_table
+{
+protected:
+       typedef GIM_HASH_TABLE_NODE<T> _node_type;
+
+       //!The nodes
+       //array< _node_type, SuperAllocator<_node_type> > m_nodes;
+       gim_array<_node_type> m_nodes;
+       //SuperBufferedArray< _node_type > m_nodes;
+       bool m_sorted;
+
+       ///Hash table data management. The hash table has the indices to the corresponding m_nodes array
+       GUINT* m_hash_table;  //!<
+       GUINT m_table_size;   //!<
+       GUINT m_node_size;    //!<
+       GUINT m_min_hash_table_size;
+
+       //! Returns the cell index
+       inline GUINT _find_cell(GUINT hashkey)
+       {
+               _node_type* nodesptr = m_nodes.pointer();
+               GUINT start_index = (hashkey % m_table_size) * m_node_size;
+               GUINT end_index = start_index + m_node_size;
+
+               while (start_index < end_index)
+               {
+                       GUINT value = m_hash_table[start_index];
+                       if (value != GIM_INVALID_HASH)
+                       {
+                               if (nodesptr[value].m_key == hashkey) return start_index;
+                       }
+                       start_index++;
+               }
+               return GIM_INVALID_HASH;
+       }
+
+       //! Find the avaliable cell for the hashkey, and return an existing cell if it has the same hash key
+       inline GUINT _find_avaliable_cell(GUINT hashkey)
+       {
+               _node_type* nodesptr = m_nodes.pointer();
+               GUINT avaliable_index = GIM_INVALID_HASH;
+               GUINT start_index = (hashkey % m_table_size) * m_node_size;
+               GUINT end_index = start_index + m_node_size;
+
+               while (start_index < end_index)
+               {
+                       GUINT value = m_hash_table[start_index];
+                       if (value == GIM_INVALID_HASH)
+                       {
+                               if (avaliable_index == GIM_INVALID_HASH)
+                               {
+                                       avaliable_index = start_index;
+                               }
+                       }
+                       else if (nodesptr[value].m_key == hashkey)
+                       {
+                               return start_index;
+                       }
+                       start_index++;
+               }
+               return avaliable_index;
+       }
+
+       //! reserves the memory for the hash table.
+       /*!
+    \pre hash table must be empty
+    \post reserves the memory for the hash table, an initializes all elements to GIM_INVALID_HASH.
+    */
+       inline void _reserve_table_memory(GUINT newtablesize)
+       {
+               if (newtablesize == 0) return;
+               if (m_node_size == 0) return;
+
+               //Get a Prime size
+
+               m_table_size = gim_next_prime(newtablesize);
+
+               GUINT datasize = m_table_size * m_node_size;
+               //Alloc the data buffer
+               m_hash_table = (GUINT*)gim_alloc(datasize * sizeof(GUINT));
+       }
+
+       inline void _invalidate_keys()
+       {
+               GUINT datasize = m_table_size * m_node_size;
+               for (GUINT i = 0; i < datasize; i++)
+               {
+                       m_hash_table[i] = GIM_INVALID_HASH;  // invalidate keys
+               }
+       }
+
+       //! Clear all memory for the hash table
+       inline void _clear_table_memory()
+       {
+               if (m_hash_table == NULL) return;
+               gim_free(m_hash_table);
+               m_hash_table = NULL;
+               m_table_size = 0;
+       }
+
+       //! Invalidates the keys (Assigning GIM_INVALID_HASH to all) Reorders the hash keys
+       inline void _rehash()
+       {
+               _invalidate_keys();
+
+               _node_type* nodesptr = m_nodes.pointer();
+               for (GUINT i = 0; i < (GUINT)m_nodes.size(); i++)
+               {
+                       GUINT nodekey = nodesptr[i].m_key;
+                       if (nodekey != GIM_INVALID_HASH)
+                       {
+                               //Search for the avaliable cell in buffer
+                               GUINT index = _find_avaliable_cell(nodekey);
+
+                               if (m_hash_table[index] != GIM_INVALID_HASH)
+                               {  //The new index is alreade used... discard this new incomming object, repeated key
+                                       btAssert(m_hash_table[index] == nodekey);
+                                       nodesptr[i].m_key = GIM_INVALID_HASH;
+                               }
+                               else
+                               {
+                                       //;
+                                       //Assign the value for alloc
+                                       m_hash_table[index] = i;
+                               }
+                       }
+               }
+       }
+
+       //! Resize hash table indices
+       inline void _resize_table(GUINT newsize)
+       {
+               //Clear memory
+               _clear_table_memory();
+               //Alloc the data
+               _reserve_table_memory(newsize);
+               //Invalidate keys and rehash
+               _rehash();
+       }
+
+       //! Destroy hash table memory
+       inline void _destroy()
+       {
+               if (m_hash_table == NULL) return;
+               _clear_table_memory();
+       }
+
+       //! Finds an avaliable hash table cell, and resizes the table if there isn't space
+       inline GUINT _assign_hash_table_cell(GUINT hashkey)
+       {
+               GUINT cell_index = _find_avaliable_cell(hashkey);
+
+               if (cell_index == GIM_INVALID_HASH)
+               {
+                       //rehashing
+                       _resize_table(m_table_size + 1);
+                       GUINT cell_index = _find_avaliable_cell(hashkey);
+                       btAssert(cell_index != GIM_INVALID_HASH);
+               }
+               return cell_index;
+       }
+
+       //! erase by index in hash table
+       inline bool _erase_by_index_hash_table(GUINT index)
+       {
+               if (index >= m_nodes.size()) return false;
+               if (m_nodes[index].m_key != GIM_INVALID_HASH)
+               {
+                       //Search for the avaliable cell in buffer
+                       GUINT cell_index = _find_cell(m_nodes[index].m_key);
+
+                       btAssert(cell_index != GIM_INVALID_HASH);
+                       btAssert(m_hash_table[cell_index] == index);
+
+                       m_hash_table[cell_index] = GIM_INVALID_HASH;
+               }
+
+               return this->_erase_unsorted(index);
+       }
+
+       //! erase by key in hash table
+       inline bool _erase_hash_table(GUINT hashkey)
+       {
+               if (hashkey == GIM_INVALID_HASH) return false;
+
+               //Search for the avaliable cell in buffer
+               GUINT cell_index = _find_cell(hashkey);
+               if (cell_index == GIM_INVALID_HASH) return false;
+
+               GUINT index = m_hash_table[cell_index];
+               m_hash_table[cell_index] = GIM_INVALID_HASH;
+
+               return this->_erase_unsorted(index);
+       }
+
+       //! insert an element in hash table
+       /*!
+    If the element exists, this won't insert the element
+    \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
+    If so, the element has been inserted at the last position of the array.
+    */
+       inline GUINT _insert_hash_table(GUINT hashkey, const T& value)
+       {
+               if (hashkey == GIM_INVALID_HASH)
+               {
+                       //Insert anyway
+                       _insert_unsorted(hashkey, value);
+                       return GIM_INVALID_HASH;
+               }
+
+               GUINT cell_index = _assign_hash_table_cell(hashkey);
+
+               GUINT value_key = m_hash_table[cell_index];
+
+               if (value_key != GIM_INVALID_HASH) return value_key;  // Not overrited
+
+               m_hash_table[cell_index] = m_nodes.size();
+
+               _insert_unsorted(hashkey, value);
+               return GIM_INVALID_HASH;
+       }
+
+       //! insert an element in hash table.
+       /*!
+    If the element exists, this replaces the element.
+    \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
+    If so, the element has been inserted at the last position of the array.
+    */
+       inline GUINT _insert_hash_table_replace(GUINT hashkey, const T& value)
+       {
+               if (hashkey == GIM_INVALID_HASH)
+               {
+                       //Insert anyway
+                       _insert_unsorted(hashkey, value);
+                       return GIM_INVALID_HASH;
+               }
+
+               GUINT cell_index = _assign_hash_table_cell(hashkey);
+
+               GUINT value_key = m_hash_table[cell_index];
+
+               if (value_key != GIM_INVALID_HASH)
+               {  //replaces the existing
+                       m_nodes[value_key] = _node_type(hashkey, value);
+                       return value_key;  // index of the replaced element
+               }
+
+               m_hash_table[cell_index] = m_nodes.size();
+
+               _insert_unsorted(hashkey, value);
+               return GIM_INVALID_HASH;
+       }
+
+       ///Sorted array data management. The hash table has the indices to the corresponding m_nodes array
+       inline bool _erase_sorted(GUINT index)
+       {
+               if (index >= (GUINT)m_nodes.size()) return false;
+               m_nodes.erase_sorted(index);
+               if (m_nodes.size() < 2) m_sorted = false;
+               return true;
+       }
+
+       //! faster, but unsorted
+       inline bool _erase_unsorted(GUINT index)
+       {
+               if (index >= m_nodes.size()) return false;
+
+               GUINT lastindex = m_nodes.size() - 1;
+               if (index < lastindex && m_hash_table != 0)
+               {
+                       GUINT hashkey = m_nodes[lastindex].m_key;
+                       if (hashkey != GIM_INVALID_HASH)
+                       {
+                               //update the new position of the last element
+                               GUINT cell_index = _find_cell(hashkey);
+                               btAssert(cell_index != GIM_INVALID_HASH);
+                               //new position of the last element which will be swaped
+                               m_hash_table[cell_index] = index;
+                       }
+               }
+               m_nodes.erase(index);
+               m_sorted = false;
+               return true;
+       }
+
+       //! Insert in position ordered
+       /*!
+    Also checks if it is needed to transform this container to a hash table, by calling check_for_switching_to_hashtable
+    */
+       inline void _insert_in_pos(GUINT hashkey, const T& value, GUINT pos)
+       {
+               m_nodes.insert(_node_type(hashkey, value), pos);
+               this->check_for_switching_to_hashtable();
+       }
+
+       //! Insert an element in an ordered array
+       inline GUINT _insert_sorted(GUINT hashkey, const T& value)
+       {
+               if (hashkey == GIM_INVALID_HASH || size() == 0)
+               {
+                       m_nodes.push_back(_node_type(hashkey, value));
+                       return GIM_INVALID_HASH;
+               }
+               //Insert at last position
+               //Sort element
+
+               GUINT result_ind = 0;
+               GUINT last_index = m_nodes.size() - 1;
+               _node_type* ptr = m_nodes.pointer();
+
+               bool found = gim_binary_search_ex(
+                       ptr, 0, last_index, result_ind, hashkey, GIM_HASH_NODE_CMP_KEY_MACRO());
+
+               //Insert before found index
+               if (found)
+               {
+                       return result_ind;
+               }
+               else
+               {
+                       _insert_in_pos(hashkey, value, result_ind);
+               }
+               return GIM_INVALID_HASH;
+       }
+
+       inline GUINT _insert_sorted_replace(GUINT hashkey, const T& value)
+       {
+               if (hashkey == GIM_INVALID_HASH || size() == 0)
+               {
+                       m_nodes.push_back(_node_type(hashkey, value));
+                       return GIM_INVALID_HASH;
+               }
+               //Insert at last position
+               //Sort element
+               GUINT result_ind;
+               GUINT last_index = m_nodes.size() - 1;
+               _node_type* ptr = m_nodes.pointer();
+
+               bool found = gim_binary_search_ex(
+                       ptr, 0, last_index, result_ind, hashkey, GIM_HASH_NODE_CMP_KEY_MACRO());
+
+               //Insert before found index
+               if (found)
+               {
+                       m_nodes[result_ind] = _node_type(hashkey, value);
+               }
+               else
+               {
+                       _insert_in_pos(hashkey, value, result_ind);
+               }
+               return result_ind;
+       }
+
+       //! Fast insertion in m_nodes array
+       inline GUINT _insert_unsorted(GUINT hashkey, const T& value)
+       {
+               m_nodes.push_back(_node_type(hashkey, value));
+               m_sorted = false;
+               return GIM_INVALID_HASH;
+       }
+
+public:
+       /*!
+        <li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
+        When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
+        <li> If node_size != 0, then this container becomes a hash table for ever
+        </ul>
+    */
+       gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE,
+                                  GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE,
+                                  GUINT min_hash_table_size = GIM_INVALID_HASH)
+       {
+               m_hash_table = NULL;
+               m_table_size = 0;
+               m_sorted = false;
+               m_node_size = node_size;
+               m_min_hash_table_size = min_hash_table_size;
+
+               if (m_node_size != 0)
+               {
+                       if (reserve_size != 0)
+                       {
+                               m_nodes.reserve(reserve_size);
+                               _reserve_table_memory(reserve_size);
+                               _invalidate_keys();
+                       }
+                       else
+                       {
+                               m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE);
+                               _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE);
+                               _invalidate_keys();
+                       }
+               }
+               else if (reserve_size != 0)
+               {
+                       m_nodes.reserve(reserve_size);
+               }
+       }
+
+       ~gim_hash_table()
+       {
+               _destroy();
+       }
+
+       inline bool is_hash_table()
+       {
+               if (m_hash_table) return true;
+               return false;
+       }
+
+       inline bool is_sorted()
+       {
+               if (size() < 2) return true;
+               return m_sorted;
+       }
+
+       bool sort()
+       {
+               if (is_sorted()) return true;
+               if (m_nodes.size() < 2) return false;
+
+               _node_type* ptr = m_nodes.pointer();
+               GUINT siz = m_nodes.size();
+               gim_sort_hash_node_array(ptr, siz);
+               m_sorted = true;
+
+               if (m_hash_table)
+               {
+                       _rehash();
+               }
+               return true;
+       }
+
+       bool switch_to_hashtable()
+       {
+               if (m_hash_table) return false;
+               if (m_node_size == 0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
+               if (m_nodes.size() < GIM_DEFAULT_HASH_TABLE_SIZE)
+               {
+                       _resize_table(GIM_DEFAULT_HASH_TABLE_SIZE);
+               }
+               else
+               {
+                       _resize_table(m_nodes.size() + 1);
+               }
+
+               return true;
+       }
+
+       bool switch_to_sorted_array()
+       {
+               if (m_hash_table == NULL) return true;
+               _clear_table_memory();
+               return sort();
+       }
+
+       //!If the container reaches the
+       bool check_for_switching_to_hashtable()
+       {
+               if (this->m_hash_table) return true;
+
+               if (!(m_nodes.size() < m_min_hash_table_size))
+               {
+                       if (m_node_size == 0)
+                       {
+                               m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
+                       }
+
+                       _resize_table(m_nodes.size() + 1);
+                       return true;
+               }
+               return false;
+       }
+
+       inline void set_sorted(bool value)
+       {
+               m_sorted = value;
+       }
+
+       //! Retrieves the amount of keys.
+       inline GUINT size() const
+       {
+               return m_nodes.size();
+       }
+
+       //! Retrieves the hash key.
+       inline GUINT get_key(GUINT index) const
+       {
+               return m_nodes[index].m_key;
+       }
+
+       //! Retrieves the value by index
+       /*!
+    */
+       inline T* get_value_by_index(GUINT index)
+       {
+               return &m_nodes[index].m_data;
+       }
+
+       inline const T& operator[](GUINT index) const
+       {
+               return m_nodes[index].m_data;
+       }
+
+       inline T& operator[](GUINT index)
+       {
+               return m_nodes[index].m_data;
+       }
+
+       //! Finds the index of the element with the key
+       /*!
+    \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
+    If so, the element has been inserted at the last position of the array.
+    */
+       inline GUINT find(GUINT hashkey)
+       {
+               if (m_hash_table)
+               {
+                       GUINT cell_index = _find_cell(hashkey);
+                       if (cell_index == GIM_INVALID_HASH) return GIM_INVALID_HASH;
+                       return m_hash_table[cell_index];
+               }
+               GUINT last_index = m_nodes.size();
+               if (last_index < 2)
+               {
+                       if (last_index == 0) return GIM_INVALID_HASH;
+                       if (m_nodes[0].m_key == hashkey) return 0;
+                       return GIM_INVALID_HASH;
+               }
+               else if (m_sorted)
+               {
+                       //Binary search
+                       GUINT result_ind = 0;
+                       last_index--;
+                       _node_type* ptr = m_nodes.pointer();
+
+                       bool found = gim_binary_search_ex(ptr, 0, last_index, result_ind, hashkey, GIM_HASH_NODE_CMP_KEY_MACRO());
+
+                       if (found) return result_ind;
+               }
+               return GIM_INVALID_HASH;
+       }
+
+       //! Retrieves the value associated with the index
+       /*!
+    \return the found element, or null
+    */
+       inline T* get_value(GUINT hashkey)
+       {
+               GUINT index = find(hashkey);
+               if (index == GIM_INVALID_HASH) return NULL;
+               return &m_nodes[index].m_data;
+       }
+
+       /*!
+    */
+       inline bool erase_by_index(GUINT index)
+       {
+               if (index > m_nodes.size()) return false;
+
+               if (m_hash_table == NULL)
+               {
+                       if (is_sorted())
+                       {
+                               return this->_erase_sorted(index);
+                       }
+                       else
+                       {
+                               return this->_erase_unsorted(index);
+                       }
+               }
+               else
+               {
+                       return this->_erase_by_index_hash_table(index);
+               }
+               return false;
+       }
+
+       inline bool erase_by_index_unsorted(GUINT index)
+       {
+               if (index > m_nodes.size()) return false;
+
+               if (m_hash_table == NULL)
+               {
+                       return this->_erase_unsorted(index);
+               }
+               else
+               {
+                       return this->_erase_by_index_hash_table(index);
+               }
+               return false;
+       }
+
+       /*!
+
+    */
+       inline bool erase_by_key(GUINT hashkey)
+       {
+               if (size() == 0) return false;
+
+               if (m_hash_table)
+               {
+                       return this->_erase_hash_table(hashkey);
+               }
+               //Binary search
+
+               if (is_sorted() == false) return false;
+
+               GUINT result_ind = find(hashkey);
+               if (result_ind != GIM_INVALID_HASH)
+               {
+                       return this->_erase_sorted(result_ind);
+               }
+               return false;
+       }
+
+       void clear()
+       {
+               m_nodes.clear();
+
+               if (m_hash_table == NULL) return;
+               GUINT datasize = m_table_size * m_node_size;
+               //Initialize the hashkeys.
+               GUINT i;
+               for (i = 0; i < datasize; i++)
+               {
+                       m_hash_table[i] = GIM_INVALID_HASH;  // invalidate keys
+               }
+               m_sorted = false;
+       }
+
+       //! Insert an element into the hash
+       /*!
+    \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
+    of the existing element.
+    */
+       inline GUINT insert(GUINT hashkey, const T& element)
+       {
+               if (m_hash_table)
+               {
+                       return this->_insert_hash_table(hashkey, element);
+               }
+               if (this->is_sorted())
+               {
+                       return this->_insert_sorted(hashkey, element);
+               }
+               return this->_insert_unsorted(hashkey, element);
+       }
+
+       //! Insert an element into the hash, and could overrite an existing object with the same hash.
+       /*!
+    \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
+    of the replaced element.
+    */
+       inline GUINT insert_override(GUINT hashkey, const T& element)
+       {
+               if (m_hash_table)
+               {
+                       return this->_insert_hash_table_replace(hashkey, element);
+               }
+               if (this->is_sorted())
+               {
+                       return this->_insert_sorted_replace(hashkey, element);
+               }
+               this->_insert_unsorted(hashkey, element);
+               return m_nodes.size();
+       }
+
+       //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted
+       /*!
+    */
+       inline GUINT insert_unsorted(GUINT hashkey, const T& element)
+       {
+               if (m_hash_table)
+               {
+                       return this->_insert_hash_table(hashkey, element);
+               }
+               return this->_insert_unsorted(hashkey, element);
+       }
+};
+
+#endif  // GIM_CONTAINERS_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_linear_math.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_linear_math.h
new file mode 100644 (file)
index 0000000..98401a4
--- /dev/null
@@ -0,0 +1,1488 @@
+#ifndef GIM_LINEAR_H_INCLUDED
+#define GIM_LINEAR_H_INCLUDED
+
+/*! \file gim_linear_math.h
+*\author Francisco Leon Najera
+Type Independant Vector and matrix operations.
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_math.h"
+#include "gim_geom_types.h"
+
+//! Zero out a 2D vector
+#define VEC_ZERO_2(a)           \
+       {                           \
+               (a)[0] = (a)[1] = 0.0f; \
+       }
+
+//! Zero out a 3D vector
+#define VEC_ZERO(a)                      \
+       {                                    \
+               (a)[0] = (a)[1] = (a)[2] = 0.0f; \
+       }
+
+/// Zero out a 4D vector
+#define VEC_ZERO_4(a)                             \
+       {                                             \
+               (a)[0] = (a)[1] = (a)[2] = (a)[3] = 0.0f; \
+       }
+
+/// Vector copy
+#define VEC_COPY_2(b, a) \
+       {                    \
+               (b)[0] = (a)[0]; \
+               (b)[1] = (a)[1]; \
+       }
+
+/// Copy 3D vector
+#define VEC_COPY(b, a)   \
+       {                    \
+               (b)[0] = (a)[0]; \
+               (b)[1] = (a)[1]; \
+               (b)[2] = (a)[2]; \
+       }
+
+/// Copy 4D vector
+#define VEC_COPY_4(b, a) \
+       {                    \
+               (b)[0] = (a)[0]; \
+               (b)[1] = (a)[1]; \
+               (b)[2] = (a)[2]; \
+               (b)[3] = (a)[3]; \
+       }
+
+/// VECTOR SWAP
+#define VEC_SWAP(b, a)                    \
+       {                                     \
+               GIM_SWAP_NUMBERS((b)[0], (a)[0]); \
+               GIM_SWAP_NUMBERS((b)[1], (a)[1]); \
+               GIM_SWAP_NUMBERS((b)[2], (a)[2]); \
+       }
+
+/// Vector difference
+#define VEC_DIFF_2(v21, v2, v1)       \
+       {                                 \
+               (v21)[0] = (v2)[0] - (v1)[0]; \
+               (v21)[1] = (v2)[1] - (v1)[1]; \
+       }
+
+/// Vector difference
+#define VEC_DIFF(v21, v2, v1)         \
+       {                                 \
+               (v21)[0] = (v2)[0] - (v1)[0]; \
+               (v21)[1] = (v2)[1] - (v1)[1]; \
+               (v21)[2] = (v2)[2] - (v1)[2]; \
+       }
+
+/// Vector difference
+#define VEC_DIFF_4(v21, v2, v1)       \
+       {                                 \
+               (v21)[0] = (v2)[0] - (v1)[0]; \
+               (v21)[1] = (v2)[1] - (v1)[1]; \
+               (v21)[2] = (v2)[2] - (v1)[2]; \
+               (v21)[3] = (v2)[3] - (v1)[3]; \
+       }
+
+/// Vector sum
+#define VEC_SUM_2(v21, v2, v1)        \
+       {                                 \
+               (v21)[0] = (v2)[0] + (v1)[0]; \
+               (v21)[1] = (v2)[1] + (v1)[1]; \
+       }
+
+/// Vector sum
+#define VEC_SUM(v21, v2, v1)          \
+       {                                 \
+               (v21)[0] = (v2)[0] + (v1)[0]; \
+               (v21)[1] = (v2)[1] + (v1)[1]; \
+               (v21)[2] = (v2)[2] + (v1)[2]; \
+       }
+
+/// Vector sum
+#define VEC_SUM_4(v21, v2, v1)        \
+       {                                 \
+               (v21)[0] = (v2)[0] + (v1)[0]; \
+               (v21)[1] = (v2)[1] + (v1)[1]; \
+               (v21)[2] = (v2)[2] + (v1)[2]; \
+               (v21)[3] = (v2)[3] + (v1)[3]; \
+       }
+
+/// scalar times vector
+#define VEC_SCALE_2(c, a, b)   \
+       {                          \
+               (c)[0] = (a) * (b)[0]; \
+               (c)[1] = (a) * (b)[1]; \
+       }
+
+/// scalar times vector
+#define VEC_SCALE(c, a, b)     \
+       {                          \
+               (c)[0] = (a) * (b)[0]; \
+               (c)[1] = (a) * (b)[1]; \
+               (c)[2] = (a) * (b)[2]; \
+       }
+
+/// scalar times vector
+#define VEC_SCALE_4(c, a, b)   \
+       {                          \
+               (c)[0] = (a) * (b)[0]; \
+               (c)[1] = (a) * (b)[1]; \
+               (c)[2] = (a) * (b)[2]; \
+               (c)[3] = (a) * (b)[3]; \
+       }
+
+/// accumulate scaled vector
+#define VEC_ACCUM_2(c, a, b)    \
+       {                           \
+               (c)[0] += (a) * (b)[0]; \
+               (c)[1] += (a) * (b)[1]; \
+       }
+
+/// accumulate scaled vector
+#define VEC_ACCUM(c, a, b)      \
+       {                           \
+               (c)[0] += (a) * (b)[0]; \
+               (c)[1] += (a) * (b)[1]; \
+               (c)[2] += (a) * (b)[2]; \
+       }
+
+/// accumulate scaled vector
+#define VEC_ACCUM_4(c, a, b)    \
+       {                           \
+               (c)[0] += (a) * (b)[0]; \
+               (c)[1] += (a) * (b)[1]; \
+               (c)[2] += (a) * (b)[2]; \
+               (c)[3] += (a) * (b)[3]; \
+       }
+
+/// Vector dot product
+#define VEC_DOT_2(a, b) ((a)[0] * (b)[0] + (a)[1] * (b)[1])
+
+/// Vector dot product
+#define VEC_DOT(a, b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2])
+
+/// Vector dot product
+#define VEC_DOT_4(a, b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2] + (a)[3] * (b)[3])
+
+/// vector impact parameter (squared)
+#define VEC_IMPACT_SQ(bsq, direction, position)              \
+       {                                                        \
+               GREAL _llel_ = VEC_DOT(direction, position);         \
+               bsq = VEC_DOT(position, position) - _llel_ * _llel_; \
+       }
+
+/// vector impact parameter
+#define VEC_IMPACT(bsq, direction, position)     \
+       {                                            \
+               VEC_IMPACT_SQ(bsq, direction, position); \
+               GIM_SQRT(bsq, bsq);                      \
+       }
+
+/// Vector length
+#define VEC_LENGTH_2(a, l)           \
+       {                                \
+               GREAL _pp = VEC_DOT_2(a, a); \
+               GIM_SQRT(_pp, l);            \
+       }
+
+/// Vector length
+#define VEC_LENGTH(a, l)           \
+       {                              \
+               GREAL _pp = VEC_DOT(a, a); \
+               GIM_SQRT(_pp, l);          \
+       }
+
+/// Vector length
+#define VEC_LENGTH_4(a, l)           \
+       {                                \
+               GREAL _pp = VEC_DOT_4(a, a); \
+               GIM_SQRT(_pp, l);            \
+       }
+
+/// Vector inv length
+#define VEC_INV_LENGTH_2(a, l)       \
+       {                                \
+               GREAL _pp = VEC_DOT_2(a, a); \
+               GIM_INV_SQRT(_pp, l);        \
+       }
+
+/// Vector inv length
+#define VEC_INV_LENGTH(a, l)       \
+       {                              \
+               GREAL _pp = VEC_DOT(a, a); \
+               GIM_INV_SQRT(_pp, l);      \
+       }
+
+/// Vector inv length
+#define VEC_INV_LENGTH_4(a, l)       \
+       {                                \
+               GREAL _pp = VEC_DOT_4(a, a); \
+               GIM_INV_SQRT(_pp, l);        \
+       }
+
+/// distance between two points
+#define VEC_DISTANCE(_len, _va, _vb) \
+       {                                \
+               vec3f _tmp_;                 \
+               VEC_DIFF(_tmp_, _vb, _va);   \
+               VEC_LENGTH(_tmp_, _len);     \
+       }
+
+/// Vector length
+#define VEC_CONJUGATE_LENGTH(a, l)                                 \
+       {                                                              \
+               GREAL _pp = 1.0 - a[0] * a[0] - a[1] * a[1] - a[2] * a[2]; \
+               GIM_SQRT(_pp, l);                                          \
+       }
+
+/// Vector length
+#define VEC_NORMALIZE(a)           \
+       {                              \
+               GREAL len;                 \
+               VEC_INV_LENGTH(a, len);    \
+               if (len < G_REAL_INFINITY) \
+               {                          \
+                       a[0] *= len;           \
+                       a[1] *= len;           \
+                       a[2] *= len;           \
+               }                          \
+       }
+
+/// Set Vector size
+#define VEC_RENORMALIZE(a, newlen) \
+       {                              \
+               GREAL len;                 \
+               VEC_INV_LENGTH(a, len);    \
+               if (len < G_REAL_INFINITY) \
+               {                          \
+                       len *= newlen;         \
+                       a[0] *= len;           \
+                       a[1] *= len;           \
+                       a[2] *= len;           \
+               }                          \
+       }
+
+/// Vector cross
+#define VEC_CROSS(c, a, b)                        \
+       {                                             \
+               c[0] = (a)[1] * (b)[2] - (a)[2] * (b)[1]; \
+               c[1] = (a)[2] * (b)[0] - (a)[0] * (b)[2]; \
+               c[2] = (a)[0] * (b)[1] - (a)[1] * (b)[0]; \
+       }
+
+/*! Vector perp -- assumes that n is of unit length
+ * accepts vector v, subtracts out any component parallel to n */
+#define VEC_PERPENDICULAR(vp, v, n)    \
+       {                                  \
+               GREAL dot = VEC_DOT(v, n);     \
+               vp[0] = (v)[0] - dot * (n)[0]; \
+               vp[1] = (v)[1] - dot * (n)[1]; \
+               vp[2] = (v)[2] - dot * (n)[2]; \
+       }
+
+/*! Vector parallel -- assumes that n is of unit length */
+#define VEC_PARALLEL(vp, v, n)     \
+       {                              \
+               GREAL dot = VEC_DOT(v, n); \
+               vp[0] = (dot) * (n)[0];    \
+               vp[1] = (dot) * (n)[1];    \
+               vp[2] = (dot) * (n)[2];    \
+       }
+
+/*! Same as Vector parallel --  n can have any length
+ * accepts vector v, subtracts out any component perpendicular to n */
+#define VEC_PROJECT(vp, v, n)         \
+       {                                 \
+               GREAL scalar = VEC_DOT(v, n); \
+               scalar /= VEC_DOT(n, n);      \
+               vp[0] = (scalar) * (n)[0];    \
+               vp[1] = (scalar) * (n)[1];    \
+               vp[2] = (scalar) * (n)[2];    \
+       }
+
+/*! accepts vector v*/
+#define VEC_UNPROJECT(vp, v, n)          \
+       {                                    \
+               GREAL scalar = VEC_DOT(v, n);    \
+               scalar = VEC_DOT(n, n) / scalar; \
+               vp[0] = (scalar) * (n)[0];       \
+               vp[1] = (scalar) * (n)[1];       \
+               vp[2] = (scalar) * (n)[2];       \
+       }
+
+/*! Vector reflection -- assumes n is of unit length
+ Takes vector v, reflects it against reflector n, and returns vr */
+#define VEC_REFLECT(vr, v, n)                  \
+       {                                          \
+               GREAL dot = VEC_DOT(v, n);             \
+               vr[0] = (v)[0] - 2.0 * (dot) * (n)[0]; \
+               vr[1] = (v)[1] - 2.0 * (dot) * (n)[1]; \
+               vr[2] = (v)[2] - 2.0 * (dot) * (n)[2]; \
+       }
+
+/*! Vector blending
+Takes two vectors a, b, blends them together with two scalars */
+#define VEC_BLEND_AB(vr, sa, a, sb, b)         \
+       {                                          \
+               vr[0] = (sa) * (a)[0] + (sb) * (b)[0]; \
+               vr[1] = (sa) * (a)[1] + (sb) * (b)[1]; \
+               vr[2] = (sa) * (a)[2] + (sb) * (b)[2]; \
+       }
+
+/*! Vector blending
+Takes two vectors a, b, blends them together with s <=1 */
+#define VEC_BLEND(vr, a, b, s) VEC_BLEND_AB(vr, (1 - s), a, s, b)
+
+#define VEC_SET3(a, b, op, c) \
+       a[0] = b[0] op c[0];      \
+       a[1] = b[1] op c[1];      \
+       a[2] = b[2] op c[2];
+
+//! Finds the bigger cartesian coordinate from a vector
+#define VEC_MAYOR_COORD(vec, maxc)                                          \
+       {                                                                       \
+               GREAL A[] = {fabs(vec[0]), fabs(vec[1]), fabs(vec[2])};             \
+               maxc = A[0] > A[1] ? (A[0] > A[2] ? 0 : 2) : (A[1] > A[2] ? 1 : 2); \
+       }
+
+//! Finds the 2 smallest cartesian coordinates from a vector
+#define VEC_MINOR_AXES(vec, i0, i1) \
+       {                               \
+               VEC_MAYOR_COORD(vec, i0);   \
+               i0 = (i0 + 1) % 3;          \
+               i1 = (i0 + 1) % 3;          \
+       }
+
+#define VEC_EQUAL(v1, v2) (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2])
+
+#define VEC_NEAR_EQUAL(v1, v2) (GIM_NEAR_EQUAL(v1[0], v2[0]) && GIM_NEAR_EQUAL(v1[1], v2[1]) && GIM_NEAR_EQUAL(v1[2], v2[2]))
+
+/// Vector cross
+#define X_AXIS_CROSS_VEC(dst, src) \
+       {                              \
+               dst[0] = 0.0f;             \
+               dst[1] = -src[2];          \
+               dst[2] = src[1];           \
+       }
+
+#define Y_AXIS_CROSS_VEC(dst, src) \
+       {                              \
+               dst[0] = src[2];           \
+               dst[1] = 0.0f;             \
+               dst[2] = -src[0];          \
+       }
+
+#define Z_AXIS_CROSS_VEC(dst, src) \
+       {                              \
+               dst[0] = -src[1];          \
+               dst[1] = src[0];           \
+               dst[2] = 0.0f;             \
+       }
+
+/// initialize matrix
+#define IDENTIFY_MATRIX_3X3(m) \
+       {                          \
+               m[0][0] = 1.0;         \
+               m[0][1] = 0.0;         \
+               m[0][2] = 0.0;         \
+                               \
+               m[1][0] = 0.0;         \
+               m[1][1] = 1.0;         \
+               m[1][2] = 0.0;         \
+                               \
+               m[2][0] = 0.0;         \
+               m[2][1] = 0.0;         \
+               m[2][2] = 1.0;         \
+       }
+
+/*! initialize matrix */
+#define IDENTIFY_MATRIX_4X4(m) \
+       {                          \
+               m[0][0] = 1.0;         \
+               m[0][1] = 0.0;         \
+               m[0][2] = 0.0;         \
+               m[0][3] = 0.0;         \
+                               \
+               m[1][0] = 0.0;         \
+               m[1][1] = 1.0;         \
+               m[1][2] = 0.0;         \
+               m[1][3] = 0.0;         \
+                               \
+               m[2][0] = 0.0;         \
+               m[2][1] = 0.0;         \
+               m[2][2] = 1.0;         \
+               m[2][3] = 0.0;         \
+                               \
+               m[3][0] = 0.0;         \
+               m[3][1] = 0.0;         \
+               m[3][2] = 0.0;         \
+               m[3][3] = 1.0;         \
+       }
+
+/*! initialize matrix */
+#define ZERO_MATRIX_4X4(m) \
+       {                      \
+               m[0][0] = 0.0;     \
+               m[0][1] = 0.0;     \
+               m[0][2] = 0.0;     \
+               m[0][3] = 0.0;     \
+                           \
+               m[1][0] = 0.0;     \
+               m[1][1] = 0.0;     \
+               m[1][2] = 0.0;     \
+               m[1][3] = 0.0;     \
+                           \
+               m[2][0] = 0.0;     \
+               m[2][1] = 0.0;     \
+               m[2][2] = 0.0;     \
+               m[2][3] = 0.0;     \
+                           \
+               m[3][0] = 0.0;     \
+               m[3][1] = 0.0;     \
+               m[3][2] = 0.0;     \
+               m[3][3] = 0.0;     \
+       }
+
+/*! matrix rotation  X */
+#define ROTX_CS(m, cosine, sine)        \
+       {                                   \
+               /* rotation about the x-axis */ \
+                                        \
+               m[0][0] = 1.0;                  \
+               m[0][1] = 0.0;                  \
+               m[0][2] = 0.0;                  \
+               m[0][3] = 0.0;                  \
+                                        \
+               m[1][0] = 0.0;                  \
+               m[1][1] = (cosine);             \
+               m[1][2] = (sine);               \
+               m[1][3] = 0.0;                  \
+                                        \
+               m[2][0] = 0.0;                  \
+               m[2][1] = -(sine);              \
+               m[2][2] = (cosine);             \
+               m[2][3] = 0.0;                  \
+                                        \
+               m[3][0] = 0.0;                  \
+               m[3][1] = 0.0;                  \
+               m[3][2] = 0.0;                  \
+               m[3][3] = 1.0;                  \
+       }
+
+/*! matrix rotation  Y */
+#define ROTY_CS(m, cosine, sine)        \
+       {                                   \
+               /* rotation about the y-axis */ \
+                                        \
+               m[0][0] = (cosine);             \
+               m[0][1] = 0.0;                  \
+               m[0][2] = -(sine);              \
+               m[0][3] = 0.0;                  \
+                                        \
+               m[1][0] = 0.0;                  \
+               m[1][1] = 1.0;                  \
+               m[1][2] = 0.0;                  \
+               m[1][3] = 0.0;                  \
+                                        \
+               m[2][0] = (sine);               \
+               m[2][1] = 0.0;                  \
+               m[2][2] = (cosine);             \
+               m[2][3] = 0.0;                  \
+                                        \
+               m[3][0] = 0.0;                  \
+               m[3][1] = 0.0;                  \
+               m[3][2] = 0.0;                  \
+               m[3][3] = 1.0;                  \
+       }
+
+/*! matrix rotation  Z */
+#define ROTZ_CS(m, cosine, sine)        \
+       {                                   \
+               /* rotation about the z-axis */ \
+                                        \
+               m[0][0] = (cosine);             \
+               m[0][1] = (sine);               \
+               m[0][2] = 0.0;                  \
+               m[0][3] = 0.0;                  \
+                                        \
+               m[1][0] = -(sine);              \
+               m[1][1] = (cosine);             \
+               m[1][2] = 0.0;                  \
+               m[1][3] = 0.0;                  \
+                                        \
+               m[2][0] = 0.0;                  \
+               m[2][1] = 0.0;                  \
+               m[2][2] = 1.0;                  \
+               m[2][3] = 0.0;                  \
+                                        \
+               m[3][0] = 0.0;                  \
+               m[3][1] = 0.0;                  \
+               m[3][2] = 0.0;                  \
+               m[3][3] = 1.0;                  \
+       }
+
+/*! matrix copy */
+#define COPY_MATRIX_2X2(b, a) \
+       {                         \
+               b[0][0] = a[0][0];    \
+               b[0][1] = a[0][1];    \
+                              \
+               b[1][0] = a[1][0];    \
+               b[1][1] = a[1][1];    \
+       }
+
+/*! matrix copy */
+#define COPY_MATRIX_2X3(b, a) \
+       {                         \
+               b[0][0] = a[0][0];    \
+               b[0][1] = a[0][1];    \
+               b[0][2] = a[0][2];    \
+                              \
+               b[1][0] = a[1][0];    \
+               b[1][1] = a[1][1];    \
+               b[1][2] = a[1][2];    \
+       }
+
+/*! matrix copy */
+#define COPY_MATRIX_3X3(b, a) \
+       {                         \
+               b[0][0] = a[0][0];    \
+               b[0][1] = a[0][1];    \
+               b[0][2] = a[0][2];    \
+                              \
+               b[1][0] = a[1][0];    \
+               b[1][1] = a[1][1];    \
+               b[1][2] = a[1][2];    \
+                              \
+               b[2][0] = a[2][0];    \
+               b[2][1] = a[2][1];    \
+               b[2][2] = a[2][2];    \
+       }
+
+/*! matrix copy */
+#define COPY_MATRIX_4X4(b, a) \
+       {                         \
+               b[0][0] = a[0][0];    \
+               b[0][1] = a[0][1];    \
+               b[0][2] = a[0][2];    \
+               b[0][3] = a[0][3];    \
+                              \
+               b[1][0] = a[1][0];    \
+               b[1][1] = a[1][1];    \
+               b[1][2] = a[1][2];    \
+               b[1][3] = a[1][3];    \
+                              \
+               b[2][0] = a[2][0];    \
+               b[2][1] = a[2][1];    \
+               b[2][2] = a[2][2];    \
+               b[2][3] = a[2][3];    \
+                              \
+               b[3][0] = a[3][0];    \
+               b[3][1] = a[3][1];    \
+               b[3][2] = a[3][2];    \
+               b[3][3] = a[3][3];    \
+       }
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_2X2(b, a) \
+       {                              \
+               b[0][0] = a[0][0];         \
+               b[0][1] = a[1][0];         \
+                                   \
+               b[1][0] = a[0][1];         \
+               b[1][1] = a[1][1];         \
+       }
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_3X3(b, a) \
+       {                              \
+               b[0][0] = a[0][0];         \
+               b[0][1] = a[1][0];         \
+               b[0][2] = a[2][0];         \
+                                   \
+               b[1][0] = a[0][1];         \
+               b[1][1] = a[1][1];         \
+               b[1][2] = a[2][1];         \
+                                   \
+               b[2][0] = a[0][2];         \
+               b[2][1] = a[1][2];         \
+               b[2][2] = a[2][2];         \
+       }
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_4X4(b, a) \
+       {                              \
+               b[0][0] = a[0][0];         \
+               b[0][1] = a[1][0];         \
+               b[0][2] = a[2][0];         \
+               b[0][3] = a[3][0];         \
+                                   \
+               b[1][0] = a[0][1];         \
+               b[1][1] = a[1][1];         \
+               b[1][2] = a[2][1];         \
+               b[1][3] = a[3][1];         \
+                                   \
+               b[2][0] = a[0][2];         \
+               b[2][1] = a[1][2];         \
+               b[2][2] = a[2][2];         \
+               b[2][3] = a[3][2];         \
+                                   \
+               b[3][0] = a[0][3];         \
+               b[3][1] = a[1][3];         \
+               b[3][2] = a[2][3];         \
+               b[3][3] = a[3][3];         \
+       }
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_2X2(b, s, a) \
+       {                             \
+               b[0][0] = (s)*a[0][0];    \
+               b[0][1] = (s)*a[0][1];    \
+                                  \
+               b[1][0] = (s)*a[1][0];    \
+               b[1][1] = (s)*a[1][1];    \
+       }
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_3X3(b, s, a) \
+       {                             \
+               b[0][0] = (s)*a[0][0];    \
+               b[0][1] = (s)*a[0][1];    \
+               b[0][2] = (s)*a[0][2];    \
+                                  \
+               b[1][0] = (s)*a[1][0];    \
+               b[1][1] = (s)*a[1][1];    \
+               b[1][2] = (s)*a[1][2];    \
+                                  \
+               b[2][0] = (s)*a[2][0];    \
+               b[2][1] = (s)*a[2][1];    \
+               b[2][2] = (s)*a[2][2];    \
+       }
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_4X4(b, s, a) \
+       {                             \
+               b[0][0] = (s)*a[0][0];    \
+               b[0][1] = (s)*a[0][1];    \
+               b[0][2] = (s)*a[0][2];    \
+               b[0][3] = (s)*a[0][3];    \
+                                  \
+               b[1][0] = (s)*a[1][0];    \
+               b[1][1] = (s)*a[1][1];    \
+               b[1][2] = (s)*a[1][2];    \
+               b[1][3] = (s)*a[1][3];    \
+                                  \
+               b[2][0] = (s)*a[2][0];    \
+               b[2][1] = (s)*a[2][1];    \
+               b[2][2] = (s)*a[2][2];    \
+               b[2][3] = (s)*a[2][3];    \
+                                  \
+               b[3][0] = s * a[3][0];    \
+               b[3][1] = s * a[3][1];    \
+               b[3][2] = s * a[3][2];    \
+               b[3][3] = s * a[3][3];    \
+       }
+
+/*! multiply matrix by scalar */
+#define SCALE_VEC_MATRIX_2X2(b, svec, a) \
+       {                                    \
+               b[0][0] = svec[0] * a[0][0];     \
+               b[1][0] = svec[0] * a[1][0];     \
+                                         \
+               b[0][1] = svec[1] * a[0][1];     \
+               b[1][1] = svec[1] * a[1][1];     \
+       }
+
+/*! multiply matrix by scalar. Each columns is scaled by each scalar vector component */
+#define SCALE_VEC_MATRIX_3X3(b, svec, a) \
+       {                                    \
+               b[0][0] = svec[0] * a[0][0];     \
+               b[1][0] = svec[0] * a[1][0];     \
+               b[2][0] = svec[0] * a[2][0];     \
+                                         \
+               b[0][1] = svec[1] * a[0][1];     \
+               b[1][1] = svec[1] * a[1][1];     \
+               b[2][1] = svec[1] * a[2][1];     \
+                                         \
+               b[0][2] = svec[2] * a[0][2];     \
+               b[1][2] = svec[2] * a[1][2];     \
+               b[2][2] = svec[2] * a[2][2];     \
+       }
+
+/*! multiply matrix by scalar */
+#define SCALE_VEC_MATRIX_4X4(b, svec, a) \
+       {                                    \
+               b[0][0] = svec[0] * a[0][0];     \
+               b[1][0] = svec[0] * a[1][0];     \
+               b[2][0] = svec[0] * a[2][0];     \
+               b[3][0] = svec[0] * a[3][0];     \
+                                         \
+               b[0][1] = svec[1] * a[0][1];     \
+               b[1][1] = svec[1] * a[1][1];     \
+               b[2][1] = svec[1] * a[2][1];     \
+               b[3][1] = svec[1] * a[3][1];     \
+                                         \
+               b[0][2] = svec[2] * a[0][2];     \
+               b[1][2] = svec[2] * a[1][2];     \
+               b[2][2] = svec[2] * a[2][2];     \
+               b[3][2] = svec[2] * a[3][2];     \
+                                         \
+               b[0][3] = svec[3] * a[0][3];     \
+               b[1][3] = svec[3] * a[1][3];     \
+               b[2][3] = svec[3] * a[2][3];     \
+               b[3][3] = svec[3] * a[3][3];     \
+       }
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_2X2(b, s, a) \
+       {                                   \
+               b[0][0] += (s)*a[0][0];         \
+               b[0][1] += (s)*a[0][1];         \
+                                        \
+               b[1][0] += (s)*a[1][0];         \
+               b[1][1] += (s)*a[1][1];         \
+       }
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_3X3(b, s, a) \
+       {                                   \
+               b[0][0] += (s)*a[0][0];         \
+               b[0][1] += (s)*a[0][1];         \
+               b[0][2] += (s)*a[0][2];         \
+                                        \
+               b[1][0] += (s)*a[1][0];         \
+               b[1][1] += (s)*a[1][1];         \
+               b[1][2] += (s)*a[1][2];         \
+                                        \
+               b[2][0] += (s)*a[2][0];         \
+               b[2][1] += (s)*a[2][1];         \
+               b[2][2] += (s)*a[2][2];         \
+       }
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_4X4(b, s, a) \
+       {                                   \
+               b[0][0] += (s)*a[0][0];         \
+               b[0][1] += (s)*a[0][1];         \
+               b[0][2] += (s)*a[0][2];         \
+               b[0][3] += (s)*a[0][3];         \
+                                        \
+               b[1][0] += (s)*a[1][0];         \
+               b[1][1] += (s)*a[1][1];         \
+               b[1][2] += (s)*a[1][2];         \
+               b[1][3] += (s)*a[1][3];         \
+                                        \
+               b[2][0] += (s)*a[2][0];         \
+               b[2][1] += (s)*a[2][1];         \
+               b[2][2] += (s)*a[2][2];         \
+               b[2][3] += (s)*a[2][3];         \
+                                        \
+               b[3][0] += (s)*a[3][0];         \
+               b[3][1] += (s)*a[3][1];         \
+               b[3][2] += (s)*a[3][2];         \
+               b[3][3] += (s)*a[3][3];         \
+       }
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_2X2(c, a, b)                      \
+       {                                                    \
+               c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0]; \
+               c[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1]; \
+                                                         \
+               c[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0]; \
+               c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1]; \
+       }
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_3X3(c, a, b)                                          \
+       {                                                                        \
+               c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0]; \
+               c[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1]; \
+               c[0][2] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2]; \
+                                                                             \
+               c[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0]; \
+               c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1]; \
+               c[1][2] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2]; \
+                                                                             \
+               c[2][0] = a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0]; \
+               c[2][1] = a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1]; \
+               c[2][2] = a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2]; \
+       }
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_4X4(c, a, b)                                                              \
+       {                                                                                            \
+               c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0] + a[0][3] * b[3][0]; \
+               c[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1] + a[0][3] * b[3][1]; \
+               c[0][2] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2] + a[0][3] * b[3][2]; \
+               c[0][3] = a[0][0] * b[0][3] + a[0][1] * b[1][3] + a[0][2] * b[2][3] + a[0][3] * b[3][3]; \
+                                                                                                 \
+               c[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0] + a[1][3] * b[3][0]; \
+               c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1] + a[1][3] * b[3][1]; \
+               c[1][2] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2] + a[1][3] * b[3][2]; \
+               c[1][3] = a[1][0] * b[0][3] + a[1][1] * b[1][3] + a[1][2] * b[2][3] + a[1][3] * b[3][3]; \
+                                                                                                 \
+               c[2][0] = a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0] + a[2][3] * b[3][0]; \
+               c[2][1] = a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1] + a[2][3] * b[3][1]; \
+               c[2][2] = a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2] + a[2][3] * b[3][2]; \
+               c[2][3] = a[2][0] * b[0][3] + a[2][1] * b[1][3] + a[2][2] * b[2][3] + a[2][3] * b[3][3]; \
+                                                                                                 \
+               c[3][0] = a[3][0] * b[0][0] + a[3][1] * b[1][0] + a[3][2] * b[2][0] + a[3][3] * b[3][0]; \
+               c[3][1] = a[3][0] * b[0][1] + a[3][1] * b[1][1] + a[3][2] * b[2][1] + a[3][3] * b[3][1]; \
+               c[3][2] = a[3][0] * b[0][2] + a[3][1] * b[1][2] + a[3][2] * b[2][2] + a[3][3] * b[3][2]; \
+               c[3][3] = a[3][0] * b[0][3] + a[3][1] * b[1][3] + a[3][2] * b[2][3] + a[3][3] * b[3][3]; \
+       }
+
+/*! matrix times vector */
+#define MAT_DOT_VEC_2X2(p, m, v)                \
+       {                                           \
+               p[0] = m[0][0] * v[0] + m[0][1] * v[1]; \
+               p[1] = m[1][0] * v[0] + m[1][1] * v[1]; \
+       }
+
+/*! matrix times vector */
+#define MAT_DOT_VEC_3X3(p, m, v)                                 \
+       {                                                            \
+               p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2]; \
+               p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2]; \
+               p[2] = m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2]; \
+       }
+
+/*! matrix times vector
+v is a vec4f
+*/
+#define MAT_DOT_VEC_4X4(p, m, v)                                                  \
+       {                                                                             \
+               p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3]; \
+               p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3]; \
+               p[2] = m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3]; \
+               p[3] = m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]; \
+       }
+
+/*! matrix times vector
+v is a vec3f
+and m is a mat4f<br>
+Last column is added as the position
+*/
+#define MAT_DOT_VEC_3X4(p, m, v)                                           \
+       {                                                                      \
+               p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3]; \
+               p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3]; \
+               p[2] = m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3]; \
+       }
+
+/*! vector transpose times matrix */
+/*! p[j] = v[0]*m[0][j] + v[1]*m[1][j] + v[2]*m[2][j]; */
+#define VEC_DOT_MAT_3X3(p, v, m)                                 \
+       {                                                            \
+               p[0] = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0]; \
+               p[1] = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1]; \
+               p[2] = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2]; \
+       }
+
+/*! affine matrix times vector */
+/** The matrix is assumed to be an affine matrix, with last two
+ * entries representing a translation */
+#define MAT_DOT_VEC_2X3(p, m, v)                          \
+       {                                                     \
+               p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2]; \
+               p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2]; \
+       }
+
+//! Transform a plane
+#define MAT_TRANSFORM_PLANE_4X4(pout, m, plane)                                         \
+       {                                                                                   \
+               pout[0] = m[0][0] * plane[0] + m[0][1] * plane[1] + m[0][2] * plane[2];         \
+               pout[1] = m[1][0] * plane[0] + m[1][1] * plane[1] + m[1][2] * plane[2];         \
+               pout[2] = m[2][0] * plane[0] + m[2][1] * plane[1] + m[2][2] * plane[2];         \
+               pout[3] = m[0][3] * pout[0] + m[1][3] * pout[1] + m[2][3] * pout[2] + plane[3]; \
+       }
+
+/** inverse transpose of matrix times vector
+ *
+ * This macro computes inverse transpose of matrix m,
+ * and multiplies vector v into it, to yeild vector p
+ *
+ * DANGER !!! Do Not use this on normal vectors!!!
+ * It will leave normals the wrong length !!!
+ * See macro below for use on normals.
+ */
+#define INV_TRANSP_MAT_DOT_VEC_2X2(p, m, v)                                 \
+       {                                                                       \
+               GREAL det;                                                          \
+                                                                            \
+               det = m[0][0] * m[1][1] - m[0][1] * m[1][0];                        \
+               p[0] = m[1][1] * v[0] - m[1][0] * v[1];                             \
+               p[1] = -m[0][1] * v[0] + m[0][0] * v[1];                            \
+                                                                            \
+               /* if matrix not singular, and not orthonormal, then renormalize */ \
+               if ((det != 1.0f) && (det != 0.0f))                                 \
+               {                                                                   \
+                       det = 1.0f / det;                                               \
+                       p[0] *= det;                                                    \
+                       p[1] *= det;                                                    \
+               }                                                                   \
+       }
+
+/** transform normal vector by inverse transpose of matrix
+ * and then renormalize the vector
+ *
+ * This macro computes inverse transpose of matrix m,
+ * and multiplies vector v into it, to yeild vector p
+ * Vector p is then normalized.
+ */
+#define NORM_XFORM_2X2(p, m, v)                                           \
+       {                                                                     \
+               GREAL len;                                                        \
+                                                                          \
+               /* do nothing if off-diagonals are zero and diagonals are       \
+    * equal */      \
+               if ((m[0][1] != 0.0) || (m[1][0] != 0.0) || (m[0][0] != m[1][1])) \
+               {                                                                 \
+                       p[0] = m[1][1] * v[0] - m[1][0] * v[1];                       \
+                       p[1] = -m[0][1] * v[0] + m[0][0] * v[1];                      \
+                                                                          \
+                       len = p[0] * p[0] + p[1] * p[1];                              \
+                       GIM_INV_SQRT(len, len);                                       \
+                       p[0] *= len;                                                  \
+                       p[1] *= len;                                                  \
+               }                                                                 \
+               else                                                              \
+               {                                                                 \
+                       VEC_COPY_2(p, v);                                             \
+               }                                                                 \
+       }
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_2X2(m, v, t) \
+       {                              \
+               m[0][0] = v[0] * t[0];     \
+               m[0][1] = v[0] * t[1];     \
+                                   \
+               m[1][0] = v[1] * t[0];     \
+               m[1][1] = v[1] * t[1];     \
+       }
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_3X3(m, v, t) \
+       {                              \
+               m[0][0] = v[0] * t[0];     \
+               m[0][1] = v[0] * t[1];     \
+               m[0][2] = v[0] * t[2];     \
+                                   \
+               m[1][0] = v[1] * t[0];     \
+               m[1][1] = v[1] * t[1];     \
+               m[1][2] = v[1] * t[2];     \
+                                   \
+               m[2][0] = v[2] * t[0];     \
+               m[2][1] = v[2] * t[1];     \
+               m[2][2] = v[2] * t[2];     \
+       }
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_4X4(m, v, t) \
+       {                              \
+               m[0][0] = v[0] * t[0];     \
+               m[0][1] = v[0] * t[1];     \
+               m[0][2] = v[0] * t[2];     \
+               m[0][3] = v[0] * t[3];     \
+                                   \
+               m[1][0] = v[1] * t[0];     \
+               m[1][1] = v[1] * t[1];     \
+               m[1][2] = v[1] * t[2];     \
+               m[1][3] = v[1] * t[3];     \
+                                   \
+               m[2][0] = v[2] * t[0];     \
+               m[2][1] = v[2] * t[1];     \
+               m[2][2] = v[2] * t[2];     \
+               m[2][3] = v[2] * t[3];     \
+                                   \
+               m[3][0] = v[3] * t[0];     \
+               m[3][1] = v[3] * t[1];     \
+               m[3][2] = v[3] * t[2];     \
+               m[3][3] = v[3] * t[3];     \
+       }
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_2X2(m, v, t) \
+       {                                    \
+               m[0][0] += v[0] * t[0];          \
+               m[0][1] += v[0] * t[1];          \
+                                         \
+               m[1][0] += v[1] * t[0];          \
+               m[1][1] += v[1] * t[1];          \
+       }
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_3X3(m, v, t) \
+       {                                    \
+               m[0][0] += v[0] * t[0];          \
+               m[0][1] += v[0] * t[1];          \
+               m[0][2] += v[0] * t[2];          \
+                                         \
+               m[1][0] += v[1] * t[0];          \
+               m[1][1] += v[1] * t[1];          \
+               m[1][2] += v[1] * t[2];          \
+                                         \
+               m[2][0] += v[2] * t[0];          \
+               m[2][1] += v[2] * t[1];          \
+               m[2][2] += v[2] * t[2];          \
+       }
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_4X4(m, v, t) \
+       {                                    \
+               m[0][0] += v[0] * t[0];          \
+               m[0][1] += v[0] * t[1];          \
+               m[0][2] += v[0] * t[2];          \
+               m[0][3] += v[0] * t[3];          \
+                                         \
+               m[1][0] += v[1] * t[0];          \
+               m[1][1] += v[1] * t[1];          \
+               m[1][2] += v[1] * t[2];          \
+               m[1][3] += v[1] * t[3];          \
+                                         \
+               m[2][0] += v[2] * t[0];          \
+               m[2][1] += v[2] * t[1];          \
+               m[2][2] += v[2] * t[2];          \
+               m[2][3] += v[2] * t[3];          \
+                                         \
+               m[3][0] += v[3] * t[0];          \
+               m[3][1] += v[3] * t[1];          \
+               m[3][2] += v[3] * t[2];          \
+               m[3][3] += v[3] * t[3];          \
+       }
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_2X2(d, m)                      \
+       {                                              \
+               d = m[0][0] * m[1][1] - m[0][1] * m[1][0]; \
+       }
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_3X3(d, m)                                   \
+       {                                                           \
+               d = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]);  \
+               d -= m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]); \
+               d += m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
+       }
+
+/** i,j,th cofactor of a 4x4 matrix
+ *
+ */
+#define COFACTOR_4X4_IJ(fac, m, i, j)                                                                                           \
+       {                                                                                                                           \
+               GUINT __ii[4], __jj[4], __k;                                                                                            \
+                                                                                                                                \
+               for (__k = 0; __k < i; __k++) __ii[__k] = __k;                                                                          \
+               for (__k = i; __k < 3; __k++) __ii[__k] = __k + 1;                                                                      \
+               for (__k = 0; __k < j; __k++) __jj[__k] = __k;                                                                          \
+               for (__k = j; __k < 3; __k++) __jj[__k] = __k + 1;                                                                      \
+                                                                                                                                \
+               (fac) = m[__ii[0]][__jj[0]] * (m[__ii[1]][__jj[1]] * m[__ii[2]][__jj[2]] - m[__ii[1]][__jj[2]] * m[__ii[2]][__jj[1]]);  \
+               (fac) -= m[__ii[0]][__jj[1]] * (m[__ii[1]][__jj[0]] * m[__ii[2]][__jj[2]] - m[__ii[1]][__jj[2]] * m[__ii[2]][__jj[0]]); \
+               (fac) += m[__ii[0]][__jj[2]] * (m[__ii[1]][__jj[0]] * m[__ii[2]][__jj[1]] - m[__ii[1]][__jj[1]] * m[__ii[2]][__jj[0]]); \
+                                                                                                                                \
+               __k = i + j;                                                                                                            \
+               if (__k != (__k / 2) * 2)                                                                                               \
+               {                                                                                                                       \
+                       (fac) = -(fac);                                                                                                     \
+               }                                                                                                                       \
+       }
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_4X4(d, m)            \
+       {                                    \
+               GREAL cofac;                     \
+               COFACTOR_4X4_IJ(cofac, m, 0, 0); \
+               d = m[0][0] * cofac;             \
+               COFACTOR_4X4_IJ(cofac, m, 0, 1); \
+               d += m[0][1] * cofac;            \
+               COFACTOR_4X4_IJ(cofac, m, 0, 2); \
+               d += m[0][2] * cofac;            \
+               COFACTOR_4X4_IJ(cofac, m, 0, 3); \
+               d += m[0][3] * cofac;            \
+       }
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_2X2(a, m)    \
+       {                         \
+               a[0][0] = (m)[1][1];  \
+               a[0][1] = -(m)[1][0]; \
+               a[1][0] = -(m)[0][1]; \
+               a[1][1] = (m)[0][0];  \
+       }
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_3X3(a, m)                                  \
+       {                                                       \
+               a[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];    \
+               a[0][1] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]); \
+               a[0][2] = m[1][0] * m[2][1] - m[1][1] * m[2][0];    \
+               a[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); \
+               a[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];    \
+               a[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); \
+               a[2][0] = m[0][1] * m[1][2] - m[0][2] * m[1][1];    \
+               a[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); \
+   a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]);            \
+       }
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_4X4(a, m)                         \
+       {                                              \
+               int i, j;                                  \
+                                                   \
+               for (i = 0; i < 4; i++)                    \
+               {                                          \
+                       for (j = 0; j < 4; j++)                \
+                       {                                      \
+                               COFACTOR_4X4_IJ(a[i][j], m, i, j); \
+                       }                                      \
+               }                                          \
+       }
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_2X2(a, m)     \
+       {                         \
+               a[0][0] = (m)[1][1];  \
+               a[1][0] = -(m)[1][0]; \
+               a[0][1] = -(m)[0][1]; \
+               a[1][1] = (m)[0][0];  \
+       }
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_3X3(a, m)                                   \
+       {                                                       \
+               a[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];    \
+               a[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]); \
+               a[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0];    \
+               a[0][1] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); \
+               a[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];    \
+               a[2][1] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); \
+               a[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1];    \
+               a[1][2] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); \
+   a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]);            \
+       }
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_4X4(a, m)                                  \
+       {                                                      \
+               char _i_, _j_;                                     \
+                                                           \
+               for (_i_ = 0; _i_ < 4; _i_++)                      \
+               {                                                  \
+                       for (_j_ = 0; _j_ < 4; _j_++)                  \
+                       {                                              \
+                               COFACTOR_4X4_IJ(a[_j_][_i_], m, _i_, _j_); \
+                       }                                              \
+               }                                                  \
+       }
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_2X2(a, s, m) \
+       {                              \
+               a[0][0] = (s)*m[1][1];     \
+               a[1][0] = -(s)*m[1][0];    \
+               a[0][1] = -(s)*m[0][1];    \
+               a[1][1] = (s)*m[0][0];     \
+       }
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_3X3(a, s, m)                               \
+       {                                                            \
+               a[0][0] = (s) * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); \
+               a[1][0] = (s) * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); \
+               a[2][0] = (s) * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
+                                                                 \
+               a[0][1] = (s) * (m[0][2] * m[2][1] - m[0][1] * m[2][2]); \
+               a[1][1] = (s) * (m[0][0] * m[2][2] - m[0][2] * m[2][0]); \
+               a[2][1] = (s) * (m[0][1] * m[2][0] - m[0][0] * m[2][1]); \
+                                                                 \
+               a[0][2] = (s) * (m[0][1] * m[1][2] - m[0][2] * m[1][1]); \
+               a[1][2] = (s) * (m[0][2] * m[1][0] - m[0][0] * m[1][2]); \
+               a[2][2] = (s) * (m[0][0] * m[1][1] - m[0][1] * m[1][0]); \
+       }
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_4X4(a, s, m)                         \
+       {                                                      \
+               char _i_, _j_;                                     \
+               for (_i_ = 0; _i_ < 4; _i_++)                      \
+               {                                                  \
+                       for (_j_ = 0; _j_ < 4; _j_++)                  \
+                       {                                              \
+                               COFACTOR_4X4_IJ(a[_j_][_i_], m, _i_, _j_); \
+                               a[_j_][_i_] *= s;                          \
+                       }                                              \
+               }                                                  \
+       }
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_2X2(b, det, a)           \
+       {                                   \
+               GREAL _tmp_;                    \
+               DETERMINANT_2X2(det, a);        \
+               _tmp_ = 1.0 / (det);            \
+               SCALE_ADJOINT_2X2(b, _tmp_, a); \
+       }
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_3X3(b, det, a)           \
+       {                                   \
+               GREAL _tmp_;                    \
+               DETERMINANT_3X3(det, a);        \
+               _tmp_ = 1.0 / (det);            \
+               SCALE_ADJOINT_3X3(b, _tmp_, a); \
+       }
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_4X4(b, det, a)           \
+       {                                   \
+               GREAL _tmp_;                    \
+               DETERMINANT_4X4(det, a);        \
+               _tmp_ = 1.0 / (det);            \
+               SCALE_ADJOINT_4X4(b, _tmp_, a); \
+       }
+
+//! Get the triple(3) row of a transform matrix
+#define MAT_GET_ROW(mat, vec3, rowindex) \
+       {                                    \
+               vec3[0] = mat[rowindex][0];      \
+               vec3[1] = mat[rowindex][1];      \
+               vec3[2] = mat[rowindex][2];      \
+       }
+
+//! Get the tuple(2) row of a transform matrix
+#define MAT_GET_ROW2(mat, vec2, rowindex) \
+       {                                     \
+               vec2[0] = mat[rowindex][0];       \
+               vec2[1] = mat[rowindex][1];       \
+       }
+
+//! Get the quad (4) row of a transform matrix
+#define MAT_GET_ROW4(mat, vec4, rowindex) \
+       {                                     \
+               vec4[0] = mat[rowindex][0];       \
+               vec4[1] = mat[rowindex][1];       \
+               vec4[2] = mat[rowindex][2];       \
+               vec4[3] = mat[rowindex][3];       \
+       }
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_COL(mat, vec3, colindex) \
+       {                                    \
+               vec3[0] = mat[0][colindex];      \
+               vec3[1] = mat[1][colindex];      \
+               vec3[2] = mat[2][colindex];      \
+       }
+
+//! Get the tuple(2) col of a transform matrix
+#define MAT_GET_COL2(mat, vec2, colindex) \
+       {                                     \
+               vec2[0] = mat[0][colindex];       \
+               vec2[1] = mat[1][colindex];       \
+       }
+
+//! Get the quad (4) col of a transform matrix
+#define MAT_GET_COL4(mat, vec4, colindex) \
+       {                                     \
+               vec4[0] = mat[0][colindex];       \
+               vec4[1] = mat[1][colindex];       \
+               vec4[2] = mat[2][colindex];       \
+               vec4[3] = mat[3][colindex];       \
+       }
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_X(mat, vec3)       \
+       {                              \
+               MAT_GET_COL(mat, vec3, 0); \
+       }
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_Y(mat, vec3)       \
+       {                              \
+               MAT_GET_COL(mat, vec3, 1); \
+       }
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_Z(mat, vec3)       \
+       {                              \
+               MAT_GET_COL(mat, vec3, 2); \
+       }
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_SET_X(mat, vec3) \
+       {                        \
+               mat[0][0] = vec3[0]; \
+               mat[1][0] = vec3[1]; \
+               mat[2][0] = vec3[2]; \
+       }
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_SET_Y(mat, vec3) \
+       {                        \
+               mat[0][1] = vec3[0]; \
+               mat[1][1] = vec3[1]; \
+               mat[2][1] = vec3[2]; \
+       }
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_SET_Z(mat, vec3) \
+       {                        \
+               mat[0][2] = vec3[0]; \
+               mat[1][2] = vec3[1]; \
+               mat[2][2] = vec3[2]; \
+       }
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_TRANSLATION(mat, vec3) \
+       {                                  \
+               vec3[0] = mat[0][3];           \
+               vec3[1] = mat[1][3];           \
+               vec3[2] = mat[2][3];           \
+       }
+
+//! Set the triple(3) col of a transform matrix
+#define MAT_SET_TRANSLATION(mat, vec3) \
+       {                                  \
+               mat[0][3] = vec3[0];           \
+               mat[1][3] = vec3[1];           \
+               mat[2][3] = vec3[2];           \
+       }
+
+//! Returns the dot product between a vec3f and the row of a matrix
+#define MAT_DOT_ROW(mat, vec3, rowindex) (vec3[0] * mat[rowindex][0] + vec3[1] * mat[rowindex][1] + vec3[2] * mat[rowindex][2])
+
+//! Returns the dot product between a vec2f and the row of a matrix
+#define MAT_DOT_ROW2(mat, vec2, rowindex) (vec2[0] * mat[rowindex][0] + vec2[1] * mat[rowindex][1])
+
+//! Returns the dot product between a vec4f and the row of a matrix
+#define MAT_DOT_ROW4(mat, vec4, rowindex) (vec4[0] * mat[rowindex][0] + vec4[1] * mat[rowindex][1] + vec4[2] * mat[rowindex][2] + vec4[3] * mat[rowindex][3])
+
+//! Returns the dot product between a vec3f and the col of a matrix
+#define MAT_DOT_COL(mat, vec3, colindex) (vec3[0] * mat[0][colindex] + vec3[1] * mat[1][colindex] + vec3[2] * mat[2][colindex])
+
+//! Returns the dot product between a vec2f and the col of a matrix
+#define MAT_DOT_COL2(mat, vec2, colindex) (vec2[0] * mat[0][colindex] + vec2[1] * mat[1][colindex])
+
+//! Returns the dot product between a vec4f and the col of a matrix
+#define MAT_DOT_COL4(mat, vec4, colindex) (vec4[0] * mat[0][colindex] + vec4[1] * mat[1][colindex] + vec4[2] * mat[2][colindex] + vec4[3] * mat[3][colindex])
+
+/*!Transpose matrix times vector
+v is a vec3f
+and m is a mat4f<br>
+*/
+#define INV_MAT_DOT_VEC_3X3(p, m, v) \
+       {                                \
+               p[0] = MAT_DOT_COL(m, v, 0); \
+               p[1] = MAT_DOT_COL(m, v, 1); \
+               p[2] = MAT_DOT_COL(m, v, 2); \
+       }
+
+#endif  // GIM_VECTOR_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_math.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_math.h
new file mode 100644 (file)
index 0000000..3c4f821
--- /dev/null
@@ -0,0 +1,148 @@
+#ifndef GIM_MATH_H_INCLUDED
+#define GIM_MATH_H_INCLUDED
+/*! \file gim_math.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "LinearMath/btScalar.h"
+
+#define GREAL btScalar
+#define GREAL2 double
+#define GINT int
+#define GUINT unsigned int
+#define GSHORT short
+#define GUSHORT unsigned short
+#define GINT64 long long
+#define GUINT64 unsigned long long
+
+#define G_PI 3.14159265358979f
+#define G_HALF_PI 1.5707963f
+//267948966
+#define G_TWO_PI 6.28318530f
+//71795864
+#define G_ROOT3 1.73205f
+#define G_ROOT2 1.41421f
+#define G_UINT_INFINITY 0xffffffff  //!< A very very high value
+#define G_REAL_INFINITY FLT_MAX
+#define G_SIGN_BITMASK 0x80000000
+#define G_EPSILON SIMD_EPSILON
+
+enum GIM_SCALAR_TYPES
+{
+       G_STYPE_REAL = 0,
+       G_STYPE_REAL2,
+       G_STYPE_SHORT,
+       G_STYPE_USHORT,
+       G_STYPE_INT,
+       G_STYPE_UINT,
+       G_STYPE_INT64,
+       G_STYPE_UINT64
+};
+
+#define G_DEGTORAD(X) ((X)*3.1415926f / 180.0f)
+#define G_RADTODEG(X) ((X)*180.0f / 3.1415926f)
+
+//! Integer representation of a floating-point value.
+#define GIM_IR(x) ((GUINT&)(x))
+
+//! Signed integer representation of a floating-point value.
+#define GIM_SIR(x) ((GINT&)(x))
+
+//! Absolute integer representation of a floating-point value
+#define GIM_AIR(x) (GIM_IR(x) & 0x7fffffff)
+
+//! Floating-point representation of an integer value.
+#define GIM_FR(x) ((GREAL&)(x))
+
+#define GIM_MAX(a, b) (a < b ? b : a)
+#define GIM_MIN(a, b) (a > b ? b : a)
+
+#define GIM_MAX3(a, b, c) GIM_MAX(a, GIM_MAX(b, c))
+#define GIM_MIN3(a, b, c) GIM_MIN(a, GIM_MIN(b, c))
+
+#define GIM_IS_ZERO(value) (value < G_EPSILON && value > -G_EPSILON)
+
+#define GIM_IS_NEGATIVE(value) (value <= -G_EPSILON)
+
+#define GIM_IS_POSISITVE(value) (value >= G_EPSILON)
+
+#define GIM_NEAR_EQUAL(v1, v2) GIM_IS_ZERO((v1 - v2))
+
+///returns a clamped number
+#define GIM_CLAMP(number, minval, maxval) (number < minval ? minval : (number > maxval ? maxval : number))
+
+#define GIM_GREATER(x, y) btFabs(x) > (y)
+
+///Swap numbers
+#define GIM_SWAP_NUMBERS(a, b) \
+       {                          \
+               a = a + b;             \
+               b = a - b;             \
+               a = a - b;             \
+       }
+
+#define GIM_INV_SQRT(va, isva)                         \
+       {                                                  \
+               if (va <= 0.0000001f)                          \
+               {                                              \
+                       isva = G_REAL_INFINITY;                    \
+               }                                              \
+               else                                           \
+               {                                              \
+                       GREAL _x = va * 0.5f;                      \
+                       GUINT _y = 0x5f3759df - (GIM_IR(va) >> 1); \
+                       isva = GIM_FR(_y);                         \
+                       isva = isva * (1.5f - (_x * isva * isva)); \
+               }                                              \
+       }
+
+#define GIM_SQRT(va, sva)      \
+       {                          \
+               GIM_INV_SQRT(va, sva); \
+               sva = 1.0f / sva;      \
+       }
+
+//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html
+inline GREAL gim_inv_sqrt(GREAL f)
+{
+       GREAL r;
+       GIM_INV_SQRT(f, r);
+       return r;
+}
+
+inline GREAL gim_sqrt(GREAL f)
+{
+       GREAL r;
+       GIM_SQRT(f, r);
+       return r;
+}
+
+#endif  // GIM_MATH_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_memory.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_memory.cpp
new file mode 100644 (file)
index 0000000..9e29ab9
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_memory.h"
+#include "stdlib.h"
+
+#ifdef GIM_SIMD_MEMORY
+#include "LinearMath/btAlignedAllocator.h"
+#endif
+
+static gim_alloc_function *g_allocfn = 0;
+static gim_alloca_function *g_allocafn = 0;
+static gim_realloc_function *g_reallocfn = 0;
+static gim_free_function *g_freefn = 0;
+
+void gim_set_alloc_handler(gim_alloc_function *fn)
+{
+       g_allocfn = fn;
+}
+
+void gim_set_alloca_handler(gim_alloca_function *fn)
+{
+       g_allocafn = fn;
+}
+
+void gim_set_realloc_handler(gim_realloc_function *fn)
+{
+       g_reallocfn = fn;
+}
+
+void gim_set_free_handler(gim_free_function *fn)
+{
+       g_freefn = fn;
+}
+
+gim_alloc_function *gim_get_alloc_handler()
+{
+       return g_allocfn;
+}
+
+gim_alloca_function *gim_get_alloca_handler()
+{
+       return g_allocafn;
+}
+
+gim_realloc_function *gim_get_realloc_handler()
+{
+       return g_reallocfn;
+}
+
+gim_free_function *gim_get_free_handler()
+{
+       return g_freefn;
+}
+
+void *gim_alloc(size_t size)
+{
+       void *ptr;
+       if (g_allocfn)
+       {
+               ptr = g_allocfn(size);
+       }
+       else
+       {
+#ifdef GIM_SIMD_MEMORY
+               ptr = btAlignedAlloc(size, 16);
+#else
+               ptr = malloc(size);
+#endif
+       }
+       return ptr;
+}
+
+void *gim_alloca(size_t size)
+{
+       if (g_allocafn)
+               return g_allocafn(size);
+       else
+               return gim_alloc(size);
+}
+
+void *gim_realloc(void *ptr, size_t oldsize, size_t newsize)
+{
+       void *newptr = gim_alloc(newsize);
+       size_t copysize = oldsize < newsize ? oldsize : newsize;
+       gim_simd_memcpy(newptr, ptr, copysize);
+       gim_free(ptr);
+       return newptr;
+}
+
+void gim_free(void *ptr)
+{
+       if (!ptr) return;
+       if (g_freefn)
+       {
+               g_freefn(ptr);
+       }
+       else
+       {
+#ifdef GIM_SIMD_MEMORY
+               btAlignedFree(ptr);
+#else
+               free(ptr);
+#endif
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_memory.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_memory.h
new file mode 100644 (file)
index 0000000..fffbfa2
--- /dev/null
@@ -0,0 +1,177 @@
+#ifndef GIM_MEMORY_H_INCLUDED
+#define GIM_MEMORY_H_INCLUDED
+/*! \file gim_memory.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_math.h"
+#include <string.h>
+
+#ifdef PREFETCH
+#include <xmmintrin.h>  // for prefetch
+#define pfval 64
+#define pfval2 128
+//! Prefetch 64
+#define pf(_x, _i) _mm_prefetch((void *)(_x + _i + pfval), 0)
+//! Prefetch 128
+#define pf2(_x, _i) _mm_prefetch((void *)(_x + _i + pfval2), 0)
+#else
+//! Prefetch 64
+#define pf(_x, _i)
+//! Prefetch 128
+#define pf2(_x, _i)
+#endif
+
+///Functions for manip packed arrays of numbers
+#define GIM_COPY_ARRAYS(dest_array, source_array, element_count) \
+       {                                                            \
+               for (GUINT _i_ = 0; _i_ < element_count; ++_i_)          \
+               {                                                        \
+                       dest_array[_i_] = source_array[_i_];                 \
+               }                                                        \
+       }
+
+#define GIM_COPY_ARRAYS_1(dest_array, source_array, element_count, copy_macro) \
+       {                                                                          \
+               for (GUINT _i_ = 0; _i_ < element_count; ++_i_)                        \
+               {                                                                      \
+                       copy_macro(dest_array[_i_], source_array[_i_]);                    \
+               }                                                                      \
+       }
+
+#define GIM_ZERO_ARRAY(array, element_count)            \
+       {                                                   \
+               for (GUINT _i_ = 0; _i_ < element_count; ++_i_) \
+               {                                               \
+                       array[_i_] = 0;                             \
+               }                                               \
+       }
+
+#define GIM_CONSTANT_ARRAY(array, element_count, constant) \
+       {                                                      \
+               for (GUINT _i_ = 0; _i_ < element_count; ++_i_)    \
+               {                                                  \
+                       array[_i_] = constant;                         \
+               }                                                  \
+       }
+
+///Function prototypes to allocate and free memory.
+typedef void *gim_alloc_function(size_t size);
+typedef void *gim_alloca_function(size_t size);  //Allocs on the heap
+typedef void *gim_realloc_function(void *ptr, size_t oldsize, size_t newsize);
+typedef void gim_free_function(void *ptr);
+
+///Memory Function Handlers
+///set new memory management functions. if fn is 0, the default handlers are used.
+void gim_set_alloc_handler(gim_alloc_function *fn);
+void gim_set_alloca_handler(gim_alloca_function *fn);
+void gim_set_realloc_handler(gim_realloc_function *fn);
+void gim_set_free_handler(gim_free_function *fn);
+
+///get current memory management functions.
+gim_alloc_function *gim_get_alloc_handler(void);
+gim_alloca_function *gim_get_alloca_handler(void);
+gim_realloc_function *gim_get_realloc_handler(void);
+gim_free_function *gim_get_free_handler(void);
+
+///Standar Memory functions
+void *gim_alloc(size_t size);
+void *gim_alloca(size_t size);
+void *gim_realloc(void *ptr, size_t oldsize, size_t newsize);
+void gim_free(void *ptr);
+
+#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+#define GIM_SIMD_MEMORY 1
+#endif
+
+//! SIMD POINTER INTEGER
+#define SIMD_T GUINT64
+//! SIMD INTEGER SIZE
+#define SIMD_T_SIZE sizeof(SIMD_T)
+
+inline void gim_simd_memcpy(void *dst, const void *src, size_t copysize)
+{
+#ifdef GIM_SIMD_MEMORY
+       /*
+//'long long int' is incompatible with visual studio 6...
+    //copy words
+    SIMD_T * ui_src_ptr = (SIMD_T *)src;
+    SIMD_T * ui_dst_ptr = (SIMD_T *)dst;
+    while(copysize>=SIMD_T_SIZE)
+    {
+        *(ui_dst_ptr++) = *(ui_src_ptr++);
+        copysize-=SIMD_T_SIZE;
+    }
+    if(copysize==0) return;
+*/
+
+       char *c_src_ptr = (char *)src;
+       char *c_dst_ptr = (char *)dst;
+       while (copysize > 0)
+       {
+               *(c_dst_ptr++) = *(c_src_ptr++);
+               copysize--;
+       }
+       return;
+#else
+       memcpy(dst, src, copysize);
+#endif
+}
+
+template <class T>
+inline void gim_swap_elements(T *_array, size_t _i, size_t _j)
+{
+       T _e_tmp_ = _array[_i];
+       _array[_i] = _array[_j];
+       _array[_j] = _e_tmp_;
+}
+
+template <class T>
+inline void gim_swap_elements_memcpy(T *_array, size_t _i, size_t _j)
+{
+       char _e_tmp_[sizeof(T)];
+       gim_simd_memcpy(_e_tmp_, &_array[_i], sizeof(T));
+       gim_simd_memcpy(&_array[_i], &_array[_j], sizeof(T));
+       gim_simd_memcpy(&_array[_j], _e_tmp_, sizeof(T));
+}
+
+template <int SIZE>
+inline void gim_swap_elements_ptr(char *_array, size_t _i, size_t _j)
+{
+       char _e_tmp_[SIZE];
+       _i *= SIZE;
+       _j *= SIZE;
+       gim_simd_memcpy(_e_tmp_, _array + _i, SIZE);
+       gim_simd_memcpy(_array + _i, _array + _j, SIZE);
+       gim_simd_memcpy(_array + _j, _e_tmp_, SIZE);
+}
+
+#endif  // GIM_MEMORY_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_pair.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_pair.h
new file mode 100644 (file)
index 0000000..56c185a
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef GIM_PAIR_H
+#define GIM_PAIR_H
+
+
+//! Overlapping pair
+struct GIM_PAIR
+{
+        int m_index1;
+        int m_index2;
+        GIM_PAIR()
+        {
+        }
+
+        GIM_PAIR(const GIM_PAIR& p)
+        {
+                m_index1 = p.m_index1;
+                m_index2 = p.m_index2;
+        }
+
+        GIM_PAIR(int index1, int index2)
+        {
+                m_index1 = index1;
+                m_index2 = index2;
+        }
+};
+
+#endif //GIM_PAIR_H
+
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_radixsort.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_radixsort.h
new file mode 100644 (file)
index 0000000..ff7907a
--- /dev/null
@@ -0,0 +1,386 @@
+#ifndef GIM_RADIXSORT_H_INCLUDED
+#define GIM_RADIXSORT_H_INCLUDED
+/*! \file gim_radixsort.h
+\author Francisco Leon Najera.
+Based on the work of Michael Herf : "fast floating-point radix sort"
+Avaliable on http://www.stereopsis.com/radix.html
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_memory.h"
+
+///Macros for sorting.
+//! Prototype for comparators
+class less_comparator
+{
+public:
+       template <class T, class Z>
+       inline int operator()(const T& a, const Z& b)
+       {
+               return (a < b ? -1 : (a > b ? 1 : 0));
+       }
+};
+
+//! Prototype for comparators
+class integer_comparator
+{
+public:
+       template <class T>
+       inline int operator()(const T& a, const T& b)
+       {
+               return (int)(a - b);
+       }
+};
+
+//!Prototype for getting the integer representation of an object
+class uint_key_func
+{
+public:
+       template <class T>
+       inline GUINT operator()(const T& a)
+       {
+               return (GUINT)a;
+       }
+};
+
+//!Prototype for copying elements
+class copy_elements_func
+{
+public:
+       template <class T>
+       inline void operator()(T& a, T& b)
+       {
+               a = b;
+       }
+};
+
+//!Prototype for copying elements
+class memcopy_elements_func
+{
+public:
+       template <class T>
+       inline void operator()(T& a, T& b)
+       {
+               gim_simd_memcpy(&a, &b, sizeof(T));
+       }
+};
+
+//! @{
+struct GIM_RSORT_TOKEN
+{
+       GUINT m_key;
+       GUINT m_value;
+       GIM_RSORT_TOKEN()
+       {
+       }
+       GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
+       {
+               m_key = rtoken.m_key;
+               m_value = rtoken.m_value;
+       }
+
+       inline bool operator<(const GIM_RSORT_TOKEN& other) const
+       {
+               return (m_key < other.m_key);
+       }
+
+       inline bool operator>(const GIM_RSORT_TOKEN& other) const
+       {
+               return (m_key > other.m_key);
+       }
+};
+
+//! Prototype for comparators
+class GIM_RSORT_TOKEN_COMPARATOR
+{
+public:
+       inline int operator()(const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b)
+       {
+               return (int)((a.m_key) - (b.m_key));
+       }
+};
+
+#define kHist 2048
+// ---- utils for accessing 11-bit quantities
+#define D11_0(x) (x & 0x7FF)
+#define D11_1(x) (x >> 11 & 0x7FF)
+#define D11_2(x) (x >> 22)
+
+///Radix sort for unsigned integer keys
+inline void gim_radix_sort_rtokens(
+       GIM_RSORT_TOKEN* array,
+       GIM_RSORT_TOKEN* sorted, GUINT element_count)
+{
+       GUINT i;
+       GUINT b0[kHist * 3];
+       GUINT* b1 = b0 + kHist;
+       GUINT* b2 = b1 + kHist;
+       for (i = 0; i < kHist * 3; ++i)
+       {
+               b0[i] = 0;
+       }
+       GUINT fi;
+       GUINT pos;
+       for (i = 0; i < element_count; ++i)
+       {
+               fi = array[i].m_key;
+               b0[D11_0(fi)]++;
+               b1[D11_1(fi)]++;
+               b2[D11_2(fi)]++;
+       }
+       {
+               GUINT sum0 = 0, sum1 = 0, sum2 = 0;
+               GUINT tsum;
+               for (i = 0; i < kHist; ++i)
+               {
+                       tsum = b0[i] + sum0;
+                       b0[i] = sum0 - 1;
+                       sum0 = tsum;
+                       tsum = b1[i] + sum1;
+                       b1[i] = sum1 - 1;
+                       sum1 = tsum;
+                       tsum = b2[i] + sum2;
+                       b2[i] = sum2 - 1;
+                       sum2 = tsum;
+               }
+       }
+       for (i = 0; i < element_count; ++i)
+       {
+               fi = array[i].m_key;
+               pos = D11_0(fi);
+               pos = ++b0[pos];
+               sorted[pos].m_key = array[i].m_key;
+               sorted[pos].m_value = array[i].m_value;
+       }
+       for (i = 0; i < element_count; ++i)
+       {
+               fi = sorted[i].m_key;
+               pos = D11_1(fi);
+               pos = ++b1[pos];
+               array[pos].m_key = sorted[i].m_key;
+               array[pos].m_value = sorted[i].m_value;
+       }
+       for (i = 0; i < element_count; ++i)
+       {
+               fi = array[i].m_key;
+               pos = D11_2(fi);
+               pos = ++b2[pos];
+               sorted[pos].m_key = array[i].m_key;
+               sorted[pos].m_value = array[i].m_value;
+       }
+}
+
+/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN
+/*!
+*\param array Array of elements to sort
+*\param sorted_tokens Tokens of sorted elements
+*\param element_count element count
+*\param uintkey_macro Functor which retrieves the integer representation of an array element
+*/
+template <typename T, class GETKEY_CLASS>
+void gim_radix_sort_array_tokens(
+       T* array,
+       GIM_RSORT_TOKEN* sorted_tokens,
+       GUINT element_count, GETKEY_CLASS uintkey_macro)
+{
+       GIM_RSORT_TOKEN* _unsorted = (GIM_RSORT_TOKEN*)gim_alloc(sizeof(GIM_RSORT_TOKEN) * element_count);
+       for (GUINT _i = 0; _i < element_count; ++_i)
+       {
+               _unsorted[_i].m_key = uintkey_macro(array[_i]);
+               _unsorted[_i].m_value = _i;
+       }
+       gim_radix_sort_rtokens(_unsorted, sorted_tokens, element_count);
+       gim_free(_unsorted);
+       gim_free(_unsorted);
+}
+
+/// Sorts array in place. For generic use
+/*!
+\param type Type of the array
+\param array
+\param element_count
+\param get_uintkey_macro Macro for extract the Integer value of the element. Similar to SIMPLE_GET_UINTKEY
+\param copy_elements_macro Macro for copy elements, similar to SIMPLE_COPY_ELEMENTS
+*/
+template <typename T, class GETKEY_CLASS, class COPY_CLASS>
+void gim_radix_sort(
+       T* array, GUINT element_count,
+       GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
+{
+       GIM_RSORT_TOKEN* _sorted = (GIM_RSORT_TOKEN*)gim_alloc(sizeof(GIM_RSORT_TOKEN) * element_count);
+       gim_radix_sort_array_tokens(array, _sorted, element_count, get_uintkey_macro);
+       T* _original_array = (T*)gim_alloc(sizeof(T) * element_count);
+       gim_simd_memcpy(_original_array, array, sizeof(T) * element_count);
+       for (GUINT _i = 0; _i < element_count; ++_i)
+       {
+               copy_elements_macro(array[_i], _original_array[_sorted[_i].m_value]);
+       }
+       gim_free(_original_array);
+       gim_free(_sorted);
+}
+
+//! Failsafe Iterative binary search,
+/*!
+If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
+\param _array
+\param _start_i the beginning of the array
+\param _end_i the ending  index of the array
+\param _search_key Value to find
+\param _comp_macro macro for comparing elements
+\param _found If true the value has found. Boolean
+\param _result_index the index of the found element, or if not found then it will get the index of the  closest bigger value
+*/
+template <class T, typename KEYCLASS, typename COMP_CLASS>
+bool gim_binary_search_ex(
+       const T* _array, GUINT _start_i,
+       GUINT _end_i, GUINT& _result_index,
+       const KEYCLASS& _search_key,
+       COMP_CLASS _comp_macro)
+{
+       GUINT _k;
+       int _comp_result;
+       GUINT _i = _start_i;
+       GUINT _j = _end_i + 1;
+       while (_i < _j)
+       {
+               _k = (_j + _i - 1) / 2;
+               _comp_result = _comp_macro(_array[_k], _search_key);
+               if (_comp_result == 0)
+               {
+                       _result_index = _k;
+                       return true;
+               }
+               else if (_comp_result < 0)
+               {
+                       _i = _k + 1;
+               }
+               else
+               {
+                       _j = _k;
+               }
+       }
+       _result_index = _i;
+       return false;
+}
+
+//! Failsafe Iterative binary search,Template version
+/*!
+If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
+\param _array
+\param _start_i the beginning of the array
+\param _end_i the ending  index of the array
+\param _search_key Value to find
+\param _result_index the index of the found element, or if not found then it will get the index of the  closest bigger value
+\return true if found, else false
+*/
+template <class T>
+bool gim_binary_search(
+       const T* _array, GUINT _start_i,
+       GUINT _end_i, const T& _search_key,
+       GUINT& _result_index)
+{
+       GUINT _i = _start_i;
+       GUINT _j = _end_i + 1;
+       GUINT _k;
+       while (_i < _j)
+       {
+               _k = (_j + _i - 1) / 2;
+               if (_array[_k] == _search_key)
+               {
+                       _result_index = _k;
+                       return true;
+               }
+               else if (_array[_k] < _search_key)
+               {
+                       _i = _k + 1;
+               }
+               else
+               {
+                       _j = _k;
+               }
+       }
+       _result_index = _i;
+       return false;
+}
+
+///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
+template <typename T, typename COMP_CLASS>
+void gim_down_heap(T* pArr, GUINT k, GUINT n, COMP_CLASS CompareFunc)
+{
+       /*  PRE: a[k+1..N] is a heap */
+       /* POST:  a[k..N]  is a heap */
+
+       T temp = pArr[k - 1];
+       /* k has child(s) */
+       while (k <= n / 2)
+       {
+               int child = 2 * k;
+
+               if ((child < (int)n) && CompareFunc(pArr[child - 1], pArr[child]) < 0)
+               {
+                       child++;
+               }
+               /* pick larger child */
+               if (CompareFunc(temp, pArr[child - 1]) < 0)
+               {
+                       /* move child up */
+                       pArr[k - 1] = pArr[child - 1];
+                       k = child;
+               }
+               else
+               {
+                       break;
+               }
+       }
+       pArr[k - 1] = temp;
+} /*downHeap*/
+
+template <typename T, typename COMP_CLASS>
+void gim_heap_sort(T* pArr, GUINT element_count, COMP_CLASS CompareFunc)
+{
+       /* sort a[0..N-1],  N.B. 0 to N-1 */
+       GUINT k;
+       GUINT n = element_count;
+       for (k = n / 2; k > 0; k--)
+       {
+               gim_down_heap(pArr, k, n, CompareFunc);
+       }
+
+       /* a[1..N] is now a heap */
+       while (n >= 2)
+       {
+               gim_swap_elements(pArr, 0, n - 1); /* largest of a[0..n-1] */
+               --n;
+               /* restore a[1..i-1] heap */
+               gim_down_heap(pArr, 1, n, CompareFunc);
+       }
+}
+
+#endif  // GIM_RADIXSORT_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_tri_collision.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_tri_collision.cpp
new file mode 100644 (file)
index 0000000..8d83e95
--- /dev/null
@@ -0,0 +1,619 @@
+
+/*! \file gim_tri_collision.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_tri_collision.h"
+
+#define TRI_LOCAL_EPSILON 0.000001f
+#define MIN_EDGE_EDGE_DIS 0.00001f
+
+class GIM_TRIANGLE_CALCULATION_CACHE
+{
+public:
+       GREAL margin;
+       btVector3 tu_vertices[3];
+       btVector3 tv_vertices[3];
+       btVector4 tu_plane;
+       btVector4 tv_plane;
+       btVector3 closest_point_u;
+       btVector3 closest_point_v;
+       btVector3 edge_edge_dir;
+       btVector3 distances;
+       GREAL du[4];
+       GREAL du0du1;
+       GREAL du0du2;
+       GREAL dv[4];
+       GREAL dv0dv1;
+       GREAL dv0dv2;
+       btVector3 temp_points[MAX_TRI_CLIPPING];
+       btVector3 temp_points1[MAX_TRI_CLIPPING];
+       btVector3 contact_points[MAX_TRI_CLIPPING];
+
+       //! if returns false, the faces are paralele
+       SIMD_FORCE_INLINE bool compute_intervals(
+               const GREAL &D0,
+               const GREAL &D1,
+               const GREAL &D2,
+               const GREAL &D0D1,
+               const GREAL &D0D2,
+               GREAL &scale_edge0,
+               GREAL &scale_edge1,
+               GUINT &edge_index0,
+               GUINT &edge_index1)
+       {
+               if (D0D1 > 0.0f)
+               {
+                       /* here we know that D0D2<=0.0 */
+                       /* that is D0, D1 are on the same side, D2 on the other or on the plane */
+                       scale_edge0 = -D2 / (D0 - D2);
+                       scale_edge1 = -D1 / (D2 - D1);
+                       edge_index0 = 2;
+                       edge_index1 = 1;
+               }
+               else if (D0D2 > 0.0f)
+               {
+                       /* here we know that d0d1<=0.0 */
+                       scale_edge0 = -D0 / (D1 - D0);
+                       scale_edge1 = -D1 / (D2 - D1);
+                       edge_index0 = 0;
+                       edge_index1 = 1;
+               }
+               else if (D1 * D2 > 0.0f || D0 != 0.0f)
+               {
+                       /* here we know that d0d1<=0.0 or that D0!=0.0 */
+                       scale_edge0 = -D0 / (D1 - D0);
+                       scale_edge1 = -D2 / (D0 - D2);
+                       edge_index0 = 0;
+                       edge_index1 = 2;
+               }
+               else
+               {
+                       return false;
+               }
+               return true;
+       }
+
+       //! clip triangle
+       /*!
+       */
+       SIMD_FORCE_INLINE GUINT clip_triangle(
+               const btVector4 &tri_plane,
+               const btVector3 *tripoints,
+               const btVector3 *srcpoints,
+               btVector3 *clip_points)
+       {
+               // edge 0
+
+               btVector4 edgeplane;
+
+               EDGE_PLANE(tripoints[0], tripoints[1], tri_plane, edgeplane);
+
+               GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
+                       edgeplane, srcpoints[0], srcpoints[1], srcpoints[2], temp_points);
+
+               if (clipped_count == 0) return 0;
+
+               // edge 1
+
+               EDGE_PLANE(tripoints[1], tripoints[2], tri_plane, edgeplane);
+
+               clipped_count = PLANE_CLIP_POLYGON3D(
+                       edgeplane, temp_points, clipped_count, temp_points1);
+
+               if (clipped_count == 0) return 0;
+
+               // edge 2
+
+               EDGE_PLANE(tripoints[2], tripoints[0], tri_plane, edgeplane);
+
+               clipped_count = PLANE_CLIP_POLYGON3D(
+                       edgeplane, temp_points1, clipped_count, clip_points);
+
+               return clipped_count;
+
+               /*GUINT i0 = (tri_plane.closestAxis()+1)%3;
+               GUINT i1 = (i0+1)%3;
+               // edge 0
+               btVector3 temp_points[MAX_TRI_CLIPPING];
+               btVector3 temp_points1[MAX_TRI_CLIPPING];
+
+               GUINT clipped_count= PLANE_CLIP_TRIANGLE_GENERIC(
+                       0,srcpoints[0],srcpoints[1],srcpoints[2],temp_points,
+                       DISTANCE_EDGE(tripoints[0],tripoints[1],i0,i1));
+               
+               
+               if(clipped_count == 0) return 0;
+
+               // edge 1
+               clipped_count = PLANE_CLIP_POLYGON_GENERIC(
+                       0,temp_points,clipped_count,temp_points1,
+                       DISTANCE_EDGE(tripoints[1],tripoints[2],i0,i1));
+
+               if(clipped_count == 0) return 0;
+
+               // edge 2
+               clipped_count = PLANE_CLIP_POLYGON_GENERIC(
+                       0,temp_points1,clipped_count,clipped_points,
+                       DISTANCE_EDGE(tripoints[2],tripoints[0],i0,i1));
+
+               return clipped_count;*/
+       }
+
+       SIMD_FORCE_INLINE void sort_isect(
+               GREAL &isect0, GREAL &isect1, GUINT &e0, GUINT &e1, btVector3 &vec0, btVector3 &vec1)
+       {
+               if (isect1 < isect0)
+               {
+                       //swap
+                       GIM_SWAP_NUMBERS(isect0, isect1);
+                       GIM_SWAP_NUMBERS(e0, e1);
+                       btVector3 tmp = vec0;
+                       vec0 = vec1;
+                       vec1 = tmp;
+               }
+       }
+
+       //! Test verifying interval intersection with the direction between planes
+       /*!
+       \pre tv_plane and tu_plane must be set
+       \post
+       distances[2] is set with the distance
+       closest_point_u, closest_point_v, edge_edge_dir are set too
+       \return
+       - 0: faces are paralele
+       - 1: face U casts face V
+       - 2: face V casts face U
+       - 3: nearest edges
+       */
+       SIMD_FORCE_INLINE GUINT cross_line_intersection_test()
+       {
+               // Compute direction of intersection line
+               edge_edge_dir = tu_plane.cross(tv_plane);
+               GREAL Dlen;
+               VEC_LENGTH(edge_edge_dir, Dlen);
+
+               if (Dlen < 0.0001)
+               {
+                       return 0;  //faces near paralele
+               }
+
+               edge_edge_dir *= 1 / Dlen;  //normalize
+
+               // Compute interval for triangle 1
+               GUINT tu_e0, tu_e1;              //edge indices
+               GREAL tu_scale_e0, tu_scale_e1;  //edge scale
+               if (!compute_intervals(du[0], du[1], du[2],
+                                                          du0du1, du0du2, tu_scale_e0, tu_scale_e1, tu_e0, tu_e1)) return 0;
+
+               // Compute interval for triangle 2
+               GUINT tv_e0, tv_e1;              //edge indices
+               GREAL tv_scale_e0, tv_scale_e1;  //edge scale
+
+               if (!compute_intervals(dv[0], dv[1], dv[2],
+                                                          dv0dv1, dv0dv2, tv_scale_e0, tv_scale_e1, tv_e0, tv_e1)) return 0;
+
+               //proyected vertices
+               btVector3 up_e0 = tu_vertices[tu_e0].lerp(tu_vertices[(tu_e0 + 1) % 3], tu_scale_e0);
+               btVector3 up_e1 = tu_vertices[tu_e1].lerp(tu_vertices[(tu_e1 + 1) % 3], tu_scale_e1);
+
+               btVector3 vp_e0 = tv_vertices[tv_e0].lerp(tv_vertices[(tv_e0 + 1) % 3], tv_scale_e0);
+               btVector3 vp_e1 = tv_vertices[tv_e1].lerp(tv_vertices[(tv_e1 + 1) % 3], tv_scale_e1);
+
+               //proyected intervals
+               GREAL isect_u[] = {up_e0.dot(edge_edge_dir), up_e1.dot(edge_edge_dir)};
+               GREAL isect_v[] = {vp_e0.dot(edge_edge_dir), vp_e1.dot(edge_edge_dir)};
+
+               sort_isect(isect_u[0], isect_u[1], tu_e0, tu_e1, up_e0, up_e1);
+               sort_isect(isect_v[0], isect_v[1], tv_e0, tv_e1, vp_e0, vp_e1);
+
+               const GREAL midpoint_u = 0.5f * (isect_u[0] + isect_u[1]);  // midpoint
+               const GREAL midpoint_v = 0.5f * (isect_v[0] + isect_v[1]);  // midpoint
+
+               if (midpoint_u < midpoint_v)
+               {
+                       if (isect_u[1] >= isect_v[1])  // face U casts face V
+                       {
+                               return 1;
+                       }
+                       else if (isect_v[0] <= isect_u[0])  // face V casts face U
+                       {
+                               return 2;
+                       }
+                       // closest points
+                       closest_point_u = up_e1;
+                       closest_point_v = vp_e0;
+                       // calc edges and separation
+
+                       if (isect_u[1] + MIN_EDGE_EDGE_DIS < isect_v[0])  //calc distance between two lines instead
+                       {
+                               SEGMENT_COLLISION(
+                                       tu_vertices[tu_e1], tu_vertices[(tu_e1 + 1) % 3],
+                                       tv_vertices[tv_e0], tv_vertices[(tv_e0 + 1) % 3],
+                                       closest_point_u,
+                                       closest_point_v);
+
+                               edge_edge_dir = closest_point_u - closest_point_v;
+                               VEC_LENGTH(edge_edge_dir, distances[2]);
+                               edge_edge_dir *= 1.0f / distances[2];  // normalize
+                       }
+                       else
+                       {
+                               distances[2] = isect_v[0] - isect_u[1];  //distance negative
+                                                                                                                //edge_edge_dir *= -1.0f; //normal pointing from V to U
+                       }
+               }
+               else
+               {
+                       if (isect_v[1] >= isect_u[1])  // face V casts face U
+                       {
+                               return 2;
+                       }
+                       else if (isect_u[0] <= isect_v[0])  // face U casts face V
+                       {
+                               return 1;
+                       }
+                       // closest points
+                       closest_point_u = up_e0;
+                       closest_point_v = vp_e1;
+                       // calc edges and separation
+
+                       if (isect_v[1] + MIN_EDGE_EDGE_DIS < isect_u[0])  //calc distance between two lines instead
+                       {
+                               SEGMENT_COLLISION(
+                                       tu_vertices[tu_e0], tu_vertices[(tu_e0 + 1) % 3],
+                                       tv_vertices[tv_e1], tv_vertices[(tv_e1 + 1) % 3],
+                                       closest_point_u,
+                                       closest_point_v);
+
+                               edge_edge_dir = closest_point_u - closest_point_v;
+                               VEC_LENGTH(edge_edge_dir, distances[2]);
+                               edge_edge_dir *= 1.0f / distances[2];  // normalize
+                       }
+                       else
+                       {
+                               distances[2] = isect_u[0] - isect_v[1];  //distance negative
+                                                                                                                //edge_edge_dir *= -1.0f; //normal pointing from V to U
+                       }
+               }
+               return 3;
+       }
+
+       //! collides by two sides
+       SIMD_FORCE_INLINE bool triangle_collision(
+               const btVector3 &u0,
+               const btVector3 &u1,
+               const btVector3 &u2,
+               GREAL margin_u,
+               const btVector3 &v0,
+               const btVector3 &v1,
+               const btVector3 &v2,
+               GREAL margin_v,
+               GIM_TRIANGLE_CONTACT_DATA &contacts)
+       {
+               margin = margin_u + margin_v;
+
+               tu_vertices[0] = u0;
+               tu_vertices[1] = u1;
+               tu_vertices[2] = u2;
+
+               tv_vertices[0] = v0;
+               tv_vertices[1] = v1;
+               tv_vertices[2] = v2;
+
+               //create planes
+               // plane v vs U points
+
+               TRIANGLE_PLANE(tv_vertices[0], tv_vertices[1], tv_vertices[2], tv_plane);
+
+               du[0] = DISTANCE_PLANE_POINT(tv_plane, tu_vertices[0]);
+               du[1] = DISTANCE_PLANE_POINT(tv_plane, tu_vertices[1]);
+               du[2] = DISTANCE_PLANE_POINT(tv_plane, tu_vertices[2]);
+
+               du0du1 = du[0] * du[1];
+               du0du2 = du[0] * du[2];
+
+               if (du0du1 > 0.0f && du0du2 > 0.0f)  // same sign on all of them + not equal 0 ?
+               {
+                       if (du[0] < 0)  //we need test behind the triangle plane
+                       {
+                               distances[0] = GIM_MAX3(du[0], du[1], du[2]);
+                               distances[0] = -distances[0];
+                               if (distances[0] > margin) return false;  //never intersect
+
+                               //reorder triangle v
+                               VEC_SWAP(tv_vertices[0], tv_vertices[1]);
+                               VEC_SCALE_4(tv_plane, -1.0f, tv_plane);
+                       }
+                       else
+                       {
+                               distances[0] = GIM_MIN3(du[0], du[1], du[2]);
+                               if (distances[0] > margin) return false;  //never intersect
+                       }
+               }
+               else
+               {
+                       //Look if we need to invert the triangle
+                       distances[0] = (du[0] + du[1] + du[2]) / 3.0f;  //centroid
+
+                       if (distances[0] < 0.0f)
+                       {
+                               //reorder triangle v
+                               VEC_SWAP(tv_vertices[0], tv_vertices[1]);
+                               VEC_SCALE_4(tv_plane, -1.0f, tv_plane);
+
+                               distances[0] = GIM_MAX3(du[0], du[1], du[2]);
+                               distances[0] = -distances[0];
+                       }
+                       else
+                       {
+                               distances[0] = GIM_MIN3(du[0], du[1], du[2]);
+                       }
+               }
+
+               // plane U vs V points
+
+               TRIANGLE_PLANE(tu_vertices[0], tu_vertices[1], tu_vertices[2], tu_plane);
+
+               dv[0] = DISTANCE_PLANE_POINT(tu_plane, tv_vertices[0]);
+               dv[1] = DISTANCE_PLANE_POINT(tu_plane, tv_vertices[1]);
+               dv[2] = DISTANCE_PLANE_POINT(tu_plane, tv_vertices[2]);
+
+               dv0dv1 = dv[0] * dv[1];
+               dv0dv2 = dv[0] * dv[2];
+
+               if (dv0dv1 > 0.0f && dv0dv2 > 0.0f)  // same sign on all of them + not equal 0 ?
+               {
+                       if (dv[0] < 0)  //we need test behind the triangle plane
+                       {
+                               distances[1] = GIM_MAX3(dv[0], dv[1], dv[2]);
+                               distances[1] = -distances[1];
+                               if (distances[1] > margin) return false;  //never intersect
+
+                               //reorder triangle u
+                               VEC_SWAP(tu_vertices[0], tu_vertices[1]);
+                               VEC_SCALE_4(tu_plane, -1.0f, tu_plane);
+                       }
+                       else
+                       {
+                               distances[1] = GIM_MIN3(dv[0], dv[1], dv[2]);
+                               if (distances[1] > margin) return false;  //never intersect
+                       }
+               }
+               else
+               {
+                       //Look if we need to invert the triangle
+                       distances[1] = (dv[0] + dv[1] + dv[2]) / 3.0f;  //centroid
+
+                       if (distances[1] < 0.0f)
+                       {
+                               //reorder triangle v
+                               VEC_SWAP(tu_vertices[0], tu_vertices[1]);
+                               VEC_SCALE_4(tu_plane, -1.0f, tu_plane);
+
+                               distances[1] = GIM_MAX3(dv[0], dv[1], dv[2]);
+                               distances[1] = -distances[1];
+                       }
+                       else
+                       {
+                               distances[1] = GIM_MIN3(dv[0], dv[1], dv[2]);
+                       }
+               }
+
+               GUINT bl;
+               /* bl = cross_line_intersection_test();
+               if(bl==3)
+               {
+                       //take edge direction too
+                       bl = distances.maxAxis();
+               }
+               else
+               {*/
+               bl = 0;
+               if (distances[0] < distances[1]) bl = 1;
+               //}
+
+               if (bl == 2)  //edge edge separation
+               {
+                       if (distances[2] > margin) return false;
+
+                       contacts.m_penetration_depth = -distances[2] + margin;
+                       contacts.m_points[0] = closest_point_v;
+                       contacts.m_point_count = 1;
+                       VEC_COPY(contacts.m_separating_normal, edge_edge_dir);
+
+                       return true;
+               }
+
+               //clip face against other
+
+               GUINT point_count;
+               //TODO
+               if (bl == 0)  //clip U points against V
+               {
+                       point_count = clip_triangle(tv_plane, tv_vertices, tu_vertices, contact_points);
+                       if (point_count == 0) return false;
+                       contacts.merge_points(tv_plane, margin, contact_points, point_count);
+               }
+               else  //clip V points against U
+               {
+                       point_count = clip_triangle(tu_plane, tu_vertices, tv_vertices, contact_points);
+                       if (point_count == 0) return false;
+                       contacts.merge_points(tu_plane, margin, contact_points, point_count);
+                       contacts.m_separating_normal *= -1.f;
+               }
+               if (contacts.m_point_count == 0) return false;
+               return true;
+       }
+};
+
+/*class GIM_TRIANGLE_CALCULATION_CACHE
+{
+public:
+       GREAL margin;
+       GUINT clipped_count;
+       btVector3 tu_vertices[3];
+       btVector3 tv_vertices[3];
+       btVector3 temp_points[MAX_TRI_CLIPPING];
+       btVector3 temp_points1[MAX_TRI_CLIPPING];
+       btVector3 clipped_points[MAX_TRI_CLIPPING];
+       GIM_TRIANGLE_CONTACT_DATA contacts1;
+       GIM_TRIANGLE_CONTACT_DATA contacts2;
+
+
+       //! clip triangle
+       GUINT clip_triangle(
+               const btVector4 & tri_plane,
+               const btVector3 * tripoints,
+               const btVector3 * srcpoints,
+               btVector3 * clipped_points)
+       {
+               // edge 0
+
+               btVector4 edgeplane;
+
+               EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
+
+               GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
+                       edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
+
+               if(clipped_count == 0) return 0;
+
+               // edge 1
+
+               EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
+
+               clipped_count = PLANE_CLIP_POLYGON3D(
+                       edgeplane,temp_points,clipped_count,temp_points1);
+
+               if(clipped_count == 0) return 0;
+
+               // edge 2
+
+               EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
+
+               clipped_count = PLANE_CLIP_POLYGON3D(
+                       edgeplane,temp_points1,clipped_count,clipped_points);
+
+               return clipped_count;
+       }
+
+
+
+
+       //! collides only on one side
+       bool triangle_collision(
+                                       const btVector3 & u0,
+                                       const btVector3 & u1,
+                                       const btVector3 & u2,
+                                       GREAL margin_u,
+                                       const btVector3 & v0,
+                                       const btVector3 & v1,
+                                       const btVector3 & v2,
+                                       GREAL margin_v,
+                                       GIM_TRIANGLE_CONTACT_DATA & contacts)
+       {
+
+               margin = margin_u + margin_v;
+
+               
+               tu_vertices[0] = u0;
+               tu_vertices[1] = u1;
+               tu_vertices[2] = u2;
+
+               tv_vertices[0] = v0;
+               tv_vertices[1] = v1;
+               tv_vertices[2] = v2;
+
+               //create planes
+               // plane v vs U points
+
+
+               TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],contacts1.m_separating_normal);
+
+               clipped_count = clip_triangle(
+                       contacts1.m_separating_normal,tv_vertices,tu_vertices,clipped_points);
+
+               if(clipped_count == 0 )
+               {
+                        return false;//Reject
+               }
+
+               //find most deep interval face1
+               contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
+               if(contacts1.m_point_count == 0) return false; // too far
+
+               //Normal pointing to triangle1
+               //contacts1.m_separating_normal *= -1.f;
+
+               //Clip tri1 by tri2 edges
+
+               TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],contacts2.m_separating_normal);
+
+               clipped_count = clip_triangle(
+                       contacts2.m_separating_normal,tu_vertices,tv_vertices,clipped_points);
+
+               if(clipped_count == 0 )
+               {
+                        return false;//Reject
+               }
+
+               //find most deep interval face1
+               contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
+               if(contacts2.m_point_count == 0) return false; // too far
+
+               contacts2.m_separating_normal *= -1.f;
+
+               ////check most dir for contacts
+               if(contacts2.m_penetration_depth<contacts1.m_penetration_depth)
+               {
+                       contacts.copy_from(contacts2);
+               }
+               else
+               {
+                       contacts.copy_from(contacts1);
+               }
+               return true;
+       }
+
+
+};*/
+
+bool GIM_TRIANGLE::collide_triangle_hard_test(
+       const GIM_TRIANGLE &other,
+       GIM_TRIANGLE_CONTACT_DATA &contact_data) const
+{
+       GIM_TRIANGLE_CALCULATION_CACHE calc_cache;
+       return calc_cache.triangle_collision(
+               m_vertices[0], m_vertices[1], m_vertices[2], m_margin,
+               other.m_vertices[0], other.m_vertices[1], other.m_vertices[2], other.m_margin,
+               contact_data);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_tri_collision.h b/dali-physics/third-party/bullet3/src/BulletCollision/Gimpact/gim_tri_collision.h
new file mode 100644 (file)
index 0000000..e6d4bf5
--- /dev/null
@@ -0,0 +1,368 @@
+#ifndef GIM_TRI_COLLISION_H_INCLUDED
+#define GIM_TRI_COLLISION_H_INCLUDED
+
+/*! \file gim_tri_collision.h
+\author Francisco Leon Najera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman@yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_box_collision.h"
+#include "gim_clip_polygon.h"
+
+#ifndef MAX_TRI_CLIPPING
+#define MAX_TRI_CLIPPING 16
+#endif
+
+//! Structure for collision
+struct GIM_TRIANGLE_CONTACT_DATA
+{
+       GREAL m_penetration_depth;
+       GUINT m_point_count;
+       btVector4 m_separating_normal;
+       btVector3 m_points[MAX_TRI_CLIPPING];
+
+       SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT_DATA &other)
+       {
+               m_penetration_depth = other.m_penetration_depth;
+               m_separating_normal = other.m_separating_normal;
+               m_point_count = other.m_point_count;
+               GUINT i = m_point_count;
+               while (i--)
+               {
+                       m_points[i] = other.m_points[i];
+               }
+       }
+
+       GIM_TRIANGLE_CONTACT_DATA()
+       {
+       }
+
+       GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA &other)
+       {
+               copy_from(other);
+       }
+
+       //! classify points that are closer
+       template <typename DISTANCE_FUNC, typename CLASS_PLANE>
+       SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE &plane,
+                                                                                          GREAL margin, const btVector3 *points, GUINT point_count, DISTANCE_FUNC distance_func)
+       {
+               m_point_count = 0;
+               m_penetration_depth = -1000.0f;
+
+               GUINT point_indices[MAX_TRI_CLIPPING];
+
+               GUINT _k;
+
+               for (_k = 0; _k < point_count; _k++)
+               {
+                       GREAL _dist = -distance_func(plane, points[_k]) + margin;
+
+                       if (_dist >= 0.0f)
+                       {
+                               if (_dist > m_penetration_depth)
+                               {
+                                       m_penetration_depth = _dist;
+                                       point_indices[0] = _k;
+                                       m_point_count = 1;
+                               }
+                               else if ((_dist + G_EPSILON) >= m_penetration_depth)
+                               {
+                                       point_indices[m_point_count] = _k;
+                                       m_point_count++;
+                               }
+                       }
+               }
+
+               for (_k = 0; _k < m_point_count; _k++)
+               {
+                       m_points[_k] = points[point_indices[_k]];
+               }
+       }
+
+       //! classify points that are closer
+       SIMD_FORCE_INLINE void merge_points(const btVector4 &plane, GREAL margin,
+                                                                               const btVector3 *points, GUINT point_count)
+       {
+               m_separating_normal = plane;
+               mergepoints_generic(plane, margin, points, point_count, DISTANCE_PLANE_3D_FUNC());
+       }
+};
+
+//! Class for colliding triangles
+class GIM_TRIANGLE
+{
+public:
+       btScalar m_margin;
+       btVector3 m_vertices[3];
+
+       GIM_TRIANGLE() : m_margin(0.1f)
+       {
+       }
+
+       SIMD_FORCE_INLINE GIM_AABB get_box() const
+       {
+               return GIM_AABB(m_vertices[0], m_vertices[1], m_vertices[2], m_margin);
+       }
+
+       SIMD_FORCE_INLINE void get_normal(btVector3 &normal) const
+       {
+               TRIANGLE_NORMAL(m_vertices[0], m_vertices[1], m_vertices[2], normal);
+       }
+
+       SIMD_FORCE_INLINE void get_plane(btVector4 &plane) const
+       {
+               TRIANGLE_PLANE(m_vertices[0], m_vertices[1], m_vertices[2], plane);
+               ;
+       }
+
+       SIMD_FORCE_INLINE void apply_transform(const btTransform &trans)
+       {
+               m_vertices[0] = trans(m_vertices[0]);
+               m_vertices[1] = trans(m_vertices[1]);
+               m_vertices[2] = trans(m_vertices[2]);
+       }
+
+       SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index, const btVector3 &triangle_normal, btVector4 &plane) const
+       {
+               const btVector3 &e0 = m_vertices[edge_index];
+               const btVector3 &e1 = m_vertices[(edge_index + 1) % 3];
+               EDGE_PLANE(e0, e1, triangle_normal, plane);
+       }
+
+       //! Gets the relative transformation of this triangle
+       /*!
+    The transformation is oriented to the triangle normal , and aligned to the 1st edge of this triangle. The position corresponds to vertice 0:
+    - triangle normal corresponds to Z axis.
+    - 1st normalized edge corresponds to X axis,
+
+    */
+       SIMD_FORCE_INLINE void get_triangle_transform(btTransform &triangle_transform) const
+       {
+               btMatrix3x3 &matrix = triangle_transform.getBasis();
+
+               btVector3 zaxis;
+               get_normal(zaxis);
+               MAT_SET_Z(matrix, zaxis);
+
+               btVector3 xaxis = m_vertices[1] - m_vertices[0];
+               VEC_NORMALIZE(xaxis);
+               MAT_SET_X(matrix, xaxis);
+
+               //y axis
+               xaxis = zaxis.cross(xaxis);
+               MAT_SET_Y(matrix, xaxis);
+
+               triangle_transform.setOrigin(m_vertices[0]);
+       }
+
+       //! Test triangles by finding separating axis
+       /*!
+       \param other Triangle for collide
+       \param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
+       */
+       bool collide_triangle_hard_test(
+               const GIM_TRIANGLE &other,
+               GIM_TRIANGLE_CONTACT_DATA &contact_data) const;
+
+       //! Test boxes before doing hard test
+       /*!
+       \param other Triangle for collide
+       \param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
+       \
+       */
+       SIMD_FORCE_INLINE bool collide_triangle(
+               const GIM_TRIANGLE &other,
+               GIM_TRIANGLE_CONTACT_DATA &contact_data) const
+       {
+               //test box collisioin
+               GIM_AABB boxu(m_vertices[0], m_vertices[1], m_vertices[2], m_margin);
+               GIM_AABB boxv(other.m_vertices[0], other.m_vertices[1], other.m_vertices[2], other.m_margin);
+               if (!boxu.has_collision(boxv)) return false;
+
+               //do hard test
+               return collide_triangle_hard_test(other, contact_data);
+       }
+
+       /*!
+
+       Solve the System for u,v parameters:
+
+       u*axe1[i1] + v*axe2[i1] = vecproj[i1]
+       u*axe1[i2] + v*axe2[i2] = vecproj[i2]
+
+       sustitute:
+       v = (vecproj[i2] - u*axe1[i2])/axe2[i2]
+
+       then the first equation in terms of 'u':
+
+       --> u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1]
+
+       --> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1]
+
+       --> u*(axe1[i1]  - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2]
+
+       --> u*((axe1[i1]*axe2[i2]  - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2]
+
+       --> u*(axe1[i1]*axe2[i2]  - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]
+
+       --> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2]  - axe1[i2]*axe2[i1])
+
+if 0.0<= u+v <=1.0 then they are inside of triangle
+
+       \return false if the point is outside of triangle.This function  doesn't take the margin
+       */
+       SIMD_FORCE_INLINE bool get_uv_parameters(
+               const btVector3 &point,
+               const btVector3 &tri_plane,
+               GREAL &u, GREAL &v) const
+       {
+               btVector3 _axe1 = m_vertices[1] - m_vertices[0];
+               btVector3 _axe2 = m_vertices[2] - m_vertices[0];
+               btVector3 _vecproj = point - m_vertices[0];
+               GUINT _i1 = (tri_plane.closestAxis() + 1) % 3;
+               GUINT _i2 = (_i1 + 1) % 3;
+               if (btFabs(_axe2[_i2]) < G_EPSILON)
+               {
+                       u = (_vecproj[_i2] * _axe2[_i1] - _vecproj[_i1] * _axe2[_i2]) / (_axe1[_i2] * _axe2[_i1] - _axe1[_i1] * _axe2[_i2]);
+                       v = (_vecproj[_i1] - u * _axe1[_i1]) / _axe2[_i1];
+               }
+               else
+               {
+                       u = (_vecproj[_i1] * _axe2[_i2] - _vecproj[_i2] * _axe2[_i1]) / (_axe1[_i1] * _axe2[_i2] - _axe1[_i2] * _axe2[_i1]);
+                       v = (_vecproj[_i2] - u * _axe1[_i2]) / _axe2[_i2];
+               }
+
+               if (u < -G_EPSILON)
+               {
+                       return false;
+               }
+               else if (v < -G_EPSILON)
+               {
+                       return false;
+               }
+               else
+               {
+                       btScalar sumuv;
+                       sumuv = u + v;
+                       if (sumuv < -G_EPSILON)
+                       {
+                               return false;
+                       }
+                       else if (sumuv - 1.0f > G_EPSILON)
+                       {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       //! is point in triangle beam?
+       /*!
+       Test if point is in triangle, with m_margin tolerance
+       */
+       SIMD_FORCE_INLINE bool is_point_inside(const btVector3 &point, const btVector3 &tri_normal) const
+       {
+               //Test with edge 0
+               btVector4 edge_plane;
+               this->get_edge_plane(0, tri_normal, edge_plane);
+               GREAL dist = DISTANCE_PLANE_POINT(edge_plane, point);
+               if (dist - m_margin > 0.0f) return false;  // outside plane
+
+               this->get_edge_plane(1, tri_normal, edge_plane);
+               dist = DISTANCE_PLANE_POINT(edge_plane, point);
+               if (dist - m_margin > 0.0f) return false;  // outside plane
+
+               this->get_edge_plane(2, tri_normal, edge_plane);
+               dist = DISTANCE_PLANE_POINT(edge_plane, point);
+               if (dist - m_margin > 0.0f) return false;  // outside plane
+               return true;
+       }
+
+       //! Bidireccional ray collision
+       SIMD_FORCE_INLINE bool ray_collision(
+               const btVector3 &vPoint,
+               const btVector3 &vDir, btVector3 &pout, btVector3 &triangle_normal,
+               GREAL &tparam, GREAL tmax = G_REAL_INFINITY)
+       {
+               btVector4 faceplane;
+               {
+                       btVector3 dif1 = m_vertices[1] - m_vertices[0];
+                       btVector3 dif2 = m_vertices[2] - m_vertices[0];
+                       VEC_CROSS(faceplane, dif1, dif2);
+                       faceplane[3] = m_vertices[0].dot(faceplane);
+               }
+
+               GUINT res = LINE_PLANE_COLLISION(faceplane, vDir, vPoint, pout, tparam, btScalar(0), tmax);
+               if (res == 0) return false;
+               if (!is_point_inside(pout, faceplane)) return false;
+
+               if (res == 2)  //invert normal
+               {
+                       triangle_normal.setValue(-faceplane[0], -faceplane[1], -faceplane[2]);
+               }
+               else
+               {
+                       triangle_normal.setValue(faceplane[0], faceplane[1], faceplane[2]);
+               }
+
+               VEC_NORMALIZE(triangle_normal);
+
+               return true;
+       }
+
+       //! one direccion ray collision
+       SIMD_FORCE_INLINE bool ray_collision_front_side(
+               const btVector3 &vPoint,
+               const btVector3 &vDir, btVector3 &pout, btVector3 &triangle_normal,
+               GREAL &tparam, GREAL tmax = G_REAL_INFINITY)
+       {
+               btVector4 faceplane;
+               {
+                       btVector3 dif1 = m_vertices[1] - m_vertices[0];
+                       btVector3 dif2 = m_vertices[2] - m_vertices[0];
+                       VEC_CROSS(faceplane, dif1, dif2);
+                       faceplane[3] = m_vertices[0].dot(faceplane);
+               }
+
+               GUINT res = LINE_PLANE_COLLISION(faceplane, vDir, vPoint, pout, tparam, btScalar(0), tmax);
+               if (res != 1) return false;
+
+               if (!is_point_inside(pout, faceplane)) return false;
+
+               triangle_normal.setValue(faceplane[0], faceplane[1], faceplane[2]);
+
+               VEC_NORMALIZE(triangle_normal);
+
+               return true;
+       }
+};
+
+#endif  // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
new file mode 100644 (file)
index 0000000..3c82133
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2014 Erwin Coumans http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_GJK_EPA_PENETATION_CONVEX_COLLISION_H
+#define BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
+
+#include "LinearMath/btTransform.h"  // Note that btVector3 might be double precision...
+#include "btGjkEpa3.h"
+#include "btGjkCollisionDescription.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+
+template <typename btConvexTemplate>
+bool btGjkEpaCalcPenDepth(const btConvexTemplate& a, const btConvexTemplate& b,
+                                                 const btGjkCollisionDescription& colDesc,
+                                                 btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB)
+{
+       (void)v;
+
+       //      const btScalar                          radialmargin(btScalar(0.));
+
+       btVector3 guessVector(b.getWorldTransform().getOrigin() - a.getWorldTransform().getOrigin());  //?? why not use the GJK input?
+
+       btGjkEpaSolver3::sResults results;
+
+       if (btGjkEpaSolver3_Penetration(a, b, guessVector, results))
+
+       {
+               //      debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
+               //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
+               wWitnessOnA = results.witnesses[0];
+               wWitnessOnB = results.witnesses[1];
+               v = results.normal;
+               return true;
+       }
+       else
+       {
+               if (btGjkEpaSolver3_Distance(a, b, guessVector, results))
+               {
+                       wWitnessOnA = results.witnesses[0];
+                       wWitnessOnB = results.witnesses[1];
+                       v = results.normal;
+                       return false;
+               }
+       }
+       return false;
+}
+
+template <typename btConvexTemplate, typename btGjkDistanceTemplate>
+int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate& b, const btGjkCollisionDescription& colDesc, btVoronoiSimplexSolver& simplexSolver, btGjkDistanceTemplate* distInfo)
+{
+       bool m_catchDegeneracies = true;
+       btScalar m_cachedSeparatingDistance = 0.f;
+
+       btScalar distance = btScalar(0.);
+       btVector3 normalInB(btScalar(0.), btScalar(0.), btScalar(0.));
+
+       btVector3 pointOnA, pointOnB;
+       btTransform localTransA = a.getWorldTransform();
+       btTransform localTransB = b.getWorldTransform();
+
+       btScalar marginA = a.getMargin();
+       btScalar marginB = b.getMargin();
+
+       int m_curIter = 0;
+       int gGjkMaxIter = colDesc.m_maxGjkIterations;  //this is to catch invalid input, perhaps check for #NaN?
+       btVector3 m_cachedSeparatingAxis = colDesc.m_firstDir;
+
+       bool isValid = false;
+       bool checkSimplex = false;
+       bool checkPenetration = true;
+       int m_degenerateSimplex = 0;
+
+       int m_lastUsedMethod = -1;
+
+       {
+               btScalar squaredDistance = BT_LARGE_FLOAT;
+               btScalar delta = btScalar(0.);
+
+               btScalar margin = marginA + marginB;
+
+               simplexSolver.reset();
+
+               for (;;)
+               //while (true)
+               {
+                       btVector3 separatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
+                       btVector3 separatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
+
+                       btVector3 pInA = a.getLocalSupportWithoutMargin(separatingAxisInA);
+                       btVector3 qInB = b.getLocalSupportWithoutMargin(separatingAxisInB);
+
+                       btVector3 pWorld = localTransA(pInA);
+                       btVector3 qWorld = localTransB(qInB);
+
+                       btVector3 w = pWorld - qWorld;
+                       delta = m_cachedSeparatingAxis.dot(w);
+
+                       // potential exit, they don't overlap
+                       if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * colDesc.m_maximumDistanceSquared))
+                       {
+                               m_degenerateSimplex = 10;
+                               checkSimplex = true;
+                               //checkPenetration = false;
+                               break;
+                       }
+
+                       //exit 0: the new point is already in the simplex, or we didn't come any closer
+                       if (simplexSolver.inSimplex(w))
+                       {
+                               m_degenerateSimplex = 1;
+                               checkSimplex = true;
+                               break;
+                       }
+                       // are we getting any closer ?
+                       btScalar f0 = squaredDistance - delta;
+                       btScalar f1 = squaredDistance * colDesc.m_gjkRelError2;
+
+                       if (f0 <= f1)
+                       {
+                               if (f0 <= btScalar(0.))
+                               {
+                                       m_degenerateSimplex = 2;
+                               }
+                               else
+                               {
+                                       m_degenerateSimplex = 11;
+                               }
+                               checkSimplex = true;
+                               break;
+                       }
+
+                       //add current vertex to simplex
+                       simplexSolver.addVertex(w, pWorld, qWorld);
+                       btVector3 newCachedSeparatingAxis;
+
+                       //calculate the closest point to the origin (update vector v)
+                       if (!simplexSolver.closest(newCachedSeparatingAxis))
+                       {
+                               m_degenerateSimplex = 3;
+                               checkSimplex = true;
+                               break;
+                       }
+
+                       if (newCachedSeparatingAxis.length2() < colDesc.m_gjkRelError2)
+                       {
+                               m_cachedSeparatingAxis = newCachedSeparatingAxis;
+                               m_degenerateSimplex = 6;
+                               checkSimplex = true;
+                               break;
+                       }
+
+                       btScalar previousSquaredDistance = squaredDistance;
+                       squaredDistance = newCachedSeparatingAxis.length2();
+#if 0
+            ///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
+            if (squaredDistance>previousSquaredDistance)
+            {
+                m_degenerateSimplex = 7;
+                squaredDistance = previousSquaredDistance;
+                checkSimplex = false;
+                break;
+            }
+#endif  //
+
+                       //redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
+
+                       //are we getting any closer ?
+                       if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
+                       {
+                               //                              m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+                               checkSimplex = true;
+                               m_degenerateSimplex = 12;
+
+                               break;
+                       }
+
+                       m_cachedSeparatingAxis = newCachedSeparatingAxis;
+
+                       //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
+                       if (m_curIter++ > gGjkMaxIter)
+                       {
+#if defined(DEBUG) || defined(_DEBUG)
+
+                               printf("btGjkPairDetector maxIter exceeded:%i\n", m_curIter);
+                               printf("sepAxis=(%f,%f,%f), squaredDistance = %f\n",
+                                          m_cachedSeparatingAxis.getX(),
+                                          m_cachedSeparatingAxis.getY(),
+                                          m_cachedSeparatingAxis.getZ(),
+                                          squaredDistance);
+#endif
+
+                               break;
+                       }
+
+                       bool check = (!simplexSolver.fullSimplex());
+                       //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
+
+                       if (!check)
+                       {
+                               //do we need this backup_closest here ?
+                               //                              m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+                               m_degenerateSimplex = 13;
+                               break;
+                       }
+               }
+
+               if (checkSimplex)
+               {
+                       simplexSolver.compute_points(pointOnA, pointOnB);
+                       normalInB = m_cachedSeparatingAxis;
+
+                       btScalar lenSqr = m_cachedSeparatingAxis.length2();
+
+                       //valid normal
+                       if (lenSqr < 0.0001)
+                       {
+                               m_degenerateSimplex = 5;
+                       }
+                       if (lenSqr > SIMD_EPSILON * SIMD_EPSILON)
+                       {
+                               btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
+                               normalInB *= rlen;  //normalize
+
+                               btScalar s = btSqrt(squaredDistance);
+
+                               btAssert(s > btScalar(0.0));
+                               pointOnA -= m_cachedSeparatingAxis * (marginA / s);
+                               pointOnB += m_cachedSeparatingAxis * (marginB / s);
+                               distance = ((btScalar(1.) / rlen) - margin);
+                               isValid = true;
+
+                               m_lastUsedMethod = 1;
+                       }
+                       else
+                       {
+                               m_lastUsedMethod = 2;
+                       }
+               }
+
+               bool catchDegeneratePenetrationCase =
+                       (m_catchDegeneracies && m_degenerateSimplex && ((distance + margin) < 0.01));
+
+               //if (checkPenetration && !isValid)
+               if (checkPenetration && (!isValid || catchDegeneratePenetrationCase))
+               {
+                       //penetration case
+
+                       //if there is no way to handle penetrations, bail out
+
+                       // Penetration depth case.
+                       btVector3 tmpPointOnA, tmpPointOnB;
+
+                       m_cachedSeparatingAxis.setZero();
+
+                       bool isValid2 = btGjkEpaCalcPenDepth(a, b,
+                                                                                                colDesc,
+                                                                                                m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB);
+
+                       if (isValid2)
+                       {
+                               btVector3 tmpNormalInB = tmpPointOnB - tmpPointOnA;
+                               btScalar lenSqr = tmpNormalInB.length2();
+                               if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
+                               {
+                                       tmpNormalInB = m_cachedSeparatingAxis;
+                                       lenSqr = m_cachedSeparatingAxis.length2();
+                               }
+
+                               if (lenSqr > (SIMD_EPSILON * SIMD_EPSILON))
+                               {
+                                       tmpNormalInB /= btSqrt(lenSqr);
+                                       btScalar distance2 = -(tmpPointOnA - tmpPointOnB).length();
+                                       //only replace valid penetrations when the result is deeper (check)
+                                       if (!isValid || (distance2 < distance))
+                                       {
+                                               distance = distance2;
+                                               pointOnA = tmpPointOnA;
+                                               pointOnB = tmpPointOnB;
+                                               normalInB = tmpNormalInB;
+
+                                               isValid = true;
+                                               m_lastUsedMethod = 3;
+                                       }
+                                       else
+                                       {
+                                               m_lastUsedMethod = 8;
+                                       }
+                               }
+                               else
+                               {
+                                       m_lastUsedMethod = 9;
+                               }
+                       }
+                       else
+
+                       {
+                               ///this is another degenerate case, where the initial GJK calculation reports a degenerate case
+                               ///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
+                               ///reports a valid positive distance. Use the results of the second GJK instead of failing.
+                               ///thanks to Jacob.Langford for the reproduction case
+                               ///http://code.google.com/p/bullet/issues/detail?id=250
+
+                               if (m_cachedSeparatingAxis.length2() > btScalar(0.))
+                               {
+                                       btScalar distance2 = (tmpPointOnA - tmpPointOnB).length() - margin;
+                                       //only replace valid distances when the distance is less
+                                       if (!isValid || (distance2 < distance))
+                                       {
+                                               distance = distance2;
+                                               pointOnA = tmpPointOnA;
+                                               pointOnB = tmpPointOnB;
+                                               pointOnA -= m_cachedSeparatingAxis * marginA;
+                                               pointOnB += m_cachedSeparatingAxis * marginB;
+                                               normalInB = m_cachedSeparatingAxis;
+                                               normalInB.normalize();
+
+                                               isValid = true;
+                                               m_lastUsedMethod = 6;
+                                       }
+                                       else
+                                       {
+                                               m_lastUsedMethod = 5;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (isValid && ((distance < 0) || (distance * distance < colDesc.m_maximumDistanceSquared)))
+       {
+               m_cachedSeparatingAxis = normalInB;
+               m_cachedSeparatingDistance = distance;
+               distInfo->m_distance = distance;
+               distInfo->m_normalBtoA = normalInB;
+               distInfo->m_pointOnB = pointOnB;
+               distInfo->m_pointOnA = pointOnB + normalInB * distance;
+               return 0;
+       }
+       return -m_lastUsedMethod;
+}
+
+#endif  //BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
new file mode 100644 (file)
index 0000000..623c58f
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btContinuousConvexCollision.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "LinearMath/btTransformUtil.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "btGjkPairDetector.h"
+#include "btPointCollector.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+btContinuousConvexCollision::btContinuousConvexCollision(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
+       : m_simplexSolver(simplexSolver),
+         m_penetrationDepthSolver(penetrationDepthSolver),
+         m_convexA(convexA),
+         m_convexB1(convexB),
+         m_planeShape(0)
+{
+}
+
+btContinuousConvexCollision::btContinuousConvexCollision(const btConvexShape* convexA, const btStaticPlaneShape* plane)
+       : m_simplexSolver(0),
+         m_penetrationDepthSolver(0),
+         m_convexA(convexA),
+         m_convexB1(0),
+         m_planeShape(plane)
+{
+}
+
+/// 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 64
+
+void btContinuousConvexCollision::computeClosestPoints(const btTransform& transA, const btTransform& transB, btPointCollector& pointCollector)
+{
+       if (m_convexB1)
+       {
+               m_simplexSolver->reset();
+               btGjkPairDetector gjk(m_convexA, m_convexB1, m_convexA->getShapeType(), m_convexB1->getShapeType(), m_convexA->getMargin(), m_convexB1->getMargin(), m_simplexSolver, m_penetrationDepthSolver);
+               btGjkPairDetector::ClosestPointInput input;
+               input.m_transformA = transA;
+               input.m_transformB = transB;
+               gjk.getClosestPoints(input, pointCollector, 0);
+       }
+       else
+       {
+               //convex versus plane
+               const btConvexShape* convexShape = m_convexA;
+               const btStaticPlaneShape* planeShape = m_planeShape;
+
+               const btVector3& planeNormal = planeShape->getPlaneNormal();
+               const btScalar& planeConstant = planeShape->getPlaneConstant();
+
+               btTransform convexWorldTransform = transA;
+               btTransform convexInPlaneTrans;
+               convexInPlaneTrans = transB.inverse() * convexWorldTransform;
+               btTransform planeInConvex;
+               planeInConvex = convexWorldTransform.inverse() * transB;
+
+               btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
+
+               btVector3 vtxInPlane = convexInPlaneTrans(vtx);
+               btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
+
+               btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
+               btVector3 vtxInPlaneWorld = transB * vtxInPlaneProjected;
+               btVector3 normalOnSurfaceB = transB.getBasis() * planeNormal;
+
+               pointCollector.addContactPoint(
+                       normalOnSurfaceB,
+                       vtxInPlaneWorld,
+                       distance);
+       }
+}
+
+bool btContinuousConvexCollision::calcTimeOfImpact(
+       const btTransform& fromA,
+       const btTransform& toA,
+       const btTransform& fromB,
+       const btTransform& toB,
+       CastResult& result)
+{
+       /// compute linear and angular velocity for this interval, to interpolate
+       btVector3 linVelA, angVelA, linVelB, angVelB;
+       btTransformUtil::calculateVelocity(fromA, toA, btScalar(1.), linVelA, angVelA);
+       btTransformUtil::calculateVelocity(fromB, toB, btScalar(1.), linVelB, angVelB);
+
+       btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
+       btScalar boundingRadiusB = m_convexB1 ? m_convexB1->getAngularMotionDisc() : 0.f;
+
+       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 lambda = btScalar(0.);
+
+       btVector3 n;
+       n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+       bool hasResult = false;
+       btVector3 c;
+
+       btScalar lastLambda = lambda;
+       //btScalar epsilon = btScalar(0.001);
+
+       int numIter = 0;
+       //first solution, using GJK
+
+       btScalar radius = 0.001f;
+       //      result.drawCoordSystem(sphereTr);
+
+       btPointCollector pointCollector1;
+
+       {
+               computeClosestPoints(fromA, fromB, pointCollector1);
+
+               hasResult = pointCollector1.m_hasResult;
+               c = pointCollector1.m_pointInWorld;
+       }
+
+       if (hasResult)
+       {
+               btScalar dist;
+               dist = pointCollector1.m_distance + result.m_allowedPenetration;
+               n = pointCollector1.m_normalOnBInWorld;
+               btScalar projectedLinearVelocity = relLinVel.dot(n);
+               if ((projectedLinearVelocity + maxAngularProjectedVelocity) <= SIMD_EPSILON)
+                       return false;
+
+               //not close enough
+               while (dist > radius)
+               {
+                       if (result.m_debugDrawer)
+                       {
+                               result.m_debugDrawer->drawSphere(c, 0.2f, btVector3(1, 1, 1));
+                       }
+                       btScalar dLambda = btScalar(0.);
+
+                       projectedLinearVelocity = relLinVel.dot(n);
+
+                       //don't report time of impact for motion away from the contact normal (or causes minor penetration)
+                       if ((projectedLinearVelocity + maxAngularProjectedVelocity) <= SIMD_EPSILON)
+                               return false;
+
+                       dLambda = dist / (projectedLinearVelocity + maxAngularProjectedVelocity);
+
+                       lambda += dLambda;
+
+                       if (lambda > btScalar(1.) || lambda < btScalar(0.))
+                               return false;
+
+                       //todo: next check with relative epsilon
+                       if (lambda <= lastLambda)
+                       {
+                               return false;
+                               //n.setValue(0,0,0);
+                               //break;
+                       }
+                       lastLambda = lambda;
+
+                       //interpolate to next lambda
+                       btTransform interpolatedTransA, interpolatedTransB, relativeTrans;
+
+                       btTransformUtil::integrateTransform(fromA, linVelA, angVelA, lambda, interpolatedTransA);
+                       btTransformUtil::integrateTransform(fromB, linVelB, angVelB, lambda, interpolatedTransB);
+                       relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA);
+
+                       if (result.m_debugDrawer)
+                       {
+                               result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(), 0.2f, btVector3(1, 0, 0));
+                       }
+
+                       result.DebugDraw(lambda);
+
+                       btPointCollector pointCollector;
+                       computeClosestPoints(interpolatedTransA, interpolatedTransB, pointCollector);
+
+                       if (pointCollector.m_hasResult)
+                       {
+                               dist = pointCollector.m_distance + result.m_allowedPenetration;
+                               c = pointCollector.m_pointInWorld;
+                               n = pointCollector.m_normalOnBInWorld;
+                       }
+                       else
+                       {
+                               result.reportFailure(-1, numIter);
+                               return false;
+                       }
+
+                       numIter++;
+                       if (numIter > MAX_ITERATIONS)
+                       {
+                               result.reportFailure(-2, numIter);
+                               return false;
+                       }
+               }
+
+               result.m_fraction = lambda;
+               result.m_normal = n;
+               result.m_hitPoint = c;
+               return true;
+       }
+
+       return false;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
new file mode 100644 (file)
index 0000000..76c7731
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_COLLISION_CONVEX_CAST_H
+#define BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
+
+#include "btConvexCast.h"
+#include "btSimplexSolverInterface.h"
+class btConvexPenetrationDepthSolver;
+class btConvexShape;
+class btStaticPlaneShape;
+
+/// btContinuousConvexCollision implements angular and linear time of impact for convex objects.
+/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis).
+/// Algorithm operates in worldspace, in order to keep in between motion globally consistent.
+/// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops
+class btContinuousConvexCollision : public btConvexCast
+{
+       btSimplexSolverInterface* m_simplexSolver;
+       btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
+       const btConvexShape* m_convexA;
+       //second object is either a convex or a plane (code sharing)
+       const btConvexShape* m_convexB1;
+       const btStaticPlaneShape* m_planeShape;
+
+       void computeClosestPoints(const btTransform& transA, const btTransform& transB, struct btPointCollector& pointCollector);
+
+public:
+       btContinuousConvexCollision(const btConvexShape* shapeA, const btConvexShape* shapeB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
+
+       btContinuousConvexCollision(const btConvexShape* shapeA, const btStaticPlaneShape* plane);
+
+       virtual bool calcTimeOfImpact(
+               const btTransform& fromA,
+               const btTransform& toA,
+               const btTransform& fromB,
+               const btTransform& toB,
+               CastResult& result);
+};
+
+#endif  //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp
new file mode 100644 (file)
index 0000000..f5b9b68
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexCast.h"
+
+btConvexCast::~btConvexCast()
+{
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h
new file mode 100644 (file)
index 0000000..85476e6
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_CAST_H
+#define BT_CONVEX_CAST_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btScalar.h"
+class btMinkowskiSumShape;
+#include "LinearMath/btIDebugDraw.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define MAX_CONVEX_CAST_ITERATIONS 64
+#define MAX_CONVEX_CAST_EPSILON (SIMD_EPSILON * 10)
+#else
+#define MAX_CONVEX_CAST_ITERATIONS 32
+#define MAX_CONVEX_CAST_EPSILON btScalar(0.0001)
+#endif
+///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases.
+///See discussion about this here https://bulletphysics.orgphpBB2/viewtopic.php?t=565
+//will need to digg deeper to make the algorithm more robust
+//since, a large epsilon can cause an early termination with false
+//positive results (ray intersections that shouldn't be there)
+
+/// btConvexCast is an interface for Casting
+class btConvexCast
+{
+public:
+       virtual ~btConvexCast();
+
+       ///RayResult stores the closest result
+       /// alternatively, add a callback method to decide about closest/all results
+       struct CastResult
+       {
+               //virtual bool  addRayResult(const btVector3& normal,btScalar   fraction) = 0;
+
+               virtual void DebugDraw(btScalar fraction) { (void)fraction; }
+               virtual void drawCoordSystem(const btTransform& trans) { (void)trans; }
+               virtual void reportFailure(int errNo, int numIterations)
+               {
+                       (void)errNo;
+                       (void)numIterations;
+               }
+               CastResult()
+                       : m_fraction(btScalar(BT_LARGE_FLOAT)),
+                         m_debugDrawer(0),
+                         m_allowedPenetration(btScalar(0)),
+                         m_subSimplexCastMaxIterations(MAX_CONVEX_CAST_ITERATIONS),
+                         m_subSimplexCastEpsilon(MAX_CONVEX_CAST_EPSILON)
+               {
+               }
+
+               virtual ~CastResult(){};
+
+               btTransform m_hitTransformA;
+               btTransform m_hitTransformB;
+               btVector3 m_normal;
+               btVector3 m_hitPoint;
+               btScalar m_fraction;  //input and output
+               btIDebugDraw* m_debugDrawer;
+               btScalar m_allowedPenetration;
+               
+               int m_subSimplexCastMaxIterations;
+               btScalar m_subSimplexCastEpsilon;
+
+       };
+
+       /// cast a convex against another convex object
+       virtual bool calcTimeOfImpact(
+               const btTransform& fromA,
+               const btTransform& toA,
+               const btTransform& fromB,
+               const btTransform& toB,
+               CastResult& result) = 0;
+};
+
+#endif  //BT_CONVEX_CAST_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
new file mode 100644 (file)
index 0000000..7672a41
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_PENETRATION_DEPTH_H
+#define BT_CONVEX_PENETRATION_DEPTH_H
+
+class btVector3;
+#include "btSimplexSolverInterface.h"
+class btConvexShape;
+class btTransform;
+
+///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation.
+class btConvexPenetrationDepthSolver
+{
+public:
+       virtual ~btConvexPenetrationDepthSolver(){};
+       virtual bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
+                                                         const btConvexShape* convexA, const btConvexShape* convexB,
+                                                         const btTransform& transA, const btTransform& transB,
+                                                         btVector3& v, btVector3& pa, btVector3& pb,
+                                                         class btIDebugDraw* debugDraw) = 0;
+};
+#endif  //BT_CONVEX_PENETRATION_DEPTH_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
new file mode 100644 (file)
index 0000000..973975f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
+#define BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+
+/// This interface is made to be used by an iterative approach to do TimeOfImpact calculations
+/// This interface allows to query for closest points and penetration depth between two (convex) objects
+/// the closest point is on the second object (B), and the normal points from the surface on B towards A.
+/// distance is between closest points on B and closest point on A. So you can calculate closest point on A
+/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB
+struct btDiscreteCollisionDetectorInterface
+{
+       struct Result
+       {
+               virtual ~Result() {}
+
+               ///setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material combiner
+               virtual void setShapeIdentifiersA(int partId0, int index0) = 0;
+               virtual void setShapeIdentifiersB(int partId1, int index1) = 0;
+               virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth) = 0;
+       };
+
+       struct ClosestPointInput
+       {
+               ClosestPointInput()
+                       : m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT))
+               {
+               }
+
+               btTransform m_transformA;
+               btTransform m_transformB;
+               btScalar m_maximumDistanceSquared;
+       };
+
+       virtual ~btDiscreteCollisionDetectorInterface(){};
+
+       //
+       // give either closest points (distance > 0) or penetration (distance)
+       // the normal always points from B towards A
+       //
+       virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false) = 0;
+};
+
+struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result
+{
+       btVector3 m_normalOnSurfaceB;
+       btVector3 m_closestPointInB;
+       btScalar m_distance;  //negative means penetration !
+
+protected:
+       btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT))
+       {
+       }
+
+public:
+       virtual ~btStorageResult(){};
+
+       virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
+       {
+               if (depth < m_distance)
+               {
+                       m_normalOnSurfaceB = normalOnBInWorld;
+                       m_closestPointInB = pointInWorld;
+                       m_distance = depth;
+               }
+       }
+};
+
+#endif  //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h
new file mode 100644 (file)
index 0000000..c9fd84b
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2014 Erwin Coumans http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef GJK_COLLISION_DESCRIPTION_H
+#define GJK_COLLISION_DESCRIPTION_H
+
+#include "LinearMath/btVector3.h"
+
+struct btGjkCollisionDescription
+{
+       btVector3 m_firstDir;
+       int m_maxGjkIterations;
+       btScalar m_maximumDistanceSquared;
+       btScalar m_gjkRelError2;
+       btGjkCollisionDescription()
+               : m_firstDir(0, 1, 0),
+                 m_maxGjkIterations(1000),
+                 m_maximumDistanceSquared(1e30f),
+                 m_gjkRelError2(1.0e-6)
+       {
+       }
+       virtual ~btGjkCollisionDescription()
+       {
+       }
+};
+
+#endif  //GJK_COLLISION_DESCRIPTION_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
new file mode 100644 (file)
index 0000000..41da699
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGjkConvexCast.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "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(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver)
+       : m_simplexSolver(simplexSolver),
+         m_convexA(convexA),
+         m_convexB(convexB)
+{
+}
+
+bool btGjkConvexCast::calcTimeOfImpact(
+       const btTransform& fromA,
+       const btTransform& toA,
+       const btTransform& fromB,
+       const btTransform& toB,
+       CastResult& result)
+{
+       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);
+
+       int maxIter = MAX_ITERATIONS;
+
+       btVector3 n;
+       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
+
+       btTransform identityTrans;
+       identityTrans.setIdentity();
+
+       //      result.drawCoordSystem(sphereTr);
+
+       btPointCollector pointCollector;
+
+       btGjkPairDetector gjk(m_convexA, m_convexB, m_simplexSolver, 0);  //m_penetrationDepthSolver);
+       btGjkPairDetector::ClosestPointInput input;
+
+       //we don't use margins during CCD
+       //      gjk.setIgnoreMargin(true);
+
+       input.m_transformA = fromA;
+       input.m_transformB = fromB;
+       gjk.getClosestPoints(input, pointCollector, 0);
+
+       hasResult = pointCollector.m_hasResult;
+       c = pointCollector.m_pointInWorld;
+
+       if (hasResult)
+       {
+               btScalar dist;
+               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);
+
+                       dLambda = dist / (projectedLinearVelocity);
+
+                       lambda = lambda - dLambda;
+
+                       if (lambda > btScalar(1.))
+                               return false;
+
+                       if (lambda < btScalar(0.))
+                               return false;
+
+                       //todo: next check with relative epsilon
+                       if (lambda <= lastLambda)
+                       {
+                               return false;
+                               //n.setValue(0,0,0);
+                               break;
+                       }
+                       lastLambda = lambda;
+
+                       //interpolate to next lambda
+                       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.))
+                               {
+                                       result.m_fraction = lastLambda;
+                                       n = pointCollector.m_normalOnBInWorld;
+                                       result.m_normal = n;
+                                       result.m_hitPoint = pointCollector.m_pointInWorld;
+                                       return true;
+                               }
+                               c = pointCollector.m_pointInWorld;
+                               n = pointCollector.m_normalOnBInWorld;
+                               dist = pointCollector.m_distance;
+                       }
+                       else
+                       {
+                               //??
+                               return false;
+                       }
+               }
+
+               //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/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
new file mode 100644 (file)
index 0000000..0ee46a5
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_GJK_CONVEX_CAST_H
+#define BT_GJK_CONVEX_CAST_H
+
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btVector3.h"
+#include "btConvexCast.h"
+class btConvexShape;
+class btMinkowskiSumShape;
+#include "btSimplexSolverInterface.h"
+
+///GjkConvexCast performs a raycast on a convex object using support mapping.
+class btGjkConvexCast : public btConvexCast
+{
+       btSimplexSolverInterface* m_simplexSolver;
+       const btConvexShape* m_convexA;
+       const btConvexShape* m_convexB;
+
+public:
+       btGjkConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver);
+
+       /// cast a convex against another convex object
+       virtual bool calcTimeOfImpact(
+               const btTransform& fromA,
+               const btTransform& toA,
+               const btTransform& fromB,
+               const btTransform& toB,
+               CastResult& result);
+};
+
+#endif  //BT_GJK_CONVEX_CAST_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
new file mode 100644 (file)
index 0000000..2288604
--- /dev/null
@@ -0,0 +1,1104 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as 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
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define GJK_ACCURACY ((btScalar)1e-12)
+#define GJK_MIN_DISTANCE ((btScalar)1e-12)
+#define GJK_DUPLICATED_EPS ((btScalar)1e-12)
+#else
+#define GJK_ACCURACY ((btScalar)0.0001)
+#define GJK_MIN_DISTANCE ((btScalar)0.0001)
+#define GJK_DUPLICATED_EPS ((btScalar)0.0001)
+#endif  //BT_USE_DOUBLE_PRECISION
+
+#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 128
+#define EPA_MAX_ITERATIONS 255
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define EPA_ACCURACY ((btScalar)1e-12)
+#define EPA_PLANE_EPS ((btScalar)1e-14)
+#define EPA_INSIDE_EPS ((btScalar)1e-9)
+#else
+#define EPA_ACCURACY ((btScalar)0.0001)
+#define EPA_PLANE_EPS ((btScalar)0.00001)
+#define EPA_INSIDE_EPS ((btScalar)0.01)
+#endif
+
+#define EPA_FALLBACK (10 * EPA_ACCURACY)
+#define EPA_MAX_FACES (EPA_MAX_VERTICES * 2)
+
+// Shorthands
+typedef unsigned int U;
+typedef unsigned char U1;
+
+// MinkowskiDiff
+struct MinkowskiDiff
+{
+       const btConvexShape* m_shapes[2];
+       btMatrix3x3 m_toshape1;
+       btTransform m_toshape0;
+#ifdef __SPU__
+       bool m_enableMargin;
+#else
+       btVector3 (btConvexShape::*Ls)(const btVector3&) const;
+#endif  //__SPU__
+
+       MinkowskiDiff()
+       {
+       }
+#ifdef __SPU__
+       void EnableMargin(bool enable)
+       {
+               m_enableMargin = enable;
+       }
+       inline btVector3 Support0(const btVector3& d) const
+       {
+               if (m_enableMargin)
+               {
+                       return m_shapes[0]->localGetSupportVertexNonVirtual(d);
+               }
+               else
+               {
+                       return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d);
+               }
+       }
+       inline btVector3 Support1(const btVector3& d) const
+       {
+               if (m_enableMargin)
+               {
+                       return m_toshape0 * (m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1 * d));
+               }
+               else
+               {
+                       return m_toshape0 * (m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1 * d));
+               }
+       }
+#else
+       void EnableMargin(bool enable)
+       {
+               if (enable)
+                       Ls = &btConvexShape::localGetSupportVertexNonVirtual;
+               else
+                       Ls = &btConvexShape::localGetSupportVertexWithoutMarginNonVirtual;
+       }
+       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));
+       }
+#endif  //__SPU__
+
+       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 = btDot(m_ray, w) / rl;
+                       alpha = btMax(omega, alpha);
+                       if (((rl - alpha) - (GJK_ACCURACY * 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;
+                       default:
+                       {
+                       }
+               }
+               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 = btCross(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 = btCross(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 ? -btDot(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 = btCross(dl[0], dl[1]);
+               const btScalar l = n.length2();
+               if (l > GJK_SIMPLEX3_EPS)
+               {
+                       btScalar mindist = -1;
+                       btScalar subw[2] = {0.f, 0.f};
+                       U subm(0);
+                       for (U i = 0; i < 3; ++i)
+                       {
+                               if (btDot(*vt[i], btCross(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 = btDot(a, n);
+                               const btScalar s = btSqrt(l);
+                               const btVector3 p = n * (d / l);
+                               mindist = p.length2();
+                               m = 7;
+                               w[0] = (btCross(dl[1], b - p)).length() / s;
+                               w[1] = (btCross(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 * btDot(a, btCross(b - c, a - b))) <= 0;
+               if (ng && (btFabs(vl) > GJK_SIMPLEX4_EPS))
+               {
+                       btScalar mindist = -1;
+                       btScalar subw[3] = {0.f, 0.f, 0.f};
+                       U subm(0);
+                       for (U i = 0; i < 3; ++i)
+                       {
+                               const U j = imd3[i];
+                               const btScalar s = vl * btDot(d, btCross(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;
+               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 = btDot(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();
+                                                               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] = btCross(outer.c[1]->w - projection,
+                                                                               outer.c[2]->w - projection)
+                                                                       .length();
+                               m_result.p[1] = btCross(outer.c[2]->w - projection,
+                                                                               outer.c[0]->w - projection)
+                                                                       .length();
+                               m_result.p[2] = btCross(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);
+       }
+       bool getedgedist(sFace* face, sSV* a, sSV* b, btScalar& dist)
+       {
+               const btVector3 ba = b->w - a->w;
+               const btVector3 n_ab = btCross(ba, face->n);   // Outward facing edge normal direction, on triangle plane
+               const btScalar a_dot_nab = btDot(a->w, n_ab);  // Only care about the sign to determine inside/outside, so not normalization required
+
+               if (a_dot_nab < 0)
+               {
+                       // Outside of edge a->b
+
+                       const btScalar ba_l2 = ba.length2();
+                       const btScalar a_dot_ba = btDot(a->w, ba);
+                       const btScalar b_dot_ba = btDot(b->w, ba);
+
+                       if (a_dot_ba > 0)
+                       {
+                               // Pick distance vertex a
+                               dist = a->w.length();
+                       }
+                       else if (b_dot_ba < 0)
+                       {
+                               // Pick distance vertex b
+                               dist = b->w.length();
+                       }
+                       else
+                       {
+                               // Pick distance to edge a->b
+                               const btScalar a_dot_b = btDot(a->w, b->w);
+                               dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
+                       }
+
+                       return true;
+               }
+
+               return false;
+       }
+       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 = btCross(b->w - a->w, c->w - a->w);
+                       const btScalar l = face->n.length();
+                       const bool v = l > EPA_ACCURACY;
+
+                       if (v)
+                       {
+                               if (!(getedgedist(face, a, b, face->d) ||
+                                         getedgedist(face, b, c, face->d) ||
+                                         getedgedist(face, c, a, face->d)))
+                               {
+                                       // Origin projects to the interior of the triangle
+                                       // Use distance to triangle plane
+                                       face->d = btDot(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;
+               for (sFace* f = minf->l[1]; f; f = f->l[1])
+               {
+                       const btScalar sqd = f->d * f->d;
+                       if (sqd < mind)
+                       {
+                               minf = f;
+                               mind = sqd;
+                       }
+               }
+               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 ((btDot(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);
+}
+
+}  // namespace gjkepa2_impl
+
+//
+// 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;
+               default:
+               {
+               }
+       }
+       return (false);
+}
+
+#ifndef __SPU__
+//
+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->getMarginNonVirtual() +
+                                                               shape1.getMarginNonVirtual();
+               const btScalar length = delta.length();
+               results.normal = delta / length;
+               results.witnesses[0] += results.normal * margin;
+               results.distance = length - margin;
+               return results.distance;
+       }
+       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);
+}
+#endif  //__SPU__
+
+/* Symbols cleanup             */
+
+#undef GJK_MAX_ITERATIONS
+#undef GJK_ACCURACY
+#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/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
new file mode 100644 (file)
index 0000000..e2cf633
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as 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 BT_GJK_EPA2_H
+#define BT_GJK_EPA2_H
+
+#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);
+#ifndef __SPU__
+       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  //__SPU__
+};
+
+#endif  //BT_GJK_EPA2_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h
new file mode 100644 (file)
index 0000000..fd67c37
--- /dev/null
@@ -0,0 +1,1063 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2014 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+Initial GJK-EPA collision solver by Nathanael Presson, 2008
+Improvements and refactoring by Erwin Coumans, 2008-2014
+*/
+#ifndef BT_GJK_EPA3_H
+#define BT_GJK_EPA3_H
+
+#include "LinearMath/btTransform.h"
+#include "btGjkCollisionDescription.h"
+
+struct btGjkEpaSolver3
+{
+       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;
+       };
+};
+
+#if defined(DEBUG) || defined(_DEBUG)
+#include <stdio.h>  //for debug printf
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+#endif  //__SPU__
+#endif
+
+// 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
+template <typename btConvexTemplate>
+struct MinkowskiDiff
+{
+       const btConvexTemplate* m_convexAPtr;
+       const btConvexTemplate* m_convexBPtr;
+
+       btMatrix3x3 m_toshape1;
+       btTransform m_toshape0;
+
+       bool m_enableMargin;
+
+       MinkowskiDiff(const btConvexTemplate& a, const btConvexTemplate& b)
+               : m_convexAPtr(&a),
+                 m_convexBPtr(&b)
+       {
+       }
+
+       void EnableMargin(bool enable)
+       {
+               m_enableMargin = enable;
+       }
+       inline btVector3 Support0(const btVector3& d) const
+       {
+               return m_convexAPtr->getLocalSupportWithMargin(d);
+       }
+       inline btVector3 Support1(const btVector3& d) const
+       {
+               return m_toshape0 * m_convexBPtr->getLocalSupportWithMargin(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));
+       }
+};
+
+enum eGjkStatus
+{
+       eGjkValid,
+       eGjkInside,
+       eGjkFailed
+};
+
+// GJK
+template <typename btConvexTemplate>
+struct GJK
+{
+       /* Types                */
+       struct sSV
+       {
+               btVector3 d, w;
+       };
+       struct sSimplex
+       {
+               sSV* c[4];
+               btScalar p[4];
+               U rank;
+       };
+
+       /* Fields               */
+
+       MinkowskiDiff<btConvexTemplate> 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;
+       eGjkStatus m_status;
+       /* Methods              */
+
+       GJK(const btConvexTemplate& a, const btConvexTemplate& b)
+               : m_shape(a, b)
+       {
+               Initialize();
+       }
+       void Initialize()
+       {
+               m_ray = btVector3(0, 0, 0);
+               m_nfree = 0;
+               m_status = eGjkFailed;
+               m_current = 0;
+               m_distance = 0;
+       }
+       eGjkStatus Evaluate(const MinkowskiDiff<btConvexTemplate>& 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 = eGjkValid;
+               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 = eGjkInside;
+                               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 = btDot(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 = eGjkInside;
+                       }
+                       else
+                       { /* Return old simplex                         */
+                               removevertice(m_simplices[m_current]);
+                               break;
+                       }
+                       m_status = ((++iterations) < GJK_MAX_ITERATIONS) ? m_status : eGjkFailed;
+               } while (m_status == eGjkValid);
+               m_simplex = &m_simplices[m_current];
+               switch (m_status)
+               {
+                       case eGjkValid:
+                               m_distance = m_ray.length();
+                               break;
+                       case eGjkInside:
+                               m_distance = 0;
+                               break;
+                       default:
+                       {
+                       }
+               }
+               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 = btCross(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 = btCross(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 ? -btDot(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 = btCross(dl[0], dl[1]);
+               const btScalar l = n.length2();
+               if (l > GJK_SIMPLEX3_EPS)
+               {
+                       btScalar mindist = -1;
+                       btScalar subw[2] = {0.f, 0.f};
+                       U subm(0);
+                       for (U i = 0; i < 3; ++i)
+                       {
+                               if (btDot(*vt[i], btCross(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 = btDot(a, n);
+                               const btScalar s = btSqrt(l);
+                               const btVector3 p = n * (d / l);
+                               mindist = p.length2();
+                               m = 7;
+                               w[0] = (btCross(dl[1], b - p)).length() / s;
+                               w[1] = (btCross(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 * btDot(a, btCross(b - c, a - b))) <= 0;
+               if (ng && (btFabs(vl) > GJK_SIMPLEX4_EPS))
+               {
+                       btScalar mindist = -1;
+                       btScalar subw[3] = {0.f, 0.f, 0.f};
+                       U subm(0);
+                       for (U i = 0; i < 3; ++i)
+                       {
+                               const U j = imd3[i];
+                               const btScalar s = vl * btDot(d, btCross(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);
+       }
+};
+
+enum eEpaStatus
+{
+       eEpaValid,
+       eEpaTouching,
+       eEpaDegenerated,
+       eEpaNonConvex,
+       eEpaInvalidHull,
+       eEpaOutOfFaces,
+       eEpaOutOfVertices,
+       eEpaAccuraryReached,
+       eEpaFallBack,
+       eEpaFailed
+};
+
+// EPA
+template <typename btConvexTemplate>
+struct EPA
+{
+       /* Types                */
+
+       struct sFace
+       {
+               btVector3 n;
+               btScalar d;
+               typename GJK<btConvexTemplate>::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) {}
+       };
+
+       /* Fields               */
+       eEpaStatus m_status;
+       typename GJK<btConvexTemplate>::sSimplex m_result;
+       btVector3 m_normal;
+       btScalar m_depth;
+       typename GJK<btConvexTemplate>::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 = eEpaFailed;
+               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]);
+               }
+       }
+       eEpaStatus Evaluate(GJK<btConvexTemplate>& gjk, const btVector3& guess)
+       {
+               typename GJK<btConvexTemplate>::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 = eEpaValid;
+                       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 = eEpaValid;
+                               for (; iterations < EPA_MAX_ITERATIONS; ++iterations)
+                               {
+                                       if (m_nextsv < EPA_MAX_VERTICES)
+                                       {
+                                               sHorizon horizon;
+                                               typename GJK<btConvexTemplate>::sSV* w = &m_sv_store[m_nextsv++];
+                                               bool valid = true;
+                                               best->pass = (U1)(++pass);
+                                               gjk.getsupport(best->n, *w);
+                                               const btScalar wdist = btDot(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();
+                                                               outer = *best;
+                                                       }
+                                                       else
+                                                       {
+                                                               m_status = eEpaInvalidHull;
+                                                               break;
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       m_status = eEpaAccuraryReached;
+                                                       break;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               m_status = eEpaOutOfVertices;
+                                               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] = btCross(outer.c[1]->w - projection,
+                                                                               outer.c[2]->w - projection)
+                                                                       .length();
+                               m_result.p[1] = btCross(outer.c[2]->w - projection,
+                                                                               outer.c[0]->w - projection)
+                                                                       .length();
+                               m_result.p[2] = btCross(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 = eEpaFallBack;
+               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);
+       }
+       bool getedgedist(sFace* face, typename GJK<btConvexTemplate>::sSV* a, typename GJK<btConvexTemplate>::sSV* b, btScalar& dist)
+       {
+               const btVector3 ba = b->w - a->w;
+               const btVector3 n_ab = btCross(ba, face->n);   // Outward facing edge normal direction, on triangle plane
+               const btScalar a_dot_nab = btDot(a->w, n_ab);  // Only care about the sign to determine inside/outside, so not normalization required
+
+               if (a_dot_nab < 0)
+               {
+                       // Outside of edge a->b
+
+                       const btScalar ba_l2 = ba.length2();
+                       const btScalar a_dot_ba = btDot(a->w, ba);
+                       const btScalar b_dot_ba = btDot(b->w, ba);
+
+                       if (a_dot_ba > 0)
+                       {
+                               // Pick distance vertex a
+                               dist = a->w.length();
+                       }
+                       else if (b_dot_ba < 0)
+                       {
+                               // Pick distance vertex b
+                               dist = b->w.length();
+                       }
+                       else
+                       {
+                               // Pick distance to edge a->b
+                               const btScalar a_dot_b = btDot(a->w, b->w);
+                               dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
+                       }
+
+                       return true;
+               }
+
+               return false;
+       }
+       sFace* newface(typename GJK<btConvexTemplate>::sSV* a, typename GJK<btConvexTemplate>::sSV* b, typename GJK<btConvexTemplate>::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 = btCross(b->w - a->w, c->w - a->w);
+                       const btScalar l = face->n.length();
+                       const bool v = l > EPA_ACCURACY;
+
+                       if (v)
+                       {
+                               if (!(getedgedist(face, a, b, face->d) ||
+                                         getedgedist(face, b, c, face->d) ||
+                                         getedgedist(face, c, a, face->d)))
+                               {
+                                       // Origin projects to the interior of the triangle
+                                       // Use distance to triangle plane
+                                       face->d = btDot(a->w, face->n) / l;
+                               }
+
+                               face->n /= l;
+                               if (forced || (face->d >= -EPA_PLANE_EPS))
+                               {
+                                       return face;
+                               }
+                               else
+                                       m_status = eEpaNonConvex;
+                       }
+                       else
+                               m_status = eEpaDegenerated;
+
+                       remove(m_hull, face);
+                       append(m_stock, face);
+                       return 0;
+               }
+               m_status = m_stock.root ? eEpaOutOfVertices : eEpaOutOfFaces;
+               return 0;
+       }
+       sFace* findbest()
+       {
+               sFace* minf = m_hull.root;
+               btScalar mind = minf->d * minf->d;
+               for (sFace* f = minf->l[1]; f; f = f->l[1])
+               {
+                       const btScalar sqd = f->d * f->d;
+                       if (sqd < mind)
+                       {
+                               minf = f;
+                               mind = sqd;
+                       }
+               }
+               return (minf);
+       }
+       bool expand(U pass, typename GJK<btConvexTemplate>::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 ((btDot(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);
+       }
+};
+
+template <typename btConvexTemplate>
+static void Initialize(const btConvexTemplate& a, const btConvexTemplate& b,
+                                          btGjkEpaSolver3::sResults& results,
+                                          MinkowskiDiff<btConvexTemplate>& shape)
+{
+       /* Results              */
+       results.witnesses[0] =
+               results.witnesses[1] = btVector3(0, 0, 0);
+       results.status = btGjkEpaSolver3::sResults::Separated;
+       /* Shape                */
+
+       shape.m_toshape1 = b.getWorldTransform().getBasis().transposeTimes(a.getWorldTransform().getBasis());
+       shape.m_toshape0 = a.getWorldTransform().inverseTimes(b.getWorldTransform());
+}
+
+//
+// Api
+//
+
+//
+template <typename btConvexTemplate>
+bool btGjkEpaSolver3_Distance(const btConvexTemplate& a, const btConvexTemplate& b,
+                                                         const btVector3& guess,
+                                                         btGjkEpaSolver3::sResults& results)
+{
+       MinkowskiDiff<btConvexTemplate> shape(a, b);
+       Initialize(a, b, results, shape);
+       GJK<btConvexTemplate> gjk(a, b);
+       eGjkStatus gjk_status = gjk.Evaluate(shape, guess);
+       if (gjk_status == eGjkValid)
+       {
+               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] = a.getWorldTransform() * w0;
+               results.witnesses[1] = a.getWorldTransform() * 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 == eGjkInside ? btGjkEpaSolver3::sResults::Penetrating : btGjkEpaSolver3::sResults::GJK_Failed;
+               return (false);
+       }
+}
+
+template <typename btConvexTemplate>
+bool btGjkEpaSolver3_Penetration(const btConvexTemplate& a,
+                                                                const btConvexTemplate& b,
+                                                                const btVector3& guess,
+                                                                btGjkEpaSolver3::sResults& results)
+{
+       MinkowskiDiff<btConvexTemplate> shape(a, b);
+       Initialize(a, b, results, shape);
+       GJK<btConvexTemplate> gjk(a, b);
+       eGjkStatus gjk_status = gjk.Evaluate(shape, -guess);
+       switch (gjk_status)
+       {
+               case eGjkInside:
+               {
+                       EPA<btConvexTemplate> epa;
+                       eEpaStatus epa_status = epa.Evaluate(gjk, -guess);
+                       if (epa_status != eEpaFailed)
+                       {
+                               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 = btGjkEpaSolver3::sResults::Penetrating;
+                               results.witnesses[0] = a.getWorldTransform() * w0;
+                               results.witnesses[1] = a.getWorldTransform() * (w0 - epa.m_normal * epa.m_depth);
+                               results.normal = -epa.m_normal;
+                               results.distance = -epa.m_depth;
+                               return (true);
+                       }
+                       else
+                               results.status = btGjkEpaSolver3::sResults::EPA_Failed;
+               }
+               break;
+               case eGjkFailed:
+                       results.status = btGjkEpaSolver3::sResults::GJK_Failed;
+                       break;
+               default:
+               {
+               }
+       }
+       return (false);
+}
+
+#if 0
+int    btComputeGjkEpaPenetration2(const btCollisionDescription& colDesc, btDistanceInfo* distInfo)
+{
+    btGjkEpaSolver3::sResults results;
+    btVector3 guess = colDesc.m_firstDir;
+    
+    bool res = btGjkEpaSolver3::Penetration(colDesc.m_objA,colDesc.m_objB,
+                                            colDesc.m_transformA,colDesc.m_transformB,
+                                            colDesc.m_localSupportFuncA,colDesc.m_localSupportFuncB,
+                                            guess,
+                                            results);
+    if (res)
+    {
+        if ((results.status==btGjkEpaSolver3::sResults::Penetrating) || results.status==GJK::eStatus::Inside)
+        {
+            //normal could be 'swapped'
+            
+            distInfo->m_distance = results.distance;
+            distInfo->m_normalBtoA = results.normal;
+            btVector3 tmpNormalInB = results.witnesses[1]-results.witnesses[0];
+            btScalar lenSqr = tmpNormalInB.length2();
+            if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
+            {
+                tmpNormalInB = results.normal;
+                lenSqr = results.normal.length2();
+            }
+            
+            if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
+            {
+                tmpNormalInB /= btSqrt(lenSqr);
+                btScalar distance2 = -(results.witnesses[0]-results.witnesses[1]).length();
+                //only replace valid penetrations when the result is deeper (check)
+                //if ((distance2 < results.distance))
+                {
+                    distInfo->m_distance = distance2;
+                    distInfo->m_pointOnA= results.witnesses[0];
+                    distInfo->m_pointOnB= results.witnesses[1];
+                    distInfo->m_normalBtoA= tmpNormalInB;
+                    return 0;
+                }
+            }
+        }
+        
+    }
+    
+    return -1;
+}
+#endif
+
+template <typename btConvexTemplate, typename btDistanceInfoTemplate>
+int btComputeGjkDistance(const btConvexTemplate& a, const btConvexTemplate& b,
+                                                const btGjkCollisionDescription& colDesc, btDistanceInfoTemplate* distInfo)
+{
+       btGjkEpaSolver3::sResults results;
+       btVector3 guess = colDesc.m_firstDir;
+
+       bool isSeparated = btGjkEpaSolver3_Distance(a, b,
+                                                                                               guess,
+                                                                                               results);
+       if (isSeparated)
+       {
+               distInfo->m_distance = results.distance;
+               distInfo->m_pointOnA = results.witnesses[0];
+               distInfo->m_pointOnB = results.witnesses[1];
+               distInfo->m_normalBtoA = results.normal;
+               return 0;
+       }
+
+       return -1;
+}
+
+/* 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
+
+#endif  //BT_GJK_EPA3_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
new file mode 100644 (file)
index 0000000..3b79ddf
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+EPA Copyright (c) Ricardo Padrela 2006
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "btGjkEpaPenetrationDepthSolver.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+
+bool btGjkEpaPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
+                                                                                                 const btConvexShape* pConvexA, const btConvexShape* pConvexB,
+                                                                                                 const btTransform& transformA, const btTransform& transformB,
+                                                                                                 btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
+                                                                                                 class btIDebugDraw* debugDraw)
+{
+       (void)debugDraw;
+       (void)v;
+       (void)simplexSolver;
+
+       btVector3 guessVectors[] = {
+               btVector3(transformB.getOrigin() - transformA.getOrigin()).safeNormalize(),
+               btVector3(transformA.getOrigin() - transformB.getOrigin()).safeNormalize(),
+               btVector3(0, 0, 1),
+               btVector3(0, 1, 0),
+               btVector3(1, 0, 0),
+               btVector3(1, 1, 0),
+               btVector3(1, 1, 1),
+               btVector3(0, 1, 1),
+               btVector3(1, 0, 1),
+       };
+
+       int numVectors = sizeof(guessVectors) / sizeof(btVector3);
+
+       for (int i = 0; i < numVectors; i++)
+       {
+               simplexSolver.reset();
+               btVector3 guessVector = guessVectors[i];
+
+               btGjkEpaSolver2::sResults results;
+
+               if (btGjkEpaSolver2::Penetration(pConvexA, transformA,
+                                                                                pConvexB, transformB,
+                                                                                guessVector, results))
+
+               {
+                       wWitnessOnA = results.witnesses[0];
+                       wWitnessOnB = results.witnesses[1];
+                       v = results.normal;
+                       return true;
+               }
+               else
+               {
+                       if (btGjkEpaSolver2::Distance(pConvexA, transformA, pConvexB, transformB, guessVector, results))
+                       {
+                               wWitnessOnA = results.witnesses[0];
+                               wWitnessOnB = results.witnesses[1];
+                               v = results.normal;
+                               return false;
+                       }
+               }
+       }
+
+       //failed to find a distance/penetration
+       wWitnessOnA.setValue(0, 0, 0);
+       wWitnessOnB.setValue(0, 0, 0);
+       v.setValue(0, 0, 0);
+       return false;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
new file mode 100644 (file)
index 0000000..90f0c17
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+EPA Copyright (c) Ricardo Padrela 2006 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BT_GJP_EPA_PENETRATION_DEPTH_H
+#define BT_GJP_EPA_PENETRATION_DEPTH_H
+
+#include "btConvexPenetrationDepthSolver.h"
+
+///EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to
+///calculate the penetration depth between two convex shapes.
+class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver
+{
+public:
+       btGjkEpaPenetrationDepthSolver()
+       {
+       }
+
+       bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
+                                         const btConvexShape* pConvexA, const btConvexShape* pConvexB,
+                                         const btTransform& transformA, const btTransform& transformB,
+                                         btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
+                                         class btIDebugDraw* debugDraw);
+
+private:
+};
+
+#endif  // BT_GJP_EPA_PENETRATION_DEPTH_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
new file mode 100644 (file)
index 0000000..bee8c33
--- /dev/null
@@ -0,0 +1,1183 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGjkPairDetector.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+
+#if defined(DEBUG) || defined(_DEBUG)
+//#define TEST_NON_VIRTUAL 1
+#include <stdio.h>  //for debug printf
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+#endif  //__SPU__
+#endif
+
+//must be above the machine epsilon
+#ifdef BT_USE_DOUBLE_PRECISION
+#define REL_ERROR2 btScalar(1.0e-12)
+btScalar gGjkEpaPenetrationTolerance = 1.0e-12;
+#else
+#define REL_ERROR2 btScalar(1.0e-6)
+btScalar gGjkEpaPenetrationTolerance = 0.001;
+#endif
+
+
+btGjkPairDetector::btGjkPairDetector(const btConvexShape *objectA, const btConvexShape *objectB, btSimplexSolverInterface *simplexSolver, btConvexPenetrationDepthSolver *penetrationDepthSolver)
+       : m_cachedSeparatingAxis(btScalar(0.), btScalar(1.), btScalar(0.)),
+         m_penetrationDepthSolver(penetrationDepthSolver),
+         m_simplexSolver(simplexSolver),
+         m_minkowskiA(objectA),
+         m_minkowskiB(objectB),
+         m_shapeTypeA(objectA->getShapeType()),
+         m_shapeTypeB(objectB->getShapeType()),
+         m_marginA(objectA->getMargin()),
+         m_marginB(objectB->getMargin()),
+         m_ignoreMargin(false),
+         m_lastUsedMethod(-1),
+         m_catchDegeneracies(1),
+         m_fixContactNormalDirection(1)
+{
+}
+btGjkPairDetector::btGjkPairDetector(const btConvexShape *objectA, const btConvexShape *objectB, int shapeTypeA, int shapeTypeB, btScalar marginA, btScalar marginB, btSimplexSolverInterface *simplexSolver, btConvexPenetrationDepthSolver *penetrationDepthSolver)
+       : m_cachedSeparatingAxis(btScalar(0.), btScalar(1.), btScalar(0.)),
+         m_penetrationDepthSolver(penetrationDepthSolver),
+         m_simplexSolver(simplexSolver),
+         m_minkowskiA(objectA),
+         m_minkowskiB(objectB),
+         m_shapeTypeA(shapeTypeA),
+         m_shapeTypeB(shapeTypeB),
+         m_marginA(marginA),
+         m_marginB(marginB),
+         m_ignoreMargin(false),
+         m_lastUsedMethod(-1),
+         m_catchDegeneracies(1),
+         m_fixContactNormalDirection(1)
+{
+}
+
+void btGjkPairDetector::getClosestPoints(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw, bool swapResults)
+{
+       (void)swapResults;
+
+       getClosestPointsNonVirtual(input, output, debugDraw);
+}
+
+static void btComputeSupport(const btConvexShape *convexA, const btTransform &localTransA, const btConvexShape *convexB, const btTransform &localTransB, const btVector3 &dir, bool check2d, btVector3 &supAworld, btVector3 &supBworld, btVector3 &aMinb)
+{
+       btVector3 separatingAxisInA = (dir)*localTransA.getBasis();
+       btVector3 separatingAxisInB = (-dir) * localTransB.getBasis();
+
+       btVector3 pInANoMargin = convexA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+       btVector3 qInBNoMargin = convexB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
+
+       btVector3 pInA = pInANoMargin;
+       btVector3 qInB = qInBNoMargin;
+
+       supAworld = localTransA(pInA);
+       supBworld = localTransB(qInB);
+
+       if (check2d)
+       {
+               supAworld[2] = 0.f;
+               supBworld[2] = 0.f;
+       }
+
+       aMinb = supAworld - supBworld;
+}
+
+struct btSupportVector
+{
+       btVector3 v;   //!< Support point in minkowski sum
+       btVector3 v1;  //!< Support point in obj1
+       btVector3 v2;  //!< Support point in obj2
+};
+
+struct btSimplex
+{
+       btSupportVector ps[4];
+       int last;  //!< index of last added point
+};
+
+static btVector3 ccd_vec3_origin(0, 0, 0);
+
+inline void btSimplexInit(btSimplex *s)
+{
+       s->last = -1;
+}
+
+inline int btSimplexSize(const btSimplex *s)
+{
+       return s->last + 1;
+}
+
+inline const btSupportVector *btSimplexPoint(const btSimplex *s, int idx)
+{
+       // here is no check on boundaries
+       return &s->ps[idx];
+}
+inline void btSupportCopy(btSupportVector *d, const btSupportVector *s)
+{
+       *d = *s;
+}
+
+inline void btVec3Copy(btVector3 *v, const btVector3 *w)
+{
+       *v = *w;
+}
+
+inline void ccdVec3Add(btVector3 *v, const btVector3 *w)
+{
+       v->m_floats[0] += w->m_floats[0];
+       v->m_floats[1] += w->m_floats[1];
+       v->m_floats[2] += w->m_floats[2];
+}
+
+inline void ccdVec3Sub(btVector3 *v, const btVector3 *w)
+{
+       *v -= *w;
+}
+inline void btVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
+{
+       *d = (*v) - (*w);
+}
+inline btScalar btVec3Dot(const btVector3 *a, const btVector3 *b)
+{
+       btScalar dot;
+       dot = a->dot(*b);
+
+       return dot;
+}
+
+inline btScalar ccdVec3Dist2(const btVector3 *a, const btVector3 *b)
+{
+       btVector3 ab;
+       btVec3Sub2(&ab, a, b);
+       return btVec3Dot(&ab, &ab);
+}
+
+inline void btVec3Scale(btVector3 *d, btScalar k)
+{
+       d->m_floats[0] *= k;
+       d->m_floats[1] *= k;
+       d->m_floats[2] *= k;
+}
+
+inline void btVec3Cross(btVector3 *d, const btVector3 *a, const btVector3 *b)
+{
+       d->m_floats[0] = (a->m_floats[1] * b->m_floats[2]) - (a->m_floats[2] * b->m_floats[1]);
+       d->m_floats[1] = (a->m_floats[2] * b->m_floats[0]) - (a->m_floats[0] * b->m_floats[2]);
+       d->m_floats[2] = (a->m_floats[0] * b->m_floats[1]) - (a->m_floats[1] * b->m_floats[0]);
+}
+
+inline void btTripleCross(const btVector3 *a, const btVector3 *b,
+                                                 const btVector3 *c, btVector3 *d)
+{
+       btVector3 e;
+       btVec3Cross(&e, a, b);
+       btVec3Cross(d, &e, c);
+}
+
+inline int ccdEq(btScalar _a, btScalar _b)
+{
+       btScalar ab;
+       btScalar a, b;
+
+       ab = btFabs(_a - _b);
+       if (btFabs(ab) < SIMD_EPSILON)
+               return 1;
+
+       a = btFabs(_a);
+       b = btFabs(_b);
+       if (b > a)
+       {
+               return ab < SIMD_EPSILON * b;
+       }
+       else
+       {
+               return ab < SIMD_EPSILON * a;
+       }
+}
+
+btScalar ccdVec3X(const btVector3 *v)
+{
+       return v->x();
+}
+
+btScalar ccdVec3Y(const btVector3 *v)
+{
+       return v->y();
+}
+
+btScalar ccdVec3Z(const btVector3 *v)
+{
+       return v->z();
+}
+inline int btVec3Eq(const btVector3 *a, const btVector3 *b)
+{
+       return ccdEq(ccdVec3X(a), ccdVec3X(b)) && ccdEq(ccdVec3Y(a), ccdVec3Y(b)) && ccdEq(ccdVec3Z(a), ccdVec3Z(b));
+}
+
+inline void btSimplexAdd(btSimplex *s, const btSupportVector *v)
+{
+       // here is no check on boundaries in sake of speed
+       ++s->last;
+       btSupportCopy(s->ps + s->last, v);
+}
+
+inline void btSimplexSet(btSimplex *s, size_t pos, const btSupportVector *a)
+{
+       btSupportCopy(s->ps + pos, a);
+}
+
+inline void btSimplexSetSize(btSimplex *s, int size)
+{
+       s->last = size - 1;
+}
+
+inline const btSupportVector *ccdSimplexLast(const btSimplex *s)
+{
+       return btSimplexPoint(s, s->last);
+}
+
+inline int ccdSign(btScalar val)
+{
+       if (btFuzzyZero(val))
+       {
+               return 0;
+       }
+       else if (val < btScalar(0))
+       {
+               return -1;
+       }
+       return 1;
+}
+
+inline btScalar btVec3PointSegmentDist2(const btVector3 *P,
+                                                                               const btVector3 *x0,
+                                                                               const btVector3 *b,
+                                                                               btVector3 *witness)
+{
+       // The computation comes from solving equation of segment:
+       //      S(t) = x0 + t.d
+       //          where - x0 is initial point of segment
+       //                - d is direction of segment from x0 (|d| > 0)
+       //                - t belongs to <0, 1> interval
+       //
+       // Than, distance from a segment to some point P can be expressed:
+       //      D(t) = |x0 + t.d - P|^2
+       //          which is distance from any point on segment. Minimization
+       //          of this function brings distance from P to segment.
+       // Minimization of D(t) leads to simple quadratic equation that's
+       // solving is straightforward.
+       //
+       // Bonus of this method is witness point for free.
+
+       btScalar dist, t;
+       btVector3 d, a;
+
+       // direction of segment
+       btVec3Sub2(&d, b, x0);
+
+       // precompute vector from P to x0
+       btVec3Sub2(&a, x0, P);
+
+       t = -btScalar(1.) * btVec3Dot(&a, &d);
+       t /= btVec3Dot(&d, &d);
+
+       if (t < btScalar(0) || btFuzzyZero(t))
+       {
+               dist = ccdVec3Dist2(x0, P);
+               if (witness)
+                       btVec3Copy(witness, x0);
+       }
+       else if (t > btScalar(1) || ccdEq(t, btScalar(1)))
+       {
+               dist = ccdVec3Dist2(b, P);
+               if (witness)
+                       btVec3Copy(witness, b);
+       }
+       else
+       {
+               if (witness)
+               {
+                       btVec3Copy(witness, &d);
+                       btVec3Scale(witness, t);
+                       ccdVec3Add(witness, x0);
+                       dist = ccdVec3Dist2(witness, P);
+               }
+               else
+               {
+                       // recycling variables
+                       btVec3Scale(&d, t);
+                       ccdVec3Add(&d, &a);
+                       dist = btVec3Dot(&d, &d);
+               }
+       }
+
+       return dist;
+}
+
+btScalar btVec3PointTriDist2(const btVector3 *P,
+                                                        const btVector3 *x0, const btVector3 *B,
+                                                        const btVector3 *C,
+                                                        btVector3 *witness)
+{
+       // Computation comes from analytic expression for triangle (x0, B, C)
+       //      T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and
+       // Then equation for distance is:
+       //      D(s, t) = | T(s, t) - P |^2
+       // This leads to minimization of quadratic function of two variables.
+       // The solution from is taken only if s is between 0 and 1, t is
+       // between 0 and 1 and t + s < 1, otherwise distance from segment is
+       // computed.
+
+       btVector3 d1, d2, a;
+       double u, v, w, p, q, r;
+       double s, t, dist, dist2;
+       btVector3 witness2;
+
+       btVec3Sub2(&d1, B, x0);
+       btVec3Sub2(&d2, C, x0);
+       btVec3Sub2(&a, x0, P);
+
+       u = btVec3Dot(&a, &a);
+       v = btVec3Dot(&d1, &d1);
+       w = btVec3Dot(&d2, &d2);
+       p = btVec3Dot(&a, &d1);
+       q = btVec3Dot(&a, &d2);
+       r = btVec3Dot(&d1, &d2);
+
+       s = (q * r - w * p) / (w * v - r * r);
+       t = (-s * r - q) / w;
+
+       if ((btFuzzyZero(s) || s > btScalar(0)) && (ccdEq(s, btScalar(1)) || s < btScalar(1)) && (btFuzzyZero(t) || t > btScalar(0)) && (ccdEq(t, btScalar(1)) || t < btScalar(1)) && (ccdEq(t + s, btScalar(1)) || t + s < btScalar(1)))
+       {
+               if (witness)
+               {
+                       btVec3Scale(&d1, s);
+                       btVec3Scale(&d2, t);
+                       btVec3Copy(witness, x0);
+                       ccdVec3Add(witness, &d1);
+                       ccdVec3Add(witness, &d2);
+
+                       dist = ccdVec3Dist2(witness, P);
+               }
+               else
+               {
+                       dist = s * s * v;
+                       dist += t * t * w;
+                       dist += btScalar(2.) * s * t * r;
+                       dist += btScalar(2.) * s * p;
+                       dist += btScalar(2.) * t * q;
+                       dist += u;
+               }
+       }
+       else
+       {
+               dist = btVec3PointSegmentDist2(P, x0, B, witness);
+
+               dist2 = btVec3PointSegmentDist2(P, x0, C, &witness2);
+               if (dist2 < dist)
+               {
+                       dist = dist2;
+                       if (witness)
+                               btVec3Copy(witness, &witness2);
+               }
+
+               dist2 = btVec3PointSegmentDist2(P, B, C, &witness2);
+               if (dist2 < dist)
+               {
+                       dist = dist2;
+                       if (witness)
+                               btVec3Copy(witness, &witness2);
+               }
+       }
+
+       return dist;
+}
+
+static int btDoSimplex2(btSimplex *simplex, btVector3 *dir)
+{
+       const btSupportVector *A, *B;
+       btVector3 AB, AO, tmp;
+       btScalar dot;
+
+       // get last added as A
+       A = ccdSimplexLast(simplex);
+       // get the other point
+       B = btSimplexPoint(simplex, 0);
+       // compute AB oriented segment
+       btVec3Sub2(&AB, &B->v, &A->v);
+       // compute AO vector
+       btVec3Copy(&AO, &A->v);
+       btVec3Scale(&AO, -btScalar(1));
+
+       // dot product AB . AO
+       dot = btVec3Dot(&AB, &AO);
+
+       // check if origin doesn't lie on AB segment
+       btVec3Cross(&tmp, &AB, &AO);
+       if (btFuzzyZero(btVec3Dot(&tmp, &tmp)) && dot > btScalar(0))
+       {
+               return 1;
+       }
+
+       // check if origin is in area where AB segment is
+       if (btFuzzyZero(dot) || dot < btScalar(0))
+       {
+               // origin is in outside are of A
+               btSimplexSet(simplex, 0, A);
+               btSimplexSetSize(simplex, 1);
+               btVec3Copy(dir, &AO);
+       }
+       else
+       {
+               // origin is in area where AB segment is
+
+               // keep simplex untouched and set direction to
+               // AB x AO x AB
+               btTripleCross(&AB, &AO, &AB, dir);
+       }
+
+       return 0;
+}
+
+static int btDoSimplex3(btSimplex *simplex, btVector3 *dir)
+{
+       const btSupportVector *A, *B, *C;
+       btVector3 AO, AB, AC, ABC, tmp;
+       btScalar dot, dist;
+
+       // get last added as A
+       A = ccdSimplexLast(simplex);
+       // get the other points
+       B = btSimplexPoint(simplex, 1);
+       C = btSimplexPoint(simplex, 0);
+
+       // check touching contact
+       dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &B->v, &C->v, 0);
+       if (btFuzzyZero(dist))
+       {
+               return 1;
+       }
+
+       // check if triangle is really triangle (has area > 0)
+       // if not simplex can't be expanded and thus no itersection is found
+       if (btVec3Eq(&A->v, &B->v) || btVec3Eq(&A->v, &C->v))
+       {
+               return -1;
+       }
+
+       // compute AO vector
+       btVec3Copy(&AO, &A->v);
+       btVec3Scale(&AO, -btScalar(1));
+
+       // compute AB and AC segments and ABC vector (perpendircular to triangle)
+       btVec3Sub2(&AB, &B->v, &A->v);
+       btVec3Sub2(&AC, &C->v, &A->v);
+       btVec3Cross(&ABC, &AB, &AC);
+
+       btVec3Cross(&tmp, &ABC, &AC);
+       dot = btVec3Dot(&tmp, &AO);
+       if (btFuzzyZero(dot) || dot > btScalar(0))
+       {
+               dot = btVec3Dot(&AC, &AO);
+               if (btFuzzyZero(dot) || dot > btScalar(0))
+               {
+                       // C is already in place
+                       btSimplexSet(simplex, 1, A);
+                       btSimplexSetSize(simplex, 2);
+                       btTripleCross(&AC, &AO, &AC, dir);
+               }
+               else
+               {
+                       dot = btVec3Dot(&AB, &AO);
+                       if (btFuzzyZero(dot) || dot > btScalar(0))
+                       {
+                               btSimplexSet(simplex, 0, B);
+                               btSimplexSet(simplex, 1, A);
+                               btSimplexSetSize(simplex, 2);
+                               btTripleCross(&AB, &AO, &AB, dir);
+                       }
+                       else
+                       {
+                               btSimplexSet(simplex, 0, A);
+                               btSimplexSetSize(simplex, 1);
+                               btVec3Copy(dir, &AO);
+                       }
+               }
+       }
+       else
+       {
+               btVec3Cross(&tmp, &AB, &ABC);
+               dot = btVec3Dot(&tmp, &AO);
+               if (btFuzzyZero(dot) || dot > btScalar(0))
+               {
+                       dot = btVec3Dot(&AB, &AO);
+                       if (btFuzzyZero(dot) || dot > btScalar(0))
+                       {
+                               btSimplexSet(simplex, 0, B);
+                               btSimplexSet(simplex, 1, A);
+                               btSimplexSetSize(simplex, 2);
+                               btTripleCross(&AB, &AO, &AB, dir);
+                       }
+                       else
+                       {
+                               btSimplexSet(simplex, 0, A);
+                               btSimplexSetSize(simplex, 1);
+                               btVec3Copy(dir, &AO);
+                       }
+               }
+               else
+               {
+                       dot = btVec3Dot(&ABC, &AO);
+                       if (btFuzzyZero(dot) || dot > btScalar(0))
+                       {
+                               btVec3Copy(dir, &ABC);
+                       }
+                       else
+                       {
+                               btSupportVector tmp;
+                               btSupportCopy(&tmp, C);
+                               btSimplexSet(simplex, 0, B);
+                               btSimplexSet(simplex, 1, &tmp);
+
+                               btVec3Copy(dir, &ABC);
+                               btVec3Scale(dir, -btScalar(1));
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int btDoSimplex4(btSimplex *simplex, btVector3 *dir)
+{
+       const btSupportVector *A, *B, *C, *D;
+       btVector3 AO, AB, AC, AD, ABC, ACD, ADB;
+       int B_on_ACD, C_on_ADB, D_on_ABC;
+       int AB_O, AC_O, AD_O;
+       btScalar dist;
+
+       // get last added as A
+       A = ccdSimplexLast(simplex);
+       // get the other points
+       B = btSimplexPoint(simplex, 2);
+       C = btSimplexPoint(simplex, 1);
+       D = btSimplexPoint(simplex, 0);
+
+       // check if tetrahedron is really tetrahedron (has volume > 0)
+       // if it is not simplex can't be expanded and thus no intersection is
+       // found
+       dist = btVec3PointTriDist2(&A->v, &B->v, &C->v, &D->v, 0);
+       if (btFuzzyZero(dist))
+       {
+               return -1;
+       }
+
+       // check if origin lies on some of tetrahedron's face - if so objects
+       // intersect
+       dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &B->v, &C->v, 0);
+       if (btFuzzyZero(dist))
+               return 1;
+       dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &C->v, &D->v, 0);
+       if (btFuzzyZero(dist))
+               return 1;
+       dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &B->v, &D->v, 0);
+       if (btFuzzyZero(dist))
+               return 1;
+       dist = btVec3PointTriDist2(&ccd_vec3_origin, &B->v, &C->v, &D->v, 0);
+       if (btFuzzyZero(dist))
+               return 1;
+
+       // compute AO, AB, AC, AD segments and ABC, ACD, ADB normal vectors
+       btVec3Copy(&AO, &A->v);
+       btVec3Scale(&AO, -btScalar(1));
+       btVec3Sub2(&AB, &B->v, &A->v);
+       btVec3Sub2(&AC, &C->v, &A->v);
+       btVec3Sub2(&AD, &D->v, &A->v);
+       btVec3Cross(&ABC, &AB, &AC);
+       btVec3Cross(&ACD, &AC, &AD);
+       btVec3Cross(&ADB, &AD, &AB);
+
+       // side (positive or negative) of B, C, D relative to planes ACD, ADB
+       // and ABC respectively
+       B_on_ACD = ccdSign(btVec3Dot(&ACD, &AB));
+       C_on_ADB = ccdSign(btVec3Dot(&ADB, &AC));
+       D_on_ABC = ccdSign(btVec3Dot(&ABC, &AD));
+
+       // whether origin is on same side of ACD, ADB, ABC as B, C, D
+       // respectively
+       AB_O = ccdSign(btVec3Dot(&ACD, &AO)) == B_on_ACD;
+       AC_O = ccdSign(btVec3Dot(&ADB, &AO)) == C_on_ADB;
+       AD_O = ccdSign(btVec3Dot(&ABC, &AO)) == D_on_ABC;
+
+       if (AB_O && AC_O && AD_O)
+       {
+               // origin is in tetrahedron
+               return 1;
+               // rearrange simplex to triangle and call btDoSimplex3()
+       }
+       else if (!AB_O)
+       {
+               // B is farthest from the origin among all of the tetrahedron's
+               // points, so remove it from the list and go on with the triangle
+               // case
+
+               // D and C are in place
+               btSimplexSet(simplex, 2, A);
+               btSimplexSetSize(simplex, 3);
+       }
+       else if (!AC_O)
+       {
+               // C is farthest
+               btSimplexSet(simplex, 1, D);
+               btSimplexSet(simplex, 0, B);
+               btSimplexSet(simplex, 2, A);
+               btSimplexSetSize(simplex, 3);
+       }
+       else
+       {  // (!AD_O)
+               btSimplexSet(simplex, 0, C);
+               btSimplexSet(simplex, 1, B);
+               btSimplexSet(simplex, 2, A);
+               btSimplexSetSize(simplex, 3);
+       }
+
+       return btDoSimplex3(simplex, dir);
+}
+
+static int btDoSimplex(btSimplex *simplex, btVector3 *dir)
+{
+       if (btSimplexSize(simplex) == 2)
+       {
+               // simplex contains segment only one segment
+               return btDoSimplex2(simplex, dir);
+       }
+       else if (btSimplexSize(simplex) == 3)
+       {
+               // simplex contains triangle
+               return btDoSimplex3(simplex, dir);
+       }
+       else
+       {  // btSimplexSize(simplex) == 4
+               // tetrahedron - this is the only shape which can encapsule origin
+               // so btDoSimplex4() also contains test on it
+               return btDoSimplex4(simplex, dir);
+       }
+}
+
+#ifdef __SPU__
+void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw)
+#else
+void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw)
+#endif
+{
+       m_cachedSeparatingDistance = 0.f;
+
+       btScalar distance = btScalar(0.);
+       btVector3 normalInB(btScalar(0.), btScalar(0.), btScalar(0.));
+
+       btVector3 pointOnA, pointOnB;
+       btTransform localTransA = input.m_transformA;
+       btTransform localTransB = input.m_transformB;
+       btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
+       localTransA.getOrigin() -= positionOffset;
+       localTransB.getOrigin() -= positionOffset;
+
+       bool check2d = m_minkowskiA->isConvex2d() && m_minkowskiB->isConvex2d();
+
+       btScalar marginA = m_marginA;
+       btScalar marginB = m_marginB;
+
+
+       //for CCD we don't use margins
+       if (m_ignoreMargin)
+       {
+               marginA = btScalar(0.);
+               marginB = btScalar(0.);
+       }
+
+       m_curIter = 0;
+       int gGjkMaxIter = 1000;  //this is to catch invalid input, perhaps check for #NaN?
+       m_cachedSeparatingAxis.setValue(0, 1, 0);
+
+       bool isValid = false;
+       bool checkSimplex = false;
+       bool checkPenetration = true;
+       m_degenerateSimplex = 0;
+
+       m_lastUsedMethod = -1;
+       int status = -2;
+       btVector3 orgNormalInB(0, 0, 0);
+       btScalar margin = marginA + marginB;
+
+       //we add a separate implementation to check if the convex shapes intersect
+       //See also "Real-time Collision Detection with Implicit Objects" by Leif Olvang
+       //Todo: integrate the simplex penetration check directly inside the Bullet btVoronoiSimplexSolver
+       //and remove this temporary code from libCCD
+       //this fixes issue https://github.com/bulletphysics/bullet3/issues/1703
+       //note, for large differences in shapes, use double precision build!
+       {
+               btScalar squaredDistance = BT_LARGE_FLOAT;
+               btScalar delta = btScalar(0.);
+
+               btSimplex simplex1;
+               btSimplex *simplex = &simplex1;
+               btSimplexInit(simplex);
+
+               btVector3 dir(1, 0, 0);
+
+               {
+                       btVector3 lastSupV;
+                       btVector3 supAworld;
+                       btVector3 supBworld;
+                       btComputeSupport(m_minkowskiA, localTransA, m_minkowskiB, localTransB, dir, check2d, supAworld, supBworld, lastSupV);
+
+                       btSupportVector last;
+                       last.v = lastSupV;
+                       last.v1 = supAworld;
+                       last.v2 = supBworld;
+
+                       btSimplexAdd(simplex, &last);
+
+                       dir = -lastSupV;
+
+                       // start iterations
+                       for (int iterations = 0; iterations < gGjkMaxIter; iterations++)
+                       {
+                               // obtain support point
+                               btComputeSupport(m_minkowskiA, localTransA, m_minkowskiB, localTransB, dir, check2d, supAworld, supBworld, lastSupV);
+
+                               // check if farthest point in Minkowski difference in direction dir
+                               // isn't somewhere before origin (the test on negative dot product)
+                               // - because if it is, objects are not intersecting at all.
+                               btScalar delta = lastSupV.dot(dir);
+                               if (delta < 0)
+                               {
+                                       //no intersection, besides margin
+                                       status = -1;
+                                       break;
+                               }
+
+                               // add last support vector to simplex
+                               last.v = lastSupV;
+                               last.v1 = supAworld;
+                               last.v2 = supBworld;
+
+                               btSimplexAdd(simplex, &last);
+
+                               // if btDoSimplex returns 1 if objects intersect, -1 if objects don't
+                               // intersect and 0 if algorithm should continue
+
+                               btVector3 newDir;
+                               int do_simplex_res = btDoSimplex(simplex, &dir);
+
+                               if (do_simplex_res == 1)
+                               {
+                                       status = 0;  // intersection found
+                                       break;
+                               }
+                               else if (do_simplex_res == -1)
+                               {
+                                       // intersection not found
+                                       status = -1;
+                                       break;
+                               }
+
+                               if (btFuzzyZero(btVec3Dot(&dir, &dir)))
+                               {
+                                       // intersection not found
+                                       status = -1;
+                               }
+
+                               if (dir.length2() < SIMD_EPSILON)
+                               {
+                                       //no intersection, besides margin
+                                       status = -1;
+                                       break;
+                               }
+
+                               if (dir.fuzzyZero())
+                               {
+                                       // intersection not found
+                                       status = -1;
+                                       break;
+                               }
+                       }
+               }
+
+               m_simplexSolver->reset();
+               if (status == 0)
+               {
+                       //status = 0;
+                       //printf("Intersect!\n");
+               }
+
+               if (status == -1)
+               {
+                       //printf("not intersect\n");
+               }
+               //printf("dir=%f,%f,%f\n",dir[0],dir[1],dir[2]);
+               if (1)
+               {
+                       for (;;)
+                       //while (true)
+                       {
+                               btVector3 separatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
+                               btVector3 separatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
+
+                               btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+                               btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
+
+                               btVector3 pWorld = localTransA(pInA);
+                               btVector3 qWorld = localTransB(qInB);
+
+                               if (check2d)
+                               {
+                                       pWorld[2] = 0.f;
+                                       qWorld[2] = 0.f;
+                               }
+
+                               btVector3 w = pWorld - qWorld;
+                               delta = m_cachedSeparatingAxis.dot(w);
+
+                               // potential exit, they don't overlap
+                               if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared))
+                               {
+                                       m_degenerateSimplex = 10;
+                                       checkSimplex = true;
+                                       //checkPenetration = false;
+                                       break;
+                               }
+
+                               //exit 0: the new point is already in the simplex, or we didn't come any closer
+                               if (m_simplexSolver->inSimplex(w))
+                               {
+                                       m_degenerateSimplex = 1;
+                                       checkSimplex = true;
+                                       break;
+                               }
+                               // are we getting any closer ?
+                               btScalar f0 = squaredDistance - delta;
+                               btScalar f1 = squaredDistance * REL_ERROR2;
+
+                               if (f0 <= f1)
+                               {
+                                       if (f0 <= btScalar(0.))
+                                       {
+                                               m_degenerateSimplex = 2;
+                                       }
+                                       else
+                                       {
+                                               m_degenerateSimplex = 11;
+                                       }
+                                       checkSimplex = true;
+                                       break;
+                               }
+
+                               //add current vertex to simplex
+                               m_simplexSolver->addVertex(w, pWorld, qWorld);
+                               btVector3 newCachedSeparatingAxis;
+
+                               //calculate the closest point to the origin (update vector v)
+                               if (!m_simplexSolver->closest(newCachedSeparatingAxis))
+                               {
+                                       m_degenerateSimplex = 3;
+                                       checkSimplex = true;
+                                       break;
+                               }
+
+                               if (newCachedSeparatingAxis.length2() < REL_ERROR2)
+                               {
+                                       m_cachedSeparatingAxis = newCachedSeparatingAxis;
+                                       m_degenerateSimplex = 6;
+                                       checkSimplex = true;
+                                       break;
+                               }
+
+                               btScalar previousSquaredDistance = squaredDistance;
+                               squaredDistance = newCachedSeparatingAxis.length2();
+#if 0
+                               ///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
+                               if (squaredDistance > previousSquaredDistance)
+                               {
+                                       m_degenerateSimplex = 7;
+                                       squaredDistance = previousSquaredDistance;
+                                       checkSimplex = false;
+                                       break;
+                               }
+#endif  //
+
+                               //redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
+
+                               //are we getting any closer ?
+                               if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
+                               {
+                                       //                              m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+                                       checkSimplex = true;
+                                       m_degenerateSimplex = 12;
+
+                                       break;
+                               }
+
+                               m_cachedSeparatingAxis = newCachedSeparatingAxis;
+
+                               //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
+                               if (m_curIter++ > gGjkMaxIter)
+                               {
+#if defined(DEBUG) || defined(_DEBUG)
+
+                                       printf("btGjkPairDetector maxIter exceeded:%i\n", m_curIter);
+                                       printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n",
+                                                  m_cachedSeparatingAxis.getX(),
+                                                  m_cachedSeparatingAxis.getY(),
+                                                  m_cachedSeparatingAxis.getZ(),
+                                                  squaredDistance,
+                                                  m_minkowskiA->getShapeType(),
+                                                  m_minkowskiB->getShapeType());
+
+#endif
+                                       break;
+                               }
+
+                               bool check = (!m_simplexSolver->fullSimplex());
+                               //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
+
+                               if (!check)
+                               {
+                                       //do we need this backup_closest here ?
+                                       //                              m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+                                       m_degenerateSimplex = 13;
+                                       break;
+                               }
+                       }
+
+                       if (checkSimplex)
+                       {
+                               m_simplexSolver->compute_points(pointOnA, pointOnB);
+                               normalInB = m_cachedSeparatingAxis;
+
+                               btScalar lenSqr = m_cachedSeparatingAxis.length2();
+
+                               //valid normal
+                               if (lenSqr < REL_ERROR2)
+                               {
+                                       m_degenerateSimplex = 5;
+                               }
+                               if (lenSqr > SIMD_EPSILON * SIMD_EPSILON)
+                               {
+                                       btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
+                                       normalInB *= rlen;  //normalize
+
+                                       btScalar s = btSqrt(squaredDistance);
+
+                                       btAssert(s > btScalar(0.0));
+                                       pointOnA -= m_cachedSeparatingAxis * (marginA / s);
+                                       pointOnB += m_cachedSeparatingAxis * (marginB / s);
+                                       distance = ((btScalar(1.) / rlen) - margin);
+                                       isValid = true;
+                                       orgNormalInB = normalInB;
+
+                                       m_lastUsedMethod = 1;
+                               }
+                               else
+                               {
+                                       m_lastUsedMethod = 2;
+                               }
+                       }
+               }
+
+               bool catchDegeneratePenetrationCase =
+                       (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance + margin) < gGjkEpaPenetrationTolerance));
+
+               //if (checkPenetration && !isValid)
+               if ((checkPenetration && (!isValid || catchDegeneratePenetrationCase)) || (status == 0))
+               {
+                       //penetration case
+
+                       //if there is no way to handle penetrations, bail out
+                       if (m_penetrationDepthSolver)
+                       {
+                               // Penetration depth case.
+                               btVector3 tmpPointOnA, tmpPointOnB;
+
+                               m_cachedSeparatingAxis.setZero();
+
+                               bool isValid2 = m_penetrationDepthSolver->calcPenDepth(
+                                       *m_simplexSolver,
+                                       m_minkowskiA, m_minkowskiB,
+                                       localTransA, localTransB,
+                                       m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB,
+                                       debugDraw);
+
+                               if (m_cachedSeparatingAxis.length2())
+                               {
+                                       if (isValid2)
+                                       {
+                                               btVector3 tmpNormalInB = tmpPointOnB - tmpPointOnA;
+                                               btScalar lenSqr = tmpNormalInB.length2();
+                                               if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
+                                               {
+                                                       tmpNormalInB = m_cachedSeparatingAxis;
+                                                       lenSqr = m_cachedSeparatingAxis.length2();
+                                               }
+
+                                               if (lenSqr > (SIMD_EPSILON * SIMD_EPSILON))
+                                               {
+                                                       tmpNormalInB /= btSqrt(lenSqr);
+                                                       btScalar distance2 = -(tmpPointOnA - tmpPointOnB).length();
+                                                       m_lastUsedMethod = 3;
+                                                       //only replace valid penetrations when the result is deeper (check)
+                                                       if (!isValid || (distance2 < distance))
+                                                       {
+                                                               distance = distance2;
+                                                               pointOnA = tmpPointOnA;
+                                                               pointOnB = tmpPointOnB;
+                                                               normalInB = tmpNormalInB;
+                                                               isValid = true;
+                                                       }
+                                                       else
+                                                       {
+                                                               m_lastUsedMethod = 8;
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       m_lastUsedMethod = 9;
+                                               }
+                                       }
+                                       else
+
+                                       {
+                                               ///this is another degenerate case, where the initial GJK calculation reports a degenerate case
+                                               ///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
+                                               ///reports a valid positive distance. Use the results of the second GJK instead of failing.
+                                               ///thanks to Jacob.Langford for the reproduction case
+                                               ///http://code.google.com/p/bullet/issues/detail?id=250
+
+                                               if (m_cachedSeparatingAxis.length2() > btScalar(0.))
+                                               {
+                                                       btScalar distance2 = (tmpPointOnA - tmpPointOnB).length() - margin;
+                                                       //only replace valid distances when the distance is less
+                                                       if (!isValid || (distance2 < distance))
+                                                       {
+                                                               distance = distance2;
+                                                               pointOnA = tmpPointOnA;
+                                                               pointOnB = tmpPointOnB;
+                                                               pointOnA -= m_cachedSeparatingAxis * marginA;
+                                                               pointOnB += m_cachedSeparatingAxis * marginB;
+                                                               normalInB = m_cachedSeparatingAxis;
+                                                               normalInB.normalize();
+
+                                                               isValid = true;
+                                                               m_lastUsedMethod = 6;
+                                                       }
+                                                       else
+                                                       {
+                                                               m_lastUsedMethod = 5;
+                                                       }
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       //printf("EPA didn't return a valid value\n");
+                               }
+                       }
+               }
+       }
+
+       if (isValid && ((distance < 0) || (distance * distance < input.m_maximumDistanceSquared)))
+       {
+               m_cachedSeparatingAxis = normalInB;
+               m_cachedSeparatingDistance = distance;
+               if (1)
+               {
+                       ///todo: need to track down this EPA penetration solver degeneracy
+                       ///the penetration solver reports penetration but the contact normal
+                       ///connecting the contact points is pointing in the opposite direction
+                       ///until then, detect the issue and revert the normal
+
+                       btScalar d2 = 0.f;
+                       {
+                               btVector3 separatingAxisInA = (-orgNormalInB) * localTransA.getBasis();
+                               btVector3 separatingAxisInB = orgNormalInB * localTransB.getBasis();
+
+                               btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+                               btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
+
+                               btVector3 pWorld = localTransA(pInA);
+                               btVector3 qWorld = localTransB(qInB);
+                               btVector3 w = pWorld - qWorld;
+                               d2 = orgNormalInB.dot(w) - margin;
+                       }
+
+                       btScalar d1 = 0;
+                       {
+                               btVector3 separatingAxisInA = (normalInB)*localTransA.getBasis();
+                               btVector3 separatingAxisInB = -normalInB * localTransB.getBasis();
+
+                               btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+                               btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
+
+                               btVector3 pWorld = localTransA(pInA);
+                               btVector3 qWorld = localTransB(qInB);
+                               btVector3 w = pWorld - qWorld;
+                               d1 = (-normalInB).dot(w) - margin;
+                       }
+                       btScalar d0 = 0.f;
+                       {
+                               btVector3 separatingAxisInA = (-normalInB) * input.m_transformA.getBasis();
+                               btVector3 separatingAxisInB = normalInB * input.m_transformB.getBasis();
+
+                               btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+                               btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
+
+                               btVector3 pWorld = localTransA(pInA);
+                               btVector3 qWorld = localTransB(qInB);
+                               btVector3 w = pWorld - qWorld;
+                               d0 = normalInB.dot(w) - margin;
+                       }
+
+                       if (d1 > d0)
+                       {
+                               m_lastUsedMethod = 10;
+                               normalInB *= -1;
+                       }
+
+                       if (orgNormalInB.length2())
+                       {
+                               if (d2 > d0 && d2 > d1 && d2 > distance)
+                               {
+                                       normalInB = orgNormalInB;
+                                       distance = d2;
+                               }
+                       }
+               }
+
+               output.addContactPoint(
+                       normalInB,
+                       pointOnB + positionOffset,
+                       distance);
+       }
+       else
+       {
+               //printf("invalid gjk query\n");
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
new file mode 100644 (file)
index 0000000..eee2f7d
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_GJK_PAIR_DETECTOR_H
+#define BT_GJK_PAIR_DETECTOR_H
+
+#include "btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+class btConvexShape;
+#include "btSimplexSolverInterface.h"
+class btConvexPenetrationDepthSolver;
+
+/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface
+class btGjkPairDetector : public btDiscreteCollisionDetectorInterface
+{
+       btVector3 m_cachedSeparatingAxis;
+       btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
+       btSimplexSolverInterface* m_simplexSolver;
+       const btConvexShape* m_minkowskiA;
+       const btConvexShape* m_minkowskiB;
+       int m_shapeTypeA;
+       int m_shapeTypeB;
+       btScalar m_marginA;
+       btScalar m_marginB;
+
+       bool m_ignoreMargin;
+       btScalar m_cachedSeparatingDistance;
+
+public:
+       //some debugging to fix degeneracy problems
+       int m_lastUsedMethod;
+       int m_curIter;
+       int m_degenerateSimplex;
+       int m_catchDegeneracies;
+       int m_fixContactNormalDirection;
+
+       btGjkPairDetector(const btConvexShape* objectA, const btConvexShape* objectB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
+       btGjkPairDetector(const btConvexShape* objectA, const btConvexShape* objectB, int shapeTypeA, int shapeTypeB, btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
+       virtual ~btGjkPairDetector(){};
+
+       virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
+
+       void getClosestPointsNonVirtual(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw);
+
+       void setMinkowskiA(const btConvexShape* minkA)
+       {
+               m_minkowskiA = minkA;
+       }
+
+       void setMinkowskiB(const btConvexShape* minkB)
+       {
+               m_minkowskiB = minkB;
+       }
+       void setCachedSeparatingAxis(const btVector3& separatingAxis)
+       {
+               m_cachedSeparatingAxis = separatingAxis;
+       }
+
+       const btVector3& getCachedSeparatingAxis() const
+       {
+               return m_cachedSeparatingAxis;
+       }
+       btScalar getCachedSeparatingDistance() const
+       {
+               return m_cachedSeparatingDistance;
+       }
+
+       void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver)
+       {
+               m_penetrationDepthSolver = penetrationDepthSolver;
+       }
+
+       ///don't use setIgnoreMargin, it's for Bullet's internal use
+       void setIgnoreMargin(bool ignoreMargin)
+       {
+               m_ignoreMargin = ignoreMargin;
+       }
+};
+
+#endif  //BT_GJK_PAIR_DETECTOR_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
new file mode 100644 (file)
index 0000000..3132328
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MANIFOLD_CONTACT_POINT_H
+#define BT_MANIFOLD_CONTACT_POINT_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransformUtil.h"
+
+#ifdef PFX_USE_FREE_VECTORMATH
+#include "physics_effects/base_level/solver/pfx_constraint_row.h"
+typedef sce::PhysicsEffects::PfxConstraintRow btConstraintRow;
+#else
+// Don't change following order of parameters
+ATTRIBUTE_ALIGNED16(struct)
+btConstraintRow
+{
+       btScalar m_normal[3];
+       btScalar m_rhs;
+       btScalar m_jacDiagInv;
+       btScalar m_lowerLimit;
+       btScalar m_upperLimit;
+       btScalar m_accumImpulse;
+};
+typedef btConstraintRow PfxConstraintRow;
+#endif  //PFX_USE_FREE_VECTORMATH
+
+enum btContactPointFlags
+{
+       BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED = 1,
+       BT_CONTACT_FLAG_HAS_CONTACT_CFM = 2,
+       BT_CONTACT_FLAG_HAS_CONTACT_ERP = 4,
+       BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING = 8,
+       BT_CONTACT_FLAG_FRICTION_ANCHOR = 16,
+};
+
+/// ManifoldContactPoint collects and maintains persistent contactpoints.
+/// used to improve stability and performance of rigidbody dynamics response.
+class btManifoldPoint
+{
+public:
+       btManifoldPoint()
+               : m_userPersistentData(0),
+                 m_contactPointFlags(0),
+                 m_appliedImpulse(0.f),
+                 m_prevRHS(0.f),
+                 m_appliedImpulseLateral1(0.f),
+                 m_appliedImpulseLateral2(0.f),
+                 m_contactMotion1(0.f),
+                 m_contactMotion2(0.f),
+                 m_contactCFM(0.f),
+                 m_contactERP(0.f),
+                 m_frictionCFM(0.f),
+                 m_lifeTime(0)
+       {
+       }
+
+       btManifoldPoint(const btVector3& pointA, const btVector3& pointB,
+                                       const btVector3& normal,
+                                       btScalar distance) : m_localPointA(pointA),
+                                                                                m_localPointB(pointB),
+                                                                                m_positionWorldOnB(0,0,0),
+                                                                                m_positionWorldOnA(0,0,0),
+                                                                                m_normalWorldOnB(normal),
+                                                                                m_distance1(distance),
+                                                                                m_combinedFriction(btScalar(0.)),
+                                                                                m_combinedRollingFriction(btScalar(0.)),
+                                                                                m_combinedSpinningFriction(btScalar(0.)),
+                                                                                m_combinedRestitution(btScalar(0.)),
+                                                                                m_partId0(-1),
+                                                                                m_partId1(-1),
+                                                                                m_index0(-1),
+                                                                                m_index1(-1),
+                                                                                m_userPersistentData(0),
+                                                                                m_contactPointFlags(0),
+                                                                                m_appliedImpulse(0.f),
+                                                                                m_prevRHS(0.f),
+                                                                                m_appliedImpulseLateral1(0.f),
+                                                                                m_appliedImpulseLateral2(0.f),
+                                                                                m_contactMotion1(0.f),
+                                                                                m_contactMotion2(0.f),
+                                                                                m_contactCFM(0.f),
+                                                                                m_contactERP(0.f),
+                                                                                m_frictionCFM(0.f),
+                                                                                m_lifeTime(0),
+                                                                                m_lateralFrictionDir1(0,0,0),
+                                                                                m_lateralFrictionDir2(0,0,0)
+       {
+       }
+
+       btVector3 m_localPointA;
+       btVector3 m_localPointB;
+       btVector3 m_positionWorldOnB;
+       ///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
+       btVector3 m_positionWorldOnA;
+       btVector3 m_normalWorldOnB;
+
+       btScalar m_distance1;
+       btScalar m_combinedFriction;
+       btScalar m_combinedRollingFriction;   //torsional friction orthogonal to contact normal, useful to make spheres stop rolling forever
+       btScalar m_combinedSpinningFriction;  //torsional friction around contact normal, useful for grasping objects
+       btScalar m_combinedRestitution;
+
+       //BP mod, store contact triangles.
+       int m_partId0;
+       int m_partId1;
+       int m_index0;
+       int m_index1;
+
+       mutable void* m_userPersistentData;
+       //bool                  m_lateralFrictionInitialized;
+       int m_contactPointFlags;
+
+       btScalar m_appliedImpulse;
+       btScalar m_prevRHS;
+       btScalar m_appliedImpulseLateral1;
+       btScalar m_appliedImpulseLateral2;
+       btScalar m_contactMotion1;
+       btScalar m_contactMotion2;
+
+       union {
+               btScalar m_contactCFM;
+               btScalar m_combinedContactStiffness1;
+       };
+
+       union {
+               btScalar m_contactERP;
+               btScalar m_combinedContactDamping1;
+       };
+
+       btScalar m_frictionCFM;
+
+       int m_lifeTime;  //lifetime of the contactpoint in frames
+
+       btVector3 m_lateralFrictionDir1;
+       btVector3 m_lateralFrictionDir2;
+
+       btScalar getDistance() const
+       {
+               return m_distance1;
+       }
+       int getLifeTime() const
+       {
+               return m_lifeTime;
+       }
+
+       const btVector3& getPositionWorldOnA() const
+       {
+               return m_positionWorldOnA;
+               //                              return m_positionWorldOnB + m_normalWorldOnB * m_distance1;
+       }
+
+       const btVector3& getPositionWorldOnB() const
+       {
+               return m_positionWorldOnB;
+       }
+
+       void setDistance(btScalar dist)
+       {
+               m_distance1 = dist;
+       }
+
+       ///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver
+       btScalar getAppliedImpulse() const
+       {
+               return m_appliedImpulse;
+       }
+};
+
+#endif  //BT_MANIFOLD_CONTACT_POINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
new file mode 100644 (file)
index 0000000..dcb2980
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+#define NUM_UNITSPHERE_POINTS 42
+
+bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
+                                                                                                        const btConvexShape* convexA, const btConvexShape* convexB,
+                                                                                                        const btTransform& transA, const btTransform& transB,
+                                                                                                        btVector3& v, btVector3& pa, btVector3& pb,
+                                                                                                        class btIDebugDraw* debugDraw)
+{
+       (void)v;
+
+       bool check2d = convexA->isConvex2d() && convexB->isConvex2d();
+
+       struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result
+       {
+               btIntermediateResult() : m_hasResult(false)
+               {
+               }
+
+               btVector3 m_normalOnBInWorld;
+               btVector3 m_pointInWorld;
+               btScalar m_depth;
+               bool m_hasResult;
+
+               virtual void setShapeIdentifiersA(int partId0, int index0)
+               {
+                       (void)partId0;
+                       (void)index0;
+               }
+               virtual void setShapeIdentifiersB(int partId1, int index1)
+               {
+                       (void)partId1;
+                       (void)index1;
+               }
+               void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
+               {
+                       m_normalOnBInWorld = normalOnBInWorld;
+                       m_pointInWorld = pointInWorld;
+                       m_depth = depth;
+                       m_hasResult = true;
+               }
+       };
+
+       //just take fixed number of orientation, and sample the penetration depth in that direction
+       btScalar minProj = btScalar(BT_LARGE_FLOAT);
+       btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.));
+       btVector3 minA, minB;
+       btVector3 separatingAxisInA, separatingAxisInB;
+       btVector3 pInA, qInB, pWorld, qWorld, w;
+
+#ifndef __SPU__
+#define USE_BATCHED_SUPPORT 1
+#endif
+#ifdef USE_BATCHED_SUPPORT
+
+       btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+       btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+       btVector3 separatingAxisInABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+       btVector3 separatingAxisInBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
+       int i;
+
+       int numSampleDirections = NUM_UNITSPHERE_POINTS;
+
+       for (i = 0; i < numSampleDirections; i++)
+       {
+               btVector3 norm = getPenetrationDirections()[i];
+               separatingAxisInABatch[i] = (-norm) * transA.getBasis();
+               separatingAxisInBBatch[i] = norm * transB.getBasis();
+       }
+
+       {
+               int numPDA = convexA->getNumPreferredPenetrationDirections();
+               if (numPDA)
+               {
+                       for (int i = 0; i < numPDA; i++)
+                       {
+                               btVector3 norm;
+                               convexA->getPreferredPenetrationDirection(i, norm);
+                               norm = transA.getBasis() * norm;
+                               getPenetrationDirections()[numSampleDirections] = norm;
+                               separatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+                               separatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+                               numSampleDirections++;
+                       }
+               }
+       }
+
+       {
+               int numPDB = convexB->getNumPreferredPenetrationDirections();
+               if (numPDB)
+               {
+                       for (int i = 0; i < numPDB; i++)
+                       {
+                               btVector3 norm;
+                               convexB->getPreferredPenetrationDirection(i, norm);
+                               norm = transB.getBasis() * norm;
+                               getPenetrationDirections()[numSampleDirections] = norm;
+                               separatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+                               separatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+                               numSampleDirections++;
+                       }
+               }
+       }
+
+       convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(separatingAxisInABatch, supportVerticesABatch, numSampleDirections);
+       convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(separatingAxisInBBatch, supportVerticesBBatch, numSampleDirections);
+
+       for (i = 0; i < numSampleDirections; i++)
+       {
+               btVector3 norm = getPenetrationDirections()[i];
+               if (check2d)
+               {
+                       norm[2] = 0.f;
+               }
+               if (norm.length2() > 0.01)
+               {
+                       separatingAxisInA = separatingAxisInABatch[i];
+                       separatingAxisInB = separatingAxisInBBatch[i];
+
+                       pInA = supportVerticesABatch[i];
+                       qInB = supportVerticesBBatch[i];
+
+                       pWorld = transA(pInA);
+                       qWorld = transB(qInB);
+                       if (check2d)
+                       {
+                               pWorld[2] = 0.f;
+                               qWorld[2] = 0.f;
+                       }
+
+                       w = qWorld - pWorld;
+                       btScalar delta = norm.dot(w);
+                       //find smallest delta
+                       if (delta < minProj)
+                       {
+                               minProj = delta;
+                               minNorm = norm;
+                               minA = pWorld;
+                               minB = qWorld;
+                       }
+               }
+       }
+#else
+
+       int numSampleDirections = NUM_UNITSPHERE_POINTS;
+
+#ifndef __SPU__
+       {
+               int numPDA = convexA->getNumPreferredPenetrationDirections();
+               if (numPDA)
+               {
+                       for (int i = 0; i < numPDA; i++)
+                       {
+                               btVector3 norm;
+                               convexA->getPreferredPenetrationDirection(i, norm);
+                               norm = transA.getBasis() * norm;
+                               getPenetrationDirections()[numSampleDirections] = norm;
+                               numSampleDirections++;
+                       }
+               }
+       }
+
+       {
+               int numPDB = convexB->getNumPreferredPenetrationDirections();
+               if (numPDB)
+               {
+                       for (int i = 0; i < numPDB; i++)
+                       {
+                               btVector3 norm;
+                               convexB->getPreferredPenetrationDirection(i, norm);
+                               norm = transB.getBasis() * norm;
+                               getPenetrationDirections()[numSampleDirections] = norm;
+                               numSampleDirections++;
+                       }
+               }
+       }
+#endif  // __SPU__
+
+       for (int i = 0; i < numSampleDirections; i++)
+       {
+               const btVector3& norm = getPenetrationDirections()[i];
+               separatingAxisInA = (-norm) * transA.getBasis();
+               separatingAxisInB = norm * transB.getBasis();
+               pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
+               qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
+               pWorld = transA(pInA);
+               qWorld = transB(qInB);
+               w = qWorld - pWorld;
+               btScalar delta = norm.dot(w);
+               //find smallest delta
+               if (delta < minProj)
+               {
+                       minProj = delta;
+                       minNorm = norm;
+                       minA = pWorld;
+                       minB = qWorld;
+               }
+       }
+#endif  //USE_BATCHED_SUPPORT
+
+       //add the margins
+
+       minA += minNorm * convexA->getMarginNonVirtual();
+       minB -= minNorm * convexB->getMarginNonVirtual();
+       //no penetration
+       if (minProj < btScalar(0.))
+               return false;
+
+       btScalar extraSeparation = 0.5f;  ///scale dependent
+       minProj += extraSeparation + (convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual());
+
+//#define DEBUG_DRAW 1
+#ifdef DEBUG_DRAW
+       if (debugDraw)
+       {
+               btVector3 color(0, 1, 0);
+               debugDraw->drawLine(minA, minB, color);
+               color = btVector3(1, 1, 1);
+               btVector3 vec = minB - minA;
+               btScalar prj2 = minNorm.dot(vec);
+               debugDraw->drawLine(minA, minA + (minNorm * minProj), color);
+       }
+#endif  //DEBUG_DRAW
+
+       btGjkPairDetector gjkdet(convexA, convexB, &simplexSolver, 0);
+
+       btScalar offsetDist = minProj;
+       btVector3 offset = minNorm * offsetDist;
+
+       btGjkPairDetector::ClosestPointInput input;
+
+       btVector3 newOrg = transA.getOrigin() + offset;
+
+       btTransform displacedTrans = transA;
+       displacedTrans.setOrigin(newOrg);
+
+       input.m_transformA = displacedTrans;
+       input.m_transformB = transB;
+       input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);  //minProj;
+
+       btIntermediateResult res;
+       gjkdet.setCachedSeparatingAxis(-minNorm);
+       gjkdet.getClosestPoints(input, res, debugDraw);
+
+       btScalar correctedMinNorm = minProj - res.m_depth;
+
+       //the penetration depth is over-estimated, relax it
+       btScalar penetration_relaxation = btScalar(1.);
+       minNorm *= penetration_relaxation;
+
+       if (res.m_hasResult)
+       {
+               pa = res.m_pointInWorld - minNorm * correctedMinNorm;
+               pb = res.m_pointInWorld;
+               v = minNorm;
+
+#ifdef DEBUG_DRAW
+               if (debugDraw)
+               {
+                       btVector3 color(1, 0, 0);
+                       debugDraw->drawLine(pa, pb, color);
+               }
+#endif  //DEBUG_DRAW
+       }
+       return res.m_hasResult;
+}
+
+btVector3* btMinkowskiPenetrationDepthSolver::getPenetrationDirections()
+{
+       static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2] =
+               {
+                       btVector3(btScalar(0.000000), btScalar(-0.000000), btScalar(-1.000000)),
+                       btVector3(btScalar(0.723608), btScalar(-0.525725), btScalar(-0.447219)),
+                       btVector3(btScalar(-0.276388), btScalar(-0.850649), btScalar(-0.447219)),
+                       btVector3(btScalar(-0.894426), btScalar(-0.000000), btScalar(-0.447216)),
+                       btVector3(btScalar(-0.276388), btScalar(0.850649), btScalar(-0.447220)),
+                       btVector3(btScalar(0.723608), btScalar(0.525725), btScalar(-0.447219)),
+                       btVector3(btScalar(0.276388), btScalar(-0.850649), btScalar(0.447220)),
+                       btVector3(btScalar(-0.723608), btScalar(-0.525725), btScalar(0.447219)),
+                       btVector3(btScalar(-0.723608), btScalar(0.525725), btScalar(0.447219)),
+                       btVector3(btScalar(0.276388), btScalar(0.850649), btScalar(0.447219)),
+                       btVector3(btScalar(0.894426), btScalar(0.000000), btScalar(0.447216)),
+                       btVector3(btScalar(-0.000000), btScalar(0.000000), btScalar(1.000000)),
+                       btVector3(btScalar(0.425323), btScalar(-0.309011), btScalar(-0.850654)),
+                       btVector3(btScalar(-0.162456), btScalar(-0.499995), btScalar(-0.850654)),
+                       btVector3(btScalar(0.262869), btScalar(-0.809012), btScalar(-0.525738)),
+                       btVector3(btScalar(0.425323), btScalar(0.309011), btScalar(-0.850654)),
+                       btVector3(btScalar(0.850648), btScalar(-0.000000), btScalar(-0.525736)),
+                       btVector3(btScalar(-0.525730), btScalar(-0.000000), btScalar(-0.850652)),
+                       btVector3(btScalar(-0.688190), btScalar(-0.499997), btScalar(-0.525736)),
+                       btVector3(btScalar(-0.162456), btScalar(0.499995), btScalar(-0.850654)),
+                       btVector3(btScalar(-0.688190), btScalar(0.499997), btScalar(-0.525736)),
+                       btVector3(btScalar(0.262869), btScalar(0.809012), btScalar(-0.525738)),
+                       btVector3(btScalar(0.951058), btScalar(0.309013), btScalar(0.000000)),
+                       btVector3(btScalar(0.951058), btScalar(-0.309013), btScalar(0.000000)),
+                       btVector3(btScalar(0.587786), btScalar(-0.809017), btScalar(0.000000)),
+                       btVector3(btScalar(0.000000), btScalar(-1.000000), btScalar(0.000000)),
+                       btVector3(btScalar(-0.587786), btScalar(-0.809017), btScalar(0.000000)),
+                       btVector3(btScalar(-0.951058), btScalar(-0.309013), btScalar(-0.000000)),
+                       btVector3(btScalar(-0.951058), btScalar(0.309013), btScalar(-0.000000)),
+                       btVector3(btScalar(-0.587786), btScalar(0.809017), btScalar(-0.000000)),
+                       btVector3(btScalar(-0.000000), btScalar(1.000000), btScalar(-0.000000)),
+                       btVector3(btScalar(0.587786), btScalar(0.809017), btScalar(-0.000000)),
+                       btVector3(btScalar(0.688190), btScalar(-0.499997), btScalar(0.525736)),
+                       btVector3(btScalar(-0.262869), btScalar(-0.809012), btScalar(0.525738)),
+                       btVector3(btScalar(-0.850648), btScalar(0.000000), btScalar(0.525736)),
+                       btVector3(btScalar(-0.262869), btScalar(0.809012), btScalar(0.525738)),
+                       btVector3(btScalar(0.688190), btScalar(0.499997), btScalar(0.525736)),
+                       btVector3(btScalar(0.525730), btScalar(0.000000), btScalar(0.850652)),
+                       btVector3(btScalar(0.162456), btScalar(-0.499995), btScalar(0.850654)),
+                       btVector3(btScalar(-0.425323), btScalar(-0.309011), btScalar(0.850654)),
+                       btVector3(btScalar(-0.425323), btScalar(0.309011), btScalar(0.850654)),
+                       btVector3(btScalar(0.162456), btScalar(0.499995), btScalar(0.850654))};
+
+       return sPenetrationDirections;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
new file mode 100644 (file)
index 0000000..2ad663b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+#define BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+
+#include "btConvexPenetrationDepthSolver.h"
+
+///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation.
+///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points.
+class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver
+{
+protected:
+       static btVector3* getPenetrationDirections();
+
+public:
+       virtual bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
+                                                         const btConvexShape* convexA, const btConvexShape* convexB,
+                                                         const btTransform& transA, const btTransform& transB,
+                                                         btVector3& v, btVector3& pa, btVector3& pb,
+                                                         class btIDebugDraw* debugDraw);
+};
+
+#endif  //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btMprPenetration.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
new file mode 100644 (file)
index 0000000..534a66d
--- /dev/null
@@ -0,0 +1,884 @@
+
+/***
+ * ---------------------------------
+ * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>
+ *
+ *  This file was ported from mpr.c file, part of libccd.
+ *  The Minkoski Portal Refinement implementation was ported 
+ *  to OpenCL by Erwin Coumans for the Bullet 3 Physics library.
+ *  The original MPR idea and implementation is by Gary Snethen
+ *  in XenoCollide, see http://github.com/erwincoumans/xenocollide
+ *
+ *  Distributed under the OSI-approved BSD License (the "License");
+ *  see <http://www.opensource.org/licenses/bsd-license.php>.
+ *  This software is distributed WITHOUT ANY WARRANTY; without even the
+ *  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *  See the License for more information.
+ */
+
+///2014 Oct, Erwin Coumans, Use templates to avoid void* casts
+
+#ifndef BT_MPR_PENETRATION_H
+#define BT_MPR_PENETRATION_H
+
+#define BT_DEBUG_MPR1
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+//#define MPR_AVERAGE_CONTACT_POSITIONS
+
+struct btMprCollisionDescription
+{
+       btVector3 m_firstDir;
+       int m_maxGjkIterations;
+       btScalar m_maximumDistanceSquared;
+       btScalar m_gjkRelError2;
+
+       btMprCollisionDescription()
+               : m_firstDir(0, 1, 0),
+                 m_maxGjkIterations(1000),
+                 m_maximumDistanceSquared(1e30f),
+                 m_gjkRelError2(1.0e-6)
+       {
+       }
+       virtual ~btMprCollisionDescription()
+       {
+       }
+};
+
+struct btMprDistanceInfo
+{
+       btVector3 m_pointOnA;
+       btVector3 m_pointOnB;
+       btVector3 m_normalBtoA;
+       btScalar m_distance;
+};
+
+#ifdef __cplusplus
+#define BT_MPR_SQRT sqrtf
+#else
+#define BT_MPR_SQRT sqrt
+#endif
+#define BT_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))
+#define BT_MPR_FABS fabs
+
+#define BT_MPR_TOLERANCE 1E-6f
+#define BT_MPR_MAX_ITERATIONS 1000
+
+struct _btMprSupport_t
+{
+       btVector3 v;   //!< Support point in minkowski sum
+       btVector3 v1;  //!< Support point in obj1
+       btVector3 v2;  //!< Support point in obj2
+};
+typedef struct _btMprSupport_t btMprSupport_t;
+
+struct _btMprSimplex_t
+{
+       btMprSupport_t ps[4];
+       int last;  //!< index of last added point
+};
+typedef struct _btMprSimplex_t btMprSimplex_t;
+
+inline btMprSupport_t *btMprSimplexPointW(btMprSimplex_t *s, int idx)
+{
+       return &s->ps[idx];
+}
+
+inline void btMprSimplexSetSize(btMprSimplex_t *s, int size)
+{
+       s->last = size - 1;
+}
+
+#ifdef DEBUG_MPR
+inline void btPrintPortalVertex(_btMprSimplex_t *portal, int index)
+{
+       printf("portal[%d].v = %f,%f,%f, v1=%f,%f,%f, v2=%f,%f,%f\n", index, portal->ps[index].v.x(), portal->ps[index].v.y(), portal->ps[index].v.z(),
+                  portal->ps[index].v1.x(), portal->ps[index].v1.y(), portal->ps[index].v1.z(),
+                  portal->ps[index].v2.x(), portal->ps[index].v2.y(), portal->ps[index].v2.z());
+}
+#endif  //DEBUG_MPR
+
+inline int btMprSimplexSize(const btMprSimplex_t *s)
+{
+       return s->last + 1;
+}
+
+inline const btMprSupport_t *btMprSimplexPoint(const btMprSimplex_t *s, int idx)
+{
+       // here is no check on boundaries
+       return &s->ps[idx];
+}
+
+inline void btMprSupportCopy(btMprSupport_t *d, const btMprSupport_t *s)
+{
+       *d = *s;
+}
+
+inline void btMprSimplexSet(btMprSimplex_t *s, size_t pos, const btMprSupport_t *a)
+{
+       btMprSupportCopy(s->ps + pos, a);
+}
+
+inline void btMprSimplexSwap(btMprSimplex_t *s, size_t pos1, size_t pos2)
+{
+       btMprSupport_t supp;
+
+       btMprSupportCopy(&supp, &s->ps[pos1]);
+       btMprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
+       btMprSupportCopy(&s->ps[pos2], &supp);
+}
+
+inline int btMprIsZero(float val)
+{
+       return BT_MPR_FABS(val) < FLT_EPSILON;
+}
+
+inline int btMprEq(float _a, float _b)
+{
+       float ab;
+       float a, b;
+
+       ab = BT_MPR_FABS(_a - _b);
+       if (BT_MPR_FABS(ab) < FLT_EPSILON)
+               return 1;
+
+       a = BT_MPR_FABS(_a);
+       b = BT_MPR_FABS(_b);
+       if (b > a)
+       {
+               return ab < FLT_EPSILON * b;
+       }
+       else
+       {
+               return ab < FLT_EPSILON * a;
+       }
+}
+
+inline int btMprVec3Eq(const btVector3 *a, const btVector3 *b)
+{
+       return btMprEq((*a).x(), (*b).x()) && btMprEq((*a).y(), (*b).y()) && btMprEq((*a).z(), (*b).z());
+}
+
+template <typename btConvexTemplate>
+inline void btFindOrigin(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc, btMprSupport_t *center)
+{
+       center->v1 = a.getObjectCenterInWorld();
+       center->v2 = b.getObjectCenterInWorld();
+       center->v = center->v1 - center->v2;
+}
+
+inline void btMprVec3Set(btVector3 *v, float x, float y, float z)
+{
+       v->setValue(x, y, z);
+}
+
+inline void btMprVec3Add(btVector3 *v, const btVector3 *w)
+{
+       *v += *w;
+}
+
+inline void btMprVec3Copy(btVector3 *v, const btVector3 *w)
+{
+       *v = *w;
+}
+
+inline void btMprVec3Scale(btVector3 *d, float k)
+{
+       *d *= k;
+}
+
+inline float btMprVec3Dot(const btVector3 *a, const btVector3 *b)
+{
+       float dot;
+
+       dot = btDot(*a, *b);
+       return dot;
+}
+
+inline float btMprVec3Len2(const btVector3 *v)
+{
+       return btMprVec3Dot(v, v);
+}
+
+inline void btMprVec3Normalize(btVector3 *d)
+{
+       float k = 1.f / BT_MPR_SQRT(btMprVec3Len2(d));
+       btMprVec3Scale(d, k);
+}
+
+inline void btMprVec3Cross(btVector3 *d, const btVector3 *a, const btVector3 *b)
+{
+       *d = btCross(*a, *b);
+}
+
+inline void btMprVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
+{
+       *d = *v - *w;
+}
+
+inline void btPortalDir(const btMprSimplex_t *portal, btVector3 *dir)
+{
+       btVector3 v2v1, v3v1;
+
+       btMprVec3Sub2(&v2v1, &btMprSimplexPoint(portal, 2)->v,
+                                 &btMprSimplexPoint(portal, 1)->v);
+       btMprVec3Sub2(&v3v1, &btMprSimplexPoint(portal, 3)->v,
+                                 &btMprSimplexPoint(portal, 1)->v);
+       btMprVec3Cross(dir, &v2v1, &v3v1);
+       btMprVec3Normalize(dir);
+}
+
+inline int portalEncapsulesOrigin(const btMprSimplex_t *portal,
+                                                                 const btVector3 *dir)
+{
+       float dot;
+       dot = btMprVec3Dot(dir, &btMprSimplexPoint(portal, 1)->v);
+       return btMprIsZero(dot) || dot > 0.f;
+}
+
+inline int portalReachTolerance(const btMprSimplex_t *portal,
+                                                               const btMprSupport_t *v4,
+                                                               const btVector3 *dir)
+{
+       float dv1, dv2, dv3, dv4;
+       float dot1, dot2, dot3;
+
+       // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
+
+       dv1 = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, dir);
+       dv2 = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, dir);
+       dv3 = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, dir);
+       dv4 = btMprVec3Dot(&v4->v, dir);
+
+       dot1 = dv4 - dv1;
+       dot2 = dv4 - dv2;
+       dot3 = dv4 - dv3;
+
+       dot1 = BT_MPR_FMIN(dot1, dot2);
+       dot1 = BT_MPR_FMIN(dot1, dot3);
+
+       return btMprEq(dot1, BT_MPR_TOLERANCE) || dot1 < BT_MPR_TOLERANCE;
+}
+
+inline int portalCanEncapsuleOrigin(const btMprSimplex_t *portal,
+                                                                       const btMprSupport_t *v4,
+                                                                       const btVector3 *dir)
+{
+       float dot;
+       dot = btMprVec3Dot(&v4->v, dir);
+       return btMprIsZero(dot) || dot > 0.f;
+}
+
+inline void btExpandPortal(btMprSimplex_t *portal,
+                                                  const btMprSupport_t *v4)
+{
+       float dot;
+       btVector3 v4v0;
+
+       btMprVec3Cross(&v4v0, &v4->v, &btMprSimplexPoint(portal, 0)->v);
+       dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &v4v0);
+       if (dot > 0.f)
+       {
+               dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &v4v0);
+               if (dot > 0.f)
+               {
+                       btMprSimplexSet(portal, 1, v4);
+               }
+               else
+               {
+                       btMprSimplexSet(portal, 3, v4);
+               }
+       }
+       else
+       {
+               dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &v4v0);
+               if (dot > 0.f)
+               {
+                       btMprSimplexSet(portal, 2, v4);
+               }
+               else
+               {
+                       btMprSimplexSet(portal, 1, v4);
+               }
+       }
+}
+template <typename btConvexTemplate>
+inline void btMprSupport(const btConvexTemplate &a, const btConvexTemplate &b,
+                                                const btMprCollisionDescription &colDesc,
+                                                const btVector3 &dir, btMprSupport_t *supp)
+{
+       btVector3 separatingAxisInA = dir * a.getWorldTransform().getBasis();
+       btVector3 separatingAxisInB = -dir * b.getWorldTransform().getBasis();
+
+       btVector3 pInA = a.getLocalSupportWithMargin(separatingAxisInA);
+       btVector3 qInB = b.getLocalSupportWithMargin(separatingAxisInB);
+
+       supp->v1 = a.getWorldTransform()(pInA);
+       supp->v2 = b.getWorldTransform()(qInB);
+       supp->v = supp->v1 - supp->v2;
+}
+
+template <typename btConvexTemplate>
+static int btDiscoverPortal(const btConvexTemplate &a, const btConvexTemplate &b,
+                                                       const btMprCollisionDescription &colDesc,
+                                                       btMprSimplex_t *portal)
+{
+       btVector3 dir, va, vb;
+       float dot;
+       int cont;
+
+       // vertex 0 is center of portal
+       btFindOrigin(a, b, colDesc, btMprSimplexPointW(portal, 0));
+
+       // vertex 0 is center of portal
+       btMprSimplexSetSize(portal, 1);
+
+       btVector3 zero = btVector3(0, 0, 0);
+       btVector3 *org = &zero;
+
+       if (btMprVec3Eq(&btMprSimplexPoint(portal, 0)->v, org))
+       {
+               // Portal's center lies on origin (0,0,0) => we know that objects
+               // intersect but we would need to know penetration info.
+               // So move center little bit...
+               btMprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
+               btMprVec3Add(&btMprSimplexPointW(portal, 0)->v, &va);
+       }
+
+       // vertex 1 = support in direction of origin
+       btMprVec3Copy(&dir, &btMprSimplexPoint(portal, 0)->v);
+       btMprVec3Scale(&dir, -1.f);
+       btMprVec3Normalize(&dir);
+
+       btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 1));
+
+       btMprSimplexSetSize(portal, 2);
+
+       // test if origin isn't outside of v1
+       dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &dir);
+
+       if (btMprIsZero(dot) || dot < 0.f)
+               return -1;
+
+       // vertex 2
+       btMprVec3Cross(&dir, &btMprSimplexPoint(portal, 0)->v,
+                                  &btMprSimplexPoint(portal, 1)->v);
+       if (btMprIsZero(btMprVec3Len2(&dir)))
+       {
+               if (btMprVec3Eq(&btMprSimplexPoint(portal, 1)->v, org))
+               {
+                       // origin lies on v1
+                       return 1;
+               }
+               else
+               {
+                       // origin lies on v0-v1 segment
+                       return 2;
+               }
+       }
+
+       btMprVec3Normalize(&dir);
+       btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 2));
+
+       dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &dir);
+       if (btMprIsZero(dot) || dot < 0.f)
+               return -1;
+
+       btMprSimplexSetSize(portal, 3);
+
+       // vertex 3 direction
+       btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
+                                 &btMprSimplexPoint(portal, 0)->v);
+       btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
+                                 &btMprSimplexPoint(portal, 0)->v);
+       btMprVec3Cross(&dir, &va, &vb);
+       btMprVec3Normalize(&dir);
+
+       // it is better to form portal faces to be oriented "outside" origin
+       dot = btMprVec3Dot(&dir, &btMprSimplexPoint(portal, 0)->v);
+       if (dot > 0.f)
+       {
+               btMprSimplexSwap(portal, 1, 2);
+               btMprVec3Scale(&dir, -1.f);
+       }
+
+       while (btMprSimplexSize(portal) < 4)
+       {
+               btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 3));
+
+               dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &dir);
+               if (btMprIsZero(dot) || dot < 0.f)
+                       return -1;
+
+               cont = 0;
+
+               // test if origin is outside (v1, v0, v3) - set v2 as v3 and
+               // continue
+               btMprVec3Cross(&va, &btMprSimplexPoint(portal, 1)->v,
+                                          &btMprSimplexPoint(portal, 3)->v);
+               dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
+               if (dot < 0.f && !btMprIsZero(dot))
+               {
+                       btMprSimplexSet(portal, 2, btMprSimplexPoint(portal, 3));
+                       cont = 1;
+               }
+
+               if (!cont)
+               {
+                       // test if origin is outside (v3, v0, v2) - set v1 as v3 and
+                       // continue
+                       btMprVec3Cross(&va, &btMprSimplexPoint(portal, 3)->v,
+                                                  &btMprSimplexPoint(portal, 2)->v);
+                       dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
+                       if (dot < 0.f && !btMprIsZero(dot))
+                       {
+                               btMprSimplexSet(portal, 1, btMprSimplexPoint(portal, 3));
+                               cont = 1;
+                       }
+               }
+
+               if (cont)
+               {
+                       btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
+                                                 &btMprSimplexPoint(portal, 0)->v);
+                       btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
+                                                 &btMprSimplexPoint(portal, 0)->v);
+                       btMprVec3Cross(&dir, &va, &vb);
+                       btMprVec3Normalize(&dir);
+               }
+               else
+               {
+                       btMprSimplexSetSize(portal, 4);
+               }
+       }
+
+       return 0;
+}
+
+template <typename btConvexTemplate>
+static int btRefinePortal(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc,
+                                                 btMprSimplex_t *portal)
+{
+       btVector3 dir;
+       btMprSupport_t v4;
+
+       for (int i = 0; i < BT_MPR_MAX_ITERATIONS; i++)
+       //while (1)
+       {
+               // compute direction outside the portal (from v0 through v1,v2,v3
+               // face)
+               btPortalDir(portal, &dir);
+
+               // test if origin is inside the portal
+               if (portalEncapsulesOrigin(portal, &dir))
+                       return 0;
+
+               // get next support point
+
+               btMprSupport(a, b, colDesc, dir, &v4);
+
+               // test if v4 can expand portal to contain origin and if portal
+               // expanding doesn't reach given tolerance
+               if (!portalCanEncapsuleOrigin(portal, &v4, &dir) || portalReachTolerance(portal, &v4, &dir))
+               {
+                       return -1;
+               }
+
+               // v1-v2-v3 triangle must be rearranged to face outside Minkowski
+               // difference (direction from v0).
+               btExpandPortal(portal, &v4);
+       }
+
+       return -1;
+}
+
+static void btFindPos(const btMprSimplex_t *portal, btVector3 *pos)
+{
+       btVector3 zero = btVector3(0, 0, 0);
+       btVector3 *origin = &zero;
+
+       btVector3 dir;
+       size_t i;
+       float b[4], sum, inv;
+       btVector3 vec, p1, p2;
+
+       btPortalDir(portal, &dir);
+
+       // use barycentric coordinates of tetrahedron to find origin
+       btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
+                                  &btMprSimplexPoint(portal, 2)->v);
+       b[0] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
+
+       btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
+                                  &btMprSimplexPoint(portal, 2)->v);
+       b[1] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
+
+       btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 0)->v,
+                                  &btMprSimplexPoint(portal, 1)->v);
+       b[2] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
+
+       btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
+                                  &btMprSimplexPoint(portal, 1)->v);
+       b[3] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
+
+       sum = b[0] + b[1] + b[2] + b[3];
+
+       if (btMprIsZero(sum) || sum < 0.f)
+       {
+               b[0] = 0.f;
+
+               btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
+                                          &btMprSimplexPoint(portal, 3)->v);
+               b[1] = btMprVec3Dot(&vec, &dir);
+               btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
+                                          &btMprSimplexPoint(portal, 1)->v);
+               b[2] = btMprVec3Dot(&vec, &dir);
+               btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
+                                          &btMprSimplexPoint(portal, 2)->v);
+               b[3] = btMprVec3Dot(&vec, &dir);
+
+               sum = b[1] + b[2] + b[3];
+       }
+
+       inv = 1.f / sum;
+
+       btMprVec3Copy(&p1, origin);
+       btMprVec3Copy(&p2, origin);
+       for (i = 0; i < 4; i++)
+       {
+               btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v1);
+               btMprVec3Scale(&vec, b[i]);
+               btMprVec3Add(&p1, &vec);
+
+               btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v2);
+               btMprVec3Scale(&vec, b[i]);
+               btMprVec3Add(&p2, &vec);
+       }
+       btMprVec3Scale(&p1, inv);
+       btMprVec3Scale(&p2, inv);
+#ifdef MPR_AVERAGE_CONTACT_POSITIONS
+       btMprVec3Copy(pos, &p1);
+       btMprVec3Add(pos, &p2);
+       btMprVec3Scale(pos, 0.5);
+#else
+       btMprVec3Copy(pos, &p2);
+#endif  //MPR_AVERAGE_CONTACT_POSITIONS
+}
+
+inline float btMprVec3Dist2(const btVector3 *a, const btVector3 *b)
+{
+       btVector3 ab;
+       btMprVec3Sub2(&ab, a, b);
+       return btMprVec3Len2(&ab);
+}
+
+inline float _btMprVec3PointSegmentDist2(const btVector3 *P,
+                                                                                const btVector3 *x0,
+                                                                                const btVector3 *b,
+                                                                                btVector3 *witness)
+{
+       // The computation comes from solving equation of segment:
+       //      S(t) = x0 + t.d
+       //          where - x0 is initial point of segment
+       //                - d is direction of segment from x0 (|d| > 0)
+       //                - t belongs to <0, 1> interval
+       //
+       // Than, distance from a segment to some point P can be expressed:
+       //      D(t) = |x0 + t.d - P|^2
+       //          which is distance from any point on segment. Minimization
+       //          of this function brings distance from P to segment.
+       // Minimization of D(t) leads to simple quadratic equation that's
+       // solving is straightforward.
+       //
+       // Bonus of this method is witness point for free.
+
+       float dist, t;
+       btVector3 d, a;
+
+       // direction of segment
+       btMprVec3Sub2(&d, b, x0);
+
+       // precompute vector from P to x0
+       btMprVec3Sub2(&a, x0, P);
+
+       t = -1.f * btMprVec3Dot(&a, &d);
+       t /= btMprVec3Len2(&d);
+
+       if (t < 0.f || btMprIsZero(t))
+       {
+               dist = btMprVec3Dist2(x0, P);
+               if (witness)
+                       btMprVec3Copy(witness, x0);
+       }
+       else if (t > 1.f || btMprEq(t, 1.f))
+       {
+               dist = btMprVec3Dist2(b, P);
+               if (witness)
+                       btMprVec3Copy(witness, b);
+       }
+       else
+       {
+               if (witness)
+               {
+                       btMprVec3Copy(witness, &d);
+                       btMprVec3Scale(witness, t);
+                       btMprVec3Add(witness, x0);
+                       dist = btMprVec3Dist2(witness, P);
+               }
+               else
+               {
+                       // recycling variables
+                       btMprVec3Scale(&d, t);
+                       btMprVec3Add(&d, &a);
+                       dist = btMprVec3Len2(&d);
+               }
+       }
+
+       return dist;
+}
+
+inline float btMprVec3PointTriDist2(const btVector3 *P,
+                                                                       const btVector3 *x0, const btVector3 *B,
+                                                                       const btVector3 *C,
+                                                                       btVector3 *witness)
+{
+       // Computation comes from analytic expression for triangle (x0, B, C)
+       //      T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and
+       // Then equation for distance is:
+       //      D(s, t) = | T(s, t) - P |^2
+       // This leads to minimization of quadratic function of two variables.
+       // The solution from is taken only if s is between 0 and 1, t is
+       // between 0 and 1 and t + s < 1, otherwise distance from segment is
+       // computed.
+
+       btVector3 d1, d2, a;
+       float u, v, w, p, q, r;
+       float s, t, dist, dist2;
+       btVector3 witness2;
+
+       btMprVec3Sub2(&d1, B, x0);
+       btMprVec3Sub2(&d2, C, x0);
+       btMprVec3Sub2(&a, x0, P);
+
+       u = btMprVec3Dot(&a, &a);
+       v = btMprVec3Dot(&d1, &d1);
+       w = btMprVec3Dot(&d2, &d2);
+       p = btMprVec3Dot(&a, &d1);
+       q = btMprVec3Dot(&a, &d2);
+       r = btMprVec3Dot(&d1, &d2);
+
+       btScalar div = (w * v - r * r);
+       if (btMprIsZero(div))
+       {
+               s = -1;
+       }
+       else
+       {
+               s = (q * r - w * p) / div;
+               t = (-s * r - q) / w;
+       }
+
+       if ((btMprIsZero(s) || s > 0.f) && (btMprEq(s, 1.f) || s < 1.f) && (btMprIsZero(t) || t > 0.f) && (btMprEq(t, 1.f) || t < 1.f) && (btMprEq(t + s, 1.f) || t + s < 1.f))
+       {
+               if (witness)
+               {
+                       btMprVec3Scale(&d1, s);
+                       btMprVec3Scale(&d2, t);
+                       btMprVec3Copy(witness, x0);
+                       btMprVec3Add(witness, &d1);
+                       btMprVec3Add(witness, &d2);
+
+                       dist = btMprVec3Dist2(witness, P);
+               }
+               else
+               {
+                       dist = s * s * v;
+                       dist += t * t * w;
+                       dist += 2.f * s * t * r;
+                       dist += 2.f * s * p;
+                       dist += 2.f * t * q;
+                       dist += u;
+               }
+       }
+       else
+       {
+               dist = _btMprVec3PointSegmentDist2(P, x0, B, witness);
+
+               dist2 = _btMprVec3PointSegmentDist2(P, x0, C, &witness2);
+               if (dist2 < dist)
+               {
+                       dist = dist2;
+                       if (witness)
+                               btMprVec3Copy(witness, &witness2);
+               }
+
+               dist2 = _btMprVec3PointSegmentDist2(P, B, C, &witness2);
+               if (dist2 < dist)
+               {
+                       dist = dist2;
+                       if (witness)
+                               btMprVec3Copy(witness, &witness2);
+               }
+       }
+
+       return dist;
+}
+
+template <typename btConvexTemplate>
+static void btFindPenetr(const btConvexTemplate &a, const btConvexTemplate &b,
+                                                const btMprCollisionDescription &colDesc,
+                                                btMprSimplex_t *portal,
+                                                float *depth, btVector3 *pdir, btVector3 *pos)
+{
+       btVector3 dir;
+       btMprSupport_t v4;
+       unsigned long iterations;
+
+       btVector3 zero = btVector3(0, 0, 0);
+       btVector3 *origin = &zero;
+
+       iterations = 1UL;
+       for (int i = 0; i < BT_MPR_MAX_ITERATIONS; i++)
+       //while (1)
+       {
+               // compute portal direction and obtain next support point
+               btPortalDir(portal, &dir);
+
+               btMprSupport(a, b, colDesc, dir, &v4);
+
+               // reached tolerance -> find penetration info
+               if (portalReachTolerance(portal, &v4, &dir) || iterations == BT_MPR_MAX_ITERATIONS)
+               {
+                       *depth = btMprVec3PointTriDist2(origin, &btMprSimplexPoint(portal, 1)->v, &btMprSimplexPoint(portal, 2)->v, &btMprSimplexPoint(portal, 3)->v, pdir);
+                       *depth = BT_MPR_SQRT(*depth);
+
+                       if (btMprIsZero((*pdir).x()) && btMprIsZero((*pdir).y()) && btMprIsZero((*pdir).z()))
+                       {
+                               *pdir = dir;
+                       }
+                       btMprVec3Normalize(pdir);
+
+                       // barycentric coordinates:
+                       btFindPos(portal, pos);
+
+                       return;
+               }
+
+               btExpandPortal(portal, &v4);
+
+               iterations++;
+       }
+}
+
+static void btFindPenetrTouch(btMprSimplex_t *portal, float *depth, btVector3 *dir, btVector3 *pos)
+{
+       // Touching contact on portal's v1 - so depth is zero and direction
+       // is unimportant and pos can be guessed
+       *depth = 0.f;
+       btVector3 zero = btVector3(0, 0, 0);
+       btVector3 *origin = &zero;
+
+       btMprVec3Copy(dir, origin);
+#ifdef MPR_AVERAGE_CONTACT_POSITIONS
+       btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
+       btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
+       btMprVec3Scale(pos, 0.5);
+#else
+       btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
+#endif
+}
+
+static void btFindPenetrSegment(btMprSimplex_t *portal,
+                                                               float *depth, btVector3 *dir, btVector3 *pos)
+{
+       // Origin lies on v0-v1 segment.
+       // Depth is distance to v1, direction also and position must be
+       // computed
+#ifdef MPR_AVERAGE_CONTACT_POSITIONS
+       btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
+       btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
+       btMprVec3Scale(pos, 0.5f);
+#else
+       btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
+#endif  //MPR_AVERAGE_CONTACT_POSITIONS
+
+       btMprVec3Copy(dir, &btMprSimplexPoint(portal, 1)->v);
+       *depth = BT_MPR_SQRT(btMprVec3Len2(dir));
+       btMprVec3Normalize(dir);
+}
+
+template <typename btConvexTemplate>
+inline int btMprPenetration(const btConvexTemplate &a, const btConvexTemplate &b,
+                                                       const btMprCollisionDescription &colDesc,
+                                                       float *depthOut, btVector3 *dirOut, btVector3 *posOut)
+{
+       btMprSimplex_t portal;
+
+       // Phase 1: Portal discovery
+       int result = btDiscoverPortal(a, b, colDesc, &portal);
+
+       //sepAxis[pairIndex] = *pdir;//or -dir?
+
+       switch (result)
+       {
+               case 0:
+               {
+                       // Phase 2: Portal refinement
+
+                       result = btRefinePortal(a, b, colDesc, &portal);
+                       if (result < 0)
+                               return -1;
+
+                       // Phase 3. Penetration info
+                       btFindPenetr(a, b, colDesc, &portal, depthOut, dirOut, posOut);
+
+                       break;
+               }
+               case 1:
+               {
+                       // Touching contact on portal's v1.
+                       btFindPenetrTouch(&portal, depthOut, dirOut, posOut);
+                       result = 0;
+                       break;
+               }
+               case 2:
+               {
+                       btFindPenetrSegment(&portal, depthOut, dirOut, posOut);
+                       result = 0;
+                       break;
+               }
+               default:
+               {
+                       //if (res < 0)
+                       //{
+                       // Origin isn't inside portal - no collision.
+                       result = -1;
+                       //}
+               }
+       };
+
+       return result;
+};
+
+template <typename btConvexTemplate, typename btMprDistanceTemplate>
+inline int btComputeMprPenetration(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc, btMprDistanceTemplate *distInfo)
+{
+       btVector3 dir, pos;
+       float depth;
+
+       int res = btMprPenetration(a, b, colDesc, &depth, &dir, &pos);
+       if (res == 0)
+       {
+               distInfo->m_distance = -depth;
+               distInfo->m_pointOnB = pos;
+               distInfo->m_normalBtoA = -dir;
+               distInfo->m_pointOnA = pos - distInfo->m_distance * dir;
+               return 0;
+       }
+
+       return -1;
+}
+
+#endif  //BT_MPR_PENETRATION_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
new file mode 100644 (file)
index 0000000..366cf15
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btPersistentManifold.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btSerializer.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btCollisionObjectData btCollisionObjectDoubleData
+#else
+#define btCollisionObjectData btCollisionObjectFloatData
+#endif
+
+btScalar gContactBreakingThreshold = btScalar(0.02);
+ContactDestroyedCallback gContactDestroyedCallback = 0;
+ContactProcessedCallback gContactProcessedCallback = 0;
+ContactStartedCallback gContactStartedCallback = 0;
+ContactEndedCallback gContactEndedCallback = 0;
+///gContactCalcArea3Points will approximate the convex hull area using 3 points
+///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower
+bool gContactCalcArea3Points = true;
+
+btPersistentManifold::btPersistentManifold()
+       : btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
+         m_body0(0),
+         m_body1(0),
+         m_cachedPoints(0),
+         m_companionIdA(0),
+         m_companionIdB(0),
+         m_index1a(0)
+{
+}
+
+#ifdef DEBUG_PERSISTENCY
+#include <stdio.h>
+void btPersistentManifold::DebugPersistency()
+{
+       int i;
+       printf("DebugPersistency : numPoints %d\n", m_cachedPoints);
+       for (i = 0; i < m_cachedPoints; i++)
+       {
+               printf("m_pointCache[%d].m_userPersistentData = %x\n", i, m_pointCache[i].m_userPersistentData);
+       }
+}
+#endif  //DEBUG_PERSISTENCY
+
+void btPersistentManifold::clearUserCache(btManifoldPoint& pt)
+{
+       void* oldPtr = pt.m_userPersistentData;
+       if (oldPtr)
+       {
+#ifdef DEBUG_PERSISTENCY
+               int i;
+               int occurance = 0;
+               for (i = 0; i < m_cachedPoints; i++)
+               {
+                       if (m_pointCache[i].m_userPersistentData == oldPtr)
+                       {
+                               occurance++;
+                               if (occurance > 1)
+                                       printf("error in clearUserCache\n");
+                       }
+               }
+               btAssert(occurance <= 0);
+#endif  //DEBUG_PERSISTENCY
+
+               if (pt.m_userPersistentData && gContactDestroyedCallback)
+               {
+                       (*gContactDestroyedCallback)(pt.m_userPersistentData);
+                       pt.m_userPersistentData = 0;
+               }
+
+#ifdef DEBUG_PERSISTENCY
+               DebugPersistency();
+#endif
+       }
+}
+
+static inline btScalar calcArea4Points(const btVector3& p0, const btVector3& p1, const btVector3& p2, const btVector3& p3)
+{
+       // It calculates possible 3 area constructed from random 4 points and returns the biggest one.
+
+       btVector3 a[3], b[3];
+       a[0] = p0 - p1;
+       a[1] = p0 - p2;
+       a[2] = p0 - p3;
+       b[0] = p2 - p3;
+       b[1] = p1 - p3;
+       b[2] = p1 - p2;
+
+       //todo: Following 3 cross production can be easily optimized by SIMD.
+       btVector3 tmp0 = a[0].cross(b[0]);
+       btVector3 tmp1 = a[1].cross(b[1]);
+       btVector3 tmp2 = a[2].cross(b[2]);
+
+       return btMax(btMax(tmp0.length2(), tmp1.length2()), tmp2.length2());
+}
+
+int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt)
+{
+       //calculate 4 possible cases areas, and take biggest area
+       //also need to keep 'deepest'
+
+       int maxPenetrationIndex = -1;
+#define KEEP_DEEPEST_POINT 1
+#ifdef KEEP_DEEPEST_POINT
+       btScalar maxPenetration = pt.getDistance();
+       for (int i = 0; i < 4; i++)
+       {
+               if (m_pointCache[i].getDistance() < maxPenetration)
+               {
+                       maxPenetrationIndex = i;
+                       maxPenetration = m_pointCache[i].getDistance();
+               }
+       }
+#endif  //KEEP_DEEPEST_POINT
+
+       btScalar res0(btScalar(0.)), res1(btScalar(0.)), res2(btScalar(0.)), res3(btScalar(0.));
+
+       if (gContactCalcArea3Points)
+       {
+               if (maxPenetrationIndex != 0)
+               {
+                       btVector3 a0 = pt.m_localPointA - m_pointCache[1].m_localPointA;
+                       btVector3 b0 = m_pointCache[3].m_localPointA - m_pointCache[2].m_localPointA;
+                       btVector3 cross = a0.cross(b0);
+                       res0 = cross.length2();
+               }
+               if (maxPenetrationIndex != 1)
+               {
+                       btVector3 a1 = pt.m_localPointA - m_pointCache[0].m_localPointA;
+                       btVector3 b1 = m_pointCache[3].m_localPointA - m_pointCache[2].m_localPointA;
+                       btVector3 cross = a1.cross(b1);
+                       res1 = cross.length2();
+               }
+
+               if (maxPenetrationIndex != 2)
+               {
+                       btVector3 a2 = pt.m_localPointA - m_pointCache[0].m_localPointA;
+                       btVector3 b2 = m_pointCache[3].m_localPointA - m_pointCache[1].m_localPointA;
+                       btVector3 cross = a2.cross(b2);
+                       res2 = cross.length2();
+               }
+
+               if (maxPenetrationIndex != 3)
+               {
+                       btVector3 a3 = pt.m_localPointA - m_pointCache[0].m_localPointA;
+                       btVector3 b3 = m_pointCache[2].m_localPointA - m_pointCache[1].m_localPointA;
+                       btVector3 cross = a3.cross(b3);
+                       res3 = cross.length2();
+               }
+       }
+       else
+       {
+               if (maxPenetrationIndex != 0)
+               {
+                       res0 = calcArea4Points(pt.m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[2].m_localPointA, m_pointCache[3].m_localPointA);
+               }
+
+               if (maxPenetrationIndex != 1)
+               {
+                       res1 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[2].m_localPointA, m_pointCache[3].m_localPointA);
+               }
+
+               if (maxPenetrationIndex != 2)
+               {
+                       res2 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[3].m_localPointA);
+               }
+
+               if (maxPenetrationIndex != 3)
+               {
+                       res3 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[2].m_localPointA);
+               }
+       }
+       btVector4 maxvec(res0, res1, res2, res3);
+       int biggestarea = maxvec.closestAxis4();
+       return biggestarea;
+}
+
+int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
+{
+       btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
+       int size = getNumContacts();
+       int nearestPoint = -1;
+       for (int i = 0; i < size; i++)
+       {
+               const btManifoldPoint& mp = m_pointCache[i];
+
+               btVector3 diffA = mp.m_localPointA - newPoint.m_localPointA;
+               const btScalar distToManiPoint = diffA.dot(diffA);
+               if (distToManiPoint < shortestDist)
+               {
+                       shortestDist = distToManiPoint;
+                       nearestPoint = i;
+               }
+       }
+       return nearestPoint;
+}
+
+int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive)
+{
+       if (!isPredictive)
+       {
+               btAssert(validContactDistance(newPoint));
+       }
+
+       int insertIndex = getNumContacts();
+       if (insertIndex == MANIFOLD_CACHE_SIZE)
+       {
+#if MANIFOLD_CACHE_SIZE >= 4
+               //sort cache so best points come first, based on area
+               insertIndex = sortCachedPoints(newPoint);
+#else
+               insertIndex = 0;
+#endif
+               clearUserCache(m_pointCache[insertIndex]);
+       }
+       else
+       {
+               m_cachedPoints++;
+       }
+       if (insertIndex < 0)
+               insertIndex = 0;
+
+       btAssert(m_pointCache[insertIndex].m_userPersistentData == 0);
+       m_pointCache[insertIndex] = newPoint;
+       return insertIndex;
+}
+
+btScalar btPersistentManifold::getContactBreakingThreshold() const
+{
+       return m_contactBreakingThreshold;
+}
+
+void btPersistentManifold::refreshContactPoints(const btTransform& trA, const btTransform& trB)
+{
+       int i;
+#ifdef DEBUG_PERSISTENCY
+       printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
+                  trA.getOrigin().getX(),
+                  trA.getOrigin().getY(),
+                  trA.getOrigin().getZ(),
+                  trB.getOrigin().getX(),
+                  trB.getOrigin().getY(),
+                  trB.getOrigin().getZ());
+#endif  //DEBUG_PERSISTENCY
+       /// first refresh worldspace positions and distance
+       for (i = getNumContacts() - 1; i >= 0; i--)
+       {
+               btManifoldPoint& manifoldPoint = m_pointCache[i];
+               manifoldPoint.m_positionWorldOnA = trA(manifoldPoint.m_localPointA);
+               manifoldPoint.m_positionWorldOnB = trB(manifoldPoint.m_localPointB);
+               manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
+               manifoldPoint.m_lifeTime++;
+       }
+
+       /// then
+       btScalar distance2d;
+       btVector3 projectedDifference, projectedPoint;
+       for (i = getNumContacts() - 1; i >= 0; i--)
+       {
+               btManifoldPoint& manifoldPoint = m_pointCache[i];
+               //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
+               if (!validContactDistance(manifoldPoint))
+               {
+                       removeContactPoint(i);
+               }
+               else
+               {
+                       //todo: friction anchor may require the contact to be around a bit longer
+                       //contact also becomes invalid when relative movement orthogonal to normal exceeds margin
+                       projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
+                       projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
+                       distance2d = projectedDifference.dot(projectedDifference);
+                       if (distance2d > getContactBreakingThreshold() * getContactBreakingThreshold())
+                       {
+                               removeContactPoint(i);
+                       }
+                       else
+                       {
+                               //contact point processed callback
+                               if (gContactProcessedCallback)
+                                       (*gContactProcessedCallback)(manifoldPoint, (void*)m_body0, (void*)m_body1);
+                       }
+               }
+       }
+#ifdef DEBUG_PERSISTENCY
+       DebugPersistency();
+#endif  //
+}
+
+int btPersistentManifold::calculateSerializeBufferSize() const
+{
+       return sizeof(btPersistentManifoldData);
+}
+
+const char* btPersistentManifold::serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const
+{
+       btPersistentManifoldData* dataOut = (btPersistentManifoldData*)dataBuffer;
+       memset(dataOut, 0, sizeof(btPersistentManifoldData));
+
+       dataOut->m_body0 = (btCollisionObjectData*)serializer->getUniquePointer((void*)manifold->getBody0());
+       dataOut->m_body1 = (btCollisionObjectData*)serializer->getUniquePointer((void*)manifold->getBody1());
+       dataOut->m_contactBreakingThreshold = manifold->getContactBreakingThreshold();
+       dataOut->m_contactProcessingThreshold = manifold->getContactProcessingThreshold();
+       dataOut->m_numCachedPoints = manifold->getNumContacts();
+       dataOut->m_companionIdA = manifold->m_companionIdA;
+       dataOut->m_companionIdB = manifold->m_companionIdB;
+       dataOut->m_index1a = manifold->m_index1a;
+       dataOut->m_objectType = manifold->m_objectType;
+
+       for (int i = 0; i < this->getNumContacts(); i++)
+       {
+               const btManifoldPoint& pt = manifold->getContactPoint(i);
+               dataOut->m_pointCacheAppliedImpulse[i] = pt.m_appliedImpulse;
+               dataOut->m_pointCachePrevRHS[i] = pt.m_prevRHS;
+               dataOut->m_pointCacheAppliedImpulseLateral1[i] = pt.m_appliedImpulseLateral1;
+               dataOut->m_pointCacheAppliedImpulseLateral2[i] = pt.m_appliedImpulseLateral2;
+               pt.m_localPointA.serialize(dataOut->m_pointCacheLocalPointA[i]);
+               pt.m_localPointB.serialize(dataOut->m_pointCacheLocalPointB[i]);
+               pt.m_normalWorldOnB.serialize(dataOut->m_pointCacheNormalWorldOnB[i]);
+               dataOut->m_pointCacheDistance[i] = pt.m_distance1;
+               dataOut->m_pointCacheCombinedContactDamping1[i] = pt.m_combinedContactDamping1;
+               dataOut->m_pointCacheCombinedContactStiffness1[i] = pt.m_combinedContactStiffness1;
+               dataOut->m_pointCacheLifeTime[i] = pt.m_lifeTime;
+               dataOut->m_pointCacheFrictionCFM[i] = pt.m_frictionCFM;
+               dataOut->m_pointCacheContactERP[i] = pt.m_contactERP;
+               dataOut->m_pointCacheContactCFM[i] = pt.m_contactCFM;
+               dataOut->m_pointCacheContactPointFlags[i] = pt.m_contactPointFlags;
+               dataOut->m_pointCacheIndex0[i] = pt.m_index0;
+               dataOut->m_pointCacheIndex1[i] = pt.m_index1;
+               dataOut->m_pointCachePartId0[i] = pt.m_partId0;
+               dataOut->m_pointCachePartId1[i] = pt.m_partId1;
+               pt.m_positionWorldOnA.serialize(dataOut->m_pointCachePositionWorldOnA[i]);
+               pt.m_positionWorldOnB.serialize(dataOut->m_pointCachePositionWorldOnB[i]);
+               dataOut->m_pointCacheCombinedFriction[i] = pt.m_combinedFriction;
+               pt.m_lateralFrictionDir1.serialize(dataOut->m_pointCacheLateralFrictionDir1[i]);
+               pt.m_lateralFrictionDir2.serialize(dataOut->m_pointCacheLateralFrictionDir2[i]);
+               dataOut->m_pointCacheCombinedRollingFriction[i] = pt.m_combinedRollingFriction;
+               dataOut->m_pointCacheCombinedSpinningFriction[i] = pt.m_combinedSpinningFriction;
+               dataOut->m_pointCacheCombinedRestitution[i] = pt.m_combinedRestitution;
+               dataOut->m_pointCacheContactMotion1[i] = pt.m_contactMotion1;
+               dataOut->m_pointCacheContactMotion2[i] = pt.m_contactMotion2;
+       }
+       return btPersistentManifoldDataName;
+}
+
+void btPersistentManifold::deSerialize(const struct btPersistentManifoldDoubleData* manifoldDataPtr)
+{
+       m_contactBreakingThreshold = manifoldDataPtr->m_contactBreakingThreshold;
+       m_contactProcessingThreshold = manifoldDataPtr->m_contactProcessingThreshold;
+       m_cachedPoints = manifoldDataPtr->m_numCachedPoints;
+       m_companionIdA = manifoldDataPtr->m_companionIdA;
+       m_companionIdB = manifoldDataPtr->m_companionIdB;
+       //m_index1a = manifoldDataPtr->m_index1a;
+       m_objectType = manifoldDataPtr->m_objectType;
+
+       for (int i = 0; i < this->getNumContacts(); i++)
+       {
+               btManifoldPoint& pt = m_pointCache[i];
+
+               pt.m_appliedImpulse = manifoldDataPtr->m_pointCacheAppliedImpulse[i];
+               pt.m_prevRHS = manifoldDataPtr->m_pointCachePrevRHS[i];
+               pt.m_appliedImpulseLateral1 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral1[i];
+               pt.m_appliedImpulseLateral2 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral2[i];
+               pt.m_localPointA.deSerializeDouble(manifoldDataPtr->m_pointCacheLocalPointA[i]);
+               pt.m_localPointB.deSerializeDouble(manifoldDataPtr->m_pointCacheLocalPointB[i]);
+               pt.m_normalWorldOnB.deSerializeDouble(manifoldDataPtr->m_pointCacheNormalWorldOnB[i]);
+               pt.m_distance1 = manifoldDataPtr->m_pointCacheDistance[i];
+               pt.m_combinedContactDamping1 = manifoldDataPtr->m_pointCacheCombinedContactDamping1[i];
+               pt.m_combinedContactStiffness1 = manifoldDataPtr->m_pointCacheCombinedContactStiffness1[i];
+               pt.m_lifeTime = manifoldDataPtr->m_pointCacheLifeTime[i];
+               pt.m_frictionCFM = manifoldDataPtr->m_pointCacheFrictionCFM[i];
+               pt.m_contactERP = manifoldDataPtr->m_pointCacheContactERP[i];
+               pt.m_contactCFM = manifoldDataPtr->m_pointCacheContactCFM[i];
+               pt.m_contactPointFlags = manifoldDataPtr->m_pointCacheContactPointFlags[i];
+               pt.m_index0 = manifoldDataPtr->m_pointCacheIndex0[i];
+               pt.m_index1 = manifoldDataPtr->m_pointCacheIndex1[i];
+               pt.m_partId0 = manifoldDataPtr->m_pointCachePartId0[i];
+               pt.m_partId1 = manifoldDataPtr->m_pointCachePartId1[i];
+               pt.m_positionWorldOnA.deSerializeDouble(manifoldDataPtr->m_pointCachePositionWorldOnA[i]);
+               pt.m_positionWorldOnB.deSerializeDouble(manifoldDataPtr->m_pointCachePositionWorldOnB[i]);
+               pt.m_combinedFriction = manifoldDataPtr->m_pointCacheCombinedFriction[i];
+               pt.m_lateralFrictionDir1.deSerializeDouble(manifoldDataPtr->m_pointCacheLateralFrictionDir1[i]);
+               pt.m_lateralFrictionDir2.deSerializeDouble(manifoldDataPtr->m_pointCacheLateralFrictionDir2[i]);
+               pt.m_combinedRollingFriction = manifoldDataPtr->m_pointCacheCombinedRollingFriction[i];
+               pt.m_combinedSpinningFriction = manifoldDataPtr->m_pointCacheCombinedSpinningFriction[i];
+               pt.m_combinedRestitution = manifoldDataPtr->m_pointCacheCombinedRestitution[i];
+               pt.m_contactMotion1 = manifoldDataPtr->m_pointCacheContactMotion1[i];
+               pt.m_contactMotion2 = manifoldDataPtr->m_pointCacheContactMotion2[i];
+       }
+}
+
+void btPersistentManifold::deSerialize(const struct btPersistentManifoldFloatData* manifoldDataPtr)
+{
+       m_contactBreakingThreshold = manifoldDataPtr->m_contactBreakingThreshold;
+       m_contactProcessingThreshold = manifoldDataPtr->m_contactProcessingThreshold;
+       m_cachedPoints = manifoldDataPtr->m_numCachedPoints;
+       m_companionIdA = manifoldDataPtr->m_companionIdA;
+       m_companionIdB = manifoldDataPtr->m_companionIdB;
+       //m_index1a = manifoldDataPtr->m_index1a;
+       m_objectType = manifoldDataPtr->m_objectType;
+
+       for (int i = 0; i < this->getNumContacts(); i++)
+       {
+               btManifoldPoint& pt = m_pointCache[i];
+
+               pt.m_appliedImpulse = manifoldDataPtr->m_pointCacheAppliedImpulse[i];
+               pt.m_prevRHS = manifoldDataPtr->m_pointCachePrevRHS[i];
+               pt.m_appliedImpulseLateral1 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral1[i];
+               pt.m_appliedImpulseLateral2 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral2[i];
+               pt.m_localPointA.deSerialize(manifoldDataPtr->m_pointCacheLocalPointA[i]);
+               pt.m_localPointB.deSerialize(manifoldDataPtr->m_pointCacheLocalPointB[i]);
+               pt.m_normalWorldOnB.deSerialize(manifoldDataPtr->m_pointCacheNormalWorldOnB[i]);
+               pt.m_distance1 = manifoldDataPtr->m_pointCacheDistance[i];
+               pt.m_combinedContactDamping1 = manifoldDataPtr->m_pointCacheCombinedContactDamping1[i];
+               pt.m_combinedContactStiffness1 = manifoldDataPtr->m_pointCacheCombinedContactStiffness1[i];
+               pt.m_lifeTime = manifoldDataPtr->m_pointCacheLifeTime[i];
+               pt.m_frictionCFM = manifoldDataPtr->m_pointCacheFrictionCFM[i];
+               pt.m_contactERP = manifoldDataPtr->m_pointCacheContactERP[i];
+               pt.m_contactCFM = manifoldDataPtr->m_pointCacheContactCFM[i];
+               pt.m_contactPointFlags = manifoldDataPtr->m_pointCacheContactPointFlags[i];
+               pt.m_index0 = manifoldDataPtr->m_pointCacheIndex0[i];
+               pt.m_index1 = manifoldDataPtr->m_pointCacheIndex1[i];
+               pt.m_partId0 = manifoldDataPtr->m_pointCachePartId0[i];
+               pt.m_partId1 = manifoldDataPtr->m_pointCachePartId1[i];
+               pt.m_positionWorldOnA.deSerialize(manifoldDataPtr->m_pointCachePositionWorldOnA[i]);
+               pt.m_positionWorldOnB.deSerialize(manifoldDataPtr->m_pointCachePositionWorldOnB[i]);
+               pt.m_combinedFriction = manifoldDataPtr->m_pointCacheCombinedFriction[i];
+               pt.m_lateralFrictionDir1.deSerialize(manifoldDataPtr->m_pointCacheLateralFrictionDir1[i]);
+               pt.m_lateralFrictionDir2.deSerialize(manifoldDataPtr->m_pointCacheLateralFrictionDir2[i]);
+               pt.m_combinedRollingFriction = manifoldDataPtr->m_pointCacheCombinedRollingFriction[i];
+               pt.m_combinedSpinningFriction = manifoldDataPtr->m_pointCacheCombinedSpinningFriction[i];
+               pt.m_combinedRestitution = manifoldDataPtr->m_pointCacheCombinedRestitution[i];
+               pt.m_contactMotion1 = manifoldDataPtr->m_pointCacheContactMotion1[i];
+               pt.m_contactMotion2 = manifoldDataPtr->m_pointCacheContactMotion2[i];
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
new file mode 100644 (file)
index 0000000..b07e486
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_PERSISTENT_MANIFOLD_H
+#define BT_PERSISTENT_MANIFOLD_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "btManifoldPoint.h"
+class btCollisionObject;
+#include "LinearMath/btAlignedAllocator.h"
+
+struct btCollisionResult;
+struct btCollisionObjectDoubleData;
+struct btCollisionObjectFloatData;
+
+///maximum contact breaking and merging threshold
+extern btScalar gContactBreakingThreshold;
+
+#ifndef SWIG
+class btPersistentManifold;
+
+typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
+typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp, void* body0, void* body1);
+typedef void (*ContactStartedCallback)(btPersistentManifold* const& manifold);
+typedef void (*ContactEndedCallback)(btPersistentManifold* const& manifold);
+extern ContactDestroyedCallback gContactDestroyedCallback;
+extern ContactProcessedCallback gContactProcessedCallback;
+extern ContactStartedCallback gContactStartedCallback;
+extern ContactEndedCallback gContactEndedCallback;
+#endif  //SWIG
+
+//the enum starts at 1024 to avoid type conflicts with btTypedConstraint
+enum btContactManifoldTypes
+{
+       MIN_CONTACT_MANIFOLD_TYPE = 1024,
+       BT_PERSISTENT_MANIFOLD_TYPE
+};
+
+#define MANIFOLD_CACHE_SIZE 4
+
+///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
+///Those contact points are created by the collision narrow phase.
+///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time.
+///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large)
+///reduces the cache to 4 points, when more then 4 points are added, using following rules:
+///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
+///note that some pairs of objects might have more then one contact manifold.
+
+//ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
+ATTRIBUTE_ALIGNED16(class)
+btPersistentManifold : public btTypedObject
+{
+       btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
+
+       /// this two body pointers can point to the physics rigidbody class.
+       const btCollisionObject* m_body0;
+       const btCollisionObject* m_body1;
+
+       int m_cachedPoints;
+
+       btScalar m_contactBreakingThreshold;
+       btScalar m_contactProcessingThreshold;
+
+       /// sort cached points so most isolated points come first
+       int sortCachedPoints(const btManifoldPoint& pt);
+
+       int findContactPoint(const btManifoldPoint* unUsed, int numUnused, const btManifoldPoint& pt);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       int m_companionIdA;
+       int m_companionIdB;
+
+       int m_index1a;
+
+       btPersistentManifold();
+
+       btPersistentManifold(const btCollisionObject* body0, const btCollisionObject* body1, int, btScalar contactBreakingThreshold, btScalar contactProcessingThreshold)
+               : btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
+                 m_body0(body0),
+                 m_body1(body1),
+                 m_cachedPoints(0),
+                 m_contactBreakingThreshold(contactBreakingThreshold),
+                 m_contactProcessingThreshold(contactProcessingThreshold),
+                 m_companionIdA(0),
+                 m_companionIdB(0),
+                 m_index1a(0)
+       {
+       }
+
+       SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0; }
+       SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1; }
+
+       void setBodies(const btCollisionObject* body0, const btCollisionObject* body1)
+       {
+               m_body0 = body0;
+               m_body1 = body1;
+       }
+
+       void clearUserCache(btManifoldPoint & pt);
+
+#ifdef DEBUG_PERSISTENCY
+       void DebugPersistency();
+#endif  //
+
+       SIMD_FORCE_INLINE int getNumContacts() const
+       {
+               return m_cachedPoints;
+       }
+       /// the setNumContacts API is usually not used, except when you gather/fill all contacts manually
+       void setNumContacts(int cachedPoints)
+       {
+               m_cachedPoints = cachedPoints;
+       }
+
+       SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const
+       {
+               btAssert(index < m_cachedPoints);
+               return m_pointCache[index];
+       }
+
+       SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index)
+       {
+               btAssert(index < m_cachedPoints);
+               return m_pointCache[index];
+       }
+
+       ///@todo: get this margin from the current physics / collision environment
+       btScalar getContactBreakingThreshold() const;
+
+       btScalar getContactProcessingThreshold() const
+       {
+               return m_contactProcessingThreshold;
+       }
+
+       void setContactBreakingThreshold(btScalar contactBreakingThreshold)
+       {
+               m_contactBreakingThreshold = contactBreakingThreshold;
+       }
+
+       void setContactProcessingThreshold(btScalar contactProcessingThreshold)
+       {
+               m_contactProcessingThreshold = contactProcessingThreshold;
+       }
+
+       int getCacheEntry(const btManifoldPoint& newPoint) const;
+
+       int addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive = false);
+
+       void removeContactPoint(int index)
+       {
+               clearUserCache(m_pointCache[index]);
+
+               int lastUsedIndex = getNumContacts() - 1;
+               //              m_pointCache[index] = m_pointCache[lastUsedIndex];
+               if (index != lastUsedIndex)
+               {
+                       m_pointCache[index] = m_pointCache[lastUsedIndex];
+                       //get rid of duplicated userPersistentData pointer
+                       m_pointCache[lastUsedIndex].m_userPersistentData = 0;
+                       m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
+                       m_pointCache[lastUsedIndex].m_prevRHS = 0.f;
+                       m_pointCache[lastUsedIndex].m_contactPointFlags = 0;
+                       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);
+               m_cachedPoints--;
+
+               if (gContactEndedCallback && m_cachedPoints == 0)
+               {
+                       gContactEndedCallback(this);
+               }
+       }
+       void replaceContactPoint(const btManifoldPoint& newPoint, int insertIndex)
+       {
+               btAssert(validContactDistance(newPoint));
+
+#define MAINTAIN_PERSISTENCY 1
+#ifdef MAINTAIN_PERSISTENCY
+               int lifeTime = m_pointCache[insertIndex].getLifeTime();
+               btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
+               btScalar prevRHS = m_pointCache[insertIndex].m_prevRHS;
+               btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
+               btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
+
+               bool replacePoint = true;
+               ///we keep existing contact points for friction anchors
+               ///if the friction force is within the Coulomb friction cone
+               if (newPoint.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
+               {
+                       //   printf("appliedImpulse=%f\n", appliedImpulse);
+                       //   printf("appliedLateralImpulse1=%f\n", appliedLateralImpulse1);
+                       //   printf("appliedLateralImpulse2=%f\n", appliedLateralImpulse2);
+                       //   printf("mu = %f\n", m_pointCache[insertIndex].m_combinedFriction);
+                       btScalar mu = m_pointCache[insertIndex].m_combinedFriction;
+                       btScalar eps = 0;  //we could allow to enlarge or shrink the tolerance to check against the friction cone a bit, say 1e-7
+                       btScalar a = appliedLateralImpulse1 * appliedLateralImpulse1 + appliedLateralImpulse2 * appliedLateralImpulse2;
+                       btScalar b = eps + mu * appliedImpulse;
+                       b = b * b;
+                       replacePoint = (a) > (b);
+               }
+
+               if (replacePoint)
+               {
+                       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_prevRHS = prevRHS;
+                       m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
+                       m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
+               }
+
+               m_pointCache[insertIndex].m_lifeTime = lifeTime;
+#else
+               clearUserCache(m_pointCache[insertIndex]);
+               m_pointCache[insertIndex] = newPoint;
+
+#endif
+       }
+
+       bool validContactDistance(const btManifoldPoint& pt) const
+       {
+               return pt.m_distance1 <= getContactBreakingThreshold();
+       }
+       /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
+       void refreshContactPoints(const btTransform& trA, const btTransform& trB);
+
+       SIMD_FORCE_INLINE void clearManifold()
+       {
+               int i;
+               for (i = 0; i < m_cachedPoints; i++)
+               {
+                       clearUserCache(m_pointCache[i]);
+               }
+
+               if (gContactEndedCallback && m_cachedPoints)
+               {
+                       gContactEndedCallback(this);
+               }
+               m_cachedPoints = 0;
+       }
+
+       int calculateSerializeBufferSize() const;
+       const char* serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const;
+       void deSerialize(const struct btPersistentManifoldDoubleData* manifoldDataPtr);
+       void deSerialize(const struct btPersistentManifoldFloatData* manifoldDataPtr);
+};
+
+// clang-format off
+
+struct btPersistentManifoldDoubleData
+{
+       btVector3DoubleData m_pointCacheLocalPointA[4];
+       btVector3DoubleData m_pointCacheLocalPointB[4];
+       btVector3DoubleData m_pointCachePositionWorldOnA[4];
+       btVector3DoubleData m_pointCachePositionWorldOnB[4];
+       btVector3DoubleData m_pointCacheNormalWorldOnB[4];
+       btVector3DoubleData     m_pointCacheLateralFrictionDir1[4];
+       btVector3DoubleData     m_pointCacheLateralFrictionDir2[4];
+       double m_pointCacheDistance[4];
+       double m_pointCacheAppliedImpulse[4];
+       double m_pointCachePrevRHS[4];
+        double m_pointCacheCombinedFriction[4];
+       double m_pointCacheCombinedRollingFriction[4];
+       double m_pointCacheCombinedSpinningFriction[4];
+       double m_pointCacheCombinedRestitution[4];
+       int     m_pointCachePartId0[4];
+       int     m_pointCachePartId1[4];
+       int     m_pointCacheIndex0[4];
+       int     m_pointCacheIndex1[4];
+       int m_pointCacheContactPointFlags[4];
+       double m_pointCacheAppliedImpulseLateral1[4];
+       double m_pointCacheAppliedImpulseLateral2[4];
+       double m_pointCacheContactMotion1[4];
+       double m_pointCacheContactMotion2[4];
+       double m_pointCacheContactCFM[4];
+       double m_pointCacheCombinedContactStiffness1[4];
+       double m_pointCacheContactERP[4];
+       double m_pointCacheCombinedContactDamping1[4];
+       double m_pointCacheFrictionCFM[4];
+       int m_pointCacheLifeTime[4];
+
+       int m_numCachedPoints;
+       int m_companionIdA;
+       int m_companionIdB;
+       int m_index1a;
+
+       int m_objectType;
+       double  m_contactBreakingThreshold;
+       double  m_contactProcessingThreshold;
+       int m_padding;
+
+       btCollisionObjectDoubleData *m_body0;
+       btCollisionObjectDoubleData *m_body1;
+};
+
+
+struct btPersistentManifoldFloatData
+{
+       btVector3FloatData m_pointCacheLocalPointA[4];
+       btVector3FloatData m_pointCacheLocalPointB[4];
+       btVector3FloatData m_pointCachePositionWorldOnA[4];
+       btVector3FloatData m_pointCachePositionWorldOnB[4];
+       btVector3FloatData m_pointCacheNormalWorldOnB[4];
+       btVector3FloatData      m_pointCacheLateralFrictionDir1[4];
+       btVector3FloatData      m_pointCacheLateralFrictionDir2[4];
+       float m_pointCacheDistance[4];
+       float m_pointCacheAppliedImpulse[4];
+       float m_pointCachePrevRHS[4];
+       float m_pointCacheCombinedFriction[4];
+       float m_pointCacheCombinedRollingFriction[4];
+       float m_pointCacheCombinedSpinningFriction[4];
+       float m_pointCacheCombinedRestitution[4];
+       int     m_pointCachePartId0[4];
+       int     m_pointCachePartId1[4];
+       int     m_pointCacheIndex0[4];
+       int     m_pointCacheIndex1[4];
+       int m_pointCacheContactPointFlags[4];
+       float m_pointCacheAppliedImpulseLateral1[4];
+       float m_pointCacheAppliedImpulseLateral2[4];
+       float m_pointCacheContactMotion1[4];
+       float m_pointCacheContactMotion2[4];
+       float m_pointCacheContactCFM[4];
+       float m_pointCacheCombinedContactStiffness1[4];
+       float m_pointCacheContactERP[4];
+       float m_pointCacheCombinedContactDamping1[4];
+       float m_pointCacheFrictionCFM[4];
+       int m_pointCacheLifeTime[4];
+
+       int m_numCachedPoints;
+       int m_companionIdA;
+       int m_companionIdB;
+       int m_index1a;
+
+       int m_objectType;
+       float   m_contactBreakingThreshold;
+       float   m_contactProcessingThreshold;
+       int m_padding;
+
+       btCollisionObjectFloatData *m_body0;
+       btCollisionObjectFloatData *m_body1;
+};
+
+// clang-format on
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btPersistentManifoldData btPersistentManifoldDoubleData
+#define btPersistentManifoldDataName "btPersistentManifoldDoubleData"
+#else
+#define btPersistentManifoldData btPersistentManifoldFloatData
+#define btPersistentManifoldDataName "btPersistentManifoldFloatData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+#endif  //BT_PERSISTENT_MANIFOLD_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h
new file mode 100644 (file)
index 0000000..adebcbe
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_POINT_COLLECTOR_H
+#define BT_POINT_COLLECTOR_H
+
+#include "btDiscreteCollisionDetectorInterface.h"
+
+struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result
+{
+       btVector3 m_normalOnBInWorld;
+       btVector3 m_pointInWorld;
+       btScalar m_distance;  //negative means penetration
+
+       bool m_hasResult;
+
+       btPointCollector()
+               : m_distance(btScalar(BT_LARGE_FLOAT)), m_hasResult(false)
+       {
+       }
+
+       virtual void setShapeIdentifiersA(int partId0, int index0)
+       {
+               (void)partId0;
+               (void)index0;
+       }
+       virtual void setShapeIdentifiersB(int partId1, int index1)
+       {
+               (void)partId1;
+               (void)index1;
+       }
+
+       virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
+       {
+               if (depth < m_distance)
+               {
+                       m_hasResult = true;
+                       m_normalOnBInWorld = normalOnBInWorld;
+                       m_pointInWorld = pointInWorld;
+                       //negative means penetration
+                       m_distance = depth;
+               }
+       }
+};
+
+#endif  //BT_POINT_COLLECTOR_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
new file mode 100644 (file)
index 0000000..9d18360
--- /dev/null
@@ -0,0 +1,548 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+///Separating axis rest based on work from Pierre Terdiman, see
+///And contact clipping based on work from Simon Hobbs
+
+#include "btPolyhedralContactClipping.h"
+#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
+
+#include <float.h>  //for FLT_MAX
+
+int gExpectedNbTests = 0;
+int gActualNbTests = 0;
+bool gUseInternalObject = true;
+
+// Clips a face to the back of a plane
+void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS, btScalar planeEqWS)
+{
+       int ve;
+       btScalar ds, de;
+       int numVerts = pVtxIn.size();
+       if (numVerts < 2)
+               return;
+
+       btVector3 firstVertex = pVtxIn[pVtxIn.size() - 1];
+       btVector3 endVertex = pVtxIn[0];
+
+       ds = planeNormalWS.dot(firstVertex) + planeEqWS;
+
+       for (ve = 0; ve < numVerts; ve++)
+       {
+               endVertex = pVtxIn[ve];
+
+               de = planeNormalWS.dot(endVertex) + planeEqWS;
+
+               if (ds < 0)
+               {
+                       if (de < 0)
+                       {
+                               // Start < 0, end < 0, so output endVertex
+                               ppVtxOut.push_back(endVertex);
+                       }
+                       else
+                       {
+                               // Start < 0, end >= 0, so output intersection
+                               ppVtxOut.push_back(firstVertex.lerp(endVertex, btScalar(ds * 1.f / (ds - de))));
+                       }
+               }
+               else
+               {
+                       if (de < 0)
+                       {
+                               // Start >= 0, end < 0 so output intersection and end
+                               ppVtxOut.push_back(firstVertex.lerp(endVertex, btScalar(ds * 1.f / (ds - de))));
+                               ppVtxOut.push_back(endVertex);
+                       }
+               }
+               firstVertex = endVertex;
+               ds = de;
+       }
+}
+
+static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btVector3& sep_axis, btScalar& depth, btVector3& witnessPointA, btVector3& witnessPointB)
+{
+       btScalar Min0, Max0;
+       btScalar Min1, Max1;
+       btVector3 witnesPtMinA, witnesPtMaxA;
+       btVector3 witnesPtMinB, witnesPtMaxB;
+
+       hullA.project(transA, sep_axis, Min0, Max0, witnesPtMinA, witnesPtMaxA);
+       hullB.project(transB, sep_axis, Min1, Max1, witnesPtMinB, witnesPtMaxB);
+
+       if (Max0 < Min1 || Max1 < Min0)
+               return false;
+
+       btScalar d0 = Max0 - Min1;
+       btAssert(d0 >= 0.0f);
+       btScalar d1 = Max1 - Min0;
+       btAssert(d1 >= 0.0f);
+       if (d0 < d1)
+       {
+               depth = d0;
+               witnessPointA = witnesPtMaxA;
+               witnessPointB = witnesPtMinB;
+       }
+       else
+       {
+               depth = d1;
+               witnessPointA = witnesPtMinA;
+               witnessPointB = witnesPtMaxB;
+       }
+
+       return true;
+}
+
+static int gActualSATPairTests = 0;
+
+inline bool IsAlmostZero(const btVector3& v)
+{
+       if (btFabs(v.x()) > 1e-6 || btFabs(v.y()) > 1e-6 || btFabs(v.z()) > 1e-6) return false;
+       return true;
+}
+
+#ifdef TEST_INTERNAL_OBJECTS
+
+inline void BoxSupport(const btScalar extents[3], const btScalar sv[3], btScalar p[3])
+{
+       // This version is ~11.000 cycles (4%) faster overall in one of the tests.
+       //      IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK);
+       //      IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK);
+       //      IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK);
+       p[0] = sv[0] < 0.0f ? -extents[0] : extents[0];
+       p[1] = sv[1] < 0.0f ? -extents[1] : extents[1];
+       p[2] = sv[2] < 0.0f ? -extents[2] : extents[2];
+}
+
+void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTransform& tr)
+{
+       const btMatrix3x3& rot = tr.getBasis();
+       const btVector3& r0 = rot[0];
+       const btVector3& r1 = rot[1];
+       const btVector3& r2 = rot[2];
+
+       const btScalar x = r0.x() * in.x() + r1.x() * in.y() + r2.x() * in.z();
+       const btScalar y = r0.y() * in.x() + r1.y() * in.y() + r2.y() * in.z();
+       const btScalar z = r0.z() * in.x() + r1.z() * in.y() + r2.z() * in.z();
+
+       out.setValue(x, y, z);
+}
+
+bool TestInternalObjects(const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin)
+{
+       const btScalar dp = delta_c.dot(axis);
+
+       btVector3 localAxis0;
+       InverseTransformPoint3x3(localAxis0, axis, trans0);
+       btVector3 localAxis1;
+       InverseTransformPoint3x3(localAxis1, axis, trans1);
+
+       btScalar p0[3];
+       BoxSupport(convex0.m_extents, localAxis0, p0);
+       btScalar p1[3];
+       BoxSupport(convex1.m_extents, localAxis1, p1);
+
+       const btScalar Radius0 = p0[0] * localAxis0.x() + p0[1] * localAxis0.y() + p0[2] * localAxis0.z();
+       const btScalar Radius1 = p1[0] * localAxis1.x() + p1[1] * localAxis1.y() + p1[2] * localAxis1.z();
+
+       const btScalar MinRadius = Radius0 > convex0.m_radius ? Radius0 : convex0.m_radius;
+       const btScalar MaxRadius = Radius1 > convex1.m_radius ? Radius1 : convex1.m_radius;
+
+       const btScalar MinMaxRadius = MaxRadius + MinRadius;
+       const btScalar d0 = MinMaxRadius + dp;
+       const btScalar d1 = MinMaxRadius - dp;
+
+       const btScalar depth = d0 < d1 ? d0 : d1;
+       if (depth > dmin)
+               return false;
+       return true;
+}
+#endif  //TEST_INTERNAL_OBJECTS
+
+SIMD_FORCE_INLINE void btSegmentsClosestPoints(
+       btVector3& ptsVector,
+       btVector3& offsetA,
+       btVector3& offsetB,
+       btScalar& tA, btScalar& tB,
+       const btVector3& translation,
+       const btVector3& dirA, btScalar hlenA,
+       const btVector3& dirB, btScalar hlenB)
+{
+       // compute the parameters of the closest points on each line segment
+
+       btScalar dirA_dot_dirB = btDot(dirA, dirB);
+       btScalar dirA_dot_trans = btDot(dirA, translation);
+       btScalar dirB_dot_trans = btDot(dirB, translation);
+
+       btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
+
+       if (denom == 0.0f)
+       {
+               tA = 0.0f;
+       }
+       else
+       {
+               tA = (dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB) / denom;
+               if (tA < -hlenA)
+                       tA = -hlenA;
+               else if (tA > hlenA)
+                       tA = hlenA;
+       }
+
+       tB = tA * dirA_dot_dirB - dirB_dot_trans;
+
+       if (tB < -hlenB)
+       {
+               tB = -hlenB;
+               tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+               if (tA < -hlenA)
+                       tA = -hlenA;
+               else if (tA > hlenA)
+                       tA = hlenA;
+       }
+       else if (tB > hlenB)
+       {
+               tB = hlenB;
+               tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+               if (tA < -hlenA)
+                       tA = -hlenA;
+               else if (tA > hlenA)
+                       tA = hlenA;
+       }
+
+       // compute the closest points relative to segment centers.
+
+       offsetA = dirA * tA;
+       offsetB = dirB * tB;
+
+       ptsVector = translation - offsetA + offsetB;
+}
+
+bool btPolyhedralContactClipping::findSeparatingAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut)
+{
+       gActualSATPairTests++;
+
+       //#ifdef TEST_INTERNAL_OBJECTS
+       const btVector3 c0 = transA * hullA.m_localCenter;
+       const btVector3 c1 = transB * hullB.m_localCenter;
+       const btVector3 DeltaC2 = c0 - c1;
+       //#endif
+
+       btScalar dmin = FLT_MAX;
+       int curPlaneTests = 0;
+
+       int numFacesA = hullA.m_faces.size();
+       // Test normals from hullA
+       for (int i = 0; i < numFacesA; i++)
+       {
+               const btVector3 Normal(hullA.m_faces[i].m_plane[0], hullA.m_faces[i].m_plane[1], hullA.m_faces[i].m_plane[2]);
+               btVector3 faceANormalWS = transA.getBasis() * Normal;
+               if (DeltaC2.dot(faceANormalWS) < 0)
+                       faceANormalWS *= -1.f;
+
+               curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+               gExpectedNbTests++;
+               if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
+                       continue;
+               gActualNbTests++;
+#endif
+
+               btScalar d;
+               btVector3 wA, wB;
+               if (!TestSepAxis(hullA, hullB, transA, transB, faceANormalWS, d, wA, wB))
+                       return false;
+
+               if (d < dmin)
+               {
+                       dmin = d;
+                       sep = faceANormalWS;
+               }
+       }
+
+       int numFacesB = hullB.m_faces.size();
+       // Test normals from hullB
+       for (int i = 0; i < numFacesB; i++)
+       {
+               const btVector3 Normal(hullB.m_faces[i].m_plane[0], hullB.m_faces[i].m_plane[1], hullB.m_faces[i].m_plane[2]);
+               btVector3 WorldNormal = transB.getBasis() * Normal;
+               if (DeltaC2.dot(WorldNormal) < 0)
+                       WorldNormal *= -1.f;
+
+               curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+               gExpectedNbTests++;
+               if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
+                       continue;
+               gActualNbTests++;
+#endif
+
+               btScalar d;
+               btVector3 wA, wB;
+               if (!TestSepAxis(hullA, hullB, transA, transB, WorldNormal, d, wA, wB))
+                       return false;
+
+               if (d < dmin)
+               {
+                       dmin = d;
+                       sep = WorldNormal;
+               }
+       }
+
+       btVector3 edgeAstart, edgeAend, edgeBstart, edgeBend;
+       int edgeA = -1;
+       int edgeB = -1;
+       btVector3 worldEdgeA;
+       btVector3 worldEdgeB;
+       btVector3 witnessPointA(0, 0, 0), witnessPointB(0, 0, 0);
+
+       int curEdgeEdge = 0;
+       // Test edges
+       for (int e0 = 0; e0 < hullA.m_uniqueEdges.size(); e0++)
+       {
+               const btVector3 edge0 = hullA.m_uniqueEdges[e0];
+               const btVector3 WorldEdge0 = transA.getBasis() * edge0;
+               for (int e1 = 0; e1 < hullB.m_uniqueEdges.size(); e1++)
+               {
+                       const btVector3 edge1 = hullB.m_uniqueEdges[e1];
+                       const btVector3 WorldEdge1 = transB.getBasis() * edge1;
+
+                       btVector3 Cross = WorldEdge0.cross(WorldEdge1);
+                       curEdgeEdge++;
+                       if (!IsAlmostZero(Cross))
+                       {
+                               Cross = Cross.normalize();
+                               if (DeltaC2.dot(Cross) < 0)
+                                       Cross *= -1.f;
+
+#ifdef TEST_INTERNAL_OBJECTS
+                               gExpectedNbTests++;
+                               if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
+                                       continue;
+                               gActualNbTests++;
+#endif
+
+                               btScalar dist;
+                               btVector3 wA, wB;
+                               if (!TestSepAxis(hullA, hullB, transA, transB, Cross, dist, wA, wB))
+                                       return false;
+
+                               if (dist < dmin)
+                               {
+                                       dmin = dist;
+                                       sep = Cross;
+                                       edgeA = e0;
+                                       edgeB = e1;
+                                       worldEdgeA = WorldEdge0;
+                                       worldEdgeB = WorldEdge1;
+                                       witnessPointA = wA;
+                                       witnessPointB = wB;
+                               }
+                       }
+               }
+       }
+
+       if (edgeA >= 0 && edgeB >= 0)
+       {
+               //              printf("edge-edge\n");
+               //add an edge-edge contact
+
+               btVector3 ptsVector;
+               btVector3 offsetA;
+               btVector3 offsetB;
+               btScalar tA;
+               btScalar tB;
+
+               btVector3 translation = witnessPointB - witnessPointA;
+
+               btVector3 dirA = worldEdgeA;
+               btVector3 dirB = worldEdgeB;
+
+               btScalar hlenB = 1e30f;
+               btScalar hlenA = 1e30f;
+
+               btSegmentsClosestPoints(ptsVector, offsetA, offsetB, tA, tB,
+                                                               translation,
+                                                               dirA, hlenA,
+                                                               dirB, hlenB);
+
+               btScalar nlSqrt = ptsVector.length2();
+               if (nlSqrt > SIMD_EPSILON)
+               {
+                       btScalar nl = btSqrt(nlSqrt);
+                       ptsVector *= 1.f / nl;
+                       if (ptsVector.dot(DeltaC2) < 0.f)
+                       {
+                               ptsVector *= -1.f;
+                       }
+                       btVector3 ptOnB = witnessPointB + offsetB;
+                       btScalar distance = nl;
+                       resultOut.addContactPoint(ptsVector, ptOnB, -distance);
+               }
+       }
+
+       if ((DeltaC2.dot(sep)) < 0.0f)
+               sep = -sep;
+
+       return true;
+}
+
+void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut)
+{
+       worldVertsB2.resize(0);
+       btVertexArray* pVtxIn = &worldVertsB1;
+       btVertexArray* pVtxOut = &worldVertsB2;
+       pVtxOut->reserve(pVtxIn->size());
+
+       int closestFaceA = -1;
+       {
+               btScalar dmin = FLT_MAX;
+               for (int face = 0; face < hullA.m_faces.size(); face++)
+               {
+                       const btVector3 Normal(hullA.m_faces[face].m_plane[0], hullA.m_faces[face].m_plane[1], hullA.m_faces[face].m_plane[2]);
+                       const btVector3 faceANormalWS = transA.getBasis() * Normal;
+
+                       btScalar d = faceANormalWS.dot(separatingNormal);
+                       if (d < dmin)
+                       {
+                               dmin = d;
+                               closestFaceA = face;
+                       }
+               }
+       }
+       if (closestFaceA < 0)
+               return;
+
+       const btFace& polyA = hullA.m_faces[closestFaceA];
+
+       // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+       int numVerticesA = polyA.m_indices.size();
+       for (int e0 = 0; e0 < numVerticesA; e0++)
+       {
+               const btVector3& a = hullA.m_vertices[polyA.m_indices[e0]];
+               const btVector3& b = hullA.m_vertices[polyA.m_indices[(e0 + 1) % numVerticesA]];
+               const btVector3 edge0 = a - b;
+               const btVector3 WorldEdge0 = transA.getBasis() * edge0;
+               btVector3 worldPlaneAnormal1 = transA.getBasis() * btVector3(polyA.m_plane[0], polyA.m_plane[1], polyA.m_plane[2]);
+
+               btVector3 planeNormalWS1 = -WorldEdge0.cross(worldPlaneAnormal1);  //.cross(WorldEdge0);
+               btVector3 worldA1 = transA * a;
+               btScalar planeEqWS1 = -worldA1.dot(planeNormalWS1);
+
+//int otherFace=0;
+#ifdef BLA1
+               int otherFace = polyA.m_connectedFaces[e0];
+               btVector3 localPlaneNormal(hullA.m_faces[otherFace].m_plane[0], hullA.m_faces[otherFace].m_plane[1], hullA.m_faces[otherFace].m_plane[2]);
+               btScalar localPlaneEq = hullA.m_faces[otherFace].m_plane[3];
+
+               btVector3 planeNormalWS = transA.getBasis() * localPlaneNormal;
+               btScalar planeEqWS = localPlaneEq - planeNormalWS.dot(transA.getOrigin());
+#else
+               btVector3 planeNormalWS = planeNormalWS1;
+               btScalar planeEqWS = planeEqWS1;
+
+#endif
+               //clip face
+
+               clipFace(*pVtxIn, *pVtxOut, planeNormalWS, planeEqWS);
+               btSwap(pVtxIn, pVtxOut);
+               pVtxOut->resize(0);
+       }
+
+       //#define ONLY_REPORT_DEEPEST_POINT
+
+       btVector3 point;
+
+       // only keep points that are behind the witness face
+       {
+               btVector3 localPlaneNormal(polyA.m_plane[0], polyA.m_plane[1], polyA.m_plane[2]);
+               btScalar localPlaneEq = polyA.m_plane[3];
+               btVector3 planeNormalWS = transA.getBasis() * localPlaneNormal;
+               btScalar planeEqWS = localPlaneEq - planeNormalWS.dot(transA.getOrigin());
+               for (int i = 0; i < pVtxIn->size(); i++)
+               {
+                       btVector3 vtx = pVtxIn->at(i);
+                       btScalar depth = planeNormalWS.dot(vtx) + planeEqWS;
+                       if (depth <= minDist)
+                       {
+                               //                              printf("clamped: depth=%f to minDist=%f\n",depth,minDist);
+                               depth = minDist;
+                       }
+
+                       if (depth <= maxDist)
+                       {
+                               btVector3 point = pVtxIn->at(i);
+#ifdef ONLY_REPORT_DEEPEST_POINT
+                               curMaxDist = depth;
+#else
+#if 0
+                               if (depth<-3)
+                               {
+                                       printf("error in btPolyhedralContactClipping depth = %f\n", depth);
+                                       printf("likely wrong separatingNormal passed in\n");
+                               }
+#endif
+                               resultOut.addContactPoint(separatingNormal, point, depth);
+#endif
+                       }
+               }
+       }
+#ifdef ONLY_REPORT_DEEPEST_POINT
+       if (curMaxDist < maxDist)
+       {
+               resultOut.addContactPoint(separatingNormal, point, curMaxDist);
+       }
+#endif  //ONLY_REPORT_DEEPEST_POINT
+}
+
+void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btScalar minDist, btScalar maxDist, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, btDiscreteCollisionDetectorInterface::Result& resultOut)
+{
+       btVector3 separatingNormal = separatingNormal1.normalized();
+       //      const btVector3 c0 = transA * hullA.m_localCenter;
+       //      const btVector3 c1 = transB * hullB.m_localCenter;
+       //const btVector3 DeltaC2 = c0 - c1;
+
+       int closestFaceB = -1;
+       btScalar dmax = -FLT_MAX;
+       {
+               for (int face = 0; face < hullB.m_faces.size(); face++)
+               {
+                       const btVector3 Normal(hullB.m_faces[face].m_plane[0], hullB.m_faces[face].m_plane[1], hullB.m_faces[face].m_plane[2]);
+                       const btVector3 WorldNormal = transB.getBasis() * Normal;
+                       btScalar d = WorldNormal.dot(separatingNormal);
+                       if (d > dmax)
+                       {
+                               dmax = d;
+                               closestFaceB = face;
+                       }
+               }
+       }
+       worldVertsB1.resize(0);
+       {
+               const btFace& polyB = hullB.m_faces[closestFaceB];
+               const int numVertices = polyB.m_indices.size();
+               for (int e0 = 0; e0 < numVertices; e0++)
+               {
+                       const btVector3& b = hullB.m_vertices[polyB.m_indices[e0]];
+                       worldVertsB1.push_back(transB * b);
+               }
+       }
+
+       if (closestFaceB >= 0)
+               clipFaceAgainstHull(separatingNormal, hullA, transA, worldVertsB1, worldVertsB2, minDist, maxDist, resultOut);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
new file mode 100644 (file)
index 0000000..328f642
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#ifndef BT_POLYHEDRAL_CONTACT_CLIPPING_H
+#define BT_POLYHEDRAL_CONTACT_CLIPPING_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btTransform.h"
+#include "btDiscreteCollisionDetectorInterface.h"
+
+class btConvexPolyhedron;
+
+typedef btAlignedObjectArray<btVector3> btVertexArray;
+
+// Clips a face to the back of a plane
+struct btPolyhedralContactClipping
+{
+       static void clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btScalar minDist, btScalar maxDist, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, btDiscreteCollisionDetectorInterface::Result& resultOut);
+
+       static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut);
+
+       static bool findSeparatingAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut);
+
+       ///the clipFace method is used internally
+       static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS, btScalar planeEqWS);
+};
+
+#endif  // BT_POLYHEDRAL_CONTACT_CLIPPING_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
new file mode 100644 (file)
index 0000000..f2de4e9
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 <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, unsigned int flags)
+       : m_from(from),
+         m_to(to),
+         //@BP Mod
+         m_flags(flags),
+         m_hitFraction(btScalar(1.))
+{
+}
+
+void btTriangleRaycastCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
+{
+       const btVector3& vert0 = triangle[0];
+       const btVector3& vert1 = triangle[1];
+       const btVector3& vert2 = triangle[2];
+
+       btVector3 v10;
+       v10 = vert1 - vert0;
+       btVector3 v20;
+       v20 = vert2 - vert0;
+
+       btVector3 triangleNormal;
+       triangleNormal = v10.cross(v20);
+
+       const btScalar dist = vert0.dot(triangleNormal);
+       btScalar dist_a = triangleNormal.dot(m_from);
+       dist_a -= dist;
+       btScalar dist_b = triangleNormal.dot(m_to);
+       dist_b -= dist;
+
+       if (dist_a * dist_b >= btScalar(0.0))
+       {
+               return;  // same sign
+       }
+
+       if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a <= btScalar(0.0)))
+       {
+               // Backface, skip check
+               return;
+       }
+
+       const btScalar proj_length = dist_a - dist_b;
+       const btScalar distance = (dist_a) / (proj_length);
+       // Now we have the intersection point on the plane, we'll see if it's inside the triangle
+       // Add an epsilon as a tolerance for the raycast,
+       // in case the ray hits exacly on the edge of the triangle.
+       // It must be scaled for the triangle size.
+
+       if (distance < m_hitFraction)
+       {
+               btScalar edge_tolerance = triangleNormal.length2();
+               edge_tolerance *= btScalar(-0.0001);
+               btVector3 point;
+               point.setInterpolate3(m_from, m_to, distance);
+               {
+                       btVector3 v0p;
+                       v0p = vert0 - point;
+                       btVector3 v1p;
+                       v1p = vert1 - point;
+                       btVector3 cp0;
+                       cp0 = v0p.cross(v1p);
+
+                       if ((btScalar)(cp0.dot(triangleNormal)) >= edge_tolerance)
+                       {
+                               btVector3 v2p;
+                               v2p = vert2 - point;
+                               btVector3 cp1;
+                               cp1 = v1p.cross(v2p);
+                               if ((btScalar)(cp1.dot(triangleNormal)) >= edge_tolerance)
+                               {
+                                       btVector3 cp2;
+                                       cp2 = v2p.cross(v0p);
+
+                                       if ((btScalar)(cp2.dot(triangleNormal)) >= edge_tolerance)
+                                       {
+                                               //@BP Mod
+                                               // Triangle normal isn't normalized
+                                               triangleNormal.normalize();
+
+                                               //@BP Mod - Allow for unflipped normal when raycasting against backfaces
+                                               if (((m_flags & kF_KeepUnflippedNormal) == 0) && (dist_a <= btScalar(0.0)))
+                                               {
+                                                       m_hitFraction = reportHit(-triangleNormal, distance, partId, triangleIndex);
+                                               }
+                                               else
+                                               {
+                                                       m_hitFraction = reportHit(triangleNormal, distance, partId, triangleIndex);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+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.0f;
+       m_triangleCollisionMargin = triangleCollisionMargin;
+       m_allowedPenetration = 0.f;
+}
+
+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.);
+       castResult.m_allowedPenetration = m_allowedPenetration;
+       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/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
new file mode 100644 (file)
index 0000000..58a48c7
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_RAYCAST_TRI_CALLBACK_H
+#define BT_RAYCAST_TRI_CALLBACK_H
+
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "LinearMath/btTransform.h"
+struct btBroadphaseProxy;
+class btConvexShape;
+
+class btTriangleRaycastCallback : public btTriangleCallback
+{
+public:
+       //input
+       btVector3 m_from;
+       btVector3 m_to;
+
+       //@BP Mod - allow backface filtering and unflipped normals
+       enum EFlags
+       {
+               kF_None = 0,
+               kF_FilterBackfaces = 1 << 0,
+               kF_KeepUnflippedNormal = 1 << 1,             // Prevents returned face normal getting flipped when a ray hits a back-facing triangle
+                                                                                                        ///SubSimplexConvexCastRaytest is the default, even if kF_None is set.
+               kF_UseSubSimplexConvexCastRaytest = 1 << 2,  // Uses an approximate but faster ray versus convex intersection algorithm
+               kF_UseGjkConvexCastRaytest = 1 << 3,
+               kF_DisableHeightfieldAccelerator  = 1 << 4, //don't use the heightfield raycast accelerator. See https://github.com/bulletphysics/bullet3/pull/2062
+               kF_Terminator = 0xFFFFFFFF
+       };
+       unsigned int m_flags;
+
+       btScalar m_hitFraction;
+
+       btTriangleRaycastCallback(const btVector3& from, const btVector3& to, unsigned int flags = 0);
+
+       virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+
+       virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
+};
+
+class btTriangleConvexcastCallback : public btTriangleCallback
+{
+public:
+       const btConvexShape* m_convexShape;
+       btTransform m_convexShapeFrom;
+       btTransform m_convexShapeTo;
+       btTransform m_triangleToWorld;
+       btScalar m_hitFraction;
+       btScalar m_triangleCollisionMargin;
+       btScalar m_allowedPenetration;
+
+       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  //BT_RAYCAST_TRI_CALLBACK_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
new file mode 100644 (file)
index 0000000..b994aca
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SIMPLEX_SOLVER_INTERFACE_H
+#define BT_SIMPLEX_SOLVER_INTERFACE_H
+
+#include "LinearMath/btVector3.h"
+
+#define NO_VIRTUAL_INTERFACE 1
+#ifdef NO_VIRTUAL_INTERFACE
+#include "btVoronoiSimplexSolver.h"
+#define btSimplexSolverInterface btVoronoiSimplexSolver
+#else
+
+/// btSimplexSolverInterface can incrementally calculate distance between origin and up to 4 vertices
+/// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on
+/// voronoi regions or barycentric coordinates
+class btSimplexSolverInterface
+{
+public:
+       virtual ~btSimplexSolverInterface(){};
+
+       virtual void reset() = 0;
+
+       virtual void addVertex(const btVector3& w, const btVector3& p, const btVector3& q) = 0;
+
+       virtual bool closest(btVector3& v) = 0;
+
+       virtual btScalar maxVertex() = 0;
+
+       virtual bool fullSimplex() const = 0;
+
+       virtual int getSimplex(btVector3* pBuf, btVector3* qBuf, btVector3* yBuf) const = 0;
+
+       virtual bool inSimplex(const btVector3& w) = 0;
+
+       virtual void backup_closest(btVector3& v) = 0;
+
+       virtual bool emptySimplex() const = 0;
+
+       virtual void compute_points(btVector3& p1, btVector3& p2) = 0;
+
+       virtual int numVertices() const = 0;
+};
+#endif
+#endif  //BT_SIMPLEX_SOLVER_INTERFACE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
new file mode 100644 (file)
index 0000000..8b011a8
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSubSimplexConvexCast.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "btPointCollector.h"
+#include "LinearMath/btTransformUtil.h"
+
+btSubsimplexConvexCast::btSubsimplexConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver)
+       : m_simplexSolver(simplexSolver),
+         m_convexA(convexA),
+         m_convexB(convexB)
+{
+}
+
+
+bool btSubsimplexConvexCast::calcTimeOfImpact(
+       const btTransform& fromA,
+       const btTransform& toA,
+       const btTransform& fromB,
+       const btTransform& toB,
+       CastResult& result)
+{
+       m_simplexSolver->reset();
+
+       btVector3 linVelA, linVelB;
+       linVelA = toA.getOrigin() - fromA.getOrigin();
+       linVelB = toB.getOrigin() - fromB.getOrigin();
+
+       btScalar lambda = btScalar(0.);
+
+       btTransform interpolatedTransA = fromA;
+       btTransform interpolatedTransB = fromB;
+
+       ///take relative motion
+       btVector3 r = (linVelA - linVelB);
+       btVector3 v;
+
+       btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r * fromA.getBasis()));
+       btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r * fromB.getBasis()));
+       v = supVertexA - supVertexB;
+       int maxIter = result.m_subSimplexCastMaxIterations;
+
+       btVector3 n;
+       n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+
+       btVector3 c;
+
+       btScalar dist2 = v.length2();
+
+
+
+       btVector3 w, p;
+       btScalar VdotR;
+
+       while ((dist2 > result.m_subSimplexCastEpsilon) && maxIter--)
+       {
+               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);
+
+                       if (VdotR >= -(SIMD_EPSILON * SIMD_EPSILON))
+                               return false;
+                       else
+                       {
+                               lambda = lambda - VdotW / VdotR;
+                               //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 = supVertexA - supVertexB;
+
+                               n = v;
+                       }
+               }
+               ///Just like regular GJK only add the vertex if it isn't already (close) to current vertex, it would lead to divisions by zero and NaN etc.
+               if (!m_simplexSolver->inSimplex(w))
+                       m_simplexSolver->addVertex(w, supVertexA, supVertexB);
+
+               if (m_simplexSolver->closest(v))
+               {
+                       dist2 = v.length2();
+
+                       //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());
+               }
+               else
+               {
+                       dist2 = btScalar(0.);
+               }
+       }
+
+       //int numiter = MAX_ITERATIONS - maxIter;
+       //      printf("number of iterations: %d", numiter);
+
+       //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/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
new file mode 100644 (file)
index 0000000..e2b6bbc
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SUBSIMPLEX_CONVEX_CAST_H
+#define BT_SUBSIMPLEX_CONVEX_CAST_H
+
+#include "btConvexCast.h"
+#include "btSimplexSolverInterface.h"
+class btConvexShape;
+
+/// btSubsimplexConvexCast implements Gino van den Bergens' paper
+///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection"
+/// GJK based Ray Cast, optimized version
+/// Objects should not start in overlap, otherwise results are not defined.
+class btSubsimplexConvexCast : public btConvexCast
+{
+       btSimplexSolverInterface* m_simplexSolver;
+       const btConvexShape* m_convexA;
+       const btConvexShape* m_convexB;
+
+public:
+       btSubsimplexConvexCast(const btConvexShape* shapeA, const btConvexShape* shapeB, btSimplexSolverInterface* simplexSolver);
+
+       //virtual ~btSubsimplexConvexCast();
+       ///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects.
+       ///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector.
+       virtual bool calcTimeOfImpact(
+               const btTransform& fromA,
+               const btTransform& toA,
+               const btTransform& fromB,
+               const btTransform& toB,
+               CastResult& result);
+};
+
+#endif  //BT_SUBSIMPLEX_CONVEX_CAST_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
new file mode 100644 (file)
index 0000000..6b65a25
--- /dev/null
@@ -0,0 +1,577 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+       
+       Elsevier CDROM license agreements grants nonexclusive license to use the software
+       for any purpose, commercial or non-commercial as long as the following credit is included
+       identifying the original source of the software:
+
+       Parts of the source are "from the book Real-Time Collision Detection by
+       Christer Ericson, published by Morgan Kaufmann Publishers,
+       (c) 2005 Elsevier Inc."
+               
+*/
+
+#include "btVoronoiSimplexSolver.h"
+
+#define VERTA 0
+#define VERTB 1
+#define VERTC 2
+#define VERTD 3
+
+#define CATCH_DEGENERATE_TETRAHEDRON 1
+void btVoronoiSimplexSolver::removeVertex(int index)
+{
+       btAssert(m_numVertices > 0);
+       m_numVertices--;
+       m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
+       m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
+       m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
+}
+
+void btVoronoiSimplexSolver::reduceVertices(const btUsageBitfield& usedVerts)
+{
+       if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
+               removeVertex(3);
+
+       if ((numVertices() >= 3) && (!usedVerts.usedVertexC))
+               removeVertex(2);
+
+       if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
+               removeVertex(1);
+
+       if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
+               removeVertex(0);
+}
+
+//clear the simplex, remove all the vertices
+void btVoronoiSimplexSolver::reset()
+{
+       m_cachedValidClosest = false;
+       m_numVertices = 0;
+       m_needsUpdate = true;
+       m_lastW = btVector3(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+       m_cachedBC.reset();
+}
+
+//add a vertex
+void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q)
+{
+       m_lastW = w;
+       m_needsUpdate = true;
+
+       m_simplexVectorW[m_numVertices] = w;
+       m_simplexPointsP[m_numVertices] = p;
+       m_simplexPointsQ[m_numVertices] = q;
+
+       m_numVertices++;
+}
+
+bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
+{
+       if (m_needsUpdate)
+       {
+               m_cachedBC.reset();
+
+               m_needsUpdate = false;
+
+               switch (numVertices())
+               {
+                       case 0:
+                               m_cachedValidClosest = false;
+                               break;
+                       case 1:
+                       {
+                               m_cachedP1 = m_simplexPointsP[0];
+                               m_cachedP2 = m_simplexPointsQ[0];
+                               m_cachedV = m_cachedP1 - m_cachedP2;  //== m_simplexVectorW[0]
+                               m_cachedBC.reset();
+                               m_cachedBC.setBarycentricCoordinates(btScalar(1.), btScalar(0.), btScalar(0.), btScalar(0.));
+                               m_cachedValidClosest = m_cachedBC.isValid();
+                               break;
+                       };
+                       case 2:
+                       {
+                               //closest point origin from line segment
+                               const btVector3& from = m_simplexVectorW[0];
+                               const btVector3& to = m_simplexVectorW[1];
+                               btVector3 nearest;
+
+                               btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
+                               btVector3 diff = p - from;
+                               btVector3 v = to - from;
+                               btScalar t = v.dot(diff);
+
+                               if (t > 0)
+                               {
+                                       btScalar dotVV = v.dot(v);
+                                       if (t < dotVV)
+                                       {
+                                               t /= dotVV;
+                                               diff -= t * v;
+                                               m_cachedBC.m_usedVertices.usedVertexA = true;
+                                               m_cachedBC.m_usedVertices.usedVertexB = true;
+                                       }
+                                       else
+                                       {
+                                               t = 1;
+                                               diff -= v;
+                                               //reduce to 1 point
+                                               m_cachedBC.m_usedVertices.usedVertexB = true;
+                                       }
+                               }
+                               else
+                               {
+                                       t = 0;
+                                       //reduce to 1 point
+                                       m_cachedBC.m_usedVertices.usedVertexA = true;
+                               }
+                               m_cachedBC.setBarycentricCoordinates(1 - t, t);
+                               nearest = from + t * v;
+
+                               m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
+                               m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
+                               m_cachedV = m_cachedP1 - m_cachedP2;
+
+                               reduceVertices(m_cachedBC.m_usedVertices);
+
+                               m_cachedValidClosest = m_cachedBC.isValid();
+                               break;
+                       }
+                       case 3:
+                       {
+                               //closest point origin from triangle
+                               btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
+
+                               const btVector3& a = m_simplexVectorW[0];
+                               const btVector3& b = m_simplexVectorW[1];
+                               const btVector3& c = m_simplexVectorW[2];
+
+                               closestPtPointTriangle(p, a, b, c, m_cachedBC);
+                               m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+                                                        m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+                                                        m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
+
+                               m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+                                                        m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+                                                        m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
+
+                               m_cachedV = m_cachedP1 - m_cachedP2;
+
+                               reduceVertices(m_cachedBC.m_usedVertices);
+                               m_cachedValidClosest = m_cachedBC.isValid();
+
+                               break;
+                       }
+                       case 4:
+                       {
+                               btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
+
+                               const btVector3& a = m_simplexVectorW[0];
+                               const btVector3& b = m_simplexVectorW[1];
+                               const btVector3& c = m_simplexVectorW[2];
+                               const btVector3& d = m_simplexVectorW[3];
+
+                               bool hasSeparation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
+
+                               if (hasSeparation)
+                               {
+                                       m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+                                                                m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+                                                                m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
+                                                                m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
+
+                                       m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+                                                                m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+                                                                m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
+                                                                m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
+
+                                       m_cachedV = m_cachedP1 - m_cachedP2;
+                                       reduceVertices(m_cachedBC.m_usedVertices);
+                               }
+                               else
+                               {
+                                       //                                      printf("sub distance got penetration\n");
+
+                                       if (m_cachedBC.m_degenerate)
+                                       {
+                                               m_cachedValidClosest = false;
+                                       }
+                                       else
+                                       {
+                                               m_cachedValidClosest = true;
+                                               //degenerate case == false, penetration = true + zero
+                                               m_cachedV.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+                                       }
+                                       break;
+                               }
+
+                               m_cachedValidClosest = m_cachedBC.isValid();
+
+                               //closest point origin from tetrahedron
+                               break;
+                       }
+                       default:
+                       {
+                               m_cachedValidClosest = false;
+                       }
+               };
+       }
+
+       return m_cachedValidClosest;
+}
+
+//return/calculate the closest vertex
+bool btVoronoiSimplexSolver::closest(btVector3& v)
+{
+       bool succes = updateClosestVectorAndPoints();
+       v = m_cachedV;
+       return succes;
+}
+
+btScalar btVoronoiSimplexSolver::maxVertex()
+{
+       int i, numverts = numVertices();
+       btScalar maxV = btScalar(0.);
+       for (i = 0; i < numverts; i++)
+       {
+               btScalar curLen2 = m_simplexVectorW[i].length2();
+               if (maxV < curLen2)
+                       maxV = curLen2;
+       }
+       return maxV;
+}
+
+//return the current simplex
+int btVoronoiSimplexSolver::getSimplex(btVector3* pBuf, btVector3* qBuf, btVector3* yBuf) const
+{
+       int i;
+       for (i = 0; i < numVertices(); i++)
+       {
+               yBuf[i] = m_simplexVectorW[i];
+               pBuf[i] = m_simplexPointsP[i];
+               qBuf[i] = m_simplexPointsQ[i];
+       }
+       return numVertices();
+}
+
+bool btVoronoiSimplexSolver::inSimplex(const btVector3& w)
+{
+       bool found = false;
+       int i, numverts = numVertices();
+       //btScalar maxV = btScalar(0.);
+
+       //w is in the current (reduced) simplex
+       for (i = 0; i < numverts; i++)
+       {
+#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
+               if (m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
+#else
+               if (m_simplexVectorW[i] == w)
+#endif
+               {
+                       found = true;
+                       break;
+               }
+       }
+
+       //check in case lastW is already removed
+       if (w == m_lastW)
+               return true;
+
+       return found;
+}
+
+void btVoronoiSimplexSolver::backup_closest(btVector3& v)
+{
+       v = m_cachedV;
+}
+
+bool btVoronoiSimplexSolver::emptySimplex() const
+{
+       return (numVertices() == 0);
+}
+
+void btVoronoiSimplexSolver::compute_points(btVector3& p1, btVector3& p2)
+{
+       updateClosestVectorAndPoints();
+       p1 = m_cachedP1;
+       p2 = m_cachedP2;
+}
+
+bool btVoronoiSimplexSolver::closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, btSubSimplexClosestResult& result)
+{
+       result.m_usedVertices.reset();
+
+       // Check if P in vertex region outside A
+       btVector3 ab = b - a;
+       btVector3 ac = c - a;
+       btVector3 ap = p - a;
+       btScalar d1 = ab.dot(ap);
+       btScalar d2 = ac.dot(ap);
+       if (d1 <= btScalar(0.0) && d2 <= btScalar(0.0))
+       {
+               result.m_closestPointOnSimplex = a;
+               result.m_usedVertices.usedVertexA = true;
+               result.setBarycentricCoordinates(1, 0, 0);
+               return true;  // a; // barycentric coordinates (1,0,0)
+       }
+
+       // Check if P in vertex region outside B
+       btVector3 bp = p - b;
+       btScalar d3 = ab.dot(bp);
+       btScalar d4 = ac.dot(bp);
+       if (d3 >= btScalar(0.0) && d4 <= d3)
+       {
+               result.m_closestPointOnSimplex = b;
+               result.m_usedVertices.usedVertexB = true;
+               result.setBarycentricCoordinates(0, 1, 0);
+
+               return true;  // b; // barycentric coordinates (0,1,0)
+       }
+       // Check if P in edge region of AB, if so return projection of P onto AB
+       btScalar vc = d1 * d4 - d3 * d2;
+       if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0))
+       {
+               btScalar v = d1 / (d1 - d3);
+               result.m_closestPointOnSimplex = a + v * ab;
+               result.m_usedVertices.usedVertexA = true;
+               result.m_usedVertices.usedVertexB = true;
+               result.setBarycentricCoordinates(1 - v, v, 0);
+               return true;
+               //return a + v * ab; // barycentric coordinates (1-v,v,0)
+       }
+
+       // Check if P in vertex region outside C
+       btVector3 cp = p - c;
+       btScalar d5 = ab.dot(cp);
+       btScalar d6 = ac.dot(cp);
+       if (d6 >= btScalar(0.0) && d5 <= d6)
+       {
+               result.m_closestPointOnSimplex = c;
+               result.m_usedVertices.usedVertexC = true;
+               result.setBarycentricCoordinates(0, 0, 1);
+               return true;  //c; // barycentric coordinates (0,0,1)
+       }
+
+       // Check if P in edge region of AC, if so return projection of P onto AC
+       btScalar vb = d5 * d2 - d1 * d6;
+       if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0))
+       {
+               btScalar w = d2 / (d2 - d6);
+               result.m_closestPointOnSimplex = a + w * ac;
+               result.m_usedVertices.usedVertexA = true;
+               result.m_usedVertices.usedVertexC = true;
+               result.setBarycentricCoordinates(1 - w, 0, w);
+               return true;
+               //return a + w * ac; // barycentric coordinates (1-w,0,w)
+       }
+
+       // Check if P in edge region of BC, if so return projection of P onto BC
+       btScalar va = d3 * d6 - d5 * d4;
+       if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0))
+       {
+               btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
+
+               result.m_closestPointOnSimplex = b + w * (c - b);
+               result.m_usedVertices.usedVertexB = true;
+               result.m_usedVertices.usedVertexC = true;
+               result.setBarycentricCoordinates(0, 1 - w, w);
+               return true;
+               // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
+       }
+
+       // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
+       btScalar denom = btScalar(1.0) / (va + vb + vc);
+       btScalar v = vb * denom;
+       btScalar w = vc * denom;
+
+       result.m_closestPointOnSimplex = a + ab * v + ac * w;
+       result.m_usedVertices.usedVertexA = true;
+       result.m_usedVertices.usedVertexB = true;
+       result.m_usedVertices.usedVertexC = true;
+       result.setBarycentricCoordinates(1 - v - w, v, w);
+
+       return true;
+       //      return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w
+}
+
+/// Test if point p and d lie on opposite sides of plane through abc
+int btVoronoiSimplexSolver::pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d)
+{
+       btVector3 normal = (b - a).cross(c - a);
+
+       btScalar signp = (p - a).dot(normal);  // [AP AB AC]
+       btScalar signd = (d - a).dot(normal);  // [AD AB AC]
+
+#ifdef CATCH_DEGENERATE_TETRAHEDRON
+#ifdef BT_USE_DOUBLE_PRECISION
+       if (signd * signd < (btScalar(1e-8) * btScalar(1e-8)))
+       {
+               return -1;
+       }
+#else
+       if (signd * signd < (btScalar(1e-4) * btScalar(1e-4)))
+       {
+               //              printf("affine dependent/degenerate\n");//
+               return -1;
+       }
+#endif
+
+#endif
+       // Points on opposite sides if expression signs are opposite
+       return signp * signd < btScalar(0.);
+}
+
+bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult)
+{
+       btSubSimplexClosestResult tempResult;
+
+       // Start out assuming point inside all halfspaces, so closest to itself
+       finalResult.m_closestPointOnSimplex = p;
+       finalResult.m_usedVertices.reset();
+       finalResult.m_usedVertices.usedVertexA = true;
+       finalResult.m_usedVertices.usedVertexB = true;
+       finalResult.m_usedVertices.usedVertexC = true;
+       finalResult.m_usedVertices.usedVertexD = true;
+
+       int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
+       int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
+       int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
+       int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
+
+       if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
+       {
+               finalResult.m_degenerate = true;
+               return false;
+       }
+
+       if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
+       {
+               return false;
+       }
+
+       btScalar bestSqDist = FLT_MAX;
+       // If point outside face abc then compute closest point on abc
+       if (pointOutsideABC)
+       {
+               closestPtPointTriangle(p, a, b, c, tempResult);
+               btVector3 q = tempResult.m_closestPointOnSimplex;
+
+               btScalar sqDist = (q - p).dot(q - p);
+               // Update best closest point if (squared) distance is less than current best
+               if (sqDist < bestSqDist)
+               {
+                       bestSqDist = sqDist;
+                       finalResult.m_closestPointOnSimplex = q;
+                       //convert result bitmask!
+                       finalResult.m_usedVertices.reset();
+                       finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+                       finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
+                       finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+                       finalResult.setBarycentricCoordinates(
+                               tempResult.m_barycentricCoords[VERTA],
+                               tempResult.m_barycentricCoords[VERTB],
+                               tempResult.m_barycentricCoords[VERTC],
+                               0);
+               }
+       }
+
+       // Repeat test for face acd
+       if (pointOutsideACD)
+       {
+               closestPtPointTriangle(p, a, c, d, tempResult);
+               btVector3 q = tempResult.m_closestPointOnSimplex;
+               //convert result bitmask!
+
+               btScalar sqDist = (q - p).dot(q - p);
+               if (sqDist < bestSqDist)
+               {
+                       bestSqDist = sqDist;
+                       finalResult.m_closestPointOnSimplex = q;
+                       finalResult.m_usedVertices.reset();
+                       finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+
+                       finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
+                       finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
+                       finalResult.setBarycentricCoordinates(
+                               tempResult.m_barycentricCoords[VERTA],
+                               0,
+                               tempResult.m_barycentricCoords[VERTB],
+                               tempResult.m_barycentricCoords[VERTC]);
+               }
+       }
+       // Repeat test for face adb
+
+       if (pointOutsideADB)
+       {
+               closestPtPointTriangle(p, a, d, b, tempResult);
+               btVector3 q = tempResult.m_closestPointOnSimplex;
+               //convert result bitmask!
+
+               btScalar sqDist = (q - p).dot(q - p);
+               if (sqDist < bestSqDist)
+               {
+                       bestSqDist = sqDist;
+                       finalResult.m_closestPointOnSimplex = q;
+                       finalResult.m_usedVertices.reset();
+                       finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+                       finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
+
+                       finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+                       finalResult.setBarycentricCoordinates(
+                               tempResult.m_barycentricCoords[VERTA],
+                               tempResult.m_barycentricCoords[VERTC],
+                               0,
+                               tempResult.m_barycentricCoords[VERTB]);
+               }
+       }
+       // Repeat test for face bdc
+
+       if (pointOutsideBDC)
+       {
+               closestPtPointTriangle(p, b, d, c, tempResult);
+               btVector3 q = tempResult.m_closestPointOnSimplex;
+               //convert result bitmask!
+               btScalar sqDist = (q - p).dot(q - p);
+               if (sqDist < bestSqDist)
+               {
+                       bestSqDist = sqDist;
+                       finalResult.m_closestPointOnSimplex = q;
+                       finalResult.m_usedVertices.reset();
+                       //
+                       finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
+                       finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+                       finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+
+                       finalResult.setBarycentricCoordinates(
+                               0,
+                               tempResult.m_barycentricCoords[VERTA],
+                               tempResult.m_barycentricCoords[VERTC],
+                               tempResult.m_barycentricCoords[VERTB]);
+               }
+       }
+
+       //help! we ended up full !
+
+       if (finalResult.m_usedVertices.usedVertexA &&
+               finalResult.m_usedVertices.usedVertexB &&
+               finalResult.m_usedVertices.usedVertexC &&
+               finalResult.m_usedVertices.usedVertexD)
+       {
+               return true;
+       }
+
+       return true;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/dali-physics/third-party/bullet3/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
new file mode 100644 (file)
index 0000000..5ed896f
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_VORONOI_SIMPLEX_SOLVER_H
+#define BT_VORONOI_SIMPLEX_SOLVER_H
+
+#include "btSimplexSolverInterface.h"
+
+#define VORONOI_SIMPLEX_MAX_VERTS 5
+
+///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
+#define BT_USE_EQUAL_VERTEX_THRESHOLD
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 1e-12f
+#else
+#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
+#endif  //BT_USE_DOUBLE_PRECISION
+
+struct btUsageBitfield
+{
+       btUsageBitfield()
+       {
+               reset();
+       }
+
+       void reset()
+       {
+               usedVertexA = false;
+               usedVertexB = false;
+               usedVertexC = false;
+               usedVertexD = false;
+       }
+       unsigned short usedVertexA : 1;
+       unsigned short usedVertexB : 1;
+       unsigned short usedVertexC : 1;
+       unsigned short usedVertexD : 1;
+       unsigned short unused1 : 1;
+       unsigned short unused2 : 1;
+       unsigned short unused3 : 1;
+       unsigned short unused4 : 1;
+};
+
+struct btSubSimplexClosestResult
+{
+       btVector3 m_closestPointOnSimplex;
+       //MASK for m_usedVertices
+       //stores the simplex vertex-usage, using the MASK,
+       // if m_usedVertices & MASK then the related vertex is used
+       btUsageBitfield m_usedVertices;
+       btScalar m_barycentricCoords[4];
+       bool m_degenerate;
+
+       void reset()
+       {
+               m_degenerate = false;
+               setBarycentricCoordinates();
+               m_usedVertices.reset();
+       }
+       bool isValid()
+       {
+               bool valid = (m_barycentricCoords[0] >= btScalar(0.)) &&
+                                        (m_barycentricCoords[1] >= btScalar(0.)) &&
+                                        (m_barycentricCoords[2] >= btScalar(0.)) &&
+                                        (m_barycentricCoords[3] >= btScalar(0.));
+
+               return valid;
+       }
+       void setBarycentricCoordinates(btScalar a = btScalar(0.), btScalar b = btScalar(0.), btScalar c = btScalar(0.), btScalar d = btScalar(0.))
+       {
+               m_barycentricCoords[0] = a;
+               m_barycentricCoords[1] = b;
+               m_barycentricCoords[2] = c;
+               m_barycentricCoords[3] = d;
+       }
+};
+
+/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
+/// Can be used with GJK, as an alternative to Johnson distance algorithm.
+#ifdef NO_VIRTUAL_INTERFACE
+ATTRIBUTE_ALIGNED16(class)
+btVoronoiSimplexSolver
+#else
+ATTRIBUTE_ALIGNED16(class)
+btVoronoiSimplexSolver : public btSimplexSolverInterface
+#endif
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       int m_numVertices;
+
+       btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
+       btVector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
+       btVector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
+
+       btVector3 m_cachedP1;
+       btVector3 m_cachedP2;
+       btVector3 m_cachedV;
+       btVector3 m_lastW;
+
+       btScalar m_equalVertexThreshold;
+       bool m_cachedValidClosest;
+
+       btSubSimplexClosestResult m_cachedBC;
+
+       bool m_needsUpdate;
+
+       void removeVertex(int index);
+       void reduceVertices(const btUsageBitfield& usedVerts);
+       bool updateClosestVectorAndPoints();
+
+       bool closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult);
+       int pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d);
+       bool closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, btSubSimplexClosestResult& result);
+
+public:
+       btVoronoiSimplexSolver()
+               : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
+       {
+       }
+       void reset();
+
+       void addVertex(const btVector3& w, const btVector3& p, const btVector3& q);
+
+       void setEqualVertexThreshold(btScalar threshold)
+       {
+               m_equalVertexThreshold = threshold;
+       }
+
+       btScalar getEqualVertexThreshold() const
+       {
+               return m_equalVertexThreshold;
+       }
+
+       bool closest(btVector3 & v);
+
+       btScalar maxVertex();
+
+       bool fullSimplex() const
+       {
+               return (m_numVertices == 4);
+       }
+
+       int getSimplex(btVector3 * pBuf, btVector3 * qBuf, btVector3 * yBuf) const;
+
+       bool inSimplex(const btVector3& w);
+
+       void backup_closest(btVector3 & v);
+
+       bool emptySimplex() const;
+
+       void compute_points(btVector3 & p1, btVector3 & p2);
+
+       int numVertices() const
+       {
+               return m_numVertices;
+       }
+};
+
+#endif  //BT_VORONOI_SIMPLEX_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletCollision/premake4.lua b/dali-physics/third-party/bullet3/src/BulletCollision/premake4.lua
new file mode 100644 (file)
index 0000000..e1c9bdb
--- /dev/null
@@ -0,0 +1,23 @@
+       project "BulletCollision"
+
+       kind "StaticLib"
+    if os.is("Linux") then
+        buildoptions{"-fPIC"}
+    end
+       includedirs {
+               "..",
+       }
+       files {
+               "*.cpp",
+               "*.h",
+               "BroadphaseCollision/*.cpp",
+               "BroadphaseCollision/*.h",
+               "CollisionDispatch/*.cpp",
+                "CollisionDispatch/*.h",
+               "CollisionShapes/*.cpp",
+               "CollisionShapes/*.h",
+               "Gimpact/*.cpp",
+               "Gimpact/*.h",
+               "NarrowPhaseCollision/*.cpp",
+               "NarrowPhaseCollision/*.h",
+       }
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/CMakeLists.txt b/dali-physics/third-party/bullet3/src/BulletDynamics/CMakeLists.txt
new file mode 100644 (file)
index 0000000..cfd49e9
--- /dev/null
@@ -0,0 +1,179 @@
+INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src  )
+
+
+
+SET(BulletDynamics_SRCS
+       Character/btKinematicCharacterController.cpp
+       ConstraintSolver/btConeTwistConstraint.cpp
+       ConstraintSolver/btContactConstraint.cpp
+       ConstraintSolver/btFixedConstraint.cpp
+       ConstraintSolver/btGearConstraint.cpp
+       ConstraintSolver/btGeneric6DofConstraint.cpp
+       ConstraintSolver/btGeneric6DofSpringConstraint.cpp
+       ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
+       ConstraintSolver/btHinge2Constraint.cpp
+       ConstraintSolver/btHingeConstraint.cpp
+       ConstraintSolver/btPoint2PointConstraint.cpp
+       ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
+       ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp
+       ConstraintSolver/btBatchedConstraints.cpp
+       ConstraintSolver/btNNCGConstraintSolver.cpp
+       ConstraintSolver/btSliderConstraint.cpp
+       ConstraintSolver/btSolve2LinearConstraint.cpp
+       ConstraintSolver/btTypedConstraint.cpp
+       ConstraintSolver/btUniversalConstraint.cpp
+       Dynamics/btDiscreteDynamicsWorld.cpp
+       Dynamics/btDiscreteDynamicsWorldMt.cpp
+       Dynamics/btSimulationIslandManagerMt.cpp
+       Dynamics/btRigidBody.cpp
+       Dynamics/btSimpleDynamicsWorld.cpp
+#      Dynamics/Bullet-C-API.cpp
+       Vehicle/btRaycastVehicle.cpp
+       Vehicle/btWheelInfo.cpp
+       Featherstone/btMultiBody.cpp
+       Featherstone/btMultiBodyConstraint.cpp
+       Featherstone/btMultiBodyConstraintSolver.cpp
+       Featherstone/btMultiBodyDynamicsWorld.cpp
+       Featherstone/btMultiBodyFixedConstraint.cpp
+       Featherstone/btMultiBodyGearConstraint.cpp
+       Featherstone/btMultiBodyJointLimitConstraint.cpp
+       Featherstone/btMultiBodyJointMotor.cpp
+       Featherstone/btMultiBodyMLCPConstraintSolver.cpp
+       Featherstone/btMultiBodyPoint2Point.cpp
+       Featherstone/btMultiBodySliderConstraint.cpp
+       Featherstone/btMultiBodySphericalJointMotor.cpp
+       Featherstone/btMultiBodySphericalJointLimit.cpp
+       MLCPSolvers/btDantzigLCP.cpp
+       MLCPSolvers/btMLCPSolver.cpp
+       MLCPSolvers/btLemkeAlgorithm.cpp
+)
+
+SET(Root_HDRS
+       ../btBulletDynamicsCommon.h
+       ../btBulletCollisionCommon.h
+)
+SET(ConstraintSolver_HDRS
+       ConstraintSolver/btConeTwistConstraint.h
+       ConstraintSolver/btConstraintSolver.h
+       ConstraintSolver/btContactConstraint.h
+       ConstraintSolver/btContactSolverInfo.h
+       ConstraintSolver/btFixedConstraint.h
+       ConstraintSolver/btGearConstraint.h
+       ConstraintSolver/btGeneric6DofConstraint.h
+       ConstraintSolver/btGeneric6DofSpringConstraint.h
+       ConstraintSolver/btGeneric6DofSpring2Constraint.h
+       ConstraintSolver/btHinge2Constraint.h
+       ConstraintSolver/btHingeConstraint.h
+       ConstraintSolver/btJacobianEntry.h
+       ConstraintSolver/btPoint2PointConstraint.h
+       ConstraintSolver/btSequentialImpulseConstraintSolver.h
+       ConstraintSolver/btSequentialImpulseConstraintSolverMt.h
+       ConstraintSolver/btNNCGConstraintSolver.h
+       ConstraintSolver/btSliderConstraint.h
+       ConstraintSolver/btSolve2LinearConstraint.h
+       ConstraintSolver/btSolverBody.h
+       ConstraintSolver/btSolverConstraint.h
+       ConstraintSolver/btTypedConstraint.h
+       ConstraintSolver/btUniversalConstraint.h
+)
+SET(Dynamics_HDRS
+       Dynamics/btActionInterface.h
+       Dynamics/btDiscreteDynamicsWorld.h
+       Dynamics/btDiscreteDynamicsWorldMt.h
+       Dynamics/btSimulationIslandManagerMt.h
+       Dynamics/btDynamicsWorld.h
+       Dynamics/btSimpleDynamicsWorld.h
+       Dynamics/btRigidBody.h
+)
+SET(Vehicle_HDRS
+       Vehicle/btRaycastVehicle.h
+       Vehicle/btVehicleRaycaster.h
+       Vehicle/btWheelInfo.h
+)
+
+SET(Featherstone_HDRS
+       Featherstone/btMultiBody.h
+       Featherstone/btMultiBodyConstraint.h
+       Featherstone/btMultiBodyConstraintSolver.h
+       Featherstone/btMultiBodyDynamicsWorld.h
+       Featherstone/btMultiBodyFixedConstraint.h
+       Featherstone/btMultiBodyGearConstraint.h
+       Featherstone/btMultiBodyJointLimitConstraint.h
+       Featherstone/btMultiBodyJointMotor.h
+       Featherstone/btMultiBodyLink.h
+       Featherstone/btMultiBodyLinkCollider.h
+       Featherstone/btMultiBodyMLCPConstraintSolver.h
+       Featherstone/btMultiBodyPoint2Point.h
+       Featherstone/btMultiBodySliderConstraint.h
+       Featherstone/btMultiBodySolverConstraint.h
+  Featherstone/btMultiBodySphericalJointMotor.h
+       Featherstone/btMultiBodySphericalJointLimit.h
+
+)
+
+SET(MLCPSolvers_HDRS
+       MLCPSolvers/btDantzigLCP.h
+       MLCPSolvers/btDantzigSolver.h
+       MLCPSolvers/btMLCPSolver.h
+       MLCPSolvers/btMLCPSolverInterface.h
+       MLCPSolvers/btPATHSolver.h
+       MLCPSolvers/btSolveProjectedGaussSeidel.h
+       MLCPSolvers/btLemkeSolver.h
+       MLCPSolvers/btLemkeAlgorithm.h
+)
+
+SET(Character_HDRS
+       Character/btCharacterControllerInterface.h
+       Character/btKinematicCharacterController.h
+)
+
+
+
+SET(BulletDynamics_HDRS
+       ${Root_HDRS}
+       ${ConstraintSolver_HDRS}
+       ${Dynamics_HDRS}
+       ${Vehicle_HDRS}
+       ${Character_HDRS}
+       ${Featherstone_HDRS}
+       ${MLCPSolvers_HDRS}
+)
+
+
+ADD_LIBRARY(BulletDynamics ${BulletDynamics_SRCS} ${BulletDynamics_HDRS})
+SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES SOVERSION ${BULLET_VERSION})
+IF (BUILD_SHARED_LIBS)
+       TARGET_LINK_LIBRARIES(BulletDynamics BulletCollision LinearMath)
+ENDIF (BUILD_SHARED_LIBS)
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS BulletDynamics DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS BulletDynamics RUNTIME DESTINATION bin
+                                                               LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                                               ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h"  PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+                               INSTALL(FILES ../btBulletDynamicsCommon.h
+DESTINATION ${INCLUDE_INSTALL_DIR}/BulletDynamics)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES FRAMEWORK true)
+                       SET_TARGET_PROPERTIES(BulletDynamics PROPERTIES PUBLIC_HEADER "${Root_HDRS}")
+                       # Have to list out sub-directories manually:
+                       SET_PROPERTY(SOURCE ${ConstraintSolver_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/ConstraintSolver)
+                       SET_PROPERTY(SOURCE ${Dynamics_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Dynamics)
+                       SET_PROPERTY(SOURCE ${Vehicle_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Vehicle)
+                       SET_PROPERTY(SOURCE ${Character_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Character)
+                       SET_PROPERTY(SOURCE ${Featherstone_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/Featherstone)
+                       SET_PROPERTY(SOURCE ${MLCPSolvers_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/MLCPSolvers)
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Character/btCharacterControllerInterface.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Character/btCharacterControllerInterface.h
new file mode 100644 (file)
index 0000000..2ccf317
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+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.
+*/
+
+#ifndef BT_CHARACTER_CONTROLLER_INTERFACE_H
+#define BT_CHARACTER_CONTROLLER_INTERFACE_H
+
+#include "LinearMath/btVector3.h"
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+
+class btCollisionShape;
+class btRigidBody;
+class btCollisionWorld;
+
+class btCharacterControllerInterface : public btActionInterface
+{
+public:
+       btCharacterControllerInterface(){};
+       virtual ~btCharacterControllerInterface(){};
+
+       virtual void setWalkDirection(const btVector3& walkDirection) = 0;
+       virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0;
+       virtual void reset(btCollisionWorld* collisionWorld) = 0;
+       virtual void warp(const btVector3& origin) = 0;
+
+       virtual void preStep(btCollisionWorld* collisionWorld) = 0;
+       virtual void playerStep(btCollisionWorld* collisionWorld, btScalar dt) = 0;
+       virtual bool canJump() const = 0;
+       virtual void jump(const btVector3& dir = btVector3(0, 0, 0)) = 0;
+
+       virtual bool onGround() const = 0;
+       virtual void setUpInterpolate(bool value) = 0;
+};
+
+#endif  //BT_CHARACTER_CONTROLLER_INTERFACE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Character/btKinematicCharacterController.cpp
new file mode 100644 (file)
index 0000000..2bbccb2
--- /dev/null
@@ -0,0 +1,996 @@
+/*
+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 <stdio.h>
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btGhostObject.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "LinearMath/btDefaultMotionState.h"
+#include "btKinematicCharacterController.h"
+
+// static helper method
+static btVector3
+getNormalizedVector(const btVector3& v)
+{
+       btVector3 n(0, 0, 0);
+
+       if (v.length() > SIMD_EPSILON)
+       {
+               n = v.normalized();
+       }
+       return n;
+}
+
+///@todo Interact with dynamic objects,
+///Ride kinematicly animated platforms properly
+///More realistic (or maybe just a config option) falling
+/// -> Should integrate falling velocity manually and use that in stepDown()
+///Support jumping
+///Support ducking
+class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
+{
+public:
+       btKinematicClosestNotMeRayResultCallback(btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
+       {
+               m_me = me;
+       }
+
+       virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
+       {
+               if (rayResult.m_collisionObject == m_me)
+                       return 1.0;
+
+               return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
+       }
+
+protected:
+       btCollisionObject* m_me;
+};
+
+class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
+{
+public:
+       btKinematicClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
+               : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)), m_me(me), m_up(up), m_minSlopeDot(minSlopeDot)
+       {
+       }
+
+       virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
+       {
+               if (convexResult.m_hitCollisionObject == m_me)
+                       return btScalar(1.0);
+
+               if (!convexResult.m_hitCollisionObject->hasContactResponse())
+                       return btScalar(1.0);
+
+               btVector3 hitNormalWorld;
+               if (normalInWorldSpace)
+               {
+                       hitNormalWorld = convexResult.m_hitNormalLocal;
+               }
+               else
+               {
+                       ///need to transform normal into worldspace
+                       hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal;
+               }
+
+               btScalar dotUp = m_up.dot(hitNormalWorld);
+               if (dotUp < m_minSlopeDot)
+               {
+                       return btScalar(1.0);
+               }
+
+               return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
+       }
+
+protected:
+       btCollisionObject* m_me;
+       const btVector3 m_up;
+       btScalar m_minSlopeDot;
+};
+
+/*
+ * Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
+ *
+ * from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
+ */
+btVector3 btKinematicCharacterController::computeReflectionDirection(const btVector3& direction, const btVector3& normal)
+{
+       return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
+}
+
+/*
+ * Returns the portion of 'direction' that is parallel to 'normal'
+ */
+btVector3 btKinematicCharacterController::parallelComponent(const btVector3& direction, const btVector3& normal)
+{
+       btScalar magnitude = direction.dot(normal);
+       return normal * magnitude;
+}
+
+/*
+ * Returns the portion of 'direction' that is perpindicular to 'normal'
+ */
+btVector3 btKinematicCharacterController::perpindicularComponent(const btVector3& direction, const btVector3& normal)
+{
+       return direction - parallelComponent(direction, normal);
+}
+
+btKinematicCharacterController::btKinematicCharacterController(btPairCachingGhostObject* ghostObject, btConvexShape* convexShape, btScalar stepHeight, const btVector3& up)
+{
+       m_ghostObject = ghostObject;
+       m_up.setValue(0.0f, 0.0f, 1.0f);
+       m_jumpAxis.setValue(0.0f, 0.0f, 1.0f);
+       m_addedMargin = 0.02;
+       m_walkDirection.setValue(0.0, 0.0, 0.0);
+       m_AngVel.setValue(0.0, 0.0, 0.0);
+       m_useGhostObjectSweepTest = true;
+       m_turnAngle = btScalar(0.0);
+       m_convexShape = convexShape;
+       m_useWalkDirection = true;  // use walk direction by default, legacy behavior
+       m_velocityTimeInterval = 0.0;
+       m_verticalVelocity = 0.0;
+       m_verticalOffset = 0.0;
+       m_gravity = 9.8 * 3.0;  // 3G acceleration.
+       m_fallSpeed = 55.0;     // Terminal velocity of a sky diver in m/s.
+       m_jumpSpeed = 10.0;     // ?
+       m_SetjumpSpeed = m_jumpSpeed;
+       m_wasOnGround = false;
+       m_wasJumping = false;
+       m_interpolateUp = true;
+       m_currentStepOffset = 0.0;
+       m_maxPenetrationDepth = 0.2;
+       full_drop = false;
+       bounce_fix = false;
+       m_linearDamping = btScalar(0.0);
+       m_angularDamping = btScalar(0.0);
+
+       setUp(up);
+       setStepHeight(stepHeight);
+       setMaxSlope(btRadians(45.0));
+}
+
+btKinematicCharacterController::~btKinematicCharacterController()
+{
+}
+
+btPairCachingGhostObject* btKinematicCharacterController::getGhostObject()
+{
+       return m_ghostObject;
+}
+
+bool btKinematicCharacterController::recoverFromPenetration(btCollisionWorld* collisionWorld)
+{
+       // Here we must refresh the overlapping paircache as the penetrating movement itself or the
+       // previous recovery iteration might have used setWorldTransform and pushed us into an object
+       // that is not in the previous cache contents from the last timestep, as will happen if we
+       // are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck.
+       //
+       // Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase
+       // paircache and the ghostobject's internal paircache at the same time.    /BW
+
+       btVector3 minAabb, maxAabb;
+       m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb, maxAabb);
+       collisionWorld->getBroadphase()->setAabb(m_ghostObject->getBroadphaseHandle(),
+                                                                                        minAabb,
+                                                                                        maxAabb,
+                                                                                        collisionWorld->getDispatcher());
+
+       bool penetration = false;
+
+       collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
+
+       m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
+
+       //      btScalar maxPen = btScalar(0.0);
+       for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
+       {
+               m_manifoldArray.resize(0);
+
+               btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
+
+               btCollisionObject* obj0 = static_cast<btCollisionObject*>(collisionPair->m_pProxy0->m_clientObject);
+               btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
+
+               if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse()))
+                       continue;
+
+               if (!needsCollision(obj0, obj1))
+                       continue;
+
+               if (collisionPair->m_algorithm)
+                       collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
+
+               for (int j = 0; j < m_manifoldArray.size(); j++)
+               {
+                       btPersistentManifold* manifold = m_manifoldArray[j];
+                       btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
+                       for (int p = 0; p < manifold->getNumContacts(); p++)
+                       {
+                               const btManifoldPoint& pt = manifold->getContactPoint(p);
+
+                               btScalar dist = pt.getDistance();
+
+                               if (dist < -m_maxPenetrationDepth)
+                               {
+                                       // TODO: cause problems on slopes, not sure if it is needed
+                                       //if (dist < maxPen)
+                                       //{
+                                       //      maxPen = dist;
+                                       //      m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
+
+                                       //}
+                                       m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
+                                       penetration = true;
+                               }
+                               else
+                               {
+                                       //printf("touching %f\n", dist);
+                               }
+                       }
+
+                       //manifold->clearManifold();
+               }
+       }
+       btTransform newTrans = m_ghostObject->getWorldTransform();
+       newTrans.setOrigin(m_currentPosition);
+       m_ghostObject->setWorldTransform(newTrans);
+       //      printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
+       return penetration;
+}
+
+void btKinematicCharacterController::stepUp(btCollisionWorld* world)
+{
+       btScalar stepHeight = 0.0f;
+       if (m_verticalVelocity < 0.0)
+               stepHeight = m_stepHeight;
+
+       // phase 1: up
+       btTransform start, end;
+
+       start.setIdentity();
+       end.setIdentity();
+
+       /* FIXME: Handle penetration properly */
+       start.setOrigin(m_currentPosition);
+
+       m_targetPosition = m_currentPosition + m_up * (stepHeight) + m_jumpAxis * ((m_verticalOffset > 0.f ? m_verticalOffset : 0.f));
+       m_currentPosition = m_targetPosition;
+
+       end.setOrigin(m_targetPosition);
+
+       start.setRotation(m_currentOrientation);
+       end.setRotation(m_targetOrientation);
+
+       btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, -m_up, m_maxSlopeCosine);
+       callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+       callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+
+       if (m_useGhostObjectSweepTest)
+       {
+               m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
+       }
+       else
+       {
+               world->convexSweepTest(m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
+       }
+
+       if (callback.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))
+       {
+               // Only modify the position if the hit was a slope and not a wall or ceiling.
+               if (callback.m_hitNormalWorld.dot(m_up) > 0.0)
+               {
+                       // we moved up only a fraction of the step height
+                       m_currentStepOffset = stepHeight * callback.m_closestHitFraction;
+                       if (m_interpolateUp == true)
+                               m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+                       else
+                               m_currentPosition = m_targetPosition;
+               }
+
+               btTransform& xform = m_ghostObject->getWorldTransform();
+               xform.setOrigin(m_currentPosition);
+               m_ghostObject->setWorldTransform(xform);
+
+               // fix penetration if we hit a ceiling for example
+               int numPenetrationLoops = 0;
+               m_touchingContact = false;
+               while (recoverFromPenetration(world))
+               {
+                       numPenetrationLoops++;
+                       m_touchingContact = true;
+                       if (numPenetrationLoops > 4)
+                       {
+                               //printf("character could not recover from penetration = %d\n", numPenetrationLoops);
+                               break;
+                       }
+               }
+               m_targetPosition = m_ghostObject->getWorldTransform().getOrigin();
+               m_currentPosition = m_targetPosition;
+
+               if (m_verticalOffset > 0)
+               {
+                       m_verticalOffset = 0.0;
+                       m_verticalVelocity = 0.0;
+                       m_currentStepOffset = m_stepHeight;
+               }
+       }
+       else
+       {
+               m_currentStepOffset = stepHeight;
+               m_currentPosition = m_targetPosition;
+       }
+}
+
+bool btKinematicCharacterController::needsCollision(const btCollisionObject* body0, const btCollisionObject* body1)
+{
+       bool collides = (body0->getBroadphaseHandle()->m_collisionFilterGroup & body1->getBroadphaseHandle()->m_collisionFilterMask) != 0;
+       collides = collides && (body1->getBroadphaseHandle()->m_collisionFilterGroup & body0->getBroadphaseHandle()->m_collisionFilterMask);
+       return collides;
+}
+
+void btKinematicCharacterController::updateTargetPositionBasedOnCollision(const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
+{
+       btVector3 movementDirection = m_targetPosition - m_currentPosition;
+       btScalar movementLength = movementDirection.length();
+       if (movementLength > SIMD_EPSILON)
+       {
+               movementDirection.normalize();
+
+               btVector3 reflectDir = computeReflectionDirection(movementDirection, hitNormal);
+               reflectDir.normalize();
+
+               btVector3 parallelDir, perpindicularDir;
+
+               parallelDir = parallelComponent(reflectDir, hitNormal);
+               perpindicularDir = perpindicularComponent(reflectDir, hitNormal);
+
+               m_targetPosition = m_currentPosition;
+               if (0)  //tangentMag != 0.0)
+               {
+                       btVector3 parComponent = parallelDir * btScalar(tangentMag * movementLength);
+                       //                      printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
+                       m_targetPosition += parComponent;
+               }
+
+               if (normalMag != 0.0)
+               {
+                       btVector3 perpComponent = perpindicularDir * btScalar(normalMag * movementLength);
+                       //                      printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
+                       m_targetPosition += perpComponent;
+               }
+       }
+       else
+       {
+               //              printf("movementLength don't normalize a zero vector\n");
+       }
+}
+
+void btKinematicCharacterController::stepForwardAndStrafe(btCollisionWorld* collisionWorld, const btVector3& walkMove)
+{
+       // printf("m_normalizedDirection=%f,%f,%f\n",
+       //      m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
+       // phase 2: forward and strafe
+       btTransform start, end;
+
+       m_targetPosition = m_currentPosition + walkMove;
+
+       start.setIdentity();
+       end.setIdentity();
+
+       btScalar fraction = 1.0;
+       btScalar distance2 = (m_currentPosition - m_targetPosition).length2();
+       //      printf("distance2=%f\n",distance2);
+
+       int maxIter = 10;
+
+       while (fraction > btScalar(0.01) && maxIter-- > 0)
+       {
+               start.setOrigin(m_currentPosition);
+               end.setOrigin(m_targetPosition);
+               btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
+
+               start.setRotation(m_currentOrientation);
+               end.setRotation(m_targetOrientation);
+
+               btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, sweepDirNegative, btScalar(0.0));
+               callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+               callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+
+               btScalar margin = m_convexShape->getMargin();
+               m_convexShape->setMargin(margin + m_addedMargin);
+
+               if (!(start == end))
+               {
+                       if (m_useGhostObjectSweepTest)
+                       {
+                               m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+                       }
+                       else
+                       {
+                               collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+                       }
+               }
+               m_convexShape->setMargin(margin);
+
+               fraction -= callback.m_closestHitFraction;
+
+               if (callback.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))
+               {
+                       // we moved only a fraction
+                       //btScalar hitDistance;
+                       //hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
+
+                       //                      m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+
+                       updateTargetPositionBasedOnCollision(callback.m_hitNormalWorld);
+                       btVector3 currentDir = m_targetPosition - m_currentPosition;
+                       distance2 = currentDir.length2();
+                       if (distance2 > SIMD_EPSILON)
+                       {
+                               currentDir.normalize();
+                               /* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
+                               if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0))
+                               {
+                                       break;
+                               }
+                       }
+                       else
+                       {
+                               //                              printf("currentDir: don't normalize a zero vector\n");
+                               break;
+                       }
+               }
+               else
+               {
+                       m_currentPosition = m_targetPosition;
+               }
+       }
+}
+
+void btKinematicCharacterController::stepDown(btCollisionWorld* collisionWorld, btScalar dt)
+{
+       btTransform start, end, end_double;
+       bool runonce = false;
+
+       // phase 3: down
+       /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
+       btVector3 step_drop = m_up * (m_currentStepOffset + additionalDownStep);
+       btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt;
+       btVector3 gravity_drop = m_up * downVelocity; 
+       m_targetPosition -= (step_drop + gravity_drop);*/
+
+       btVector3 orig_position = m_targetPosition;
+
+       btScalar downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
+
+       if (m_verticalVelocity > 0.0)
+               return;
+
+       if (downVelocity > 0.0 && downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
+               downVelocity = m_fallSpeed;
+
+       btVector3 step_drop = m_up * (m_currentStepOffset + downVelocity);
+       m_targetPosition -= step_drop;
+
+       btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, m_up, m_maxSlopeCosine);
+       callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+       callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+
+       btKinematicClosestNotMeConvexResultCallback callback2(m_ghostObject, m_up, m_maxSlopeCosine);
+       callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+       callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+
+       while (1)
+       {
+               start.setIdentity();
+               end.setIdentity();
+
+               end_double.setIdentity();
+
+               start.setOrigin(m_currentPosition);
+               end.setOrigin(m_targetPosition);
+
+               start.setRotation(m_currentOrientation);
+               end.setRotation(m_targetOrientation);
+
+               //set double test for 2x the step drop, to check for a large drop vs small drop
+               end_double.setOrigin(m_targetPosition - step_drop);
+
+               if (m_useGhostObjectSweepTest)
+               {
+                       m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+
+                       if (!callback.hasHit() && m_ghostObject->hasContactResponse())
+                       {
+                               //test a double fall height, to see if the character should interpolate it's fall (full) or not (partial)
+                               m_ghostObject->convexSweepTest(m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+                       }
+               }
+               else
+               {
+                       collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+
+                       if (!callback.hasHit() && m_ghostObject->hasContactResponse())
+                       {
+                               //test a double fall height, to see if the character should interpolate it's fall (large) or not (small)
+                               collisionWorld->convexSweepTest(m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+                       }
+               }
+
+               btScalar downVelocity2 = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
+               bool has_hit;
+               if (bounce_fix == true)
+                       has_hit = (callback.hasHit() || callback2.hasHit()) && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject);
+               else
+                       has_hit = callback2.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback2.m_hitCollisionObject);
+
+               btScalar stepHeight = 0.0f;
+               if (m_verticalVelocity < 0.0)
+                       stepHeight = m_stepHeight;
+
+               if (downVelocity2 > 0.0 && downVelocity2 < stepHeight && has_hit == true && runonce == false && (m_wasOnGround || !m_wasJumping))
+               {
+                       //redo the velocity calculation when falling a small amount, for fast stairs motion
+                       //for larger falls, use the smoother/slower interpolated movement by not touching the target position
+
+                       m_targetPosition = orig_position;
+                       downVelocity = stepHeight;
+
+                       step_drop = m_up * (m_currentStepOffset + downVelocity);
+                       m_targetPosition -= step_drop;
+                       runonce = true;
+                       continue;  //re-run previous tests
+               }
+               break;
+       }
+
+       if ((m_ghostObject->hasContactResponse() && (callback.hasHit() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))) || runonce == true)
+       {
+               // we dropped a fraction of the height -> hit floor
+               btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2;
+
+               //printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY());
+
+               if (bounce_fix == true)
+               {
+                       if (full_drop == true)
+                               m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+                       else
+                               //due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually
+                               m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, fraction);
+               }
+               else
+                       m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+
+               full_drop = false;
+
+               m_verticalVelocity = 0.0;
+               m_verticalOffset = 0.0;
+               m_wasJumping = false;
+       }
+       else
+       {
+               // we dropped the full height
+
+               full_drop = true;
+
+               if (bounce_fix == true)
+               {
+                       downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
+                       if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
+                       {
+                               m_targetPosition += step_drop;  //undo previous target change
+                               downVelocity = m_fallSpeed;
+                               step_drop = m_up * (m_currentStepOffset + downVelocity);
+                               m_targetPosition -= step_drop;
+                       }
+               }
+               //printf("full drop - %g, %g\n", m_currentPosition.getY(), m_targetPosition.getY());
+
+               m_currentPosition = m_targetPosition;
+       }
+}
+
+void btKinematicCharacterController::setWalkDirection(
+       const btVector3& walkDirection)
+{
+       m_useWalkDirection = true;
+       m_walkDirection = walkDirection;
+       m_normalizedDirection = getNormalizedVector(m_walkDirection);
+}
+
+void btKinematicCharacterController::setVelocityForTimeInterval(
+       const btVector3& velocity,
+       btScalar timeInterval)
+{
+       //      printf("setVelocity!\n");
+       //      printf("  interval: %f\n", timeInterval);
+       //      printf("  velocity: (%f, %f, %f)\n",
+       //               velocity.x(), velocity.y(), velocity.z());
+
+       m_useWalkDirection = false;
+       m_walkDirection = velocity;
+       m_normalizedDirection = getNormalizedVector(m_walkDirection);
+       m_velocityTimeInterval += timeInterval;
+}
+
+void btKinematicCharacterController::setAngularVelocity(const btVector3& velocity)
+{
+       m_AngVel = velocity;
+}
+
+const btVector3& btKinematicCharacterController::getAngularVelocity() const
+{
+       return m_AngVel;
+}
+
+void btKinematicCharacterController::setLinearVelocity(const btVector3& velocity)
+{
+       m_walkDirection = velocity;
+
+       // HACK: if we are moving in the direction of the up, treat it as a jump :(
+       if (m_walkDirection.length2() > 0)
+       {
+               btVector3 w = velocity.normalized();
+               btScalar c = w.dot(m_up);
+               if (c != 0)
+               {
+                       //there is a component in walkdirection for vertical velocity
+                       btVector3 upComponent = m_up * (btSin(SIMD_HALF_PI - btAcos(c)) * m_walkDirection.length());
+                       m_walkDirection -= upComponent;
+                       m_verticalVelocity = (c < 0.0f ? -1 : 1) * upComponent.length();
+
+                       if (c > 0.0f)
+                       {
+                               m_wasJumping = true;
+                               m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
+                       }
+               }
+       }
+       else
+               m_verticalVelocity = 0.0f;
+}
+
+btVector3 btKinematicCharacterController::getLinearVelocity() const
+{
+       return m_walkDirection + (m_verticalVelocity * m_up);
+}
+
+void btKinematicCharacterController::reset(btCollisionWorld* collisionWorld)
+{
+       m_verticalVelocity = 0.0;
+       m_verticalOffset = 0.0;
+       m_wasOnGround = false;
+       m_wasJumping = false;
+       m_walkDirection.setValue(0, 0, 0);
+       m_velocityTimeInterval = 0.0;
+
+       //clear pair cache
+       btHashedOverlappingPairCache* cache = m_ghostObject->getOverlappingPairCache();
+       while (cache->getOverlappingPairArray().size() > 0)
+       {
+               cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher());
+       }
+}
+
+void btKinematicCharacterController::warp(const btVector3& origin)
+{
+       btTransform xform;
+       xform.setIdentity();
+       xform.setOrigin(origin);
+       m_ghostObject->setWorldTransform(xform);
+}
+
+void btKinematicCharacterController::preStep(btCollisionWorld* collisionWorld)
+{
+       m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
+       m_targetPosition = m_currentPosition;
+
+       m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
+       m_targetOrientation = m_currentOrientation;
+       //      printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
+}
+
+void btKinematicCharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar dt)
+{
+       //      printf("playerStep(): ");
+       //      printf("  dt = %f", dt);
+
+       if (m_AngVel.length2() > 0.0f)
+       {
+               m_AngVel *= btPow(btScalar(1) - m_angularDamping, dt);
+       }
+
+       // integrate for angular velocity
+       if (m_AngVel.length2() > 0.0f)
+       {
+               btTransform xform;
+               xform = m_ghostObject->getWorldTransform();
+
+               btQuaternion rot(m_AngVel.normalized(), m_AngVel.length() * dt);
+
+               btQuaternion orn = rot * xform.getRotation();
+
+               xform.setRotation(orn);
+               m_ghostObject->setWorldTransform(xform);
+
+               m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
+               m_targetPosition = m_currentPosition;
+               m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
+               m_targetOrientation = m_currentOrientation;
+       }
+
+       // quick check...
+       if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0 || m_walkDirection.fuzzyZero())) 
+       {
+               //              printf("\n");
+               return;  // no motion
+       }
+
+       m_wasOnGround = onGround();
+
+       //btVector3 lvel = m_walkDirection;
+       //btScalar c = 0.0f;
+
+       if (m_walkDirection.length2() > 0)
+       {
+               // apply damping
+               m_walkDirection *= btPow(btScalar(1) - m_linearDamping, dt);
+       }
+
+       m_verticalVelocity *= btPow(btScalar(1) - m_linearDamping, dt);
+
+       // Update fall velocity.
+       m_verticalVelocity -= m_gravity * dt;
+       if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
+       {
+               m_verticalVelocity = m_jumpSpeed;
+       }
+       if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
+       {
+               m_verticalVelocity = -btFabs(m_fallSpeed);
+       }
+       m_verticalOffset = m_verticalVelocity * dt;
+
+       btTransform xform;
+       xform = m_ghostObject->getWorldTransform();
+
+       //      printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
+       //      printf("walkSpeed=%f\n",walkSpeed);
+
+       stepUp(collisionWorld);
+       //todo: Experimenting with behavior of controller when it hits a ceiling..
+       //bool hitUp = stepUp (collisionWorld);
+       //if (hitUp)
+       //{
+       //      m_verticalVelocity -= m_gravity * dt;
+       //      if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
+       //      {
+       //              m_verticalVelocity = m_jumpSpeed;
+       //      }
+       //      if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
+       //      {
+       //              m_verticalVelocity = -btFabs(m_fallSpeed);
+       //      }
+       //      m_verticalOffset = m_verticalVelocity * dt;
+
+       //      xform = m_ghostObject->getWorldTransform();
+       //}
+
+       if (m_useWalkDirection)
+       {
+               stepForwardAndStrafe(collisionWorld, m_walkDirection);
+       }
+       else
+       {
+               //printf("  time: %f", m_velocityTimeInterval);
+               // still have some time left for moving!
+               btScalar dtMoving =
+                       (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
+               m_velocityTimeInterval -= dt;
+
+               // how far will we move while we are moving?
+               btVector3 move = m_walkDirection * dtMoving;
+
+               //printf("  dtMoving: %f", dtMoving);
+
+               // okay, step
+               stepForwardAndStrafe(collisionWorld, move);
+       }
+       stepDown(collisionWorld, dt);
+
+       //todo: Experimenting with max jump height
+       //if (m_wasJumping)
+       //{
+       //      btScalar ds = m_currentPosition[m_upAxis] - m_jumpPosition[m_upAxis];
+       //      if (ds > m_maxJumpHeight)
+       //      {
+       //              // substract the overshoot
+       //              m_currentPosition[m_upAxis] -= ds - m_maxJumpHeight;
+
+       //              // max height was reached, so potential energy is at max
+       //              // and kinematic energy is 0, thus velocity is 0.
+       //              if (m_verticalVelocity > 0.0)
+       //                      m_verticalVelocity = 0.0;
+       //      }
+       //}
+       // printf("\n");
+
+       xform.setOrigin(m_currentPosition);
+       m_ghostObject->setWorldTransform(xform);
+
+       int numPenetrationLoops = 0;
+       m_touchingContact = false;
+       while (recoverFromPenetration(collisionWorld))
+       {
+               numPenetrationLoops++;
+               m_touchingContact = true;
+               if (numPenetrationLoops > 4)
+               {
+                       //printf("character could not recover from penetration = %d\n", numPenetrationLoops);
+                       break;
+               }
+       }
+}
+
+void btKinematicCharacterController::setFallSpeed(btScalar fallSpeed)
+{
+       m_fallSpeed = fallSpeed;
+}
+
+void btKinematicCharacterController::setJumpSpeed(btScalar jumpSpeed)
+{
+       m_jumpSpeed = jumpSpeed;
+       m_SetjumpSpeed = m_jumpSpeed;
+}
+
+void btKinematicCharacterController::setMaxJumpHeight(btScalar maxJumpHeight)
+{
+       m_maxJumpHeight = maxJumpHeight;
+}
+
+bool btKinematicCharacterController::canJump() const
+{
+       return onGround();
+}
+
+void btKinematicCharacterController::jump(const btVector3& v)
+{
+       m_jumpSpeed = v.length2() == 0 ? m_SetjumpSpeed : v.length();
+       m_verticalVelocity = m_jumpSpeed;
+       m_wasJumping = true;
+
+       m_jumpAxis = v.length2() == 0 ? m_up : v.normalized();
+
+       m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
+
+#if 0
+       currently no jumping.
+       btTransform xform;
+       m_rigidBody->getMotionState()->getWorldTransform (xform);
+       btVector3 up = xform.getBasis()[1];
+       up.normalize ();
+       btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
+       m_rigidBody->applyCentralImpulse (up * magnitude);
+#endif
+}
+
+void btKinematicCharacterController::setGravity(const btVector3& gravity)
+{
+       if (gravity.length2() > 0) setUpVector(-gravity);
+
+       m_gravity = gravity.length();
+}
+
+btVector3 btKinematicCharacterController::getGravity() const
+{
+       return -m_gravity * m_up;
+}
+
+void btKinematicCharacterController::setMaxSlope(btScalar slopeRadians)
+{
+       m_maxSlopeRadians = slopeRadians;
+       m_maxSlopeCosine = btCos(slopeRadians);
+}
+
+btScalar btKinematicCharacterController::getMaxSlope() const
+{
+       return m_maxSlopeRadians;
+}
+
+void btKinematicCharacterController::setMaxPenetrationDepth(btScalar d)
+{
+       m_maxPenetrationDepth = d;
+}
+
+btScalar btKinematicCharacterController::getMaxPenetrationDepth() const
+{
+       return m_maxPenetrationDepth;
+}
+
+bool btKinematicCharacterController::onGround() const
+{
+       return (fabs(m_verticalVelocity) < SIMD_EPSILON) && (fabs(m_verticalOffset) < SIMD_EPSILON);
+}
+
+void btKinematicCharacterController::setStepHeight(btScalar h)
+{
+       m_stepHeight = h;
+}
+
+btVector3* btKinematicCharacterController::getUpAxisDirections()
+{
+       static btVector3 sUpAxisDirection[3] = {btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f)};
+
+       return sUpAxisDirection;
+}
+
+void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer)
+{
+}
+
+void btKinematicCharacterController::setUpInterpolate(bool value)
+{
+       m_interpolateUp = value;
+}
+
+void btKinematicCharacterController::setUp(const btVector3& up)
+{
+       if (up.length2() > 0 && m_gravity > 0.0f)
+       {
+               setGravity(-m_gravity * up.normalized());
+               return;
+       }
+
+       setUpVector(up);
+}
+
+void btKinematicCharacterController::setUpVector(const btVector3& up)
+{
+       if (m_up == up)
+               return;
+
+       btVector3 u = m_up;
+
+       if (up.length2() > 0)
+               m_up = up.normalized();
+       else
+               m_up = btVector3(0.0, 0.0, 0.0);
+
+       if (!m_ghostObject) return;
+       btQuaternion rot = getRotation(m_up, u);
+
+       //set orientation with new up
+       btTransform xform;
+       xform = m_ghostObject->getWorldTransform();
+       btQuaternion orn = rot.inverse() * xform.getRotation();
+       xform.setRotation(orn);
+       m_ghostObject->setWorldTransform(xform);
+}
+
+btQuaternion btKinematicCharacterController::getRotation(btVector3& v0, btVector3& v1) const
+{
+       if (v0.length2() == 0.0f || v1.length2() == 0.0f)
+       {
+               btQuaternion q;
+               return q;
+       }
+
+       return shortestArcQuatNormalize2(v0, v1);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Character/btKinematicCharacterController.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Character/btKinematicCharacterController.h
new file mode 100644 (file)
index 0000000..ff34fc8
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+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.
+*/
+
+#ifndef BT_KINEMATIC_CHARACTER_CONTROLLER_H
+#define BT_KINEMATIC_CHARACTER_CONTROLLER_H
+
+#include "LinearMath/btVector3.h"
+
+#include "btCharacterControllerInterface.h"
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+class btCollisionShape;
+class btConvexShape;
+class btRigidBody;
+class btCollisionWorld;
+class btCollisionDispatcher;
+class btPairCachingGhostObject;
+
+///btKinematicCharacterController is an object that supports a sliding motion in a world.
+///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
+///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
+ATTRIBUTE_ALIGNED16(class)
+btKinematicCharacterController : public btCharacterControllerInterface
+{
+protected:
+       btScalar m_halfHeight;
+
+       btPairCachingGhostObject* m_ghostObject;
+       btConvexShape* m_convexShape;  //is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
+
+       btScalar m_maxPenetrationDepth;
+       btScalar m_verticalVelocity;
+       btScalar m_verticalOffset;
+       btScalar m_fallSpeed;
+       btScalar m_jumpSpeed;
+       btScalar m_SetjumpSpeed;
+       btScalar m_maxJumpHeight;
+       btScalar m_maxSlopeRadians;  // Slope angle that is set (used for returning the exact value)
+       btScalar m_maxSlopeCosine;   // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization)
+       btScalar m_gravity;
+
+       btScalar m_turnAngle;
+
+       btScalar m_stepHeight;
+
+       btScalar m_addedMargin;  //@todo: remove this and fix the code
+
+       ///this is the desired walk direction, set by the user
+       btVector3 m_walkDirection;
+       btVector3 m_normalizedDirection;
+       btVector3 m_AngVel;
+
+       btVector3 m_jumpPosition;
+
+       //some internal variables
+       btVector3 m_currentPosition;
+       btScalar m_currentStepOffset;
+       btVector3 m_targetPosition;
+
+       btQuaternion m_currentOrientation;
+       btQuaternion m_targetOrientation;
+
+       ///keep track of the contact manifolds
+       btManifoldArray m_manifoldArray;
+
+       bool m_touchingContact;
+       btVector3 m_touchingNormal;
+
+       btScalar m_linearDamping;
+       btScalar m_angularDamping;
+
+       bool m_wasOnGround;
+       bool m_wasJumping;
+       bool m_useGhostObjectSweepTest;
+       bool m_useWalkDirection;
+       btScalar m_velocityTimeInterval;
+       btVector3 m_up;
+       btVector3 m_jumpAxis;
+
+       static btVector3* getUpAxisDirections();
+       bool m_interpolateUp;
+       bool full_drop;
+       bool bounce_fix;
+
+       btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal);
+       btVector3 parallelComponent(const btVector3& direction, const btVector3& normal);
+       btVector3 perpindicularComponent(const btVector3& direction, const btVector3& normal);
+
+       bool recoverFromPenetration(btCollisionWorld * collisionWorld);
+       void stepUp(btCollisionWorld * collisionWorld);
+       void updateTargetPositionBasedOnCollision(const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
+       void stepForwardAndStrafe(btCollisionWorld * collisionWorld, const btVector3& walkMove);
+       void stepDown(btCollisionWorld * collisionWorld, btScalar dt);
+
+       virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1);
+
+       void setUpVector(const btVector3& up);
+
+       btQuaternion getRotation(btVector3 & v0, btVector3 & v1) const;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btKinematicCharacterController(btPairCachingGhostObject * ghostObject, btConvexShape * convexShape, btScalar stepHeight, const btVector3& up = btVector3(1.0, 0.0, 0.0));
+       ~btKinematicCharacterController();
+
+       ///btActionInterface interface
+       virtual void updateAction(btCollisionWorld * collisionWorld, btScalar deltaTime)
+       {
+               preStep(collisionWorld);
+               playerStep(collisionWorld, deltaTime);
+       }
+
+       ///btActionInterface interface
+       void debugDraw(btIDebugDraw * debugDrawer);
+
+       void setUp(const btVector3& up);
+
+       const btVector3& getUp() { return m_up; }
+
+       /// This should probably be called setPositionIncrementPerSimulatorStep.
+       /// This is neither a direction nor a velocity, but the amount to
+       ///     increment the position each simulation iteration, regardless
+       ///     of dt.
+       /// This call will reset any velocity set by setVelocityForTimeInterval().
+       virtual void setWalkDirection(const btVector3& walkDirection);
+
+       /// Caller provides a velocity with which the character should move for
+       ///     the given time period.  After the time period, velocity is reset
+       ///     to zero.
+       /// This call will reset any walk direction set by setWalkDirection().
+       /// Negative time intervals will result in no motion.
+       virtual void setVelocityForTimeInterval(const btVector3& velocity,
+                                                                                       btScalar timeInterval);
+
+       virtual void setAngularVelocity(const btVector3& velocity);
+       virtual const btVector3& getAngularVelocity() const;
+
+       virtual void setLinearVelocity(const btVector3& velocity);
+       virtual btVector3 getLinearVelocity() const;
+
+       void setLinearDamping(btScalar d) { m_linearDamping = btClamped(d, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); }
+       btScalar getLinearDamping() const { return m_linearDamping; }
+       void setAngularDamping(btScalar d) { m_angularDamping = btClamped(d, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); }
+       btScalar getAngularDamping() const { return m_angularDamping; }
+
+       void reset(btCollisionWorld * collisionWorld);
+       void warp(const btVector3& origin);
+
+       void preStep(btCollisionWorld * collisionWorld);
+       void playerStep(btCollisionWorld * collisionWorld, btScalar dt);
+
+       void setStepHeight(btScalar h);
+       btScalar getStepHeight() const { return m_stepHeight; }
+       void setFallSpeed(btScalar fallSpeed);
+       btScalar getFallSpeed() const { return m_fallSpeed; }
+       void setJumpSpeed(btScalar jumpSpeed);
+       btScalar getJumpSpeed() const { return m_jumpSpeed; }
+       void setMaxJumpHeight(btScalar maxJumpHeight);
+       bool canJump() const;
+
+       void jump(const btVector3& v = btVector3(0, 0, 0));
+
+       void applyImpulse(const btVector3& v) { jump(v); }
+
+       void setGravity(const btVector3& gravity);
+       btVector3 getGravity() const;
+
+       /// The max slope determines the maximum angle that the controller can walk up.
+       /// The slope angle is measured in radians.
+       void setMaxSlope(btScalar slopeRadians);
+       btScalar getMaxSlope() const;
+
+       void setMaxPenetrationDepth(btScalar d);
+       btScalar getMaxPenetrationDepth() const;
+
+       btPairCachingGhostObject* getGhostObject();
+       void setUseGhostSweepTest(bool useGhostObjectSweepTest)
+       {
+               m_useGhostObjectSweepTest = useGhostObjectSweepTest;
+       }
+
+       bool onGround() const;
+       void setUpInterpolate(bool value);
+};
+
+#endif  // BT_KINEMATIC_CHARACTER_CONTROLLER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
new file mode 100644 (file)
index 0000000..89bd067
--- /dev/null
@@ -0,0 +1,1084 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btBatchedConstraints.h"
+
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btQuickprof.h"
+
+#include <string.h>  //for memset
+
+#include <cmath>
+
+const int kNoMerge = -1;
+
+bool btBatchedConstraints::s_debugDrawBatches = false;
+
+struct btBatchedConstraintInfo
+{
+       int constraintIndex;
+       int numConstraintRows;
+       int bodyIds[2];
+};
+
+struct btBatchInfo
+{
+       int numConstraints;
+       int mergeIndex;
+
+       btBatchInfo() : numConstraints(0), mergeIndex(kNoMerge) {}
+};
+
+bool btBatchedConstraints::validate(btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies) const
+{
+       //
+       // validate: for debugging only. Verify coloring of bodies, that no body is touched by more than one batch in any given phase
+       //
+       int errors = 0;
+       const int kUnassignedBatch = -1;
+
+       btAlignedObjectArray<int> bodyBatchId;
+       for (int iPhase = 0; iPhase < m_phases.size(); ++iPhase)
+       {
+               bodyBatchId.resizeNoInitialize(0);
+               bodyBatchId.resize(bodies.size(), kUnassignedBatch);
+               const Range& phase = m_phases[iPhase];
+               for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch)
+               {
+                       const Range& batch = m_batches[iBatch];
+                       for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons)
+                       {
+                               int iCons = m_constraintIndices[iiCons];
+                               const btSolverConstraint& cons = constraints->at(iCons);
+                               const btSolverBody& bodyA = bodies[cons.m_solverBodyIdA];
+                               const btSolverBody& bodyB = bodies[cons.m_solverBodyIdB];
+                               if (!bodyA.internalGetInvMass().isZero())
+                               {
+                                       int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdA];
+                                       if (thisBodyBatchId == kUnassignedBatch)
+                                       {
+                                               bodyBatchId[cons.m_solverBodyIdA] = iBatch;
+                                       }
+                                       else if (thisBodyBatchId != iBatch)
+                                       {
+                                               btAssert(!"dynamic body is used in 2 different batches in the same phase");
+                                               errors++;
+                                       }
+                               }
+                               if (!bodyB.internalGetInvMass().isZero())
+                               {
+                                       int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdB];
+                                       if (thisBodyBatchId == kUnassignedBatch)
+                                       {
+                                               bodyBatchId[cons.m_solverBodyIdB] = iBatch;
+                                       }
+                                       else if (thisBodyBatchId != iBatch)
+                                       {
+                                               btAssert(!"dynamic body is used in 2 different batches in the same phase");
+                                               errors++;
+                                       }
+                               }
+                       }
+               }
+       }
+       return errors == 0;
+}
+
+static void debugDrawSingleBatch(const btBatchedConstraints* bc,
+                                                                btConstraintArray* constraints,
+                                                                const btAlignedObjectArray<btSolverBody>& bodies,
+                                                                int iBatch,
+                                                                const btVector3& color,
+                                                                const btVector3& offset)
+{
+       if (bc && bc->m_debugDrawer && iBatch < bc->m_batches.size())
+       {
+               const btBatchedConstraints::Range& b = bc->m_batches[iBatch];
+               for (int iiCon = b.begin; iiCon < b.end; ++iiCon)
+               {
+                       int iCon = bc->m_constraintIndices[iiCon];
+                       const btSolverConstraint& con = constraints->at(iCon);
+                       int iBody0 = con.m_solverBodyIdA;
+                       int iBody1 = con.m_solverBodyIdB;
+                       btVector3 pos0 = bodies[iBody0].getWorldTransform().getOrigin() + offset;
+                       btVector3 pos1 = bodies[iBody1].getWorldTransform().getOrigin() + offset;
+                       bc->m_debugDrawer->drawLine(pos0, pos1, color);
+               }
+       }
+}
+
+static void debugDrawPhase(const btBatchedConstraints* bc,
+                                                  btConstraintArray* constraints,
+                                                  const btAlignedObjectArray<btSolverBody>& bodies,
+                                                  int iPhase,
+                                                  const btVector3& color0,
+                                                  const btVector3& color1,
+                                                  const btVector3& offset)
+{
+       BT_PROFILE("debugDrawPhase");
+       if (bc && bc->m_debugDrawer && iPhase < bc->m_phases.size())
+       {
+               const btBatchedConstraints::Range& phase = bc->m_phases[iPhase];
+               for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch)
+               {
+                       float tt = float(iBatch - phase.begin) / float(btMax(1, phase.end - phase.begin - 1));
+                       btVector3 col = lerp(color0, color1, tt);
+                       debugDrawSingleBatch(bc, constraints, bodies, iBatch, col, offset);
+               }
+       }
+}
+
+static void debugDrawAllBatches(const btBatchedConstraints* bc,
+                                                               btConstraintArray* constraints,
+                                                               const btAlignedObjectArray<btSolverBody>& bodies)
+{
+       BT_PROFILE("debugDrawAllBatches");
+       if (bc && bc->m_debugDrawer && bc->m_phases.size() > 0)
+       {
+               btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
+               btVector3 bboxMax = -bboxMin;
+               for (int iBody = 0; iBody < bodies.size(); ++iBody)
+               {
+                       const btVector3& pos = bodies[iBody].getWorldTransform().getOrigin();
+                       bboxMin.setMin(pos);
+                       bboxMax.setMax(pos);
+               }
+               btVector3 bboxExtent = bboxMax - bboxMin;
+               btVector3 offsetBase = btVector3(0, bboxExtent.y() * 1.1f, 0);
+               btVector3 offsetStep = btVector3(0, 0, bboxExtent.z() * 1.1f);
+               int numPhases = bc->m_phases.size();
+               for (int iPhase = 0; iPhase < numPhases; ++iPhase)
+               {
+                       float b = float(iPhase) / float(numPhases - 1);
+                       btVector3 color0 = btVector3(1, 0, b);
+                       btVector3 color1 = btVector3(0, 1, b);
+                       btVector3 offset = offsetBase + offsetStep * (float(iPhase) - float(numPhases - 1) * 0.5);
+                       debugDrawPhase(bc, constraints, bodies, iPhase, color0, color1, offset);
+               }
+       }
+}
+
+static void initBatchedBodyDynamicFlags(btAlignedObjectArray<bool>* outBodyDynamicFlags, const btAlignedObjectArray<btSolverBody>& bodies)
+{
+       BT_PROFILE("initBatchedBodyDynamicFlags");
+       btAlignedObjectArray<bool>& bodyDynamicFlags = *outBodyDynamicFlags;
+       bodyDynamicFlags.resizeNoInitialize(bodies.size());
+       for (int i = 0; i < bodies.size(); ++i)
+       {
+               const btSolverBody& body = bodies[i];
+               bodyDynamicFlags[i] = (body.internalGetInvMass().x() > btScalar(0));
+       }
+}
+
+static int runLengthEncodeConstraintInfo(btBatchedConstraintInfo* outConInfos, int numConstraints)
+{
+       BT_PROFILE("runLengthEncodeConstraintInfo");
+       // detect and run-length encode constraint rows that repeat the same bodies
+       int iDest = 0;
+       int iSrc = 0;
+       while (iSrc < numConstraints)
+       {
+               const btBatchedConstraintInfo& srcConInfo = outConInfos[iSrc];
+               btBatchedConstraintInfo& conInfo = outConInfos[iDest];
+               conInfo.constraintIndex = iSrc;
+               conInfo.bodyIds[0] = srcConInfo.bodyIds[0];
+               conInfo.bodyIds[1] = srcConInfo.bodyIds[1];
+               while (iSrc < numConstraints && outConInfos[iSrc].bodyIds[0] == srcConInfo.bodyIds[0] && outConInfos[iSrc].bodyIds[1] == srcConInfo.bodyIds[1])
+               {
+                       ++iSrc;
+               }
+               conInfo.numConstraintRows = iSrc - conInfo.constraintIndex;
+               ++iDest;
+       }
+       return iDest;
+}
+
+struct ReadSolverConstraintsLoop : public btIParallelForBody
+{
+       btBatchedConstraintInfo* m_outConInfos;
+       btConstraintArray* m_constraints;
+
+       ReadSolverConstraintsLoop(btBatchedConstraintInfo* outConInfos, btConstraintArray* constraints)
+       {
+               m_outConInfos = outConInfos;
+               m_constraints = constraints;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               for (int i = iBegin; i < iEnd; ++i)
+               {
+                       btBatchedConstraintInfo& conInfo = m_outConInfos[i];
+                       const btSolverConstraint& con = m_constraints->at(i);
+                       conInfo.bodyIds[0] = con.m_solverBodyIdA;
+                       conInfo.bodyIds[1] = con.m_solverBodyIdB;
+                       conInfo.constraintIndex = i;
+                       conInfo.numConstraintRows = 1;
+               }
+       }
+};
+
+static int initBatchedConstraintInfo(btBatchedConstraintInfo* outConInfos, btConstraintArray* constraints)
+{
+       BT_PROFILE("initBatchedConstraintInfo");
+       int numConstraints = constraints->size();
+       bool inParallel = true;
+       if (inParallel)
+       {
+               ReadSolverConstraintsLoop loop(outConInfos, constraints);
+               int grainSize = 1200;
+               btParallelFor(0, numConstraints, grainSize, loop);
+       }
+       else
+       {
+               for (int i = 0; i < numConstraints; ++i)
+               {
+                       btBatchedConstraintInfo& conInfo = outConInfos[i];
+                       const btSolverConstraint& con = constraints->at(i);
+                       conInfo.bodyIds[0] = con.m_solverBodyIdA;
+                       conInfo.bodyIds[1] = con.m_solverBodyIdB;
+                       conInfo.constraintIndex = i;
+                       conInfo.numConstraintRows = 1;
+               }
+       }
+       bool useRunLengthEncoding = true;
+       if (useRunLengthEncoding)
+       {
+               numConstraints = runLengthEncodeConstraintInfo(outConInfos, numConstraints);
+       }
+       return numConstraints;
+}
+
+static void expandConstraintRowsInPlace(int* constraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows)
+{
+       BT_PROFILE("expandConstraintRowsInPlace");
+       if (numConstraintRows > numConstraints)
+       {
+               // we walk the array in reverse to avoid overwriteing
+               for (int iCon = numConstraints - 1; iCon >= 0; --iCon)
+               {
+                       const btBatchedConstraintInfo& conInfo = conInfos[iCon];
+                       int iBatch = constraintBatchIds[iCon];
+                       for (int i = conInfo.numConstraintRows - 1; i >= 0; --i)
+                       {
+                               int iDest = conInfo.constraintIndex + i;
+                               btAssert(iDest >= iCon);
+                               btAssert(iDest >= 0 && iDest < numConstraintRows);
+                               constraintBatchIds[iDest] = iBatch;
+                       }
+               }
+       }
+}
+
+static void expandConstraintRows(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows)
+{
+       BT_PROFILE("expandConstraintRows");
+       for (int iCon = 0; iCon < numConstraints; ++iCon)
+       {
+               const btBatchedConstraintInfo& conInfo = conInfos[iCon];
+               int iBatch = srcConstraintBatchIds[iCon];
+               for (int i = 0; i < conInfo.numConstraintRows; ++i)
+               {
+                       int iDest = conInfo.constraintIndex + i;
+                       btAssert(iDest >= iCon);
+                       btAssert(iDest >= 0 && iDest < numConstraintRows);
+                       destConstraintBatchIds[iDest] = iBatch;
+               }
+       }
+}
+
+struct ExpandConstraintRowsLoop : public btIParallelForBody
+{
+       int* m_destConstraintBatchIds;
+       const int* m_srcConstraintBatchIds;
+       const btBatchedConstraintInfo* m_conInfos;
+       int m_numConstraintRows;
+
+       ExpandConstraintRowsLoop(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraintRows)
+       {
+               m_destConstraintBatchIds = destConstraintBatchIds;
+               m_srcConstraintBatchIds = srcConstraintBatchIds;
+               m_conInfos = conInfos;
+               m_numConstraintRows = numConstraintRows;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               expandConstraintRows(m_destConstraintBatchIds, m_srcConstraintBatchIds + iBegin, m_conInfos + iBegin, iEnd - iBegin, m_numConstraintRows);
+       }
+};
+
+static void expandConstraintRowsMt(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows)
+{
+       BT_PROFILE("expandConstraintRowsMt");
+       ExpandConstraintRowsLoop loop(destConstraintBatchIds, srcConstraintBatchIds, conInfos, numConstraintRows);
+       int grainSize = 600;
+       btParallelFor(0, numConstraints, grainSize, loop);
+}
+
+static void initBatchedConstraintInfoArray(btAlignedObjectArray<btBatchedConstraintInfo>* outConInfos, btConstraintArray* constraints)
+{
+       BT_PROFILE("initBatchedConstraintInfoArray");
+       btAlignedObjectArray<btBatchedConstraintInfo>& conInfos = *outConInfos;
+       int numConstraints = constraints->size();
+       conInfos.resizeNoInitialize(numConstraints);
+
+       int newSize = initBatchedConstraintInfo(&outConInfos->at(0), constraints);
+       conInfos.resizeNoInitialize(newSize);
+}
+
+static void mergeSmallBatches(btBatchInfo* batches, int iBeginBatch, int iEndBatch, int minBatchSize, int maxBatchSize)
+{
+       BT_PROFILE("mergeSmallBatches");
+       for (int iBatch = iEndBatch - 1; iBatch >= iBeginBatch; --iBatch)
+       {
+               btBatchInfo& batch = batches[iBatch];
+               if (batch.mergeIndex == kNoMerge && batch.numConstraints > 0 && batch.numConstraints < minBatchSize)
+               {
+                       for (int iDestBatch = iBatch - 1; iDestBatch >= iBeginBatch; --iDestBatch)
+                       {
+                               btBatchInfo& destBatch = batches[iDestBatch];
+                               if (destBatch.mergeIndex == kNoMerge && (destBatch.numConstraints + batch.numConstraints) < maxBatchSize)
+                               {
+                                       destBatch.numConstraints += batch.numConstraints;
+                                       batch.numConstraints = 0;
+                                       batch.mergeIndex = iDestBatch;
+                                       break;
+                               }
+                       }
+               }
+       }
+       // flatten mergeIndexes
+       // e.g. in case where A was merged into B and then B was merged into C, we need A to point to C instead of B
+       // Note: loop goes forward through batches because batches always merge from higher indexes to lower,
+       //     so by going from low to high it reduces the amount of trail-following
+       for (int iBatch = iBeginBatch; iBatch < iEndBatch; ++iBatch)
+       {
+               btBatchInfo& batch = batches[iBatch];
+               if (batch.mergeIndex != kNoMerge)
+               {
+                       int iMergeDest = batches[batch.mergeIndex].mergeIndex;
+                       // follow trail of merges to the end
+                       while (iMergeDest != kNoMerge)
+                       {
+                               int iNext = batches[iMergeDest].mergeIndex;
+                               if (iNext == kNoMerge)
+                               {
+                                       batch.mergeIndex = iMergeDest;
+                                       break;
+                               }
+                               iMergeDest = iNext;
+                       }
+               }
+       }
+}
+
+static void updateConstraintBatchIdsForMerges(int* constraintBatchIds, int numConstraints, const btBatchInfo* batches, int numBatches)
+{
+       BT_PROFILE("updateConstraintBatchIdsForMerges");
+       // update batchIds to account for merges
+       for (int i = 0; i < numConstraints; ++i)
+       {
+               int iBatch = constraintBatchIds[i];
+               btAssert(iBatch < numBatches);
+               // if this constraint references a batch that was merged into another batch
+               if (batches[iBatch].mergeIndex != kNoMerge)
+               {
+                       // update batchId
+                       constraintBatchIds[i] = batches[iBatch].mergeIndex;
+               }
+       }
+}
+
+struct UpdateConstraintBatchIdsForMergesLoop : public btIParallelForBody
+{
+       int* m_constraintBatchIds;
+       const btBatchInfo* m_batches;
+       int m_numBatches;
+
+       UpdateConstraintBatchIdsForMergesLoop(int* constraintBatchIds, const btBatchInfo* batches, int numBatches)
+       {
+               m_constraintBatchIds = constraintBatchIds;
+               m_batches = batches;
+               m_numBatches = numBatches;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               BT_PROFILE("UpdateConstraintBatchIdsForMergesLoop");
+               updateConstraintBatchIdsForMerges(m_constraintBatchIds + iBegin, iEnd - iBegin, m_batches, m_numBatches);
+       }
+};
+
+static void updateConstraintBatchIdsForMergesMt(int* constraintBatchIds, int numConstraints, const btBatchInfo* batches, int numBatches)
+{
+       BT_PROFILE("updateConstraintBatchIdsForMergesMt");
+       UpdateConstraintBatchIdsForMergesLoop loop(constraintBatchIds, batches, numBatches);
+       int grainSize = 800;
+       btParallelFor(0, numConstraints, grainSize, loop);
+}
+
+inline bool BatchCompare(const btBatchedConstraints::Range& a, const btBatchedConstraints::Range& b)
+{
+       int lenA = a.end - a.begin;
+       int lenB = b.end - b.begin;
+       return lenA > lenB;
+}
+
+static void writeOutConstraintIndicesForRangeOfBatches(btBatchedConstraints* bc,
+                                                                                                          const int* constraintBatchIds,
+                                                                                                          int numConstraints,
+                                                                                                          int* constraintIdPerBatch,
+                                                                                                          int batchBegin,
+                                                                                                          int batchEnd)
+{
+       BT_PROFILE("writeOutConstraintIndicesForRangeOfBatches");
+       for (int iCon = 0; iCon < numConstraints; ++iCon)
+       {
+               int iBatch = constraintBatchIds[iCon];
+               if (iBatch >= batchBegin && iBatch < batchEnd)
+               {
+                       int iDestCon = constraintIdPerBatch[iBatch];
+                       constraintIdPerBatch[iBatch] = iDestCon + 1;
+                       bc->m_constraintIndices[iDestCon] = iCon;
+               }
+       }
+}
+
+struct WriteOutConstraintIndicesLoop : public btIParallelForBody
+{
+       btBatchedConstraints* m_batchedConstraints;
+       const int* m_constraintBatchIds;
+       int m_numConstraints;
+       int* m_constraintIdPerBatch;
+       int m_maxNumBatchesPerPhase;
+
+       WriteOutConstraintIndicesLoop(btBatchedConstraints* bc, const int* constraintBatchIds, int numConstraints, int* constraintIdPerBatch, int maxNumBatchesPerPhase)
+       {
+               m_batchedConstraints = bc;
+               m_constraintBatchIds = constraintBatchIds;
+               m_numConstraints = numConstraints;
+               m_constraintIdPerBatch = constraintIdPerBatch;
+               m_maxNumBatchesPerPhase = maxNumBatchesPerPhase;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               BT_PROFILE("WriteOutConstraintIndicesLoop");
+               int batchBegin = iBegin * m_maxNumBatchesPerPhase;
+               int batchEnd = iEnd * m_maxNumBatchesPerPhase;
+               writeOutConstraintIndicesForRangeOfBatches(m_batchedConstraints,
+                                                                                                  m_constraintBatchIds,
+                                                                                                  m_numConstraints,
+                                                                                                  m_constraintIdPerBatch,
+                                                                                                  batchBegin,
+                                                                                                  batchEnd);
+       }
+};
+
+static void writeOutConstraintIndicesMt(btBatchedConstraints* bc,
+                                                                               const int* constraintBatchIds,
+                                                                               int numConstraints,
+                                                                               int* constraintIdPerBatch,
+                                                                               int maxNumBatchesPerPhase,
+                                                                               int numPhases)
+{
+       BT_PROFILE("writeOutConstraintIndicesMt");
+       bool inParallel = true;
+       if (inParallel)
+       {
+               WriteOutConstraintIndicesLoop loop(bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase);
+               btParallelFor(0, numPhases, 1, loop);
+       }
+       else
+       {
+               for (int iCon = 0; iCon < numConstraints; ++iCon)
+               {
+                       int iBatch = constraintBatchIds[iCon];
+                       int iDestCon = constraintIdPerBatch[iBatch];
+                       constraintIdPerBatch[iBatch] = iDestCon + 1;
+                       bc->m_constraintIndices[iDestCon] = iCon;
+               }
+       }
+}
+
+static void writeGrainSizes(btBatchedConstraints* bc)
+{
+       typedef btBatchedConstraints::Range Range;
+       int numPhases = bc->m_phases.size();
+       bc->m_phaseGrainSize.resizeNoInitialize(numPhases);
+       int numThreads = btGetTaskScheduler()->getNumThreads();
+       for (int iPhase = 0; iPhase < numPhases; ++iPhase)
+       {
+               const Range& phase = bc->m_phases[iPhase];
+               int numBatches = phase.end - phase.begin;
+               float grainSize = std::floor((0.25f * numBatches / float(numThreads)) + 0.0f);
+               bc->m_phaseGrainSize[iPhase] = btMax(1, int(grainSize));
+       }
+}
+
+static void writeOutBatches(btBatchedConstraints* bc,
+                                                       const int* constraintBatchIds,
+                                                       int numConstraints,
+                                                       const btBatchInfo* batches,
+                                                       int* batchWork,
+                                                       int maxNumBatchesPerPhase,
+                                                       int numPhases)
+{
+       BT_PROFILE("writeOutBatches");
+       typedef btBatchedConstraints::Range Range;
+       bc->m_constraintIndices.reserve(numConstraints);
+       bc->m_batches.resizeNoInitialize(0);
+       bc->m_phases.resizeNoInitialize(0);
+
+       //int maxNumBatches = numPhases * maxNumBatchesPerPhase;
+       {
+               int* constraintIdPerBatch = batchWork;  // for each batch, keep an index into the next available slot in the m_constraintIndices array
+               int iConstraint = 0;
+               for (int iPhase = 0; iPhase < numPhases; ++iPhase)
+               {
+                       int curPhaseBegin = bc->m_batches.size();
+                       int iBegin = iPhase * maxNumBatchesPerPhase;
+                       int iEnd = iBegin + maxNumBatchesPerPhase;
+                       for (int i = iBegin; i < iEnd; ++i)
+                       {
+                               const btBatchInfo& batch = batches[i];
+                               int curBatchBegin = iConstraint;
+                               constraintIdPerBatch[i] = curBatchBegin;  // record the start of each batch in m_constraintIndices array
+                               int numConstraints = batch.numConstraints;
+                               iConstraint += numConstraints;
+                               if (numConstraints > 0)
+                               {
+                                       bc->m_batches.push_back(Range(curBatchBegin, iConstraint));
+                               }
+                       }
+                       // if any batches were emitted this phase,
+                       if (bc->m_batches.size() > curPhaseBegin)
+                       {
+                               // output phase
+                               bc->m_phases.push_back(Range(curPhaseBegin, bc->m_batches.size()));
+                       }
+               }
+
+               btAssert(iConstraint == numConstraints);
+               bc->m_constraintIndices.resizeNoInitialize(numConstraints);
+               writeOutConstraintIndicesMt(bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase, numPhases);
+       }
+       // for each phase
+       for (int iPhase = 0; iPhase < bc->m_phases.size(); ++iPhase)
+       {
+               // sort the batches from largest to smallest (can be helpful to some task schedulers)
+               const Range& curBatches = bc->m_phases[iPhase];
+               bc->m_batches.quickSortInternal(BatchCompare, curBatches.begin, curBatches.end - 1);
+       }
+       bc->m_phaseOrder.resize(bc->m_phases.size());
+       for (int i = 0; i < bc->m_phases.size(); ++i)
+       {
+               bc->m_phaseOrder[i] = i;
+       }
+       writeGrainSizes(bc);
+}
+
+//
+// PreallocatedMemoryHelper -- helper object for allocating a number of chunks of memory in a single contiguous block.
+//                             It is generally more efficient to do a single larger allocation than many smaller allocations.
+//
+// Example Usage:
+//
+//  btVector3* bodyPositions = NULL;
+//  btBatchedConstraintInfo* conInfos = NULL;
+//  {
+//    PreallocatedMemoryHelper<8> memHelper;
+//    memHelper.addChunk( (void**) &bodyPositions, sizeof( btVector3 ) * bodies.size() );
+//    memHelper.addChunk( (void**) &conInfos, sizeof( btBatchedConstraintInfo ) * numConstraints );
+//    void* memPtr = malloc( memHelper.getSizeToAllocate() );  // allocate the memory
+//    memHelper.setChunkPointers( memPtr );  // update pointers to chunks
+//  }
+template <int N>
+class PreallocatedMemoryHelper
+{
+       struct Chunk
+       {
+               void** ptr;
+               size_t size;
+       };
+       Chunk m_chunks[N];
+       int m_numChunks;
+
+public:
+       PreallocatedMemoryHelper() { m_numChunks = 0; }
+       void addChunk(void** ptr, size_t sz)
+       {
+               btAssert(m_numChunks < N);
+               if (m_numChunks < N)
+               {
+                       Chunk& chunk = m_chunks[m_numChunks];
+                       chunk.ptr = ptr;
+                       chunk.size = sz;
+                       m_numChunks++;
+               }
+       }
+       size_t getSizeToAllocate() const
+       {
+               size_t totalSize = 0;
+               for (int i = 0; i < m_numChunks; ++i)
+               {
+                       totalSize += m_chunks[i].size;
+               }
+               return totalSize;
+       }
+       void setChunkPointers(void* mem) const
+       {
+               size_t totalSize = 0;
+               for (int i = 0; i < m_numChunks; ++i)
+               {
+                       const Chunk& chunk = m_chunks[i];
+                       char* chunkPtr = static_cast<char*>(mem) + totalSize;
+                       *chunk.ptr = chunkPtr;
+                       totalSize += chunk.size;
+               }
+       }
+};
+
+static btVector3 findMaxDynamicConstraintExtent(
+       btVector3* bodyPositions,
+       bool* bodyDynamicFlags,
+       btBatchedConstraintInfo* conInfos,
+       int numConstraints,
+       int numBodies)
+{
+       BT_PROFILE("findMaxDynamicConstraintExtent");
+       btVector3 consExtent = btVector3(1, 1, 1) * 0.001;
+       for (int iCon = 0; iCon < numConstraints; ++iCon)
+       {
+               const btBatchedConstraintInfo& con = conInfos[iCon];
+               int iBody0 = con.bodyIds[0];
+               int iBody1 = con.bodyIds[1];
+               btAssert(iBody0 >= 0 && iBody0 < numBodies);
+               btAssert(iBody1 >= 0 && iBody1 < numBodies);
+               // is it a dynamic constraint?
+               if (bodyDynamicFlags[iBody0] && bodyDynamicFlags[iBody1])
+               {
+                       btVector3 delta = bodyPositions[iBody1] - bodyPositions[iBody0];
+                       consExtent.setMax(delta.absolute());
+               }
+       }
+       return consExtent;
+}
+
+struct btIntVec3
+{
+       int m_ints[3];
+
+       SIMD_FORCE_INLINE const int& operator[](int i) const { return m_ints[i]; }
+       SIMD_FORCE_INLINE int& operator[](int i) { return m_ints[i]; }
+};
+
+struct AssignConstraintsToGridBatchesParams
+{
+       bool* bodyDynamicFlags;
+       btIntVec3* bodyGridCoords;
+       int numBodies;
+       btBatchedConstraintInfo* conInfos;
+       int* constraintBatchIds;
+       btIntVec3 gridChunkDim;
+       int maxNumBatchesPerPhase;
+       int numPhases;
+       int phaseMask;
+
+       AssignConstraintsToGridBatchesParams()
+       {
+               memset(this, 0, sizeof(*this));
+       }
+};
+
+static void assignConstraintsToGridBatches(const AssignConstraintsToGridBatchesParams& params, int iConBegin, int iConEnd)
+{
+       BT_PROFILE("assignConstraintsToGridBatches");
+       // (can be done in parallel)
+       for (int iCon = iConBegin; iCon < iConEnd; ++iCon)
+       {
+               const btBatchedConstraintInfo& con = params.conInfos[iCon];
+               int iBody0 = con.bodyIds[0];
+               int iBody1 = con.bodyIds[1];
+               int iPhase = iCon;  //iBody0; // pseudorandom choice to distribute evenly amongst phases
+               iPhase &= params.phaseMask;
+               int gridCoord[3];
+               // is it a dynamic constraint?
+               if (params.bodyDynamicFlags[iBody0] && params.bodyDynamicFlags[iBody1])
+               {
+                       const btIntVec3& body0Coords = params.bodyGridCoords[iBody0];
+                       const btIntVec3& body1Coords = params.bodyGridCoords[iBody1];
+                       // for each dimension x,y,z,
+                       for (int i = 0; i < 3; ++i)
+                       {
+                               int coordMin = btMin(body0Coords.m_ints[i], body1Coords.m_ints[i]);
+                               int coordMax = btMax(body0Coords.m_ints[i], body1Coords.m_ints[i]);
+                               if (coordMin != coordMax)
+                               {
+                                       btAssert(coordMax == coordMin + 1);
+                                       if ((coordMin & 1) == 0)
+                                       {
+                                               iPhase &= ~(1 << i);  // force bit off
+                                       }
+                                       else
+                                       {
+                                               iPhase |= (1 << i);  // force bit on
+                                               iPhase &= params.phaseMask;
+                                       }
+                               }
+                               gridCoord[i] = coordMin;
+                       }
+               }
+               else
+               {
+                       if (!params.bodyDynamicFlags[iBody0])
+                       {
+                               iBody0 = con.bodyIds[1];
+                       }
+                       btAssert(params.bodyDynamicFlags[iBody0]);
+                       const btIntVec3& body0Coords = params.bodyGridCoords[iBody0];
+                       // for each dimension x,y,z,
+                       for (int i = 0; i < 3; ++i)
+                       {
+                               gridCoord[i] = body0Coords.m_ints[i];
+                       }
+               }
+               // calculate chunk coordinates
+               int chunkCoord[3];
+               btIntVec3 gridChunkDim = params.gridChunkDim;
+               // for each dimension x,y,z,
+               for (int i = 0; i < 3; ++i)
+               {
+                       int coordOffset = (iPhase >> i) & 1;
+                       chunkCoord[i] = (gridCoord[i] - coordOffset) / 2;
+                       btClamp(chunkCoord[i], 0, gridChunkDim[i] - 1);
+                       btAssert(chunkCoord[i] < gridChunkDim[i]);
+               }
+               int iBatch = iPhase * params.maxNumBatchesPerPhase + chunkCoord[0] + chunkCoord[1] * gridChunkDim[0] + chunkCoord[2] * gridChunkDim[0] * gridChunkDim[1];
+               btAssert(iBatch >= 0 && iBatch < params.maxNumBatchesPerPhase * params.numPhases);
+               params.constraintBatchIds[iCon] = iBatch;
+       }
+}
+
+struct AssignConstraintsToGridBatchesLoop : public btIParallelForBody
+{
+       const AssignConstraintsToGridBatchesParams* m_params;
+
+       AssignConstraintsToGridBatchesLoop(const AssignConstraintsToGridBatchesParams& params)
+       {
+               m_params = &params;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               assignConstraintsToGridBatches(*m_params, iBegin, iEnd);
+       }
+};
+
+//
+// setupSpatialGridBatchesMt -- generate batches using a uniform 3D grid
+//
+/*
+
+Bodies are treated as 3D points at their center of mass. We only consider dynamic bodies at this stage,
+because only dynamic bodies are mutated when a constraint is solved, thus subject to race conditions.
+
+1. Compute a bounding box around all dynamic bodies
+2. Compute the maximum extent of all dynamic constraints. Each dynamic constraint is treated as a line segment, and we need the size of
+   box that will fully enclose any single dynamic constraint
+
+3. Establish the cell size of our grid, the cell size in each dimension must be at least as large as the dynamic constraints max-extent,
+   so that no dynamic constraint can span more than 2 cells of our grid on any axis of the grid. The cell size should be adjusted
+   larger in order to keep the total number of cells from being excessively high
+
+Key idea: Given that each constraint spans 1 or 2 grid cells in each dimension, we can handle all constraints by processing
+          in chunks of 2x2x2 cells with 8 different 1-cell offsets ((0,0,0),(0,0,1),(0,1,0),(0,1,1),(1,0,0)...).
+          For each of the 8 offsets, we create a phase, and for each 2x2x2 chunk with dynamic constraints becomes a batch in that phase.
+
+4. Once the grid is established, we can calculate for each constraint which phase and batch it belongs in.
+
+5. Do a merge small batches on the batches of each phase separately, to try to even out the sizes of batches
+
+Optionally, we can "collapse" one dimension of our 3D grid to turn it into a 2D grid, which reduces the number of phases
+to 4. With fewer phases, there are more constraints per phase and this makes it easier to create batches of a useful size.
+*/
+//
+static void setupSpatialGridBatchesMt(
+       btBatchedConstraints* batchedConstraints,
+       btAlignedObjectArray<char>* scratchMemory,
+       btConstraintArray* constraints,
+       const btAlignedObjectArray<btSolverBody>& bodies,
+       int minBatchSize,
+       int maxBatchSize,
+       bool use2DGrid)
+{
+       BT_PROFILE("setupSpatialGridBatchesMt");
+       const int numPhases = 8;
+       int numConstraints = constraints->size();
+       int numConstraintRows = constraints->size();
+
+       const int maxGridChunkCount = 128;
+       int allocNumBatchesPerPhase = maxGridChunkCount;
+       int minNumBatchesPerPhase = 16;
+       int allocNumBatches = allocNumBatchesPerPhase * numPhases;
+
+       btVector3* bodyPositions = NULL;
+       bool* bodyDynamicFlags = NULL;
+       btIntVec3* bodyGridCoords = NULL;
+       btBatchInfo* batches = NULL;
+       int* batchWork = NULL;
+       btBatchedConstraintInfo* conInfos = NULL;
+       int* constraintBatchIds = NULL;
+       int* constraintRowBatchIds = NULL;
+       {
+               PreallocatedMemoryHelper<10> memHelper;
+               memHelper.addChunk((void**)&bodyPositions, sizeof(btVector3) * bodies.size());
+               memHelper.addChunk((void**)&bodyDynamicFlags, sizeof(bool) * bodies.size());
+               memHelper.addChunk((void**)&bodyGridCoords, sizeof(btIntVec3) * bodies.size());
+               memHelper.addChunk((void**)&batches, sizeof(btBatchInfo) * allocNumBatches);
+               memHelper.addChunk((void**)&batchWork, sizeof(int) * allocNumBatches);
+               memHelper.addChunk((void**)&conInfos, sizeof(btBatchedConstraintInfo) * numConstraints);
+               memHelper.addChunk((void**)&constraintBatchIds, sizeof(int) * numConstraints);
+               memHelper.addChunk((void**)&constraintRowBatchIds, sizeof(int) * numConstraintRows);
+               size_t scratchSize = memHelper.getSizeToAllocate();
+               // if we need to reallocate
+               if (static_cast<size_t>(scratchMemory->capacity()) < scratchSize)
+               {
+                       // allocate 6.25% extra to avoid repeated reallocs
+                       scratchMemory->reserve(scratchSize + scratchSize / 16);
+               }
+               scratchMemory->resizeNoInitialize(scratchSize);
+               char* memPtr = &scratchMemory->at(0);
+               memHelper.setChunkPointers(memPtr);
+       }
+
+       numConstraints = initBatchedConstraintInfo(conInfos, constraints);
+
+       // compute bounding box around all dynamic bodies
+       // (could be done in parallel)
+       btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
+       btVector3 bboxMax = -bboxMin;
+       //int dynamicBodyCount = 0;
+       for (int i = 0; i < bodies.size(); ++i)
+       {
+               const btSolverBody& body = bodies[i];
+               btVector3 bodyPos = body.getWorldTransform().getOrigin();
+               bool isDynamic = (body.internalGetInvMass().x() > btScalar(0));
+               bodyPositions[i] = bodyPos;
+               bodyDynamicFlags[i] = isDynamic;
+               if (isDynamic)
+               {
+                       //dynamicBodyCount++;
+                       bboxMin.setMin(bodyPos);
+                       bboxMax.setMax(bodyPos);
+               }
+       }
+
+       // find max extent of all dynamic constraints
+       // (could be done in parallel)
+       btVector3 consExtent = findMaxDynamicConstraintExtent(bodyPositions, bodyDynamicFlags, conInfos, numConstraints, bodies.size());
+
+       btVector3 gridExtent = bboxMax - bboxMin;
+
+       gridExtent.setMax(btVector3(btScalar(1), btScalar(1), btScalar(1)));
+
+       btVector3 gridCellSize = consExtent;
+       int gridDim[3];
+       gridDim[0] = int(1.0 + gridExtent.x() / gridCellSize.x());
+       gridDim[1] = int(1.0 + gridExtent.y() / gridCellSize.y());
+       gridDim[2] = int(1.0 + gridExtent.z() / gridCellSize.z());
+
+       // if we can collapse an axis, it will cut our number of phases in half which could be more efficient
+       int phaseMask = 7;
+       bool collapseAxis = use2DGrid;
+       if (collapseAxis)
+       {
+               // pick the smallest axis to collapse, leaving us with the greatest number of cells in our grid
+               int iAxisToCollapse = 0;
+               int axisDim = gridDim[iAxisToCollapse];
+               //for each dimension
+               for (int i = 0; i < 3; ++i)
+               {
+                       if (gridDim[i] < axisDim)
+                       {
+                               iAxisToCollapse = i;
+                               axisDim = gridDim[i];
+                       }
+               }
+               // collapse it
+               gridCellSize[iAxisToCollapse] = gridExtent[iAxisToCollapse] * 2.0f;
+               phaseMask &= ~(1 << iAxisToCollapse);
+       }
+
+       int numGridChunks = 0;
+       btIntVec3 gridChunkDim;  // each chunk is 2x2x2 group of cells
+       while (true)
+       {
+               gridDim[0] = int(1.0 + gridExtent.x() / gridCellSize.x());
+               gridDim[1] = int(1.0 + gridExtent.y() / gridCellSize.y());
+               gridDim[2] = int(1.0 + gridExtent.z() / gridCellSize.z());
+               gridChunkDim[0] = btMax(1, (gridDim[0] + 0) / 2);
+               gridChunkDim[1] = btMax(1, (gridDim[1] + 0) / 2);
+               gridChunkDim[2] = btMax(1, (gridDim[2] + 0) / 2);
+               numGridChunks = gridChunkDim[0] * gridChunkDim[1] * gridChunkDim[2];
+               float nChunks = float(gridChunkDim[0]) * float(gridChunkDim[1]) * float(gridChunkDim[2]);  // suceptible to integer overflow
+               if (numGridChunks <= maxGridChunkCount && nChunks <= maxGridChunkCount)
+               {
+                       break;
+               }
+               gridCellSize *= 1.25;  // should roughly cut numCells in half
+       }
+       btAssert(numGridChunks <= maxGridChunkCount);
+       int maxNumBatchesPerPhase = numGridChunks;
+
+       // for each dynamic body, compute grid coords
+       btVector3 invGridCellSize = btVector3(1, 1, 1) / gridCellSize;
+       // (can be done in parallel)
+       for (int iBody = 0; iBody < bodies.size(); ++iBody)
+       {
+               btIntVec3& coords = bodyGridCoords[iBody];
+               if (bodyDynamicFlags[iBody])
+               {
+                       btVector3 v = (bodyPositions[iBody] - bboxMin) * invGridCellSize;
+                       coords.m_ints[0] = int(v.x());
+                       coords.m_ints[1] = int(v.y());
+                       coords.m_ints[2] = int(v.z());
+                       btAssert(coords.m_ints[0] >= 0 && coords.m_ints[0] < gridDim[0]);
+                       btAssert(coords.m_ints[1] >= 0 && coords.m_ints[1] < gridDim[1]);
+                       btAssert(coords.m_ints[2] >= 0 && coords.m_ints[2] < gridDim[2]);
+               }
+               else
+               {
+                       coords.m_ints[0] = -1;
+                       coords.m_ints[1] = -1;
+                       coords.m_ints[2] = -1;
+               }
+       }
+
+       for (int iPhase = 0; iPhase < numPhases; ++iPhase)
+       {
+               int batchBegin = iPhase * maxNumBatchesPerPhase;
+               int batchEnd = batchBegin + maxNumBatchesPerPhase;
+               for (int iBatch = batchBegin; iBatch < batchEnd; ++iBatch)
+               {
+                       btBatchInfo& batch = batches[iBatch];
+                       batch = btBatchInfo();
+               }
+       }
+
+       {
+               AssignConstraintsToGridBatchesParams params;
+               params.bodyDynamicFlags = bodyDynamicFlags;
+               params.bodyGridCoords = bodyGridCoords;
+               params.numBodies = bodies.size();
+               params.conInfos = conInfos;
+               params.constraintBatchIds = constraintBatchIds;
+               params.gridChunkDim = gridChunkDim;
+               params.maxNumBatchesPerPhase = maxNumBatchesPerPhase;
+               params.numPhases = numPhases;
+               params.phaseMask = phaseMask;
+               bool inParallel = true;
+               if (inParallel)
+               {
+                       AssignConstraintsToGridBatchesLoop loop(params);
+                       int grainSize = 250;
+                       btParallelFor(0, numConstraints, grainSize, loop);
+               }
+               else
+               {
+                       assignConstraintsToGridBatches(params, 0, numConstraints);
+               }
+       }
+       for (int iCon = 0; iCon < numConstraints; ++iCon)
+       {
+               const btBatchedConstraintInfo& con = conInfos[iCon];
+               int iBatch = constraintBatchIds[iCon];
+               btBatchInfo& batch = batches[iBatch];
+               batch.numConstraints += con.numConstraintRows;
+       }
+
+       for (int iPhase = 0; iPhase < numPhases; ++iPhase)
+       {
+               // if phase is legit,
+               if (iPhase == (iPhase & phaseMask))
+               {
+                       int iBeginBatch = iPhase * maxNumBatchesPerPhase;
+                       int iEndBatch = iBeginBatch + maxNumBatchesPerPhase;
+                       mergeSmallBatches(batches, iBeginBatch, iEndBatch, minBatchSize, maxBatchSize);
+               }
+       }
+       // all constraints have been assigned a batchId
+       updateConstraintBatchIdsForMergesMt(constraintBatchIds, numConstraints, batches, maxNumBatchesPerPhase * numPhases);
+
+       if (numConstraintRows > numConstraints)
+       {
+               expandConstraintRowsMt(&constraintRowBatchIds[0], &constraintBatchIds[0], &conInfos[0], numConstraints, numConstraintRows);
+       }
+       else
+       {
+               constraintRowBatchIds = constraintBatchIds;
+       }
+
+       writeOutBatches(batchedConstraints, constraintRowBatchIds, numConstraintRows, batches, batchWork, maxNumBatchesPerPhase, numPhases);
+       btAssert(batchedConstraints->validate(constraints, bodies));
+}
+
+static void setupSingleBatch(
+       btBatchedConstraints* bc,
+       int numConstraints)
+{
+       BT_PROFILE("setupSingleBatch");
+       typedef btBatchedConstraints::Range Range;
+
+       bc->m_constraintIndices.resize(numConstraints);
+       for (int i = 0; i < numConstraints; ++i)
+       {
+               bc->m_constraintIndices[i] = i;
+       }
+
+       bc->m_batches.resizeNoInitialize(0);
+       bc->m_phases.resizeNoInitialize(0);
+       bc->m_phaseOrder.resizeNoInitialize(0);
+       bc->m_phaseGrainSize.resizeNoInitialize(0);
+
+       if (numConstraints > 0)
+       {
+               bc->m_batches.push_back(Range(0, numConstraints));
+               bc->m_phases.push_back(Range(0, 1));
+               bc->m_phaseOrder.push_back(0);
+               bc->m_phaseGrainSize.push_back(1);
+       }
+}
+
+void btBatchedConstraints::setup(
+       btConstraintArray* constraints,
+       const btAlignedObjectArray<btSolverBody>& bodies,
+       BatchingMethod batchingMethod,
+       int minBatchSize,
+       int maxBatchSize,
+       btAlignedObjectArray<char>* scratchMemory)
+{
+       if (constraints->size() >= minBatchSize * 4)
+       {
+               bool use2DGrid = batchingMethod == BATCHING_METHOD_SPATIAL_GRID_2D;
+               setupSpatialGridBatchesMt(this, scratchMemory, constraints, bodies, minBatchSize, maxBatchSize, use2DGrid);
+               if (s_debugDrawBatches)
+               {
+                       debugDrawAllBatches(this, constraints, bodies);
+               }
+       }
+       else
+       {
+               setupSingleBatch(this, constraints->size());
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btBatchedConstraints.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btBatchedConstraints.h
new file mode 100644 (file)
index 0000000..651df7a
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_BATCHED_CONSTRAINTS_H
+#define BT_BATCHED_CONSTRAINTS_H
+
+#include "LinearMath/btThreads.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
+#include "BulletDynamics/ConstraintSolver/btSolverConstraint.h"
+
+class btIDebugDraw;
+
+struct btBatchedConstraints
+{
+       enum BatchingMethod
+       {
+               BATCHING_METHOD_SPATIAL_GRID_2D,
+               BATCHING_METHOD_SPATIAL_GRID_3D,
+               BATCHING_METHOD_COUNT
+       };
+       struct Range
+       {
+               int begin;
+               int end;
+
+               Range() : begin(0), end(0) {}
+               Range(int _beg, int _end) : begin(_beg), end(_end) {}
+       };
+
+       btAlignedObjectArray<int> m_constraintIndices;
+       btAlignedObjectArray<Range> m_batches;        // each batch is a range of indices in the m_constraintIndices array
+       btAlignedObjectArray<Range> m_phases;         // each phase is range of indices in the m_batches array
+       btAlignedObjectArray<char> m_phaseGrainSize;  // max grain size for each phase
+       btAlignedObjectArray<int> m_phaseOrder;       // phases can be done in any order, so we can randomize the order here
+       btIDebugDraw* m_debugDrawer;
+
+       static bool s_debugDrawBatches;
+
+       btBatchedConstraints() { m_debugDrawer = NULL; }
+       void setup(btConstraintArray* constraints,
+                          const btAlignedObjectArray<btSolverBody>& bodies,
+                          BatchingMethod batchingMethod,
+                          int minBatchSize,
+                          int maxBatchSize,
+                          btAlignedObjectArray<char>* scratchMemory);
+       bool validate(btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies) const;
+};
+
+#endif  // BT_BATCHED_CONSTRAINTS_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
new file mode 100644 (file)
index 0000000..ac046aa
--- /dev/null
@@ -0,0 +1,1116 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+Written by: Marcus Hennix
+*/
+
+#include "btConeTwistConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMinMax.h"
+#include <cmath>
+#include <new>
+
+//#define CONETWIST_USE_OBSOLETE_SOLVER true
+#define CONETWIST_USE_OBSOLETE_SOLVER false
+#define CONETWIST_DEF_FIX_THRESH btScalar(.05f)
+
+SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld)
+{
+       btVector3 vec = axis * invInertiaWorld;
+       return axis.dot(vec);
+}
+
+btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA, btRigidBody& rbB,
+                                                                                        const btTransform& rbAFrame, const btTransform& rbBFrame)
+       : btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA, rbB), m_rbAFrame(rbAFrame), m_rbBFrame(rbBFrame), m_angularOnly(false), m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
+{
+       init();
+}
+
+btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA, const btTransform& rbAFrame)
+       : btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA), m_rbAFrame(rbAFrame), m_angularOnly(false), m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
+{
+       m_rbBFrame = m_rbAFrame;
+       m_rbBFrame.setOrigin(btVector3(0., 0., 0.));
+       init();
+}
+
+void btConeTwistConstraint::init()
+{
+       m_angularOnly = false;
+       m_solveTwistLimit = false;
+       m_solveSwingLimit = false;
+       m_bMotorEnabled = false;
+       m_maxMotorImpulse = btScalar(-1);
+
+       setLimit(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+       m_damping = btScalar(0.01);
+       m_fixThresh = CONETWIST_DEF_FIX_THRESH;
+       m_flags = 0;
+       m_linCFM = btScalar(0.f);
+       m_linERP = btScalar(0.7f);
+       m_angCFM = btScalar(0.f);
+}
+
+void btConeTwistConstraint::getInfo1(btConstraintInfo1* info)
+{
+       if (m_useSolveConstraintObsolete)
+       {
+               info->m_numConstraintRows = 0;
+               info->nub = 0;
+       }
+       else
+       {
+               info->m_numConstraintRows = 3;
+               info->nub = 3;
+               calcAngleInfo2(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
+               if (m_solveSwingLimit)
+               {
+                       info->m_numConstraintRows++;
+                       info->nub--;
+                       if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+                       {
+                               info->m_numConstraintRows++;
+                               info->nub--;
+                       }
+               }
+               if (m_solveTwistLimit)
+               {
+                       info->m_numConstraintRows++;
+                       info->nub--;
+               }
+       }
+}
+
+void btConeTwistConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
+{
+       //always reserve 6 rows: object transform is not available on SPU
+       info->m_numConstraintRows = 6;
+       info->nub = 0;
+}
+
+void btConeTwistConstraint::getInfo2(btConstraintInfo2* info)
+{
+       getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
+}
+
+void btConeTwistConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB)
+{
+       calcAngleInfo2(transA, transB, invInertiaWorldA, invInertiaWorldB);
+
+       btAssert(!m_useSolveConstraintObsolete);
+       // set jacobian
+       info->m_J1linearAxis[0] = 1;
+       info->m_J1linearAxis[info->rowskip + 1] = 1;
+       info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
+       btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin();
+       {
+               btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
+               btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + info->rowskip);
+               btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * info->rowskip);
+               btVector3 a1neg = -a1;
+               a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+       info->m_J2linearAxis[0] = -1;
+       info->m_J2linearAxis[info->rowskip + 1] = -1;
+       info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
+       btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin();
+       {
+               btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
+               btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + info->rowskip);
+               btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * info->rowskip);
+               a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+       // set right hand side
+       btScalar linERP = (m_flags & BT_CONETWIST_FLAGS_LIN_ERP) ? m_linERP : info->erp;
+       btScalar k = info->fps * linERP;
+       int j;
+       for (j = 0; j < 3; j++)
+       {
+               info->m_constraintError[j * info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]);
+               info->m_lowerLimit[j * info->rowskip] = -SIMD_INFINITY;
+               info->m_upperLimit[j * info->rowskip] = SIMD_INFINITY;
+               if (m_flags & BT_CONETWIST_FLAGS_LIN_CFM)
+               {
+                       info->cfm[j * info->rowskip] = m_linCFM;
+               }
+       }
+       int row = 3;
+       int srow = row * info->rowskip;
+       btVector3 ax1;
+       // angular limits
+       if (m_solveSwingLimit)
+       {
+               btScalar* J1 = info->m_J1angularAxis;
+               btScalar* J2 = info->m_J2angularAxis;
+               if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+               {
+                       btTransform trA = transA * m_rbAFrame;
+                       btVector3 p = trA.getBasis().getColumn(1);
+                       btVector3 q = trA.getBasis().getColumn(2);
+                       int srow1 = srow + info->rowskip;
+                       J1[srow + 0] = p[0];
+                       J1[srow + 1] = p[1];
+                       J1[srow + 2] = p[2];
+                       J1[srow1 + 0] = q[0];
+                       J1[srow1 + 1] = q[1];
+                       J1[srow1 + 2] = q[2];
+                       J2[srow + 0] = -p[0];
+                       J2[srow + 1] = -p[1];
+                       J2[srow + 2] = -p[2];
+                       J2[srow1 + 0] = -q[0];
+                       J2[srow1 + 1] = -q[1];
+                       J2[srow1 + 2] = -q[2];
+                       btScalar fact = info->fps * m_relaxationFactor;
+                       info->m_constraintError[srow] = fact * m_swingAxis.dot(p);
+                       info->m_constraintError[srow1] = fact * m_swingAxis.dot(q);
+                       info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                       info->m_upperLimit[srow] = SIMD_INFINITY;
+                       info->m_lowerLimit[srow1] = -SIMD_INFINITY;
+                       info->m_upperLimit[srow1] = SIMD_INFINITY;
+                       srow = srow1 + info->rowskip;
+               }
+               else
+               {
+                       ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor;
+                       J1[srow + 0] = ax1[0];
+                       J1[srow + 1] = ax1[1];
+                       J1[srow + 2] = ax1[2];
+                       J2[srow + 0] = -ax1[0];
+                       J2[srow + 1] = -ax1[1];
+                       J2[srow + 2] = -ax1[2];
+                       btScalar k = info->fps * m_biasFactor;
+
+                       info->m_constraintError[srow] = k * m_swingCorrection;
+                       if (m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
+                       {
+                               info->cfm[srow] = m_angCFM;
+                       }
+                       // m_swingCorrection is always positive or 0
+                       info->m_lowerLimit[srow] = 0;
+                       info->m_upperLimit[srow] = (m_bMotorEnabled && m_maxMotorImpulse >= 0.0f) ? m_maxMotorImpulse : SIMD_INFINITY;
+                       srow += info->rowskip;
+               }
+       }
+       if (m_solveTwistLimit)
+       {
+               ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor;
+               btScalar* J1 = info->m_J1angularAxis;
+               btScalar* J2 = info->m_J2angularAxis;
+               J1[srow + 0] = ax1[0];
+               J1[srow + 1] = ax1[1];
+               J1[srow + 2] = ax1[2];
+               J2[srow + 0] = -ax1[0];
+               J2[srow + 1] = -ax1[1];
+               J2[srow + 2] = -ax1[2];
+               btScalar k = info->fps * m_biasFactor;
+               info->m_constraintError[srow] = k * m_twistCorrection;
+               if (m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
+               {
+                       info->cfm[srow] = m_angCFM;
+               }
+               if (m_twistSpan > 0.0f)
+               {
+                       if (m_twistCorrection > 0.0f)
+                       {
+                               info->m_lowerLimit[srow] = 0;
+                               info->m_upperLimit[srow] = SIMD_INFINITY;
+                       }
+                       else
+                       {
+                               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                               info->m_upperLimit[srow] = 0;
+                       }
+               }
+               else
+               {
+                       info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                       info->m_upperLimit[srow] = SIMD_INFINITY;
+               }
+               srow += info->rowskip;
+       }
+}
+
+void btConeTwistConstraint::buildJacobian()
+{
+       if (m_useSolveConstraintObsolete)
+       {
+               m_appliedImpulse = btScalar(0.);
+               m_accTwistLimitImpulse = btScalar(0.);
+               m_accSwingLimitImpulse = btScalar(0.);
+               m_accMotorImpulse = btVector3(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++)
+                       {
+                               new (&m_jac[i]) btJacobianEntry(
+                                       m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+                                       m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+                                       pivotAInW - m_rbA.getCenterOfMassPosition(),
+                                       pivotBInW - m_rbB.getCenterOfMassPosition(),
+                                       normal[i],
+                                       m_rbA.getInvInertiaDiagLocal(),
+                                       m_rbA.getInvMass(),
+                                       m_rbB.getInvInertiaDiagLocal(),
+                                       m_rbB.getInvMass());
+                       }
+               }
+
+               calcAngleInfo2(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
+       }
+}
+
+void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA, btSolverBody& bodyB, btScalar timeStep)
+{
+#ifndef __SPU__
+       if (m_useSolveConstraintObsolete)
+       {
+               btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
+               btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
+
+               btScalar tau = btScalar(0.3);
+
+               //linear part
+               if (!m_angularOnly)
+               {
+                       btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
+                       btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
+
+                       btVector3 vel1;
+                       bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1, vel1);
+                       btVector3 vel2;
+                       bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2, vel2);
+                       btVector3 vel = vel1 - vel2;
+
+                       for (int i = 0; i < 3; i++)
+                       {
+                               const btVector3& normal = m_jac[i].m_linearJointAxis;
+                               btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal();
+
+                               btScalar rel_vel;
+                               rel_vel = normal.dot(vel);
+                               //positional error (zeroth order error)
+                               btScalar depth = -(pivotAInW - pivotBInW).dot(normal);  //this is the error projected on the normal
+                               btScalar impulse = depth * tau / timeStep * jacDiagABInv - rel_vel * jacDiagABInv;
+                               m_appliedImpulse += impulse;
+
+                               btVector3 ftorqueAxis1 = rel_pos1.cross(normal);
+                               btVector3 ftorqueAxis2 = rel_pos2.cross(normal);
+                               bodyA.internalApplyImpulse(normal * m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld() * ftorqueAxis1, impulse);
+                               bodyB.internalApplyImpulse(normal * m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld() * ftorqueAxis2, -impulse);
+                       }
+               }
+
+               // apply motor
+               if (m_bMotorEnabled)
+               {
+                       // compute current and predicted transforms
+                       btTransform trACur = m_rbA.getCenterOfMassTransform();
+                       btTransform trBCur = m_rbB.getCenterOfMassTransform();
+                       btVector3 omegaA;
+                       bodyA.internalGetAngularVelocity(omegaA);
+                       btVector3 omegaB;
+                       bodyB.internalGetAngularVelocity(omegaB);
+                       btTransform trAPred;
+                       trAPred.setIdentity();
+                       btVector3 zerovec(0, 0, 0);
+                       btTransformUtil::integrateTransform(
+                               trACur, zerovec, omegaA, timeStep, trAPred);
+                       btTransform trBPred;
+                       trBPred.setIdentity();
+                       btTransformUtil::integrateTransform(
+                               trBCur, zerovec, omegaB, timeStep, trBPred);
+
+                       // compute desired transforms in world
+                       btTransform trPose(m_qTarget);
+                       btTransform trABDes = m_rbBFrame * trPose * m_rbAFrame.inverse();
+                       btTransform trADes = trBPred * trABDes;
+                       btTransform trBDes = trAPred * trABDes.inverse();
+
+                       // compute desired omegas in world
+                       btVector3 omegaADes, omegaBDes;
+
+                       btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes);
+                       btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes);
+
+                       // compute delta omegas
+                       btVector3 dOmegaA = omegaADes - omegaA;
+                       btVector3 dOmegaB = omegaBDes - omegaB;
+
+                       // compute weighted avg axis of dOmega (weighting based on inertias)
+                       btVector3 axisA, axisB;
+                       btScalar kAxisAInv = 0, kAxisBInv = 0;
+
+                       if (dOmegaA.length2() > SIMD_EPSILON)
+                       {
+                               axisA = dOmegaA.normalized();
+                               kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(axisA);
+                       }
+
+                       if (dOmegaB.length2() > SIMD_EPSILON)
+                       {
+                               axisB = dOmegaB.normalized();
+                               kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(axisB);
+                       }
+
+                       btVector3 avgAxis = kAxisAInv * axisA + kAxisBInv * axisB;
+
+                       static bool bDoTorque = true;
+                       if (bDoTorque && avgAxis.length2() > SIMD_EPSILON)
+                       {
+                               avgAxis.normalize();
+                               kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(avgAxis);
+                               kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(avgAxis);
+                               btScalar kInvCombined = kAxisAInv + kAxisBInv;
+
+                               btVector3 impulse = (kAxisAInv * dOmegaA - kAxisBInv * dOmegaB) /
+                                                                       (kInvCombined * kInvCombined);
+
+                               if (m_maxMotorImpulse >= 0)
+                               {
+                                       btScalar fMaxImpulse = m_maxMotorImpulse;
+                                       if (m_bNormalizedMotorStrength)
+                                               fMaxImpulse = fMaxImpulse / kAxisAInv;
+
+                                       btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse;
+                                       btScalar newUnclampedMag = newUnclampedAccImpulse.length();
+                                       if (newUnclampedMag > fMaxImpulse)
+                                       {
+                                               newUnclampedAccImpulse.normalize();
+                                               newUnclampedAccImpulse *= fMaxImpulse;
+                                               impulse = newUnclampedAccImpulse - m_accMotorImpulse;
+                                       }
+                                       m_accMotorImpulse += impulse;
+                               }
+
+                               btScalar impulseMag = impulse.length();
+                               btVector3 impulseAxis = impulse / impulseMag;
+
+                               bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * impulseAxis, impulseMag);
+                               bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * impulseAxis, -impulseMag);
+                       }
+               }
+               else if (m_damping > SIMD_EPSILON)  // no motor: do a little damping
+               {
+                       btVector3 angVelA;
+                       bodyA.internalGetAngularVelocity(angVelA);
+                       btVector3 angVelB;
+                       bodyB.internalGetAngularVelocity(angVelB);
+                       btVector3 relVel = angVelB - angVelA;
+                       if (relVel.length2() > SIMD_EPSILON)
+                       {
+                               btVector3 relVelAxis = relVel.normalized();
+                               btScalar m_kDamping = btScalar(1.) /
+                                                                         (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) +
+                                                                          getRigidBodyB().computeAngularImpulseDenominator(relVelAxis));
+                               btVector3 impulse = m_damping * m_kDamping * relVel;
+
+                               btScalar impulseMag = impulse.length();
+                               btVector3 impulseAxis = impulse / impulseMag;
+                               bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * impulseAxis, impulseMag);
+                               bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * impulseAxis, -impulseMag);
+                       }
+               }
+
+               // joint limits
+               {
+                       ///solve angular part
+                       btVector3 angVelA;
+                       bodyA.internalGetAngularVelocity(angVelA);
+                       btVector3 angVelB;
+                       bodyB.internalGetAngularVelocity(angVelB);
+
+                       // solve swing limit
+                       if (m_solveSwingLimit)
+                       {
+                               btScalar amplitude = m_swingLimitRatio * m_swingCorrection * m_biasFactor / timeStep;
+                               btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis);
+                               if (relSwingVel > 0)
+                                       amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor;
+                               btScalar impulseMag = amplitude * m_kSwing;
+
+                               // Clamp the accumulated impulse
+                               btScalar temp = m_accSwingLimitImpulse;
+                               m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0));
+                               impulseMag = m_accSwingLimitImpulse - temp;
+
+                               btVector3 impulse = m_swingAxis * impulseMag;
+
+                               // don't let cone response affect twist
+                               // (this can happen since body A's twist doesn't match body B's AND we use an elliptical cone limit)
+                               {
+                                       btVector3 impulseTwistCouple = impulse.dot(m_twistAxisA) * m_twistAxisA;
+                                       btVector3 impulseNoTwistCouple = impulse - impulseTwistCouple;
+                                       impulse = impulseNoTwistCouple;
+                               }
+
+                               impulseMag = impulse.length();
+                               btVector3 noTwistSwingAxis = impulse / impulseMag;
+
+                               bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * noTwistSwingAxis, impulseMag);
+                               bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * noTwistSwingAxis, -impulseMag);
+                       }
+
+                       // solve twist limit
+                       if (m_solveTwistLimit)
+                       {
+                               btScalar amplitude = m_twistLimitRatio * m_twistCorrection * m_biasFactor / timeStep;
+                               btScalar relTwistVel = (angVelB - angVelA).dot(m_twistAxis);
+                               if (relTwistVel > 0)  // only damp when moving towards limit (m_twistAxis flipping is important)
+                                       amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor;
+                               btScalar impulseMag = amplitude * m_kTwist;
+
+                               // Clamp the accumulated impulse
+                               btScalar temp = m_accTwistLimitImpulse;
+                               m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0));
+                               impulseMag = m_accTwistLimitImpulse - temp;
+
+                               //              btVector3 impulse = m_twistAxis * impulseMag;
+
+                               bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * m_twistAxis, impulseMag);
+                               bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * m_twistAxis, -impulseMag);
+                       }
+               }
+       }
+#else
+       btAssert(0);
+#endif  //__SPU__
+}
+
+void btConeTwistConstraint::updateRHS(btScalar timeStep)
+{
+       (void)timeStep;
+}
+
+#ifndef __SPU__
+void btConeTwistConstraint::calcAngleInfo()
+{
+       m_swingCorrection = btScalar(0.);
+       m_twistLimitSign = btScalar(0.);
+       m_solveTwistLimit = false;
+       m_solveSwingLimit = false;
+
+       btVector3 b1Axis1(0, 0, 0), b1Axis2(0, 0, 0), b1Axis3(0, 0, 0);
+       btVector3 b2Axis1(0, 0, 0), b2Axis2(0, 0, 0);
+
+       b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0);
+       b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0);
+
+       btScalar swing1 = btScalar(0.), swing2 = btScalar(0.);
+
+       btScalar swx = btScalar(0.), swy = btScalar(0.);
+       btScalar thresh = btScalar(10.);
+       btScalar fact;
+
+       // Get Frame into world space
+       if (m_swingSpan1 >= btScalar(0.05f))
+       {
+               b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1);
+               swx = b2Axis1.dot(b1Axis1);
+               swy = b2Axis1.dot(b1Axis2);
+               swing1 = btAtan2Fast(swy, swx);
+               fact = (swy * swy + swx * swx) * thresh * thresh;
+               fact = fact / (fact + btScalar(1.0));
+               swing1 *= fact;
+       }
+
+       if (m_swingSpan2 >= btScalar(0.05f))
+       {
+               b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2);
+               swx = b2Axis1.dot(b1Axis1);
+               swy = b2Axis1.dot(b1Axis3);
+               swing2 = btAtan2Fast(swy, swx);
+               fact = (swy * swy + swx * swx) * thresh * thresh;
+               fact = fact / (fact + btScalar(1.0));
+               swing2 *= fact;
+       }
+
+       btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1 * m_swingSpan1);
+       btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2 * m_swingSpan2);
+       btScalar EllipseAngle = btFabs(swing1 * swing1) * RMaxAngle1Sq + btFabs(swing2 * swing2) * RMaxAngle2Sq;
+
+       if (EllipseAngle > 1.0f)
+       {
+               m_swingCorrection = EllipseAngle - 1.0f;
+               m_solveSwingLimit = true;
+               // Calculate necessary axis & factors
+               m_swingAxis = b2Axis1.cross(b1Axis2 * b2Axis1.dot(b1Axis2) + b1Axis3 * b2Axis1.dot(b1Axis3));
+               m_swingAxis.normalize();
+               btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f;
+               m_swingAxis *= swingAxisSign;
+       }
+
+       // Twist limits
+       if (m_twistSpan >= btScalar(0.))
+       {
+               btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1);
+               btQuaternion rotationArc = shortestArcQuat(b2Axis1, b1Axis1);
+               btVector3 TwistRef = quatRotate(rotationArc, b2Axis2);
+               btScalar twist = btAtan2Fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2));
+               m_twistAngle = twist;
+
+               //              btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.);
+               btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.);
+               if (twist <= -m_twistSpan * lockedFreeFactor)
+               {
+                       m_twistCorrection = -(twist + m_twistSpan);
+                       m_solveTwistLimit = true;
+                       m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
+                       m_twistAxis.normalize();
+                       m_twistAxis *= -1.0f;
+               }
+               else if (twist > m_twistSpan * lockedFreeFactor)
+               {
+                       m_twistCorrection = (twist - m_twistSpan);
+                       m_solveTwistLimit = true;
+                       m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
+                       m_twistAxis.normalize();
+               }
+       }
+}
+#endif  //__SPU__
+
+static btVector3 vTwist(1, 0, 0);  // twist axis in constraint's space
+
+void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB)
+{
+       m_swingCorrection = btScalar(0.);
+       m_twistLimitSign = btScalar(0.);
+       m_solveTwistLimit = false;
+       m_solveSwingLimit = false;
+       // compute rotation of A wrt B (in constraint space)
+       if (m_bMotorEnabled && (!m_useSolveConstraintObsolete))
+       {  // it is assumed that setMotorTarget() was alredy called
+               // and motor target m_qTarget is within constraint limits
+               // TODO : split rotation to pure swing and pure twist
+               // compute desired transforms in world
+               btTransform trPose(m_qTarget);
+               btTransform trA = transA * m_rbAFrame;
+               btTransform trB = transB * m_rbBFrame;
+               btTransform trDeltaAB = trB * trPose * trA.inverse();
+               btQuaternion qDeltaAB = trDeltaAB.getRotation();
+               btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z());
+               btScalar swingAxisLen2 = swingAxis.length2();
+               if (btFuzzyZero(swingAxisLen2))
+               {
+                       return;
+               }
+               m_swingAxis = swingAxis;
+               m_swingAxis.normalize();
+               m_swingCorrection = qDeltaAB.getAngle();
+               if (!btFuzzyZero(m_swingCorrection))
+               {
+                       m_solveSwingLimit = true;
+               }
+               return;
+       }
+
+       {
+               // compute rotation of A wrt B (in constraint space)
+               btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation();
+               btQuaternion qB = transB.getRotation() * m_rbBFrame.getRotation();
+               btQuaternion qAB = qB.inverse() * qA;
+               // split rotation into cone and twist
+               // (all this is done from B's perspective. Maybe I should be averaging axes...)
+               btVector3 vConeNoTwist = quatRotate(qAB, vTwist);
+               vConeNoTwist.normalize();
+               btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist);
+               qABCone.normalize();
+               btQuaternion qABTwist = qABCone.inverse() * qAB;
+               qABTwist.normalize();
+
+               if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh)
+               {
+                       btScalar swingAngle, swingLimit = 0;
+                       btVector3 swingAxis;
+                       computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit);
+
+                       if (swingAngle > swingLimit * m_limitSoftness)
+                       {
+                               m_solveSwingLimit = true;
+
+                               // compute limit ratio: 0->1, where
+                               // 0 == beginning of soft limit
+                               // 1 == hard/real limit
+                               m_swingLimitRatio = 1.f;
+                               if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON)
+                               {
+                                       m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness) /
+                                                                               (swingLimit - swingLimit * m_limitSoftness);
+                               }
+
+                               // swing correction tries to get back to soft limit
+                               m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness);
+
+                               // adjustment of swing axis (based on ellipse normal)
+                               adjustSwingAxisToUseEllipseNormal(swingAxis);
+
+                               // Calculate necessary axis & factors
+                               m_swingAxis = quatRotate(qB, -swingAxis);
+
+                               m_twistAxisA.setValue(0, 0, 0);
+
+                               m_kSwing = btScalar(1.) /
+                                                  (computeAngularImpulseDenominator(m_swingAxis, invInertiaWorldA) +
+                                                       computeAngularImpulseDenominator(m_swingAxis, invInertiaWorldB));
+                       }
+               }
+               else
+               {
+                       // you haven't set any limits;
+                       // or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?)
+                       // anyway, we have either hinge or fixed joint
+                       btVector3 ivA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
+                       btVector3 jvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
+                       btVector3 kvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(2);
+                       btVector3 ivB = transB.getBasis() * m_rbBFrame.getBasis().getColumn(0);
+                       btVector3 target;
+                       btScalar x = ivB.dot(ivA);
+                       btScalar y = ivB.dot(jvA);
+                       btScalar z = ivB.dot(kvA);
+                       if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+                       {  // fixed. We'll need to add one more row to constraint
+                               if ((!btFuzzyZero(y)) || (!(btFuzzyZero(z))))
+                               {
+                                       m_solveSwingLimit = true;
+                                       m_swingAxis = -ivB.cross(ivA);
+                               }
+                       }
+                       else
+                       {
+                               if (m_swingSpan1 < m_fixThresh)
+                               {  // hinge around Y axis
+                                       //                                      if(!(btFuzzyZero(y)))
+                                       if ((!(btFuzzyZero(x))) || (!(btFuzzyZero(z))))
+                                       {
+                                               m_solveSwingLimit = true;
+                                               if (m_swingSpan2 >= m_fixThresh)
+                                               {
+                                                       y = btScalar(0.f);
+                                                       btScalar span2 = btAtan2(z, x);
+                                                       if (span2 > m_swingSpan2)
+                                                       {
+                                                               x = btCos(m_swingSpan2);
+                                                               z = btSin(m_swingSpan2);
+                                                       }
+                                                       else if (span2 < -m_swingSpan2)
+                                                       {
+                                                               x = btCos(m_swingSpan2);
+                                                               z = -btSin(m_swingSpan2);
+                                                       }
+                                               }
+                                       }
+                               }
+                               else
+                               {  // hinge around Z axis
+                                       //                                      if(!btFuzzyZero(z))
+                                       if ((!(btFuzzyZero(x))) || (!(btFuzzyZero(y))))
+                                       {
+                                               m_solveSwingLimit = true;
+                                               if (m_swingSpan1 >= m_fixThresh)
+                                               {
+                                                       z = btScalar(0.f);
+                                                       btScalar span1 = btAtan2(y, x);
+                                                       if (span1 > m_swingSpan1)
+                                                       {
+                                                               x = btCos(m_swingSpan1);
+                                                               y = btSin(m_swingSpan1);
+                                                       }
+                                                       else if (span1 < -m_swingSpan1)
+                                                       {
+                                                               x = btCos(m_swingSpan1);
+                                                               y = -btSin(m_swingSpan1);
+                                                       }
+                                               }
+                                       }
+                               }
+                               target[0] = x * ivA[0] + y * jvA[0] + z * kvA[0];
+                               target[1] = x * ivA[1] + y * jvA[1] + z * kvA[1];
+                               target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2];
+                               target.normalize();
+                               m_swingAxis = -ivB.cross(target);
+                               m_swingCorrection = m_swingAxis.length();
+
+                               if (!btFuzzyZero(m_swingCorrection))
+                                       m_swingAxis.normalize();
+                       }
+               }
+
+               if (m_twistSpan >= btScalar(0.f))
+               {
+                       btVector3 twistAxis;
+                       computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis);
+
+                       if (m_twistAngle > m_twistSpan * m_limitSoftness)
+                       {
+                               m_solveTwistLimit = true;
+
+                               m_twistLimitRatio = 1.f;
+                               if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON)
+                               {
+                                       m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness) /
+                                                                               (m_twistSpan - m_twistSpan * m_limitSoftness);
+                               }
+
+                               // twist correction tries to get back to soft limit
+                               m_twistCorrection = m_twistAngle - (m_twistSpan * m_limitSoftness);
+
+                               m_twistAxis = quatRotate(qB, -twistAxis);
+
+                               m_kTwist = btScalar(1.) /
+                                                  (computeAngularImpulseDenominator(m_twistAxis, invInertiaWorldA) +
+                                                       computeAngularImpulseDenominator(m_twistAxis, invInertiaWorldB));
+                       }
+
+                       if (m_solveSwingLimit)
+                               m_twistAxisA = quatRotate(qA, -twistAxis);
+               }
+               else
+               {
+                       m_twistAngle = btScalar(0.f);
+               }
+       }
+}
+
+// given a cone rotation in constraint space, (pre: twist must already be removed)
+// this method computes its corresponding swing angle and axis.
+// more interestingly, it computes the cone/swing limit (angle) for this cone "pose".
+void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
+                                                                                                btScalar& swingAngle,   // out
+                                                                                                btVector3& vSwingAxis,  // out
+                                                                                                btScalar& swingLimit)   // out
+{
+       swingAngle = qCone.getAngle();
+       if (swingAngle > SIMD_EPSILON)
+       {
+               vSwingAxis = btVector3(qCone.x(), qCone.y(), qCone.z());
+               vSwingAxis.normalize();
+#if 0
+        // non-zero twist?! this should never happen.
+       btAssert(fabs(vSwingAxis.x()) <= SIMD_EPSILON));
+#endif
+
+               // Compute limit for given swing. tricky:
+               // Given a swing axis, we're looking for the intersection with the bounding cone ellipse.
+               // (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.)
+
+               // For starters, compute the direction from center to surface of ellipse.
+               // This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis.
+               // (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.)
+               btScalar xEllipse = vSwingAxis.y();
+               btScalar yEllipse = -vSwingAxis.z();
+
+               // Now, we use the slope of the vector (using x/yEllipse) and find the length
+               // of the line that intersects the ellipse:
+               //  x^2   y^2
+               //  --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits)
+               //  a^2   b^2
+               // Do the math and it should be clear.
+
+               swingLimit = m_swingSpan1;  // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1
+               if (fabs(xEllipse) > SIMD_EPSILON)
+               {
+                       btScalar surfaceSlope2 = (yEllipse * yEllipse) / (xEllipse * xEllipse);
+                       btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
+                       norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
+                       btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
+                       swingLimit = std::sqrt(swingLimit2);
+               }
+
+               // test!
+               /*swingLimit = m_swingSpan2;
+               if (fabs(vSwingAxis.z()) > SIMD_EPSILON)
+               {
+               btScalar mag_2 = m_swingSpan1*m_swingSpan1 + m_swingSpan2*m_swingSpan2;
+               btScalar sinphi = m_swingSpan2 / sqrt(mag_2);
+               btScalar phi = asin(sinphi);
+               btScalar theta = atan2(fabs(vSwingAxis.y()),fabs(vSwingAxis.z()));
+               btScalar alpha = 3.14159f - theta - phi;
+               btScalar sinalpha = sin(alpha);
+               swingLimit = m_swingSpan1 * sinphi/sinalpha;
+               }*/
+       }
+       else if (swingAngle < 0)
+       {
+               // this should never happen!
+#if 0
+        btAssert(0);
+#endif
+       }
+}
+
+btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const
+{
+       // compute x/y in ellipse using cone angle (0 -> 2*PI along surface of cone)
+       btScalar xEllipse = btCos(fAngleInRadians);
+       btScalar yEllipse = btSin(fAngleInRadians);
+
+       // Use the slope of the vector (using x/yEllipse) and find the length
+       // of the line that intersects the ellipse:
+       //  x^2   y^2
+       //  --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits)
+       //  a^2   b^2
+       // Do the math and it should be clear.
+
+       btScalar swingLimit = m_swingSpan1;  // if xEllipse == 0, just use axis b (1)
+       if (fabs(xEllipse) > SIMD_EPSILON)
+       {
+               btScalar surfaceSlope2 = (yEllipse * yEllipse) / (xEllipse * xEllipse);
+               btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
+               norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
+               btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
+               swingLimit = std::sqrt(swingLimit2);
+       }
+
+       // convert into point in constraint space:
+       // note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively
+       btVector3 vSwingAxis(0, xEllipse, -yEllipse);
+       btQuaternion qSwing(vSwingAxis, swingLimit);
+       btVector3 vPointInConstraintSpace(fLength, 0, 0);
+       return quatRotate(qSwing, vPointInConstraintSpace);
+}
+
+// given a twist rotation in constraint space, (pre: cone must already be removed)
+// this method computes its corresponding angle and axis.
+void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist,
+                                                                                                 btScalar& twistAngle,   // out
+                                                                                                 btVector3& vTwistAxis)  // out
+{
+       btQuaternion qMinTwist = qTwist;
+       twistAngle = qTwist.getAngle();
+
+       if (twistAngle > SIMD_PI)  // long way around. flip quat and recalculate.
+       {
+               qMinTwist = -(qTwist);
+               twistAngle = qMinTwist.getAngle();
+       }
+       if (twistAngle < 0)
+       {
+               // this should never happen
+#if 0
+        btAssert(0);
+#endif
+       }
+
+       vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z());
+       if (twistAngle > SIMD_EPSILON)
+               vTwistAxis.normalize();
+}
+
+void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const
+{
+       // the swing axis is computed as the "twist-free" cone rotation,
+       // but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2).
+       // so, if we're outside the limits, the closest way back inside the cone isn't
+       // along the vector back to the center. better (and more stable) to use the ellipse normal.
+
+       // convert swing axis to direction from center to surface of ellipse
+       // (ie. rotate 2D vector by PI/2)
+       btScalar y = -vSwingAxis.z();
+       btScalar z = vSwingAxis.y();
+
+       // do the math...
+       if (fabs(z) > SIMD_EPSILON)  // avoid division by 0. and we don't need an update if z == 0.
+       {
+               // compute gradient/normal of ellipse surface at current "point"
+               btScalar grad = y / z;
+               grad *= m_swingSpan2 / m_swingSpan1;
+
+               // adjust y/z to represent normal at point (instead of vector to point)
+               if (y > 0)
+                       y = fabs(grad * z);
+               else
+                       y = -fabs(grad * z);
+
+               // convert ellipse direction back to swing axis
+               vSwingAxis.setZ(-y);
+               vSwingAxis.setY(z);
+               vSwingAxis.normalize();
+       }
+}
+
+void btConeTwistConstraint::setMotorTarget(const btQuaternion& q)
+{
+       //btTransform trACur = m_rbA.getCenterOfMassTransform();
+       //btTransform trBCur = m_rbB.getCenterOfMassTransform();
+       //      btTransform trABCur = trBCur.inverse() * trACur;
+       //      btQuaternion qABCur = trABCur.getRotation();
+       //      btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame);
+       //btQuaternion qConstraintCur = trConstraintCur.getRotation();
+
+       btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation();
+       setMotorTargetInConstraintSpace(qConstraint);
+}
+
+void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion& q)
+{
+       m_qTarget = q;
+
+       // clamp motor target to within limits
+       {
+               btScalar softness = 1.f;  //m_limitSoftness;
+
+               // split into twist and cone
+               btVector3 vTwisted = quatRotate(m_qTarget, vTwist);
+               btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted);
+               qTargetCone.normalize();
+               btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget;
+               qTargetTwist.normalize();
+
+               // clamp cone
+               if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f))
+               {
+                       btScalar swingAngle, swingLimit;
+                       btVector3 swingAxis;
+                       computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit);
+
+                       if (fabs(swingAngle) > SIMD_EPSILON)
+                       {
+                               if (swingAngle > swingLimit * softness)
+                                       swingAngle = swingLimit * softness;
+                               else if (swingAngle < -swingLimit * softness)
+                                       swingAngle = -swingLimit * softness;
+                               qTargetCone = btQuaternion(swingAxis, swingAngle);
+                       }
+               }
+
+               // clamp twist
+               if (m_twistSpan >= btScalar(0.05f))
+               {
+                       btScalar twistAngle;
+                       btVector3 twistAxis;
+                       computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis);
+
+                       if (fabs(twistAngle) > SIMD_EPSILON)
+                       {
+                               // eddy todo: limitSoftness used here???
+                               if (twistAngle > m_twistSpan * softness)
+                                       twistAngle = m_twistSpan * softness;
+                               else if (twistAngle < -m_twistSpan * softness)
+                                       twistAngle = -m_twistSpan * softness;
+                               qTargetTwist = btQuaternion(twistAxis, twistAngle);
+                       }
+               }
+
+               m_qTarget = qTargetCone * qTargetTwist;
+       }
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void btConeTwistConstraint::setParam(int num, btScalar value, int axis)
+{
+       switch (num)
+       {
+               case BT_CONSTRAINT_ERP:
+               case BT_CONSTRAINT_STOP_ERP:
+                       if ((axis >= 0) && (axis < 3))
+                       {
+                               m_linERP = value;
+                               m_flags |= BT_CONETWIST_FLAGS_LIN_ERP;
+                       }
+                       else
+                       {
+                               m_biasFactor = value;
+                       }
+                       break;
+               case BT_CONSTRAINT_CFM:
+               case BT_CONSTRAINT_STOP_CFM:
+                       if ((axis >= 0) && (axis < 3))
+                       {
+                               m_linCFM = value;
+                               m_flags |= BT_CONETWIST_FLAGS_LIN_CFM;
+                       }
+                       else
+                       {
+                               m_angCFM = value;
+                               m_flags |= BT_CONETWIST_FLAGS_ANG_CFM;
+                       }
+                       break;
+               default:
+                       btAssertConstrParams(0);
+                       break;
+       }
+}
+
+///return the local value of parameter
+btScalar btConeTwistConstraint::getParam(int num, int axis) const
+{
+       btScalar retVal = 0;
+       switch (num)
+       {
+               case BT_CONSTRAINT_ERP:
+               case BT_CONSTRAINT_STOP_ERP:
+                       if ((axis >= 0) && (axis < 3))
+                       {
+                               btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_ERP);
+                               retVal = m_linERP;
+                       }
+                       else if ((axis >= 3) && (axis < 6))
+                       {
+                               retVal = m_biasFactor;
+                       }
+                       else
+                       {
+                               btAssertConstrParams(0);
+                       }
+                       break;
+               case BT_CONSTRAINT_CFM:
+               case BT_CONSTRAINT_STOP_CFM:
+                       if ((axis >= 0) && (axis < 3))
+                       {
+                               btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_CFM);
+                               retVal = m_linCFM;
+                       }
+                       else if ((axis >= 3) && (axis < 6))
+                       {
+                               btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_ANG_CFM);
+                               retVal = m_angCFM;
+                       }
+                       else
+                       {
+                               btAssertConstrParams(0);
+                       }
+                       break;
+               default:
+                       btAssertConstrParams(0);
+       }
+       return retVal;
+}
+
+void btConeTwistConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
+{
+       m_rbAFrame = frameA;
+       m_rbBFrame = frameB;
+       buildJacobian();
+       //calculateTransforms();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
new file mode 100644 (file)
index 0000000..64f44df
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+Written by: Marcus Hennix
+*/
+
+/*
+Overview:
+
+btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc).
+It is a fixed translation, 3 degree-of-freedom (DOF) rotational "joint".
+It divides the 3 rotational DOFs into swing (movement within a cone) and twist.
+Swing is divided into swing1 and swing2 which can have different limits, giving an elliptical shape.
+(Note: the cone's base isn't flat, so this ellipse is "embedded" on the surface of a sphere.)
+
+In the contraint's frame of reference:
+twist is along the x-axis,
+and swing 1 and 2 are along the z and y axes respectively.
+*/
+
+#ifndef BT_CONETWISTCONSTRAINT_H
+#define BT_CONETWISTCONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btConeTwistConstraintData2 btConeTwistConstraintDoubleData
+#define btConeTwistConstraintDataName "btConeTwistConstraintDoubleData"
+#else
+#define btConeTwistConstraintData2 btConeTwistConstraintData
+#define btConeTwistConstraintDataName "btConeTwistConstraintData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+class btRigidBody;
+
+enum btConeTwistFlags
+{
+       BT_CONETWIST_FLAGS_LIN_CFM = 1,
+       BT_CONETWIST_FLAGS_LIN_ERP = 2,
+       BT_CONETWIST_FLAGS_ANG_CFM = 4
+};
+
+///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc)
+ATTRIBUTE_ALIGNED16(class)
+btConeTwistConstraint : public btTypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+       btJacobianEntry m_jac[3];  //3 orthogonal linear constraints
+
+       btTransform m_rbAFrame;
+       btTransform m_rbBFrame;
+
+       btScalar m_limitSoftness;
+       btScalar m_biasFactor;
+       btScalar m_relaxationFactor;
+
+       btScalar m_damping;
+
+       btScalar m_swingSpan1;
+       btScalar m_swingSpan2;
+       btScalar m_twistSpan;
+
+       btScalar m_fixThresh;
+
+       btVector3 m_swingAxis;
+       btVector3 m_twistAxis;
+
+       btScalar m_kSwing;
+       btScalar m_kTwist;
+
+       btScalar m_twistLimitSign;
+       btScalar m_swingCorrection;
+       btScalar m_twistCorrection;
+
+       btScalar m_twistAngle;
+
+       btScalar m_accSwingLimitImpulse;
+       btScalar m_accTwistLimitImpulse;
+
+       bool m_angularOnly;
+       bool m_solveTwistLimit;
+       bool m_solveSwingLimit;
+
+       bool m_useSolveConstraintObsolete;
+
+       // not yet used...
+       btScalar m_swingLimitRatio;
+       btScalar m_twistLimitRatio;
+       btVector3 m_twistAxisA;
+
+       // motor
+       bool m_bMotorEnabled;
+       bool m_bNormalizedMotorStrength;
+       btQuaternion m_qTarget;
+       btScalar m_maxMotorImpulse;
+       btVector3 m_accMotorImpulse;
+
+       // parameters
+       int m_flags;
+       btScalar m_linCFM;
+       btScalar m_linERP;
+       btScalar m_angCFM;
+
+protected:
+       void init();
+
+       void computeConeLimitInfo(const btQuaternion& qCone,                                           // in
+                                                         btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit);  // all outs
+
+       void computeTwistLimitInfo(const btQuaternion& qTwist,                    // in
+                                                          btScalar& twistAngle, btVector3& vTwistAxis);  // all outs
+
+       void adjustSwingAxisToUseEllipseNormal(btVector3 & vSwingAxis) const;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btConeTwistConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame);
+
+       btConeTwistConstraint(btRigidBody & rbA, const btTransform& rbAFrame);
+
+       virtual void buildJacobian();
+
+       virtual void getInfo1(btConstraintInfo1 * info);
+
+       void getInfo1NonVirtual(btConstraintInfo1 * info);
+
+       virtual void getInfo2(btConstraintInfo2 * info);
+
+       void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB);
+
+       virtual void solveConstraintObsolete(btSolverBody & bodyA, btSolverBody & bodyB, btScalar timeStep);
+
+       void updateRHS(btScalar timeStep);
+
+       const btRigidBody& getRigidBodyA() const
+       {
+               return m_rbA;
+       }
+       const btRigidBody& getRigidBodyB() const
+       {
+               return m_rbB;
+       }
+
+       void setAngularOnly(bool angularOnly)
+       {
+               m_angularOnly = angularOnly;
+       }
+
+       bool getAngularOnly() const
+       {
+               return m_angularOnly;
+       }
+
+       void setLimit(int limitIndex, btScalar limitValue)
+       {
+               switch (limitIndex)
+               {
+                       case 3:
+                       {
+                               m_twistSpan = limitValue;
+                               break;
+                       }
+                       case 4:
+                       {
+                               m_swingSpan2 = limitValue;
+                               break;
+                       }
+                       case 5:
+                       {
+                               m_swingSpan1 = limitValue;
+                               break;
+                       }
+                       default:
+                       {
+                       }
+               };
+       }
+
+       btScalar getLimit(int limitIndex) const
+       {
+               switch (limitIndex)
+               {
+                       case 3:
+                       {
+                               return m_twistSpan;
+                               break;
+                       }
+                       case 4:
+                       {
+                               return m_swingSpan2;
+                               break;
+                       }
+                       case 5:
+                       {
+                               return m_swingSpan1;
+                               break;
+                       }
+                       default:
+                       {
+                               btAssert(0 && "Invalid limitIndex specified for btConeTwistConstraint");
+                               return 0.0;
+                       }
+               };
+       }
+
+       // setLimit(), a few notes:
+       // _softness:
+       //              0->1, recommend ~0.8->1.
+       //              describes % of limits where movement is free.
+       //              beyond this softness %, the limit is gradually enforced until the "hard" (1.0) limit is reached.
+       // _biasFactor:
+       //              0->1?, recommend 0.3 +/-0.3 or so.
+       //              strength with which constraint resists zeroth order (angular, not angular velocity) limit violation.
+       // __relaxationFactor:
+       //              0->1, recommend to stay near 1.
+       //              the lower the value, the less the constraint will fight velocities which violate the angular limits.
+       void setLimit(btScalar _swingSpan1, btScalar _swingSpan2, btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
+       {
+               m_swingSpan1 = _swingSpan1;
+               m_swingSpan2 = _swingSpan2;
+               m_twistSpan = _twistSpan;
+
+               m_limitSoftness = _softness;
+               m_biasFactor = _biasFactor;
+               m_relaxationFactor = _relaxationFactor;
+       }
+
+       const btTransform& getAFrame() const { return m_rbAFrame; };
+       const btTransform& getBFrame() const { return m_rbBFrame; };
+
+       inline int getSolveTwistLimit()
+       {
+               return m_solveTwistLimit;
+       }
+
+       inline int getSolveSwingLimit()
+       {
+               return m_solveSwingLimit;
+       }
+
+       inline btScalar getTwistLimitSign()
+       {
+               return m_twistLimitSign;
+       }
+
+       void calcAngleInfo();
+       void calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB);
+
+       inline btScalar getSwingSpan1() const
+       {
+               return m_swingSpan1;
+       }
+       inline btScalar getSwingSpan2() const
+       {
+               return m_swingSpan2;
+       }
+       inline btScalar getTwistSpan() const
+       {
+               return m_twistSpan;
+       }
+       inline btScalar getLimitSoftness() const
+       {
+               return m_limitSoftness;
+       }
+       inline btScalar getBiasFactor() const
+       {
+               return m_biasFactor;
+       }
+       inline btScalar getRelaxationFactor() const
+       {
+               return m_relaxationFactor;
+       }
+       inline btScalar getTwistAngle() const
+       {
+               return m_twistAngle;
+       }
+       bool isPastSwingLimit() { return m_solveSwingLimit; }
+
+       btScalar getDamping() const { return m_damping; }
+       void setDamping(btScalar damping) { m_damping = damping; }
+
+       void enableMotor(bool b) { m_bMotorEnabled = b; }
+       bool isMotorEnabled() const { return m_bMotorEnabled; }
+       btScalar getMaxMotorImpulse() const { return m_maxMotorImpulse; }
+       bool isMaxMotorImpulseNormalized() const { return m_bNormalizedMotorStrength; }
+       void setMaxMotorImpulse(btScalar maxMotorImpulse)
+       {
+               m_maxMotorImpulse = maxMotorImpulse;
+               m_bNormalizedMotorStrength = false;
+       }
+       void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse)
+       {
+               m_maxMotorImpulse = maxMotorImpulse;
+               m_bNormalizedMotorStrength = true;
+       }
+
+       btScalar getFixThresh() { return m_fixThresh; }
+       void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; }
+
+       // setMotorTarget:
+       // q: the desired rotation of bodyA wrt bodyB.
+       // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability)
+       // note: don't forget to enableMotor()
+       void setMotorTarget(const btQuaternion& q);
+       const btQuaternion& getMotorTarget() const { return m_qTarget; }
+
+       // same as above, but q is the desired rotation of frameA wrt frameB in constraint space
+       void setMotorTargetInConstraintSpace(const btQuaternion& q);
+
+       btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const;
+
+       ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+       ///If no axis is provided, it uses the default axis for this constraint.
+       virtual void setParam(int num, btScalar value, int axis = -1);
+
+       virtual void setFrames(const btTransform& frameA, const btTransform& frameB);
+
+       const btTransform& getFrameOffsetA() const
+       {
+               return m_rbAFrame;
+       }
+
+       const btTransform& getFrameOffsetB() const
+       {
+               return m_rbBFrame;
+       }
+
+       ///return the local value of parameter
+       virtual btScalar getParam(int num, int axis = -1) const;
+
+       int getFlags() const
+       {
+               return m_flags;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+struct btConeTwistConstraintDoubleData
+{
+       btTypedConstraintDoubleData m_typeConstraintData;
+       btTransformDoubleData m_rbAFrame;
+       btTransformDoubleData m_rbBFrame;
+
+       //limits
+       double m_swingSpan1;
+       double m_swingSpan2;
+       double m_twistSpan;
+       double m_limitSoftness;
+       double m_biasFactor;
+       double m_relaxationFactor;
+
+       double m_damping;
+};
+
+#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+///this structure is not used, except for loading pre-2.82 .bullet files
+struct btConeTwistConstraintData
+{
+       btTypedConstraintData m_typeConstraintData;
+       btTransformFloatData m_rbAFrame;
+       btTransformFloatData m_rbBFrame;
+
+       //limits
+       float m_swingSpan1;
+       float m_swingSpan2;
+       float m_twistSpan;
+       float m_limitSoftness;
+       float m_biasFactor;
+       float m_relaxationFactor;
+
+       float m_damping;
+
+       char m_pad[4];
+};
+#endif  //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+//
+
+SIMD_FORCE_INLINE int btConeTwistConstraint::calculateSerializeBufferSize() const
+{
+       return sizeof(btConeTwistConstraintData2);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btConeTwistConstraintData2* cone = (btConeTwistConstraintData2*)dataBuffer;
+       btTypedConstraint::serialize(&cone->m_typeConstraintData, serializer);
+
+       m_rbAFrame.serialize(cone->m_rbAFrame);
+       m_rbBFrame.serialize(cone->m_rbBFrame);
+
+       cone->m_swingSpan1 = m_swingSpan1;
+       cone->m_swingSpan2 = m_swingSpan2;
+       cone->m_twistSpan = m_twistSpan;
+       cone->m_limitSoftness = m_limitSoftness;
+       cone->m_biasFactor = m_biasFactor;
+       cone->m_relaxationFactor = m_relaxationFactor;
+       cone->m_damping = m_damping;
+
+       return btConeTwistConstraintDataName;
+}
+
+#endif  //BT_CONETWISTCONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h
new file mode 100644 (file)
index 0000000..777eccf
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONSTRAINT_SOLVER_H
+#define BT_CONSTRAINT_SOLVER_H
+
+#include "LinearMath/btScalar.h"
+
+class btPersistentManifold;
+class btRigidBody;
+class btCollisionObject;
+class btTypedConstraint;
+struct btContactSolverInfo;
+struct btBroadphaseProxy;
+class btIDebugDraw;
+class btStackAlloc;
+class btDispatcher;
+/// btConstraintSolver provides solver interface
+
+enum btConstraintSolverType
+{
+       BT_SEQUENTIAL_IMPULSE_SOLVER = 1,
+       BT_MLCP_SOLVER = 2,
+       BT_NNCG_SOLVER = 4,
+       BT_MULTIBODY_SOLVER = 8,
+       BT_BLOCK_SOLVER = 16,
+};
+
+class btConstraintSolver
+{
+public:
+       virtual ~btConstraintSolver() {}
+
+       virtual void prepareSolve(int /* numBodies */, int /* numManifolds */) { ; }
+
+       ///solve a group of constraints
+       virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, class btIDebugDraw* debugDrawer, btDispatcher* dispatcher) = 0;
+
+       virtual void allSolved(const btContactSolverInfo& /* info */, class btIDebugDraw* /* debugDrawer */) { ; }
+
+       ///clear internal cached data and reset random seed
+       virtual void reset() = 0;
+
+       virtual btConstraintSolverType getSolverType() const = 0;
+};
+
+#endif  //BT_CONSTRAINT_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
new file mode 100644 (file)
index 0000000..e8ebe3a
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btContactConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btContactSolverInfo.h"
+#include "LinearMath/btMinMax.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+
+btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold, btRigidBody& rbA, btRigidBody& rbB)
+       : btTypedConstraint(CONTACT_CONSTRAINT_TYPE, rbA, rbB),
+         m_contactManifold(*contactManifold)
+{
+}
+
+btContactConstraint::~btContactConstraint()
+{
+}
+
+void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold)
+{
+       m_contactManifold = *contactManifold;
+}
+
+void btContactConstraint::getInfo1(btConstraintInfo1* info)
+{
+}
+
+void btContactConstraint::getInfo2(btConstraintInfo2* info)
+{
+}
+
+void btContactConstraint::buildJacobian()
+{
+}
+
+#include "btContactConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btContactSolverInfo.h"
+#include "LinearMath/btMinMax.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+
+//response  between two dynamic objects without friction and no restitution, assuming 0 penetration depth
+btScalar resolveSingleCollision(
+       btRigidBody* body1,
+       btCollisionObject* colObj2,
+       const btVector3& contactPositionWorld,
+       const btVector3& contactNormalOnB,
+       const btContactSolverInfo& solverInfo,
+       btScalar distance)
+{
+       btRigidBody* body2 = btRigidBody::upcast(colObj2);
+
+       const btVector3& normal = contactNormalOnB;
+
+       btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin();
+       btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin();
+
+       btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1);
+       btVector3 vel2 = body2 ? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0, 0, 0);
+       btVector3 vel = vel1 - vel2;
+       btScalar rel_vel;
+       rel_vel = normal.dot(vel);
+
+       btScalar combinedRestitution = 0.f;
+       btScalar restitution = combinedRestitution * -rel_vel;
+
+       btScalar positionalError = solverInfo.m_erp * -distance / solverInfo.m_timeStep;
+       btScalar velocityError = -(1.0f + restitution) * rel_vel;  // * damping;
+       btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld, normal);
+       btScalar denom1 = body2 ? body2->computeImpulseDenominator(contactPositionWorld, normal) : 0.f;
+       btScalar relaxation = 1.f;
+       btScalar jacDiagABInv = relaxation / (denom0 + denom1);
+
+       btScalar penetrationImpulse = positionalError * jacDiagABInv;
+       btScalar velocityImpulse = velocityError * jacDiagABInv;
+
+       btScalar normalImpulse = penetrationImpulse + velocityImpulse;
+       normalImpulse = 0.f > normalImpulse ? 0.f : normalImpulse;
+
+       body1->applyImpulse(normal * (normalImpulse), rel_pos1);
+       if (body2)
+               body2->applyImpulse(-normal * (normalImpulse), rel_pos2);
+
+       return normalImpulse;
+}
+
+//bilateral constraint between two dynamic objects
+void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
+                                                       btRigidBody& body2, const btVector3& pos2,
+                                                       btScalar distance, const btVector3& normal, btScalar& impulse, btScalar timeStep)
+{
+       (void)timeStep;
+       (void)distance;
+
+       btScalar normalLenSqr = normal.length2();
+       btAssert(btFabs(normalLenSqr) < btScalar(1.1));
+       if (normalLenSqr > btScalar(1.1))
+       {
+               impulse = btScalar(0.);
+               return;
+       }
+       btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
+       btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
+       //this jacobian entry could be re-used for all iterations
+
+       btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
+       btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
+       btVector3 vel = vel1 - vel2;
+
+       btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(),
+                                               body2.getCenterOfMassTransform().getBasis().transpose(),
+                                               rel_pos1, rel_pos2, normal, body1.getInvInertiaDiagLocal(), body1.getInvMass(),
+                                               body2.getInvInertiaDiagLocal(), body2.getInvMass());
+
+       btScalar jacDiagAB = jac.getDiagonal();
+       btScalar jacDiagABInv = btScalar(1.) / jacDiagAB;
+
+       btScalar rel_vel = jac.getRelativeVelocity(
+               body1.getLinearVelocity(),
+               body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(),
+               body2.getLinearVelocity(),
+               body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity());
+
+       rel_vel = normal.dot(vel);
+
+       //todo: move this into proper structure
+       btScalar contactDamping = btScalar(0.2);
+
+#ifdef ONLY_USE_LINEAR_MASS
+       btScalar massTerm = btScalar(1.) / (body1.getInvMass() + body2.getInvMass());
+       impulse = -contactDamping * rel_vel * massTerm;
+#else
+       btScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
+       impulse = velocityImpulse;
+#endif
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btContactConstraint.h
new file mode 100644 (file)
index 0000000..b213a38
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONTACT_CONSTRAINT_H
+#define BT_CONTACT_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+
+///btContactConstraint can be automatically created to solve contact constraints using the unified btTypedConstraint interface
+ATTRIBUTE_ALIGNED16(class)
+btContactConstraint : public btTypedConstraint
+{
+protected:
+       btPersistentManifold m_contactManifold;
+
+protected:
+       btContactConstraint(btPersistentManifold * contactManifold, btRigidBody & rbA, btRigidBody & rbB);
+
+public:
+       void setContactManifold(btPersistentManifold * contactManifold);
+
+       btPersistentManifold* getContactManifold()
+       {
+               return &m_contactManifold;
+       }
+
+       const btPersistentManifold* getContactManifold() const
+       {
+               return &m_contactManifold;
+       }
+
+       virtual ~btContactConstraint();
+
+       virtual void getInfo1(btConstraintInfo1 * info);
+
+       virtual void getInfo2(btConstraintInfo2 * info);
+
+       ///obsolete methods
+       virtual void buildJacobian();
+};
+
+///very basic collision resolution without friction
+btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld, const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo, btScalar distance);
+
+///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects
+void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
+                                                       btRigidBody& body2, const btVector3& pos2,
+                                                       btScalar distance, const btVector3& normal, btScalar& impulse, btScalar timeStep);
+
+#endif  //BT_CONTACT_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
new file mode 100644 (file)
index 0000000..6304167
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONTACT_SOLVER_INFO
+#define BT_CONTACT_SOLVER_INFO
+
+#include "LinearMath/btScalar.h"
+
+enum btSolverMode
+{
+       SOLVER_RANDMIZE_ORDER = 1,
+       SOLVER_FRICTION_SEPARATE = 2,
+       SOLVER_USE_WARMSTARTING = 4,
+       SOLVER_USE_2_FRICTION_DIRECTIONS = 16,
+       SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32,
+       SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64,
+       SOLVER_CACHE_FRIENDLY = 128,
+       SOLVER_SIMD = 256,
+       SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512,
+       SOLVER_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024,
+       SOLVER_DISABLE_IMPLICIT_CONE_FRICTION = 2048,
+       SOLVER_USE_ARTICULATED_WARMSTARTING = 4096,
+};
+
+struct btContactSolverInfoData
+{
+       btScalar m_tau;
+       btScalar m_damping;  //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+       btScalar m_friction;
+       btScalar m_timeStep;
+       btScalar m_restitution;
+       int m_numIterations;
+       btScalar m_maxErrorReduction;
+       btScalar m_sor;          //successive over-relaxation term
+       btScalar m_erp;          //error reduction for non-contact constraints
+       btScalar m_erp2;         //error reduction for contact constraints
+       btScalar m_deformable_erp;          //error reduction for deformable constraints
+       btScalar m_deformable_cfm;          //constraint force mixing for deformable constraints
+       btScalar m_deformable_maxErrorReduction; // maxErrorReduction for deformable contact
+       btScalar m_globalCfm;    //constraint force mixing for contacts and non-contacts
+       btScalar m_frictionERP;  //error reduction for friction constraints
+       btScalar m_frictionCFM;  //constraint force mixing for friction constraints
+
+       int m_splitImpulse;
+       btScalar m_splitImpulsePenetrationThreshold;
+       btScalar m_splitImpulseTurnErp;
+       btScalar m_linearSlop;
+       btScalar m_warmstartingFactor;
+       btScalar m_articulatedWarmstartingFactor;
+       int m_solverMode;
+       int m_restingContactRestitutionThreshold;
+       int m_minimumSolverBatchSize;
+       btScalar m_maxGyroscopicForce;
+       btScalar m_singleAxisRollingFrictionThreshold;
+       btScalar m_leastSquaresResidualThreshold;
+       btScalar m_restitutionVelocityThreshold;
+       bool m_jointFeedbackInWorldSpace;
+       bool m_jointFeedbackInJointFrame;
+       int m_reportSolverAnalytics;
+       int m_numNonContactInnerIterations;
+};
+
+struct btContactSolverInfo : public btContactSolverInfoData
+{
+       inline btContactSolverInfo()
+       {
+               m_tau = btScalar(0.6);
+               m_damping = btScalar(1.0);
+               m_friction = btScalar(0.3);
+               m_timeStep = btScalar(1.f / 60.f);
+               m_restitution = btScalar(0.);
+               m_maxErrorReduction = btScalar(20.);
+               m_numIterations = 10;
+               m_erp = btScalar(0.2);
+               m_erp2 = btScalar(0.2);
+               m_deformable_erp = btScalar(0.06);
+               m_deformable_cfm = btScalar(0.01);
+               m_deformable_maxErrorReduction = btScalar(0.1);
+               m_globalCfm = btScalar(0.);
+               m_frictionERP = btScalar(0.2);  //positional friction 'anchors' are disabled by default
+               m_frictionCFM = btScalar(0.);
+               m_sor = btScalar(1.);
+               m_splitImpulse = true;
+               m_splitImpulsePenetrationThreshold = -.04f;
+               m_splitImpulseTurnErp = 0.1f;
+               m_linearSlop = btScalar(0.0);
+               m_warmstartingFactor = btScalar(0.85);
+               m_articulatedWarmstartingFactor = btScalar(0.85);
+               //m_solverMode =  SOLVER_USE_WARMSTARTING |  SOLVER_SIMD | SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | SOLVER_RANDMIZE_ORDER;
+               m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD;  // | SOLVER_RANDMIZE_ORDER;
+               m_restingContactRestitutionThreshold = 2;              //unused as of 2.81
+               m_minimumSolverBatchSize = 128;                        //try to combine islands until the amount of constraints reaches this limit
+               m_maxGyroscopicForce = 100.f;                          ///it is only used for 'explicit' version of gyroscopic force
+               m_singleAxisRollingFrictionThreshold = 1e30f;          ///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
+               m_leastSquaresResidualThreshold = 0.f;
+               m_restitutionVelocityThreshold = 0.2f;  //if the relative velocity is below this threshold, there is zero restitution
+               m_jointFeedbackInWorldSpace = false;
+               m_jointFeedbackInJointFrame = false;
+               m_reportSolverAnalytics = 0;
+               m_numNonContactInnerIterations = 1;   // the number of inner iterations for solving motor constraint in a single iteration of the constraint solve
+       }
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btContactSolverInfoDoubleData
+{
+       double m_tau;
+       double m_damping;  //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+       double m_friction;
+       double m_timeStep;
+       double m_restitution;
+       double m_maxErrorReduction;
+       double m_sor;
+       double m_erp;        //used as Baumgarte factor
+       double m_erp2;       //used in Split Impulse
+       double m_globalCfm;  //constraint force mixing
+       double m_splitImpulsePenetrationThreshold;
+       double m_splitImpulseTurnErp;
+       double m_linearSlop;
+       double m_warmstartingFactor;
+       double m_articulatedWarmstartingFactor;
+       double m_maxGyroscopicForce;  ///it is only used for 'explicit' version of gyroscopic force
+       double m_singleAxisRollingFrictionThreshold;
+
+       int m_numIterations;
+       int m_solverMode;
+       int m_restingContactRestitutionThreshold;
+       int m_minimumSolverBatchSize;
+       int m_splitImpulse;
+       char m_padding[4];
+};
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btContactSolverInfoFloatData
+{
+       float m_tau;
+       float m_damping;  //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+       float m_friction;
+       float m_timeStep;
+
+       float m_restitution;
+       float m_maxErrorReduction;
+       float m_sor;
+       float m_erp;  //used as Baumgarte factor
+
+       float m_erp2;       //used in Split Impulse
+       float m_globalCfm;  //constraint force mixing
+       float m_splitImpulsePenetrationThreshold;
+       float m_splitImpulseTurnErp;
+
+       float m_linearSlop;
+       float m_warmstartingFactor;
+       float m_articulatedWarmstartingFactor;
+       float m_maxGyroscopicForce;
+
+       float m_singleAxisRollingFrictionThreshold;
+       int m_numIterations;
+       int m_solverMode;
+       int m_restingContactRestitutionThreshold;
+
+       int m_minimumSolverBatchSize;
+       int m_splitImpulse;
+       
+};
+
+#endif  //BT_CONTACT_SOLVER_INFO
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp
new file mode 100644 (file)
index 0000000..bba102d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btFixedConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include <new>
+
+btFixedConstraint::btFixedConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB)
+       : btGeneric6DofSpring2Constraint(rbA, rbB, frameInA, frameInB)
+{
+       setAngularLowerLimit(btVector3(0, 0, 0));
+       setAngularUpperLimit(btVector3(0, 0, 0));
+       setLinearLowerLimit(btVector3(0, 0, 0));
+       setLinearUpperLimit(btVector3(0, 0, 0));
+}
+
+btFixedConstraint::~btFixedConstraint()
+{
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btFixedConstraint.h
new file mode 100644 (file)
index 0000000..6d474ea
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_FIXED_CONSTRAINT_H
+#define BT_FIXED_CONSTRAINT_H
+
+#include "btGeneric6DofSpring2Constraint.h"
+
+ATTRIBUTE_ALIGNED16(class)
+btFixedConstraint : public btGeneric6DofSpring2Constraint
+{
+public:
+       btFixedConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB);
+
+       virtual ~btFixedConstraint();
+};
+
+#endif  //BT_FIXED_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
new file mode 100644 (file)
index 0000000..7535c52
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2012 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// Implemented by Erwin Coumans. The idea for the constraint comes from Dimitris Papavasiliou.
+
+#include "btGearConstraint.h"
+
+btGearConstraint::btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA, const btVector3& axisInB, btScalar ratio)
+       : btTypedConstraint(GEAR_CONSTRAINT_TYPE, rbA, rbB),
+         m_axisInA(axisInA),
+         m_axisInB(axisInB),
+         m_ratio(ratio)
+{
+}
+
+btGearConstraint::~btGearConstraint()
+{
+}
+
+void btGearConstraint::getInfo1(btConstraintInfo1* info)
+{
+       info->m_numConstraintRows = 1;
+       info->nub = 1;
+}
+
+void btGearConstraint::getInfo2(btConstraintInfo2* info)
+{
+       btVector3 globalAxisA, globalAxisB;
+
+       globalAxisA = m_rbA.getWorldTransform().getBasis() * this->m_axisInA;
+       globalAxisB = m_rbB.getWorldTransform().getBasis() * this->m_axisInB;
+
+       info->m_J1angularAxis[0] = globalAxisA[0];
+       info->m_J1angularAxis[1] = globalAxisA[1];
+       info->m_J1angularAxis[2] = globalAxisA[2];
+
+       info->m_J2angularAxis[0] = m_ratio * globalAxisB[0];
+       info->m_J2angularAxis[1] = m_ratio * globalAxisB[1];
+       info->m_J2angularAxis[2] = m_ratio * globalAxisB[2];
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGearConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGearConstraint.h
new file mode 100644 (file)
index 0000000..64b15df
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2012 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_GEAR_CONSTRAINT_H
+#define BT_GEAR_CONSTRAINT_H
+
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btGearConstraintData btGearConstraintDoubleData
+#define btGearConstraintDataName "btGearConstraintDoubleData"
+#else
+#define btGearConstraintData btGearConstraintFloatData
+#define btGearConstraintDataName "btGearConstraintFloatData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+///The btGeatConstraint will couple the angular velocity for two bodies around given local axis and ratio.
+///See Bullet/Demos/ConstraintDemo for an example use.
+class btGearConstraint : public btTypedConstraint
+{
+protected:
+       btVector3 m_axisInA;
+       btVector3 m_axisInB;
+       bool m_useFrameA;
+       btScalar m_ratio;
+
+public:
+       btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA, const btVector3& axisInB, btScalar ratio = 1.f);
+       virtual ~btGearConstraint();
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void getInfo1(btConstraintInfo1* info);
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void getInfo2(btConstraintInfo2* info);
+
+       void setAxisA(btVector3& axisA)
+       {
+               m_axisInA = axisA;
+       }
+       void setAxisB(btVector3& axisB)
+       {
+               m_axisInB = axisB;
+       }
+       void setRatio(btScalar ratio)
+       {
+               m_ratio = ratio;
+       }
+       const btVector3& getAxisA() const
+       {
+               return m_axisInA;
+       }
+       const btVector3& getAxisB() const
+       {
+               return m_axisInB;
+       }
+       btScalar getRatio() const
+       {
+               return m_ratio;
+       }
+
+       virtual void setParam(int num, btScalar value, int axis = -1)
+       {
+               (void)num;
+               (void)value;
+               (void)axis;
+               btAssert(0);
+       }
+
+       ///return the local value of parameter
+       virtual btScalar getParam(int num, int axis = -1) const
+       {
+               (void)num;
+               (void)axis;
+               btAssert(0);
+               return 0.f;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btGearConstraintFloatData
+{
+       btTypedConstraintFloatData m_typeConstraintData;
+
+       btVector3FloatData m_axisInA;
+       btVector3FloatData m_axisInB;
+
+       float m_ratio;
+       char m_padding[4];
+};
+
+struct btGearConstraintDoubleData
+{
+       btTypedConstraintDoubleData m_typeConstraintData;
+
+       btVector3DoubleData m_axisInA;
+       btVector3DoubleData m_axisInB;
+
+       double m_ratio;
+};
+
+SIMD_FORCE_INLINE int btGearConstraint::calculateSerializeBufferSize() const
+{
+       return sizeof(btGearConstraintData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btGearConstraintData* gear = (btGearConstraintData*)dataBuffer;
+       btTypedConstraint::serialize(&gear->m_typeConstraintData, serializer);
+
+       m_axisInA.serialize(gear->m_axisInA);
+       m_axisInB.serialize(gear->m_axisInB);
+
+       gear->m_ratio = m_ratio;
+
+       // Fill padding with zeros to appease msan.
+#ifndef BT_USE_DOUBLE_PRECISION
+       gear->m_padding[0] = 0;
+       gear->m_padding[1] = 0;
+       gear->m_padding[2] = 0;
+       gear->m_padding[3] = 0;
+#endif
+
+       return btGearConstraintDataName;
+}
+
+#endif  //BT_GEAR_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
new file mode 100644 (file)
index 0000000..14ec4a8
--- /dev/null
@@ -0,0 +1,975 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+/*
+2007-09-09
+Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+#include "btGeneric6DofConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btTransformUtil.h"
+#include <new>
+
+#define D6_USE_OBSOLETE_METHOD false
+#define D6_USE_FRAME_OFFSET 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), m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), m_flags(0), m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD)
+{
+       calculateTransforms();
+}
+
+btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
+       : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB),
+         m_frameInB(frameInB),
+         m_useLinearReferenceFrameA(useLinearReferenceFrameB),
+         m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
+         m_flags(0),
+         m_useSolveConstraintObsolete(false)
+{
+       ///not providing rigidbody A means implicitly using worldspace for body A
+       m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
+       calculateTransforms();
+}
+
+#define GENERIC_D6_DISABLE_WARMSTARTING 1
+
+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];
+}
+
+///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
+bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz);
+bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz)
+{
+       //      // rot =  cy*cz          -cy*sz           sy
+       //      //        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
+       //      //       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
+       //
+
+       btScalar fi = btGetMatrixElem(mat, 2);
+       if (fi < btScalar(1.0f))
+       {
+               if (fi > btScalar(-1.0f))
+               {
+                       xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 8));
+                       xyz[1] = btAsin(btGetMatrixElem(mat, 2));
+                       xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
+                       return true;
+               }
+               else
+               {
+                       // WARNING.  Not unique.  XA - ZA = -atan2(r10,r11)
+                       xyz[0] = -btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
+                       xyz[1] = -SIMD_HALF_PI;
+                       xyz[2] = btScalar(0.0);
+                       return false;
+               }
+       }
+       else
+       {
+               // WARNING.  Not unique.  XAngle + ZAngle = atan2(r10,r11)
+               xyz[0] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
+               xyz[1] = SIMD_HALF_PI;
+               xyz[2] = 0.0;
+       }
+       return false;
+}
+
+//////////////////////////// btRotationalLimitMotor ////////////////////////////////////
+
+int btRotationalLimitMotor::testLimitValue(btScalar test_value)
+{
+       if (m_loLimit > m_hiLimit)
+       {
+               m_currentLimit = 0;  //Free from violation
+               return 0;
+       }
+       if (test_value < m_loLimit)
+       {
+               m_currentLimit = 1;  //low limit violation
+               m_currentLimitError = test_value - m_loLimit;
+               if (m_currentLimitError > SIMD_PI)
+                       m_currentLimitError -= SIMD_2_PI;
+               else if (m_currentLimitError < -SIMD_PI)
+                       m_currentLimitError += SIMD_2_PI;
+               return 1;
+       }
+       else if (test_value > m_hiLimit)
+       {
+               m_currentLimit = 2;  //High limit violation
+               m_currentLimitError = test_value - m_hiLimit;
+               if (m_currentLimitError > SIMD_PI)
+                       m_currentLimitError -= SIMD_2_PI;
+               else if (m_currentLimitError < -SIMD_PI)
+                       m_currentLimitError += SIMD_2_PI;
+               return 2;
+       };
+
+       m_currentLimit = 0;  //Free from violation
+       return 0;
+}
+
+btScalar btRotationalLimitMotor::solveAngularLimits(
+       btScalar timeStep, btVector3& axis, btScalar jacDiagABInv,
+       btRigidBody* body0, btRigidBody* body1)
+{
+       if (needApplyTorques() == false) return 0.0f;
+
+       btScalar target_velocity = m_targetVelocity;
+       btScalar maxMotorForce = m_maxMotorForce;
+
+       //current error correction
+       if (m_currentLimit != 0)
+       {
+               target_velocity = -m_stopERP * m_currentLimitError / (timeStep);
+               maxMotorForce = m_maxLimitForce;
+       }
+
+       maxMotorForce *= timeStep;
+
+       // current velocity difference
+
+       btVector3 angVelA = body0->getAngularVelocity();
+       btVector3 angVelB = body1->getAngularVelocity();
+
+       btVector3 vel_diff;
+       vel_diff = angVelA - angVelB;
+
+       btScalar rel_vel = axis.dot(vel_diff);
+
+       // correction velocity
+       btScalar motor_relvel = m_limitSoftness * (target_velocity - m_damping * rel_vel);
+
+       if (motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON)
+       {
+               return 0.0f;  //no need for applying force
+       }
+
+       // correction impulse
+       btScalar unclippedMotorImpulse = (1 + m_bounce) * motor_relvel * jacDiagABInv;
+
+       // clip correction impulse
+       btScalar clippedMotorImpulse;
+
+       ///@todo: should clip against accumulated impulse
+       if (unclippedMotorImpulse > 0.0f)
+       {
+               clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce ? maxMotorForce : unclippedMotorImpulse;
+       }
+       else
+       {
+               clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce : unclippedMotorImpulse;
+       }
+
+       // sort with accumulated impulses
+       btScalar lo = btScalar(-BT_LARGE_FLOAT);
+       btScalar hi = btScalar(BT_LARGE_FLOAT);
+
+       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);
+       body1->applyTorqueImpulse(-motorImp);
+
+       return clippedMotorImpulse;
+}
+
+//////////////////////////// End btRotationalLimitMotor ////////////////////////////////////
+
+//////////////////////////// btTranslationalLimitMotor ////////////////////////////////////
+
+int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value)
+{
+       btScalar loLimit = m_lowerLimit[limitIndex];
+       btScalar hiLimit = m_upperLimit[limitIndex];
+       if (loLimit > hiLimit)
+       {
+               m_currentLimit[limitIndex] = 0;  //Free from violation
+               m_currentLimitError[limitIndex] = btScalar(0.f);
+               return 0;
+       }
+
+       if (test_value < loLimit)
+       {
+               m_currentLimit[limitIndex] = 2;  //low limit violation
+               m_currentLimitError[limitIndex] = test_value - loLimit;
+               return 2;
+       }
+       else if (test_value > hiLimit)
+       {
+               m_currentLimit[limitIndex] = 1;  //High limit violation
+               m_currentLimitError[limitIndex] = test_value - hiLimit;
+               return 1;
+       };
+
+       m_currentLimit[limitIndex] = 0;  //Free from violation
+       m_currentLimitError[limitIndex] = btScalar(0.f);
+       return 0;
+}
+
+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)
+{
+       ///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
+
+       //positional error (zeroth order error)
+       btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a);
+       btScalar lo = btScalar(-BT_LARGE_FLOAT);
+       btScalar hi = btScalar(BT_LARGE_FLOAT);
+
+       btScalar minLimit = m_lowerLimit[limit_index];
+       btScalar maxLimit = m_upperLimit[limit_index];
+
+       //handle the limits
+       if (minLimit < maxLimit)
+       {
+               {
+                       if (depth > maxLimit)
+                       {
+                               depth -= maxLimit;
+                               lo = btScalar(0.);
+                       }
+                       else
+                       {
+                               if (depth < minLimit)
+                               {
+                                       depth -= minLimit;
+                                       hi = btScalar(0.);
+                               }
+                               else
+                               {
+                                       return 0.0f;
+                               }
+                       }
+               }
+       }
+
+       btScalar normalImpulse = m_limitSoftness * (m_restitution * depth / timeStep - m_damping * rel_vel) * jacDiagABInv;
+
+       btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index];
+       btScalar sum = oldNormalImpulse + normalImpulse;
+       m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum;
+       normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse;
+
+       btVector3 impulse_vector = axis_normal_on_a * normalImpulse;
+       body1.applyImpulse(impulse_vector, rel_pos1);
+       body2.applyImpulse(-impulse_vector, rel_pos2);
+
+       return normalImpulse;
+}
+
+//////////////////////////// btTranslationalLimitMotor ////////////////////////////////////
+
+void btGeneric6DofConstraint::calculateAngleInfo()
+{
+       btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse() * m_calculatedTransformB.getBasis();
+       matrixToEulerXYZ(relative_frame, m_calculatedAxisAngleDiff);
+       // in euler angle mode we do not actually constrain the angular velocity
+       // along the axes axis[0] and axis[2] (although we do use axis[1]) :
+       //
+       //    to get                    constrain w2-w1 along           ...not
+       //    ------                    ---------------------           ------
+       //    d(angle[0])/dt = 0        ax[1] x ax[2]                   ax[0]
+       //    d(angle[1])/dt = 0        ax[1]
+       //    d(angle[2])/dt = 0        ax[0] x ax[1]                   ax[2]
+       //
+       // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
+       // to prove the result for angle[0], write the expression for angle[0] from
+       // GetInfo1 then take the derivative. to prove this for angle[2] it is
+       // easier to take the euler rate expression for d(angle[2])/dt with respect
+       // to the components of w and set that to 0.
+       btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
+       btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
+
+       m_calculatedAxis[1] = axis2.cross(axis0);
+       m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
+       m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
+
+       m_calculatedAxis[0].normalize();
+       m_calculatedAxis[1].normalize();
+       m_calculatedAxis[2].normalize();
+}
+
+void btGeneric6DofConstraint::calculateTransforms()
+{
+       calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+}
+
+void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA, const btTransform& transB)
+{
+       m_calculatedTransformA = transA * m_frameInA;
+       m_calculatedTransformB = transB * m_frameInB;
+       calculateLinearInfo();
+       calculateAngleInfo();
+       if (m_useOffsetForConstraintFrame)
+       {  //  get weight factors depending on masses
+               btScalar miA = getRigidBodyA().getInvMass();
+               btScalar miB = getRigidBodyB().getInvMass();
+               m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+               btScalar miS = miA + miB;
+               if (miS > btScalar(0.f))
+               {
+                       m_factA = miB / miS;
+               }
+               else
+               {
+                       m_factA = btScalar(0.5f);
+               }
+               m_factB = btScalar(1.0f) - m_factA;
+       }
+}
+
+void btGeneric6DofConstraint::buildLinearJacobian(
+       btJacobianEntry& jacLinear, const btVector3& normalWorld,
+       const btVector3& pivotAInW, const btVector3& pivotBInW)
+{
+       new (&jacLinear) btJacobianEntry(
+               m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+               m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+               pivotAInW - m_rbA.getCenterOfMassPosition(),
+               pivotBInW - m_rbB.getCenterOfMassPosition(),
+               normalWorld,
+               m_rbA.getInvInertiaDiagLocal(),
+               m_rbA.getInvMass(),
+               m_rbB.getInvInertiaDiagLocal(),
+               m_rbB.getInvMass());
+}
+
+void btGeneric6DofConstraint::buildAngularJacobian(
+       btJacobianEntry& jacAngular, const btVector3& jointAxisW)
+{
+       new (&jacAngular) btJacobianEntry(jointAxisW,
+                                                                         m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+                                                                         m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+                                                                         m_rbA.getInvInertiaDiagLocal(),
+                                                                         m_rbB.getInvInertiaDiagLocal());
+}
+
+bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index)
+{
+       btScalar angle = m_calculatedAxisAngleDiff[axis_index];
+       angle = btAdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
+       m_angularLimits[axis_index].m_currentPosition = angle;
+       //test limits
+       m_angularLimits[axis_index].testLimitValue(angle);
+       return m_angularLimits[axis_index].needApplyTorques();
+}
+
+void btGeneric6DofConstraint::buildJacobian()
+{
+#ifndef __SPU__
+       if (m_useSolveConstraintObsolete)
+       {
+               // 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(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+
+               //  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);
+
+                               buildLinearJacobian(
+                                       m_jacLinear[i], normalWorld,
+                                       pivotAInW, pivotBInW);
+                       }
+               }
+
+               // angular part
+               for (i = 0; i < 3; i++)
+               {
+                       //calculates error angle
+                       if (testAngularLimitMotor(i))
+                       {
+                               normalWorld = this->getAxis(i);
+                               // Create angular atom
+                               buildAngularJacobian(m_jacAng[i], normalWorld);
+                       }
+               }
+       }
+#endif  //__SPU__
+}
+
+void btGeneric6DofConstraint::getInfo1(btConstraintInfo1* info)
+{
+       if (m_useSolveConstraintObsolete)
+       {
+               info->m_numConstraintRows = 0;
+               info->nub = 0;
+       }
+       else
+       {
+               //prepare constraint
+               calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+               info->m_numConstraintRows = 0;
+               info->nub = 6;
+               int i;
+               //test linear limits
+               for (i = 0; i < 3; i++)
+               {
+                       if (m_linearLimits.needApplyForce(i))
+                       {
+                               info->m_numConstraintRows++;
+                               info->nub--;
+                       }
+               }
+               //test angular limits
+               for (i = 0; i < 3; i++)
+               {
+                       if (testAngularLimitMotor(i))
+                       {
+                               info->m_numConstraintRows++;
+                               info->nub--;
+                       }
+               }
+       }
+}
+
+void btGeneric6DofConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
+{
+       if (m_useSolveConstraintObsolete)
+       {
+               info->m_numConstraintRows = 0;
+               info->nub = 0;
+       }
+       else
+       {
+               //pre-allocate all 6
+               info->m_numConstraintRows = 6;
+               info->nub = 0;
+       }
+}
+
+void btGeneric6DofConstraint::getInfo2(btConstraintInfo2* info)
+{
+       btAssert(!m_useSolveConstraintObsolete);
+
+       const btTransform& transA = m_rbA.getCenterOfMassTransform();
+       const btTransform& transB = m_rbB.getCenterOfMassTransform();
+       const btVector3& linVelA = m_rbA.getLinearVelocity();
+       const btVector3& linVelB = m_rbB.getLinearVelocity();
+       const btVector3& angVelA = m_rbA.getAngularVelocity();
+       const btVector3& angVelB = m_rbB.getAngularVelocity();
+
+       if (m_useOffsetForConstraintFrame)
+       {  // for stability better to solve angular limits first
+               int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+               setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
+       }
+       else
+       {  // leave old version for compatibility
+               int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+               setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
+       }
+}
+
+void btGeneric6DofConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
+{
+       btAssert(!m_useSolveConstraintObsolete);
+       //prepare constraint
+       calculateTransforms(transA, transB);
+
+       int i;
+       for (i = 0; i < 3; i++)
+       {
+               testAngularLimitMotor(i);
+       }
+
+       if (m_useOffsetForConstraintFrame)
+       {  // for stability better to solve angular limits first
+               int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+               setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
+       }
+       else
+       {  // leave old version for compatibility
+               int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+               setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
+       }
+}
+
+int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
+{
+       //      int row = 0;
+       //solve linear limits
+       btRotationalLimitMotor limot;
+       for (int i = 0; i < 3; i++)
+       {
+               if (m_linearLimits.needApplyForce(i))
+               {  // re-use rotational motor code
+                       limot.m_bounce = btScalar(0.f);
+                       limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
+                       limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
+                       limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
+                       limot.m_damping = m_linearLimits.m_damping;
+                       limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
+                       limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
+                       limot.m_limitSoftness = m_linearLimits.m_limitSoftness;
+                       limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
+                       limot.m_maxLimitForce = btScalar(0.f);
+                       limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
+                       limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
+                       btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
+                       int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT);
+                       limot.m_normalCFM = (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
+                       limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
+                       limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
+                       if (m_useOffsetForConstraintFrame)
+                       {
+                               int indx1 = (i + 1) % 3;
+                               int indx2 = (i + 2) % 3;
+                               int rotAllowed = 1;  // rotations around orthos to current axis
+                               if (m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
+                               {
+                                       rotAllowed = 0;
+                               }
+                               row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed);
+                       }
+                       else
+                       {
+                               row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0);
+                       }
+               }
+       }
+       return row;
+}
+
+int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2* info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
+{
+       btGeneric6DofConstraint* d6constraint = this;
+       int row = row_offset;
+       //solve angular limits
+       for (int i = 0; i < 3; i++)
+       {
+               if (d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
+               {
+                       btVector3 axis = d6constraint->getAxis(i);
+                       int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT);
+                       if (!(flags & BT_6DOF_FLAGS_CFM_NORM))
+                       {
+                               m_angularLimits[i].m_normalCFM = info->cfm[0];
+                       }
+                       if (!(flags & BT_6DOF_FLAGS_CFM_STOP))
+                       {
+                               m_angularLimits[i].m_stopCFM = info->cfm[0];
+                       }
+                       if (!(flags & BT_6DOF_FLAGS_ERP_STOP))
+                       {
+                               m_angularLimits[i].m_stopERP = info->erp;
+                       }
+                       row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i),
+                                                                                transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1);
+               }
+       }
+
+       return row;
+}
+
+void btGeneric6DofConstraint::updateRHS(btScalar timeStep)
+{
+       (void)timeStep;
+}
+
+void btGeneric6DofConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
+{
+       m_frameInA = frameA;
+       m_frameInB = frameB;
+       buildJacobian();
+       calculateTransforms();
+}
+
+btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const
+{
+       return m_calculatedAxis[axis_index];
+}
+
+btScalar btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const
+{
+       return m_calculatedLinearDiff[axisIndex];
+}
+
+btScalar btGeneric6DofConstraint::getAngle(int axisIndex) const
+{
+       return m_calculatedAxisAngleDiff[axisIndex];
+}
+
+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;
+}
+
+void btGeneric6DofConstraint::calculateLinearInfo()
+{
+       m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
+       m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
+       for (int i = 0; i < 3; i++)
+       {
+               m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
+               m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
+       }
+}
+
+int btGeneric6DofConstraint::get_limit_motor_info2(
+       btRotationalLimitMotor* limot,
+       const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
+       btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed)
+{
+       int srow = row * info->rowskip;
+       bool powered = limot->m_enableMotor;
+       int limit = limot->m_currentLimit;
+       if (powered || limit)
+       {  // if the joint is powered, or has joint limits, add in the extra row
+               btScalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
+               btScalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
+               J1[srow + 0] = ax1[0];
+               J1[srow + 1] = ax1[1];
+               J1[srow + 2] = ax1[2];
+
+               J2[srow + 0] = -ax1[0];
+               J2[srow + 1] = -ax1[1];
+               J2[srow + 2] = -ax1[2];
+
+               if ((!rotational))
+               {
+                       if (m_useOffsetForConstraintFrame)
+                       {
+                               btVector3 tmpA, tmpB, relA, relB;
+                               // get vector from bodyB to frameB in WCS
+                               relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+                               // get its projection to constraint axis
+                               btVector3 projB = ax1 * relB.dot(ax1);
+                               // get vector directed from bodyB to constraint axis (and orthogonal to it)
+                               btVector3 orthoB = relB - projB;
+                               // same for bodyA
+                               relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
+                               btVector3 projA = ax1 * relA.dot(ax1);
+                               btVector3 orthoA = relA - projA;
+                               // get desired offset between frames A and B along constraint axis
+                               btScalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError;
+                               // desired vector from projection of center of bodyA to projection of center of bodyB to constraint axis
+                               btVector3 totalDist = projA + ax1 * desiredOffs - projB;
+                               // get offset vectors relA and relB
+                               relA = orthoA + totalDist * m_factA;
+                               relB = orthoB - totalDist * m_factB;
+                               tmpA = relA.cross(ax1);
+                               tmpB = relB.cross(ax1);
+                               if (m_hasStaticBody && (!rotAllowed))
+                               {
+                                       tmpA *= m_factA;
+                                       tmpB *= m_factB;
+                               }
+                               int i;
+                               for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i];
+                               for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i];
+                       }
+                       else
+                       {
+                               btVector3 ltd;  // Linear Torque Decoupling vector
+                               btVector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin();
+                               ltd = c.cross(ax1);
+                               info->m_J1angularAxis[srow + 0] = ltd[0];
+                               info->m_J1angularAxis[srow + 1] = ltd[1];
+                               info->m_J1angularAxis[srow + 2] = ltd[2];
+
+                               c = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+                               ltd = -c.cross(ax1);
+                               info->m_J2angularAxis[srow + 0] = ltd[0];
+                               info->m_J2angularAxis[srow + 1] = ltd[1];
+                               info->m_J2angularAxis[srow + 2] = ltd[2];
+                       }
+               }
+               // if we're limited low and high simultaneously, the joint motor is
+               // ineffective
+               if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
+               info->m_constraintError[srow] = btScalar(0.f);
+               if (powered)
+               {
+                       info->cfm[srow] = limot->m_normalCFM;
+                       if (!limit)
+                       {
+                               btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
+
+                               btScalar mot_fact = getMotorFactor(limot->m_currentPosition,
+                                                                                                  limot->m_loLimit,
+                                                                                                  limot->m_hiLimit,
+                                                                                                  tag_vel,
+                                                                                                  info->fps * limot->m_stopERP);
+                               info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
+                               info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
+                               info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
+                       }
+               }
+               if (limit)
+               {
+                       btScalar k = info->fps * limot->m_stopERP;
+                       if (!rotational)
+                       {
+                               info->m_constraintError[srow] += k * limot->m_currentLimitError;
+                       }
+                       else
+                       {
+                               info->m_constraintError[srow] += -k * limot->m_currentLimitError;
+                       }
+                       info->cfm[srow] = limot->m_stopCFM;
+                       if (limot->m_loLimit == limot->m_hiLimit)
+                       {  // limited low and high simultaneously
+                               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                               info->m_upperLimit[srow] = SIMD_INFINITY;
+                       }
+                       else
+                       {
+                               if (limit == 1)
+                               {
+                                       info->m_lowerLimit[srow] = 0;
+                                       info->m_upperLimit[srow] = SIMD_INFINITY;
+                               }
+                               else
+                               {
+                                       info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                                       info->m_upperLimit[srow] = 0;
+                               }
+                               // deal with bounce
+                               if (limot->m_bounce > 0)
+                               {
+                                       // calculate joint velocity
+                                       btScalar vel;
+                                       if (rotational)
+                                       {
+                                               vel = angVelA.dot(ax1);
+                                               //make sure that if no body -> angVelB == zero vec
+                                               //                        if (body1)
+                                               vel -= angVelB.dot(ax1);
+                                       }
+                                       else
+                                       {
+                                               vel = linVelA.dot(ax1);
+                                               //make sure that if no body -> angVelB == zero vec
+                                               //                        if (body1)
+                                               vel -= linVelB.dot(ax1);
+                                       }
+                                       // only apply bounce if the velocity is incoming, and if the
+                                       // resulting c[] exceeds what we already have.
+                                       if (limit == 1)
+                                       {
+                                               if (vel < 0)
+                                               {
+                                                       btScalar newc = -limot->m_bounce * vel;
+                                                       if (newc > info->m_constraintError[srow])
+                                                               info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (vel > 0)
+                                               {
+                                                       btScalar newc = -limot->m_bounce * vel;
+                                                       if (newc < info->m_constraintError[srow])
+                                                               info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               return 1;
+       }
+       else
+               return 0;
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis)
+{
+       if ((axis >= 0) && (axis < 3))
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_STOP_ERP:
+                               m_linearLimits.m_stopERP[axis] = value;
+                               m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       case BT_CONSTRAINT_STOP_CFM:
+                               m_linearLimits.m_stopCFM[axis] = value;
+                               m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                               m_linearLimits.m_normalCFM[axis] = value;
+                               m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       else if ((axis >= 3) && (axis < 6))
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_STOP_ERP:
+                               m_angularLimits[axis - 3].m_stopERP = value;
+                               m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       case BT_CONSTRAINT_STOP_CFM:
+                               m_angularLimits[axis - 3].m_stopCFM = value;
+                               m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                               m_angularLimits[axis - 3].m_normalCFM = value;
+                               m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       else
+       {
+               btAssertConstrParams(0);
+       }
+}
+
+///return the local value of parameter
+btScalar btGeneric6DofConstraint::getParam(int num, int axis) const
+{
+       btScalar retVal = 0;
+       if ((axis >= 0) && (axis < 3))
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_STOP_ERP:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_linearLimits.m_stopERP[axis];
+                               break;
+                       case BT_CONSTRAINT_STOP_CFM:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_linearLimits.m_stopCFM[axis];
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_linearLimits.m_normalCFM[axis];
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       else if ((axis >= 3) && (axis < 6))
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_STOP_ERP:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_angularLimits[axis - 3].m_stopERP;
+                               break;
+                       case BT_CONSTRAINT_STOP_CFM:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_angularLimits[axis - 3].m_stopCFM;
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+                               retVal = m_angularLimits[axis - 3].m_normalCFM;
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       else
+       {
+               btAssertConstrParams(0);
+       }
+       return retVal;
+}
+
+void btGeneric6DofConstraint::setAxis(const btVector3& axis1, const btVector3& axis2)
+{
+       btVector3 zAxis = axis1.normalized();
+       btVector3 yAxis = axis2.normalized();
+       btVector3 xAxis = yAxis.cross(zAxis);  // we want right coordinate system
+
+       btTransform frameInW;
+       frameInW.setIdentity();
+       frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+                                                                xAxis[1], yAxis[1], zAxis[1],
+                                                                xAxis[2], yAxis[2], zAxis[2]);
+
+       // now get constraint frame in local coordinate systems
+       m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+       m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+
+       calculateTransforms();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
new file mode 100644 (file)
index 0000000..1febc2b
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
+/// Added support for generic constraint solver through getInfo1/getInfo2 methods
+
+/*
+2007-09-09
+btGeneric6DofConstraint Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+#ifndef BT_GENERIC_6DOF_CONSTRAINT_H
+#define BT_GENERIC_6DOF_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btGeneric6DofConstraintData2 btGeneric6DofConstraintDoubleData2
+#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintDoubleData2"
+#else
+#define btGeneric6DofConstraintData2 btGeneric6DofConstraintData
+#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+//! 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_normalCFM;       //!< Constraint force mixing factor
+       btScalar m_stopERP;         //!< Error tolerance factor when joint is at limit
+       btScalar m_stopCFM;         //!< Constraint force mixing 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
+       btScalar m_currentPosition;    //!  current value of angle
+       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 = 6.0f;
+               m_maxLimitForce = 300.0f;
+               m_loLimit = 1.0f;
+               m_hiLimit = -1.0f;
+               m_normalCFM = 0.f;
+               m_stopERP = 0.2f;
+               m_stopCFM = 0.f;
+               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_normalCFM = limot.m_normalCFM;
+               m_stopERP = limot.m_stopERP;
+               m_stopCFM = limot.m_stopCFM;
+               m_bounce = limot.m_bounce;
+               m_currentLimit = limot.m_currentLimit;
+               m_currentLimitError = limot.m_currentLimitError;
+               m_enableMotor = limot.m_enableMotor;
+       }
+
+       //! Is limited
+       bool isLimited() const
+       {
+               if (m_loLimit > m_hiLimit) return false;
+               return true;
+       }
+
+       //! Need apply correction
+       bool needApplyTorques() const
+       {
+               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
+       btVector3 m_normalCFM;     //!< Constraint force mixing factor
+       btVector3 m_stopERP;       //!< Error tolerance factor when joint is at limit
+       btVector3 m_stopCFM;       //!< Constraint force mixing factor when joint is at limit
+                                                          //!@}
+       bool m_enableMotor[3];
+       btVector3 m_targetVelocity;     //!< target motor velocity
+       btVector3 m_maxMotorForce;      //!< max force on motor
+       btVector3 m_currentLimitError;  //!  How much is violated this limit
+       btVector3 m_currentLinearDiff;  //!  Current relative offset of constraint frames
+       int m_currentLimit[3];          //!< 0=free, 1=at lower limit, 2=at upper 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_normalCFM.setValue(0.f, 0.f, 0.f);
+               m_stopERP.setValue(0.2f, 0.2f, 0.2f);
+               m_stopCFM.setValue(0.f, 0.f, 0.f);
+
+               m_limitSoftness = 0.7f;
+               m_damping = btScalar(1.0f);
+               m_restitution = btScalar(0.5f);
+               for (int i = 0; i < 3; i++)
+               {
+                       m_enableMotor[i] = false;
+                       m_targetVelocity[i] = btScalar(0.f);
+                       m_maxMotorForce[i] = btScalar(0.f);
+               }
+       }
+
+       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;
+               m_normalCFM = other.m_normalCFM;
+               m_stopERP = other.m_stopERP;
+               m_stopCFM = other.m_stopCFM;
+
+               for (int i = 0; i < 3; i++)
+               {
+                       m_enableMotor[i] = other.m_enableMotor[i];
+                       m_targetVelocity[i] = other.m_targetVelocity[i];
+                       m_maxMotorForce[i] = other.m_maxMotorForce[i];
+               }
+       }
+
+       //! 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) const
+       {
+               return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
+       }
+       inline bool needApplyForce(int limitIndex) const
+       {
+               if (m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
+               return true;
+       }
+       int testLimitValue(int limitIndex, btScalar test_value);
+
+       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);
+};
+
+enum bt6DofFlags
+{
+       BT_6DOF_FLAGS_CFM_NORM = 1,
+       BT_6DOF_FLAGS_CFM_STOP = 2,
+       BT_6DOF_FLAGS_ERP_STOP = 4
+};
+#define BT_6DOF_FLAGS_AXIS_SHIFT 3  // bits per axis
+
+/// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
+/*!
+btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'.
+currently this limit supports rotational motors<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>
+</tr><tr>
+       <td>X</td>
+       <td>-PI</td>
+       <td>PI</td>
+</tr><tr>
+       <td>Y</td>
+       <td>-PI/2</td>
+       <td>PI/2</td>
+</tr><tr>
+       <td>Z</td>
+       <td>-PI</td>
+       <td>PI</td>
+</tr>
+</table>
+</li>
+</ul>
+
+*/
+ATTRIBUTE_ALIGNED16(class)
+btGeneric6DofConstraint : public btTypedConstraint
+{
+protected:
+       //! relative_frames
+       //!@{
+       btTransform m_frameInA;  //!< the constraint space w.r.t body A
+       btTransform m_frameInB;  //!< the constraint space w.r.t body B
+       //!@}
+
+       //! Jacobians
+       //!@{
+       btJacobianEntry m_jacLinear[3];  //!< 3 orthogonal linear constraints
+       btJacobianEntry m_jacAng[3];     //!< 3 orthogonal angular constraints
+       //!@}
+
+       //! Linear_Limit_parameters
+       //!@{
+       btTranslationalLimitMotor m_linearLimits;
+       //!@}
+
+       //! hinge_parameters
+       //!@{
+       btRotationalLimitMotor m_angularLimits[3];
+       //!@}
+
+protected:
+       //! temporal variables
+       //!@{
+       btScalar m_timeStep;
+       btTransform m_calculatedTransformA;
+       btTransform m_calculatedTransformB;
+       btVector3 m_calculatedAxisAngleDiff;
+       btVector3 m_calculatedAxis[3];
+       btVector3 m_calculatedLinearDiff;
+       btScalar m_factA;
+       btScalar m_factB;
+       bool m_hasStaticBody;
+
+       btVector3 m_AnchorPos;  // point betwen pivots of bodies A and B to solve linear axes
+
+       bool m_useLinearReferenceFrameA;
+       bool m_useOffsetForConstraintFrame;
+
+       int m_flags;
+
+       //!@}
+
+       btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other)
+       {
+               btAssert(0);
+               (void)other;
+               return *this;
+       }
+
+       int setAngularLimits(btConstraintInfo2 * info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
+
+       int setLinearLimits(btConstraintInfo2 * info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
+
+       void buildLinearJacobian(
+               btJacobianEntry & jacLinear, const btVector3& normalWorld,
+               const btVector3& pivotAInW, const btVector3& pivotBInW);
+
+       void buildAngularJacobian(btJacobianEntry & jacAngular, const btVector3& jointAxisW);
+
+       // tests linear limits
+       void calculateLinearInfo();
+
+       //! calcs the euler angles between the two bodies.
+       void calculateAngleInfo();
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       ///for backwards compatibility during the transition to 'getInfo/getInfo2'
+       bool m_useSolveConstraintObsolete;
+
+       btGeneric6DofConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA);
+       btGeneric6DofConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
+
+       //! 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(const btTransform& transA, const btTransform& transB);
+
+       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 getInfo1(btConstraintInfo1 * info);
+
+       void getInfo1NonVirtual(btConstraintInfo1 * info);
+
+       virtual void getInfo2(btConstraintInfo2 * info);
+
+       void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
+
+       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::calculateTransforms() must be called previously.
+       */
+       btScalar getAngle(int axis_index) const;
+
+       //! Get the relative position of the constraint pivot
+       /*!
+       \pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
+       */
+       btScalar getRelativePivotPosition(int axis_index) const;
+
+       void setFrames(const btTransform& frameA, const btTransform& frameB);
+
+       //! Test angular limit.
+       /*!
+       Calculates angular correction and returns true if limit needs to be corrected.
+       \pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
+       */
+       bool testAngularLimitMotor(int axis_index);
+
+       void setLinearLowerLimit(const btVector3& linearLower)
+       {
+               m_linearLimits.m_lowerLimit = linearLower;
+       }
+
+       void getLinearLowerLimit(btVector3 & linearLower) const
+       {
+               linearLower = m_linearLimits.m_lowerLimit;
+       }
+
+       void setLinearUpperLimit(const btVector3& linearUpper)
+       {
+               m_linearLimits.m_upperLimit = linearUpper;
+       }
+
+       void getLinearUpperLimit(btVector3 & linearUpper) const
+       {
+               linearUpper = m_linearLimits.m_upperLimit;
+       }
+
+       void setAngularLowerLimit(const btVector3& angularLower)
+       {
+               for (int i = 0; i < 3; i++)
+                       m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]);
+       }
+
+       void getAngularLowerLimit(btVector3 & angularLower) const
+       {
+               for (int i = 0; i < 3; i++)
+                       angularLower[i] = m_angularLimits[i].m_loLimit;
+       }
+
+       void setAngularUpperLimit(const btVector3& angularUpper)
+       {
+               for (int i = 0; i < 3; i++)
+                       m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]);
+       }
+
+       void getAngularUpperLimit(btVector3 & angularUpper) const
+       {
+               for (int i = 0; i < 3; i++)
+                       angularUpper[i] = m_angularLimits[i].m_hiLimit;
+       }
+
+       //! 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
+               {
+                       lo = btNormalizeAngle(lo);
+                       hi = btNormalizeAngle(hi);
+                       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) const
+       {
+               if (limitIndex < 3)
+               {
+                       return m_linearLimits.isLimited(limitIndex);
+               }
+               return m_angularLimits[limitIndex - 3].isLimited();
+       }
+
+       virtual void calcAnchorPos(void);  // overridable
+
+       int get_limit_motor_info2(btRotationalLimitMotor * limot,
+                                                         const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
+                                                         btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
+
+       // access for UseFrameOffset
+       bool getUseFrameOffset() const { return m_useOffsetForConstraintFrame; }
+       void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+
+       bool getUseLinearReferenceFrameA() const { return m_useLinearReferenceFrameA; }
+       void setUseLinearReferenceFrameA(bool linearReferenceFrameA) { m_useLinearReferenceFrameA = linearReferenceFrameA; }
+
+       ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+       ///If no axis is provided, it uses the default axis for this constraint.
+       virtual void setParam(int num, btScalar value, int axis = -1);
+       ///return the local value of parameter
+       virtual btScalar getParam(int num, int axis = -1) const;
+
+       void setAxis(const btVector3& axis1, const btVector3& axis2);
+
+       virtual int getFlags() const
+       {
+               return m_flags;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+struct btGeneric6DofConstraintData
+{
+       btTypedConstraintData m_typeConstraintData;
+       btTransformFloatData m_rbAFrame;  // constraint axii. Assumes z is hinge axis.
+       btTransformFloatData m_rbBFrame;
+
+       btVector3FloatData m_linearUpperLimit;
+       btVector3FloatData m_linearLowerLimit;
+
+       btVector3FloatData m_angularUpperLimit;
+       btVector3FloatData m_angularLowerLimit;
+
+       int m_useLinearReferenceFrameA;
+       int m_useOffsetForConstraintFrame;
+};
+
+struct btGeneric6DofConstraintDoubleData2
+{
+       btTypedConstraintDoubleData m_typeConstraintData;
+       btTransformDoubleData m_rbAFrame;  // constraint axii. Assumes z is hinge axis.
+       btTransformDoubleData m_rbBFrame;
+
+       btVector3DoubleData m_linearUpperLimit;
+       btVector3DoubleData m_linearLowerLimit;
+
+       btVector3DoubleData m_angularUpperLimit;
+       btVector3DoubleData m_angularLowerLimit;
+
+       int m_useLinearReferenceFrameA;
+       int m_useOffsetForConstraintFrame;
+};
+
+SIMD_FORCE_INLINE int btGeneric6DofConstraint::calculateSerializeBufferSize() const
+{
+       return sizeof(btGeneric6DofConstraintData2);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btGeneric6DofConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btGeneric6DofConstraintData2* dof = (btGeneric6DofConstraintData2*)dataBuffer;
+       btTypedConstraint::serialize(&dof->m_typeConstraintData, serializer);
+
+       m_frameInA.serialize(dof->m_rbAFrame);
+       m_frameInB.serialize(dof->m_rbBFrame);
+
+       int i;
+       for (i = 0; i < 3; i++)
+       {
+               dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit;
+               dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit;
+               dof->m_linearLowerLimit.m_floats[i] = m_linearLimits.m_lowerLimit[i];
+               dof->m_linearUpperLimit.m_floats[i] = m_linearLimits.m_upperLimit[i];
+       }
+
+       dof->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA ? 1 : 0;
+       dof->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame ? 1 : 0;
+
+       return btGeneric6DofConstraintDataName;
+}
+
+#endif  //BT_GENERIC_6DOF_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
new file mode 100644 (file)
index 0000000..39e0cc0
--- /dev/null
@@ -0,0 +1,1243 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+2014 May: btGeneric6DofSpring2Constraint is created from the original (2.82.2712) btGeneric6DofConstraint by Gabor Puhr and Tamas Umenhoffer
+Pros:
+- Much more accurate and stable in a lot of situation. (Especially when a sleeping chain of RBs connected with 6dof2 is pulled)
+- Stable and accurate spring with minimal energy loss that works with all of the solvers. (latter is not true for the original 6dof spring)
+- Servo motor functionality
+- Much more accurate bouncing. 0 really means zero bouncing (not true for the original 6odf) and there is only a minimal energy loss when the value is 1 (because of the solvers' precision)
+- Rotation order for the Euler system can be set. (One axis' freedom is still limited to pi/2)
+
+Cons:
+- It is slower than the original 6dof. There is no exact ratio, but half speed is a good estimation. (with PGS)
+- At bouncing the correct velocity is calculated, but not the correct position. (it is because of the solver can correct position or velocity, but not both.)
+*/
+
+/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
+/// Added support for generic constraint solver through getInfo1/getInfo2 methods
+
+/*
+2007-09-09
+btGeneric6DofConstraint Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+#include "btGeneric6DofSpring2Constraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include <cmath>
+#include <new>
+
+btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder)
+       : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, rbA, rbB), m_frameInA(frameInA), m_frameInB(frameInB), m_rotateOrder(rotOrder), m_flags(0)
+{
+       calculateTransforms();
+}
+
+btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbB, const btTransform& frameInB, RotateOrder rotOrder)
+       : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, getFixedBody(), rbB), m_frameInB(frameInB), m_rotateOrder(rotOrder), m_flags(0)
+{
+       ///not providing rigidbody A means implicitly using worldspace for body A
+       m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
+       calculateTransforms();
+}
+
+btScalar btGeneric6DofSpring2Constraint::btGetMatrixElem(const btMatrix3x3& mat, int index)
+{
+       int i = index % 3;
+       int j = index / 3;
+       return mat[i][j];
+}
+
+// MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz)
+{
+       // rot =  cy*cz          -cy*sz           sy
+       //        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
+       //       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
+
+       btScalar fi = btGetMatrixElem(mat, 2);
+       if (fi < btScalar(1.0f))
+       {
+               if (fi > btScalar(-1.0f))
+               {
+                       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;
+}
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerXZY(const btMatrix3x3& mat, btVector3& xyz)
+{
+       // rot =  cy*cz          -sz           sy*cz
+       //        cy*cx*sz+sx*sy  cx*cz        sy*cx*sz-cy*sx
+       //        cy*sx*sz-cx*sy  sx*cz        sy*sx*sz+cx*cy
+
+       btScalar fi = btGetMatrixElem(mat, 1);
+       if (fi < btScalar(1.0f))
+       {
+               if (fi > btScalar(-1.0f))
+               {
+                       xyz[0] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 4));
+                       xyz[1] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0));
+                       xyz[2] = btAsin(-btGetMatrixElem(mat, 1));
+                       return true;
+               }
+               else
+               {
+                       xyz[0] = -btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8));
+                       xyz[1] = btScalar(0.0);
+                       xyz[2] = SIMD_HALF_PI;
+                       return false;
+               }
+       }
+       else
+       {
+               xyz[0] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8));
+               xyz[1] = 0.0;
+               xyz[2] = -SIMD_HALF_PI;
+       }
+       return false;
+}
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerYXZ(const btMatrix3x3& mat, btVector3& xyz)
+{
+       // rot =  cy*cz+sy*sx*sz  cz*sy*sx-cy*sz  cx*sy
+       //        cx*sz           cx*cz           -sx
+       //        cy*sx*sz-cz*sy  sy*sz+cy*cz*sx  cy*cx
+
+       btScalar fi = btGetMatrixElem(mat, 5);
+       if (fi < btScalar(1.0f))
+       {
+               if (fi > btScalar(-1.0f))
+               {
+                       xyz[0] = btAsin(-btGetMatrixElem(mat, 5));
+                       xyz[1] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 8));
+                       xyz[2] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
+                       return true;
+               }
+               else
+               {
+                       xyz[0] = SIMD_HALF_PI;
+                       xyz[1] = -btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
+                       xyz[2] = btScalar(0.0);
+                       return false;
+               }
+       }
+       else
+       {
+               xyz[0] = -SIMD_HALF_PI;
+               xyz[1] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
+               xyz[2] = 0.0;
+       }
+       return false;
+}
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerYZX(const btMatrix3x3& mat, btVector3& xyz)
+{
+       // rot =  cy*cz   sy*sx-cy*cx*sz   cx*sy+cy*sz*sx
+       //        sz           cz*cx           -cz*sx
+       //        -cz*sy  cy*sx+cx*sy*sz   cy*cx-sy*sz*sx
+
+       btScalar fi = btGetMatrixElem(mat, 3);
+       if (fi < btScalar(1.0f))
+       {
+               if (fi > btScalar(-1.0f))
+               {
+                       xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 4));
+                       xyz[1] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 0));
+                       xyz[2] = btAsin(btGetMatrixElem(mat, 3));
+                       return true;
+               }
+               else
+               {
+                       xyz[0] = btScalar(0.0);
+                       xyz[1] = -btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8));
+                       xyz[2] = -SIMD_HALF_PI;
+                       return false;
+               }
+       }
+       else
+       {
+               xyz[0] = btScalar(0.0);
+               xyz[1] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8));
+               xyz[2] = SIMD_HALF_PI;
+       }
+       return false;
+}
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerZXY(const btMatrix3x3& mat, btVector3& xyz)
+{
+       // rot =  cz*cy-sz*sx*sy    -cx*sz   cz*sy+cy*sz*sx
+       //        cy*sz+cz*sx*sy     cz*cx   sz*sy-cz*xy*sx
+       //        -cx*sy              sx     cx*cy
+
+       btScalar fi = btGetMatrixElem(mat, 7);
+       if (fi < btScalar(1.0f))
+       {
+               if (fi > btScalar(-1.0f))
+               {
+                       xyz[0] = btAsin(btGetMatrixElem(mat, 7));
+                       xyz[1] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8));
+                       xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 4));
+                       return true;
+               }
+               else
+               {
+                       xyz[0] = -SIMD_HALF_PI;
+                       xyz[1] = btScalar(0.0);
+                       xyz[2] = -btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0));
+                       return false;
+               }
+       }
+       else
+       {
+               xyz[0] = SIMD_HALF_PI;
+               xyz[1] = btScalar(0.0);
+               xyz[2] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0));
+       }
+       return false;
+}
+
+bool btGeneric6DofSpring2Constraint::matrixToEulerZYX(const btMatrix3x3& mat, btVector3& xyz)
+{
+       // rot =  cz*cy   cz*sy*sx-cx*sz   sz*sx+cz*cx*sy
+       //        cy*sz   cz*cx+sz*sy*sx   cx*sz*sy-cz*sx
+       //        -sy          cy*sx         cy*cx
+
+       btScalar fi = btGetMatrixElem(mat, 6);
+       if (fi < btScalar(1.0f))
+       {
+               if (fi > btScalar(-1.0f))
+               {
+                       xyz[0] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8));
+                       xyz[1] = btAsin(-btGetMatrixElem(mat, 6));
+                       xyz[2] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 0));
+                       return true;
+               }
+               else
+               {
+                       xyz[0] = btScalar(0.0);
+                       xyz[1] = SIMD_HALF_PI;
+                       xyz[2] = -btAtan2(btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 2));
+                       return false;
+               }
+       }
+       else
+       {
+               xyz[0] = btScalar(0.0);
+               xyz[1] = -SIMD_HALF_PI;
+               xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), -btGetMatrixElem(mat, 2));
+       }
+       return false;
+}
+
+void btGeneric6DofSpring2Constraint::calculateAngleInfo()
+{
+       btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse() * m_calculatedTransformB.getBasis();
+       switch (m_rotateOrder)
+       {
+               case RO_XYZ:
+                       matrixToEulerXYZ(relative_frame, m_calculatedAxisAngleDiff);
+                       break;
+               case RO_XZY:
+                       matrixToEulerXZY(relative_frame, m_calculatedAxisAngleDiff);
+                       break;
+               case RO_YXZ:
+                       matrixToEulerYXZ(relative_frame, m_calculatedAxisAngleDiff);
+                       break;
+               case RO_YZX:
+                       matrixToEulerYZX(relative_frame, m_calculatedAxisAngleDiff);
+                       break;
+               case RO_ZXY:
+                       matrixToEulerZXY(relative_frame, m_calculatedAxisAngleDiff);
+                       break;
+               case RO_ZYX:
+                       matrixToEulerZYX(relative_frame, m_calculatedAxisAngleDiff);
+                       break;
+               default:
+                       btAssert(false);
+       }
+       // 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.
+       switch (m_rotateOrder)
+       {
+               case RO_XYZ:
+               {
+                       //Is this the "line of nodes" calculation choosing planes YZ (B coordinate system) and xy (A coordinate system)? (http://en.wikipedia.org/wiki/Euler_angles)
+                       //The two planes are non-homologous, so this is a Tait Bryan angle formalism and not a proper Euler
+                       //Extrinsic rotations are equal to the reversed order intrinsic rotations so the above xyz extrinsic rotations (axes are fixed) are the same as the zy'x" intrinsic rotations (axes are refreshed after each rotation)
+                       //that is why xy and YZ planes are chosen (this will describe a zy'x" intrinsic rotation) (see the figure on the left at http://en.wikipedia.org/wiki/Euler_angles under Tait Bryan angles)
+                       // x' = Nperp = N.cross(axis2)
+                       // y' = N = axis2.cross(axis0)
+                       // z' = z
+                       //
+                       // x" = X
+                       // y" = y'
+                       // z" = ??
+                       //in other words:
+                       //first rotate around z
+                       //second rotate around y'= z.cross(X)
+                       //third rotate around x" = X
+                       //Original XYZ extrinsic rotation order.
+                       //Planes: xy and YZ normals: z, X.  Plane intersection (N) is z.cross(X)
+                       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]);
+                       break;
+               }
+               case RO_XZY:
+               {
+                       //planes: xz,ZY normals: y, X
+                       //first rotate around y
+                       //second rotate around z'= y.cross(X)
+                       //third rotate around x" = X
+                       btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
+                       btVector3 axis1 = m_calculatedTransformA.getBasis().getColumn(1);
+                       m_calculatedAxis[2] = axis0.cross(axis1);
+                       m_calculatedAxis[0] = axis1.cross(m_calculatedAxis[2]);
+                       m_calculatedAxis[1] = m_calculatedAxis[2].cross(axis0);
+                       break;
+               }
+               case RO_YXZ:
+               {
+                       //planes: yx,XZ normals: z, Y
+                       //first rotate around z
+                       //second rotate around x'= z.cross(Y)
+                       //third rotate around y" = Y
+                       btVector3 axis1 = m_calculatedTransformB.getBasis().getColumn(1);
+                       btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
+                       m_calculatedAxis[0] = axis1.cross(axis2);
+                       m_calculatedAxis[1] = axis2.cross(m_calculatedAxis[0]);
+                       m_calculatedAxis[2] = m_calculatedAxis[0].cross(axis1);
+                       break;
+               }
+               case RO_YZX:
+               {
+                       //planes: yz,ZX normals: x, Y
+                       //first rotate around x
+                       //second rotate around z'= x.cross(Y)
+                       //third rotate around y" = Y
+                       btVector3 axis0 = m_calculatedTransformA.getBasis().getColumn(0);
+                       btVector3 axis1 = m_calculatedTransformB.getBasis().getColumn(1);
+                       m_calculatedAxis[2] = axis0.cross(axis1);
+                       m_calculatedAxis[0] = axis1.cross(m_calculatedAxis[2]);
+                       m_calculatedAxis[1] = m_calculatedAxis[2].cross(axis0);
+                       break;
+               }
+               case RO_ZXY:
+               {
+                       //planes: zx,XY normals: y, Z
+                       //first rotate around y
+                       //second rotate around x'= y.cross(Z)
+                       //third rotate around z" = Z
+                       btVector3 axis1 = m_calculatedTransformA.getBasis().getColumn(1);
+                       btVector3 axis2 = m_calculatedTransformB.getBasis().getColumn(2);
+                       m_calculatedAxis[0] = axis1.cross(axis2);
+                       m_calculatedAxis[1] = axis2.cross(m_calculatedAxis[0]);
+                       m_calculatedAxis[2] = m_calculatedAxis[0].cross(axis1);
+                       break;
+               }
+               case RO_ZYX:
+               {
+                       //planes: zy,YX normals: x, Z
+                       //first rotate around x
+                       //second rotate around y' = x.cross(Z)
+                       //third rotate around z" = Z
+                       btVector3 axis0 = m_calculatedTransformA.getBasis().getColumn(0);
+                       btVector3 axis2 = m_calculatedTransformB.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]);
+                       break;
+               }
+               default:
+                       btAssert(false);
+       }
+
+       m_calculatedAxis[0].normalize();
+       m_calculatedAxis[1].normalize();
+       m_calculatedAxis[2].normalize();
+}
+
+void btGeneric6DofSpring2Constraint::calculateTransforms()
+{
+       calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+}
+
+void btGeneric6DofSpring2Constraint::calculateTransforms(const btTransform& transA, const btTransform& transB)
+{
+       m_calculatedTransformA = transA * m_frameInA;
+       m_calculatedTransformB = transB * m_frameInB;
+       calculateLinearInfo();
+       calculateAngleInfo();
+
+       btScalar miA = getRigidBodyA().getInvMass();
+       btScalar miB = getRigidBodyB().getInvMass();
+       m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+       btScalar miS = miA + miB;
+       if (miS > btScalar(0.f))
+       {
+               m_factA = miB / miS;
+       }
+       else
+       {
+               m_factA = btScalar(0.5f);
+       }
+       m_factB = btScalar(1.0f) - m_factA;
+}
+
+void btGeneric6DofSpring2Constraint::testAngularLimitMotor(int axis_index)
+{
+       btScalar angle = m_calculatedAxisAngleDiff[axis_index];
+       angle = btAdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
+       m_angularLimits[axis_index].m_currentPosition = angle;
+       m_angularLimits[axis_index].testLimitValue(angle);
+}
+
+void btGeneric6DofSpring2Constraint::getInfo1(btConstraintInfo1* info)
+{
+       //prepare constraint
+       calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+       info->m_numConstraintRows = 0;
+       info->nub = 0;
+       int i;
+       //test linear limits
+       for (i = 0; i < 3; i++)
+       {
+               if (m_linearLimits.m_currentLimit[i] == 4)
+                       info->m_numConstraintRows += 2;
+               else if (m_linearLimits.m_currentLimit[i] != 0)
+                       info->m_numConstraintRows += 1;
+               if (m_linearLimits.m_enableMotor[i]) info->m_numConstraintRows += 1;
+               if (m_linearLimits.m_enableSpring[i]) info->m_numConstraintRows += 1;
+       }
+       //test angular limits
+       for (i = 0; i < 3; i++)
+       {
+               testAngularLimitMotor(i);
+               if (m_angularLimits[i].m_currentLimit == 4)
+                       info->m_numConstraintRows += 2;
+               else if (m_angularLimits[i].m_currentLimit != 0)
+                       info->m_numConstraintRows += 1;
+               if (m_angularLimits[i].m_enableMotor) info->m_numConstraintRows += 1;
+               if (m_angularLimits[i].m_enableSpring) info->m_numConstraintRows += 1;
+       }
+}
+
+void btGeneric6DofSpring2Constraint::getInfo2(btConstraintInfo2* info)
+{
+       const btTransform& transA = m_rbA.getCenterOfMassTransform();
+       const btTransform& transB = m_rbB.getCenterOfMassTransform();
+       const btVector3& linVelA = m_rbA.getLinearVelocity();
+       const btVector3& linVelB = m_rbB.getLinearVelocity();
+       const btVector3& angVelA = m_rbA.getAngularVelocity();
+       const btVector3& angVelB = m_rbB.getAngularVelocity();
+
+       // for stability better to solve angular limits first
+       int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
+       setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
+}
+
+int btGeneric6DofSpring2Constraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
+{
+       //solve linear limits
+       btRotationalLimitMotor2 limot;
+       for (int i = 0; i < 3; i++)
+       {
+               if (m_linearLimits.m_currentLimit[i] || m_linearLimits.m_enableMotor[i] || m_linearLimits.m_enableSpring[i])
+               {  // re-use rotational motor code
+                       limot.m_bounce = m_linearLimits.m_bounce[i];
+                       limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
+                       limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
+                       limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
+                       limot.m_currentLimitErrorHi = m_linearLimits.m_currentLimitErrorHi[i];
+                       limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
+                       limot.m_servoMotor = m_linearLimits.m_servoMotor[i];
+                       limot.m_servoTarget = m_linearLimits.m_servoTarget[i];
+                       limot.m_enableSpring = m_linearLimits.m_enableSpring[i];
+                       limot.m_springStiffness = m_linearLimits.m_springStiffness[i];
+                       limot.m_springStiffnessLimited = m_linearLimits.m_springStiffnessLimited[i];
+                       limot.m_springDamping = m_linearLimits.m_springDamping[i];
+                       limot.m_springDampingLimited = m_linearLimits.m_springDampingLimited[i];
+                       limot.m_equilibriumPoint = m_linearLimits.m_equilibriumPoint[i];
+                       limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
+                       limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
+                       limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
+                       limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
+                       btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
+                       int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT2);
+                       limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP2) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
+                       limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP2) ? m_linearLimits.m_stopERP[i] : info->erp;
+                       limot.m_motorCFM = (flags & BT_6DOF_FLAGS_CFM_MOTO2) ? m_linearLimits.m_motorCFM[i] : info->cfm[0];
+                       limot.m_motorERP = (flags & BT_6DOF_FLAGS_ERP_MOTO2) ? m_linearLimits.m_motorERP[i] : info->erp;
+
+                       //rotAllowed is a bit of a magic from the original 6dof. The calculation of it here is something that imitates the original behavior as much as possible.
+                       int indx1 = (i + 1) % 3;
+                       int indx2 = (i + 2) % 3;
+                       int rotAllowed = 1;  // rotations around orthos to current axis (it is used only when one of the body is static)
+#define D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION 1.0e-3
+                       bool indx1Violated = m_angularLimits[indx1].m_currentLimit == 1 ||
+                                                                m_angularLimits[indx1].m_currentLimit == 2 ||
+                                                                (m_angularLimits[indx1].m_currentLimit == 3 && (m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION)) ||
+                                                                (m_angularLimits[indx1].m_currentLimit == 4 && (m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION));
+                       bool indx2Violated = m_angularLimits[indx2].m_currentLimit == 1 ||
+                                                                m_angularLimits[indx2].m_currentLimit == 2 ||
+                                                                (m_angularLimits[indx2].m_currentLimit == 3 && (m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION)) ||
+                                                                (m_angularLimits[indx2].m_currentLimit == 4 && (m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION));
+                       if (indx1Violated && indx2Violated)
+                       {
+                               rotAllowed = 0;
+                       }
+                       row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed);
+               }
+       }
+       return row;
+}
+
+int btGeneric6DofSpring2Constraint::setAngularLimits(btConstraintInfo2* info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
+{
+       int row = row_offset;
+
+       //order of rotational constraint rows
+       int cIdx[] = {0, 1, 2};
+       switch (m_rotateOrder)
+       {
+               case RO_XYZ:
+                       cIdx[0] = 0;
+                       cIdx[1] = 1;
+                       cIdx[2] = 2;
+                       break;
+               case RO_XZY:
+                       cIdx[0] = 0;
+                       cIdx[1] = 2;
+                       cIdx[2] = 1;
+                       break;
+               case RO_YXZ:
+                       cIdx[0] = 1;
+                       cIdx[1] = 0;
+                       cIdx[2] = 2;
+                       break;
+               case RO_YZX:
+                       cIdx[0] = 1;
+                       cIdx[1] = 2;
+                       cIdx[2] = 0;
+                       break;
+               case RO_ZXY:
+                       cIdx[0] = 2;
+                       cIdx[1] = 0;
+                       cIdx[2] = 1;
+                       break;
+               case RO_ZYX:
+                       cIdx[0] = 2;
+                       cIdx[1] = 1;
+                       cIdx[2] = 0;
+                       break;
+               default:
+                       btAssert(false);
+       }
+
+       for (int ii = 0; ii < 3; ii++)
+       {
+               int i = cIdx[ii];
+               if (m_angularLimits[i].m_currentLimit || m_angularLimits[i].m_enableMotor || m_angularLimits[i].m_enableSpring)
+               {
+                       btVector3 axis = getAxis(i);
+                       int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT2);
+                       if (!(flags & BT_6DOF_FLAGS_CFM_STOP2))
+                       {
+                               m_angularLimits[i].m_stopCFM = info->cfm[0];
+                       }
+                       if (!(flags & BT_6DOF_FLAGS_ERP_STOP2))
+                       {
+                               m_angularLimits[i].m_stopERP = info->erp;
+                       }
+                       if (!(flags & BT_6DOF_FLAGS_CFM_MOTO2))
+                       {
+                               m_angularLimits[i].m_motorCFM = info->cfm[0];
+                       }
+                       if (!(flags & BT_6DOF_FLAGS_ERP_MOTO2))
+                       {
+                               m_angularLimits[i].m_motorERP = info->erp;
+                       }
+                       row += get_limit_motor_info2(&m_angularLimits[i], transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1);
+               }
+       }
+
+       return row;
+}
+
+void btGeneric6DofSpring2Constraint::setFrames(const btTransform& frameA, const btTransform& frameB)
+{
+       m_frameInA = frameA;
+       m_frameInB = frameB;
+       buildJacobian();
+       calculateTransforms();
+}
+
+void btGeneric6DofSpring2Constraint::calculateLinearInfo()
+{
+       m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
+       m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
+       for (int i = 0; i < 3; i++)
+       {
+               m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
+               m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
+       }
+}
+
+void btGeneric6DofSpring2Constraint::calculateJacobi(btRotationalLimitMotor2* limot, const btTransform& transA, const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed)
+{
+       btScalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
+       btScalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
+
+       J1[srow + 0] = ax1[0];
+       J1[srow + 1] = ax1[1];
+       J1[srow + 2] = ax1[2];
+
+       J2[srow + 0] = -ax1[0];
+       J2[srow + 1] = -ax1[1];
+       J2[srow + 2] = -ax1[2];
+
+       if (!rotational)
+       {
+               btVector3 tmpA, tmpB, relA, relB;
+               // get vector from bodyB to frameB in WCS
+               relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+               // same for bodyA
+               relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
+               tmpA = relA.cross(ax1);
+               tmpB = relB.cross(ax1);
+               if (m_hasStaticBody && (!rotAllowed))
+               {
+                       tmpA *= m_factA;
+                       tmpB *= m_factB;
+               }
+               int i;
+               for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i];
+               for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i];
+       }
+}
+
+int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
+       btRotationalLimitMotor2* limot,
+       const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
+       btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed)
+{
+       int count = 0;
+       int srow = row * info->rowskip;
+
+       if (limot->m_currentLimit == 4)
+       {
+               btScalar vel = rotational ? angVelA.dot(ax1) - angVelB.dot(ax1) : linVelA.dot(ax1) - linVelB.dot(ax1);
+
+               calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
+               info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitError * (rotational ? -1 : 1);
+               if (rotational)
+               {
+                       if (info->m_constraintError[srow] - vel * limot->m_stopERP > 0)
+                       {
+                               btScalar bounceerror = -limot->m_bounce * vel;
+                               if (bounceerror > info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
+                       }
+               }
+               else
+               {
+                       if (info->m_constraintError[srow] - vel * limot->m_stopERP < 0)
+                       {
+                               btScalar bounceerror = -limot->m_bounce * vel;
+                               if (bounceerror < info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
+                       }
+               }
+               info->m_lowerLimit[srow] = rotational ? 0 : -SIMD_INFINITY;
+               info->m_upperLimit[srow] = rotational ? SIMD_INFINITY : 0;
+               info->cfm[srow] = limot->m_stopCFM;
+               srow += info->rowskip;
+               ++count;
+
+               calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
+               info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitErrorHi * (rotational ? -1 : 1);
+               if (rotational)
+               {
+                       if (info->m_constraintError[srow] - vel * limot->m_stopERP < 0)
+                       {
+                               btScalar bounceerror = -limot->m_bounce * vel;
+                               if (bounceerror < info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
+                       }
+               }
+               else
+               {
+                       if (info->m_constraintError[srow] - vel * limot->m_stopERP > 0)
+                       {
+                               btScalar bounceerror = -limot->m_bounce * vel;
+                               if (bounceerror > info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
+                       }
+               }
+               info->m_lowerLimit[srow] = rotational ? -SIMD_INFINITY : 0;
+               info->m_upperLimit[srow] = rotational ? 0 : SIMD_INFINITY;
+               info->cfm[srow] = limot->m_stopCFM;
+               srow += info->rowskip;
+               ++count;
+       }
+       else if (limot->m_currentLimit == 3)
+       {
+               calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
+               info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitError * (rotational ? -1 : 1);
+               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+               info->m_upperLimit[srow] = SIMD_INFINITY;
+               info->cfm[srow] = limot->m_stopCFM;
+               srow += info->rowskip;
+               ++count;
+       }
+
+       if (limot->m_enableMotor && !limot->m_servoMotor)
+       {
+               calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
+               btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
+               btScalar mot_fact = getMotorFactor(limot->m_currentPosition,
+                                                                                  limot->m_loLimit,
+                                                                                  limot->m_hiLimit,
+                                                                                  tag_vel,
+                                                                                  info->fps * limot->m_motorERP);
+               info->m_constraintError[srow] = mot_fact * limot->m_targetVelocity;
+               info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
+               info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
+               info->cfm[srow] = limot->m_motorCFM;
+               srow += info->rowskip;
+               ++count;
+       }
+
+       if (limot->m_enableMotor && limot->m_servoMotor)
+       {
+               btScalar error = limot->m_currentPosition - limot->m_servoTarget;
+               btScalar curServoTarget = limot->m_servoTarget;
+               if (rotational)
+               {
+                       if (error > SIMD_PI)
+                       {
+                               error -= SIMD_2_PI;
+                               curServoTarget += SIMD_2_PI;
+                       }
+                       if (error < -SIMD_PI)
+                       {
+                               error += SIMD_2_PI;
+                               curServoTarget -= SIMD_2_PI;
+                       }
+               }
+
+               calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
+               btScalar targetvelocity = error < 0 ? -limot->m_targetVelocity : limot->m_targetVelocity;
+               btScalar tag_vel = -targetvelocity;
+               btScalar mot_fact;
+               if (error != 0)
+               {
+                       btScalar lowLimit;
+                       btScalar hiLimit;
+                       if (limot->m_loLimit > limot->m_hiLimit)
+                       {
+                               lowLimit = error > 0 ? curServoTarget : -SIMD_INFINITY;
+                               hiLimit = error < 0 ? curServoTarget : SIMD_INFINITY;
+                       }
+                       else
+                       {
+                               lowLimit = error > 0 && curServoTarget > limot->m_loLimit ? curServoTarget : limot->m_loLimit;
+                               hiLimit = error < 0 && curServoTarget < limot->m_hiLimit ? curServoTarget : limot->m_hiLimit;
+                       }
+                       mot_fact = getMotorFactor(limot->m_currentPosition, lowLimit, hiLimit, tag_vel, info->fps * limot->m_motorERP);
+               }
+               else
+               {
+                       mot_fact = 0;
+               }
+               info->m_constraintError[srow] = mot_fact * targetvelocity * (rotational ? -1 : 1);
+               info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
+               info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
+               info->cfm[srow] = limot->m_motorCFM;
+               srow += info->rowskip;
+               ++count;
+       }
+
+       if (limot->m_enableSpring)
+       {
+               btScalar error = limot->m_currentPosition - limot->m_equilibriumPoint;
+               calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
+
+               //btScalar cfm = 1.0 / ((1.0/info->fps)*limot->m_springStiffness+ limot->m_springDamping);
+               //if(cfm > 0.99999)
+               //      cfm = 0.99999;
+               //btScalar erp = (1.0/info->fps)*limot->m_springStiffness / ((1.0/info->fps)*limot->m_springStiffness + limot->m_springDamping);
+               //info->m_constraintError[srow] = info->fps * erp * error * (rotational ? -1.0 : 1.0);
+               //info->m_lowerLimit[srow] = -SIMD_INFINITY;
+               //info->m_upperLimit[srow] = SIMD_INFINITY;
+
+               btScalar dt = BT_ONE / info->fps;
+               btScalar kd = limot->m_springDamping;
+               btScalar ks = limot->m_springStiffness;
+               btScalar vel;
+               if (rotational)
+               {
+                       vel = angVelA.dot(ax1) - angVelB.dot(ax1);
+               }
+               else
+               {
+                       btVector3 tanVelA = angVelA.cross(m_calculatedTransformA.getOrigin() - transA.getOrigin());
+                       btVector3 tanVelB = angVelB.cross(m_calculatedTransformB.getOrigin() - transB.getOrigin());
+                       vel = (linVelA + tanVelA).dot(ax1) - (linVelB + tanVelB).dot(ax1);
+               }
+               btScalar cfm = BT_ZERO;
+               btScalar mA = BT_ONE / m_rbA.getInvMass();
+               btScalar mB = BT_ONE / m_rbB.getInvMass();
+               if (rotational)
+               {
+                       btScalar rrA = (m_calculatedTransformA.getOrigin() - transA.getOrigin()).length2();
+                       btScalar rrB = (m_calculatedTransformB.getOrigin() - transB.getOrigin()).length2();
+                       if (m_rbA.getInvMass()) mA = mA * rrA + 1 / (m_rbA.getInvInertiaTensorWorld() * ax1).length();
+                       if (m_rbB.getInvMass()) mB = mB * rrB + 1 / (m_rbB.getInvInertiaTensorWorld() * ax1).length();
+               }
+               btScalar m;
+               if (m_rbA.getInvMass() == 0) m = mB; else
+               if (m_rbB.getInvMass() == 0) m = mA; else
+                       m = mA*mB / (mA + mB);
+               btScalar angularfreq = btSqrt(ks / m);
+
+               //limit stiffness (the spring should not be sampled faster that the quarter of its angular frequency)
+               if (limot->m_springStiffnessLimited && 0.25 < angularfreq * dt)
+               {
+                       ks = BT_ONE / dt / dt / btScalar(16.0) * m;
+               }
+               //avoid damping that would blow up the spring
+               if (limot->m_springDampingLimited && kd * dt > m)
+               {
+                       kd = m / dt;
+               }
+               btScalar fs = ks * error * dt;
+               btScalar fd = -kd * (vel) * (rotational ? -1 : 1) * dt;
+               btScalar f = (fs + fd);
+
+               // after the spring force affecting the body(es) the new velocity will be
+               // vel + f / m * (rotational ? -1 : 1)
+               // so in theory this should be set here for m_constraintError
+               // (with m_constraintError we set a desired velocity for the affected body(es))
+               // however in practice any value is fine as long as it is greater than the "proper" velocity,
+               // because the m_lowerLimit and the m_upperLimit will determinate the strength of the final pulling force
+               // so it is much simpler (and more robust) just to simply use inf (with the proper sign)
+               // (Even with our best intent the "new" velocity is only an estimation. If we underestimate
+               // the "proper" velocity that will weaken the spring, however if we overestimate it, it doesn't
+               // matter, because the solver will limit it according the force limit)
+               // you may also wonder what if the current velocity (vel) so high that the pulling force will not change its direction (in this iteration)
+               // will we not request a velocity with the wrong direction ?
+               // and the answer is not, because in practice during the solving the current velocity is subtracted from the m_constraintError
+               // so the sign of the force that is really matters
+               if (m_flags & BT_6DOF_FLAGS_USE_INFINITE_ERROR)
+                       info->m_constraintError[srow] = (rotational ? -1 : 1) * (f < 0 ? -SIMD_INFINITY : SIMD_INFINITY);
+               else
+                       info->m_constraintError[srow] = vel + f / m * (rotational ? -1 : 1);
+
+               btScalar minf = f < fd ? f : fd;
+               btScalar maxf = f < fd ? fd : f;
+               if (!rotational)
+               {
+                       info->m_lowerLimit[srow] = minf > 0 ? 0 : minf;
+                       info->m_upperLimit[srow] = maxf < 0 ? 0 : maxf;
+               }
+               else
+               {
+                       info->m_lowerLimit[srow] = -maxf > 0 ? 0 : -maxf;
+                       info->m_upperLimit[srow] = -minf < 0 ? 0 : -minf;
+               }
+
+               info->cfm[srow] = cfm;
+               srow += info->rowskip;
+               ++count;
+       }
+
+       return count;
+}
+
+//override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+//If no axis is provided, it uses the default axis for this constraint.
+void btGeneric6DofSpring2Constraint::setParam(int num, btScalar value, int axis)
+{
+       if ((axis >= 0) && (axis < 3))
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_STOP_ERP:
+                               m_linearLimits.m_stopERP[axis] = value;
+                               m_flags |= BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+                               break;
+                       case BT_CONSTRAINT_STOP_CFM:
+                               m_linearLimits.m_stopCFM[axis] = value;
+                               m_flags |= BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+                               break;
+                       case BT_CONSTRAINT_ERP:
+                               m_linearLimits.m_motorERP[axis] = value;
+                               m_flags |= BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                               m_linearLimits.m_motorCFM[axis] = value;
+                               m_flags |= BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       else if ((axis >= 3) && (axis < 6))
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_STOP_ERP:
+                               m_angularLimits[axis - 3].m_stopERP = value;
+                               m_flags |= BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+                               break;
+                       case BT_CONSTRAINT_STOP_CFM:
+                               m_angularLimits[axis - 3].m_stopCFM = value;
+                               m_flags |= BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+                               break;
+                       case BT_CONSTRAINT_ERP:
+                               m_angularLimits[axis - 3].m_motorERP = value;
+                               m_flags |= BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                               m_angularLimits[axis - 3].m_motorCFM = value;
+                               m_flags |= BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       else
+       {
+               btAssertConstrParams(0);
+       }
+}
+
+//return the local value of parameter
+btScalar btGeneric6DofSpring2Constraint::getParam(int num, int axis) const
+{
+       btScalar retVal = 0;
+       if ((axis >= 0) && (axis < 3))
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_STOP_ERP:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+                               retVal = m_linearLimits.m_stopERP[axis];
+                               break;
+                       case BT_CONSTRAINT_STOP_CFM:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+                               retVal = m_linearLimits.m_stopCFM[axis];
+                               break;
+                       case BT_CONSTRAINT_ERP:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+                               retVal = m_linearLimits.m_motorERP[axis];
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+                               retVal = m_linearLimits.m_motorCFM[axis];
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       else if ((axis >= 3) && (axis < 6))
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_STOP_ERP:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+                               retVal = m_angularLimits[axis - 3].m_stopERP;
+                               break;
+                       case BT_CONSTRAINT_STOP_CFM:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+                               retVal = m_angularLimits[axis - 3].m_stopCFM;
+                               break;
+                       case BT_CONSTRAINT_ERP:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+                               retVal = m_angularLimits[axis - 3].m_motorERP;
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                               btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
+                               retVal = m_angularLimits[axis - 3].m_motorCFM;
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       else
+       {
+               btAssertConstrParams(0);
+       }
+       return retVal;
+}
+
+void btGeneric6DofSpring2Constraint::setAxis(const btVector3& axis1, const btVector3& axis2)
+{
+       btVector3 zAxis = axis1.normalized();
+       btVector3 yAxis = axis2.normalized();
+       btVector3 xAxis = yAxis.cross(zAxis);  // we want right coordinate system
+
+       btTransform frameInW;
+       frameInW.setIdentity();
+       frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+                                                                xAxis[1], yAxis[1], zAxis[1],
+                                                                xAxis[2], yAxis[2], zAxis[2]);
+
+       // now get constraint frame in local coordinate systems
+       m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+       m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+
+       calculateTransforms();
+}
+
+void btGeneric6DofSpring2Constraint::setBounce(int index, btScalar bounce)
+{
+       btAssert((index >= 0) && (index < 6));
+       if (index < 3)
+               m_linearLimits.m_bounce[index] = bounce;
+       else
+               m_angularLimits[index - 3].m_bounce = bounce;
+}
+
+void btGeneric6DofSpring2Constraint::enableMotor(int index, bool onOff)
+{
+       btAssert((index >= 0) && (index < 6));
+       if (index < 3)
+               m_linearLimits.m_enableMotor[index] = onOff;
+       else
+               m_angularLimits[index - 3].m_enableMotor = onOff;
+}
+
+void btGeneric6DofSpring2Constraint::setServo(int index, bool onOff)
+{
+       btAssert((index >= 0) && (index < 6));
+       if (index < 3)
+               m_linearLimits.m_servoMotor[index] = onOff;
+       else
+               m_angularLimits[index - 3].m_servoMotor = onOff;
+}
+
+void btGeneric6DofSpring2Constraint::setTargetVelocity(int index, btScalar velocity)
+{
+       btAssert((index >= 0) && (index < 6));
+       if (index < 3)
+               m_linearLimits.m_targetVelocity[index] = velocity;
+       else
+               m_angularLimits[index - 3].m_targetVelocity = velocity;
+}
+
+void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOrg)
+{
+       btAssert((index >= 0) && (index < 6));
+       if (index < 3)
+       {
+               m_linearLimits.m_servoTarget[index] = targetOrg;
+       }
+       else
+       {
+               //wrap between -PI and PI, see also
+               //https://stackoverflow.com/questions/4633177/c-how-to-wrap-a-float-to-the-interval-pi-pi
+
+               btScalar target = targetOrg + SIMD_PI;
+               if (1)
+               {
+                       btScalar m = target - SIMD_2_PI * std::floor(target / SIMD_2_PI);
+                       // handle boundary cases resulted from floating-point cut off:
+                       {
+                               if (m >= SIMD_2_PI)
+                               {
+                                       target = 0;
+                               }
+                               else
+                               {
+                                       if (m < 0)
+                                       {
+                                               if (SIMD_2_PI + m == SIMD_2_PI)
+                                                       target = 0;
+                                               else
+                                                       target = SIMD_2_PI + m;
+                                       }
+                                       else
+                                       {
+                                               target = m;
+                                       }
+                               }
+                       }
+                       target -= SIMD_PI;
+               }
+
+               m_angularLimits[index - 3].m_servoTarget = target;
+       }
+}
+
+void btGeneric6DofSpring2Constraint::setMaxMotorForce(int index, btScalar force)
+{
+       btAssert((index >= 0) && (index < 6));
+       if (index < 3)
+               m_linearLimits.m_maxMotorForce[index] = force;
+       else
+               m_angularLimits[index - 3].m_maxMotorForce = force;
+}
+
+void btGeneric6DofSpring2Constraint::enableSpring(int index, bool onOff)
+{
+       btAssert((index >= 0) && (index < 6));
+       if (index < 3)
+               m_linearLimits.m_enableSpring[index] = onOff;
+       else
+               m_angularLimits[index - 3].m_enableSpring = onOff;
+}
+
+void btGeneric6DofSpring2Constraint::setStiffness(int index, btScalar stiffness, bool limitIfNeeded)
+{
+       btAssert((index >= 0) && (index < 6));
+       if (index < 3)
+       {
+               m_linearLimits.m_springStiffness[index] = stiffness;
+               m_linearLimits.m_springStiffnessLimited[index] = limitIfNeeded;
+       }
+       else
+       {
+               m_angularLimits[index - 3].m_springStiffness = stiffness;
+               m_angularLimits[index - 3].m_springStiffnessLimited = limitIfNeeded;
+       }
+}
+
+void btGeneric6DofSpring2Constraint::setDamping(int index, btScalar damping, bool limitIfNeeded)
+{
+       btAssert((index >= 0) && (index < 6));
+       if (index < 3)
+       {
+               m_linearLimits.m_springDamping[index] = damping;
+               m_linearLimits.m_springDampingLimited[index] = limitIfNeeded;
+       }
+       else
+       {
+               m_angularLimits[index - 3].m_springDamping = damping;
+               m_angularLimits[index - 3].m_springDampingLimited = limitIfNeeded;
+       }
+}
+
+void btGeneric6DofSpring2Constraint::setEquilibriumPoint()
+{
+       calculateTransforms();
+       int i;
+       for (i = 0; i < 3; i++)
+               m_linearLimits.m_equilibriumPoint[i] = m_calculatedLinearDiff[i];
+       for (i = 0; i < 3; i++)
+               m_angularLimits[i].m_equilibriumPoint = m_calculatedAxisAngleDiff[i];
+}
+
+void btGeneric6DofSpring2Constraint::setEquilibriumPoint(int index)
+{
+       btAssert((index >= 0) && (index < 6));
+       calculateTransforms();
+       if (index < 3)
+               m_linearLimits.m_equilibriumPoint[index] = m_calculatedLinearDiff[index];
+       else
+               m_angularLimits[index - 3].m_equilibriumPoint = m_calculatedAxisAngleDiff[index - 3];
+}
+
+void btGeneric6DofSpring2Constraint::setEquilibriumPoint(int index, btScalar val)
+{
+       btAssert((index >= 0) && (index < 6));
+       if (index < 3)
+               m_linearLimits.m_equilibriumPoint[index] = val;
+       else
+               m_angularLimits[index - 3].m_equilibriumPoint = val;
+}
+
+//////////////////////////// btRotationalLimitMotor2 ////////////////////////////////////
+
+void btRotationalLimitMotor2::testLimitValue(btScalar test_value)
+{
+       //we can't normalize the angles here because we would lost the sign that we use later, but it doesn't seem to be a problem
+       if (m_loLimit > m_hiLimit)
+       {
+               m_currentLimit = 0;
+               m_currentLimitError = btScalar(0.f);
+       }
+       else if (m_loLimit == m_hiLimit)
+       {
+               m_currentLimitError = test_value - m_loLimit;
+               m_currentLimit = 3;
+       }
+       else
+       {
+               m_currentLimitError = test_value - m_loLimit;
+               m_currentLimitErrorHi = test_value - m_hiLimit;
+               m_currentLimit = 4;
+       }
+}
+
+//////////////////////////// btTranslationalLimitMotor2 ////////////////////////////////////
+
+void btTranslationalLimitMotor2::testLimitValue(int limitIndex, btScalar test_value)
+{
+       btScalar loLimit = m_lowerLimit[limitIndex];
+       btScalar hiLimit = m_upperLimit[limitIndex];
+       if (loLimit > hiLimit)
+       {
+               m_currentLimitError[limitIndex] = 0;
+               m_currentLimit[limitIndex] = 0;
+       }
+       else if (loLimit == hiLimit)
+       {
+               m_currentLimitError[limitIndex] = test_value - loLimit;
+               m_currentLimit[limitIndex] = 3;
+       }
+       else
+       {
+               m_currentLimitError[limitIndex] = test_value - loLimit;
+               m_currentLimitErrorHi[limitIndex] = test_value - hiLimit;
+               m_currentLimit[limitIndex] = 4;
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
new file mode 100644 (file)
index 0000000..d2fe24b
--- /dev/null
@@ -0,0 +1,667 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+2014 May: btGeneric6DofSpring2Constraint is created from the original (2.82.2712) btGeneric6DofConstraint by Gabor Puhr and Tamas Umenhoffer
+Pros:
+- Much more accurate and stable in a lot of situation. (Especially when a sleeping chain of RBs connected with 6dof2 is pulled)
+- Stable and accurate spring with minimal energy loss that works with all of the solvers. (latter is not true for the original 6dof spring)
+- Servo motor functionality
+- Much more accurate bouncing. 0 really means zero bouncing (not true for the original 6odf) and there is only a minimal energy loss when the value is 1 (because of the solvers' precision)
+- Rotation order for the Euler system can be set. (One axis' freedom is still limited to pi/2)
+
+Cons:
+- It is slower than the original 6dof. There is no exact ratio, but half speed is a good estimation.
+- At bouncing the correct velocity is calculated, but not the correct position. (it is because of the solver can correct position or velocity, but not both.)
+*/
+
+/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
+/// Added support for generic constraint solver through getInfo1/getInfo2 methods
+
+/*
+2007-09-09
+btGeneric6DofConstraint Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+#ifndef BT_GENERIC_6DOF_CONSTRAINT2_H
+#define BT_GENERIC_6DOF_CONSTRAINT2_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintDoubleData2
+#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintDoubleData2"
+#else
+#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintData
+#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+enum RotateOrder
+{
+       RO_XYZ = 0,
+       RO_XZY,
+       RO_YXZ,
+       RO_YZX,
+       RO_ZXY,
+       RO_ZYX
+};
+
+class btRotationalLimitMotor2
+{
+public:
+       // upper < lower means free
+       // upper == lower means locked
+       // upper > lower means limited
+       btScalar m_loLimit;
+       btScalar m_hiLimit;
+       btScalar m_bounce;
+       btScalar m_stopERP;
+       btScalar m_stopCFM;
+       btScalar m_motorERP;
+       btScalar m_motorCFM;
+       bool m_enableMotor;
+       btScalar m_targetVelocity;
+       btScalar m_maxMotorForce;
+       bool m_servoMotor;
+       btScalar m_servoTarget;
+       bool m_enableSpring;
+       btScalar m_springStiffness;
+       bool m_springStiffnessLimited;
+       btScalar m_springDamping;
+       bool m_springDampingLimited;
+       btScalar m_equilibriumPoint;
+
+       btScalar m_currentLimitError;
+       btScalar m_currentLimitErrorHi;
+       btScalar m_currentPosition;
+       int m_currentLimit;
+
+       btRotationalLimitMotor2()
+       {
+               m_loLimit = 1.0f;
+               m_hiLimit = -1.0f;
+               m_bounce = 0.0f;
+               m_stopERP = 0.2f;
+               m_stopCFM = 0.f;
+               m_motorERP = 0.9f;
+               m_motorCFM = 0.f;
+               m_enableMotor = false;
+               m_targetVelocity = 0;
+               m_maxMotorForce = 6.0f;
+               m_servoMotor = false;
+               m_servoTarget = 0;
+               m_enableSpring = false;
+               m_springStiffness = 0;
+               m_springStiffnessLimited = false;
+               m_springDamping = 0;
+               m_springDampingLimited = false;
+               m_equilibriumPoint = 0;
+
+               m_currentLimitError = 0;
+               m_currentLimitErrorHi = 0;
+               m_currentPosition = 0;
+               m_currentLimit = 0;
+       }
+
+       btRotationalLimitMotor2(const btRotationalLimitMotor2& limot)
+       {
+               m_loLimit = limot.m_loLimit;
+               m_hiLimit = limot.m_hiLimit;
+               m_bounce = limot.m_bounce;
+               m_stopERP = limot.m_stopERP;
+               m_stopCFM = limot.m_stopCFM;
+               m_motorERP = limot.m_motorERP;
+               m_motorCFM = limot.m_motorCFM;
+               m_enableMotor = limot.m_enableMotor;
+               m_targetVelocity = limot.m_targetVelocity;
+               m_maxMotorForce = limot.m_maxMotorForce;
+               m_servoMotor = limot.m_servoMotor;
+               m_servoTarget = limot.m_servoTarget;
+               m_enableSpring = limot.m_enableSpring;
+               m_springStiffness = limot.m_springStiffness;
+               m_springStiffnessLimited = limot.m_springStiffnessLimited;
+               m_springDamping = limot.m_springDamping;
+               m_springDampingLimited = limot.m_springDampingLimited;
+               m_equilibriumPoint = limot.m_equilibriumPoint;
+
+               m_currentLimitError = limot.m_currentLimitError;
+               m_currentLimitErrorHi = limot.m_currentLimitErrorHi;
+               m_currentPosition = limot.m_currentPosition;
+               m_currentLimit = limot.m_currentLimit;
+       }
+
+       bool isLimited()
+       {
+               if (m_loLimit > m_hiLimit) return false;
+               return true;
+       }
+
+       void testLimitValue(btScalar test_value);
+};
+
+class btTranslationalLimitMotor2
+{
+public:
+       // upper < lower means free
+       // upper == lower means locked
+       // upper > lower means limited
+       btVector3 m_lowerLimit;
+       btVector3 m_upperLimit;
+       btVector3 m_bounce;
+       btVector3 m_stopERP;
+       btVector3 m_stopCFM;
+       btVector3 m_motorERP;
+       btVector3 m_motorCFM;
+       bool m_enableMotor[3];
+       bool m_servoMotor[3];
+       bool m_enableSpring[3];
+       btVector3 m_servoTarget;
+       btVector3 m_springStiffness;
+       bool m_springStiffnessLimited[3];
+       btVector3 m_springDamping;
+       bool m_springDampingLimited[3];
+       btVector3 m_equilibriumPoint;
+       btVector3 m_targetVelocity;
+       btVector3 m_maxMotorForce;
+
+       btVector3 m_currentLimitError;
+       btVector3 m_currentLimitErrorHi;
+       btVector3 m_currentLinearDiff;
+       int m_currentLimit[3];
+
+       btTranslationalLimitMotor2()
+       {
+               m_lowerLimit.setValue(0.f, 0.f, 0.f);
+               m_upperLimit.setValue(0.f, 0.f, 0.f);
+               m_bounce.setValue(0.f, 0.f, 0.f);
+               m_stopERP.setValue(0.2f, 0.2f, 0.2f);
+               m_stopCFM.setValue(0.f, 0.f, 0.f);
+               m_motorERP.setValue(0.9f, 0.9f, 0.9f);
+               m_motorCFM.setValue(0.f, 0.f, 0.f);
+
+               m_currentLimitError.setValue(0.f, 0.f, 0.f);
+               m_currentLimitErrorHi.setValue(0.f, 0.f, 0.f);
+               m_currentLinearDiff.setValue(0.f, 0.f, 0.f);
+
+               for (int i = 0; i < 3; i++)
+               {
+                       m_enableMotor[i] = false;
+                       m_servoMotor[i] = false;
+                       m_enableSpring[i] = false;
+                       m_servoTarget[i] = btScalar(0.f);
+                       m_springStiffness[i] = btScalar(0.f);
+                       m_springStiffnessLimited[i] = false;
+                       m_springDamping[i] = btScalar(0.f);
+                       m_springDampingLimited[i] = false;
+                       m_equilibriumPoint[i] = btScalar(0.f);
+                       m_targetVelocity[i] = btScalar(0.f);
+                       m_maxMotorForce[i] = btScalar(0.f);
+
+                       m_currentLimit[i] = 0;
+               }
+       }
+
+       btTranslationalLimitMotor2(const btTranslationalLimitMotor2& other)
+       {
+               m_lowerLimit = other.m_lowerLimit;
+               m_upperLimit = other.m_upperLimit;
+               m_bounce = other.m_bounce;
+               m_stopERP = other.m_stopERP;
+               m_stopCFM = other.m_stopCFM;
+               m_motorERP = other.m_motorERP;
+               m_motorCFM = other.m_motorCFM;
+
+               m_currentLimitError = other.m_currentLimitError;
+               m_currentLimitErrorHi = other.m_currentLimitErrorHi;
+               m_currentLinearDiff = other.m_currentLinearDiff;
+
+               for (int i = 0; i < 3; i++)
+               {
+                       m_enableMotor[i] = other.m_enableMotor[i];
+                       m_servoMotor[i] = other.m_servoMotor[i];
+                       m_enableSpring[i] = other.m_enableSpring[i];
+                       m_servoTarget[i] = other.m_servoTarget[i];
+                       m_springStiffness[i] = other.m_springStiffness[i];
+                       m_springStiffnessLimited[i] = other.m_springStiffnessLimited[i];
+                       m_springDamping[i] = other.m_springDamping[i];
+                       m_springDampingLimited[i] = other.m_springDampingLimited[i];
+                       m_equilibriumPoint[i] = other.m_equilibriumPoint[i];
+                       m_targetVelocity[i] = other.m_targetVelocity[i];
+                       m_maxMotorForce[i] = other.m_maxMotorForce[i];
+
+                       m_currentLimit[i] = other.m_currentLimit[i];
+               }
+       }
+
+       inline bool isLimited(int limitIndex)
+       {
+               return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
+       }
+
+       void testLimitValue(int limitIndex, btScalar test_value);
+};
+
+enum bt6DofFlags2
+{
+       BT_6DOF_FLAGS_CFM_STOP2 = 1,
+       BT_6DOF_FLAGS_ERP_STOP2 = 2,
+       BT_6DOF_FLAGS_CFM_MOTO2 = 4,
+       BT_6DOF_FLAGS_ERP_MOTO2 = 8,
+       BT_6DOF_FLAGS_USE_INFINITE_ERROR = (1<<16)
+};
+#define BT_6DOF_FLAGS_AXIS_SHIFT2 4  // bits per axis
+
+ATTRIBUTE_ALIGNED16(class)
+btGeneric6DofSpring2Constraint : public btTypedConstraint
+{
+protected:
+       btTransform m_frameInA;
+       btTransform m_frameInB;
+
+       btJacobianEntry m_jacLinear[3];
+       btJacobianEntry m_jacAng[3];
+
+       btTranslationalLimitMotor2 m_linearLimits;
+       btRotationalLimitMotor2 m_angularLimits[3];
+
+       RotateOrder m_rotateOrder;
+
+protected:
+       btTransform m_calculatedTransformA;
+       btTransform m_calculatedTransformB;
+       btVector3 m_calculatedAxisAngleDiff;
+       btVector3 m_calculatedAxis[3];
+       btVector3 m_calculatedLinearDiff;
+       btScalar m_factA;
+       btScalar m_factB;
+       bool m_hasStaticBody;
+       int m_flags;
+
+       btGeneric6DofSpring2Constraint& operator=(const btGeneric6DofSpring2Constraint&)
+       {
+               btAssert(0);
+               return *this;
+       }
+
+       int setAngularLimits(btConstraintInfo2 * info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
+       int setLinearLimits(btConstraintInfo2 * info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
+
+       void calculateLinearInfo();
+       void calculateAngleInfo();
+       void testAngularLimitMotor(int axis_index);
+
+       void calculateJacobi(btRotationalLimitMotor2 * limot, const btTransform& transA, const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed);
+       int get_limit_motor_info2(btRotationalLimitMotor2 * limot,
+                                                         const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
+                                                         btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btGeneric6DofSpring2Constraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ);
+       btGeneric6DofSpring2Constraint(btRigidBody & rbB, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ);
+
+       virtual void buildJacobian() {}
+       virtual void getInfo1(btConstraintInfo1 * info);
+       virtual void getInfo2(btConstraintInfo2 * info);
+       virtual int calculateSerializeBufferSize() const;
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+
+       btRotationalLimitMotor2* getRotationalLimitMotor(int index) { return &m_angularLimits[index]; }
+       btTranslationalLimitMotor2* getTranslationalLimitMotor() { return &m_linearLimits; }
+
+       // Calculates the global transform for the joint offset for body A an B, and also calculates the angle differences between the bodies.
+       void calculateTransforms(const btTransform& transA, const btTransform& transB);
+       void calculateTransforms();
+
+       // Gets the global transform of the offset for body A
+       const btTransform& getCalculatedTransformA() const { return m_calculatedTransformA; }
+       // Gets the global transform of the offset for body B
+       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; }
+
+       // Get the rotation axis in global coordinates ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
+       btVector3 getAxis(int axis_index) const { return m_calculatedAxis[axis_index]; }
+
+       // Get the relative Euler angle ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
+       btScalar getAngle(int axis_index) const { return m_calculatedAxisAngleDiff[axis_index]; }
+
+       // Get the relative position of the constraint pivot ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
+       btScalar getRelativePivotPosition(int axis_index) const { return m_calculatedLinearDiff[axis_index]; }
+
+       void setFrames(const btTransform& frameA, const btTransform& frameB);
+
+       void setLinearLowerLimit(const btVector3& linearLower) { m_linearLimits.m_lowerLimit = linearLower; }
+       void getLinearLowerLimit(btVector3 & linearLower) { linearLower = m_linearLimits.m_lowerLimit; }
+       void setLinearUpperLimit(const btVector3& linearUpper) { m_linearLimits.m_upperLimit = linearUpper; }
+       void getLinearUpperLimit(btVector3 & linearUpper) { linearUpper = m_linearLimits.m_upperLimit; }
+
+       void setAngularLowerLimit(const btVector3& angularLower)
+       {
+               for (int i = 0; i < 3; i++)
+                       m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]);
+       }
+
+       void setAngularLowerLimitReversed(const btVector3& angularLower)
+       {
+               for (int i = 0; i < 3; i++)
+                       m_angularLimits[i].m_hiLimit = btNormalizeAngle(-angularLower[i]);
+       }
+
+       void getAngularLowerLimit(btVector3 & angularLower)
+       {
+               for (int i = 0; i < 3; i++)
+                       angularLower[i] = m_angularLimits[i].m_loLimit;
+       }
+
+       void getAngularLowerLimitReversed(btVector3 & angularLower)
+       {
+               for (int i = 0; i < 3; i++)
+                       angularLower[i] = -m_angularLimits[i].m_hiLimit;
+       }
+
+       void setAngularUpperLimit(const btVector3& angularUpper)
+       {
+               for (int i = 0; i < 3; i++)
+                       m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]);
+       }
+
+       void setAngularUpperLimitReversed(const btVector3& angularUpper)
+       {
+               for (int i = 0; i < 3; i++)
+                       m_angularLimits[i].m_loLimit = btNormalizeAngle(-angularUpper[i]);
+       }
+
+       void getAngularUpperLimit(btVector3 & angularUpper)
+       {
+               for (int i = 0; i < 3; i++)
+                       angularUpper[i] = m_angularLimits[i].m_hiLimit;
+       }
+
+       void getAngularUpperLimitReversed(btVector3 & angularUpper)
+       {
+               for (int i = 0; i < 3; i++)
+                       angularUpper[i] = -m_angularLimits[i].m_loLimit;
+       }
+
+       //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
+               {
+                       lo = btNormalizeAngle(lo);
+                       hi = btNormalizeAngle(hi);
+                       m_angularLimits[axis - 3].m_loLimit = lo;
+                       m_angularLimits[axis - 3].m_hiLimit = hi;
+               }
+       }
+
+       void setLimitReversed(int axis, btScalar lo, btScalar hi)
+       {
+               if (axis < 3)
+               {
+                       m_linearLimits.m_lowerLimit[axis] = lo;
+                       m_linearLimits.m_upperLimit[axis] = hi;
+               }
+               else
+               {
+                       lo = btNormalizeAngle(lo);
+                       hi = btNormalizeAngle(hi);
+                       m_angularLimits[axis - 3].m_hiLimit = -lo;
+                       m_angularLimits[axis - 3].m_loLimit = -hi;
+               }
+       }
+
+       bool isLimited(int limitIndex)
+       {
+               if (limitIndex < 3)
+               {
+                       return m_linearLimits.isLimited(limitIndex);
+               }
+               return m_angularLimits[limitIndex - 3].isLimited();
+       }
+
+       void setRotationOrder(RotateOrder order) { m_rotateOrder = order; }
+       RotateOrder getRotationOrder() { return m_rotateOrder; }
+
+       void setAxis(const btVector3& axis1, const btVector3& axis2);
+
+       void setBounce(int index, btScalar bounce);
+
+       void enableMotor(int index, bool onOff);
+       void setServo(int index, bool onOff);  // set the type of the motor (servo or not) (the motor has to be turned on for servo also)
+       void setTargetVelocity(int index, btScalar velocity);
+       void setServoTarget(int index, btScalar target);
+       void setMaxMotorForce(int index, btScalar force);
+
+       void enableSpring(int index, bool onOff);
+       void setStiffness(int index, btScalar stiffness, bool limitIfNeeded = true);  // if limitIfNeeded is true the system will automatically limit the stiffness in necessary situations where otherwise the spring would move unrealistically too widely
+       void setDamping(int index, btScalar damping, bool limitIfNeeded = true);      // if limitIfNeeded is true the system will automatically limit the damping in necessary situations where otherwise the spring would blow up
+       void setEquilibriumPoint();                                                   // set the current constraint position/orientation as an equilibrium point for all DOF
+       void setEquilibriumPoint(int index);                                          // set the current constraint position/orientation as an equilibrium point for given DOF
+       void setEquilibriumPoint(int index, btScalar val);
+
+       //override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+       //If no axis is provided, it uses the default axis for this constraint.
+       virtual void setParam(int num, btScalar value, int axis = -1);
+       virtual btScalar getParam(int num, int axis = -1) const;
+
+       static btScalar btGetMatrixElem(const btMatrix3x3& mat, int index);
+       static bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz);
+       static bool matrixToEulerXZY(const btMatrix3x3& mat, btVector3& xyz);
+       static bool matrixToEulerYXZ(const btMatrix3x3& mat, btVector3& xyz);
+       static bool matrixToEulerYZX(const btMatrix3x3& mat, btVector3& xyz);
+       static bool matrixToEulerZXY(const btMatrix3x3& mat, btVector3& xyz);
+       static bool matrixToEulerZYX(const btMatrix3x3& mat, btVector3& xyz);
+};
+
+struct btGeneric6DofSpring2ConstraintData
+{
+       btTypedConstraintData m_typeConstraintData;
+       btTransformFloatData m_rbAFrame;
+       btTransformFloatData m_rbBFrame;
+
+       btVector3FloatData m_linearUpperLimit;
+       btVector3FloatData m_linearLowerLimit;
+       btVector3FloatData m_linearBounce;
+       btVector3FloatData m_linearStopERP;
+       btVector3FloatData m_linearStopCFM;
+       btVector3FloatData m_linearMotorERP;
+       btVector3FloatData m_linearMotorCFM;
+       btVector3FloatData m_linearTargetVelocity;
+       btVector3FloatData m_linearMaxMotorForce;
+       btVector3FloatData m_linearServoTarget;
+       btVector3FloatData m_linearSpringStiffness;
+       btVector3FloatData m_linearSpringDamping;
+       btVector3FloatData m_linearEquilibriumPoint;
+       char m_linearEnableMotor[4];
+       char m_linearServoMotor[4];
+       char m_linearEnableSpring[4];
+       char m_linearSpringStiffnessLimited[4];
+       char m_linearSpringDampingLimited[4];
+       char m_padding1[4];
+
+       btVector3FloatData m_angularUpperLimit;
+       btVector3FloatData m_angularLowerLimit;
+       btVector3FloatData m_angularBounce;
+       btVector3FloatData m_angularStopERP;
+       btVector3FloatData m_angularStopCFM;
+       btVector3FloatData m_angularMotorERP;
+       btVector3FloatData m_angularMotorCFM;
+       btVector3FloatData m_angularTargetVelocity;
+       btVector3FloatData m_angularMaxMotorForce;
+       btVector3FloatData m_angularServoTarget;
+       btVector3FloatData m_angularSpringStiffness;
+       btVector3FloatData m_angularSpringDamping;
+       btVector3FloatData m_angularEquilibriumPoint;
+       char m_angularEnableMotor[4];
+       char m_angularServoMotor[4];
+       char m_angularEnableSpring[4];
+       char m_angularSpringStiffnessLimited[4];
+       char m_angularSpringDampingLimited[4];
+
+       int m_rotateOrder;
+};
+
+struct btGeneric6DofSpring2ConstraintDoubleData2
+{
+       btTypedConstraintDoubleData m_typeConstraintData;
+       btTransformDoubleData m_rbAFrame;
+       btTransformDoubleData m_rbBFrame;
+
+       btVector3DoubleData m_linearUpperLimit;
+       btVector3DoubleData m_linearLowerLimit;
+       btVector3DoubleData m_linearBounce;
+       btVector3DoubleData m_linearStopERP;
+       btVector3DoubleData m_linearStopCFM;
+       btVector3DoubleData m_linearMotorERP;
+       btVector3DoubleData m_linearMotorCFM;
+       btVector3DoubleData m_linearTargetVelocity;
+       btVector3DoubleData m_linearMaxMotorForce;
+       btVector3DoubleData m_linearServoTarget;
+       btVector3DoubleData m_linearSpringStiffness;
+       btVector3DoubleData m_linearSpringDamping;
+       btVector3DoubleData m_linearEquilibriumPoint;
+       char m_linearEnableMotor[4];
+       char m_linearServoMotor[4];
+       char m_linearEnableSpring[4];
+       char m_linearSpringStiffnessLimited[4];
+       char m_linearSpringDampingLimited[4];
+       char m_padding1[4];
+
+       btVector3DoubleData m_angularUpperLimit;
+       btVector3DoubleData m_angularLowerLimit;
+       btVector3DoubleData m_angularBounce;
+       btVector3DoubleData m_angularStopERP;
+       btVector3DoubleData m_angularStopCFM;
+       btVector3DoubleData m_angularMotorERP;
+       btVector3DoubleData m_angularMotorCFM;
+       btVector3DoubleData m_angularTargetVelocity;
+       btVector3DoubleData m_angularMaxMotorForce;
+       btVector3DoubleData m_angularServoTarget;
+       btVector3DoubleData m_angularSpringStiffness;
+       btVector3DoubleData m_angularSpringDamping;
+       btVector3DoubleData m_angularEquilibriumPoint;
+       char m_angularEnableMotor[4];
+       char m_angularServoMotor[4];
+       char m_angularEnableSpring[4];
+       char m_angularSpringStiffnessLimited[4];
+       char m_angularSpringDampingLimited[4];
+
+       int m_rotateOrder;
+};
+
+SIMD_FORCE_INLINE int btGeneric6DofSpring2Constraint::calculateSerializeBufferSize() const
+{
+       return sizeof(btGeneric6DofSpring2ConstraintData2);
+}
+
+SIMD_FORCE_INLINE const char* btGeneric6DofSpring2Constraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btGeneric6DofSpring2ConstraintData2* dof = (btGeneric6DofSpring2ConstraintData2*)dataBuffer;
+       btTypedConstraint::serialize(&dof->m_typeConstraintData, serializer);
+
+       m_frameInA.serialize(dof->m_rbAFrame);
+       m_frameInB.serialize(dof->m_rbBFrame);
+
+       int i;
+       for (i = 0; i < 3; i++)
+       {
+               dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit;
+               dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit;
+               dof->m_angularBounce.m_floats[i] = m_angularLimits[i].m_bounce;
+               dof->m_angularStopERP.m_floats[i] = m_angularLimits[i].m_stopERP;
+               dof->m_angularStopCFM.m_floats[i] = m_angularLimits[i].m_stopCFM;
+               dof->m_angularMotorERP.m_floats[i] = m_angularLimits[i].m_motorERP;
+               dof->m_angularMotorCFM.m_floats[i] = m_angularLimits[i].m_motorCFM;
+               dof->m_angularTargetVelocity.m_floats[i] = m_angularLimits[i].m_targetVelocity;
+               dof->m_angularMaxMotorForce.m_floats[i] = m_angularLimits[i].m_maxMotorForce;
+               dof->m_angularServoTarget.m_floats[i] = m_angularLimits[i].m_servoTarget;
+               dof->m_angularSpringStiffness.m_floats[i] = m_angularLimits[i].m_springStiffness;
+               dof->m_angularSpringDamping.m_floats[i] = m_angularLimits[i].m_springDamping;
+               dof->m_angularEquilibriumPoint.m_floats[i] = m_angularLimits[i].m_equilibriumPoint;
+       }
+       dof->m_angularLowerLimit.m_floats[3] = 0;
+       dof->m_angularUpperLimit.m_floats[3] = 0;
+       dof->m_angularBounce.m_floats[3] = 0;
+       dof->m_angularStopERP.m_floats[3] = 0;
+       dof->m_angularStopCFM.m_floats[3] = 0;
+       dof->m_angularMotorERP.m_floats[3] = 0;
+       dof->m_angularMotorCFM.m_floats[3] = 0;
+       dof->m_angularTargetVelocity.m_floats[3] = 0;
+       dof->m_angularMaxMotorForce.m_floats[3] = 0;
+       dof->m_angularServoTarget.m_floats[3] = 0;
+       dof->m_angularSpringStiffness.m_floats[3] = 0;
+       dof->m_angularSpringDamping.m_floats[3] = 0;
+       dof->m_angularEquilibriumPoint.m_floats[3] = 0;
+       for (i = 0; i < 4; i++)
+       {
+               dof->m_angularEnableMotor[i] = i < 3 ? (m_angularLimits[i].m_enableMotor ? 1 : 0) : 0;
+               dof->m_angularServoMotor[i] = i < 3 ? (m_angularLimits[i].m_servoMotor ? 1 : 0) : 0;
+               dof->m_angularEnableSpring[i] = i < 3 ? (m_angularLimits[i].m_enableSpring ? 1 : 0) : 0;
+               dof->m_angularSpringStiffnessLimited[i] = i < 3 ? (m_angularLimits[i].m_springStiffnessLimited ? 1 : 0) : 0;
+               dof->m_angularSpringDampingLimited[i] = i < 3 ? (m_angularLimits[i].m_springDampingLimited ? 1 : 0) : 0;
+       }
+
+       m_linearLimits.m_lowerLimit.serialize(dof->m_linearLowerLimit);
+       m_linearLimits.m_upperLimit.serialize(dof->m_linearUpperLimit);
+       m_linearLimits.m_bounce.serialize(dof->m_linearBounce);
+       m_linearLimits.m_stopERP.serialize(dof->m_linearStopERP);
+       m_linearLimits.m_stopCFM.serialize(dof->m_linearStopCFM);
+       m_linearLimits.m_motorERP.serialize(dof->m_linearMotorERP);
+       m_linearLimits.m_motorCFM.serialize(dof->m_linearMotorCFM);
+       m_linearLimits.m_targetVelocity.serialize(dof->m_linearTargetVelocity);
+       m_linearLimits.m_maxMotorForce.serialize(dof->m_linearMaxMotorForce);
+       m_linearLimits.m_servoTarget.serialize(dof->m_linearServoTarget);
+       m_linearLimits.m_springStiffness.serialize(dof->m_linearSpringStiffness);
+       m_linearLimits.m_springDamping.serialize(dof->m_linearSpringDamping);
+       m_linearLimits.m_equilibriumPoint.serialize(dof->m_linearEquilibriumPoint);
+       for (i = 0; i < 4; i++)
+       {
+               dof->m_linearEnableMotor[i] = i < 3 ? (m_linearLimits.m_enableMotor[i] ? 1 : 0) : 0;
+               dof->m_linearServoMotor[i] = i < 3 ? (m_linearLimits.m_servoMotor[i] ? 1 : 0) : 0;
+               dof->m_linearEnableSpring[i] = i < 3 ? (m_linearLimits.m_enableSpring[i] ? 1 : 0) : 0;
+               dof->m_linearSpringStiffnessLimited[i] = i < 3 ? (m_linearLimits.m_springStiffnessLimited[i] ? 1 : 0) : 0;
+               dof->m_linearSpringDampingLimited[i] = i < 3 ? (m_linearLimits.m_springDampingLimited[i] ? 1 : 0) : 0;
+       }
+
+       dof->m_rotateOrder = m_rotateOrder;
+
+       dof->m_padding1[0] = 0;
+       dof->m_padding1[1] = 0;
+       dof->m_padding1[2] = 0;
+       dof->m_padding1[3] = 0;
+
+       return btGeneric6DofSpring2ConstraintDataName;
+}
+
+#endif  //BT_GENERIC_6DOF_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
new file mode 100644 (file)
index 0000000..8baf52b
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btGeneric6DofSpringConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+
+btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
+       : btGeneric6DofConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA)
+{
+       init();
+}
+
+btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
+       : btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB)
+{
+       init();
+}
+
+void btGeneric6DofSpringConstraint::init()
+{
+       m_objectType = D6_SPRING_CONSTRAINT_TYPE;
+
+       for (int i = 0; i < 6; i++)
+       {
+               m_springEnabled[i] = false;
+               m_equilibriumPoint[i] = btScalar(0.f);
+               m_springStiffness[i] = btScalar(0.f);
+               m_springDamping[i] = btScalar(1.f);
+       }
+}
+
+void btGeneric6DofSpringConstraint::enableSpring(int index, bool onOff)
+{
+       btAssert((index >= 0) && (index < 6));
+       m_springEnabled[index] = onOff;
+       if (index < 3)
+       {
+               m_linearLimits.m_enableMotor[index] = onOff;
+       }
+       else
+       {
+               m_angularLimits[index - 3].m_enableMotor = onOff;
+       }
+}
+
+void btGeneric6DofSpringConstraint::setStiffness(int index, btScalar stiffness)
+{
+       btAssert((index >= 0) && (index < 6));
+       m_springStiffness[index] = stiffness;
+}
+
+void btGeneric6DofSpringConstraint::setDamping(int index, btScalar damping)
+{
+       btAssert((index >= 0) && (index < 6));
+       m_springDamping[index] = damping;
+}
+
+void btGeneric6DofSpringConstraint::setEquilibriumPoint()
+{
+       calculateTransforms();
+       int i;
+
+       for (i = 0; i < 3; i++)
+       {
+               m_equilibriumPoint[i] = m_calculatedLinearDiff[i];
+       }
+       for (i = 0; i < 3; i++)
+       {
+               m_equilibriumPoint[i + 3] = m_calculatedAxisAngleDiff[i];
+       }
+}
+
+void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index)
+{
+       btAssert((index >= 0) && (index < 6));
+       calculateTransforms();
+       if (index < 3)
+       {
+               m_equilibriumPoint[index] = m_calculatedLinearDiff[index];
+       }
+       else
+       {
+               m_equilibriumPoint[index] = m_calculatedAxisAngleDiff[index - 3];
+       }
+}
+
+void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index, btScalar val)
+{
+       btAssert((index >= 0) && (index < 6));
+       m_equilibriumPoint[index] = val;
+}
+
+void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* info)
+{
+       // it is assumed that calculateTransforms() have been called before this call
+       int i;
+       //btVector3 relVel = m_rbB.getLinearVelocity() - m_rbA.getLinearVelocity();
+       for (i = 0; i < 3; i++)
+       {
+               if (m_springEnabled[i])
+               {
+                       // get current position of constraint
+                       btScalar currPos = m_calculatedLinearDiff[i];
+                       // calculate difference
+                       btScalar delta = currPos - m_equilibriumPoint[i];
+                       // spring force is (delta * m_stiffness) according to Hooke's Law
+                       btScalar force = delta * m_springStiffness[i];
+                       btScalar velFactor = info->fps * m_springDamping[i] / btScalar(info->m_numIterations);
+                       m_linearLimits.m_targetVelocity[i] = velFactor * force;
+                       m_linearLimits.m_maxMotorForce[i] = btFabs(force);
+               }
+       }
+       for (i = 0; i < 3; i++)
+       {
+               if (m_springEnabled[i + 3])
+               {
+                       // get current position of constraint
+                       btScalar currPos = m_calculatedAxisAngleDiff[i];
+                       // calculate difference
+                       btScalar delta = currPos - m_equilibriumPoint[i + 3];
+                       // spring force is (-delta * m_stiffness) according to Hooke's Law
+                       btScalar force = -delta * m_springStiffness[i + 3];
+                       btScalar velFactor = info->fps * m_springDamping[i + 3] / btScalar(info->m_numIterations);
+                       m_angularLimits[i].m_targetVelocity = velFactor * force;
+                       m_angularLimits[i].m_maxMotorForce = btFabs(force);
+               }
+       }
+}
+
+void btGeneric6DofSpringConstraint::getInfo2(btConstraintInfo2* info)
+{
+       // this will be called by constraint solver at the constraint setup stage
+       // set current motor parameters
+       internalUpdateSprings(info);
+       // do the rest of job for constraint setup
+       btGeneric6DofConstraint::getInfo2(info);
+}
+
+void btGeneric6DofSpringConstraint::setAxis(const btVector3& axis1, const btVector3& axis2)
+{
+       btVector3 zAxis = axis1.normalized();
+       btVector3 yAxis = axis2.normalized();
+       btVector3 xAxis = yAxis.cross(zAxis);  // we want right coordinate system
+
+       btTransform frameInW;
+       frameInW.setIdentity();
+       frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+                                                                xAxis[1], yAxis[1], zAxis[1],
+                                                                xAxis[2], yAxis[2], zAxis[2]);
+
+       // now get constraint frame in local coordinate systems
+       m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+       m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+
+       calculateTransforms();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
new file mode 100644 (file)
index 0000000..02b9d4d
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_GENERIC_6DOF_SPRING_CONSTRAINT_H
+#define BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btTypedConstraint.h"
+#include "btGeneric6DofConstraint.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintDoubleData2
+#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintDoubleData2"
+#else
+#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintData
+#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+/// Generic 6 DOF constraint that allows to set spring motors to any translational and rotational DOF
+
+/// DOF index used in enableSpring() and setStiffness() means:
+/// 0 : translation X
+/// 1 : translation Y
+/// 2 : translation Z
+/// 3 : rotation X (3rd Euler rotational around new position of X axis, range [-PI+epsilon, PI-epsilon] )
+/// 4 : rotation Y (2nd Euler rotational around new position of Y axis, range [-PI/2+epsilon, PI/2-epsilon] )
+/// 5 : rotation Z (1st Euler rotational around Z axis, range [-PI+epsilon, PI-epsilon] )
+
+ATTRIBUTE_ALIGNED16(class)
+btGeneric6DofSpringConstraint : public btGeneric6DofConstraint
+{
+protected:
+       bool m_springEnabled[6];
+       btScalar m_equilibriumPoint[6];
+       btScalar m_springStiffness[6];
+       btScalar m_springDamping[6];  // between 0 and 1 (1 == no damping)
+       void init();
+       void internalUpdateSprings(btConstraintInfo2 * info);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btGeneric6DofSpringConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA);
+       btGeneric6DofSpringConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
+       void enableSpring(int index, bool onOff);
+       void setStiffness(int index, btScalar stiffness);
+       void setDamping(int index, btScalar damping);
+       void setEquilibriumPoint();           // set the current constraint position/orientation as an equilibrium point for all DOF
+       void setEquilibriumPoint(int index);  // set the current constraint position/orientation as an equilibrium point for given DOF
+       void setEquilibriumPoint(int index, btScalar val);
+
+       bool isSpringEnabled(int index) const
+       {
+               return m_springEnabled[index];
+       }
+
+       btScalar getStiffness(int index) const
+       {
+               return m_springStiffness[index];
+       }
+
+       btScalar getDamping(int index) const
+       {
+               return m_springDamping[index];
+       }
+
+       btScalar getEquilibriumPoint(int index) const
+       {
+               return m_equilibriumPoint[index];
+       }
+
+       virtual void setAxis(const btVector3& axis1, const btVector3& axis2);
+
+       virtual void getInfo2(btConstraintInfo2 * info);
+
+       virtual int calculateSerializeBufferSize() const;
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+struct btGeneric6DofSpringConstraintData
+{
+       btGeneric6DofConstraintData m_6dofData;
+
+       int m_springEnabled[6];
+       float m_equilibriumPoint[6];
+       float m_springStiffness[6];
+       float m_springDamping[6];
+};
+
+struct btGeneric6DofSpringConstraintDoubleData2
+{
+       btGeneric6DofConstraintDoubleData2 m_6dofData;
+
+       int m_springEnabled[6];
+       double m_equilibriumPoint[6];
+       double m_springStiffness[6];
+       double m_springDamping[6];
+};
+
+SIMD_FORCE_INLINE int btGeneric6DofSpringConstraint::calculateSerializeBufferSize() const
+{
+       return sizeof(btGeneric6DofSpringConstraintData2);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btGeneric6DofSpringConstraintData2* dof = (btGeneric6DofSpringConstraintData2*)dataBuffer;
+       btGeneric6DofConstraint::serialize(&dof->m_6dofData, serializer);
+
+       int i;
+       for (i = 0; i < 6; i++)
+       {
+               dof->m_equilibriumPoint[i] = m_equilibriumPoint[i];
+               dof->m_springDamping[i] = m_springDamping[i];
+               dof->m_springEnabled[i] = m_springEnabled[i] ? 1 : 0;
+               dof->m_springStiffness[i] = m_springStiffness[i];
+       }
+       return btGeneric6DofSpringConstraintDataName;
+}
+
+#endif  // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp
new file mode 100644 (file)
index 0000000..6507e1a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btHinge2Constraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+
+// constructor
+// anchor, axis1 and axis2 are in world coordinate system
+// axis1 must be orthogonal to axis2
+btHinge2Constraint::btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2)
+       : btGeneric6DofSpring2Constraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), RO_XYZ),
+         m_anchor(anchor),
+         m_axis1(axis1),
+         m_axis2(axis2)
+{
+       // build frame basis
+       // 6DOF constraint uses Euler angles and to define limits
+       // it is assumed that rotational order is :
+       // Z - first, allowed limits are (-PI,PI);
+       // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number
+       // used to prevent constraint from instability on poles;
+       // new position of X, allowed limits are (-PI,PI);
+       // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs
+       // Build the frame in world coordinate system first
+       btVector3 zAxis = axis1.normalize();
+       btVector3 xAxis = axis2.normalize();
+       btVector3 yAxis = zAxis.cross(xAxis);  // we want right coordinate system
+       btTransform frameInW;
+       frameInW.setIdentity();
+       frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+                                                                xAxis[1], yAxis[1], zAxis[1],
+                                                                xAxis[2], yAxis[2], zAxis[2]);
+       frameInW.setOrigin(anchor);
+       // now get constraint frame in local coordinate systems
+       m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW;
+       m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW;
+       // sei limits
+       setLinearLowerLimit(btVector3(0.f, 0.f, -1.f));
+       setLinearUpperLimit(btVector3(0.f, 0.f, 1.f));
+       // like front wheels of a car
+       setAngularLowerLimit(btVector3(1.f, 0.f, -SIMD_HALF_PI * 0.5f));
+       setAngularUpperLimit(btVector3(-1.f, 0.f, SIMD_HALF_PI * 0.5f));
+       // enable suspension
+       enableSpring(2, true);
+       setStiffness(2, SIMD_PI * SIMD_PI * 4.f);
+       setDamping(2, 0.01f);
+       setEquilibriumPoint();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
new file mode 100644 (file)
index 0000000..95f604a
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_HINGE2_CONSTRAINT_H
+#define BT_HINGE2_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btTypedConstraint.h"
+#include "btGeneric6DofSpring2Constraint.h"
+
+// Constraint similar to ODE Hinge2 Joint
+// has 3 degrees of frredom:
+// 2 rotational degrees of freedom, similar to Euler rotations around Z (axis 1) and X (axis 2)
+// 1 translational (along axis Z) with suspension spring
+
+ATTRIBUTE_ALIGNED16(class)
+btHinge2Constraint : public btGeneric6DofSpring2Constraint
+{
+protected:
+       btVector3 m_anchor;
+       btVector3 m_axis1;
+       btVector3 m_axis2;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       // constructor
+       // anchor, axis1 and axis2 are in world coordinate system
+       // axis1 must be orthogonal to axis2
+       btHinge2Constraint(btRigidBody & rbA, btRigidBody & rbB, btVector3 & anchor, btVector3 & axis1, btVector3 & axis2);
+       // access
+       const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); }
+       const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); }
+       const btVector3& getAxis1() { return m_axis1; }
+       const btVector3& getAxis2() { return m_axis2; }
+       btScalar getAngle1() { return getAngle(2); }
+       btScalar getAngle2() { return getAngle(0); }
+       // limits
+       void setUpperLimit(btScalar ang1max) { setAngularUpperLimit(btVector3(-1.f, 0.f, ang1max)); }
+       void setLowerLimit(btScalar ang1min) { setAngularLowerLimit(btVector3(1.f, 0.f, ang1min)); }
+};
+
+#endif  // BT_HINGE2_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
new file mode 100644 (file)
index 0000000..cb59e5a
--- /dev/null
@@ -0,0 +1,1083 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btHingeConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMinMax.h"
+#include <new>
+#include "btSolverBody.h"
+
+//#define HINGE_USE_OBSOLETE_SOLVER false
+#define HINGE_USE_OBSOLETE_SOLVER false
+
+#define HINGE_USE_FRAME_OFFSET true
+
+#ifndef __SPU__
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB,
+                                                                        const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA)
+       : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA, rbB),
+#ifdef _BT_USE_CENTER_LIMIT_
+         m_limit(),
+#endif
+         m_angularOnly(false),
+         m_enableAngularMotor(false),
+         m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+         m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+         m_useReferenceFrameA(useReferenceFrameA),
+         m_flags(0),
+         m_normalCFM(0),
+         m_normalERP(0),
+         m_stopCFM(0),
+         m_stopERP(0)
+{
+       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());
+
+#ifndef _BT_USE_CENTER_LIMIT_
+       //start with free
+       m_lowerLimit = btScalar(1.0f);
+       m_upperLimit = btScalar(-1.0f);
+       m_biasFactor = 0.3f;
+       m_relaxationFactor = 1.0f;
+       m_limitSoftness = 0.9f;
+       m_solveLimit = false;
+#endif
+       m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA)
+       : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),
+#ifdef _BT_USE_CENTER_LIMIT_
+         m_limit(),
+#endif
+         m_angularOnly(false),
+         m_enableAngularMotor(false),
+         m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+         m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+         m_useReferenceFrameA(useReferenceFrameA),
+         m_flags(0),
+         m_normalCFM(0),
+         m_normalERP(0),
+         m_stopCFM(0),
+         m_stopERP(0)
+{
+       // since no frame is given, assume this to be zero angle and just pick rb transform axis
+       // fixed axis in worldspace
+       btVector3 rbAxisA1, rbAxisA2;
+       btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
+
+       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());
+
+#ifndef _BT_USE_CENTER_LIMIT_
+       //start with free
+       m_lowerLimit = btScalar(1.0f);
+       m_upperLimit = btScalar(-1.0f);
+       m_biasFactor = 0.3f;
+       m_relaxationFactor = 1.0f;
+       m_limitSoftness = 0.9f;
+       m_solveLimit = false;
+#endif
+       m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB,
+                                                                        const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA)
+       : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA, rbB), m_rbAFrame(rbAFrame), m_rbBFrame(rbBFrame),
+#ifdef _BT_USE_CENTER_LIMIT_
+         m_limit(),
+#endif
+         m_angularOnly(false),
+         m_enableAngularMotor(false),
+         m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+         m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+         m_useReferenceFrameA(useReferenceFrameA),
+         m_flags(0),
+         m_normalCFM(0),
+         m_normalERP(0),
+         m_stopCFM(0),
+         m_stopERP(0)
+{
+#ifndef _BT_USE_CENTER_LIMIT_
+       //start with free
+       m_lowerLimit = btScalar(1.0f);
+       m_upperLimit = btScalar(-1.0f);
+       m_biasFactor = 0.3f;
+       m_relaxationFactor = 1.0f;
+       m_limitSoftness = 0.9f;
+       m_solveLimit = false;
+#endif
+       m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA)
+       : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_rbAFrame(rbAFrame), m_rbBFrame(rbAFrame),
+#ifdef _BT_USE_CENTER_LIMIT_
+         m_limit(),
+#endif
+         m_angularOnly(false),
+         m_enableAngularMotor(false),
+         m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+         m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+         m_useReferenceFrameA(useReferenceFrameA),
+         m_flags(0),
+         m_normalCFM(0),
+         m_normalERP(0),
+         m_stopCFM(0),
+         m_stopERP(0)
+{
+       ///not providing rigidbody B means implicitly using worldspace for body B
+
+       m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin());
+#ifndef _BT_USE_CENTER_LIMIT_
+       //start with free
+       m_lowerLimit = btScalar(1.0f);
+       m_upperLimit = btScalar(-1.0f);
+       m_biasFactor = 0.3f;
+       m_relaxationFactor = 1.0f;
+       m_limitSoftness = 0.9f;
+       m_solveLimit = false;
+#endif
+       m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+void btHingeConstraint::buildJacobian()
+{
+       if (m_useSolveConstraintObsolete)
+       {
+               m_appliedImpulse = btScalar(0.);
+               m_accMotorImpulse = btScalar(0.);
+
+               if (!m_angularOnly)
+               {
+                       btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
+                       btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
+                       btVector3 relPos = pivotBInW - pivotAInW;
+
+                       btVector3 normal[3];
+                       if (relPos.length2() > SIMD_EPSILON)
+                       {
+                               normal[0] = relPos.normalized();
+                       }
+                       else
+                       {
+                               normal[0].setValue(btScalar(1.0), 0, 0);
+                       }
+
+                       btPlaneSpace1(normal[0], normal[1], normal[2]);
+
+                       for (int i = 0; i < 3; i++)
+                       {
+                               new (&m_jac[i]) btJacobianEntry(
+                                       m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+                                       m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+                                       pivotAInW - m_rbA.getCenterOfMassPosition(),
+                                       pivotBInW - m_rbB.getCenterOfMassPosition(),
+                                       normal[i],
+                                       m_rbA.getInvInertiaDiagLocal(),
+                                       m_rbA.getInvMass(),
+                                       m_rbB.getInvInertiaDiagLocal(),
+                                       m_rbB.getInvMass());
+                       }
+               }
+
+               //calculate two perpendicular jointAxis, orthogonal to hingeAxis
+               //these two jointAxis require equal angular velocities for both bodies
+
+               //this is unused for now, it's a todo
+               btVector3 jointAxis0local;
+               btVector3 jointAxis1local;
+
+               btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2), jointAxis0local, jointAxis1local);
+
+               btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local;
+               btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local;
+               btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
+
+               new (&m_jacAng[0]) btJacobianEntry(jointAxis0,
+                                                                                  m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+                                                                                  m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+                                                                                  m_rbA.getInvInertiaDiagLocal(),
+                                                                                  m_rbB.getInvInertiaDiagLocal());
+
+               new (&m_jacAng[1]) btJacobianEntry(jointAxis1,
+                                                                                  m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+                                                                                  m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+                                                                                  m_rbA.getInvInertiaDiagLocal(),
+                                                                                  m_rbB.getInvInertiaDiagLocal());
+
+               new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld,
+                                                                                  m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+                                                                                  m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+                                                                                  m_rbA.getInvInertiaDiagLocal(),
+                                                                                  m_rbB.getInvInertiaDiagLocal());
+
+               // clear accumulator
+               m_accLimitImpulse = btScalar(0.);
+
+               // test angular limit
+               testLimit(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+
+               //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));
+       }
+}
+
+#endif  //__SPU__
+
+static inline btScalar btNormalizeAnglePositive(btScalar angle)
+{
+       return btFmod(btFmod(angle, btScalar(2.0 * SIMD_PI)) + btScalar(2.0 * SIMD_PI), btScalar(2.0 * SIMD_PI));
+}
+
+static btScalar btShortestAngularDistance(btScalar accAngle, btScalar curAngle)
+{
+       btScalar result = btNormalizeAngle(btNormalizeAnglePositive(btNormalizeAnglePositive(curAngle) -
+                                                                                                                               btNormalizeAnglePositive(accAngle)));
+       return result;
+}
+
+static btScalar btShortestAngleUpdate(btScalar accAngle, btScalar curAngle)
+{
+       btScalar tol(0.3);
+       btScalar result = btShortestAngularDistance(accAngle, curAngle);
+
+       if (btFabs(result) > tol)
+               return curAngle;
+       else
+               return accAngle + result;
+
+       return curAngle;
+}
+
+btScalar btHingeAccumulatedAngleConstraint::getAccumulatedHingeAngle()
+{
+       btScalar hingeAngle = getHingeAngle();
+       m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle, hingeAngle);
+       return m_accumulatedAngle;
+}
+void btHingeAccumulatedAngleConstraint::setAccumulatedHingeAngle(btScalar accAngle)
+{
+       m_accumulatedAngle = accAngle;
+}
+
+void btHingeAccumulatedAngleConstraint::getInfo1(btConstraintInfo1* info)
+{
+       //update m_accumulatedAngle
+       btScalar curHingeAngle = getHingeAngle();
+       m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle, curHingeAngle);
+
+       btHingeConstraint::getInfo1(info);
+}
+
+void btHingeConstraint::getInfo1(btConstraintInfo1* info)
+{
+       if (m_useSolveConstraintObsolete)
+       {
+               info->m_numConstraintRows = 0;
+               info->nub = 0;
+       }
+       else
+       {
+               info->m_numConstraintRows = 5;  // Fixed 3 linear + 2 angular
+               info->nub = 1;
+               //always add the row, to avoid computation (data is not available yet)
+               //prepare constraint
+               testLimit(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+               if (getSolveLimit() || getEnableAngularMotor())
+               {
+                       info->m_numConstraintRows++;  // limit 3rd anguar as well
+                       info->nub--;
+               }
+       }
+}
+
+void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
+{
+       if (m_useSolveConstraintObsolete)
+       {
+               info->m_numConstraintRows = 0;
+               info->nub = 0;
+       }
+       else
+       {
+               //always add the 'limit' row, to avoid computation (data is not available yet)
+               info->m_numConstraintRows = 6;  // Fixed 3 linear + 2 angular
+               info->nub = 0;
+       }
+}
+
+void btHingeConstraint::getInfo2(btConstraintInfo2* info)
+{
+       if (m_useOffsetForConstraintFrame)
+       {
+               getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity());
+       }
+       else
+       {
+               getInfo2Internal(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity());
+       }
+}
+
+void btHingeConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
+{
+       ///the regular (virtual) implementation getInfo2 already performs 'testLimit' during getInfo1, so we need to do it now
+       testLimit(transA, transB);
+
+       getInfo2Internal(info, transA, transB, angVelA, angVelB);
+}
+
+void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
+{
+       btAssert(!m_useSolveConstraintObsolete);
+       int i, skip = info->rowskip;
+       // transforms in world space
+       btTransform trA = transA * m_rbAFrame;
+       btTransform trB = transB * m_rbBFrame;
+       // pivot point
+       btVector3 pivotAInW = trA.getOrigin();
+       btVector3 pivotBInW = trB.getOrigin();
+#if 0
+       if (0)
+       {
+               for (i=0;i<6;i++)
+               {
+                       info->m_J1linearAxis[i*skip]=0;
+                       info->m_J1linearAxis[i*skip+1]=0;
+                       info->m_J1linearAxis[i*skip+2]=0;
+
+                       info->m_J1angularAxis[i*skip]=0;
+                       info->m_J1angularAxis[i*skip+1]=0;
+                       info->m_J1angularAxis[i*skip+2]=0;
+
+                       info->m_J2linearAxis[i*skip]=0;
+                       info->m_J2linearAxis[i*skip+1]=0;
+                       info->m_J2linearAxis[i*skip+2]=0;
+
+                       info->m_J2angularAxis[i*skip]=0;
+                       info->m_J2angularAxis[i*skip+1]=0;
+                       info->m_J2angularAxis[i*skip+2]=0;
+
+                       info->m_constraintError[i*skip]=0.f;
+               }
+       }
+#endif  //#if 0
+       // linear (all fixed)
+
+       if (!m_angularOnly)
+       {
+               info->m_J1linearAxis[0] = 1;
+               info->m_J1linearAxis[skip + 1] = 1;
+               info->m_J1linearAxis[2 * skip + 2] = 1;
+
+               info->m_J2linearAxis[0] = -1;
+               info->m_J2linearAxis[skip + 1] = -1;
+               info->m_J2linearAxis[2 * skip + 2] = -1;
+       }
+
+       btVector3 a1 = pivotAInW - transA.getOrigin();
+       {
+               btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
+               btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip);
+               btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip);
+               btVector3 a1neg = -a1;
+               a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+       btVector3 a2 = pivotBInW - transB.getOrigin();
+       {
+               btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
+               btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip);
+               btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip);
+               a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+       // linear RHS
+       btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp;
+
+       btScalar k = info->fps * normalErp;
+       if (!m_angularOnly)
+       {
+               for (i = 0; i < 3; i++)
+               {
+                       info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]);
+               }
+       }
+       // make rotations around X and Y equal
+       // the hinge axis should be the only unconstrained
+       // rotational axis, the angular velocity of the two bodies perpendicular to
+       // the hinge axis should be equal. thus the constraint equations are
+       //    p*w1 - p*w2 = 0
+       //    q*w1 - q*w2 = 0
+       // where p and q are unit vectors normal to the hinge axis, and w1 and w2
+       // are the angular velocity vectors of the two bodies.
+       // get hinge axis (Z)
+       btVector3 ax1 = trA.getBasis().getColumn(2);
+       // get 2 orthos to hinge axis (X, Y)
+       btVector3 p = trA.getBasis().getColumn(0);
+       btVector3 q = trA.getBasis().getColumn(1);
+       // set the two hinge angular rows
+       int s3 = 3 * info->rowskip;
+       int s4 = 4 * info->rowskip;
+
+       info->m_J1angularAxis[s3 + 0] = p[0];
+       info->m_J1angularAxis[s3 + 1] = p[1];
+       info->m_J1angularAxis[s3 + 2] = p[2];
+       info->m_J1angularAxis[s4 + 0] = q[0];
+       info->m_J1angularAxis[s4 + 1] = q[1];
+       info->m_J1angularAxis[s4 + 2] = q[2];
+
+       info->m_J2angularAxis[s3 + 0] = -p[0];
+       info->m_J2angularAxis[s3 + 1] = -p[1];
+       info->m_J2angularAxis[s3 + 2] = -p[2];
+       info->m_J2angularAxis[s4 + 0] = -q[0];
+       info->m_J2angularAxis[s4 + 1] = -q[1];
+       info->m_J2angularAxis[s4 + 2] = -q[2];
+       // compute the right hand side of the constraint equation. set relative
+       // body velocities along p and q to bring the hinge back into alignment.
+       // if ax1,ax2 are the unit length hinge axes as computed from body1 and
+       // body2, we need to rotate both bodies along the axis u = (ax1 x ax2).
+       // if `theta' is the angle between ax1 and ax2, we need an angular velocity
+       // along u to cover angle erp*theta in one step :
+       //   |angular_velocity| = angle/time = erp*theta / stepsize
+       //                      = (erp*fps) * theta
+       //    angular_velocity  = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+       //                      = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+       // ...as ax1 and ax2 are unit length. if theta is smallish,
+       // theta ~= sin(theta), so
+       //    angular_velocity  = (erp*fps) * (ax1 x ax2)
+       // ax1 x ax2 is in the plane space of ax1, so we project the angular
+       // velocity to p and q to find the right hand side.
+       btVector3 ax2 = trB.getBasis().getColumn(2);
+       btVector3 u = ax1.cross(ax2);
+       info->m_constraintError[s3] = k * u.dot(p);
+       info->m_constraintError[s4] = k * u.dot(q);
+       // check angular limits
+       int nrow = 4;  // last filled row
+       int srow;
+       btScalar limit_err = btScalar(0.0);
+       int limit = 0;
+       if (getSolveLimit())
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               limit_err = m_limit.getCorrection() * m_referenceSign;
+#else
+               limit_err = m_correction * m_referenceSign;
+#endif
+               limit = (limit_err > btScalar(0.0)) ? 1 : 2;
+       }
+       // if the hinge has joint limits or motor, add in the extra row
+       bool powered = getEnableAngularMotor();
+       if (limit || powered)
+       {
+               nrow++;
+               srow = nrow * info->rowskip;
+               info->m_J1angularAxis[srow + 0] = ax1[0];
+               info->m_J1angularAxis[srow + 1] = ax1[1];
+               info->m_J1angularAxis[srow + 2] = ax1[2];
+
+               info->m_J2angularAxis[srow + 0] = -ax1[0];
+               info->m_J2angularAxis[srow + 1] = -ax1[1];
+               info->m_J2angularAxis[srow + 2] = -ax1[2];
+
+               btScalar lostop = getLowerLimit();
+               btScalar histop = getUpperLimit();
+               if (limit && (lostop == histop))
+               {  // the joint motor is ineffective
+                       powered = false;
+               }
+               info->m_constraintError[srow] = btScalar(0.0f);
+               btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
+               if (powered)
+               {
+                       if (m_flags & BT_HINGE_FLAGS_CFM_NORM)
+                       {
+                               info->cfm[srow] = m_normalCFM;
+                       }
+                       btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
+                       info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
+                       info->m_lowerLimit[srow] = -m_maxMotorImpulse;
+                       info->m_upperLimit[srow] = m_maxMotorImpulse;
+               }
+               if (limit)
+               {
+                       k = info->fps * currERP;
+                       info->m_constraintError[srow] += k * limit_err;
+                       if (m_flags & BT_HINGE_FLAGS_CFM_STOP)
+                       {
+                               info->cfm[srow] = m_stopCFM;
+                       }
+                       if (lostop == histop)
+                       {
+                               // limited low and high simultaneously
+                               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                               info->m_upperLimit[srow] = SIMD_INFINITY;
+                       }
+                       else if (limit == 1)
+                       {  // low limit
+                               info->m_lowerLimit[srow] = 0;
+                               info->m_upperLimit[srow] = SIMD_INFINITY;
+                       }
+                       else
+                       {  // high limit
+                               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                               info->m_upperLimit[srow] = 0;
+                       }
+                       // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
+#ifdef _BT_USE_CENTER_LIMIT_
+                       btScalar bounce = m_limit.getRelaxationFactor();
+#else
+                       btScalar bounce = m_relaxationFactor;
+#endif
+                       if (bounce > btScalar(0.0))
+                       {
+                               btScalar vel = angVelA.dot(ax1);
+                               vel -= angVelB.dot(ax1);
+                               // only apply bounce if the velocity is incoming, and if the
+                               // resulting c[] exceeds what we already have.
+                               if (limit == 1)
+                               {  // low limit
+                                       if (vel < 0)
+                                       {
+                                               btScalar newc = -bounce * vel;
+                                               if (newc > info->m_constraintError[srow])
+                                               {
+                                                       info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                               }
+                               else
+                               {  // high limit - all those computations are reversed
+                                       if (vel > 0)
+                                       {
+                                               btScalar newc = -bounce * vel;
+                                               if (newc < info->m_constraintError[srow])
+                                               {
+                                                       info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                               }
+                       }
+#ifdef _BT_USE_CENTER_LIMIT_
+                       info->m_constraintError[srow] *= m_limit.getBiasFactor();
+#else
+                       info->m_constraintError[srow] *= m_biasFactor;
+#endif
+               }  // if(limit)
+       }      // if angular limit or powered
+}
+
+void btHingeConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
+{
+       m_rbAFrame = frameA;
+       m_rbBFrame = frameB;
+       buildJacobian();
+}
+
+void btHingeConstraint::updateRHS(btScalar timeStep)
+{
+       (void)timeStep;
+}
+
+btScalar btHingeConstraint::getHingeAngle()
+{
+       return getHingeAngle(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+}
+
+btScalar btHingeConstraint::getHingeAngle(const btTransform& transA, const btTransform& transB)
+{
+       const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
+       const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
+       const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1);
+       //      btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+       btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+       return m_referenceSign * angle;
+}
+
+void btHingeConstraint::testLimit(const btTransform& transA, const btTransform& transB)
+{
+       // Compute limit information
+       m_hingeAngle = getHingeAngle(transA, transB);
+#ifdef _BT_USE_CENTER_LIMIT_
+       m_limit.test(m_hingeAngle);
+#else
+       m_correction = btScalar(0.);
+       m_limitSign = btScalar(0.);
+       m_solveLimit = false;
+       if (m_lowerLimit <= m_upperLimit)
+       {
+               m_hingeAngle = btAdjustAngleToLimits(m_hingeAngle, m_lowerLimit, m_upperLimit);
+               if (m_hingeAngle <= m_lowerLimit)
+               {
+                       m_correction = (m_lowerLimit - m_hingeAngle);
+                       m_limitSign = 1.0f;
+                       m_solveLimit = true;
+               }
+               else if (m_hingeAngle >= m_upperLimit)
+               {
+                       m_correction = m_upperLimit - m_hingeAngle;
+                       m_limitSign = -1.0f;
+                       m_solveLimit = true;
+               }
+       }
+#endif
+       return;
+}
+
+static btVector3 vHinge(0, 0, btScalar(1));
+
+void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt)
+{
+       // convert target from body to constraint space
+       btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * qAinB * m_rbAFrame.getRotation();
+       qConstraint.normalize();
+
+       // extract "pure" hinge component
+       btVector3 vNoHinge = quatRotate(qConstraint, vHinge);
+       vNoHinge.normalize();
+       btQuaternion qNoHinge = shortestArcQuat(vHinge, vNoHinge);
+       btQuaternion qHinge = qNoHinge.inverse() * qConstraint;
+       qHinge.normalize();
+
+       // compute angular target, clamped to limits
+       btScalar targetAngle = qHinge.getAngle();
+       if (targetAngle > SIMD_PI)  // long way around. flip quat and recalculate.
+       {
+               qHinge = -(qHinge);
+               targetAngle = qHinge.getAngle();
+       }
+       if (qHinge.getZ() < 0)
+               targetAngle = -targetAngle;
+
+       setMotorTarget(targetAngle, dt);
+}
+
+void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt)
+{
+#ifdef _BT_USE_CENTER_LIMIT_
+       m_limit.fit(targetAngle);
+#else
+       if (m_lowerLimit < m_upperLimit)
+       {
+               if (targetAngle < m_lowerLimit)
+                       targetAngle = m_lowerLimit;
+               else if (targetAngle > m_upperLimit)
+                       targetAngle = m_upperLimit;
+       }
+#endif
+       // compute angular velocity
+       btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+       btScalar dAngle = targetAngle - curAngle;
+       m_motorTargetVelocity = dAngle / dt;
+}
+
+void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
+{
+       btAssert(!m_useSolveConstraintObsolete);
+       int i, s = info->rowskip;
+       // transforms in world space
+       btTransform trA = transA * m_rbAFrame;
+       btTransform trB = transB * m_rbBFrame;
+       // pivot point
+//     btVector3 pivotAInW = trA.getOrigin();
+//     btVector3 pivotBInW = trB.getOrigin();
+#if 1
+       // difference between frames in WCS
+       btVector3 ofs = trB.getOrigin() - trA.getOrigin();
+       // now get weight factors depending on masses
+       btScalar miA = getRigidBodyA().getInvMass();
+       btScalar miB = getRigidBodyB().getInvMass();
+       bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+       btScalar miS = miA + miB;
+       btScalar factA, factB;
+       if (miS > btScalar(0.f))
+       {
+               factA = miB / miS;
+       }
+       else
+       {
+               factA = btScalar(0.5f);
+       }
+       factB = btScalar(1.0f) - factA;
+       // get the desired direction of hinge axis
+       // as weighted sum of Z-orthos of frameA and frameB in WCS
+       btVector3 ax1A = trA.getBasis().getColumn(2);
+       btVector3 ax1B = trB.getBasis().getColumn(2);
+       btVector3 ax1 = ax1A * factA + ax1B * factB;
+       if (ax1.length2()<SIMD_EPSILON)
+       {
+               factA=0.f;
+               factB=1.f;
+               ax1 = ax1A * factA + ax1B * factB;
+       }
+       ax1.normalize();
+       // fill first 3 rows
+       // we want: velA + wA x relA == velB + wB x relB
+       btTransform bodyA_trans = transA;
+       btTransform bodyB_trans = transB;
+       int s0 = 0;
+       int s1 = s;
+       int s2 = s * 2;
+       int nrow = 2;  // last filled row
+       btVector3 tmpA, tmpB, relA, relB, p, q;
+       // get vector from bodyB to frameB in WCS
+       relB = trB.getOrigin() - bodyB_trans.getOrigin();
+       // get its projection to hinge axis
+       btVector3 projB = ax1 * relB.dot(ax1);
+       // get vector directed from bodyB to hinge axis (and orthogonal to it)
+       btVector3 orthoB = relB - projB;
+       // same for bodyA
+       relA = trA.getOrigin() - bodyA_trans.getOrigin();
+       btVector3 projA = ax1 * relA.dot(ax1);
+       btVector3 orthoA = relA - projA;
+       btVector3 totalDist = projA - projB;
+       // get offset vectors relA and relB
+       relA = orthoA + totalDist * factA;
+       relB = orthoB - totalDist * factB;
+       // now choose average ortho to hinge axis
+       p = orthoB * factA + orthoA * factB;
+       btScalar len2 = p.length2();
+       if (len2 > SIMD_EPSILON)
+       {
+               p /= btSqrt(len2);
+       }
+       else
+       {
+               p = trA.getBasis().getColumn(1);
+       }
+       // make one more ortho
+       q = ax1.cross(p);
+       // fill three rows
+       tmpA = relA.cross(p);
+       tmpB = relB.cross(p);
+       for (i = 0; i < 3; i++) info->m_J1angularAxis[s0 + i] = tmpA[i];
+       for (i = 0; i < 3; i++) info->m_J2angularAxis[s0 + i] = -tmpB[i];
+       tmpA = relA.cross(q);
+       tmpB = relB.cross(q);
+       if (hasStaticBody && getSolveLimit())
+       {  // to make constraint between static and dynamic objects more rigid
+               // remove wA (or wB) from equation if angular limit is hit
+               tmpB *= factB;
+               tmpA *= factA;
+       }
+       for (i = 0; i < 3; i++) info->m_J1angularAxis[s1 + i] = tmpA[i];
+       for (i = 0; i < 3; i++) info->m_J2angularAxis[s1 + i] = -tmpB[i];
+       tmpA = relA.cross(ax1);
+       tmpB = relB.cross(ax1);
+       if (hasStaticBody)
+       {  // to make constraint between static and dynamic objects more rigid
+               // remove wA (or wB) from equation
+               tmpB *= factB;
+               tmpA *= factA;
+       }
+       for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = tmpA[i];
+       for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = -tmpB[i];
+
+       btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp;
+       btScalar k = info->fps * normalErp;
+
+       if (!m_angularOnly)
+       {
+               for (i = 0; i < 3; i++) info->m_J1linearAxis[s0 + i] = p[i];
+               for (i = 0; i < 3; i++) info->m_J1linearAxis[s1 + i] = q[i];
+               for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = ax1[i];
+
+               for (i = 0; i < 3; i++) info->m_J2linearAxis[s0 + i] = -p[i];
+               for (i = 0; i < 3; i++) info->m_J2linearAxis[s1 + i] = -q[i];
+               for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -ax1[i];
+
+               // compute three elements of right hand side
+
+               btScalar rhs = k * p.dot(ofs);
+               info->m_constraintError[s0] = rhs;
+               rhs = k * q.dot(ofs);
+               info->m_constraintError[s1] = rhs;
+               rhs = k * ax1.dot(ofs);
+               info->m_constraintError[s2] = rhs;
+       }
+       // the hinge axis should be the only unconstrained
+       // rotational axis, the angular velocity of the two bodies perpendicular to
+       // the hinge axis should be equal. thus the constraint equations are
+       //    p*w1 - p*w2 = 0
+       //    q*w1 - q*w2 = 0
+       // where p and q are unit vectors normal to the hinge axis, and w1 and w2
+       // are the angular velocity vectors of the two bodies.
+       int s3 = 3 * s;
+       int s4 = 4 * s;
+       info->m_J1angularAxis[s3 + 0] = p[0];
+       info->m_J1angularAxis[s3 + 1] = p[1];
+       info->m_J1angularAxis[s3 + 2] = p[2];
+       info->m_J1angularAxis[s4 + 0] = q[0];
+       info->m_J1angularAxis[s4 + 1] = q[1];
+       info->m_J1angularAxis[s4 + 2] = q[2];
+
+       info->m_J2angularAxis[s3 + 0] = -p[0];
+       info->m_J2angularAxis[s3 + 1] = -p[1];
+       info->m_J2angularAxis[s3 + 2] = -p[2];
+       info->m_J2angularAxis[s4 + 0] = -q[0];
+       info->m_J2angularAxis[s4 + 1] = -q[1];
+       info->m_J2angularAxis[s4 + 2] = -q[2];
+       // compute the right hand side of the constraint equation. set relative
+       // body velocities along p and q to bring the hinge back into alignment.
+       // if ax1A,ax1B are the unit length hinge axes as computed from bodyA and
+       // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
+       // if "theta" is the angle between ax1 and ax2, we need an angular velocity
+       // along u to cover angle erp*theta in one step :
+       //   |angular_velocity| = angle/time = erp*theta / stepsize
+       //                      = (erp*fps) * theta
+       //    angular_velocity  = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+       //                      = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+       // ...as ax1 and ax2 are unit length. if theta is smallish,
+       // theta ~= sin(theta), so
+       //    angular_velocity  = (erp*fps) * (ax1 x ax2)
+       // ax1 x ax2 is in the plane space of ax1, so we project the angular
+       // velocity to p and q to find the right hand side.
+       k = info->fps * normalErp;  //??
+
+       btVector3 u = ax1A.cross(ax1B);
+       info->m_constraintError[s3] = k * u.dot(p);
+       info->m_constraintError[s4] = k * u.dot(q);
+#endif
+       // check angular limits
+       nrow = 4;  // last filled row
+       int srow;
+       btScalar limit_err = btScalar(0.0);
+       int limit = 0;
+       if (getSolveLimit())
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               limit_err = m_limit.getCorrection() * m_referenceSign;
+#else
+               limit_err = m_correction * m_referenceSign;
+#endif
+               limit = (limit_err > btScalar(0.0)) ? 1 : 2;
+       }
+       // if the hinge has joint limits or motor, add in the extra row
+       bool powered = getEnableAngularMotor();
+       if (limit || powered)
+       {
+               nrow++;
+               srow = nrow * info->rowskip;
+               info->m_J1angularAxis[srow + 0] = ax1[0];
+               info->m_J1angularAxis[srow + 1] = ax1[1];
+               info->m_J1angularAxis[srow + 2] = ax1[2];
+
+               info->m_J2angularAxis[srow + 0] = -ax1[0];
+               info->m_J2angularAxis[srow + 1] = -ax1[1];
+               info->m_J2angularAxis[srow + 2] = -ax1[2];
+
+               btScalar lostop = getLowerLimit();
+               btScalar histop = getUpperLimit();
+               if (limit && (lostop == histop))
+               {  // the joint motor is ineffective
+                       powered = false;
+               }
+               info->m_constraintError[srow] = btScalar(0.0f);
+               btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
+               if (powered)
+               {
+                       if (m_flags & BT_HINGE_FLAGS_CFM_NORM)
+                       {
+                               info->cfm[srow] = m_normalCFM;
+                       }
+                       btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
+                       info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
+                       info->m_lowerLimit[srow] = -m_maxMotorImpulse;
+                       info->m_upperLimit[srow] = m_maxMotorImpulse;
+               }
+               if (limit)
+               {
+                       k = info->fps * currERP;
+                       info->m_constraintError[srow] += k * limit_err;
+                       if (m_flags & BT_HINGE_FLAGS_CFM_STOP)
+                       {
+                               info->cfm[srow] = m_stopCFM;
+                       }
+                       if (lostop == histop)
+                       {
+                               // limited low and high simultaneously
+                               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                               info->m_upperLimit[srow] = SIMD_INFINITY;
+                       }
+                       else if (limit == 1)
+                       {  // low limit
+                               info->m_lowerLimit[srow] = 0;
+                               info->m_upperLimit[srow] = SIMD_INFINITY;
+                       }
+                       else
+                       {  // high limit
+                               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                               info->m_upperLimit[srow] = 0;
+                       }
+                       // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
+#ifdef _BT_USE_CENTER_LIMIT_
+                       btScalar bounce = m_limit.getRelaxationFactor();
+#else
+                       btScalar bounce = m_relaxationFactor;
+#endif
+                       if (bounce > btScalar(0.0))
+                       {
+                               btScalar vel = angVelA.dot(ax1);
+                               vel -= angVelB.dot(ax1);
+                               // only apply bounce if the velocity is incoming, and if the
+                               // resulting c[] exceeds what we already have.
+                               if (limit == 1)
+                               {  // low limit
+                                       if (vel < 0)
+                                       {
+                                               btScalar newc = -bounce * vel;
+                                               if (newc > info->m_constraintError[srow])
+                                               {
+                                                       info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                               }
+                               else
+                               {  // high limit - all those computations are reversed
+                                       if (vel > 0)
+                                       {
+                                               btScalar newc = -bounce * vel;
+                                               if (newc < info->m_constraintError[srow])
+                                               {
+                                                       info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                               }
+                       }
+#ifdef _BT_USE_CENTER_LIMIT_
+                       info->m_constraintError[srow] *= m_limit.getBiasFactor();
+#else
+                       info->m_constraintError[srow] *= m_biasFactor;
+#endif
+               }  // if(limit)
+       }      // if angular limit or powered
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void btHingeConstraint::setParam(int num, btScalar value, int axis)
+{
+       if ((axis == -1) || (axis == 5))
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_STOP_ERP:
+                               m_stopERP = value;
+                               m_flags |= BT_HINGE_FLAGS_ERP_STOP;
+                               break;
+                       case BT_CONSTRAINT_STOP_CFM:
+                               m_stopCFM = value;
+                               m_flags |= BT_HINGE_FLAGS_CFM_STOP;
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                               m_normalCFM = value;
+                               m_flags |= BT_HINGE_FLAGS_CFM_NORM;
+                               break;
+                       case BT_CONSTRAINT_ERP:
+                               m_normalERP = value;
+                               m_flags |= BT_HINGE_FLAGS_ERP_NORM;
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       else
+       {
+               btAssertConstrParams(0);
+       }
+}
+
+///return the local value of parameter
+btScalar btHingeConstraint::getParam(int num, int axis) const
+{
+       btScalar retVal = 0;
+       if ((axis == -1) || (axis == 5))
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_STOP_ERP:
+                               btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_STOP);
+                               retVal = m_stopERP;
+                               break;
+                       case BT_CONSTRAINT_STOP_CFM:
+                               btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_STOP);
+                               retVal = m_stopCFM;
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                               btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_NORM);
+                               retVal = m_normalCFM;
+                               break;
+                       case BT_CONSTRAINT_ERP:
+                               btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_NORM);
+                               retVal = m_normalERP;
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       else
+       {
+               btAssertConstrParams(0);
+       }
+       return retVal;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h
new file mode 100644 (file)
index 0000000..8b1f1af
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */
+
+#ifndef BT_HINGECONSTRAINT_H
+#define BT_HINGECONSTRAINT_H
+
+#define _BT_USE_CENTER_LIMIT_ 1
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btHingeConstraintData btHingeConstraintDoubleData2  //rename to 2 for backwards compatibility, so we can still load the 'btHingeConstraintDoubleData' version
+#define btHingeConstraintDataName "btHingeConstraintDoubleData2"
+#else
+#define btHingeConstraintData btHingeConstraintFloatData
+#define btHingeConstraintDataName "btHingeConstraintFloatData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+enum btHingeFlags
+{
+       BT_HINGE_FLAGS_CFM_STOP = 1,
+       BT_HINGE_FLAGS_ERP_STOP = 2,
+       BT_HINGE_FLAGS_CFM_NORM = 4,
+       BT_HINGE_FLAGS_ERP_NORM = 8
+};
+
+/// 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
+ATTRIBUTE_ALIGNED16(class)
+btHingeConstraint : public btTypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+       btJacobianEntry m_jac[3];     //3 orthogonal linear constraints
+       btJacobianEntry m_jacAng[3];  //2 orthogonal angular constraints+ 1 for limit/motor
+
+       btTransform m_rbAFrame;  // constraint axii. Assumes z is hinge axis.
+       btTransform m_rbBFrame;
+
+       btScalar m_motorTargetVelocity;
+       btScalar m_maxMotorImpulse;
+
+#ifdef _BT_USE_CENTER_LIMIT_
+       btAngularLimit m_limit;
+#else
+       btScalar m_lowerLimit;
+       btScalar m_upperLimit;
+       btScalar m_limitSign;
+       btScalar m_correction;
+
+       btScalar m_limitSoftness;
+       btScalar m_biasFactor;
+       btScalar m_relaxationFactor;
+
+       bool m_solveLimit;
+#endif
+
+       btScalar m_kHinge;
+
+       btScalar m_accLimitImpulse;
+       btScalar m_hingeAngle;
+       btScalar m_referenceSign;
+
+       bool m_angularOnly;
+       bool m_enableAngularMotor;
+       bool m_useSolveConstraintObsolete;
+       bool m_useOffsetForConstraintFrame;
+       bool m_useReferenceFrameA;
+
+       btScalar m_accMotorImpulse;
+
+       int m_flags;
+       btScalar m_normalCFM;
+       btScalar m_normalERP;
+       btScalar m_stopCFM;
+       btScalar m_stopERP;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btHingeConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB, const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA = false);
+
+       btHingeConstraint(btRigidBody & rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA = false);
+
+       btHingeConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false);
+
+       btHingeConstraint(btRigidBody & rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false);
+
+       virtual void buildJacobian();
+
+       virtual void getInfo1(btConstraintInfo1 * info);
+
+       void getInfo1NonVirtual(btConstraintInfo1 * info);
+
+       virtual void getInfo2(btConstraintInfo2 * info);
+
+       void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
+
+       void getInfo2Internal(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
+       void getInfo2InternalUsingFrameOffset(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
+
+       void updateRHS(btScalar timeStep);
+
+       const btRigidBody& getRigidBodyA() const
+       {
+               return m_rbA;
+       }
+       const btRigidBody& getRigidBodyB() const
+       {
+               return m_rbB;
+       }
+
+       btRigidBody& getRigidBodyA()
+       {
+               return m_rbA;
+       }
+
+       btRigidBody& getRigidBodyB()
+       {
+               return m_rbB;
+       }
+
+       btTransform& getFrameOffsetA()
+       {
+               return m_rbAFrame;
+       }
+
+       btTransform& getFrameOffsetB()
+       {
+               return m_rbBFrame;
+       }
+
+       void setFrames(const btTransform& frameA, const btTransform& frameB);
+
+       void setAngularOnly(bool angularOnly)
+       {
+               m_angularOnly = angularOnly;
+       }
+
+       void enableAngularMotor(bool enableMotor, btScalar targetVelocity, btScalar maxMotorImpulse)
+       {
+               m_enableAngularMotor = enableMotor;
+               m_motorTargetVelocity = targetVelocity;
+               m_maxMotorImpulse = maxMotorImpulse;
+       }
+
+       // extra motor API, including ability to set a target rotation (as opposed to angular velocity)
+       // note: setMotorTarget sets angular velocity under the hood, so you must call it every tick to
+       //       maintain a given angular target.
+       void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; }
+       void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; }
+       void setMotorTargetVelocity(btScalar motorTargetVelocity) { m_motorTargetVelocity = motorTargetVelocity; }
+       void setMotorTarget(const btQuaternion& qAinB, btScalar dt);  // qAinB is rotation of body A wrt body B.
+       void setMotorTarget(btScalar targetAngle, btScalar dt);
+
+       void setLimit(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               m_limit.set(low, high, _softness, _biasFactor, _relaxationFactor);
+#else
+               m_lowerLimit = btNormalizeAngle(low);
+               m_upperLimit = btNormalizeAngle(high);
+               m_limitSoftness = _softness;
+               m_biasFactor = _biasFactor;
+               m_relaxationFactor = _relaxationFactor;
+#endif
+       }
+
+       btScalar getLimitSoftness() const
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               return m_limit.getSoftness();
+#else
+               return m_limitSoftness;
+#endif
+       }
+
+       btScalar getLimitBiasFactor() const
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               return m_limit.getBiasFactor();
+#else
+               return m_biasFactor;
+#endif
+       }
+
+       btScalar getLimitRelaxationFactor() const
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               return m_limit.getRelaxationFactor();
+#else
+               return m_relaxationFactor;
+#endif
+       }
+
+       void setAxis(btVector3 & axisInA)
+       {
+               btVector3 rbAxisA1, rbAxisA2;
+               btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
+               btVector3 pivotInA = m_rbAFrame.getOrigin();
+               //              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 = m_rbA.getCenterOfMassTransform().getBasis() * axisInA;
+
+               btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB);
+               btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1);
+               btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
+
+               m_rbBFrame.getOrigin() = m_rbB.getCenterOfMassTransform().inverse()(m_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());
+               m_rbBFrame.getBasis() = m_rbB.getCenterOfMassTransform().getBasis().inverse() * m_rbBFrame.getBasis();
+       }
+
+       bool hasLimit() const
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               return m_limit.getHalfRange() > 0;
+#else
+               return m_lowerLimit <= m_upperLimit;
+#endif
+       }
+
+       btScalar getLowerLimit() const
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               return m_limit.getLow();
+#else
+               return m_lowerLimit;
+#endif
+       }
+
+       btScalar getUpperLimit() const
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               return m_limit.getHigh();
+#else
+               return m_upperLimit;
+#endif
+       }
+
+       ///The getHingeAngle gives the hinge angle in range [-PI,PI]
+       btScalar getHingeAngle();
+
+       btScalar getHingeAngle(const btTransform& transA, const btTransform& transB);
+
+       void testLimit(const btTransform& transA, const btTransform& transB);
+
+       const btTransform& getAFrame() const { return m_rbAFrame; };
+       const btTransform& getBFrame() const { return m_rbBFrame; };
+
+       btTransform& getAFrame() { return m_rbAFrame; };
+       btTransform& getBFrame() { return m_rbBFrame; };
+
+       inline int getSolveLimit()
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               return m_limit.isLimit();
+#else
+               return m_solveLimit;
+#endif
+       }
+
+       inline btScalar getLimitSign()
+       {
+#ifdef _BT_USE_CENTER_LIMIT_
+               return m_limit.getSign();
+#else
+               return m_limitSign;
+#endif
+       }
+
+       inline bool getAngularOnly()
+       {
+               return m_angularOnly;
+       }
+       inline bool getEnableAngularMotor()
+       {
+               return m_enableAngularMotor;
+       }
+       inline btScalar getMotorTargetVelocity()
+       {
+               return m_motorTargetVelocity;
+       }
+       inline btScalar getMaxMotorImpulse()
+       {
+               return m_maxMotorImpulse;
+       }
+       // access for UseFrameOffset
+       bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
+       void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+       // access for UseReferenceFrameA
+       bool getUseReferenceFrameA() const { return m_useReferenceFrameA; }
+       void setUseReferenceFrameA(bool useReferenceFrameA) { m_useReferenceFrameA = useReferenceFrameA; }
+
+       ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+       ///If no axis is provided, it uses the default axis for this constraint.
+       virtual void setParam(int num, btScalar value, int axis = -1);
+       ///return the local value of parameter
+       virtual btScalar getParam(int num, int axis = -1) const;
+
+       virtual int getFlags() const
+       {
+               return m_flags;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+//only for backward compatibility
+#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+///this structure is not used, except for loading pre-2.82 .bullet files
+struct btHingeConstraintDoubleData
+{
+       btTypedConstraintData m_typeConstraintData;
+       btTransformDoubleData m_rbAFrame;  // constraint axii. Assumes z is hinge axis.
+       btTransformDoubleData m_rbBFrame;
+       int m_useReferenceFrameA;
+       int m_angularOnly;
+       int m_enableAngularMotor;
+       float m_motorTargetVelocity;
+       float m_maxMotorImpulse;
+
+       float m_lowerLimit;
+       float m_upperLimit;
+       float m_limitSoftness;
+       float m_biasFactor;
+       float m_relaxationFactor;
+};
+#endif  //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+
+///The getAccumulatedHingeAngle returns the accumulated hinge angle, taking rotation across the -PI/PI boundary into account
+ATTRIBUTE_ALIGNED16(class)
+btHingeAccumulatedAngleConstraint : public btHingeConstraint
+{
+protected:
+       btScalar m_accumulatedAngle;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btHingeAccumulatedAngleConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB, const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA = false)
+               : btHingeConstraint(rbA, rbB, pivotInA, pivotInB, axisInA, axisInB, useReferenceFrameA)
+       {
+               m_accumulatedAngle = getHingeAngle();
+       }
+
+       btHingeAccumulatedAngleConstraint(btRigidBody & rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA = false)
+               : btHingeConstraint(rbA, pivotInA, axisInA, useReferenceFrameA)
+       {
+               m_accumulatedAngle = getHingeAngle();
+       }
+
+       btHingeAccumulatedAngleConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false)
+               : btHingeConstraint(rbA, rbB, rbAFrame, rbBFrame, useReferenceFrameA)
+       {
+               m_accumulatedAngle = getHingeAngle();
+       }
+
+       btHingeAccumulatedAngleConstraint(btRigidBody & rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false)
+               : btHingeConstraint(rbA, rbAFrame, useReferenceFrameA)
+       {
+               m_accumulatedAngle = getHingeAngle();
+       }
+       btScalar getAccumulatedHingeAngle();
+       void setAccumulatedHingeAngle(btScalar accAngle);
+       virtual void getInfo1(btConstraintInfo1 * info);
+};
+
+struct btHingeConstraintFloatData
+{
+       btTypedConstraintData m_typeConstraintData;
+       btTransformFloatData m_rbAFrame;  // constraint axii. Assumes z is hinge axis.
+       btTransformFloatData m_rbBFrame;
+       int m_useReferenceFrameA;
+       int m_angularOnly;
+
+       int m_enableAngularMotor;
+       float m_motorTargetVelocity;
+       float m_maxMotorImpulse;
+
+       float m_lowerLimit;
+       float m_upperLimit;
+       float m_limitSoftness;
+       float m_biasFactor;
+       float m_relaxationFactor;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btHingeConstraintDoubleData2
+{
+       btTypedConstraintDoubleData m_typeConstraintData;
+       btTransformDoubleData m_rbAFrame;  // constraint axii. Assumes z is hinge axis.
+       btTransformDoubleData m_rbBFrame;
+       int m_useReferenceFrameA;
+       int m_angularOnly;
+       int m_enableAngularMotor;
+       double m_motorTargetVelocity;
+       double m_maxMotorImpulse;
+
+       double m_lowerLimit;
+       double m_upperLimit;
+       double m_limitSoftness;
+       double m_biasFactor;
+       double m_relaxationFactor;
+       char m_padding1[4];
+};
+
+SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const
+{
+       return sizeof(btHingeConstraintData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btHingeConstraintData* hingeData = (btHingeConstraintData*)dataBuffer;
+       btTypedConstraint::serialize(&hingeData->m_typeConstraintData, serializer);
+
+       m_rbAFrame.serialize(hingeData->m_rbAFrame);
+       m_rbBFrame.serialize(hingeData->m_rbBFrame);
+
+       hingeData->m_angularOnly = m_angularOnly;
+       hingeData->m_enableAngularMotor = m_enableAngularMotor;
+       hingeData->m_maxMotorImpulse = float(m_maxMotorImpulse);
+       hingeData->m_motorTargetVelocity = float(m_motorTargetVelocity);
+       hingeData->m_useReferenceFrameA = m_useReferenceFrameA;
+#ifdef _BT_USE_CENTER_LIMIT_
+       hingeData->m_lowerLimit = float(m_limit.getLow());
+       hingeData->m_upperLimit = float(m_limit.getHigh());
+       hingeData->m_limitSoftness = float(m_limit.getSoftness());
+       hingeData->m_biasFactor = float(m_limit.getBiasFactor());
+       hingeData->m_relaxationFactor = float(m_limit.getRelaxationFactor());
+#else
+       hingeData->m_lowerLimit = float(m_lowerLimit);
+       hingeData->m_upperLimit = float(m_upperLimit);
+       hingeData->m_limitSoftness = float(m_limitSoftness);
+       hingeData->m_biasFactor = float(m_biasFactor);
+       hingeData->m_relaxationFactor = float(m_relaxationFactor);
+#endif
+
+       // Fill padding with zeros to appease msan.
+#ifdef BT_USE_DOUBLE_PRECISION
+       hingeData->m_padding1[0] = 0;
+       hingeData->m_padding1[1] = 0;
+       hingeData->m_padding1[2] = 0;
+       hingeData->m_padding1[3] = 0;
+#endif
+
+       return btHingeConstraintDataName;
+}
+
+#endif  //BT_HINGECONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h
new file mode 100644 (file)
index 0000000..a251073
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_JACOBIAN_ENTRY_H
+#define BT_JACOBIAN_ENTRY_H
+
+#include "LinearMath/btMatrix3x3.h"
+
+//notes:
+// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components
+// which makes the btJacobianEntry memory layout 16 bytes
+// if you only are interested in angular part, just feed massInvA and massInvB zero
+
+/// Jacobian entry is an abstraction that allows to describe constraints
+/// it can be used in combination with a constraint solver
+/// Can be used to relate the effect of an impulse to the constraint error
+ATTRIBUTE_ALIGNED16(class)
+btJacobianEntry
+{
+public:
+       btJacobianEntry(){};
+       //constraint between two different rigidbodies
+       btJacobianEntry(
+               const btMatrix3x3& world2A,
+               const btMatrix3x3& world2B,
+               const btVector3& rel_pos1, const btVector3& rel_pos2,
+               const btVector3& jointAxis,
+               const btVector3& inertiaInvA,
+               const btScalar massInvA,
+               const btVector3& inertiaInvB,
+               const btScalar massInvB)
+               : m_linearJointAxis(jointAxis)
+       {
+               m_aJ = world2A * (rel_pos1.cross(m_linearJointAxis));
+               m_bJ = world2B * (rel_pos2.cross(-m_linearJointAxis));
+               m_0MinvJt = inertiaInvA * m_aJ;
+               m_1MinvJt = inertiaInvB * m_bJ;
+               m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
+
+               btAssert(m_Adiag > btScalar(0.0));
+       }
+
+       //angular constraint between two different rigidbodies
+       btJacobianEntry(const btVector3& jointAxis,
+                                       const btMatrix3x3& world2A,
+                                       const btMatrix3x3& world2B,
+                                       const btVector3& inertiaInvA,
+                                       const btVector3& inertiaInvB)
+               : m_linearJointAxis(btVector3(btScalar(0.), btScalar(0.), btScalar(0.)))
+       {
+               m_aJ = world2A * jointAxis;
+               m_bJ = world2B * -jointAxis;
+               m_0MinvJt = inertiaInvA * m_aJ;
+               m_1MinvJt = inertiaInvB * m_bJ;
+               m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+
+               btAssert(m_Adiag > btScalar(0.0));
+       }
+
+       //angular constraint between two different rigidbodies
+       btJacobianEntry(const btVector3& axisInA,
+                                       const btVector3& axisInB,
+                                       const btVector3& inertiaInvA,
+                                       const btVector3& inertiaInvB)
+               : m_linearJointAxis(btVector3(btScalar(0.), btScalar(0.), btScalar(0.))), m_aJ(axisInA), m_bJ(-axisInB)
+       {
+               m_0MinvJt = inertiaInvA * m_aJ;
+               m_1MinvJt = inertiaInvB * m_bJ;
+               m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+
+               btAssert(m_Adiag > btScalar(0.0));
+       }
+
+       //constraint on one rigidbody
+       btJacobianEntry(
+               const btMatrix3x3& world2A,
+               const btVector3& rel_pos1, const btVector3& rel_pos2,
+               const btVector3& jointAxis,
+               const btVector3& inertiaInvA,
+               const btScalar massInvA)
+               : m_linearJointAxis(jointAxis)
+       {
+               m_aJ = world2A * (rel_pos1.cross(jointAxis));
+               m_bJ = world2A * (rel_pos2.cross(-jointAxis));
+               m_0MinvJt = inertiaInvA * m_aJ;
+               m_1MinvJt = btVector3(btScalar(0.), btScalar(0.), btScalar(0.));
+               m_Adiag = massInvA + m_0MinvJt.dot(m_aJ);
+
+               btAssert(m_Adiag > btScalar(0.0));
+       }
+
+       btScalar getDiagonal() const { return m_Adiag; }
+
+       // for two constraints on the same rigidbody (for example vehicle friction)
+       btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const
+       {
+               const btJacobianEntry& jacA = *this;
+               btScalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis);
+               btScalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ);
+               return lin + ang;
+       }
+
+       // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
+       btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA, const btScalar massInvB) const
+       {
+               const btJacobianEntry& jacA = *this;
+               btVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
+               btVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
+               btVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
+               btVector3 lin0 = massInvA * lin;
+               btVector3 lin1 = massInvB * lin;
+               btVector3 sum = ang0 + ang1 + lin0 + lin1;
+               return sum[0] + sum[1] + sum[2];
+       }
+
+       btScalar getRelativeVelocity(const btVector3& linvelA, const btVector3& angvelA, const btVector3& linvelB, const btVector3& angvelB)
+       {
+               btVector3 linrel = linvelA - linvelB;
+               btVector3 angvela = angvelA * m_aJ;
+               btVector3 angvelb = angvelB * m_bJ;
+               linrel *= m_linearJointAxis;
+               angvela += angvelb;
+               angvela += linrel;
+               btScalar rel_vel2 = angvela[0] + angvela[1] + angvela[2];
+               return rel_vel2 + SIMD_EPSILON;
+       }
+       //private:
+
+       btVector3 m_linearJointAxis;
+       btVector3 m_aJ;
+       btVector3 m_bJ;
+       btVector3 m_0MinvJt;
+       btVector3 m_1MinvJt;
+       //Optimization: can be stored in the w/last component of one of the vectors
+       btScalar m_Adiag;
+};
+
+#endif  //BT_JACOBIAN_ENTRY_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp
new file mode 100644 (file)
index 0000000..454adc8
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btNNCGConstraintSolver.h"
+
+btScalar btNNCGConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+       m_pNC.resizeNoInitialize(m_tmpSolverNonContactConstraintPool.size());
+       m_pC.resizeNoInitialize(m_tmpSolverContactConstraintPool.size());
+       m_pCF.resizeNoInitialize(m_tmpSolverContactFrictionConstraintPool.size());
+       m_pCRF.resizeNoInitialize(m_tmpSolverContactRollingFrictionConstraintPool.size());
+
+       m_deltafNC.resizeNoInitialize(m_tmpSolverNonContactConstraintPool.size());
+       m_deltafC.resizeNoInitialize(m_tmpSolverContactConstraintPool.size());
+       m_deltafCF.resizeNoInitialize(m_tmpSolverContactFrictionConstraintPool.size());
+       m_deltafCRF.resizeNoInitialize(m_tmpSolverContactRollingFrictionConstraintPool.size());
+
+       return val;
+}
+
+btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
+{
+       int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+       int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+       int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+       if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
+       {
+               if (1)  // uncomment this for a bit less random ((iteration & 7) == 0)
+               {
+                       for (int j = 0; j < numNonContactPool; ++j)
+                       {
+                               int tmp = m_orderNonContactConstraintPool[j];
+                               int swapi = btRandInt2(j + 1);
+                               m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
+                               m_orderNonContactConstraintPool[swapi] = tmp;
+                       }
+
+                       //contact/friction constraints are not solved more than
+                       if (iteration < infoGlobal.m_numIterations)
+                       {
+                               for (int j = 0; j < numConstraintPool; ++j)
+                               {
+                                       int tmp = m_orderTmpConstraintPool[j];
+                                       int swapi = btRandInt2(j + 1);
+                                       m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
+                                       m_orderTmpConstraintPool[swapi] = tmp;
+                               }
+
+                               for (int j = 0; j < numFrictionPool; ++j)
+                               {
+                                       int tmp = m_orderFrictionConstraintPool[j];
+                                       int swapi = btRandInt2(j + 1);
+                                       m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
+                                       m_orderFrictionConstraintPool[swapi] = tmp;
+                               }
+                       }
+               }
+       }
+
+       btScalar deltaflengthsqr = 0;
+       {
+               for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
+               {
+                       btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+                       if (iteration < constraint.m_overrideNumSolverIterations)
+                       {
+                               btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
+                               m_deltafNC[j] = deltaf;
+                               deltaflengthsqr += deltaf * deltaf;
+                       }
+               }
+       }
+
+       if (m_onlyForNoneContact)
+       {
+               if (iteration == 0)
+               {
+                       for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = m_deltafNC[j];
+               }
+               else
+               {
+                       // deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
+                       btScalar beta = m_deltafLengthSqrPrev > 0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
+                       if (beta > 1)
+                       {
+                               for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = 0;
+                       }
+                       else
+                       {
+                               for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
+                               {
+                                       btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+                                       if (iteration < constraint.m_overrideNumSolverIterations)
+                                       {
+                                               btScalar additionaldeltaimpulse = beta * m_pNC[j];
+                                               constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
+                                               m_pNC[j] = beta * m_pNC[j] + m_deltafNC[j];
+                                               btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+                                               btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+                                               const btSolverConstraint& c = constraint;
+                                               body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
+                                               body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
+                                       }
+                               }
+                       }
+               }
+               m_deltafLengthSqrPrev = deltaflengthsqr;
+       }
+
+       {
+               if (iteration < infoGlobal.m_numIterations)
+               {
+                       for (int j = 0; j < numConstraints; j++)
+                       {
+                               if (constraints[j]->isEnabled())
+                               {
+                                       int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
+                                       int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
+                                       btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
+                                       btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
+                                       constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
+                               }
+                       }
+
+                       ///solve all contact constraints
+                       if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+                       {
+                               int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                               int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
+
+                               for (int c = 0; c < numPoolConstraints; c++)
+                               {
+                                       btScalar totalImpulse = 0;
+
+                                       {
+                                               const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
+                                               btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                               m_deltafC[c] = deltaf;
+                                               deltaflengthsqr += deltaf * deltaf;
+                                               totalImpulse = solveManifold.m_appliedImpulse;
+                                       }
+                                       bool applyFriction = true;
+                                       if (applyFriction)
+                                       {
+                                               {
+                                                       btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
+
+                                                       if (totalImpulse > btScalar(0))
+                                                       {
+                                                               solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                                                               solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+                                                               btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                                               m_deltafCF[c * multiplier] = deltaf;
+                                                               deltaflengthsqr += deltaf * deltaf;
+                                                       }
+                                                       else
+                                                       {
+                                                               m_deltafCF[c * multiplier] = 0;
+                                                       }
+                                               }
+
+                                               if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
+                                               {
+                                                       btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
+
+                                                       if (totalImpulse > btScalar(0))
+                                                       {
+                                                               solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                                                               solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+                                                               btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                                               m_deltafCF[c * multiplier + 1] = deltaf;
+                                                               deltaflengthsqr += deltaf * deltaf;
+                                                       }
+                                                       else
+                                                       {
+                                                               m_deltafCF[c * multiplier + 1] = 0;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       else  //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+                       {
+                               //solve the friction constraints after all contact constraints, don't interleave them
+                               int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                               int j;
+
+                               for (j = 0; j < numPoolConstraints; j++)
+                               {
+                                       const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+                                       btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                       m_deltafC[j] = deltaf;
+                                       deltaflengthsqr += deltaf * deltaf;
+                               }
+
+                               ///solve all friction constraints
+
+                               int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+                               for (j = 0; j < numFrictionPoolConstraints; j++)
+                               {
+                                       btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+                                       btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+
+                                       if (totalImpulse > btScalar(0))
+                                       {
+                                               solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                                               solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+                                               btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                               m_deltafCF[j] = deltaf;
+                                               deltaflengthsqr += deltaf * deltaf;
+                                       }
+                                       else
+                                       {
+                                               m_deltafCF[j] = 0;
+                                       }
+                               }
+                       }
+
+                       {
+                               int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+                               for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
+                               {
+                                       btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+                                       btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+                                       if (totalImpulse > btScalar(0))
+                                       {
+                                               btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+                                               if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+                                                       rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+                                               rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+                                               rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+                                               btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+                                               m_deltafCRF[j] = deltaf;
+                                               deltaflengthsqr += deltaf * deltaf;
+                                       }
+                                       else
+                                       {
+                                               m_deltafCRF[j] = 0;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (!m_onlyForNoneContact)
+       {
+               if (iteration == 0)
+               {
+                       for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = m_deltafNC[j];
+                       for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) m_pC[j] = m_deltafC[j];
+                       for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) m_pCF[j] = m_deltafCF[j];
+                       for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) m_pCRF[j] = m_deltafCRF[j];
+               }
+               else
+               {
+                       // deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
+                       btScalar beta = m_deltafLengthSqrPrev > 0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
+                       if (beta > 1)
+                       {
+                               for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = 0;
+                               for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) m_pC[j] = 0;
+                               for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) m_pCF[j] = 0;
+                               for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) m_pCRF[j] = 0;
+                       }
+                       else
+                       {
+                               for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
+                               {
+                                       btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+                                       if (iteration < constraint.m_overrideNumSolverIterations)
+                                       {
+                                               btScalar additionaldeltaimpulse = beta * m_pNC[j];
+                                               constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
+                                               m_pNC[j] = beta * m_pNC[j] + m_deltafNC[j];
+                                               btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+                                               btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+                                               const btSolverConstraint& c = constraint;
+                                               body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
+                                               body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
+                                       }
+                               }
+                               for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++)
+                               {
+                                       btSolverConstraint& constraint = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+                                       if (iteration < infoGlobal.m_numIterations)
+                                       {
+                                               btScalar additionaldeltaimpulse = beta * m_pC[j];
+                                               constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
+                                               m_pC[j] = beta * m_pC[j] + m_deltafC[j];
+                                               btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+                                               btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+                                               const btSolverConstraint& c = constraint;
+                                               body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
+                                               body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
+                                       }
+                               }
+                               for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++)
+                               {
+                                       btSolverConstraint& constraint = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+                                       if (iteration < infoGlobal.m_numIterations)
+                                       {
+                                               btScalar additionaldeltaimpulse = beta * m_pCF[j];
+                                               constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
+                                               m_pCF[j] = beta * m_pCF[j] + m_deltafCF[j];
+                                               btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+                                               btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+                                               const btSolverConstraint& c = constraint;
+                                               body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
+                                               body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
+                                       }
+                               }
+                               {
+                                       for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++)
+                                       {
+                                               btSolverConstraint& constraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+                                               if (iteration < infoGlobal.m_numIterations)
+                                               {
+                                                       btScalar additionaldeltaimpulse = beta * m_pCRF[j];
+                                                       constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
+                                                       m_pCRF[j] = beta * m_pCRF[j] + m_deltafCRF[j];
+                                                       btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+                                                       btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+                                                       const btSolverConstraint& c = constraint;
+                                                       body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
+                                                       body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
+                                               }
+                                       }
+                               }
+                       }
+               }
+               m_deltafLengthSqrPrev = deltaflengthsqr;
+       }
+
+       return deltaflengthsqr;
+}
+
+btScalar btNNCGConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+       m_pNC.resizeNoInitialize(0);
+       m_pC.resizeNoInitialize(0);
+       m_pCF.resizeNoInitialize(0);
+       m_pCRF.resizeNoInitialize(0);
+
+       m_deltafNC.resizeNoInitialize(0);
+       m_deltafC.resizeNoInitialize(0);
+       m_deltafCF.resizeNoInitialize(0);
+       m_deltafCRF.resizeNoInitialize(0);
+
+       return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h
new file mode 100644 (file)
index 0000000..a01f34c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_NNCG_CONSTRAINT_SOLVER_H
+#define BT_NNCG_CONSTRAINT_SOLVER_H
+
+#include "btSequentialImpulseConstraintSolver.h"
+
+ATTRIBUTE_ALIGNED16(class)
+btNNCGConstraintSolver : public btSequentialImpulseConstraintSolver
+{
+protected:
+       btScalar m_deltafLengthSqrPrev;
+
+       btAlignedObjectArray<btScalar> m_pNC;   // p for None Contact constraints
+       btAlignedObjectArray<btScalar> m_pC;    // p for Contact constraints
+       btAlignedObjectArray<btScalar> m_pCF;   // p for ContactFriction constraints
+       btAlignedObjectArray<btScalar> m_pCRF;  // p for ContactRollingFriction constraints
+
+       //These are recalculated in every iterations. We just keep these to prevent reallocation in each iteration.
+       btAlignedObjectArray<btScalar> m_deltafNC;   // deltaf for NoneContact constraints
+       btAlignedObjectArray<btScalar> m_deltafC;    // deltaf for Contact constraints
+       btAlignedObjectArray<btScalar> m_deltafCF;   // deltaf for ContactFriction constraints
+       btAlignedObjectArray<btScalar> m_deltafCRF;  // deltaf for ContactRollingFriction constraints
+
+protected:
+       virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+       virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+
+       virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btNNCGConstraintSolver() : btSequentialImpulseConstraintSolver(), m_onlyForNoneContact(false) {}
+
+       virtual btConstraintSolverType getSolverType() const
+       {
+               return BT_NNCG_SOLVER;
+       }
+
+       bool m_onlyForNoneContact;
+};
+
+#endif  //BT_NNCG_CONSTRAINT_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
new file mode 100644 (file)
index 0000000..49a46ed
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btPoint2PointConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include <new>
+
+btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB)
+       : btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE, rbA, rbB), m_pivotInA(pivotInA), m_pivotInB(pivotInB), m_flags(0), m_useSolveConstraintObsolete(false)
+{
+}
+
+btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA, const btVector3& pivotInA)
+       : btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE, rbA), m_pivotInA(pivotInA), m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), m_flags(0), m_useSolveConstraintObsolete(false)
+{
+}
+
+void btPoint2PointConstraint::buildJacobian()
+{
+       ///we need it for both methods
+       {
+               m_appliedImpulse = btScalar(0.);
+
+               btVector3 normal(0, 0, 0);
+
+               for (int i = 0; i < 3; i++)
+               {
+                       normal[i] = 1;
+                       new (&m_jac[i]) btJacobianEntry(
+                               m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+                               m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+                               m_rbA.getCenterOfMassTransform() * m_pivotInA - m_rbA.getCenterOfMassPosition(),
+                               m_rbB.getCenterOfMassTransform() * m_pivotInB - m_rbB.getCenterOfMassPosition(),
+                               normal,
+                               m_rbA.getInvInertiaDiagLocal(),
+                               m_rbA.getInvMass(),
+                               m_rbB.getInvInertiaDiagLocal(),
+                               m_rbB.getInvMass());
+                       normal[i] = 0;
+               }
+       }
+}
+
+void btPoint2PointConstraint::getInfo1(btConstraintInfo1* info)
+{
+       getInfo1NonVirtual(info);
+}
+
+void btPoint2PointConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
+{
+       if (m_useSolveConstraintObsolete)
+       {
+               info->m_numConstraintRows = 0;
+               info->nub = 0;
+       }
+       else
+       {
+               info->m_numConstraintRows = 3;
+               info->nub = 3;
+       }
+}
+
+void btPoint2PointConstraint::getInfo2(btConstraintInfo2* info)
+{
+       getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+}
+
+void btPoint2PointConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans)
+{
+       btAssert(!m_useSolveConstraintObsolete);
+
+       //retrieve matrices
+
+       // anchor points in global coordinates with respect to body PORs.
+
+       // set jacobian
+       info->m_J1linearAxis[0] = 1;
+       info->m_J1linearAxis[info->rowskip + 1] = 1;
+       info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
+
+       btVector3 a1 = body0_trans.getBasis() * getPivotInA();
+       {
+               btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
+               btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + info->rowskip);
+               btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * info->rowskip);
+               btVector3 a1neg = -a1;
+               a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+
+       info->m_J2linearAxis[0] = -1;
+       info->m_J2linearAxis[info->rowskip + 1] = -1;
+       info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
+
+       btVector3 a2 = body1_trans.getBasis() * getPivotInB();
+
+       {
+               //      btVector3 a2n = -a2;
+               btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
+               btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + info->rowskip);
+               btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * info->rowskip);
+               a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
+       }
+
+       // set right hand side
+       btScalar currERP = (m_flags & BT_P2P_FLAGS_ERP) ? m_erp : info->erp;
+       btScalar k = info->fps * currERP;
+       int j;
+       for (j = 0; j < 3; j++)
+       {
+               info->m_constraintError[j * info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
+               //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
+       }
+       if (m_flags & BT_P2P_FLAGS_CFM)
+       {
+               for (j = 0; j < 3; j++)
+               {
+                       info->cfm[j * info->rowskip] = m_cfm;
+               }
+       }
+
+       btScalar impulseClamp = m_setting.m_impulseClamp;  //
+       for (j = 0; j < 3; j++)
+       {
+               if (m_setting.m_impulseClamp > 0)
+               {
+                       info->m_lowerLimit[j * info->rowskip] = -impulseClamp;
+                       info->m_upperLimit[j * info->rowskip] = impulseClamp;
+               }
+       }
+       info->m_damping = m_setting.m_damping;
+}
+
+void btPoint2PointConstraint::updateRHS(btScalar timeStep)
+{
+       (void)timeStep;
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void btPoint2PointConstraint::setParam(int num, btScalar value, int axis)
+{
+       if (axis != -1)
+       {
+               btAssertConstrParams(0);
+       }
+       else
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_ERP:
+                       case BT_CONSTRAINT_STOP_ERP:
+                               m_erp = value;
+                               m_flags |= BT_P2P_FLAGS_ERP;
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                       case BT_CONSTRAINT_STOP_CFM:
+                               m_cfm = value;
+                               m_flags |= BT_P2P_FLAGS_CFM;
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+}
+
+///return the local value of parameter
+btScalar btPoint2PointConstraint::getParam(int num, int axis) const
+{
+       btScalar retVal(SIMD_INFINITY);
+       if (axis != -1)
+       {
+               btAssertConstrParams(0);
+       }
+       else
+       {
+               switch (num)
+               {
+                       case BT_CONSTRAINT_ERP:
+                       case BT_CONSTRAINT_STOP_ERP:
+                               btAssertConstrParams(m_flags & BT_P2P_FLAGS_ERP);
+                               retVal = m_erp;
+                               break;
+                       case BT_CONSTRAINT_CFM:
+                       case BT_CONSTRAINT_STOP_CFM:
+                               btAssertConstrParams(m_flags & BT_P2P_FLAGS_CFM);
+                               retVal = m_cfm;
+                               break;
+                       default:
+                               btAssertConstrParams(0);
+               }
+       }
+       return retVal;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
new file mode 100644 (file)
index 0000000..c0b94e9
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_POINT2POINTCONSTRAINT_H
+#define BT_POINT2POINTCONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btPoint2PointConstraintData2 btPoint2PointConstraintDoubleData2
+#define btPoint2PointConstraintDataName "btPoint2PointConstraintDoubleData2"
+#else
+#define btPoint2PointConstraintData2 btPoint2PointConstraintFloatData
+#define btPoint2PointConstraintDataName "btPoint2PointConstraintFloatData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+struct btConstraintSetting
+{
+       btConstraintSetting() : m_tau(btScalar(0.3)),
+                                                       m_damping(btScalar(1.)),
+                                                       m_impulseClamp(btScalar(0.))
+       {
+       }
+       btScalar m_tau;
+       btScalar m_damping;
+       btScalar m_impulseClamp;
+};
+
+enum btPoint2PointFlags
+{
+       BT_P2P_FLAGS_ERP = 1,
+       BT_P2P_FLAGS_CFM = 2
+};
+
+/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
+ATTRIBUTE_ALIGNED16(class)
+btPoint2PointConstraint : public btTypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+       btJacobianEntry m_jac[3];  //3 orthogonal linear constraints
+
+       btVector3 m_pivotInA;
+       btVector3 m_pivotInB;
+
+       int m_flags;
+       btScalar m_erp;
+       btScalar m_cfm;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       ///for backwards compatibility during the transition to 'getInfo/getInfo2'
+       bool m_useSolveConstraintObsolete;
+
+       btConstraintSetting m_setting;
+
+       btPoint2PointConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB);
+
+       btPoint2PointConstraint(btRigidBody & rbA, const btVector3& pivotInA);
+
+       virtual void buildJacobian();
+
+       virtual void getInfo1(btConstraintInfo1 * info);
+
+       void getInfo1NonVirtual(btConstraintInfo1 * info);
+
+       virtual void getInfo2(btConstraintInfo2 * info);
+
+       void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& body0_trans, const btTransform& body1_trans);
+
+       void updateRHS(btScalar timeStep);
+
+       void setPivotA(const btVector3& pivotA)
+       {
+               m_pivotInA = pivotA;
+       }
+
+       void setPivotB(const btVector3& pivotB)
+       {
+               m_pivotInB = pivotB;
+       }
+
+       const btVector3& getPivotInA() const
+       {
+               return m_pivotInA;
+       }
+
+       const btVector3& getPivotInB() const
+       {
+               return m_pivotInB;
+       }
+
+       ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+       ///If no axis is provided, it uses the default axis for this constraint.
+       virtual void setParam(int num, btScalar value, int axis = -1);
+       ///return the local value of parameter
+       virtual btScalar getParam(int num, int axis = -1) const;
+
+       virtual int getFlags() const
+       {
+               return m_flags;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btPoint2PointConstraintFloatData
+{
+       btTypedConstraintData m_typeConstraintData;
+       btVector3FloatData m_pivotInA;
+       btVector3FloatData m_pivotInB;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btPoint2PointConstraintDoubleData2
+{
+       btTypedConstraintDoubleData m_typeConstraintData;
+       btVector3DoubleData m_pivotInA;
+       btVector3DoubleData m_pivotInB;
+};
+
+#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+///this structure is not used, except for loading pre-2.82 .bullet files
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btPoint2PointConstraintDoubleData
+{
+       btTypedConstraintData m_typeConstraintData;
+       btVector3DoubleData m_pivotInA;
+       btVector3DoubleData m_pivotInB;
+};
+#endif  //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+
+SIMD_FORCE_INLINE int btPoint2PointConstraint::calculateSerializeBufferSize() const
+{
+       return sizeof(btPoint2PointConstraintData2);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btPoint2PointConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btPoint2PointConstraintData2* p2pData = (btPoint2PointConstraintData2*)dataBuffer;
+
+       btTypedConstraint::serialize(&p2pData->m_typeConstraintData, serializer);
+       m_pivotInA.serialize(p2pData->m_pivotInA);
+       m_pivotInB.serialize(p2pData->m_pivotInB);
+
+       return btPoint2PointConstraintDataName;
+}
+
+#endif  //BT_POINT2POINTCONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
new file mode 100644 (file)
index 0000000..419e564
--- /dev/null
@@ -0,0 +1,1875 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//#define COMPUTE_IMPULSE_DENOM 1
+#ifdef BT_DEBUG
+#      define BT_ADDITIONAL_DEBUG
+#endif
+
+//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
+
+#include "btSequentialImpulseConstraintSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btCpuFeatureUtility.h"
+
+//#include "btJacobianEntry.h"
+#include "LinearMath/btMinMax.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include <new>
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btQuickprof.h"
+//#include "btSolverBody.h"
+//#include "btSolverConstraint.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include <string.h>  //for memset
+
+int gNumSplitImpulseRecoveries = 0;
+
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+//#define VERBOSE_RESIDUAL_PRINTF 1
+///This is the scalar reference implementation of solving a single constraint row, the innerloop of the Projected Gauss Seidel/Sequential Impulse constraint solver
+///Below are optional SSE2 and SSE4/FMA3 versions. We assume most hardware has SSE2. For SSE4/FMA3 we perform a CPU feature check.
+static btScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+       btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
+       const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetDeltaAngularVelocity());
+       const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetDeltaAngularVelocity());
+
+       //      const btScalar delta_rel_vel    =       deltaVel1Dotn-deltaVel2Dotn;
+       deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+       deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
+
+       const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
+       if (sum < c.m_lowerLimit)
+       {
+               deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
+               c.m_appliedImpulse = c.m_lowerLimit;
+       }
+       else if (sum > c.m_upperLimit)
+       {
+               deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
+               c.m_appliedImpulse = c.m_upperLimit;
+       }
+       else
+       {
+               c.m_appliedImpulse = sum;
+       }
+
+       bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+       bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+
+       return deltaImpulse * (1. / c.m_jacDiagABInv);
+}
+
+static btScalar gResolveSingleConstraintRowLowerLimit_scalar_reference(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+       btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
+       const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetDeltaAngularVelocity());
+       const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetDeltaAngularVelocity());
+
+       deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+       deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
+       const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
+       if (sum < c.m_lowerLimit)
+       {
+               deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
+               c.m_appliedImpulse = c.m_lowerLimit;
+       }
+       else
+       {
+               c.m_appliedImpulse = sum;
+       }
+       bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+       bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+
+       return deltaImpulse * (1. / c.m_jacDiagABInv);
+}
+
+#ifdef USE_SIMD
+#include <emmintrin.h>
+
+#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e, e, e, e))
+static inline __m128 btSimdDot3(__m128 vec0, __m128 vec1)
+{
+       __m128 result = _mm_mul_ps(vec0, vec1);
+       return _mm_add_ps(btVecSplat(result, 0), _mm_add_ps(btVecSplat(result, 1), btVecSplat(result, 2)));
+}
+
+#if defined(BT_ALLOW_SSE4)
+#include <intrin.h>
+
+#define USE_FMA 1
+#define USE_FMA3_INSTEAD_FMA4 1
+#define USE_SSE4_DOT 1
+
+#define SSE4_DP(a, b) _mm_dp_ps(a, b, 0x7f)
+#define SSE4_DP_FP(a, b) _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7f))
+
+#if USE_SSE4_DOT
+#define DOT_PRODUCT(a, b) SSE4_DP(a, b)
+#else
+#define DOT_PRODUCT(a, b) btSimdDot3(a, b)
+#endif
+
+#if USE_FMA
+#if USE_FMA3_INSTEAD_FMA4
+// a*b + c
+#define FMADD(a, b, c) _mm_fmadd_ps(a, b, c)
+// -(a*b) + c
+#define FMNADD(a, b, c) _mm_fnmadd_ps(a, b, c)
+#else  // USE_FMA3
+// a*b + c
+#define FMADD(a, b, c) _mm_macc_ps(a, b, c)
+// -(a*b) + c
+#define FMNADD(a, b, c) _mm_nmacc_ps(a, b, c)
+#endif
+#else  // USE_FMA
+// c + a*b
+#define FMADD(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b))
+// c - a*b
+#define FMNADD(a, b, c) _mm_sub_ps(c, _mm_mul_ps(a, b))
+#endif
+#endif
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+static btScalar gResolveSingleConstraintRowGeneric_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+       __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
+       __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+       __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+       btSimdScalar deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
+       __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
+       __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+       btSimdScalar resultLowerLess, resultUpperLess;
+       resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+       resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+       __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+       deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+       c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+       __m128 upperMinApplied = _mm_sub_ps(upperLimit1, cpAppliedImp);
+       deltaImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied));
+       c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1));
+       __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
+       __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128, bodyB.internalGetInvMass().mVec128);
+       __m128 impulseMagnitude = deltaImpulse;
+       bodyA.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+       bodyA.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+       bodyB.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+       bodyB.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
+       return deltaImpulse.m_floats[0] / c.m_jacDiagABInv;
+}
+
+// Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
+static btScalar gResolveSingleConstraintRowGeneric_sse4_1_fma3(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+#if defined(BT_ALLOW_SSE4)
+       __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
+       __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm);
+       const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
+       const __m128 upperLimit = _mm_set_ps1(c.m_upperLimit);
+       const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
+       const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
+       deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
+       deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
+       tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse);  // sum
+       const __m128 maskLower = _mm_cmpgt_ps(tmp, lowerLimit);
+       const __m128 maskUpper = _mm_cmpgt_ps(upperLimit, tmp);
+       deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), _mm_blendv_ps(_mm_sub_ps(upperLimit, c.m_appliedImpulse), deltaImpulse, maskUpper), maskLower);
+       c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, _mm_blendv_ps(upperLimit, tmp, maskUpper), maskLower);
+       bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128);
+       bodyA.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, bodyA.internalGetDeltaAngularVelocity().mVec128);
+       bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128);
+       bodyB.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, bodyB.internalGetDeltaAngularVelocity().mVec128);
+       btSimdScalar deltaImp = deltaImpulse;
+       return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
+#else
+       return gResolveSingleConstraintRowGeneric_sse2(bodyA, bodyB, c);
+#endif
+}
+
+static btScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+       __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
+       __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+       __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+       btSimdScalar deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
+       __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
+       __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+       btSimdScalar resultLowerLess, resultUpperLess;
+       resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+       resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+       __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+       deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+       c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+       __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
+       __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128);
+       __m128 impulseMagnitude = deltaImpulse;
+       bodyA.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+       bodyA.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+       bodyB.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+       bodyB.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
+       return deltaImpulse.m_floats[0] / c.m_jacDiagABInv;
+}
+
+// Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
+static btScalar gResolveSingleConstraintRowLowerLimit_sse4_1_fma3(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+#ifdef BT_ALLOW_SSE4
+       __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
+       __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm);
+       const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
+       const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
+       const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
+       deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
+       deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
+       tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse);
+       const __m128 mask = _mm_cmpgt_ps(tmp, lowerLimit);
+       deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), deltaImpulse, mask);
+       c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, tmp, mask);
+       bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128);
+       bodyA.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, bodyA.internalGetDeltaAngularVelocity().mVec128);
+       bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128);
+       bodyB.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, bodyB.internalGetDeltaAngularVelocity().mVec128);
+       btSimdScalar deltaImp = deltaImpulse;
+       return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
+#else
+       return gResolveSingleConstraintRowLowerLimit_sse2(bodyA, bodyB, c);
+#endif  //BT_ALLOW_SSE4
+}
+
+#endif  //USE_SIMD
+
+btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+       return m_resolveSingleConstraintRowGeneric(bodyA, bodyB, c);
+}
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+       return m_resolveSingleConstraintRowGeneric(bodyA, bodyB, c);
+}
+
+btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+       return m_resolveSingleConstraintRowLowerLimit(bodyA, bodyB, c);
+}
+
+btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+       return m_resolveSingleConstraintRowLowerLimit(bodyA, bodyB, c);
+}
+
+static btScalar gResolveSplitPenetrationImpulse_scalar_reference(
+       btSolverBody& bodyA,
+       btSolverBody& bodyB,
+       const btSolverConstraint& c)
+{
+       btScalar deltaImpulse = 0.f;
+
+       if (c.m_rhsPenetration)
+       {
+               gNumSplitImpulseRecoveries++;
+               deltaImpulse = c.m_rhsPenetration - btScalar(c.m_appliedPushImpulse) * c.m_cfm;
+               const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetTurnVelocity());
+               const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetTurnVelocity());
+
+               deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
+               deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
+               const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse;
+               if (sum < c.m_lowerLimit)
+               {
+                       deltaImpulse = c.m_lowerLimit - c.m_appliedPushImpulse;
+                       c.m_appliedPushImpulse = c.m_lowerLimit;
+               }
+               else
+               {
+                       c.m_appliedPushImpulse = sum;
+               }
+               bodyA.internalApplyPushImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+               bodyB.internalApplyPushImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+       }
+       return deltaImpulse * (1. / c.m_jacDiagABInv);
+}
+
+static btScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
+{
+#ifdef USE_SIMD
+       if (!c.m_rhsPenetration)
+               return 0.f;
+
+       gNumSplitImpulseRecoveries++;
+
+       __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
+       __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+       __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+       __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse), _mm_set1_ps(c.m_cfm)));
+       __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetTurnVelocity().mVec128));
+       __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetTurnVelocity().mVec128));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
+       btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
+       btSimdScalar resultLowerLess, resultUpperLess;
+       resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
+       resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
+       __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
+       deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
+       c.m_appliedPushImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
+       __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
+       __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128);
+       __m128 impulseMagnitude = deltaImpulse;
+       bodyA.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyA.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
+       bodyA.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyA.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
+       bodyB.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyB.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
+       bodyB.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyB.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
+       btSimdScalar deltaImp = deltaImpulse;
+       return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
+#else
+       return gResolveSplitPenetrationImpulse_scalar_reference(bodyA, bodyB, c);
+#endif
+}
+
+btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
+{
+       m_btSeed2 = 0;
+       m_cachedSolverMode = 0;
+       setupSolverFunctions(false);
+}
+
+void btSequentialImpulseConstraintSolver::setupSolverFunctions(bool useSimd)
+{
+       m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_scalar_reference;
+       m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_scalar_reference;
+       m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_scalar_reference;
+
+       if (useSimd)
+       {
+#ifdef USE_SIMD
+               m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2;
+               m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse2;
+               m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_sse2;
+
+#ifdef BT_ALLOW_SSE4
+               int cpuFeatures = btCpuFeatureUtility::getCpuFeatures();
+               if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1))
+               {
+                       m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3;
+                       m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
+               }
+#endif  //BT_ALLOW_SSE4
+#endif  //USE_SIMD
+       }
+}
+
+btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
+{
+}
+
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverGeneric()
+{
+       return gResolveSingleConstraintRowGeneric_scalar_reference;
+}
+
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverLowerLimit()
+{
+       return gResolveSingleConstraintRowLowerLimit_scalar_reference;
+}
+
+#ifdef USE_SIMD
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
+{
+       return gResolveSingleConstraintRowGeneric_sse2;
+}
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit()
+{
+       return gResolveSingleConstraintRowLowerLimit_sse2;
+}
+#ifdef BT_ALLOW_SSE4
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric()
+{
+       return gResolveSingleConstraintRowGeneric_sse4_1_fma3;
+}
+btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit()
+{
+       return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
+}
+#endif  //BT_ALLOW_SSE4
+#endif  //USE_SIMD
+
+unsigned long btSequentialImpulseConstraintSolver::btRand2()
+{
+       m_btSeed2 = (1664525L * m_btSeed2 + 1013904223L) & 0xffffffff;
+       return m_btSeed2;
+}
+
+//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
+int btSequentialImpulseConstraintSolver::btRandInt2(int n)
+{
+       // seems good; xor-fold and modulus
+       const unsigned long un = static_cast<unsigned long>(n);
+       unsigned long r = btRand2();
+
+       // note: probably more aggressive than it needs to be -- might be
+       //       able to get away without one or two of the innermost branches.
+       if (un <= 0x00010000UL)
+       {
+               r ^= (r >> 16);
+               if (un <= 0x00000100UL)
+               {
+                       r ^= (r >> 8);
+                       if (un <= 0x00000010UL)
+                       {
+                               r ^= (r >> 4);
+                               if (un <= 0x00000004UL)
+                               {
+                                       r ^= (r >> 2);
+                                       if (un <= 0x00000002UL)
+                                       {
+                                               r ^= (r >> 1);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return (int)(r % un);
+}
+
+void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
+{
+       btRigidBody* rb = collisionObject ? btRigidBody::upcast(collisionObject) : 0;
+
+       solverBody->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
+       solverBody->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
+       solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
+       solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
+
+       if (rb)
+       {
+               solverBody->m_worldTransform = rb->getWorldTransform();
+               solverBody->internalSetInvMass(btVector3(rb->getInvMass(), rb->getInvMass(), rb->getInvMass()) * rb->getLinearFactor());
+               solverBody->m_originalBody = rb;
+               solverBody->m_angularFactor = rb->getAngularFactor();
+               solverBody->m_linearFactor = rb->getLinearFactor();
+               solverBody->m_linearVelocity = rb->getLinearVelocity();
+               solverBody->m_angularVelocity = rb->getAngularVelocity();
+               solverBody->m_externalForceImpulse = rb->getTotalForce() * rb->getInvMass() * timeStep;
+               solverBody->m_externalTorqueImpulse = rb->getTotalTorque() * rb->getInvInertiaTensorWorld() * timeStep;
+       }
+       else
+               {
+               solverBody->m_worldTransform.setIdentity();
+               solverBody->internalSetInvMass(btVector3(0, 0, 0));
+               solverBody->m_originalBody = 0;
+               solverBody->m_angularFactor.setValue(1, 1, 1);
+               solverBody->m_linearFactor.setValue(1, 1, 1);
+               solverBody->m_linearVelocity.setValue(0, 0, 0);
+               solverBody->m_angularVelocity.setValue(0, 0, 0);
+               solverBody->m_externalForceImpulse.setValue(0, 0, 0);
+               solverBody->m_externalTorqueImpulse.setValue(0, 0, 0);
+                                       }
+                               }
+
+btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
+{
+       //printf("rel_vel =%f\n", rel_vel);
+       if (btFabs(rel_vel) < velocityThreshold)
+               return 0.;
+
+       btScalar rest = restitution * -rel_vel;
+       return rest;
+}
+
+void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj, btVector3& frictionDirection, int frictionMode)
+{
+       if (colObj && colObj->hasAnisotropicFriction(frictionMode))
+       {
+               // transform to local coordinates
+               btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis();
+               const btVector3& friction_scaling = colObj->getAnisotropicFriction();
+               //apply anisotropic friction
+               loc_lateral *= friction_scaling;
+               // ... and transform it back to global coordinates
+               frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral;
+       }
+}
+
+void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+{
+       btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+       btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+
+       btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+       btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+
+       solverConstraint.m_solverBodyIdA = solverBodyIdA;
+       solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+       solverConstraint.m_friction = cp.m_combinedFriction;
+       solverConstraint.m_originalContactPoint = 0;
+
+       solverConstraint.m_appliedImpulse = 0.f;
+       solverConstraint.m_appliedPushImpulse = 0.f;
+
+       if (body0)
+       {
+               solverConstraint.m_contactNormal1 = normalAxis;
+               btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal1);
+               solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+               solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor();
+       }
+       else
+       {
+               solverConstraint.m_contactNormal1.setZero();
+               solverConstraint.m_relpos1CrossNormal.setZero();
+               solverConstraint.m_angularComponentA.setZero();
+       }
+
+       if (bodyA)
+       {
+               solverConstraint.m_contactNormal2 = -normalAxis;
+               btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal2);
+               solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+               solverConstraint.m_angularComponentB = bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor();
+       }
+       else
+       {
+               solverConstraint.m_contactNormal2.setZero();
+               solverConstraint.m_relpos2CrossNormal.setZero();
+               solverConstraint.m_angularComponentB.setZero();
+       }
+
+       {
+               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 (bodyA)
+               {
+                       vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
+                       denom1 = bodyA->getInvMass() + normalAxis.dot(vec);
+               }
+               btScalar denom = relaxation / (denom0 + denom1);
+               solverConstraint.m_jacDiagABInv = denom;
+       }
+
+       {
+               btScalar rel_vel;
+               btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0 ? solverBodyA.m_linearVelocity + solverBodyA.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : btVector3(0, 0, 0));
+               btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA ? solverBodyB.m_linearVelocity + solverBodyB.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(bodyA ? solverBodyB.m_angularVelocity : btVector3(0, 0, 0));
+
+               rel_vel = vel1Dotn + vel2Dotn;
+
+               //              btScalar positionalError = 0.f;
+
+               btScalar velocityError = desiredVelocity - rel_vel;
+               btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+
+               btScalar penetrationImpulse = btScalar(0);
+
+               if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
+               {
+                       btScalar distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(normalAxis);
+                       btScalar positionalError = -distance * infoGlobal.m_frictionERP / infoGlobal.m_timeStep;
+                       penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+               }
+
+               solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+               solverConstraint.m_rhsPenetration = 0.f;
+               solverConstraint.m_cfm = cfmSlip;
+               solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
+               solverConstraint.m_upperLimit = solverConstraint.m_friction;
+       }
+}
+
+btSolverConstraint& 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, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+{
+       btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
+       solverConstraint.m_frictionIndex = frictionIndex;
+       setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
+               colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
+       return solverConstraint;
+}
+
+void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
+       btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
+       btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
+       btScalar desiredVelocity, btScalar cfmSlip)
+
+{
+       btVector3 normalAxis(0, 0, 0);
+
+       solverConstraint.m_contactNormal1 = normalAxis;
+       solverConstraint.m_contactNormal2 = -normalAxis;
+       btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+       btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+
+       btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+       btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+
+       solverConstraint.m_solverBodyIdA = solverBodyIdA;
+       solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+       solverConstraint.m_friction = combinedTorsionalFriction;
+       solverConstraint.m_originalContactPoint = 0;
+
+       solverConstraint.m_appliedImpulse = 0.f;
+       solverConstraint.m_appliedPushImpulse = 0.f;
+
+       {
+               btVector3 ftorqueAxis1 = -normalAxis1;
+               solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+               solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor() : btVector3(0, 0, 0);
+       }
+       {
+               btVector3 ftorqueAxis1 = normalAxis1;
+               solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+               solverConstraint.m_angularComponentB = bodyA ? bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor() : btVector3(0, 0, 0);
+       }
+
+       {
+               btVector3 iMJaA = body0 ? body0->getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal : btVector3(0, 0, 0);
+               btVector3 iMJaB = bodyA ? bodyA->getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal : btVector3(0, 0, 0);
+               btScalar sum = 0;
+               sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+               sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+               solverConstraint.m_jacDiagABInv = btScalar(1.) / sum;
+       }
+
+       {
+               btScalar rel_vel;
+               btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0 ? solverBodyA.m_linearVelocity + solverBodyA.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : btVector3(0, 0, 0));
+               btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA ? solverBodyB.m_linearVelocity + solverBodyB.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(bodyA ? solverBodyB.m_angularVelocity : btVector3(0, 0, 0));
+
+               rel_vel = vel1Dotn + vel2Dotn;
+
+               //              btScalar positionalError = 0.f;
+
+               btSimdScalar velocityError = desiredVelocity - rel_vel;
+               btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv);
+               solverConstraint.m_rhs = velocityImpulse;
+               solverConstraint.m_cfm = cfmSlip;
+               solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
+               solverConstraint.m_upperLimit = solverConstraint.m_friction;
+       }
+}
+
+btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
+{
+       btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
+       solverConstraint.m_frictionIndex = frictionIndex;
+       setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
+               colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+       return solverConstraint;
+}
+
+int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body, btScalar timeStep)
+{
+#if BT_THREADSAFE
+       int solverBodyId = -1;
+       const bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
+       const bool isStaticOrKinematic = body.isStaticOrKinematicObject();
+       const bool isKinematic = body.isKinematicObject();
+       if (isRigidBodyType && !isStaticOrKinematic)
+       {
+               // dynamic body
+               // Dynamic bodies can only be in one island, so it's safe to write to the companionId
+               solverBodyId = body.getCompanionId();
+               if (solverBodyId < 0)
+               {
+                       solverBodyId = m_tmpSolverBodyPool.size();
+                       btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+                       initSolverBody(&solverBody, &body, timeStep);
+                       body.setCompanionId(solverBodyId);
+               }
+       }
+       else if (isRigidBodyType && isKinematic)
+       {
+               //
+               // NOTE: must test for kinematic before static because some kinematic objects also
+               //   identify as "static"
+               //
+               // Kinematic bodies can be in multiple islands at once, so it is a
+               // race condition to write to them, so we use an alternate method
+               // to record the solverBodyId
+               int uniqueId = body.getWorldArrayIndex();
+               const int INVALID_SOLVER_BODY_ID = -1;
+               if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
+               {
+                       m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
+               }
+               solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
+               // if no table entry yet,
+               if (solverBodyId == INVALID_SOLVER_BODY_ID)
+               {
+                       // create a table entry for this body
+                       solverBodyId = m_tmpSolverBodyPool.size();
+                       btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+                       initSolverBody(&solverBody, &body, timeStep);
+                       m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
+               }
+       }
+       else
+       {
+               bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK);
+               // Incorrectly set collision object flags can degrade performance in various ways.
+               if (!isMultiBodyType)
+               {
+                       btAssert(body.isStaticOrKinematicObject());
+               }
+               //it could be a multibody link collider
+               // all fixed bodies (inf mass) get mapped to a single solver id
+               if (m_fixedBodyId < 0)
+               {
+                       m_fixedBodyId = m_tmpSolverBodyPool.size();
+                       btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+                       initSolverBody(&fixedBody, 0, timeStep);
+               }
+               solverBodyId = m_fixedBodyId;
+       }
+       btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
+       return solverBodyId;
+#else   // BT_THREADSAFE
+
+       int solverBodyIdA = -1;
+
+       if (body.getCompanionId() >= 0)
+       {
+               //body has already been converted
+               solverBodyIdA = body.getCompanionId();
+               btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
+       }
+       else
+       {
+               btRigidBody* rb = btRigidBody::upcast(&body);
+               //convert both active and kinematic objects (for their velocity)
+               if (rb && (rb->getInvMass() || rb->isKinematicObject()))
+               {
+                       solverBodyIdA = m_tmpSolverBodyPool.size();
+                       btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+                       initSolverBody(&solverBody, &body, timeStep);
+                       body.setCompanionId(solverBodyIdA);
+               }
+               else
+               {
+                       if (m_fixedBodyId < 0)
+                       {
+                               m_fixedBodyId = m_tmpSolverBodyPool.size();
+                               btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+                               initSolverBody(&fixedBody, 0, timeStep);
+                       }
+                       return m_fixedBodyId;
+                       //                      return 0;//assume first one is a fixed solver body
+               }
+       }
+
+       return solverBodyIdA;
+#endif  // BT_THREADSAFE
+}
+#include <stdio.h>
+
+void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
+       int solverBodyIdA, int solverBodyIdB,
+       btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
+       btScalar& relaxation,
+       const btVector3& rel_pos1, const btVector3& rel_pos2)
+{
+       //      const btVector3& pos1 = cp.getPositionWorldOnA();
+       //      const btVector3& pos2 = cp.getPositionWorldOnB();
+
+       btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+       btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+       btRigidBody* rb0 = bodyA->m_originalBody;
+       btRigidBody* rb1 = bodyB->m_originalBody;
+
+       //                      btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
+       //                      btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+       //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+       //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+
+       relaxation = infoGlobal.m_sor;
+       btScalar invTimeStep = btScalar(1) / infoGlobal.m_timeStep;
+
+       //cfm = 1 /       ( dt * kp + kd )
+       //erp = dt * kp / ( dt * kp + kd )
+
+       btScalar cfm = infoGlobal.m_globalCfm;
+       btScalar erp = infoGlobal.m_erp2;
+
+       if ((cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP))
+       {
+               if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM)
+                       cfm = cp.m_contactCFM;
+               if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP)
+                       erp = cp.m_contactERP;
+       }
+       else
+       {
+               if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
+               {
+                       btScalar denom = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1);
+                       if (denom < SIMD_EPSILON)
+                       {
+                               denom = SIMD_EPSILON;
+                       }
+                       cfm = btScalar(1) / denom;
+                       erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
+               }
+       }
+
+       cfm *= invTimeStep;
+
+       btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
+       solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
+       btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
+       solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
+
+       {
+#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 + cfm);
+               solverConstraint.m_jacDiagABInv = denom;
+       }
+
+       if (rb0)
+       {
+               solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB;
+               solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+       }
+       else
+       {
+               solverConstraint.m_contactNormal1.setZero();
+               solverConstraint.m_relpos1CrossNormal.setZero();
+       }
+       if (rb1)
+       {
+               solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB;
+               solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+       }
+       else
+       {
+               solverConstraint.m_contactNormal2.setZero();
+               solverConstraint.m_relpos2CrossNormal.setZero();
+       }
+
+       btScalar restitution = 0.f;
+       btScalar penetration = cp.getDistance() + infoGlobal.m_linearSlop;
+
+       {
+               btVector3 vel1, vel2;
+
+               vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0, 0, 0);
+               vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0, 0, 0);
+
+               //                      btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
+               btVector3 vel = vel1 - vel2;
+               btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
+
+               solverConstraint.m_friction = cp.m_combinedFriction;
+
+               restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+               if (restitution <= btScalar(0.))
+               {
+                       restitution = 0.f;
+               };
+       }
+
+       ///warm starting (or zero if disabled)
+       if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+       {
+               solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
+               if (rb0)
+                       bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
+               if (rb1)
+                       bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
+       }
+       else
+       {
+               solverConstraint.m_appliedImpulse = 0.f;
+       }
+
+       solverConstraint.m_appliedPushImpulse = 0.f;
+
+       {
+               btVector3 externalForceImpulseA = bodyA->m_originalBody ? bodyA->m_externalForceImpulse : btVector3(0, 0, 0);
+               btVector3 externalTorqueImpulseA = bodyA->m_originalBody ? bodyA->m_externalTorqueImpulse : btVector3(0, 0, 0);
+               btVector3 externalForceImpulseB = bodyB->m_originalBody ? bodyB->m_externalForceImpulse : btVector3(0, 0, 0);
+               btVector3 externalTorqueImpulseB = bodyB->m_originalBody ? bodyB->m_externalTorqueImpulse : btVector3(0, 0, 0);
+
+               btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(bodyA->m_linearVelocity + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(bodyA->m_angularVelocity + externalTorqueImpulseA);
+               btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyB->m_linearVelocity + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(bodyB->m_angularVelocity + externalTorqueImpulseB);
+               btScalar rel_vel = vel1Dotn + vel2Dotn;
+
+               btScalar positionalError = 0.f;
+               btScalar velocityError = restitution - rel_vel;  // * damping;
+
+               if (penetration > 0)
+               {
+                       positionalError = 0;
+
+                       velocityError -= penetration * invTimeStep;
+               }
+               else
+               {
+                       positionalError = -penetration * erp * invTimeStep;
+               }
+
+               btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+               btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+
+               if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+               {
+                       //combine position and velocity into rhs
+                       solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;  //-solverConstraint.m_contactNormal1.dot(bodyA->m_externalForce*bodyA->m_invMass-bodyB->m_externalForce/bodyB->m_invMass)*solverConstraint.m_jacDiagABInv;
+                       solverConstraint.m_rhsPenetration = 0.f;
+               }
+               else
+               {
+                       //split position and velocity into rhs and m_rhsPenetration
+                       solverConstraint.m_rhs = velocityImpulse;
+                       solverConstraint.m_rhsPenetration = penetrationImpulse;
+               }
+               solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
+               solverConstraint.m_lowerLimit = 0;
+               solverConstraint.m_upperLimit = 1e10f;
+       }
+}
+
+void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint,
+       int solverBodyIdA, int solverBodyIdB,
+       btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
+{
+       {
+               btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
+               
+               frictionConstraint1.m_appliedImpulse = 0.f;
+       }
+
+       if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+       {
+               btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
+               
+               frictionConstraint2.m_appliedImpulse = 0.f;
+       }
+}
+
+void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
+{
+       btCollisionObject *colObj0 = 0, *colObj1 = 0;
+
+       colObj0 = (btCollisionObject*)manifold->getBody0();
+       colObj1 = (btCollisionObject*)manifold->getBody1();
+
+       int solverBodyIdA = getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+       int solverBodyIdB = getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
+
+       //      btRigidBody* bodyA = btRigidBody::upcast(colObj0);
+       //      btRigidBody* bodyB = btRigidBody::upcast(colObj1);
+
+       btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+       btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+       ///avoid collision response between two static objects
+       if (!solverBodyA || (solverBodyA->m_invMass.fuzzyZero() && (!solverBodyB || solverBodyB->m_invMass.fuzzyZero())))
+               return;
+
+       int rollingFriction = 1;
+       for (int j = 0; j < manifold->getNumContacts(); j++)
+       {
+               btManifoldPoint& cp = manifold->getContactPoint(j);
+
+               if (cp.getDistance() <= manifold->getContactProcessingThreshold())
+               {
+                       btVector3 rel_pos1;
+                       btVector3 rel_pos2;
+                       btScalar relaxation;
+
+                       int frictionIndex = m_tmpSolverContactConstraintPool.size();
+                       btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
+                       solverConstraint.m_solverBodyIdA = solverBodyIdA;
+                       solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+                       solverConstraint.m_originalContactPoint = &cp;
+
+                       const btVector3& pos1 = cp.getPositionWorldOnA();
+                       const btVector3& pos2 = cp.getPositionWorldOnB();
+
+                       rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
+                       rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+
+                       btVector3 vel1;
+                       btVector3 vel2;
+
+                       solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1);
+                       solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2);
+
+                       btVector3 vel = vel1 - vel2;
+                       btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
+
+                       setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
+
+                       /////setup the friction constraints
+
+                       solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
+
+                       if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0))
+                       {
+                               {
+                                       addTorsionalFrictionConstraint(cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, cp.m_combinedSpinningFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+                                       btVector3 axis0, axis1;
+                                       btPlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
+                                       axis0.normalize();
+                                       axis1.normalize();
+
+                                       applyAnisotropicFriction(colObj0, axis0, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+                                       applyAnisotropicFriction(colObj1, axis0, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+                                       applyAnisotropicFriction(colObj0, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+                                       applyAnisotropicFriction(colObj1, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+                                       if (axis0.length() > 0.001)
+                                               addTorsionalFrictionConstraint(axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
+                                                       cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+                                       if (axis1.length() > 0.001)
+                                               addTorsionalFrictionConstraint(axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
+                                                       cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
+                                       }
+                               }
+
+                       ///Bullet has several options to set the friction directions
+                       ///By default, each contact has only a single friction direction that is recomputed automatically very frame
+                       ///based on the relative linear velocity.
+                       ///If the relative velocity it zero, it will automatically compute a friction direction.
+
+                       ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
+                       ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
+                       ///
+                       ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
+                       ///
+                       ///The user can manually override the friction directions for certain contacts using a contact callback,
+                       ///and use contactPoint.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED
+                       ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
+                       ///this will give a conveyor belt effect
+                       ///
+
+                       if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
+                       {
+                               cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
+                               btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
+                               if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
+                               {
+                                       cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
+                                       applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+
+                                       if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+                                       {
+                                               cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
+                                               cp.m_lateralFrictionDir2.normalize();  //??
+                                               applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                               applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                               addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+                                       }
+                               }
+                               else
+                               {
+                                       btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
+
+                                       applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+
+                                       if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+                                       {
+                                               applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                               applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                               addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+                                       }
+
+                                       if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+                                       {
+                                               cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
+
+                               if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+                                       addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
+                               }
+                       setFrictionConstraintImpulse(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
+                       }
+               }
+       }
+
+void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
+{
+       int i;
+       btPersistentManifold* manifold = 0;
+       //                      btCollisionObject* colObj0=0,*colObj1=0;
+
+       for (i = 0; i < numManifolds; i++)
+       {
+               manifold = manifoldPtr[i];
+               convertContact(manifold, infoGlobal);
+       }
+}
+
+void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow,
+       btTypedConstraint* constraint,
+       const btTypedConstraint::btConstraintInfo1& info1,
+       int solverBodyIdA,
+       int solverBodyIdB,
+       const btContactSolverInfo& infoGlobal)
+{
+       const btRigidBody& rbA = constraint->getRigidBodyA();
+       const btRigidBody& rbB = constraint->getRigidBodyB();
+
+       const btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+       const btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
+
+       int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
+       if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
+               m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
+
+       for (int j = 0; j < info1.m_numConstraintRows; j++)
+       {
+               memset(&currentConstraintRow[j], 0, sizeof(btSolverConstraint));
+               currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY;
+               currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
+               currentConstraintRow[j].m_appliedImpulse = 0.f;
+               currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+               currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
+               currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
+               currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
+       }
+
+       // these vectors are already cleared in initSolverBody, no need to redundantly clear again
+       btAssert(bodyAPtr->getDeltaLinearVelocity().isZero());
+       btAssert(bodyAPtr->getDeltaAngularVelocity().isZero());
+       btAssert(bodyAPtr->getPushVelocity().isZero());
+       btAssert(bodyAPtr->getTurnVelocity().isZero());
+       btAssert(bodyBPtr->getDeltaLinearVelocity().isZero());
+       btAssert(bodyBPtr->getDeltaAngularVelocity().isZero());
+       btAssert(bodyBPtr->getPushVelocity().isZero());
+       btAssert(bodyBPtr->getTurnVelocity().isZero());
+       //bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+       //bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+       //bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+       //bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+       //bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+       //bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+       //bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+       //bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+
+       btTypedConstraint::btConstraintInfo2 info2;
+       info2.fps = 1.f / infoGlobal.m_timeStep;
+       info2.erp = infoGlobal.m_erp;
+       info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1;
+       info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
+       info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2;
+       info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
+       info2.rowskip = sizeof(btSolverConstraint) / sizeof(btScalar);  //check this
+                                                                                                                                       ///the size of btSolverConstraint needs be a multiple of btScalar
+       btAssert(info2.rowskip * sizeof(btScalar) == sizeof(btSolverConstraint));
+       info2.m_constraintError = &currentConstraintRow->m_rhs;
+       currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
+       info2.m_damping = infoGlobal.m_damping;
+       info2.cfm = &currentConstraintRow->m_cfm;
+       info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
+       info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
+       info2.m_numIterations = infoGlobal.m_numIterations;
+       constraint->getInfo2(&info2);
+
+       ///finalize the constraint setup
+       for (int j = 0; j < info1.m_numConstraintRows; j++)
+       {
+               btSolverConstraint& solverConstraint = currentConstraintRow[j];
+
+               if (solverConstraint.m_upperLimit >= constraint->getBreakingImpulseThreshold())
+               {
+                       solverConstraint.m_upperLimit = constraint->getBreakingImpulseThreshold();
+               }
+
+               if (solverConstraint.m_lowerLimit <= -constraint->getBreakingImpulseThreshold())
+               {
+                       solverConstraint.m_lowerLimit = -constraint->getBreakingImpulseThreshold();
+               }
+
+               solverConstraint.m_originalContactPoint = constraint;
+
+               {
+                       const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
+                       solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld() * ftorqueAxis1 * constraint->getRigidBodyA().getAngularFactor();
+               }
+               {
+                       const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
+                       solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld() * ftorqueAxis2 * constraint->getRigidBodyB().getAngularFactor();
+               }
+
+               {
+                       btVector3 iMJlA = solverConstraint.m_contactNormal1 * rbA.getInvMass();
+                       btVector3 iMJaA = rbA.getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal;
+                       btVector3 iMJlB = solverConstraint.m_contactNormal2 * rbB.getInvMass();  //sign of normal?
+                       btVector3 iMJaB = rbB.getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal;
+
+                       btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1);
+                       sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+                       sum += iMJlB.dot(solverConstraint.m_contactNormal2);
+                       sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+                       btScalar fsum = btFabs(sum);
+                       btAssert(fsum > SIMD_EPSILON);
+                       btScalar sorRelaxation = 1.f;  //todo: get from globalInfo?
+                       solverConstraint.m_jacDiagABInv = fsum > SIMD_EPSILON ? sorRelaxation / sum : 0.f;
+               }
+
+               {
+                       btScalar rel_vel;
+                       btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0, 0, 0);
+                       btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0, 0, 0);
+
+                       btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0, 0, 0);
+                       btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalTorqueImpulse : btVector3(0, 0, 0);
+
+                       btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity() + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity() + externalTorqueImpulseA);
+
+                       btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity() + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity() + externalTorqueImpulseB);
+
+                       rel_vel = vel1Dotn + vel2Dotn;
+                       btScalar restitution = 0.f;
+                       btScalar positionalError = solverConstraint.m_rhs;  //already filled in by getConstraintInfo2
+                       btScalar velocityError = restitution - rel_vel * info2.m_damping;
+                       btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+                       btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+                       solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+                       solverConstraint.m_appliedImpulse = 0.f;
+               }
+       }
+}
+
+void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("convertJoints");
+       for (int j = 0; j < numConstraints; j++)
+       {
+               btTypedConstraint* constraint = constraints[j];
+               constraint->buildJacobian();
+               constraint->internalSetAppliedImpulse(0.0f);
+       }
+
+       int totalNumRows = 0;
+
+       m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
+       //calculate the total number of contraint rows
+       for (int i = 0; i < numConstraints; i++)
+       {
+               btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+               btJointFeedback* fb = constraints[i]->getJointFeedback();
+               if (fb)
+               {
+                       fb->m_appliedForceBodyA.setZero();
+                       fb->m_appliedTorqueBodyA.setZero();
+                       fb->m_appliedForceBodyB.setZero();
+                       fb->m_appliedTorqueBodyB.setZero();
+               }
+
+               if (constraints[i]->isEnabled())
+               {
+                       constraints[i]->getInfo1(&info1);
+               }
+               else
+               {
+                       info1.m_numConstraintRows = 0;
+                       info1.nub = 0;
+               }
+               totalNumRows += info1.m_numConstraintRows;
+       }
+       m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
+
+       ///setup the btSolverConstraints
+       int currentRow = 0;
+
+       for (int i = 0; i < numConstraints; i++)
+       {
+               const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+
+               if (info1.m_numConstraintRows)
+               {
+                       btAssert(currentRow < totalNumRows);
+
+                       btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
+                       btTypedConstraint* constraint = constraints[i];
+                       btRigidBody& rbA = constraint->getRigidBodyA();
+                       btRigidBody& rbB = constraint->getRigidBodyB();
+
+                       int solverBodyIdA = getOrInitSolverBody(rbA, infoGlobal.m_timeStep);
+                       int solverBodyIdB = getOrInitSolverBody(rbB, infoGlobal.m_timeStep);
+
+                       convertJoint(currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
+               }
+               currentRow += info1.m_numConstraintRows;
+       }
+}
+
+void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("convertBodies");
+       for (int i = 0; i < numBodies; i++)
+       {
+               bodies[i]->setCompanionId(-1);
+       }
+#if BT_THREADSAFE
+       m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
+#endif  // BT_THREADSAFE
+
+       m_tmpSolverBodyPool.reserve(numBodies + 1);
+       m_tmpSolverBodyPool.resize(0);
+
+       //btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+       //initSolverBody(&fixedBody,0);
+
+       for (int i = 0; i < numBodies; i++)
+       {
+               int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
+
+               btRigidBody* body = btRigidBody::upcast(bodies[i]);
+               if (body && body->getInvMass())
+               {
+                       btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
+                       btVector3 gyroForce(0, 0, 0);
+                       if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
+                       {
+                               gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
+                               solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep;
+                       }
+                       if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
+                       {
+                               gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
+                               solverBody.m_externalTorqueImpulse += gyroForce;
+                       }
+                       if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
+                       {
+                               gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
+                               solverBody.m_externalTorqueImpulse += gyroForce;
+                       }
+               }
+       }
+}
+
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       m_fixedBodyId = -1;
+       BT_PROFILE("solveGroupCacheFriendlySetup");
+       (void)debugDrawer;
+
+       // if solver mode has changed,
+       if (infoGlobal.m_solverMode != m_cachedSolverMode)
+       {
+               // update solver functions to use SIMD or non-SIMD
+               bool useSimd = !!(infoGlobal.m_solverMode & SOLVER_SIMD);
+               setupSolverFunctions(useSimd);
+               m_cachedSolverMode = infoGlobal.m_solverMode;
+       }
+       m_maxOverrideNumSolverIterations = 0;
+
+#ifdef BT_ADDITIONAL_DEBUG
+       //make sure that dynamic bodies exist for all (enabled) constraints
+       for (int i = 0; i < numConstraints; i++)
+       {
+               btTypedConstraint* constraint = constraints[i];
+               if (constraint->isEnabled())
+               {
+                       if (!constraint->getRigidBodyA().isStaticOrKinematicObject())
+                       {
+                               bool found = false;
+                               for (int b = 0; b < numBodies; b++)
+                               {
+                                       if (&constraint->getRigidBodyA() == bodies[b])
+                                       {
+                                               found = true;
+                                               break;
+                                       }
+                               }
+                               btAssert(found);
+                       }
+                       if (!constraint->getRigidBodyB().isStaticOrKinematicObject())
+                       {
+                               bool found = false;
+                               for (int b = 0; b < numBodies; b++)
+                               {
+                                       if (&constraint->getRigidBodyB() == bodies[b])
+                                       {
+                                               found = true;
+                                               break;
+                                       }
+                               }
+                               btAssert(found);
+                       }
+               }
+       }
+       //make sure that dynamic bodies exist for all contact manifolds
+       for (int i = 0; i < numManifolds; i++)
+       {
+               if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
+               {
+                       bool found = false;
+                       for (int b = 0; b < numBodies; b++)
+                       {
+                               if (manifoldPtr[i]->getBody0() == bodies[b])
+                               {
+                                       found = true;
+                                       break;
+                               }
+                       }
+                       btAssert(found);
+               }
+               if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
+               {
+                       bool found = false;
+                       for (int b = 0; b < numBodies; b++)
+                       {
+                               if (manifoldPtr[i]->getBody1() == bodies[b])
+                               {
+                                       found = true;
+                                       break;
+                               }
+                       }
+                       btAssert(found);
+               }
+       }
+#endif  //BT_ADDITIONAL_DEBUG
+
+       //convert all bodies
+       convertBodies(bodies, numBodies, infoGlobal);
+
+       convertJoints(constraints, numConstraints, infoGlobal);
+
+       convertContacts(manifoldPtr, numManifolds, infoGlobal);
+
+       //      btContactSolverInfo info = infoGlobal;
+
+       int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+       int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+       int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+       ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
+       m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
+       if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+               m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool * 2);
+       else
+               m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
+
+       m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
+       {
+               int i;
+               for (i = 0; i < numNonContactPool; i++)
+               {
+                       m_orderNonContactConstraintPool[i] = i;
+               }
+               for (i = 0; i < numConstraintPool; i++)
+               {
+                       m_orderTmpConstraintPool[i] = i;
+               }
+               for (i = 0; i < numFrictionPool; i++)
+               {
+                       m_orderFrictionConstraintPool[i] = i;
+               }
+       }
+
+       return 0.f;
+}
+
+btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
+{
+       BT_PROFILE("solveSingleIteration");
+       btScalar leastSquaresResidual = 0.f;
+
+       int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
+       int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+       int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+       if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
+       {
+               if (1)  // uncomment this for a bit less random ((iteration & 7) == 0)
+               {
+                       for (int j = 0; j < numNonContactPool; ++j)
+                       {
+                               int tmp = m_orderNonContactConstraintPool[j];
+                               int swapi = btRandInt2(j + 1);
+                               m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
+                               m_orderNonContactConstraintPool[swapi] = tmp;
+                       }
+
+                       //contact/friction constraints are not solved more than
+                       if (iteration < infoGlobal.m_numIterations)
+                       {
+                               for (int j = 0; j < numConstraintPool; ++j)
+                               {
+                                       int tmp = m_orderTmpConstraintPool[j];
+                                       int swapi = btRandInt2(j + 1);
+                                       m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
+                                       m_orderTmpConstraintPool[swapi] = tmp;
+                               }
+
+                               for (int j = 0; j < numFrictionPool; ++j)
+                               {
+                                       int tmp = m_orderFrictionConstraintPool[j];
+                                       int swapi = btRandInt2(j + 1);
+                                       m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
+                                       m_orderFrictionConstraintPool[swapi] = tmp;
+                               }
+                       }
+               }
+       }
+
+       ///solve all joint constraints
+       for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
+       {
+               btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
+               if (iteration < constraint.m_overrideNumSolverIterations)
+               {
+                       btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
+                       leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+               }
+       }
+
+       if (iteration < infoGlobal.m_numIterations)
+       {
+               for (int j = 0; j < numConstraints; j++)
+               {
+                       if (constraints[j]->isEnabled())
+                       {
+                               int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
+                               int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
+                               btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
+                               btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
+                               constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
+                       }
+               }
+
+               ///solve all contact constraints
+               if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+               {
+                       int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                       int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
+
+                       for (int c = 0; c < numPoolConstraints; c++)
+                       {
+                               btScalar totalImpulse = 0;
+
+                               {
+                                       const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
+                                       btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                       leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+
+                                       totalImpulse = solveManifold.m_appliedImpulse;
+                               }
+                               bool applyFriction = true;
+                               if (applyFriction)
+                               {
+                                       {
+                                               btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
+
+                                               if (totalImpulse > btScalar(0))
+                                               {
+                                                       solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                                                       solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+                                                       btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                                       leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+                                               }
+                                       }
+
+                                       if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
+                                       {
+                                               btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
+
+                                               if (totalImpulse > btScalar(0))
+                                               {
+                                                       solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                                                       solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+                                                       btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                                       leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+                                               }
+                                       }
+                               }
+                       }
+               }
+               else  //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+               {
+                       //solve the friction constraints after all contact constraints, don't interleave them
+                       int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                       int j;
+
+                       for (j = 0; j < numPoolConstraints; j++)
+                       {
+                               const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+                               btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                               leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+                       }
+
+                       ///solve all friction constraints
+
+                       int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+                       for (j = 0; j < numFrictionPoolConstraints; j++)
+                       {
+                               btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+                               btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+
+                               if (totalImpulse > btScalar(0))
+                               {
+                                       solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                                       solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+                                       btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                       leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+                               }
+                       }
+               }
+
+               int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+               for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
+               {
+                       btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+                       btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+                       if (totalImpulse > btScalar(0))
+                       {
+                               btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+                               if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+                                       rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+                               rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+                               rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+                               btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+                               leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+                       }
+               }
+       }
+       return leastSquaresResidual;
+}
+
+void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
+       int iteration;
+       if (infoGlobal.m_splitImpulse)
+       {
+               {
+                       for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
+                       {
+                               btScalar leastSquaresResidual = 0.f;
+                               {
+                                       int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                                       int j;
+                                       for (j = 0; j < numPoolConstraints; j++)
+                                       {
+                                               const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+
+                                               btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                               leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+                                       }
+                               }
+                               if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
+                               {
+#ifdef VERBOSE_RESIDUAL_PRINTF
+                                       printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
+#endif
+                                       break;
+                               }
+                       }
+               }
+       }
+}
+
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       BT_PROFILE("solveGroupCacheFriendlyIterations");
+
+       {
+               ///this is a special step to resolve penetrations (just for contacts)
+               solveGroupCacheFriendlySplitImpulseIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+               int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
+
+               for (int iteration = 0; iteration < maxIterations; iteration++)
+                       //for ( int iteration = maxIterations-1  ; iteration >= 0;iteration--)
+               {
+                       m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+                       if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1)))
+                       {
+#ifdef VERBOSE_RESIDUAL_PRINTF
+                               printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
+#endif
+                               m_analyticsData.m_numSolverCalls++;
+                               m_analyticsData.m_numIterationsUsed = iteration+1;
+                               m_analyticsData.m_islandId = -2;
+                               if (numBodies>0)
+                                       m_analyticsData.m_islandId = bodies[0]->getCompanionId();
+                               m_analyticsData.m_numBodies = numBodies;
+                               m_analyticsData.m_numContactManifolds = numManifolds;
+                               m_analyticsData.m_remainingLeastSquaresResidual = m_leastSquaresResidual;
+                               break;
+                       }
+               }
+       }
+       return 0.f;
+}
+
+void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
+       for (int j = iBegin; j < iEnd; j++)
+       {
+               const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
+               btManifoldPoint* pt = (btManifoldPoint*)solveManifold.m_originalContactPoint;
+               btAssert(pt);
+               pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
+               //      float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+               //      printf("pt->m_appliedImpulseLateral1 = %f\n", f);
+               pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+               //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
+               if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+               {
+                       pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
+               }
+               //do a callback here?
+       }
+}
+
+void btSequentialImpulseConstraintSolver::writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
+       for (int j = iBegin; j < iEnd; j++)
+       {
+               const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
+               btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
+               btJointFeedback* fb = constr->getJointFeedback();
+               if (fb)
+               {
+                       fb->m_appliedForceBodyA += solverConstr.m_contactNormal1 * solverConstr.m_appliedImpulse * constr->getRigidBodyA().getLinearFactor() / infoGlobal.m_timeStep;
+                       fb->m_appliedForceBodyB += solverConstr.m_contactNormal2 * solverConstr.m_appliedImpulse * constr->getRigidBodyB().getLinearFactor() / infoGlobal.m_timeStep;
+                       fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal * constr->getRigidBodyA().getAngularFactor() * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep;
+                       fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal * constr->getRigidBodyB().getAngularFactor() * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep; /*RGM ???? */
+               }
+
+               constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
+               if (btFabs(solverConstr.m_appliedImpulse) >= constr->getBreakingImpulseThreshold())
+               {
+                       constr->setEnabled(false);
+               }
+       }
+}
+
+void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
+       for (int i = iBegin; i < iEnd; i++)
+       {
+               btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
+               if (body)
+               {
+                       if (infoGlobal.m_splitImpulse)
+                               m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
+                       else
+                               m_tmpSolverBodyPool[i].writebackVelocity();
+
+                       m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
+                               m_tmpSolverBodyPool[i].m_linearVelocity +
+                               m_tmpSolverBodyPool[i].m_externalForceImpulse);
+
+                       m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
+                               m_tmpSolverBodyPool[i].m_angularVelocity +
+                               m_tmpSolverBodyPool[i].m_externalTorqueImpulse);
+
+                       if (infoGlobal.m_splitImpulse)
+                               m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform);
+
+                       m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
+               }
+       }
+}
+
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("solveGroupCacheFriendlyFinish");
+
+       if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+       {
+               writeBackContacts(0, m_tmpSolverContactConstraintPool.size(), infoGlobal);
+       }
+
+       writeBackJoints(0, m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
+       writeBackBodies(0, m_tmpSolverBodyPool.size(), infoGlobal);
+
+       m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
+
+       m_tmpSolverBodyPool.resizeNoInitialize(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, btDispatcher* /*dispatcher*/)
+{
+       BT_PROFILE("solveGroup");
+       //you need to provide at least some bodies
+
+       solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+       solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+       solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
+
+       return 0.f;
+}
+
+void btSequentialImpulseConstraintSolver::reset()
+{
+       m_btSeed2 = 0;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
new file mode 100644 (file)
index 0000000..cd00967
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
+#define BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
+
+class btIDebugDraw;
+class btPersistentManifold;
+class btDispatcher;
+class btCollisionObject;
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
+#include "BulletDynamics/ConstraintSolver/btSolverConstraint.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
+
+typedef btScalar (*btSingleConstraintRowSolver)(btSolverBody&, btSolverBody&, const btSolverConstraint&);
+
+struct btSolverAnalyticsData
+{
+       btSolverAnalyticsData()
+       {
+               m_numSolverCalls = 0;
+               m_numIterationsUsed = -1;
+               m_remainingLeastSquaresResidual = -1;
+               m_islandId = -2;
+       }
+       int m_islandId;
+       int m_numBodies;
+       int m_numContactManifolds;
+       int m_numSolverCalls;
+       int m_numIterationsUsed;
+       double m_remainingLeastSquaresResidual;
+};
+
+///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method.
+ATTRIBUTE_ALIGNED16(class)
+btSequentialImpulseConstraintSolver : public btConstraintSolver
+{
+       
+
+protected:
+       btAlignedObjectArray<btSolverBody> m_tmpSolverBodyPool;
+       btConstraintArray m_tmpSolverContactConstraintPool;
+       btConstraintArray m_tmpSolverNonContactConstraintPool;
+       btConstraintArray m_tmpSolverContactFrictionConstraintPool;
+       btConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
+
+       btAlignedObjectArray<int> m_orderTmpConstraintPool;
+       btAlignedObjectArray<int> m_orderNonContactConstraintPool;
+       btAlignedObjectArray<int> m_orderFrictionConstraintPool;
+       btAlignedObjectArray<btTypedConstraint::btConstraintInfo1> m_tmpConstraintSizesPool;
+       int m_maxOverrideNumSolverIterations;
+       int m_fixedBodyId;
+       // When running solvers on multiple threads, a race condition exists for Kinematic objects that
+       // participate in more than one solver.
+       // The getOrInitSolverBody() function writes the companionId of each body (storing the index of the solver body
+       // for the current solver). For normal dynamic bodies it isn't an issue because they can only be in one island
+       // (and therefore one thread) at a time. But kinematic bodies can be in multiple islands at once.
+       // To avoid this race condition, this solver does not write the companionId, instead it stores the solver body
+       // index in this solver-local table, indexed by the uniqueId of the body.
+       btAlignedObjectArray<int> m_kinematicBodyUniqueIdToSolverBodyTable;  // only used for multithreading
+
+       btSingleConstraintRowSolver m_resolveSingleConstraintRowGeneric;
+       btSingleConstraintRowSolver m_resolveSingleConstraintRowLowerLimit;
+       btSingleConstraintRowSolver m_resolveSplitPenetrationImpulse;
+       int m_cachedSolverMode;  // used to check if SOLVER_SIMD flag has been changed
+       void setupSolverFunctions(bool useSimd);
+
+       btScalar m_leastSquaresResidual;
+
+       void setupFrictionConstraint(btSolverConstraint & solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
+               btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2,
+               btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
+               const btContactSolverInfo& infoGlobal,
+               btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
+
+       void setupTorsionalFrictionConstraint(btSolverConstraint & solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
+               btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
+               btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
+               btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
+
+       btSolverConstraint& 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, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
+       btSolverConstraint& addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar torsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity = 0, btScalar cfmSlip = 0.f);
+
+       void setupContactConstraint(btSolverConstraint & solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp,
+               const btContactSolverInfo& infoGlobal, btScalar& relaxation, const btVector3& rel_pos1, const btVector3& rel_pos2);
+
+       static void applyAnisotropicFriction(btCollisionObject * colObj, btVector3 & frictionDirection, int frictionMode);
+
+       void setFrictionConstraintImpulse(btSolverConstraint & solverConstraint, int solverBodyIdA, int solverBodyIdB,
+               btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
+
+       ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
+       unsigned long m_btSeed2;
+
+       btScalar restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold);
+
+       virtual void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
+
+       void convertContact(btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
+
+       virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
+       void convertJoint(btSolverConstraint * currentConstraintRow, btTypedConstraint * constraint, const btTypedConstraint::btConstraintInfo1& info1, int solverBodyIdA, int solverBodyIdB, const btContactSolverInfo& infoGlobal);
+
+       virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+
+       btScalar resolveSplitPenetrationSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
+       {
+               return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
+       }
+
+       btScalar resolveSplitPenetrationImpulseCacheFriendly(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
+       {
+               return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
+       }
+
+       //internal method
+       int getOrInitSolverBody(btCollisionObject & body, btScalar timeStep);
+       void initSolverBody(btSolverBody * solverBody, btCollisionObject * collisionObject, btScalar timeStep);
+
+       btScalar resolveSingleConstraintRowGeneric(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
+       btScalar resolveSingleConstraintRowGenericSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
+       btScalar resolveSingleConstraintRowLowerLimit(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
+       btScalar resolveSingleConstraintRowLowerLimitSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
+       btScalar resolveSplitPenetrationImpulse(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
+       {
+               return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
+       }
+
+protected:
+       void writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+       void writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+       void writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+       virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+       virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+       virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+
+       virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+       virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btSequentialImpulseConstraintSolver();
+       virtual ~btSequentialImpulseConstraintSolver();
+
+       virtual btScalar solveGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
+
+       ///clear internal cached data and reset random seed
+       virtual void reset();
+
+       unsigned long btRand2();
+
+       int btRandInt2(int n);
+
+       void setRandSeed(unsigned long seed)
+       {
+               m_btSeed2 = seed;
+       }
+       unsigned long getRandSeed() const
+       {
+               return m_btSeed2;
+       }
+
+       virtual btConstraintSolverType getSolverType() const
+       {
+               return BT_SEQUENTIAL_IMPULSE_SOLVER;
+       }
+
+       btSingleConstraintRowSolver getActiveConstraintRowSolverGeneric()
+       {
+               return m_resolveSingleConstraintRowGeneric;
+       }
+       void setConstraintRowSolverGeneric(btSingleConstraintRowSolver rowSolver)
+       {
+               m_resolveSingleConstraintRowGeneric = rowSolver;
+       }
+       btSingleConstraintRowSolver getActiveConstraintRowSolverLowerLimit()
+       {
+               return m_resolveSingleConstraintRowLowerLimit;
+       }
+       void setConstraintRowSolverLowerLimit(btSingleConstraintRowSolver rowSolver)
+       {
+               m_resolveSingleConstraintRowLowerLimit = rowSolver;
+       }
+
+
+
+       ///Various implementations of solving a single constraint row using a generic equality constraint, using scalar reference, SSE2 or SSE4
+       btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric();
+       btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric();
+       btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric();
+
+       ///Various implementations of solving a single constraint row using an inequality (lower limit) constraint, using scalar reference, SSE2 or SSE4
+       btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit();
+       btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit();
+       btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit();
+       btSolverAnalyticsData m_analyticsData;
+};
+
+#endif  //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp
new file mode 100644 (file)
index 0000000..7aa9953
--- /dev/null
@@ -0,0 +1,1554 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btSequentialImpulseConstraintSolverMt.h"
+
+#include "LinearMath/btQuickprof.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+bool btSequentialImpulseConstraintSolverMt::s_allowNestedParallelForLoops = false;  // some task schedulers don't like nested loops
+int btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching = 250;
+int btSequentialImpulseConstraintSolverMt::s_minBatchSize = 50;
+int btSequentialImpulseConstraintSolverMt::s_maxBatchSize = 100;
+btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_contactBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
+btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_jointBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
+
+btSequentialImpulseConstraintSolverMt::btSequentialImpulseConstraintSolverMt()
+{
+       m_numFrictionDirections = 1;
+       m_useBatching = false;
+       m_useObsoleteJointConstraints = false;
+}
+
+btSequentialImpulseConstraintSolverMt::~btSequentialImpulseConstraintSolverMt()
+{
+}
+
+void btSequentialImpulseConstraintSolverMt::setupBatchedContactConstraints()
+{
+       BT_PROFILE("setupBatchedContactConstraints");
+       m_batchedContactConstraints.setup(&m_tmpSolverContactConstraintPool,
+                                                                         m_tmpSolverBodyPool,
+                                                                         s_contactBatchingMethod,
+                                                                         s_minBatchSize,
+                                                                         s_maxBatchSize,
+                                                                         &m_scratchMemory);
+}
+
+void btSequentialImpulseConstraintSolverMt::setupBatchedJointConstraints()
+{
+       BT_PROFILE("setupBatchedJointConstraints");
+       m_batchedJointConstraints.setup(&m_tmpSolverNonContactConstraintPool,
+                                                                       m_tmpSolverBodyPool,
+                                                                       s_jointBatchingMethod,
+                                                                       s_minBatchSize,
+                                                                       s_maxBatchSize,
+                                                                       &m_scratchMemory);
+}
+
+void btSequentialImpulseConstraintSolverMt::internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal)
+{
+       btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint];
+
+       btVector3 rel_pos1;
+       btVector3 rel_pos2;
+       btScalar relaxation;
+
+       int solverBodyIdA = contactConstraint.m_solverBodyIdA;
+       int solverBodyIdB = contactConstraint.m_solverBodyIdB;
+
+       btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+       btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+       btRigidBody* colObj0 = solverBodyA->m_originalBody;
+       btRigidBody* colObj1 = solverBodyB->m_originalBody;
+
+       btManifoldPoint& cp = *static_cast<btManifoldPoint*>(contactConstraint.m_originalContactPoint);
+
+       const btVector3& pos1 = cp.getPositionWorldOnA();
+       const btVector3& pos2 = cp.getPositionWorldOnB();
+
+       rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin();
+       rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin();
+
+       btVector3 vel1;
+       btVector3 vel2;
+
+       solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1);
+       solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2);
+
+       btVector3 vel = vel1 - vel2;
+       btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
+
+       setupContactConstraint(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
+
+       // setup rolling friction constraints
+       int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint];
+       if (rollingFrictionIndex >= 0)
+       {
+               btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex];
+               btAssert(spinningFrictionConstraint.m_frictionIndex == iContactConstraint);
+               setupTorsionalFrictionConstraint(spinningFrictionConstraint,
+                                                                                cp.m_normalWorldOnB,
+                                                                                solverBodyIdA,
+                                                                                solverBodyIdB,
+                                                                                cp,
+                                                                                cp.m_combinedSpinningFriction,
+                                                                                rel_pos1,
+                                                                                rel_pos2,
+                                                                                colObj0,
+                                                                                colObj1,
+                                                                                relaxation,
+                                                                                0.0f,
+                                                                                0.0f);
+               btVector3 axis[2];
+               btPlaneSpace1(cp.m_normalWorldOnB, axis[0], axis[1]);
+               axis[0].normalize();
+               axis[1].normalize();
+
+               applyAnisotropicFriction(colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+               applyAnisotropicFriction(colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+               applyAnisotropicFriction(colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+               applyAnisotropicFriction(colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+               // put the largest axis first
+               if (axis[1].length2() > axis[0].length2())
+               {
+                       btSwap(axis[0], axis[1]);
+               }
+               const btScalar kRollingFrictionThreshold = 0.001f;
+               for (int i = 0; i < 2; ++i)
+               {
+                       int iRollingFric = rollingFrictionIndex + 1 + i;
+                       btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
+                       btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint);
+                       btVector3 dir = axis[i];
+                       if (dir.length() > kRollingFrictionThreshold)
+                       {
+                               setupTorsionalFrictionConstraint(rollingFrictionConstraint,
+                                                                                                dir,
+                                                                                                solverBodyIdA,
+                                                                                                solverBodyIdB,
+                                                                                                cp,
+                                                                                                cp.m_combinedRollingFriction,
+                                                                                                rel_pos1,
+                                                                                                rel_pos2,
+                                                                                                colObj0,
+                                                                                                colObj1,
+                                                                                                relaxation,
+                                                                                                0.0f,
+                                                                                                0.0f);
+                       }
+                       else
+                       {
+                               rollingFrictionConstraint.m_frictionIndex = -1;  // disable constraint
+                       }
+               }
+       }
+
+       // setup friction constraints
+       //      setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
+       {
+               ///Bullet has several options to set the friction directions
+               ///By default, each contact has only a single friction direction that is recomputed automatically very frame
+               ///based on the relative linear velocity.
+               ///If the relative velocity it zero, it will automatically compute a friction direction.
+
+               ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
+               ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
+               ///
+               ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
+               ///
+               ///The user can manually override the friction directions for certain contacts using a contact callback,
+               ///and set the cp.m_lateralFrictionInitialized to true
+               ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
+               ///this will give a conveyor belt effect
+               ///
+               btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex];
+               btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint);
+
+               btSolverConstraint* frictionConstraint2 = NULL;
+               if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
+               {
+                       frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1];
+                       btAssert(frictionConstraint2->m_frictionIndex == iContactConstraint);
+               }
+
+               if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
+               {
+                       cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
+                       btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
+                       if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
+                       {
+                               cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
+                               applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                               applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                               setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+
+                               if (frictionConstraint2)
+                               {
+                                       cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
+                                       cp.m_lateralFrictionDir2.normalize();  //??
+                                       applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+                               }
+                       }
+                       else
+                       {
+                               btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
+
+                               applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                               applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                               setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+
+                               if (frictionConstraint2)
+                               {
+                                       applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
+                               }
+
+                               if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+                               {
+                                       cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
+                               }
+                       }
+               }
+               else
+               {
+                       setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
+                       if (frictionConstraint2)
+                       {
+                               setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
+                       }
+               }
+       }
+
+       setFrictionConstraintImpulse(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
+}
+
+struct SetupContactConstraintsLoop : public btIParallelForBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btBatchedConstraints* m_bc;
+       const btContactSolverInfo* m_infoGlobal;
+
+       SetupContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal)
+       {
+               m_solver = solver;
+               m_bc = bc;
+               m_infoGlobal = &infoGlobal;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               BT_PROFILE("SetupContactConstraintsLoop");
+               for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+               {
+                       const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+                       for (int i = batch.begin; i < batch.end; ++i)
+                       {
+                               int iContact = m_bc->m_constraintIndices[i];
+                               m_solver->internalSetupContactConstraints(iContact, *m_infoGlobal);
+                       }
+               }
+       }
+};
+
+void btSequentialImpulseConstraintSolverMt::setupAllContactConstraints(const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("setupAllContactConstraints");
+       if (m_useBatching)
+       {
+               const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+               SetupContactConstraintsLoop loop(this, &batchedCons, infoGlobal);
+               for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+               {
+                       int iPhase = batchedCons.m_phaseOrder[iiPhase];
+                       const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+                       int grainSize = 1;
+                       btParallelFor(phase.begin, phase.end, grainSize, loop);
+               }
+       }
+       else
+       {
+               for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i)
+               {
+                       internalSetupContactConstraints(i, infoGlobal);
+               }
+       }
+}
+
+int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body, btScalar timeStep)
+{
+       //
+       // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers)
+       //
+       // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism)
+       //
+       int solverBodyId = -1;
+       bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
+       if (isRigidBodyType && !body.isStaticOrKinematicObject())
+       {
+               // dynamic body
+               // Dynamic bodies can only be in one island, so it's safe to write to the companionId
+               solverBodyId = body.getCompanionId();
+               if (solverBodyId < 0)
+               {
+                       m_bodySolverArrayMutex.lock();
+                       // now that we have the lock, check again
+                       solverBodyId = body.getCompanionId();
+                       if (solverBodyId < 0)
+                       {
+                               solverBodyId = m_tmpSolverBodyPool.size();
+                               btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+                               initSolverBody(&solverBody, &body, timeStep);
+                               body.setCompanionId(solverBodyId);
+                       }
+                       m_bodySolverArrayMutex.unlock();
+               }
+       }
+       else if (isRigidBodyType && body.isKinematicObject())
+       {
+               //
+               // NOTE: must test for kinematic before static because some kinematic objects also
+               //   identify as "static"
+               //
+               // Kinematic bodies can be in multiple islands at once, so it is a
+               // race condition to write to them, so we use an alternate method
+               // to record the solverBodyId
+               int uniqueId = body.getWorldArrayIndex();
+               const int INVALID_SOLVER_BODY_ID = -1;
+               if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId)
+               {
+                       m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
+                       // now that we have the lock, check again
+                       if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId)
+                       {
+                               m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
+                       }
+                       m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
+               }
+               solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
+               // if no table entry yet,
+               if (INVALID_SOLVER_BODY_ID == solverBodyId)
+               {
+                       // need to acquire both locks
+                       m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
+                       m_bodySolverArrayMutex.lock();
+                       // now that we have the lock, check again
+                       solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
+                       if (INVALID_SOLVER_BODY_ID == solverBodyId)
+                       {
+                               // create a table entry for this body
+                               solverBodyId = m_tmpSolverBodyPool.size();
+                               btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+                               initSolverBody(&solverBody, &body, timeStep);
+                               m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
+                       }
+                       m_bodySolverArrayMutex.unlock();
+                       m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
+               }
+       }
+       else
+       {
+               // all fixed bodies (inf mass) get mapped to a single solver id
+               if (m_fixedBodyId < 0)
+               {
+                       m_bodySolverArrayMutex.lock();
+                       // now that we have the lock, check again
+                       if (m_fixedBodyId < 0)
+                       {
+                               m_fixedBodyId = m_tmpSolverBodyPool.size();
+                               btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+                               initSolverBody(&fixedBody, 0, timeStep);
+                       }
+                       m_bodySolverArrayMutex.unlock();
+               }
+               solverBodyId = m_fixedBodyId;
+       }
+       btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
+       return solverBodyId;
+}
+
+void btSequentialImpulseConstraintSolverMt::internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("internalCollectContactManifoldCachedInfo");
+       for (int i = 0; i < numManifolds; ++i)
+       {
+               btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i];
+               btPersistentManifold* manifold = manifoldPtr[i];
+               btCollisionObject* colObj0 = (btCollisionObject*)manifold->getBody0();
+               btCollisionObject* colObj1 = (btCollisionObject*)manifold->getBody1();
+
+               int solverBodyIdA = getOrInitSolverBodyThreadsafe(*colObj0, infoGlobal.m_timeStep);
+               int solverBodyIdB = getOrInitSolverBodyThreadsafe(*colObj1, infoGlobal.m_timeStep);
+
+               cachedInfo->solverBodyIds[0] = solverBodyIdA;
+               cachedInfo->solverBodyIds[1] = solverBodyIdB;
+               cachedInfo->numTouchingContacts = 0;
+
+               btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+               btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+               // A contact manifold between 2 static object should not exist!
+               // check the collision flags of your objects if this assert fires.
+               // Incorrectly set collision object flags can degrade performance in various ways.
+               btAssert(!m_tmpSolverBodyPool[solverBodyIdA].m_invMass.isZero() || !m_tmpSolverBodyPool[solverBodyIdB].m_invMass.isZero());
+
+               int iContact = 0;
+               for (int j = 0; j < manifold->getNumContacts(); j++)
+               {
+                       btManifoldPoint& cp = manifold->getContactPoint(j);
+
+                       if (cp.getDistance() <= manifold->getContactProcessingThreshold())
+                       {
+                               cachedInfo->contactPoints[iContact] = &cp;
+                               cachedInfo->contactHasRollingFriction[iContact] = (cp.m_combinedRollingFriction > 0.f);
+                               iContact++;
+                       }
+               }
+               cachedInfo->numTouchingContacts = iContact;
+       }
+}
+
+struct CollectContactManifoldCachedInfoLoop : public btIParallelForBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
+       btPersistentManifold** m_manifoldPtr;
+       const btContactSolverInfo* m_infoGlobal;
+
+       CollectContactManifoldCachedInfoLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal)
+       {
+               m_solver = solver;
+               m_cachedInfoArray = cachedInfoArray;
+               m_manifoldPtr = manifoldPtr;
+               m_infoGlobal = &infoGlobal;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               m_solver->internalCollectContactManifoldCachedInfo(m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal);
+       }
+};
+
+void btSequentialImpulseConstraintSolverMt::internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds)
+{
+       BT_PROFILE("internalAllocContactConstraints");
+       // possibly parallel part
+       for (int iManifold = 0; iManifold < numManifolds; ++iManifold)
+       {
+               const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold];
+               int contactIndex = cachedInfo.contactIndex;
+               int frictionIndex = contactIndex * m_numFrictionDirections;
+               int rollingFrictionIndex = cachedInfo.rollingFrictionIndex;
+               for (int i = 0; i < cachedInfo.numTouchingContacts; i++)
+               {
+                       btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex];
+                       contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[0];
+                       contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[1];
+                       contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[i];
+
+                       // allocate the friction constraints
+                       contactConstraint.m_frictionIndex = frictionIndex;
+                       for (int iDir = 0; iDir < m_numFrictionDirections; ++iDir)
+                       {
+                               btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex];
+                               frictionConstraint.m_frictionIndex = contactIndex;
+                               frictionIndex++;
+                       }
+
+                       // allocate rolling friction constraints
+                       if (cachedInfo.contactHasRollingFriction[i])
+                       {
+                               m_rollingFrictionIndexTable[contactIndex] = rollingFrictionIndex;
+                               // allocate 3 (although we may use only 2 sometimes)
+                               for (int i = 0; i < 3; i++)
+                               {
+                                       m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex].m_frictionIndex = contactIndex;
+                                       rollingFrictionIndex++;
+                               }
+                       }
+                       else
+                       {
+                               // indicate there is no rolling friction for this contact point
+                               m_rollingFrictionIndexTable[contactIndex] = -1;
+                       }
+                       contactIndex++;
+               }
+       }
+}
+
+struct AllocContactConstraintsLoop : public btIParallelForBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
+
+       AllocContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray)
+       {
+               m_solver = solver;
+               m_cachedInfoArray = cachedInfoArray;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               m_solver->internalAllocContactConstraints(m_cachedInfoArray + iBegin, iEnd - iBegin);
+       }
+};
+
+void btSequentialImpulseConstraintSolverMt::allocAllContactConstraints(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("allocAllContactConstraints");
+       btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray;  // = m_manifoldCachedInfoArray;
+       cachedInfoArray.resizeNoInitialize(numManifolds);
+       if (/* DISABLES CODE */ (false))
+       {
+               // sequential
+               internalCollectContactManifoldCachedInfo(&cachedInfoArray[0], manifoldPtr, numManifolds, infoGlobal);
+       }
+       else
+       {
+               // may alter ordering of bodies which affects determinism
+               CollectContactManifoldCachedInfoLoop loop(this, &cachedInfoArray[0], manifoldPtr, infoGlobal);
+               int grainSize = 200;
+               btParallelFor(0, numManifolds, grainSize, loop);
+       }
+
+       {
+               // serial part
+               int numContacts = 0;
+               int numRollingFrictionConstraints = 0;
+               for (int iManifold = 0; iManifold < numManifolds; ++iManifold)
+               {
+                       btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold];
+                       cachedInfo.contactIndex = numContacts;
+                       cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints;
+                       numContacts += cachedInfo.numTouchingContacts;
+                       for (int i = 0; i < cachedInfo.numTouchingContacts; ++i)
+                       {
+                               if (cachedInfo.contactHasRollingFriction[i])
+                               {
+                                       numRollingFrictionConstraints += 3;
+                               }
+                       }
+               }
+               {
+                       BT_PROFILE("allocPools");
+                       if (m_tmpSolverContactConstraintPool.capacity() < numContacts)
+                       {
+                               // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame
+                               int extraReserve = numContacts / 16;
+                               m_tmpSolverContactConstraintPool.reserve(numContacts + extraReserve);
+                               m_rollingFrictionIndexTable.reserve(numContacts + extraReserve);
+                               m_tmpSolverContactFrictionConstraintPool.reserve((numContacts + extraReserve) * m_numFrictionDirections);
+                               m_tmpSolverContactRollingFrictionConstraintPool.reserve(numRollingFrictionConstraints + extraReserve);
+                       }
+                       m_tmpSolverContactConstraintPool.resizeNoInitialize(numContacts);
+                       m_rollingFrictionIndexTable.resizeNoInitialize(numContacts);
+                       m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(numContacts * m_numFrictionDirections);
+                       m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(numRollingFrictionConstraints);
+               }
+       }
+       {
+               AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]);
+               int grainSize = 200;
+               btParallelFor(0, numManifolds, grainSize, loop);
+       }
+}
+
+void btSequentialImpulseConstraintSolverMt::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
+{
+       if (!m_useBatching)
+       {
+               btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal);
+               return;
+       }
+       BT_PROFILE("convertContacts");
+       if (numManifolds > 0)
+       {
+               if (m_fixedBodyId < 0)
+               {
+                       m_fixedBodyId = m_tmpSolverBodyPool.size();
+                       btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+                       initSolverBody(&fixedBody, 0, infoGlobal.m_timeStep);
+               }
+               allocAllContactConstraints(manifoldPtr, numManifolds, infoGlobal);
+               if (m_useBatching)
+               {
+                       setupBatchedContactConstraints();
+               }
+               setupAllContactConstraints(infoGlobal);
+       }
+}
+
+void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints(btTypedConstraint** constraints, int iBegin, int iEnd)
+{
+       BT_PROFILE("internalInitMultipleJoints");
+       for (int i = iBegin; i < iEnd; i++)
+       {
+               btTypedConstraint* constraint = constraints[i];
+               btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+               if (constraint->isEnabled())
+               {
+                       constraint->buildJacobian();
+                       constraint->internalSetAppliedImpulse(0.0f);
+                       btJointFeedback* fb = constraint->getJointFeedback();
+                       if (fb)
+                       {
+                               fb->m_appliedForceBodyA.setZero();
+                               fb->m_appliedTorqueBodyA.setZero();
+                               fb->m_appliedForceBodyB.setZero();
+                               fb->m_appliedTorqueBodyB.setZero();
+                       }
+                       constraint->getInfo1(&info1);
+               }
+               else
+               {
+                       info1.m_numConstraintRows = 0;
+                       info1.nub = 0;
+               }
+       }
+}
+
+struct InitJointsLoop : public btIParallelForBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       btTypedConstraint** m_constraints;
+
+       InitJointsLoop(btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints)
+       {
+               m_solver = solver;
+               m_constraints = constraints;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               m_solver->internalInitMultipleJoints(m_constraints, iBegin, iEnd);
+       }
+};
+
+void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("internalConvertMultipleJoints");
+       for (int i = iBegin; i < iEnd; ++i)
+       {
+               const JointParams& jointParams = jointParamsArray[i];
+               int currentRow = jointParams.m_solverConstraint;
+               if (currentRow != -1)
+               {
+                       const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+                       btAssert(currentRow < m_tmpSolverNonContactConstraintPool.size());
+                       btAssert(info1.m_numConstraintRows > 0);
+
+                       btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
+                       btTypedConstraint* constraint = constraints[i];
+
+                       convertJoint(currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal);
+               }
+       }
+}
+
+struct ConvertJointsLoop : public btIParallelForBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray;
+       btTypedConstraint** m_srcConstraints;
+       const btContactSolverInfo& m_infoGlobal;
+
+       ConvertJointsLoop(btSequentialImpulseConstraintSolverMt* solver,
+                                         const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray,
+                                         btTypedConstraint** srcConstraints,
+                                         const btContactSolverInfo& infoGlobal) : m_jointParamsArray(jointParamsArray),
+                                                                                                                          m_infoGlobal(infoGlobal)
+       {
+               m_solver = solver;
+               m_srcConstraints = srcConstraints;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               m_solver->internalConvertMultipleJoints(m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal);
+       }
+};
+
+void btSequentialImpulseConstraintSolverMt::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
+{
+       if (!m_useBatching)
+       {
+               btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal);
+               return;
+       }
+       BT_PROFILE("convertJoints");
+       bool parallelJointSetup = true;
+       m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
+       if (parallelJointSetup)
+       {
+               InitJointsLoop loop(this, constraints);
+               int grainSize = 40;
+               btParallelFor(0, numConstraints, grainSize, loop);
+       }
+       else
+       {
+               internalInitMultipleJoints(constraints, 0, numConstraints);
+       }
+
+       int totalNumRows = 0;
+       btAlignedObjectArray<JointParams> jointParamsArray;
+       jointParamsArray.resizeNoInitialize(numConstraints);
+
+       //calculate the total number of contraint rows
+       for (int i = 0; i < numConstraints; i++)
+       {
+               btTypedConstraint* constraint = constraints[i];
+
+               JointParams& params = jointParamsArray[i];
+               const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+
+               if (info1.m_numConstraintRows)
+               {
+                       params.m_solverConstraint = totalNumRows;
+                       params.m_solverBodyA = getOrInitSolverBody(constraint->getRigidBodyA(), infoGlobal.m_timeStep);
+                       params.m_solverBodyB = getOrInitSolverBody(constraint->getRigidBodyB(), infoGlobal.m_timeStep);
+               }
+               else
+               {
+                       params.m_solverConstraint = -1;
+               }
+               totalNumRows += info1.m_numConstraintRows;
+       }
+       m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
+
+       ///setup the btSolverConstraints
+       if (parallelJointSetup)
+       {
+               ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal);
+               int grainSize = 20;
+               btParallelFor(0, numConstraints, grainSize, loop);
+       }
+       else
+       {
+               internalConvertMultipleJoints(jointParamsArray, constraints, 0, numConstraints, infoGlobal);
+       }
+       setupBatchedJointConstraints();
+}
+
+void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObject** bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("internalConvertBodies");
+       for (int i = iBegin; i < iEnd; i++)
+       {
+               btCollisionObject* obj = bodies[i];
+               obj->setCompanionId(i);
+               btSolverBody& solverBody = m_tmpSolverBodyPool[i];
+               initSolverBody(&solverBody, obj, infoGlobal.m_timeStep);
+
+               btRigidBody* body = btRigidBody::upcast(obj);
+               if (body && body->getInvMass())
+               {
+                       btVector3 gyroForce(0, 0, 0);
+                       if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
+                       {
+                               gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
+                               solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep;
+                       }
+                       if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
+                       {
+                               gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
+                               solverBody.m_externalTorqueImpulse += gyroForce;
+                       }
+                       if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
+                       {
+                               gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
+                               solverBody.m_externalTorqueImpulse += gyroForce;
+                       }
+               }
+       }
+}
+
+struct ConvertBodiesLoop : public btIParallelForBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       btCollisionObject** m_bodies;
+       int m_numBodies;
+       const btContactSolverInfo& m_infoGlobal;
+
+       ConvertBodiesLoop(btSequentialImpulseConstraintSolverMt* solver,
+                                         btCollisionObject** bodies,
+                                         int numBodies,
+                                         const btContactSolverInfo& infoGlobal) : m_infoGlobal(infoGlobal)
+       {
+               m_solver = solver;
+               m_bodies = bodies;
+               m_numBodies = numBodies;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               m_solver->internalConvertBodies(m_bodies, iBegin, iEnd, m_infoGlobal);
+       }
+};
+
+void btSequentialImpulseConstraintSolverMt::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("convertBodies");
+       m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
+
+       m_tmpSolverBodyPool.resizeNoInitialize(numBodies + 1);
+
+       m_fixedBodyId = numBodies;
+       {
+               btSolverBody& fixedBody = m_tmpSolverBodyPool[m_fixedBodyId];
+               initSolverBody(&fixedBody, NULL, infoGlobal.m_timeStep);
+       }
+
+       bool parallelBodySetup = true;
+       if (parallelBodySetup)
+       {
+               ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal);
+               int grainSize = 40;
+               btParallelFor(0, numBodies, grainSize, loop);
+       }
+       else
+       {
+               internalConvertBodies(bodies, 0, numBodies, infoGlobal);
+       }
+}
+
+btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySetup(
+       btCollisionObject** bodies,
+       int numBodies,
+       btPersistentManifold** manifoldPtr,
+       int numManifolds,
+       btTypedConstraint** constraints,
+       int numConstraints,
+       const btContactSolverInfo& infoGlobal,
+       btIDebugDraw* debugDrawer)
+{
+       m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
+       m_useBatching = false;
+       if (numManifolds >= s_minimumContactManifoldsForBatching &&
+               (s_allowNestedParallelForLoops || !btThreadsAreRunning()))
+       {
+               m_useBatching = true;
+               m_batchedContactConstraints.m_debugDrawer = debugDrawer;
+               m_batchedJointConstraints.m_debugDrawer = debugDrawer;
+       }
+       btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies,
+                                                                                                                                         numBodies,
+                                                                                                                                         manifoldPtr,
+                                                                                                                                         numManifolds,
+                                                                                                                                         constraints,
+                                                                                                                                         numConstraints,
+                                                                                                                                         infoGlobal,
+                                                                                                                                         debugDrawer);
+       return 0.0f;
+}
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
+{
+       btScalar leastSquaresResidual = 0.f;
+       for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
+       {
+               int iCons = consIndices[iiCons];
+               const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons];
+               btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
+               btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
+               btScalar residual = resolveSplitPenetrationImpulse(bodyA, bodyB, solveManifold);
+               leastSquaresResidual += residual * residual;
+       }
+       return leastSquaresResidual;
+}
+
+struct ContactSplitPenetrationImpulseSolverLoop : public btIParallelSumBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btBatchedConstraints* m_bc;
+
+       ContactSplitPenetrationImpulseSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
+       {
+               m_solver = solver;
+               m_bc = bc;
+       }
+       btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               BT_PROFILE("ContactSplitPenetrationImpulseSolverLoop");
+               btScalar sum = 0;
+               for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+               {
+                       const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+                       sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
+               }
+               return sum;
+       }
+};
+
+void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
+       if (infoGlobal.m_splitImpulse)
+       {
+               for (int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
+               {
+                       btScalar leastSquaresResidual = 0.f;
+                       if (m_useBatching)
+                       {
+                               const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+                               ContactSplitPenetrationImpulseSolverLoop loop(this, &batchedCons);
+                               btScalar leastSquaresResidual = 0.f;
+                               for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+                               {
+                                       int iPhase = batchedCons.m_phaseOrder[iiPhase];
+                                       const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+                                       int grainSize = batchedCons.m_phaseGrainSize[iPhase];
+                                       leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+                               }
+                       }
+                       else
+                       {
+                               // non-batched
+                               leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size());
+                       }
+                       if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
+                       {
+#ifdef VERBOSE_RESIDUAL_PRINTF
+                               printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
+#endif
+                               break;
+                       }
+               }
+       }
+}
+
+btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       if (!m_useBatching)
+       {
+               return btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+       }
+       BT_PROFILE("solveSingleIterationMt");
+       btScalar leastSquaresResidual = 0.f;
+
+       if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
+       {
+               if (1)  // uncomment this for a bit less random ((iteration & 7) == 0)
+               {
+                       randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations);
+               }
+       }
+
+       {
+               ///solve all joint constraints
+               leastSquaresResidual += resolveAllJointConstraints(iteration);
+
+               if (iteration < infoGlobal.m_numIterations)
+               {
+                       // this loop is only used for cone-twist constraints,
+                       // it would be nice to skip this loop if none of the constraints need it
+                       if (m_useObsoleteJointConstraints)
+                       {
+                               for (int j = 0; j < numConstraints; j++)
+                               {
+                                       if (constraints[j]->isEnabled())
+                                       {
+                                               int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
+                                               int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
+                                               btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
+                                               btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
+                                               constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
+                                       }
+                               }
+                       }
+
+                       if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
+                       {
+                               // solve all contact, contact-friction, and rolling friction constraints interleaved
+                               leastSquaresResidual += resolveAllContactConstraintsInterleaved();
+                       }
+                       else  //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
+                       {
+                               // don't interleave them
+                               // solve all contact constraints
+                               leastSquaresResidual += resolveAllContactConstraints();
+
+                               // solve all contact friction constraints
+                               leastSquaresResidual += resolveAllContactFrictionConstraints();
+
+                               // solve all rolling friction constraints
+                               leastSquaresResidual += resolveAllRollingFrictionConstraints();
+                       }
+               }
+       }
+       return leastSquaresResidual;
+}
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration)
+{
+       btScalar leastSquaresResidual = 0.f;
+       for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
+       {
+               int iCons = consIndices[iiCons];
+               const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[iCons];
+               if (iteration < constraint.m_overrideNumSolverIterations)
+               {
+                       btSolverBody& bodyA = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
+                       btSolverBody& bodyB = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
+                       btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, constraint);
+                       leastSquaresResidual += residual * residual;
+               }
+       }
+       return leastSquaresResidual;
+}
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
+{
+       btScalar leastSquaresResidual = 0.f;
+       for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
+       {
+               int iCons = consIndices[iiCons];
+               const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons];
+               btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
+               btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
+               btScalar residual = resolveSingleConstraintRowLowerLimit(bodyA, bodyB, solveManifold);
+               leastSquaresResidual += residual * residual;
+       }
+       return leastSquaresResidual;
+}
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
+{
+       btScalar leastSquaresResidual = 0.f;
+       for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
+       {
+               int iContact = consIndices[iiCons];
+               btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse;
+
+               // apply sliding friction
+               if (totalImpulse > 0.0f)
+               {
+                       int iBegin = iContact * m_numFrictionDirections;
+                       int iEnd = iBegin + m_numFrictionDirections;
+                       for (int iFriction = iBegin; iFriction < iEnd; ++iFriction)
+                       {
+                               btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction++];
+                               btAssert(solveManifold.m_frictionIndex == iContact);
+
+                               solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                               solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+                               btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
+                               btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
+                               btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold);
+                               leastSquaresResidual += residual * residual;
+                       }
+               }
+       }
+       return leastSquaresResidual;
+}
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
+{
+       btScalar leastSquaresResidual = 0.f;
+       for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
+       {
+               int iContact = consIndices[iiCons];
+               int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact];
+               if (iFirstRollingFriction >= 0)
+               {
+                       btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse;
+                       // apply rolling friction
+                       if (totalImpulse > 0.0f)
+                       {
+                               int iBegin = iFirstRollingFriction;
+                               int iEnd = iBegin + 3;
+                               for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric)
+                               {
+                                       btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
+                                       if (rollingFrictionConstraint.m_frictionIndex != iContact)
+                                       {
+                                               break;
+                                       }
+                                       btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+                                       if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+                                       {
+                                               rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+                                       }
+
+                                       rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+                                       rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+                                       btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+                                       leastSquaresResidual += residual * residual;
+                               }
+                       }
+               }
+       }
+       return leastSquaresResidual;
+}
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices,
+                                                                                                                                                                                        int batchBegin,
+                                                                                                                                                                                        int batchEnd)
+{
+       btScalar leastSquaresResidual = 0.f;
+       int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+
+       for (int iiCons = batchBegin; iiCons < batchEnd; iiCons++)
+       {
+               btScalar totalImpulse = 0;
+               int iContact = contactIndices[iiCons];
+               // apply penetration constraint
+               {
+                       const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iContact];
+                       btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                       leastSquaresResidual += residual * residual;
+                       totalImpulse = solveManifold.m_appliedImpulse;
+               }
+
+               // apply sliding friction
+               if (totalImpulse > 0.0f)
+               {
+                       int iBegin = iContact * m_numFrictionDirections;
+                       int iEnd = iBegin + m_numFrictionDirections;
+                       for (int iFriction = iBegin; iFriction < iEnd; ++iFriction)
+                       {
+                               btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction];
+                               btAssert(solveManifold.m_frictionIndex == iContact);
+
+                               solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
+                               solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
+
+                               btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
+                               btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
+                               btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold);
+                               leastSquaresResidual += residual * residual;
+                       }
+               }
+
+               // apply rolling friction
+               int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact];
+               if (totalImpulse > 0.0f && iFirstRollingFriction >= 0)
+               {
+                       int iBegin = iFirstRollingFriction;
+                       int iEnd = iBegin + 3;
+                       for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric)
+                       {
+                               btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
+                               if (rollingFrictionConstraint.m_frictionIndex != iContact)
+                               {
+                                       break;
+                               }
+                               btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+                               if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+                               {
+                                       rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+                               }
+
+                               rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+                               rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+                               btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+                               leastSquaresResidual += residual * residual;
+                       }
+               }
+       }
+       return leastSquaresResidual;
+}
+
+void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering(btBatchedConstraints* batchedConstraints)
+{
+       btBatchedConstraints& bc = *batchedConstraints;
+       // randomize ordering of phases
+       for (int ii = 1; ii < bc.m_phaseOrder.size(); ++ii)
+       {
+               int iSwap = btRandInt2(ii + 1);
+               bc.m_phaseOrder.swap(ii, iSwap);
+       }
+
+       // for each batch,
+       for (int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch)
+       {
+               // randomize ordering of constraints within the batch
+               const btBatchedConstraints::Range& batch = bc.m_batches[iBatch];
+               for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons)
+               {
+                       int iSwap = batch.begin + btRandInt2(iiCons - batch.begin + 1);
+                       btAssert(iSwap >= batch.begin && iSwap < batch.end);
+                       bc.m_constraintIndices.swap(iiCons, iSwap);
+               }
+       }
+}
+
+void btSequentialImpulseConstraintSolverMt::randomizeConstraintOrdering(int iteration, int numIterations)
+{
+       // randomize ordering of joint constraints
+       randomizeBatchedConstraintOrdering(&m_batchedJointConstraints);
+
+       //contact/friction constraints are not solved more than numIterations
+       if (iteration < numIterations)
+       {
+               randomizeBatchedConstraintOrdering(&m_batchedContactConstraints);
+       }
+}
+
+struct JointSolverLoop : public btIParallelSumBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btBatchedConstraints* m_bc;
+       int m_iteration;
+
+       JointSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration)
+       {
+               m_solver = solver;
+               m_bc = bc;
+               m_iteration = iteration;
+       }
+       btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               BT_PROFILE("JointSolverLoop");
+               btScalar sum = 0;
+               for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+               {
+                       const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+                       sum += m_solver->resolveMultipleJointConstraints(m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration);
+               }
+               return sum;
+       }
+};
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveAllJointConstraints(int iteration)
+{
+       BT_PROFILE("resolveAllJointConstraints");
+       const btBatchedConstraints& batchedCons = m_batchedJointConstraints;
+       JointSolverLoop loop(this, &batchedCons, iteration);
+       btScalar leastSquaresResidual = 0.f;
+       for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+       {
+               int iPhase = batchedCons.m_phaseOrder[iiPhase];
+               const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+               int grainSize = 1;
+               leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+       }
+       return leastSquaresResidual;
+}
+
+struct ContactSolverLoop : public btIParallelSumBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btBatchedConstraints* m_bc;
+
+       ContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
+       {
+               m_solver = solver;
+               m_bc = bc;
+       }
+       btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               BT_PROFILE("ContactSolverLoop");
+               btScalar sum = 0;
+               for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+               {
+                       const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+                       sum += m_solver->resolveMultipleContactConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
+               }
+               return sum;
+       }
+};
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraints()
+{
+       BT_PROFILE("resolveAllContactConstraints");
+       const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+       ContactSolverLoop loop(this, &batchedCons);
+       btScalar leastSquaresResidual = 0.f;
+       for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+       {
+               int iPhase = batchedCons.m_phaseOrder[iiPhase];
+               const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+               int grainSize = batchedCons.m_phaseGrainSize[iPhase];
+               leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+       }
+       return leastSquaresResidual;
+}
+
+struct ContactFrictionSolverLoop : public btIParallelSumBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btBatchedConstraints* m_bc;
+
+       ContactFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
+       {
+               m_solver = solver;
+               m_bc = bc;
+       }
+       btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               BT_PROFILE("ContactFrictionSolverLoop");
+               btScalar sum = 0;
+               for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+               {
+                       const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+                       sum += m_solver->resolveMultipleContactFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
+               }
+               return sum;
+       }
+};
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactFrictionConstraints()
+{
+       BT_PROFILE("resolveAllContactFrictionConstraints");
+       const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+       ContactFrictionSolverLoop loop(this, &batchedCons);
+       btScalar leastSquaresResidual = 0.f;
+       for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+       {
+               int iPhase = batchedCons.m_phaseOrder[iiPhase];
+               const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+               int grainSize = batchedCons.m_phaseGrainSize[iPhase];
+               leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+       }
+       return leastSquaresResidual;
+}
+
+struct InterleavedContactSolverLoop : public btIParallelSumBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btBatchedConstraints* m_bc;
+
+       InterleavedContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
+       {
+               m_solver = solver;
+               m_bc = bc;
+       }
+       btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               BT_PROFILE("InterleavedContactSolverLoop");
+               btScalar sum = 0;
+               for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+               {
+                       const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+                       sum += m_solver->resolveMultipleContactConstraintsInterleaved(m_bc->m_constraintIndices, batch.begin, batch.end);
+               }
+               return sum;
+       }
+};
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraintsInterleaved()
+{
+       BT_PROFILE("resolveAllContactConstraintsInterleaved");
+       const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+       InterleavedContactSolverLoop loop(this, &batchedCons);
+       btScalar leastSquaresResidual = 0.f;
+       for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+       {
+               int iPhase = batchedCons.m_phaseOrder[iiPhase];
+               const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+               int grainSize = 1;
+               leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+       }
+       return leastSquaresResidual;
+}
+
+struct ContactRollingFrictionSolverLoop : public btIParallelSumBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btBatchedConstraints* m_bc;
+
+       ContactRollingFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
+       {
+               m_solver = solver;
+               m_bc = bc;
+       }
+       btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               BT_PROFILE("ContactFrictionSolverLoop");
+               btScalar sum = 0;
+               for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
+               {
+                       const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
+                       sum += m_solver->resolveMultipleContactRollingFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
+               }
+               return sum;
+       }
+};
+
+btScalar btSequentialImpulseConstraintSolverMt::resolveAllRollingFrictionConstraints()
+{
+       BT_PROFILE("resolveAllRollingFrictionConstraints");
+       btScalar leastSquaresResidual = 0.f;
+       //
+       // We do not generate batches for rolling friction constraints. We assume that
+       // one of two cases is true:
+       //
+       //  1. either most bodies in the simulation have rolling friction, in which case we can use the
+       //     batches for contacts and use a lookup table to translate contact indices to rolling friction
+       //     (ignoring any contact indices that don't map to a rolling friction constraint). As long as
+       //     most contacts have a corresponding rolling friction constraint, this should parallelize well.
+       //
+       //  -OR-
+       //
+       //  2. few bodies in the simulation have rolling friction, so it is not worth trying to use the
+       //     batches from contacts as most of the contacts won't have corresponding rolling friction
+       //     constraints and most threads would end up doing very little work. Most of the time would
+       //     go to threading overhead, so we don't bother with threading.
+       //
+       int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+       if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size())
+       {
+               // use batching if there are many rolling friction constraints
+               const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
+               ContactRollingFrictionSolverLoop loop(this, &batchedCons);
+               btScalar leastSquaresResidual = 0.f;
+               for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
+               {
+                       int iPhase = batchedCons.m_phaseOrder[iiPhase];
+                       const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
+                       int grainSize = 1;
+                       leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
+               }
+       }
+       else
+       {
+               // no batching, also ignores SOLVER_RANDMIZE_ORDER
+               for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
+               {
+                       btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+                       if (rollingFrictionConstraint.m_frictionIndex >= 0)
+                       {
+                               btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+                               if (totalImpulse > 0.0f)
+                               {
+                                       btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
+                                       if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
+                                               rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+                                       rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+                                       rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+                                       btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
+                                       leastSquaresResidual += residual * residual;
+                               }
+                       }
+               }
+       }
+       return leastSquaresResidual;
+}
+
+void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("internalWriteBackContacts");
+       writeBackContacts(iBegin, iEnd, infoGlobal);
+       //for ( int iContact = iBegin; iContact < iEnd; ++iContact)
+       //{
+       //    const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ];
+       //    btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint;
+       //    btAssert( pt );
+       //    pt->m_appliedImpulse = contactConstraint.m_appliedImpulse;
+       //    pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse;
+       //    if ( m_numFrictionDirections == 2 )
+       //    {
+       //        pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse;
+       //    }
+       //}
+}
+
+void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("internalWriteBackJoints");
+       writeBackJoints(iBegin, iEnd, infoGlobal);
+}
+
+void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("internalWriteBackBodies");
+       writeBackBodies(iBegin, iEnd, infoGlobal);
+}
+
+struct WriteContactPointsLoop : public btIParallelForBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btContactSolverInfo* m_infoGlobal;
+
+       WriteContactPointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
+       {
+               m_solver = solver;
+               m_infoGlobal = &infoGlobal;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               m_solver->internalWriteBackContacts(iBegin, iEnd, *m_infoGlobal);
+       }
+};
+
+struct WriteJointsLoop : public btIParallelForBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btContactSolverInfo* m_infoGlobal;
+
+       WriteJointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
+       {
+               m_solver = solver;
+               m_infoGlobal = &infoGlobal;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               m_solver->internalWriteBackJoints(iBegin, iEnd, *m_infoGlobal);
+       }
+};
+
+struct WriteBodiesLoop : public btIParallelForBody
+{
+       btSequentialImpulseConstraintSolverMt* m_solver;
+       const btContactSolverInfo* m_infoGlobal;
+
+       WriteBodiesLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
+       {
+               m_solver = solver;
+               m_infoGlobal = &infoGlobal;
+       }
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               m_solver->internalWriteBackBodies(iBegin, iEnd, *m_infoGlobal);
+       }
+};
+
+btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("solveGroupCacheFriendlyFinish");
+
+       if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+       {
+               WriteContactPointsLoop loop(this, infoGlobal);
+               int grainSize = 500;
+               btParallelFor(0, m_tmpSolverContactConstraintPool.size(), grainSize, loop);
+       }
+
+       {
+               WriteJointsLoop loop(this, infoGlobal);
+               int grainSize = 400;
+               btParallelFor(0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop);
+       }
+       {
+               WriteBodiesLoop loop(this, infoGlobal);
+               int grainSize = 100;
+               btParallelFor(0, m_tmpSolverBodyPool.size(), grainSize, loop);
+       }
+
+       m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+       m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
+
+       m_tmpSolverBodyPool.resizeNoInitialize(0);
+       return 0.f;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h
new file mode 100644 (file)
index 0000000..73a9915
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_MT_H
+#define BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_MT_H
+
+#include "btSequentialImpulseConstraintSolver.h"
+#include "btBatchedConstraints.h"
+#include "LinearMath/btThreads.h"
+
+///
+/// btSequentialImpulseConstraintSolverMt
+///
+///  A multithreaded variant of the sequential impulse constraint solver. The constraints to be solved are grouped into
+///  batches and phases where each batch of constraints within a given phase can be solved in parallel with the rest.
+///  Ideally we want as few phases as possible, and each phase should have many batches, and all of the batches should
+///  have about the same number of constraints.
+///  This method works best on a large island of many constraints.
+///
+///  Supports all of the features of the normal sequential impulse solver such as:
+///    - split penetration impulse
+///    - rolling friction
+///    - interleaving constraints
+///    - warmstarting
+///    - 2 friction directions
+///    - randomized constraint ordering
+///    - early termination when leastSquaresResidualThreshold is satisfied
+///
+///  When the SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS flag is enabled, unlike the normal SequentialImpulse solver,
+///  the rolling friction is interleaved as well.
+///  Interleaving the contact penetration constraints with friction reduces the number of parallel loops that need to be done,
+///  which reduces threading overhead so it can be a performance win, however, it does seem to produce a less stable simulation,
+///  at least on stacks of blocks.
+///
+///  When the SOLVER_RANDMIZE_ORDER flag is enabled, the ordering of phases, and the ordering of constraints within each batch
+///  is randomized, however it does not swap constraints between batches.
+///  This is to avoid regenerating the batches for each solver iteration which would be quite costly in performance.
+///
+///  Note that a non-zero leastSquaresResidualThreshold could possibly affect the determinism of the simulation
+///  if the task scheduler's parallelSum operation is non-deterministic. The parallelSum operation can be non-deterministic
+///  because floating point addition is not associative due to rounding errors.
+///  The task scheduler can and should ensure that the result of any parallelSum operation is deterministic.
+///
+ATTRIBUTE_ALIGNED16(class)
+btSequentialImpulseConstraintSolverMt : public btSequentialImpulseConstraintSolver
+{
+public:
+       virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE;
+       virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE;
+       virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE;
+       virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
+
+       // temp struct used to collect info from persistent manifolds into a cache-friendly struct using multiple threads
+       struct btContactManifoldCachedInfo
+       {
+               static const int MAX_NUM_CONTACT_POINTS = 4;
+
+               int numTouchingContacts;
+               int solverBodyIds[2];
+               int contactIndex;
+               int rollingFrictionIndex;
+               bool contactHasRollingFriction[MAX_NUM_CONTACT_POINTS];
+               btManifoldPoint* contactPoints[MAX_NUM_CONTACT_POINTS];
+       };
+       // temp struct used for setting up joint constraints in parallel
+       struct JointParams
+       {
+               int m_solverConstraint;
+               int m_solverBodyA;
+               int m_solverBodyB;
+       };
+       void internalInitMultipleJoints(btTypedConstraint * *constraints, int iBegin, int iEnd);
+       void internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+
+       // parameters to control batching
+       static bool s_allowNestedParallelForLoops;        // whether to allow nested parallel operations
+       static int s_minimumContactManifoldsForBatching;  // don't even try to batch if fewer manifolds than this
+       static btBatchedConstraints::BatchingMethod s_contactBatchingMethod;
+       static btBatchedConstraints::BatchingMethod s_jointBatchingMethod;
+       static int s_minBatchSize;  // desired number of constraints per batch
+       static int s_maxBatchSize;
+
+protected:
+       static const int CACHE_LINE_SIZE = 64;
+
+       btBatchedConstraints m_batchedContactConstraints;
+       btBatchedConstraints m_batchedJointConstraints;
+       int m_numFrictionDirections;
+       bool m_useBatching;
+       bool m_useObsoleteJointConstraints;
+       btAlignedObjectArray<btContactManifoldCachedInfo> m_manifoldCachedInfoArray;
+       btAlignedObjectArray<int> m_rollingFrictionIndexTable;  // lookup table mapping contact index to rolling friction index
+       btSpinMutex m_bodySolverArrayMutex;
+       char m_antiFalseSharingPadding[CACHE_LINE_SIZE];  // padding to keep mutexes in separate cachelines
+       btSpinMutex m_kinematicBodyUniqueIdToSolverBodyTableMutex;
+       btAlignedObjectArray<char> m_scratchMemory;
+
+       virtual void randomizeConstraintOrdering(int iteration, int numIterations);
+       virtual btScalar resolveAllJointConstraints(int iteration);
+       virtual btScalar resolveAllContactConstraints();
+       virtual btScalar resolveAllContactFrictionConstraints();
+       virtual btScalar resolveAllContactConstraintsInterleaved();
+       virtual btScalar resolveAllRollingFrictionConstraints();
+
+       virtual void setupBatchedContactConstraints();
+       virtual void setupBatchedJointConstraints();
+       virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
+       virtual void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
+       virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
+
+       int getOrInitSolverBodyThreadsafe(btCollisionObject & body, btScalar timeStep);
+       void allocAllContactConstraints(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
+       void setupAllContactConstraints(const btContactSolverInfo& infoGlobal);
+       void randomizeBatchedConstraintOrdering(btBatchedConstraints * batchedConstraints);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btSequentialImpulseConstraintSolverMt();
+       virtual ~btSequentialImpulseConstraintSolverMt();
+
+       btScalar resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration);
+       btScalar resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
+       btScalar resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
+       btScalar resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
+       btScalar resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
+       btScalar resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices, int batchBegin, int batchEnd);
+
+       void internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo * cachedInfoArray, btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
+       void internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds);
+       void internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal);
+       void internalConvertBodies(btCollisionObject * *bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+       void internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+       void internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+       void internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
+};
+
+#endif  //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_MT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
new file mode 100755 (executable)
index 0000000..e42223c
--- /dev/null
@@ -0,0 +1,823 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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>
+
+#define USE_OFFSET_FOR_CONSTANT_FRAME true
+
+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_cfmDirLin = SLIDER_CONSTRAINT_DEF_CFM;
+       m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+       m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+       m_dampingDirAng = btScalar(0.);
+       m_cfmDirAng = SLIDER_CONSTRAINT_DEF_CFM;
+       m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+       m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+       m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING;
+       m_cfmOrthoLin = SLIDER_CONSTRAINT_DEF_CFM;
+       m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+       m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+       m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING;
+       m_cfmOrthoAng = SLIDER_CONSTRAINT_DEF_CFM;
+       m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+       m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+       m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING;
+       m_cfmLimLin = SLIDER_CONSTRAINT_DEF_CFM;
+       m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+       m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+       m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING;
+       m_cfmLimAng = SLIDER_CONSTRAINT_DEF_CFM;
+
+       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);
+
+       m_flags = 0;
+       m_flags = 0;
+
+       m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME;
+
+       calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+}
+
+btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
+       : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB),
+         m_useSolveConstraintObsolete(false),
+         m_frameInA(frameInA),
+         m_frameInB(frameInB),
+         m_useLinearReferenceFrameA(useLinearReferenceFrameA)
+{
+       initParams();
+}
+
+btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA)
+       : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB),
+         m_useSolveConstraintObsolete(false),
+         m_frameInB(frameInB),
+         m_useLinearReferenceFrameA(useLinearReferenceFrameA)
+{
+       ///not providing rigidbody A means implicitly using worldspace for body A
+       m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
+       //      m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin());
+
+       initParams();
+}
+
+void btSliderConstraint::getInfo1(btConstraintInfo1* info)
+{
+       if (m_useSolveConstraintObsolete)
+       {
+               info->m_numConstraintRows = 0;
+               info->nub = 0;
+       }
+       else
+       {
+               info->m_numConstraintRows = 4;  // Fixed 2 linear + 2 angular
+               info->nub = 2;
+               //prepare constraint
+               calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+               testAngLimits();
+               testLinLimits();
+               if (getSolveLinLimit() || getPoweredLinMotor())
+               {
+                       info->m_numConstraintRows++;  // limit 3rd linear as well
+                       info->nub--;
+               }
+               if (getSolveAngLimit() || getPoweredAngMotor())
+               {
+                       info->m_numConstraintRows++;  // limit 3rd angular as well
+                       info->nub--;
+               }
+       }
+}
+
+void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
+{
+       info->m_numConstraintRows = 6;  // Fixed 2 linear + 2 angular + 1 limit (even if not used)
+       info->nub = 0;
+}
+
+void btSliderConstraint::getInfo2(btConstraintInfo2* info)
+{
+       getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(), m_rbB.getLinearVelocity(), m_rbA.getInvMass(), m_rbB.getInvMass());
+}
+
+void btSliderConstraint::calculateTransforms(const btTransform& transA, const btTransform& transB)
+{
+       if (m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete))
+       {
+               m_calculatedTransformA = transA * m_frameInA;
+               m_calculatedTransformB = transB * m_frameInB;
+       }
+       else
+       {
+               m_calculatedTransformA = transB * m_frameInB;
+               m_calculatedTransformB = transA * m_frameInA;
+       }
+       m_realPivotAInW = m_calculatedTransformA.getOrigin();
+       m_realPivotBInW = m_calculatedTransformB.getOrigin();
+       m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0);  // along X
+       if (m_useLinearReferenceFrameA || m_useSolveConstraintObsolete)
+       {
+               m_delta = m_realPivotBInW - m_realPivotAInW;
+       }
+       else
+       {
+               m_delta = m_realPivotAInW - m_realPivotBInW;
+       }
+       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);
+       }
+}
+
+void btSliderConstraint::testLinLimits(void)
+{
+       m_solveLinLim = false;
+       m_linPos = m_depth[0];
+       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.);
+       }
+}
+
+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));
+               btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0));
+               rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit);
+               m_angPos = rot;
+               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;
+               }
+       }
+}
+
+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;
+}
+
+btVector3 btSliderConstraint::getAncorInB(void)
+{
+       btVector3 ancorInB;
+       ancorInB = m_frameInB.getOrigin();
+       return ancorInB;
+}
+
+void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, btScalar rbAinvMass, btScalar rbBinvMass)
+{
+       const btTransform& trA = getCalculatedTransformA();
+       const btTransform& trB = getCalculatedTransformB();
+
+       btAssert(!m_useSolveConstraintObsolete);
+       int i, s = info->rowskip;
+
+       btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f);
+
+       // difference between frames in WCS
+       btVector3 ofs = trB.getOrigin() - trA.getOrigin();
+       // now get weight factors depending on masses
+       btScalar miA = rbAinvMass;
+       btScalar miB = rbBinvMass;
+       bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+       btScalar miS = miA + miB;
+       btScalar factA, factB;
+       if (miS > btScalar(0.f))
+       {
+               factA = miB / miS;
+       }
+       else
+       {
+               factA = btScalar(0.5f);
+       }
+       factB = btScalar(1.0f) - factA;
+       btVector3 ax1, p, q;
+       btVector3 ax1A = trA.getBasis().getColumn(0);
+       btVector3 ax1B = trB.getBasis().getColumn(0);
+       if (m_useOffsetForConstraintFrame)
+       {
+               // get the desired direction of slider axis
+               // as weighted sum of X-orthos of frameA and frameB in WCS
+               ax1 = ax1A * factA + ax1B * factB;
+               ax1.normalize();
+               // construct two orthos to slider axis
+               btPlaneSpace1(ax1, p, q);
+       }
+       else
+       {  // old way - use frameA
+               ax1 = trA.getBasis().getColumn(0);
+               // get 2 orthos to slider axis (Y, Z)
+               p = trA.getBasis().getColumn(1);
+               q = trA.getBasis().getColumn(2);
+       }
+       // make rotations around these orthos equal
+       // the slider axis should be the only unconstrained
+       // rotational axis, the angular velocity of the two bodies perpendicular to
+       // the slider axis should be equal. thus the constraint equations are
+       //    p*w1 - p*w2 = 0
+       //    q*w1 - q*w2 = 0
+       // where p and q are unit vectors normal to the slider axis, and w1 and w2
+       // are the angular velocity vectors of the two bodies.
+       info->m_J1angularAxis[0] = p[0];
+       info->m_J1angularAxis[1] = p[1];
+       info->m_J1angularAxis[2] = p[2];
+       info->m_J1angularAxis[s + 0] = q[0];
+       info->m_J1angularAxis[s + 1] = q[1];
+       info->m_J1angularAxis[s + 2] = q[2];
+
+       info->m_J2angularAxis[0] = -p[0];
+       info->m_J2angularAxis[1] = -p[1];
+       info->m_J2angularAxis[2] = -p[2];
+       info->m_J2angularAxis[s + 0] = -q[0];
+       info->m_J2angularAxis[s + 1] = -q[1];
+       info->m_J2angularAxis[s + 2] = -q[2];
+       // compute the right hand side of the constraint equation. set relative
+       // body velocities along p and q to bring the slider back into alignment.
+       // if ax1A,ax1B are the unit length slider axes as computed from bodyA and
+       // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
+       // if "theta" is the angle between ax1 and ax2, we need an angular velocity
+       // along u to cover angle erp*theta in one step :
+       //   |angular_velocity| = angle/time = erp*theta / stepsize
+       //                      = (erp*fps) * theta
+       //    angular_velocity  = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+       //                      = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+       // ...as ax1 and ax2 are unit length. if theta is smallish,
+       // theta ~= sin(theta), so
+       //    angular_velocity  = (erp*fps) * (ax1 x ax2)
+       // ax1 x ax2 is in the plane space of ax1, so we project the angular
+       // velocity to p and q to find the right hand side.
+       //      btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
+       btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp;
+       btScalar k = info->fps * currERP;
+
+       btVector3 u = ax1A.cross(ax1B);
+       info->m_constraintError[0] = k * u.dot(p);
+       info->m_constraintError[s] = k * u.dot(q);
+       if (m_flags & BT_SLIDER_FLAGS_CFM_ORTANG)
+       {
+               info->cfm[0] = m_cfmOrthoAng;
+               info->cfm[s] = m_cfmOrthoAng;
+       }
+
+       int nrow = 1;  // last filled row
+       int srow;
+       btScalar limit_err;
+       int limit;
+
+       // next two rows.
+       // we want: velA + wA x relA == velB + wB x relB ... but this would
+       // result in three equations, so we project along two orthos to the slider axis
+
+       btTransform bodyA_trans = transA;
+       btTransform bodyB_trans = transB;
+       nrow++;
+       int s2 = nrow * s;
+       nrow++;
+       int s3 = nrow * s;
+       btVector3 tmpA(0, 0, 0), tmpB(0, 0, 0), relA(0, 0, 0), relB(0, 0, 0), c(0, 0, 0);
+       if (m_useOffsetForConstraintFrame)
+       {
+               // get vector from bodyB to frameB in WCS
+               relB = trB.getOrigin() - bodyB_trans.getOrigin();
+               // get its projection to slider axis
+               btVector3 projB = ax1 * relB.dot(ax1);
+               // get vector directed from bodyB to slider axis (and orthogonal to it)
+               btVector3 orthoB = relB - projB;
+               // same for bodyA
+               relA = trA.getOrigin() - bodyA_trans.getOrigin();
+               btVector3 projA = ax1 * relA.dot(ax1);
+               btVector3 orthoA = relA - projA;
+               // get desired offset between frames A and B along slider axis
+               btScalar sliderOffs = m_linPos - m_depth[0];
+               // desired vector from projection of center of bodyA to projection of center of bodyB to slider axis
+               btVector3 totalDist = projA + ax1 * sliderOffs - projB;
+               // get offset vectors relA and relB
+               relA = orthoA + totalDist * factA;
+               relB = orthoB - totalDist * factB;
+               // now choose average ortho to slider axis
+               p = orthoB * factA + orthoA * factB;
+               btScalar len2 = p.length2();
+               if (len2 > SIMD_EPSILON)
+               {
+                       p /= btSqrt(len2);
+               }
+               else
+               {
+                       p = trA.getBasis().getColumn(1);
+               }
+               // make one more ortho
+               q = ax1.cross(p);
+               // fill two rows
+               tmpA = relA.cross(p);
+               tmpB = relB.cross(p);
+               for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = tmpA[i];
+               for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = -tmpB[i];
+               tmpA = relA.cross(q);
+               tmpB = relB.cross(q);
+               if (hasStaticBody && getSolveAngLimit())
+               {  // to make constraint between static and dynamic objects more rigid
+                       // remove wA (or wB) from equation if angular limit is hit
+                       tmpB *= factB;
+                       tmpA *= factA;
+               }
+               for (i = 0; i < 3; i++) info->m_J1angularAxis[s3 + i] = tmpA[i];
+               for (i = 0; i < 3; i++) info->m_J2angularAxis[s3 + i] = -tmpB[i];
+               for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = p[i];
+               for (i = 0; i < 3; i++) info->m_J1linearAxis[s3 + i] = q[i];
+               for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -p[i];
+               for (i = 0; i < 3; i++) info->m_J2linearAxis[s3 + i] = -q[i];
+       }
+       else
+       {  // old way - maybe incorrect if bodies are not on the slider axis
+               // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0
+               c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
+               btVector3 tmp = c.cross(p);
+               for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = factA * tmp[i];
+               for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = factB * tmp[i];
+               tmp = c.cross(q);
+               for (i = 0; i < 3; i++) info->m_J1angularAxis[s3 + i] = factA * tmp[i];
+               for (i = 0; i < 3; i++) info->m_J2angularAxis[s3 + i] = factB * tmp[i];
+
+               for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = p[i];
+               for (i = 0; i < 3; i++) info->m_J1linearAxis[s3 + i] = q[i];
+               for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -p[i];
+               for (i = 0; i < 3; i++) info->m_J2linearAxis[s3 + i] = -q[i];
+       }
+       // compute two elements of right hand side
+
+       //      k = info->fps * info->erp * getSoftnessOrthoLin();
+       currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN) ? m_softnessOrthoLin : m_softnessOrthoLin * info->erp;
+       k = info->fps * currERP;
+
+       btScalar rhs = k * p.dot(ofs);
+       info->m_constraintError[s2] = rhs;
+       rhs = k * q.dot(ofs);
+       info->m_constraintError[s3] = rhs;
+       if (m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN)
+       {
+               info->cfm[s2] = m_cfmOrthoLin;
+               info->cfm[s3] = m_cfmOrthoLin;
+       }
+
+       // check linear limits
+       limit_err = btScalar(0.0);
+       limit = 0;
+       if (getSolveLinLimit())
+       {
+               limit_err = getLinDepth() * signFact;
+               limit = (limit_err > btScalar(0.0)) ? 2 : 1;
+       }
+       bool powered = getPoweredLinMotor();
+       // if the slider has joint limits or motor, add in the extra row
+       if (limit || powered)
+       {
+               nrow++;
+               srow = nrow * info->rowskip;
+               info->m_J1linearAxis[srow + 0] = ax1[0];
+               info->m_J1linearAxis[srow + 1] = ax1[1];
+               info->m_J1linearAxis[srow + 2] = ax1[2];
+               info->m_J2linearAxis[srow + 0] = -ax1[0];
+               info->m_J2linearAxis[srow + 1] = -ax1[1];
+               info->m_J2linearAxis[srow + 2] = -ax1[2];
+               // linear torque decoupling step:
+               //
+               // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies
+               // do not create a torque couple. in other words, the points that the
+               // constraint force is applied at must lie along the same ax1 axis.
+               // a torque couple will result in limited slider-jointed free
+               // bodies from gaining angular momentum.
+               if (m_useOffsetForConstraintFrame)
+               {
+                       // this is needed only when bodyA and bodyB are both dynamic.
+                       if (!hasStaticBody)
+                       {
+                               tmpA = relA.cross(ax1);
+                               tmpB = relB.cross(ax1);
+                               info->m_J1angularAxis[srow + 0] = tmpA[0];
+                               info->m_J1angularAxis[srow + 1] = tmpA[1];
+                               info->m_J1angularAxis[srow + 2] = tmpA[2];
+                               info->m_J2angularAxis[srow + 0] = -tmpB[0];
+                               info->m_J2angularAxis[srow + 1] = -tmpB[1];
+                               info->m_J2angularAxis[srow + 2] = -tmpB[2];
+                       }
+               }
+               else
+               {                   // The old way. May be incorrect if bodies are not on the slider axis
+                       btVector3 ltd;  // Linear Torque Decoupling vector (a torque)
+                       ltd = c.cross(ax1);
+                       info->m_J1angularAxis[srow + 0] = factA * ltd[0];
+                       info->m_J1angularAxis[srow + 1] = factA * ltd[1];
+                       info->m_J1angularAxis[srow + 2] = factA * ltd[2];
+                       info->m_J2angularAxis[srow + 0] = factB * ltd[0];
+                       info->m_J2angularAxis[srow + 1] = factB * ltd[1];
+                       info->m_J2angularAxis[srow + 2] = factB * ltd[2];
+               }
+               // right-hand part
+               btScalar lostop = getLowerLinLimit();
+               btScalar histop = getUpperLinLimit();
+               if (limit && (lostop == histop))
+               {  // the joint motor is ineffective
+                       powered = false;
+               }
+               info->m_constraintError[srow] = 0.;
+               info->m_lowerLimit[srow] = 0.;
+               info->m_upperLimit[srow] = 0.;
+               currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp;
+               if (powered)
+               {
+                       if (m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN)
+                       {
+                               info->cfm[srow] = m_cfmDirLin;
+                       }
+                       btScalar tag_vel = getTargetLinMotorVelocity();
+                       btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP);
+                       info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity();
+                       info->m_lowerLimit[srow] += -getMaxLinMotorForce() / info->fps;
+                       info->m_upperLimit[srow] += getMaxLinMotorForce() / info->fps;
+               }
+               if (limit)
+               {
+                       k = info->fps * currERP;
+                       info->m_constraintError[srow] += k * limit_err;
+                       if (m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN)
+                       {
+                               info->cfm[srow] = m_cfmLimLin;
+                       }
+                       if (lostop == histop)
+                       {  // limited low and high simultaneously
+                               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                               info->m_upperLimit[srow] = SIMD_INFINITY;
+                       }
+                       else if (limit == 1)
+                       {  // low limit
+                               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                               info->m_upperLimit[srow] = 0;
+                       }
+                       else
+                       {  // high limit
+                               info->m_lowerLimit[srow] = 0;
+                               info->m_upperLimit[srow] = SIMD_INFINITY;
+                       }
+                       // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that)
+                       btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin());
+                       if (bounce > btScalar(0.0))
+                       {
+                               btScalar vel = linVelA.dot(ax1);
+                               vel -= linVelB.dot(ax1);
+                               vel *= signFact;
+                               // only apply bounce if the velocity is incoming, and if the
+                               // resulting c[] exceeds what we already have.
+                               if (limit == 1)
+                               {  // low limit
+                                       if (vel < 0)
+                                       {
+                                               btScalar newc = -bounce * vel;
+                                               if (newc > info->m_constraintError[srow])
+                                               {
+                                                       info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                               }
+                               else
+                               {  // high limit - all those computations are reversed
+                                       if (vel > 0)
+                                       {
+                                               btScalar newc = -bounce * vel;
+                                               if (newc < info->m_constraintError[srow])
+                                               {
+                                                       info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                               }
+                       }
+                       info->m_constraintError[srow] *= getSoftnessLimLin();
+               }  // if(limit)
+       }      // if linear limit
+       // check angular limits
+       limit_err = btScalar(0.0);
+       limit = 0;
+       if (getSolveAngLimit())
+       {
+               limit_err = getAngDepth();
+               limit = (limit_err > btScalar(0.0)) ? 1 : 2;
+       }
+       // if the slider has joint limits, add in the extra row
+       powered = getPoweredAngMotor();
+       if (limit || powered)
+       {
+               nrow++;
+               srow = nrow * info->rowskip;
+               info->m_J1angularAxis[srow + 0] = ax1[0];
+               info->m_J1angularAxis[srow + 1] = ax1[1];
+               info->m_J1angularAxis[srow + 2] = ax1[2];
+
+               info->m_J2angularAxis[srow + 0] = -ax1[0];
+               info->m_J2angularAxis[srow + 1] = -ax1[1];
+               info->m_J2angularAxis[srow + 2] = -ax1[2];
+
+               btScalar lostop = getLowerAngLimit();
+               btScalar histop = getUpperAngLimit();
+               if (limit && (lostop == histop))
+               {  // the joint motor is ineffective
+                       powered = false;
+               }
+               currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp;
+               if (powered)
+               {
+                       if (m_flags & BT_SLIDER_FLAGS_CFM_DIRANG)
+                       {
+                               info->cfm[srow] = m_cfmDirAng;
+                       }
+                       btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * currERP);
+                       info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity();
+                       info->m_lowerLimit[srow] = -getMaxAngMotorForce() / info->fps;
+                       info->m_upperLimit[srow] = getMaxAngMotorForce() / info->fps;
+               }
+               if (limit)
+               {
+                       k = info->fps * currERP;
+                       info->m_constraintError[srow] += k * limit_err;
+                       if (m_flags & BT_SLIDER_FLAGS_CFM_LIMANG)
+                       {
+                               info->cfm[srow] = m_cfmLimAng;
+                       }
+                       if (lostop == histop)
+                       {
+                               // limited low and high simultaneously
+                               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                               info->m_upperLimit[srow] = SIMD_INFINITY;
+                       }
+                       else if (limit == 1)
+                       {  // low limit
+                               info->m_lowerLimit[srow] = 0;
+                               info->m_upperLimit[srow] = SIMD_INFINITY;
+                       }
+                       else
+                       {  // high limit
+                               info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                               info->m_upperLimit[srow] = 0;
+                       }
+                       // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
+                       btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng());
+                       if (bounce > btScalar(0.0))
+                       {
+                               btScalar vel = m_rbA.getAngularVelocity().dot(ax1);
+                               vel -= m_rbB.getAngularVelocity().dot(ax1);
+                               // only apply bounce if the velocity is incoming, and if the
+                               // resulting c[] exceeds what we already have.
+                               if (limit == 1)
+                               {  // low limit
+                                       if (vel < 0)
+                                       {
+                                               btScalar newc = -bounce * vel;
+                                               if (newc > info->m_constraintError[srow])
+                                               {
+                                                       info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                               }
+                               else
+                               {  // high limit - all those computations are reversed
+                                       if (vel > 0)
+                                       {
+                                               btScalar newc = -bounce * vel;
+                                               if (newc < info->m_constraintError[srow])
+                                               {
+                                                       info->m_constraintError[srow] = newc;
+                                               }
+                                       }
+                               }
+                       }
+                       info->m_constraintError[srow] *= getSoftnessLimAng();
+               }  // if(limit)
+       }      // if angular limit or powered
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+///If no axis is provided, it uses the default axis for this constraint.
+void btSliderConstraint::setParam(int num, btScalar value, int axis)
+{
+       switch (num)
+       {
+               case BT_CONSTRAINT_STOP_ERP:
+                       if (axis < 1)
+                       {
+                               m_softnessLimLin = value;
+                               m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN;
+                       }
+                       else if (axis < 3)
+                       {
+                               m_softnessOrthoLin = value;
+                               m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN;
+                       }
+                       else if (axis == 3)
+                       {
+                               m_softnessLimAng = value;
+                               m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG;
+                       }
+                       else if (axis < 6)
+                       {
+                               m_softnessOrthoAng = value;
+                               m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG;
+                       }
+                       else
+                       {
+                               btAssertConstrParams(0);
+                       }
+                       break;
+               case BT_CONSTRAINT_CFM:
+                       if (axis < 1)
+                       {
+                               m_cfmDirLin = value;
+                               m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN;
+                       }
+                       else if (axis == 3)
+                       {
+                               m_cfmDirAng = value;
+                               m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG;
+                       }
+                       else
+                       {
+                               btAssertConstrParams(0);
+                       }
+                       break;
+               case BT_CONSTRAINT_STOP_CFM:
+                       if (axis < 1)
+                       {
+                               m_cfmLimLin = value;
+                               m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN;
+                       }
+                       else if (axis < 3)
+                       {
+                               m_cfmOrthoLin = value;
+                               m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN;
+                       }
+                       else if (axis == 3)
+                       {
+                               m_cfmLimAng = value;
+                               m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG;
+                       }
+                       else if (axis < 6)
+                       {
+                               m_cfmOrthoAng = value;
+                               m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG;
+                       }
+                       else
+                       {
+                               btAssertConstrParams(0);
+                       }
+                       break;
+       }
+}
+
+///return the local value of parameter
+btScalar btSliderConstraint::getParam(int num, int axis) const
+{
+       btScalar retVal(SIMD_INFINITY);
+       switch (num)
+       {
+               case BT_CONSTRAINT_STOP_ERP:
+                       if (axis < 1)
+                       {
+                               btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN);
+                               retVal = m_softnessLimLin;
+                       }
+                       else if (axis < 3)
+                       {
+                               btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN);
+                               retVal = m_softnessOrthoLin;
+                       }
+                       else if (axis == 3)
+                       {
+                               btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG);
+                               retVal = m_softnessLimAng;
+                       }
+                       else if (axis < 6)
+                       {
+                               btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG);
+                               retVal = m_softnessOrthoAng;
+                       }
+                       else
+                       {
+                               btAssertConstrParams(0);
+                       }
+                       break;
+               case BT_CONSTRAINT_CFM:
+                       if (axis < 1)
+                       {
+                               btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN);
+                               retVal = m_cfmDirLin;
+                       }
+                       else if (axis == 3)
+                       {
+                               btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG);
+                               retVal = m_cfmDirAng;
+                       }
+                       else
+                       {
+                               btAssertConstrParams(0);
+                       }
+                       break;
+               case BT_CONSTRAINT_STOP_CFM:
+                       if (axis < 1)
+                       {
+                               btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN);
+                               retVal = m_cfmLimLin;
+                       }
+                       else if (axis < 3)
+                       {
+                               btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN);
+                               retVal = m_cfmOrthoLin;
+                       }
+                       else if (axis == 3)
+                       {
+                               btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG);
+                               retVal = m_cfmLimAng;
+                       }
+                       else if (axis < 6)
+                       {
+                               btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG);
+                               retVal = m_cfmOrthoAng;
+                       }
+                       else
+                       {
+                               btAssertConstrParams(0);
+                       }
+                       break;
+       }
+       return retVal;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
new file mode 100755 (executable)
index 0000000..75b1857
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 BT_SLIDER_CONSTRAINT_H
+#define BT_SLIDER_CONSTRAINT_H
+
+#include "LinearMath/btScalar.h"  //for BT_USE_DOUBLE_PRECISION
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btSliderConstraintData2 btSliderConstraintDoubleData
+#define btSliderConstraintDataName "btSliderConstraintDoubleData"
+#else
+#define btSliderConstraintData2 btSliderConstraintData
+#define btSliderConstraintDataName "btSliderConstraintData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+#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))
+#define SLIDER_CONSTRAINT_DEF_CFM (btScalar(0.f))
+
+enum btSliderFlags
+{
+       BT_SLIDER_FLAGS_CFM_DIRLIN = (1 << 0),
+       BT_SLIDER_FLAGS_ERP_DIRLIN = (1 << 1),
+       BT_SLIDER_FLAGS_CFM_DIRANG = (1 << 2),
+       BT_SLIDER_FLAGS_ERP_DIRANG = (1 << 3),
+       BT_SLIDER_FLAGS_CFM_ORTLIN = (1 << 4),
+       BT_SLIDER_FLAGS_ERP_ORTLIN = (1 << 5),
+       BT_SLIDER_FLAGS_CFM_ORTANG = (1 << 6),
+       BT_SLIDER_FLAGS_ERP_ORTANG = (1 << 7),
+       BT_SLIDER_FLAGS_CFM_LIMLIN = (1 << 8),
+       BT_SLIDER_FLAGS_ERP_LIMLIN = (1 << 9),
+       BT_SLIDER_FLAGS_CFM_LIMANG = (1 << 10),
+       BT_SLIDER_FLAGS_ERP_LIMANG = (1 << 11)
+};
+
+ATTRIBUTE_ALIGNED16(class)
+btSliderConstraint : public btTypedConstraint
+{
+protected:
+       ///for backwards compatibility during the transition to 'getInfo/getInfo2'
+       bool m_useSolveConstraintObsolete;
+       bool m_useOffsetForConstraintFrame;
+       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_cfmDirLin;
+
+       btScalar m_softnessDirAng;
+       btScalar m_restitutionDirAng;
+       btScalar m_dampingDirAng;
+       btScalar m_cfmDirAng;
+
+       btScalar m_softnessLimLin;
+       btScalar m_restitutionLimLin;
+       btScalar m_dampingLimLin;
+       btScalar m_cfmLimLin;
+
+       btScalar m_softnessLimAng;
+       btScalar m_restitutionLimAng;
+       btScalar m_dampingLimAng;
+       btScalar m_cfmLimAng;
+
+       btScalar m_softnessOrthoLin;
+       btScalar m_restitutionOrthoLin;
+       btScalar m_dampingOrthoLin;
+       btScalar m_cfmOrthoLin;
+
+       btScalar m_softnessOrthoAng;
+       btScalar m_restitutionOrthoAng;
+       btScalar m_dampingOrthoAng;
+       btScalar m_cfmOrthoAng;
+
+       // for interlal use
+       bool m_solveLinLim;
+       bool m_solveAngLim;
+
+       int m_flags;
+
+       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_linPos;
+       btScalar m_angPos;
+
+       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:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       // constructors
+       btSliderConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA);
+       btSliderConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameA);
+
+       // overrides
+
+       virtual void getInfo1(btConstraintInfo1 * info);
+
+       void getInfo1NonVirtual(btConstraintInfo1 * info);
+
+       virtual void getInfo2(btConstraintInfo2 * info);
+
+       void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, btScalar rbAinvMass, btScalar rbBinvMass);
+
+       // 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 = btNormalizeAngle(lowerLimit); }
+       btScalar getUpperAngLimit() { return m_upperAngLimit; }
+       void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = btNormalizeAngle(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; }
+
+       btScalar getLinearPos() const { return m_linPos; }
+       btScalar getAngularPos() const { return m_angPos; }
+
+       // 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; }
+       // shared code used by ODE solver
+       void calculateTransforms(const btTransform& transA, const btTransform& transB);
+       void testLinLimits();
+       void testAngLimits();
+       // access for PE Solver
+       btVector3 getAncorInA();
+       btVector3 getAncorInB();
+       // access for UseFrameOffset
+       bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
+       void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+
+       void setFrames(const btTransform& frameA, const btTransform& frameB)
+       {
+               m_frameInA = frameA;
+               m_frameInB = frameB;
+               calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
+               buildJacobian();
+       }
+
+       ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+       ///If no axis is provided, it uses the default axis for this constraint.
+       virtual void setParam(int num, btScalar value, int axis = -1);
+       ///return the local value of parameter
+       virtual btScalar getParam(int num, int axis = -1) const;
+
+       virtual int getFlags() const
+       {
+               return m_flags;
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+
+struct btSliderConstraintData
+{
+       btTypedConstraintData m_typeConstraintData;
+       btTransformFloatData m_rbAFrame;  // constraint axii. Assumes z is hinge axis.
+       btTransformFloatData m_rbBFrame;
+
+       float m_linearUpperLimit;
+       float m_linearLowerLimit;
+
+       float m_angularUpperLimit;
+       float m_angularLowerLimit;
+
+       int m_useLinearReferenceFrameA;
+       int m_useOffsetForConstraintFrame;
+};
+
+struct btSliderConstraintDoubleData
+{
+       btTypedConstraintDoubleData m_typeConstraintData;
+       btTransformDoubleData m_rbAFrame;  // constraint axii. Assumes z is hinge axis.
+       btTransformDoubleData m_rbBFrame;
+
+       double m_linearUpperLimit;
+       double m_linearLowerLimit;
+
+       double m_angularUpperLimit;
+       double m_angularLowerLimit;
+
+       int m_useLinearReferenceFrameA;
+       int m_useOffsetForConstraintFrame;
+};
+
+SIMD_FORCE_INLINE int btSliderConstraint::calculateSerializeBufferSize() const
+{
+       return sizeof(btSliderConstraintData2);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btSliderConstraintData2* sliderData = (btSliderConstraintData2*)dataBuffer;
+       btTypedConstraint::serialize(&sliderData->m_typeConstraintData, serializer);
+
+       m_frameInA.serialize(sliderData->m_rbAFrame);
+       m_frameInB.serialize(sliderData->m_rbBFrame);
+
+       sliderData->m_linearUpperLimit = m_upperLinLimit;
+       sliderData->m_linearLowerLimit = m_lowerLinLimit;
+
+       sliderData->m_angularUpperLimit = m_upperAngLimit;
+       sliderData->m_angularLowerLimit = m_lowerAngLimit;
+
+       sliderData->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA;
+       sliderData->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame;
+
+       return btSliderConstraintDataName;
+}
+
+#endif  //BT_SLIDER_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
new file mode 100644 (file)
index 0000000..5c2060c
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSolve2LinearConstraint.h"
+
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+
+void btSolve2LinearConstraint::resolveUnilateralPairConstraint(
+       btRigidBody* body1,
+       btRigidBody* body2,
+
+       const btMatrix3x3& world2A,
+       const btMatrix3x3& world2B,
+
+       const btVector3& invInertiaADiag,
+       const btScalar invMassA,
+       const btVector3& linvelA, const btVector3& angvelA,
+       const btVector3& rel_posA1,
+       const btVector3& invInertiaBDiag,
+       const btScalar invMassB,
+       const btVector3& linvelB, const btVector3& angvelB,
+       const btVector3& rel_posA2,
+
+       btScalar depthA, const btVector3& normalA,
+       const btVector3& rel_posB1, const btVector3& rel_posB2,
+       btScalar depthB, const btVector3& normalB,
+       btScalar& imp0, btScalar& imp1)
+{
+       (void)linvelA;
+       (void)linvelB;
+       (void)angvelB;
+       (void)angvelA;
+
+       imp0 = btScalar(0.);
+       imp1 = btScalar(0.);
+
+       btScalar len = btFabs(normalA.length()) - btScalar(1.);
+       if (btFabs(len) >= SIMD_EPSILON)
+               return;
+
+       btAssert(len < SIMD_EPSILON);
+
+       //this jacobian entry could be re-used for all iterations
+       btJacobianEntry jacA(world2A, world2B, rel_posA1, rel_posA2, normalA, invInertiaADiag, invMassA,
+                                                invInertiaBDiag, invMassB);
+       btJacobianEntry jacB(world2A, world2B, rel_posB1, rel_posB2, normalB, invInertiaADiag, invMassA,
+                                                invInertiaBDiag, invMassB);
+
+       //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+       //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+
+       const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1) - body2->getVelocityInLocalPoint(rel_posA1));
+       const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1) - body2->getVelocityInLocalPoint(rel_posB1));
+
+       //      btScalar penetrationImpulse = (depth*contactTau*timeCorrection)  * massTerm;//jacDiagABInv
+       btScalar massTerm = btScalar(1.) / (invMassA + invMassB);
+
+       // calculate rhs (or error) terms
+       const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping;
+       const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping;
+
+       // dC/dv * dv = -C
+
+       // jacobian * impulse = -error
+       //
+
+       //impulse = jacobianInverse * -error
+
+       // inverting 2x2 symmetric system (offdiagonal are equal!)
+       //
+
+       btScalar nonDiag = jacA.getNonDiagonal(jacB, invMassA, invMassB);
+       btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag);
+
+       //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+       //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+
+       imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+       imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * -nonDiag * invDet;
+
+       //[a b]                                                           [d -c]
+       //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
+
+       //[jA nD] * [imp0] = [dv0]
+       //[nD jB]   [imp1]   [dv1]
+}
+
+void btSolve2LinearConstraint::resolveBilateralPairConstraint(
+       btRigidBody* body1,
+       btRigidBody* body2,
+       const btMatrix3x3& world2A,
+       const btMatrix3x3& world2B,
+
+       const btVector3& invInertiaADiag,
+       const btScalar invMassA,
+       const btVector3& linvelA, const btVector3& angvelA,
+       const btVector3& rel_posA1,
+       const btVector3& invInertiaBDiag,
+       const btScalar invMassB,
+       const btVector3& linvelB, const btVector3& angvelB,
+       const btVector3& rel_posA2,
+
+       btScalar depthA, const btVector3& normalA,
+       const btVector3& rel_posB1, const btVector3& rel_posB2,
+       btScalar depthB, const btVector3& normalB,
+       btScalar& imp0, btScalar& imp1)
+{
+       (void)linvelA;
+       (void)linvelB;
+       (void)angvelA;
+       (void)angvelB;
+
+       imp0 = btScalar(0.);
+       imp1 = btScalar(0.);
+
+       btScalar len = btFabs(normalA.length()) - btScalar(1.);
+       if (btFabs(len) >= SIMD_EPSILON)
+               return;
+
+       btAssert(len < SIMD_EPSILON);
+
+       //this jacobian entry could be re-used for all iterations
+       btJacobianEntry jacA(world2A, world2B, rel_posA1, rel_posA2, normalA, invInertiaADiag, invMassA,
+                                                invInertiaBDiag, invMassB);
+       btJacobianEntry jacB(world2A, world2B, rel_posB1, rel_posB2, normalB, invInertiaADiag, invMassA,
+                                                invInertiaBDiag, invMassB);
+
+       //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+       //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+
+       const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1) - body2->getVelocityInLocalPoint(rel_posA1));
+       const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1) - body2->getVelocityInLocalPoint(rel_posB1));
+
+       // calculate rhs (or error) terms
+       const btScalar dv0 = depthA * m_tau - vel0 * m_damping;
+       const btScalar dv1 = depthB * m_tau - vel1 * m_damping;
+
+       // dC/dv * dv = -C
+
+       // jacobian * impulse = -error
+       //
+
+       //impulse = jacobianInverse * -error
+
+       // inverting 2x2 symmetric system (offdiagonal are equal!)
+       //
+
+       btScalar nonDiag = jacA.getNonDiagonal(jacB, invMassA, invMassB);
+       btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag);
+
+       //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+       //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+
+       imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+       imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * -nonDiag * invDet;
+
+       //[a b]                                                           [d -c]
+       //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
+
+       //[jA nD] * [imp0] = [dv0]
+       //[nD jB]   [imp1]   [dv1]
+
+       if (imp0 > btScalar(0.0))
+       {
+               if (imp1 > btScalar(0.0))
+               {
+                       //both positive
+               }
+               else
+               {
+                       imp1 = btScalar(0.);
+
+                       // now imp0>0 imp1<0
+                       imp0 = dv0 / jacA.getDiagonal();
+                       if (imp0 > btScalar(0.0))
+                       {
+                       }
+                       else
+                       {
+                               imp0 = btScalar(0.);
+                       }
+               }
+       }
+       else
+       {
+               imp0 = btScalar(0.);
+
+               imp1 = dv1 / jacB.getDiagonal();
+               if (imp1 <= btScalar(0.0))
+               {
+                       imp1 = btScalar(0.);
+                       // now imp0>0 imp1<0
+                       imp0 = dv0 / jacA.getDiagonal();
+                       if (imp0 > btScalar(0.0))
+                       {
+                       }
+                       else
+                       {
+                               imp0 = btScalar(0.);
+                       }
+               }
+               else
+               {
+               }
+       }
+}
+
+/*
+void btSolve2LinearConstraint::resolveAngularConstraint(       const btMatrix3x3& invInertiaAWS,
+                                                                                       const btScalar invMassA,
+                                                                                       const btVector3& linvelA,const btVector3& angvelA,
+                                                                                       const btVector3& rel_posA1,
+                                                                                       const btMatrix3x3& invInertiaBWS,
+                                                                                       const btScalar invMassB,
+                                                                                       const btVector3& linvelB,const btVector3& angvelB,
+                                                                                       const btVector3& rel_posA2,
+
+                                                                                       btScalar depthA, const btVector3& normalA, 
+                                                                                       const btVector3& rel_posB1,const btVector3& rel_posB2,
+                                                                                       btScalar depthB, const btVector3& normalB, 
+                                                                                       btScalar& imp0,btScalar& imp1)
+{
+
+}
+*/
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h
new file mode 100644 (file)
index 0000000..0a8c901
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SOLVE_2LINEAR_CONSTRAINT_H
+#define BT_SOLVE_2LINEAR_CONSTRAINT_H
+
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btVector3.h"
+
+class btRigidBody;
+
+/// constraint class used for lateral tyre friction.
+class btSolve2LinearConstraint
+{
+       btScalar m_tau;
+       btScalar m_damping;
+
+public:
+       btSolve2LinearConstraint(btScalar tau, btScalar damping)
+       {
+               m_tau = tau;
+               m_damping = damping;
+       }
+       //
+       // solve unilateral constraint (equality, direct method)
+       //
+       void resolveUnilateralPairConstraint(
+               btRigidBody* body0,
+               btRigidBody* body1,
+
+               const btMatrix3x3& world2A,
+               const btMatrix3x3& world2B,
+
+               const btVector3& invInertiaADiag,
+               const btScalar invMassA,
+               const btVector3& linvelA, const btVector3& angvelA,
+               const btVector3& rel_posA1,
+               const btVector3& invInertiaBDiag,
+               const btScalar invMassB,
+               const btVector3& linvelB, const btVector3& angvelB,
+               const btVector3& rel_posA2,
+
+               btScalar depthA, const btVector3& normalA,
+               const btVector3& rel_posB1, const btVector3& rel_posB2,
+               btScalar depthB, const btVector3& normalB,
+               btScalar& imp0, btScalar& imp1);
+
+       //
+       // solving 2x2 lcp problem (inequality, direct solution )
+       //
+       void resolveBilateralPairConstraint(
+               btRigidBody* body0,
+               btRigidBody* body1,
+               const btMatrix3x3& world2A,
+               const btMatrix3x3& world2B,
+
+               const btVector3& invInertiaADiag,
+               const btScalar invMassA,
+               const btVector3& linvelA, const btVector3& angvelA,
+               const btVector3& rel_posA1,
+               const btVector3& invInertiaBDiag,
+               const btScalar invMassB,
+               const btVector3& linvelB, const btVector3& angvelB,
+               const btVector3& rel_posA2,
+
+               btScalar depthA, const btVector3& normalA,
+               const btVector3& rel_posB1, const btVector3& rel_posB2,
+               btScalar depthB, const btVector3& normalB,
+               btScalar& imp0, btScalar& imp1);
+
+       /*
+       void resolveAngularConstraint(  const btMatrix3x3& invInertiaAWS,
+                                               const btScalar invMassA,
+                                               const btVector3& linvelA,const btVector3& angvelA,
+                                               const btVector3& rel_posA1,
+                                               const btMatrix3x3& invInertiaBWS,
+                                               const btScalar invMassB,
+                                               const btVector3& linvelB,const btVector3& angvelB,
+                                               const btVector3& rel_posA2,
+
+                                         btScalar depthA, const btVector3& normalA, 
+                                         const btVector3& rel_posB1,const btVector3& rel_posB2,
+                                         btScalar depthB, const btVector3& normalB, 
+                                         btScalar& imp0,btScalar& imp1);
+
+*/
+};
+
+#endif  //BT_SOLVE_2LINEAR_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolverBody.h
new file mode 100644 (file)
index 0000000..8d2f108
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOLVER_BODY_H
+#define BT_SOLVER_BODY_H
+
+class btRigidBody;
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btTransformUtil.h"
+
+///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
+#ifdef BT_USE_SSE
+#define USE_SIMD 1
+#endif  //
+
+#ifdef USE_SIMD
+
+struct btSimdScalar
+{
+       SIMD_FORCE_INLINE btSimdScalar()
+       {
+       }
+
+       SIMD_FORCE_INLINE btSimdScalar(float fl)
+               : m_vec128(_mm_set1_ps(fl))
+       {
+       }
+
+       SIMD_FORCE_INLINE btSimdScalar(__m128 v128)
+               : m_vec128(v128)
+       {
+       }
+       union {
+               __m128 m_vec128;
+               float m_floats[4];
+               int m_ints[4];
+               btScalar m_unusedPadding;
+       };
+       SIMD_FORCE_INLINE __m128 get128()
+       {
+               return m_vec128;
+       }
+
+       SIMD_FORCE_INLINE const __m128 get128() const
+       {
+               return m_vec128;
+       }
+
+       SIMD_FORCE_INLINE void set128(__m128 v128)
+       {
+               m_vec128 = v128;
+       }
+
+       SIMD_FORCE_INLINE operator __m128()
+       {
+               return m_vec128;
+       }
+       SIMD_FORCE_INLINE operator const __m128() const
+       {
+               return m_vec128;
+       }
+
+       SIMD_FORCE_INLINE operator float() const
+       {
+               return m_floats[0];
+       }
+};
+
+///@brief Return the elementwise product of two btSimdScalar
+SIMD_FORCE_INLINE btSimdScalar
+operator*(const btSimdScalar& v1, const btSimdScalar& v2)
+{
+       return btSimdScalar(_mm_mul_ps(v1.get128(), v2.get128()));
+}
+
+///@brief Return the elementwise product of two btSimdScalar
+SIMD_FORCE_INLINE btSimdScalar
+operator+(const btSimdScalar& v1, const btSimdScalar& v2)
+{
+       return btSimdScalar(_mm_add_ps(v1.get128(), v2.get128()));
+}
+
+#else
+#define btSimdScalar btScalar
+#endif
+
+///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
+ATTRIBUTE_ALIGNED16(struct)
+btSolverBody
+{
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+       btTransform m_worldTransform;
+       btVector3 m_deltaLinearVelocity;
+       btVector3 m_deltaAngularVelocity;
+       btVector3 m_angularFactor;
+       btVector3 m_linearFactor;
+       btVector3 m_invMass;
+       btVector3 m_pushVelocity;
+       btVector3 m_turnVelocity;
+       btVector3 m_linearVelocity;
+       btVector3 m_angularVelocity;
+       btVector3 m_externalForceImpulse;
+       btVector3 m_externalTorqueImpulse;
+
+       btRigidBody* m_originalBody;
+       void setWorldTransform(const btTransform& worldTransform)
+       {
+               m_worldTransform = worldTransform;
+       }
+
+       const btTransform& getWorldTransform() const
+       {
+               return m_worldTransform;
+       }
+
+       SIMD_FORCE_INLINE void getVelocityInLocalPointNoDelta(const btVector3& rel_pos, btVector3& velocity) const
+       {
+               if (m_originalBody)
+                       velocity = m_linearVelocity + m_externalForceImpulse + (m_angularVelocity + m_externalTorqueImpulse).cross(rel_pos);
+               else
+                       velocity.setValue(0, 0, 0);
+       }
+
+       SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity) const
+       {
+               if (m_originalBody)
+                       velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
+               else
+                       velocity.setValue(0, 0, 0);
+       }
+
+       SIMD_FORCE_INLINE void getAngularVelocity(btVector3 & angVel) const
+       {
+               if (m_originalBody)
+                       angVel = m_angularVelocity + m_deltaAngularVelocity;
+               else
+                       angVel.setValue(0, 0, 0);
+       }
+
+       //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+       SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent, const btScalar impulseMagnitude)
+       {
+               if (m_originalBody)
+               {
+                       m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+                       m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
+               }
+       }
+
+       SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent, btScalar impulseMagnitude)
+       {
+               if (m_originalBody)
+               {
+                       m_pushVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+                       m_turnVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
+               }
+       }
+
+       const btVector3& getDeltaLinearVelocity() const
+       {
+               return m_deltaLinearVelocity;
+       }
+
+       const btVector3& getDeltaAngularVelocity() const
+       {
+               return m_deltaAngularVelocity;
+       }
+
+       const btVector3& getPushVelocity() const
+       {
+               return m_pushVelocity;
+       }
+
+       const btVector3& getTurnVelocity() const
+       {
+               return m_turnVelocity;
+       }
+
+       ////////////////////////////////////////////////
+       ///some internal methods, don't use them
+
+       btVector3& internalGetDeltaLinearVelocity()
+       {
+               return m_deltaLinearVelocity;
+       }
+
+       btVector3& internalGetDeltaAngularVelocity()
+       {
+               return m_deltaAngularVelocity;
+       }
+
+       const btVector3& internalGetAngularFactor() const
+       {
+               return m_angularFactor;
+       }
+
+       const btVector3& internalGetInvMass() const
+       {
+               return m_invMass;
+       }
+
+       void internalSetInvMass(const btVector3& invMass)
+       {
+               m_invMass = invMass;
+       }
+
+       btVector3& internalGetPushVelocity()
+       {
+               return m_pushVelocity;
+       }
+
+       btVector3& internalGetTurnVelocity()
+       {
+               return m_turnVelocity;
+       }
+
+       SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity) const
+       {
+               velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
+       }
+
+       SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3 & angVel) const
+       {
+               angVel = m_angularVelocity + m_deltaAngularVelocity;
+       }
+
+       //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+       SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent, const btScalar impulseMagnitude)
+       {
+               if (m_originalBody)
+               {
+                       m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
+                       m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
+               }
+       }
+
+       void writebackVelocity()
+       {
+               if (m_originalBody)
+               {
+                       m_linearVelocity += m_deltaLinearVelocity;
+                       m_angularVelocity += m_deltaAngularVelocity;
+
+                       //m_originalBody->setCompanionId(-1);
+               }
+       }
+
+       void writebackVelocityAndTransform(btScalar timeStep, btScalar splitImpulseTurnErp)
+       {
+               (void)timeStep;
+               if (m_originalBody)
+               {
+                       m_linearVelocity += m_deltaLinearVelocity;
+                       m_angularVelocity += m_deltaAngularVelocity;
+
+                       //correct the position/orientation based on push/turn recovery
+                       btTransform newTransform;
+                       if (m_pushVelocity[0] != 0.f || m_pushVelocity[1] != 0 || m_pushVelocity[2] != 0 || m_turnVelocity[0] != 0.f || m_turnVelocity[1] != 0 || m_turnVelocity[2] != 0)
+                       {
+                               //      btQuaternion orn = m_worldTransform.getRotation();
+                               btTransformUtil::integrateTransform(m_worldTransform, m_pushVelocity, m_turnVelocity * splitImpulseTurnErp, timeStep, newTransform);
+                               m_worldTransform = newTransform;
+                       }
+                       //m_worldTransform.setRotation(orn);
+                       //m_originalBody->setCompanionId(-1);
+               }
+       }
+};
+
+#endif  //BT_SOLVER_BODY_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h
new file mode 100644 (file)
index 0000000..9749b33
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOLVER_CONSTRAINT_H
+#define BT_SOLVER_CONSTRAINT_H
+
+class btRigidBody;
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btJacobianEntry.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+//#define NO_FRICTION_TANGENTIALS 1
+#include "btSolverBody.h"
+
+///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_contactNormal1;
+
+       btVector3 m_relpos2CrossNormal;
+       btVector3 m_contactNormal2;  //usually m_contactNormal2 == -m_contactNormal1, but not always
+
+       btVector3 m_angularComponentA;
+       btVector3 m_angularComponentB;
+
+       mutable btSimdScalar m_appliedPushImpulse;
+       mutable btSimdScalar m_appliedImpulse;
+
+       btScalar m_friction;
+       btScalar m_jacDiagABInv;
+       btScalar m_rhs;
+       btScalar m_cfm;
+
+       btScalar m_lowerLimit;
+       btScalar m_upperLimit;
+       btScalar m_rhsPenetration;
+       union {
+               void* m_originalContactPoint;
+               btScalar m_unusedPadding4;
+               int m_numRowsForNonContactConstraint;
+       };
+
+       int m_overrideNumSolverIterations;
+       int m_frictionIndex;
+       int m_solverBodyIdA;
+       int m_solverBodyIdB;
+
+       enum btSolverConstraintType
+       {
+               BT_SOLVER_CONTACT_1D = 0,
+               BT_SOLVER_FRICTION_1D
+       };
+};
+
+typedef btAlignedObjectArray<btSolverConstraint> btConstraintArray;
+
+#endif  //BT_SOLVER_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
new file mode 100644 (file)
index 0000000..9530911
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTypedConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btSerializer.h"
+
+#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.05f)
+
+btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA)
+       : btTypedObject(type),
+         m_userConstraintType(-1),
+         m_userConstraintPtr((void*)-1),
+         m_breakingImpulseThreshold(SIMD_INFINITY),
+         m_isEnabled(true),
+         m_needsFeedback(false),
+         m_overrideNumSolverIterations(-1),
+         m_rbA(rbA),
+         m_rbB(getFixedBody()),
+         m_appliedImpulse(btScalar(0.)),
+         m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
+         m_jointFeedback(0)
+{
+}
+
+btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA, btRigidBody& rbB)
+       : btTypedObject(type),
+         m_userConstraintType(-1),
+         m_userConstraintPtr((void*)-1),
+         m_breakingImpulseThreshold(SIMD_INFINITY),
+         m_isEnabled(true),
+         m_needsFeedback(false),
+         m_overrideNumSolverIterations(-1),
+         m_rbA(rbA),
+         m_rbB(rbB),
+         m_appliedImpulse(btScalar(0.)),
+         m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
+         m_jointFeedback(0)
+{
+}
+
+btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact)
+{
+       if (lowLim > uppLim)
+       {
+               return btScalar(1.0f);
+       }
+       else if (lowLim == uppLim)
+       {
+               return btScalar(0.0f);
+       }
+       btScalar lim_fact = btScalar(1.0f);
+       btScalar delta_max = vel / timeFact;
+       if (delta_max < btScalar(0.0f))
+       {
+               if ((pos >= lowLim) && (pos < (lowLim - delta_max)))
+               {
+                       lim_fact = (lowLim - pos) / delta_max;
+               }
+               else if (pos < lowLim)
+               {
+                       lim_fact = btScalar(0.0f);
+               }
+               else
+               {
+                       lim_fact = btScalar(1.0f);
+               }
+       }
+       else if (delta_max > btScalar(0.0f))
+       {
+               if ((pos <= uppLim) && (pos > (uppLim - delta_max)))
+               {
+                       lim_fact = (uppLim - pos) / delta_max;
+               }
+               else if (pos > uppLim)
+               {
+                       lim_fact = btScalar(0.0f);
+               }
+               else
+               {
+                       lim_fact = btScalar(1.0f);
+               }
+       }
+       else
+       {
+               lim_fact = btScalar(0.0f);
+       }
+       return lim_fact;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+       btTypedConstraintData2* tcd = (btTypedConstraintData2*)dataBuffer;
+
+       tcd->m_rbA = (btRigidBodyData*)serializer->getUniquePointer(&m_rbA);
+       tcd->m_rbB = (btRigidBodyData*)serializer->getUniquePointer(&m_rbB);
+       char* name = (char*)serializer->findNameForPointer(this);
+       tcd->m_name = (char*)serializer->getUniquePointer(name);
+       if (tcd->m_name)
+       {
+               serializer->serializeName(name);
+       }
+
+       tcd->m_objectType = m_objectType;
+       tcd->m_needsFeedback = m_needsFeedback;
+       tcd->m_overrideNumSolverIterations = m_overrideNumSolverIterations;
+       tcd->m_breakingImpulseThreshold = m_breakingImpulseThreshold;
+       tcd->m_isEnabled = m_isEnabled ? 1 : 0;
+
+       tcd->m_userConstraintId = m_userConstraintId;
+       tcd->m_userConstraintType = m_userConstraintType;
+
+       tcd->m_appliedImpulse = m_appliedImpulse;
+       tcd->m_dbgDrawSize = m_dbgDrawSize;
+
+       tcd->m_disableCollisionsBetweenLinkedBodies = false;
+
+       int i;
+       for (i = 0; i < m_rbA.getNumConstraintRefs(); i++)
+               if (m_rbA.getConstraintRef(i) == this)
+                       tcd->m_disableCollisionsBetweenLinkedBodies = true;
+       for (i = 0; i < m_rbB.getNumConstraintRefs(); i++)
+               if (m_rbB.getConstraintRef(i) == this)
+                       tcd->m_disableCollisionsBetweenLinkedBodies = true;
+
+       return btTypedConstraintDataName;
+}
+
+btRigidBody& btTypedConstraint::getFixedBody()
+{
+       static btRigidBody s_fixed(0, 0, 0);
+       s_fixed.setMassProps(btScalar(0.), btVector3(btScalar(0.), btScalar(0.), btScalar(0.)));
+       return s_fixed;
+}
+
+void btAngularLimit::set(btScalar low, btScalar high, btScalar _softness, btScalar _biasFactor, btScalar _relaxationFactor)
+{
+       m_halfRange = (high - low) / 2.0f;
+       m_center = btNormalizeAngle(low + m_halfRange);
+       m_softness = _softness;
+       m_biasFactor = _biasFactor;
+       m_relaxationFactor = _relaxationFactor;
+}
+
+void btAngularLimit::test(const btScalar angle)
+{
+       m_correction = 0.0f;
+       m_sign = 0.0f;
+       m_solveLimit = false;
+
+       if (m_halfRange >= 0.0f)
+       {
+               btScalar deviation = btNormalizeAngle(angle - m_center);
+               if (deviation < -m_halfRange)
+               {
+                       m_solveLimit = true;
+                       m_correction = -(deviation + m_halfRange);
+                       m_sign = +1.0f;
+               }
+               else if (deviation > m_halfRange)
+               {
+                       m_solveLimit = true;
+                       m_correction = m_halfRange - deviation;
+                       m_sign = -1.0f;
+               }
+       }
+}
+
+btScalar btAngularLimit::getError() const
+{
+       return m_correction * m_sign;
+}
+
+void btAngularLimit::fit(btScalar& angle) const
+{
+       if (m_halfRange > 0.0f)
+       {
+               btScalar relativeAngle = btNormalizeAngle(angle - m_center);
+               if (!btEqual(relativeAngle, m_halfRange))
+               {
+                       if (relativeAngle > 0.0f)
+                       {
+                               angle = getHigh();
+                       }
+                       else
+                       {
+                               angle = getLow();
+                       }
+               }
+       }
+}
+
+btScalar btAngularLimit::getLow() const
+{
+       return btNormalizeAngle(m_center - m_halfRange);
+}
+
+btScalar btAngularLimit::getHigh() const
+{
+       return btNormalizeAngle(m_center + m_halfRange);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h
new file mode 100644 (file)
index 0000000..3d6b08d
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2010 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_TYPED_CONSTRAINT_H
+#define BT_TYPED_CONSTRAINT_H
+
+#include "LinearMath/btScalar.h"
+#include "btSolverConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btTypedConstraintData2 btTypedConstraintDoubleData
+#define btTypedConstraintDataName "btTypedConstraintDoubleData"
+#else
+#define btTypedConstraintData2 btTypedConstraintFloatData
+#define btTypedConstraintDataName "btTypedConstraintFloatData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+class btSerializer;
+
+//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
+enum btTypedConstraintType
+{
+       POINT2POINT_CONSTRAINT_TYPE = 3,
+       HINGE_CONSTRAINT_TYPE,
+       CONETWIST_CONSTRAINT_TYPE,
+       D6_CONSTRAINT_TYPE,
+       SLIDER_CONSTRAINT_TYPE,
+       CONTACT_CONSTRAINT_TYPE,
+       D6_SPRING_CONSTRAINT_TYPE,
+       GEAR_CONSTRAINT_TYPE,
+       FIXED_CONSTRAINT_TYPE,
+       D6_SPRING_2_CONSTRAINT_TYPE,
+       MAX_CONSTRAINT_TYPE
+};
+
+enum btConstraintParams
+{
+       BT_CONSTRAINT_ERP = 1,
+       BT_CONSTRAINT_STOP_ERP,
+       BT_CONSTRAINT_CFM,
+       BT_CONSTRAINT_STOP_CFM
+};
+
+#if 1
+#define btAssertConstrParams(_par) btAssert(_par)
+#else
+#define btAssertConstrParams(_par)
+#endif
+
+ATTRIBUTE_ALIGNED16(struct)
+btJointFeedback
+{
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+       btVector3 m_appliedForceBodyA;
+       btVector3 m_appliedTorqueBodyA;
+       btVector3 m_appliedForceBodyB;
+       btVector3 m_appliedTorqueBodyB;
+};
+
+///TypedConstraint is the baseclass for Bullet constraints and vehicles
+ATTRIBUTE_ALIGNED16(class)
+btTypedConstraint : public btTypedObject
+{
+       int m_userConstraintType;
+
+       union {
+               int m_userConstraintId;
+               void* m_userConstraintPtr;
+       };
+
+       btScalar m_breakingImpulseThreshold;
+       bool m_isEnabled;
+       bool m_needsFeedback;
+       int m_overrideNumSolverIterations;
+
+       btTypedConstraint& operator=(btTypedConstraint& other)
+       {
+               btAssert(0);
+               (void)other;
+               return *this;
+       }
+
+protected:
+       btRigidBody& m_rbA;
+       btRigidBody& m_rbB;
+       btScalar m_appliedImpulse;
+       btScalar m_dbgDrawSize;
+       btJointFeedback* m_jointFeedback;
+
+       ///internal method used by the constraint solver, don't use them directly
+       btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       virtual ~btTypedConstraint(){};
+       btTypedConstraint(btTypedConstraintType type, btRigidBody & rbA);
+       btTypedConstraint(btTypedConstraintType type, btRigidBody & rbA, btRigidBody & rbB);
+
+       struct btConstraintInfo1
+       {
+               int m_numConstraintRows, nub;
+       };
+
+       static btRigidBody& getFixedBody();
+
+       struct btConstraintInfo2
+       {
+               // integrator parameters: frames per second (1/stepsize), default error
+               // reduction parameter (0..1).
+               btScalar fps, erp;
+
+               // for the first and second body, pointers to two (linear and angular)
+               // n*3 jacobian sub matrices, stored by rows. these matrices will have
+               // been initialized to 0 on entry. if the second body is zero then the
+               // J2xx pointers may be 0.
+               btScalar *m_J1linearAxis, *m_J1angularAxis, *m_J2linearAxis, *m_J2angularAxis;
+
+               // elements to jump from one row to the next in J's
+               int rowskip;
+
+               // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+               // "constraint force mixing" vector. c is set to zero on entry, cfm is
+               // set to a constant value (typically very small or zero) value on entry.
+               btScalar *m_constraintError, *cfm;
+
+               // lo and hi limits for variables (set to -/+ infinity on entry).
+               btScalar *m_lowerLimit, *m_upperLimit;
+
+               // number of solver iterations
+               int m_numIterations;
+
+               //damping of the velocity
+               btScalar m_damping;
+       };
+
+       int getOverrideNumSolverIterations() const
+       {
+               return m_overrideNumSolverIterations;
+       }
+
+       ///override the number of constraint solver iterations used to solve this constraint
+       ///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations
+       void setOverrideNumSolverIterations(int overideNumIterations)
+       {
+               m_overrideNumSolverIterations = overideNumIterations;
+       }
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void buildJacobian(){};
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void setupSolverConstraint(btConstraintArray & ca, int solverBodyA, int solverBodyB, btScalar timeStep)
+       {
+               (void)ca;
+               (void)solverBodyA;
+               (void)solverBodyB;
+               (void)timeStep;
+       }
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void getInfo1(btConstraintInfo1 * info) = 0;
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void getInfo2(btConstraintInfo2 * info) = 0;
+
+       ///internal method used by the constraint solver, don't use them directly
+       void internalSetAppliedImpulse(btScalar appliedImpulse)
+       {
+               m_appliedImpulse = appliedImpulse;
+       }
+       ///internal method used by the constraint solver, don't use them directly
+       btScalar internalGetAppliedImpulse()
+       {
+               return m_appliedImpulse;
+       }
+
+       btScalar getBreakingImpulseThreshold() const
+       {
+               return m_breakingImpulseThreshold;
+       }
+
+       void setBreakingImpulseThreshold(btScalar threshold)
+       {
+               m_breakingImpulseThreshold = threshold;
+       }
+
+       bool isEnabled() const
+       {
+               return m_isEnabled;
+       }
+
+       void setEnabled(bool enabled)
+       {
+               m_isEnabled = enabled;
+       }
+
+       ///internal method used by the constraint solver, don't use them directly
+       virtual void solveConstraintObsolete(btSolverBody& /*bodyA*/, btSolverBody& /*bodyB*/, btScalar /*timeStep*/){};
+
+       const btRigidBody& getRigidBodyA() const
+       {
+               return m_rbA;
+       }
+       const btRigidBody& getRigidBodyB() const
+       {
+               return m_rbB;
+       }
+
+       btRigidBody& getRigidBodyA()
+       {
+               return m_rbA;
+       }
+       btRigidBody& getRigidBodyB()
+       {
+               return m_rbB;
+       }
+
+       int getUserConstraintType() const
+       {
+               return m_userConstraintType;
+       }
+
+       void setUserConstraintType(int userConstraintType)
+       {
+               m_userConstraintType = userConstraintType;
+       };
+
+       void setUserConstraintId(int uid)
+       {
+               m_userConstraintId = uid;
+       }
+
+       int getUserConstraintId() const
+       {
+               return m_userConstraintId;
+       }
+
+       void setUserConstraintPtr(void* ptr)
+       {
+               m_userConstraintPtr = ptr;
+       }
+
+       void* getUserConstraintPtr()
+       {
+               return m_userConstraintPtr;
+       }
+
+       void setJointFeedback(btJointFeedback * jointFeedback)
+       {
+               m_jointFeedback = jointFeedback;
+       }
+
+       const btJointFeedback* getJointFeedback() const
+       {
+               return m_jointFeedback;
+       }
+
+       btJointFeedback* getJointFeedback()
+       {
+               return m_jointFeedback;
+       }
+
+       int getUid() const
+       {
+               return m_userConstraintId;
+       }
+
+       bool needsFeedback() const
+       {
+               return m_needsFeedback;
+       }
+
+       ///enableFeedback will allow to read the applied linear and angular impulse
+       ///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information
+       void enableFeedback(bool needsFeedback)
+       {
+               m_needsFeedback = needsFeedback;
+       }
+
+       ///getAppliedImpulse is an estimated total applied impulse.
+       ///This feedback could be used to determine breaking constraints or playing sounds.
+       btScalar getAppliedImpulse() const
+       {
+               btAssert(m_needsFeedback);
+               return m_appliedImpulse;
+       }
+
+       btTypedConstraintType getConstraintType() const
+       {
+               return btTypedConstraintType(m_objectType);
+       }
+
+       void setDbgDrawSize(btScalar dbgDrawSize)
+       {
+               m_dbgDrawSize = dbgDrawSize;
+       }
+       btScalar getDbgDrawSize()
+       {
+               return m_dbgDrawSize;
+       }
+
+       ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
+       ///If no axis is provided, it uses the default axis for this constraint.
+       virtual void setParam(int num, btScalar value, int axis = -1) = 0;
+
+       ///return the local value of parameter
+       virtual btScalar getParam(int num, int axis = -1) const = 0;
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
+};
+
+// returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits
+// all arguments should be normalized angles (i.e. in range [-SIMD_PI, SIMD_PI])
+SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians)
+{
+       if (angleLowerLimitInRadians >= angleUpperLimitInRadians)
+       {
+               return angleInRadians;
+       }
+       else if (angleInRadians < angleLowerLimitInRadians)
+       {
+               btScalar diffLo = btFabs(btNormalizeAngle(angleLowerLimitInRadians - angleInRadians));
+               btScalar diffHi = btFabs(btNormalizeAngle(angleUpperLimitInRadians - angleInRadians));
+               return (diffLo < diffHi) ? angleInRadians : (angleInRadians + SIMD_2_PI);
+       }
+       else if (angleInRadians > angleUpperLimitInRadians)
+       {
+               btScalar diffHi = btFabs(btNormalizeAngle(angleInRadians - angleUpperLimitInRadians));
+               btScalar diffLo = btFabs(btNormalizeAngle(angleInRadians - angleLowerLimitInRadians));
+               return (diffLo < diffHi) ? (angleInRadians - SIMD_2_PI) : angleInRadians;
+       }
+       else
+       {
+               return angleInRadians;
+       }
+}
+
+// clang-format off
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btTypedConstraintFloatData
+{
+       btRigidBodyFloatData            *m_rbA;
+       btRigidBodyFloatData            *m_rbB;
+       char    *m_name;
+
+       int     m_objectType;
+       int     m_userConstraintType;
+       int     m_userConstraintId;
+       int     m_needsFeedback;
+
+       float   m_appliedImpulse;
+       float   m_dbgDrawSize;
+
+       int     m_disableCollisionsBetweenLinkedBodies;
+       int     m_overrideNumSolverIterations;
+
+       float   m_breakingImpulseThreshold;
+       int             m_isEnabled;
+       
+};
+
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+
+#define BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
+///this structure is not used, except for loading pre-2.82 .bullet files
+struct btTypedConstraintData
+{
+       btRigidBodyData         *m_rbA;
+       btRigidBodyData         *m_rbB;
+       char    *m_name;
+
+       int     m_objectType;
+       int     m_userConstraintType;
+       int     m_userConstraintId;
+       int     m_needsFeedback;
+
+       float   m_appliedImpulse;
+       float   m_dbgDrawSize;
+
+       int     m_disableCollisionsBetweenLinkedBodies;
+       int     m_overrideNumSolverIterations;
+
+       float   m_breakingImpulseThreshold;
+       int             m_isEnabled;
+       
+};
+#endif //BACKWARDS_COMPATIBLE
+
+struct btTypedConstraintDoubleData
+{
+       btRigidBodyDoubleData           *m_rbA;
+       btRigidBodyDoubleData           *m_rbB;
+       char    *m_name;
+
+       int     m_objectType;
+       int     m_userConstraintType;
+       int     m_userConstraintId;
+       int     m_needsFeedback;
+
+       double  m_appliedImpulse;
+       double  m_dbgDrawSize;
+
+       int     m_disableCollisionsBetweenLinkedBodies;
+       int     m_overrideNumSolverIterations;
+
+       double  m_breakingImpulseThreshold;
+       int             m_isEnabled;
+       char    padding[4];
+       
+};
+
+// clang-format on
+
+SIMD_FORCE_INLINE int btTypedConstraint::calculateSerializeBufferSize() const
+{
+       return sizeof(btTypedConstraintData2);
+}
+
+class btAngularLimit
+{
+private:
+       btScalar
+               m_center,
+               m_halfRange,
+               m_softness,
+               m_biasFactor,
+               m_relaxationFactor,
+               m_correction,
+               m_sign;
+
+       bool
+               m_solveLimit;
+
+public:
+       /// Default constructor initializes limit as inactive, allowing free constraint movement
+       btAngularLimit()
+               : m_center(0.0f),
+                 m_halfRange(-1.0f),
+                 m_softness(0.9f),
+                 m_biasFactor(0.3f),
+                 m_relaxationFactor(1.0f),
+                 m_correction(0.0f),
+                 m_sign(0.0f),
+                 m_solveLimit(false)
+       {
+       }
+
+       /// Sets all limit's parameters.
+       /// When low > high limit becomes inactive.
+       /// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit
+       void set(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f);
+
+       /// Checks conastaint angle against limit. If limit is active and the angle violates the limit
+       /// correction is calculated.
+       void test(const btScalar angle);
+
+       /// Returns limit's softness
+       inline btScalar getSoftness() const
+       {
+               return m_softness;
+       }
+
+       /// Returns limit's bias factor
+       inline btScalar getBiasFactor() const
+       {
+               return m_biasFactor;
+       }
+
+       /// Returns limit's relaxation factor
+       inline btScalar getRelaxationFactor() const
+       {
+               return m_relaxationFactor;
+       }
+
+       /// Returns correction value evaluated when test() was invoked
+       inline btScalar getCorrection() const
+       {
+               return m_correction;
+       }
+
+       /// Returns sign value evaluated when test() was invoked
+       inline btScalar getSign() const
+       {
+               return m_sign;
+       }
+
+       /// Gives half of the distance between min and max limit angle
+       inline btScalar getHalfRange() const
+       {
+               return m_halfRange;
+       }
+
+       /// Returns true when the last test() invocation recognized limit violation
+       inline bool isLimit() const
+       {
+               return m_solveLimit;
+       }
+
+       /// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle
+       /// returned is modified so it equals to the limit closest to given angle.
+       void fit(btScalar& angle) const;
+
+       /// Returns correction value multiplied by sign value
+       btScalar getError() const;
+
+       btScalar getLow() const;
+
+       btScalar getHigh() const;
+};
+
+#endif  //BT_TYPED_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
new file mode 100644 (file)
index 0000000..42ed1fb
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btUniversalConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+
+#define UNIV_EPS btScalar(0.01f)
+
+// constructor
+// anchor, axis1 and axis2 are in world coordinate system
+// axis1 must be orthogonal to axis2
+btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2)
+       : btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true),
+         m_anchor(anchor),
+         m_axis1(axis1),
+         m_axis2(axis2)
+{
+       // build frame basis
+       // 6DOF constraint uses Euler angles and to define limits
+       // it is assumed that rotational order is :
+       // Z - first, allowed limits are (-PI,PI);
+       // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number
+       // used to prevent constraint from instability on poles;
+       // new position of X, allowed limits are (-PI,PI);
+       // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs
+       // Build the frame in world coordinate system first
+       btVector3 zAxis = m_axis1.normalize();
+       btVector3 yAxis = m_axis2.normalize();
+       btVector3 xAxis = yAxis.cross(zAxis);  // we want right coordinate system
+       btTransform frameInW;
+       frameInW.setIdentity();
+       frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+                                                                xAxis[1], yAxis[1], zAxis[1],
+                                                                xAxis[2], yAxis[2], zAxis[2]);
+       frameInW.setOrigin(anchor);
+       // now get constraint frame in local coordinate systems
+       m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW;
+       m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW;
+       // sei limits
+       setLinearLowerLimit(btVector3(0., 0., 0.));
+       setLinearUpperLimit(btVector3(0., 0., 0.));
+       setAngularLowerLimit(btVector3(0.f, -SIMD_HALF_PI + UNIV_EPS, -SIMD_PI + UNIV_EPS));
+       setAngularUpperLimit(btVector3(0.f, SIMD_HALF_PI - UNIV_EPS, SIMD_PI - UNIV_EPS));
+}
+
+void btUniversalConstraint::setAxis(const btVector3& axis1, const btVector3& axis2)
+{
+       m_axis1 = axis1;
+       m_axis2 = axis2;
+
+       btVector3 zAxis = axis1.normalized();
+       btVector3 yAxis = axis2.normalized();
+       btVector3 xAxis = yAxis.cross(zAxis);  // we want right coordinate system
+
+       btTransform frameInW;
+       frameInW.setIdentity();
+       frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
+                                                                xAxis[1], yAxis[1], zAxis[1],
+                                                                xAxis[2], yAxis[2], zAxis[2]);
+       frameInW.setOrigin(m_anchor);
+
+       // now get constraint frame in local coordinate systems
+       m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+       m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+
+       calculateTransforms();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
new file mode 100644 (file)
index 0000000..8c24d93
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_UNIVERSAL_CONSTRAINT_H
+#define BT_UNIVERSAL_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btTypedConstraint.h"
+#include "btGeneric6DofConstraint.h"
+
+/// Constraint similar to ODE Universal Joint
+/// has 2 rotatioonal degrees of freedom, similar to Euler rotations around Z (axis 1)
+/// and Y (axis 2)
+/// Description from ODE manual :
+/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular.
+/// In other words, rotation of the two bodies about the direction perpendicular to the two axes will be equal."
+
+ATTRIBUTE_ALIGNED16(class)
+btUniversalConstraint : public btGeneric6DofConstraint
+{
+protected:
+       btVector3 m_anchor;
+       btVector3 m_axis1;
+       btVector3 m_axis2;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       // constructor
+       // anchor, axis1 and axis2 are in world coordinate system
+       // axis1 must be orthogonal to axis2
+       btUniversalConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2);
+       // access
+       const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); }
+       const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); }
+       const btVector3& getAxis1() { return m_axis1; }
+       const btVector3& getAxis2() { return m_axis2; }
+       btScalar getAngle1() { return getAngle(2); }
+       btScalar getAngle2() { return getAngle(1); }
+       // limits
+       void setUpperLimit(btScalar ang1max, btScalar ang2max) { setAngularUpperLimit(btVector3(0.f, ang1max, ang2max)); }
+       void setLowerLimit(btScalar ang1min, btScalar ang2min) { setAngularLowerLimit(btVector3(0.f, ang1min, ang2min)); }
+
+       void setAxis(const btVector3& axis1, const btVector3& axis2);
+};
+
+#endif  // BT_UNIVERSAL_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btActionInterface.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btActionInterface.h
new file mode 100644 (file)
index 0000000..51a3fa4
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_ACTION_INTERFACE_H
+#define _BT_ACTION_INTERFACE_H
+
+class btIDebugDraw;
+class btCollisionWorld;
+
+#include "LinearMath/btScalar.h"
+#include "btRigidBody.h"
+
+///Basic interface to allow actions such as vehicles and characters to be updated inside a btDynamicsWorld
+class btActionInterface
+{
+protected:
+       static btRigidBody& getFixedBody();
+
+public:
+       virtual ~btActionInterface()
+       {
+       }
+
+       virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) = 0;
+
+       virtual void debugDraw(btIDebugDraw* debugDrawer) = 0;
+};
+
+#endif  //_BT_ACTION_INTERFACE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
new file mode 100644 (file)
index 0000000..9e99c15
--- /dev/null
@@ -0,0 +1,1469 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btDiscreteDynamicsWorld.h"
+
+//collision detection
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btQuickprof.h"
+
+//rigidbody & constraints
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
+
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btMotionState.h"
+
+#include "LinearMath/btSerializer.h"
+
+#if 0
+btAlignedObjectArray<btVector3> debugContacts;
+btAlignedObjectArray<btVector3> debugNormals;
+int startHit=2;
+int firstHit=startHit;
+#endif
+
+SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs)
+{
+       int islandId;
+
+       const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
+       const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
+       islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
+       return islandId;
+}
+
+class btSortConstraintOnIslandPredicate
+{
+public:
+       bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
+       {
+               int rIslandId0, lIslandId0;
+               rIslandId0 = btGetConstraintIslandId(rhs);
+               lIslandId0 = btGetConstraintIslandId(lhs);
+               return lIslandId0 < rIslandId0;
+       }
+};
+
+struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
+{
+       btContactSolverInfo* m_solverInfo;
+       btConstraintSolver* m_solver;
+       btTypedConstraint** m_sortedConstraints;
+       int m_numConstraints;
+       btIDebugDraw* m_debugDrawer;
+       btDispatcher* m_dispatcher;
+
+       btAlignedObjectArray<btCollisionObject*> m_bodies;
+       btAlignedObjectArray<btPersistentManifold*> m_manifolds;
+       btAlignedObjectArray<btTypedConstraint*> m_constraints;
+
+       InplaceSolverIslandCallback(
+               btConstraintSolver* solver,
+               btStackAlloc* stackAlloc,
+               btDispatcher* dispatcher)
+               : m_solverInfo(NULL),
+                 m_solver(solver),
+                 m_sortedConstraints(NULL),
+                 m_numConstraints(0),
+                 m_debugDrawer(NULL),
+                 m_dispatcher(dispatcher)
+       {
+       }
+
+       InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other)
+       {
+               btAssert(0);
+               (void)other;
+               return *this;
+       }
+
+       SIMD_FORCE_INLINE void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer)
+       {
+               btAssert(solverInfo);
+               m_solverInfo = solverInfo;
+               m_sortedConstraints = sortedConstraints;
+               m_numConstraints = numConstraints;
+               m_debugDrawer = debugDrawer;
+               m_bodies.resize(0);
+               m_manifolds.resize(0);
+               m_constraints.resize(0);
+       }
+
+       virtual void processIsland(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifolds, int numManifolds, int islandId)
+       {
+               if (islandId < 0)
+               {
+                       ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
+                       m_solver->solveGroup(bodies, numBodies, manifolds, numManifolds, &m_sortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
+               }
+               else
+               {
+                       //also add all non-contact constraints/joints for this island
+                       btTypedConstraint** startConstraint = 0;
+                       int numCurConstraints = 0;
+                       int i;
+
+                       //find the first constraint for this island
+                       for (i = 0; i < m_numConstraints; i++)
+                       {
+                               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)
+                               {
+                                       numCurConstraints++;
+                               }
+                       }
+
+                       if (m_solverInfo->m_minimumSolverBatchSize <= 1)
+                       {
+                               m_solver->solveGroup(bodies, numBodies, manifolds, numManifolds, startConstraint, numCurConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
+                       }
+                       else
+                       {
+                               for (i = 0; i < numBodies; i++)
+                                       m_bodies.push_back(bodies[i]);
+                               for (i = 0; i < numManifolds; i++)
+                                       m_manifolds.push_back(manifolds[i]);
+                               for (i = 0; i < numCurConstraints; i++)
+                                       m_constraints.push_back(startConstraint[i]);
+                               if ((m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
+                               {
+                                       processConstraints();
+                               }
+                               else
+                               {
+                                       //printf("deferred\n");
+                               }
+                       }
+               }
+       }
+       void processConstraints()
+       {
+               btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
+               btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
+               btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
+
+               m_solver->solveGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
+               m_bodies.resize(0);
+               m_manifolds.resize(0);
+               m_constraints.resize(0);
+       }
+};
+
+btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+       : btDynamicsWorld(dispatcher, pairCache, collisionConfiguration),
+         m_sortedConstraints(),
+         m_solverIslandCallback(NULL),
+         m_constraintSolver(constraintSolver),
+         m_gravity(0, -10, 0),
+         m_localTime(0),
+         m_fixedTimeStep(0),
+         m_synchronizeAllMotionStates(false),
+         m_applySpeculativeContactRestitution(false),
+         m_profileTimings(0),
+         m_latencyMotionStateInterpolation(true)
+
+{
+       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;
+
+       {
+               void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback), 16);
+               m_solverIslandCallback = new (mem) InplaceSolverIslandCallback(m_constraintSolver, 0, dispatcher);
+       }
+}
+
+btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld()
+{
+       //only delete it when we created it
+       if (m_ownsIslandManager)
+       {
+               m_islandManager->~btSimulationIslandManager();
+               btAlignedFree(m_islandManager);
+       }
+       if (m_solverIslandCallback)
+       {
+               m_solverIslandCallback->~InplaceSolverIslandCallback();
+               btAlignedFree(m_solverIslandCallback);
+       }
+       if (m_ownsConstraintSolver)
+       {
+               m_constraintSolver->~btConstraintSolver();
+               btAlignedFree(m_constraintSolver);
+       }
+}
+
+void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
+{
+       ///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
+       ///to switch status _after_ adding kinematic objects to the world
+       ///fix it for Bullet 3.x release
+       for (int i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               btRigidBody* body = btRigidBody::upcast(colObj);
+               if (body && body->getActivationState() != ISLAND_SLEEPING)
+               {
+                       if (body->isKinematicObject())
+                       {
+                               //to calculate velocities next frame
+                               body->saveKinematicState(timeStep);
+                       }
+               }
+       }
+}
+
+void btDiscreteDynamicsWorld::debugDrawWorld()
+{
+       BT_PROFILE("debugDrawWorld");
+
+       btCollisionWorld::debugDrawWorld();
+
+       bool drawConstraints = false;
+       if (getDebugDrawer())
+       {
+               int mode = getDebugDrawer()->getDebugMode();
+               if (mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
+               {
+                       drawConstraints = true;
+               }
+       }
+       if (drawConstraints)
+       {
+               for (int i = getNumConstraints() - 1; i >= 0; i--)
+               {
+                       btTypedConstraint* constraint = getConstraint(i);
+                       debugDrawConstraint(constraint);
+               }
+       }
+
+       if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals)))
+       {
+               int i;
+
+               if (getDebugDrawer() && getDebugDrawer()->getDebugMode())
+               {
+                       for (i = 0; i < m_actions.size(); i++)
+                       {
+                               m_actions[i]->debugDraw(m_debugDrawer);
+                       }
+               }
+       }
+       if (getDebugDrawer())
+               getDebugDrawer()->flushLines();
+}
+
+void btDiscreteDynamicsWorld::clearForces()
+{
+       ///@todo: iterate over awake simulation islands!
+       for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
+       {
+               btRigidBody* body = m_nonStaticRigidBodies[i];
+               //need to check if next line is ok
+               //it might break backward compatibility (people applying forces on sleeping objects get never cleared and accumulate on wake-up
+               body->clearForces();
+       }
+}
+
+///apply gravity, call this once per timestep
+void btDiscreteDynamicsWorld::applyGravity()
+{
+       ///@todo: iterate over awake simulation islands!
+       for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
+       {
+               btRigidBody* body = m_nonStaticRigidBodies[i];
+               if (body->isActive())
+               {
+                       body->applyGravity();
+               }
+       }
+}
+
+void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
+{
+       btAssert(body);
+
+       if (body->getMotionState() && !body->isStaticOrKinematicObject())
+       {
+               //we need to call the update at least once, even for sleeping objects
+               //otherwise the 'graphics' transform never updates properly
+               ///@todo: add 'dirty' flag
+               //if (body->getActivationState() != ISLAND_SLEEPING)
+               {
+                       btTransform interpolatedTransform;
+                       btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
+                                                                                               body->getInterpolationLinearVelocity(), body->getInterpolationAngularVelocity(),
+                                                                                               (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime * body->getHitFraction(),
+                                                                                               interpolatedTransform);
+                       body->getMotionState()->setWorldTransform(interpolatedTransform);
+               }
+       }
+}
+
+void btDiscreteDynamicsWorld::synchronizeMotionStates()
+{
+       //      BT_PROFILE("synchronizeMotionStates");
+       if (m_synchronizeAllMotionStates)
+       {
+               //iterate  over all collision objects
+               for (int i = 0; i < m_collisionObjects.size(); i++)
+               {
+                       btCollisionObject* colObj = m_collisionObjects[i];
+                       btRigidBody* body = btRigidBody::upcast(colObj);
+                       if (body)
+                               synchronizeSingleMotionState(body);
+               }
+       }
+       else
+       {
+               //iterate over all active rigid bodies
+               for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
+               {
+                       btRigidBody* body = m_nonStaticRigidBodies[i];
+                       if (body->isActive())
+                               synchronizeSingleMotionState(body);
+               }
+       }
+}
+
+int btDiscreteDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
+{
+       startProfiling(timeStep);
+
+       int numSimulationSubSteps = 0;
+
+       if (maxSubSteps)
+       {
+               //fixed timestep with interpolation
+               m_fixedTimeStep = fixedTimeStep;
+               m_localTime += timeStep;
+               if (m_localTime >= fixedTimeStep)
+               {
+                       numSimulationSubSteps = int(m_localTime / fixedTimeStep);
+                       m_localTime -= numSimulationSubSteps * fixedTimeStep;
+               }
+       }
+       else
+       {
+               //variable timestep
+               fixedTimeStep = timeStep;
+               m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
+               m_fixedTimeStep = 0;
+               if (btFuzzyZero(timeStep))
+               {
+                       numSimulationSubSteps = 0;
+                       maxSubSteps = 0;
+               }
+               else
+               {
+                       numSimulationSubSteps = 1;
+                       maxSubSteps = 1;
+               }
+       }
+
+       //process some debugging flags
+       if (getDebugDrawer())
+       {
+               btIDebugDraw* debugDrawer = getDebugDrawer();
+               gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
+       }
+       if (numSimulationSubSteps)
+       {
+               //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
+               int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps) ? maxSubSteps : numSimulationSubSteps;
+
+               saveKinematicState(fixedTimeStep * clampedSimulationSteps);
+
+               applyGravity();
+
+               for (int i = 0; i < clampedSimulationSteps; i++)
+               {
+                       internalSingleStepSimulation(fixedTimeStep);
+                       synchronizeMotionStates();
+               }
+       }
+       else
+       {
+               synchronizeMotionStates();
+       }
+
+       clearForces();
+
+#ifndef BT_NO_PROFILE
+       CProfileManager::Increment_Frame_Counter();
+#endif  //BT_NO_PROFILE
+
+       return numSimulationSubSteps;
+}
+
+void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
+{
+       BT_PROFILE("internalSingleStepSimulation");
+
+       if (0 != m_internalPreTickCallback)
+       {
+               (*m_internalPreTickCallback)(this, timeStep);
+       }
+
+       ///apply gravity, predict motion
+       predictUnconstraintMotion(timeStep);
+
+       btDispatcherInfo& dispatchInfo = getDispatchInfo();
+
+       dispatchInfo.m_timeStep = timeStep;
+       dispatchInfo.m_stepCount = 0;
+       dispatchInfo.m_debugDraw = getDebugDrawer();
+
+       createPredictiveContacts(timeStep);
+
+       ///perform collision detection
+       performDiscreteCollisionDetection();
+
+       calculateSimulationIslands();
+
+       getSolverInfo().m_timeStep = timeStep;
+
+       ///solve contact and other joint constraints
+       solveConstraints(getSolverInfo());
+
+       ///CallbackTriggers();
+
+       ///integrate transforms
+
+       integrateTransforms(timeStep);
+
+       ///update vehicle simulation
+       updateActions(timeStep);
+
+       updateActivationState(timeStep);
+
+       if (0 != m_internalTickCallback)
+       {
+               (*m_internalTickCallback)(this, timeStep);
+       }
+}
+
+void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
+{
+       m_gravity = gravity;
+       for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
+       {
+               btRigidBody* body = m_nonStaticRigidBodies[i];
+               if (body->isActive() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
+               {
+                       body->setGravity(gravity);
+               }
+       }
+}
+
+btVector3 btDiscreteDynamicsWorld::getGravity() const
+{
+       return m_gravity;
+}
+
+void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
+{
+       btCollisionWorld::addCollisionObject(collisionObject, collisionFilterGroup, collisionFilterMask);
+}
+
+void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+       btRigidBody* body = btRigidBody::upcast(collisionObject);
+       if (body)
+               removeRigidBody(body);
+       else
+               btCollisionWorld::removeCollisionObject(collisionObject);
+}
+
+void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
+{
+       m_nonStaticRigidBodies.remove(body);
+       btCollisionWorld::removeCollisionObject(body);
+}
+
+void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
+{
+       if (!body->isStaticOrKinematicObject() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
+       {
+               body->setGravity(m_gravity);
+       }
+
+       if (body->getCollisionShape())
+       {
+               if (!body->isStaticObject())
+               {
+                       m_nonStaticRigidBodies.push_back(body);
+               }
+               else
+               {
+                       body->setActivationState(ISLAND_SLEEPING);
+               }
+
+               bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
+               int collisionFilterGroup = isDynamic ? int(btBroadphaseProxy::DefaultFilter) : int(btBroadphaseProxy::StaticFilter);
+               int collisionFilterMask = isDynamic ? int(btBroadphaseProxy::AllFilter) : int(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+
+               addCollisionObject(body, collisionFilterGroup, collisionFilterMask);
+       }
+}
+
+void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
+{
+       if (!body->isStaticOrKinematicObject() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
+       {
+               body->setGravity(m_gravity);
+       }
+
+       if (body->getCollisionShape())
+       {
+               if (!body->isStaticObject())
+               {
+                       m_nonStaticRigidBodies.push_back(body);
+               }
+               else
+               {
+                       body->setActivationState(ISLAND_SLEEPING);
+               }
+               addCollisionObject(body, group, mask);
+       }
+}
+
+void btDiscreteDynamicsWorld::updateActions(btScalar timeStep)
+{
+       BT_PROFILE("updateActions");
+
+       for (int i = 0; i < m_actions.size(); i++)
+       {
+               m_actions[i]->updateAction(this, timeStep);
+       }
+}
+
+void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
+{
+       BT_PROFILE("updateActivationState");
+
+       for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
+       {
+               btRigidBody* body = m_nonStaticRigidBodies[i];
+               if (body)
+               {
+                       body->updateDeactivation(timeStep);
+
+                       if (body->wantsSleeping())
+                       {
+                               if (body->isStaticOrKinematicObject())
+                               {
+                                       body->setActivationState(ISLAND_SLEEPING);
+                               }
+                               else
+                               {
+                                       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
+                       {
+                               if (body->getActivationState() != DISABLE_DEACTIVATION)
+                                       body->setActivationState(ACTIVE_TAG);
+                       }
+               }
+       }
+}
+
+void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies)
+{
+       m_constraints.push_back(constraint);
+       //Make sure the two bodies of a type constraint are different (possibly add this to the btTypedConstraint constructor?)
+       btAssert(&constraint->getRigidBodyA() != &constraint->getRigidBodyB());
+
+       if (disableCollisionsBetweenLinkedBodies)
+       {
+               constraint->getRigidBodyA().addConstraintRef(constraint);
+               constraint->getRigidBodyB().addConstraintRef(constraint);
+       }
+}
+
+void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
+{
+       m_constraints.remove(constraint);
+       constraint->getRigidBodyA().removeConstraintRef(constraint);
+       constraint->getRigidBodyB().removeConstraintRef(constraint);
+}
+
+void btDiscreteDynamicsWorld::addAction(btActionInterface* action)
+{
+       m_actions.push_back(action);
+}
+
+void btDiscreteDynamicsWorld::removeAction(btActionInterface* action)
+{
+       m_actions.remove(action);
+}
+
+void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle)
+{
+       addAction(vehicle);
+}
+
+void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle)
+{
+       removeAction(vehicle);
+}
+
+void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character)
+{
+       addAction(character);
+}
+
+void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character)
+{
+       removeAction(character);
+}
+
+void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
+{
+       BT_PROFILE("solveConstraints");
+
+       m_sortedConstraints.resize(m_constraints.size());
+       int i;
+       for (i = 0; i < getNumConstraints(); i++)
+       {
+               m_sortedConstraints[i] = m_constraints[i];
+       }
+
+       //      btAssert(0);
+
+       m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate());
+
+       btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
+
+       m_solverIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), getDebugDrawer());
+       m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+
+       /// solve all the constraints for this island
+       m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverIslandCallback);
+
+       m_solverIslandCallback->processConstraints();
+
+       m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
+}
+
+void btDiscreteDynamicsWorld::calculateSimulationIslands()
+{
+       BT_PROFILE("calculateSimulationIslands");
+
+       getSimulationIslandManager()->updateActivationState(getCollisionWorld(), getCollisionWorld()->getDispatcher());
+
+       {
+               //merge islands based on speculative contact manifolds too
+               for (int i = 0; i < this->m_predictiveManifolds.size(); i++)
+               {
+                       btPersistentManifold* manifold = m_predictiveManifolds[i];
+
+                       const btCollisionObject* colObj0 = manifold->getBody0();
+                       const btCollisionObject* colObj1 = manifold->getBody1();
+
+                       if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+                               ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+                       {
+                               getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
+                       }
+               }
+       }
+
+       {
+               int i;
+               int numConstraints = int(m_constraints.size());
+               for (i = 0; i < numConstraints; i++)
+               {
+                       btTypedConstraint* constraint = m_constraints[i];
+                       if (constraint->isEnabled())
+                       {
+                               const btRigidBody* colObj0 = &constraint->getRigidBodyA();
+                               const btRigidBody* colObj1 = &constraint->getRigidBodyB();
+
+                               if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+                                       ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+                               {
+                                       getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
+                               }
+                       }
+               }
+       }
+
+       //Store the island id in each body
+       getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
+}
+
+class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
+{
+public:
+       btCollisionObject* m_me;
+       btScalar m_allowedPenetration;
+       btOverlappingPairCache* m_pairCache;
+       btDispatcher* m_dispatcher;
+
+public:
+       btClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btCollisionWorld::ClosestConvexResultCallback(fromA, toA),
+                                                                                                                                                                                                                                                                                                                                                  m_me(me),
+                                                                                                                                                                                                                                                                                                                                                  m_allowedPenetration(0.0f),
+                                                                                                                                                                                                                                                                                                                                                  m_pairCache(pairCache),
+                                                                                                                                                                                                                                                                                                                                                  m_dispatcher(dispatcher)
+       {
+       }
+
+       virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
+       {
+               if (convexResult.m_hitCollisionObject == m_me)
+                       return 1.0f;
+
+               //ignore result if there is no contact response
+               if (!convexResult.m_hitCollisionObject->hasContactResponse())
+                       return 1.0f;
+
+               btVector3 linVelA, linVelB;
+               linVelA = m_convexToWorld - m_convexFromWorld;
+               linVelB = btVector3(0, 0, 0);  //toB.getOrigin()-fromB.getOrigin();
+
+               btVector3 relativeVelocity = (linVelA - linVelB);
+               //don't report time of impact for motion away from the contact normal (or causes minor penetration)
+               if (convexResult.m_hitNormalLocal.dot(relativeVelocity) >= -m_allowedPenetration)
+                       return 1.f;
+
+               return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
+       }
+
+       virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+       {
+               //don't collide with itself
+               if (proxy0->m_clientObject == m_me)
+                       return false;
+
+               ///don't do CCD when the collision filters are not matching
+               if (!ClosestConvexResultCallback::needsCollision(proxy0))
+                       return false;
+               if (m_pairCache->getOverlapFilterCallback()) {
+                       btBroadphaseProxy* proxy1 = m_me->getBroadphaseHandle();
+                       bool collides = m_pairCache->needsBroadphaseCollision(proxy0, proxy1);
+                       if (!collides)
+                       {
+                               return false;
+                       }
+               }
+
+               btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
+
+               if (!m_dispatcher->needsCollision(m_me, otherObj))
+                       return false;
+
+               //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
+               if (m_dispatcher->needsResponse(m_me, otherObj))
+               {
+#if 0
+                       ///don't do CCD when there are already contact points (touching contact/penetration)
+                       btAlignedObjectArray<btPersistentManifold*> manifoldArray;
+                       btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0);
+                       if (collisionPair)
+                       {
+                               if (collisionPair->m_algorithm)
+                               {
+                                       manifoldArray.resize(0);
+                                       collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
+                                       for (int j=0;j<manifoldArray.size();j++)
+                                       {
+                                               btPersistentManifold* manifold = manifoldArray[j];
+                                               if (manifold->getNumContacts()>0)
+                                                       return false;
+                                       }
+                               }
+                       }
+#endif
+                       return true;
+               }
+
+               return false;
+       }
+};
+
+///internal debugging variable. this value shouldn't be too high
+int gNumClampedCcdMotions = 0;
+
+void btDiscreteDynamicsWorld::createPredictiveContactsInternal(btRigidBody** bodies, int numBodies, btScalar timeStep)
+{
+       btTransform predictedTrans;
+       for (int i = 0; i < numBodies; i++)
+       {
+               btRigidBody* body = bodies[i];
+               body->setHitFraction(1.f);
+
+               if (body->isActive() && (!body->isStaticOrKinematicObject()))
+               {
+                       body->predictIntegratedTransform(timeStep, predictedTrans);
+
+                       btScalar squareMotion = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()).length2();
+
+                       if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
+                       {
+                               BT_PROFILE("predictive convexSweepTest");
+                               if (body->getCollisionShape()->isConvex())
+                               {
+                                       gNumClampedCcdMotions++;
+#ifdef PREDICTIVE_CONTACT_USE_STATIC_ONLY
+                                       class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
+                                       {
+                                       public:
+                                               StaticOnlyCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btClosestNotMeConvexResultCallback(me, fromA, toA, pairCache, dispatcher)
+                                               {
+                                               }
+
+                                               virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+                                               {
+                                                       btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
+                                                       if (!otherObj->isStaticOrKinematicObject())
+                                                               return false;
+                                                       return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
+                                               }
+                                       };
+
+                                       StaticOnlyCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
+#else
+                                       btClosestNotMeConvexResultCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
+#endif
+                                       //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+                                       btSphereShape tmpSphere(body->getCcdSweptSphereRadius());  //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+                                       sweepResults.m_allowedPenetration = getDispatchInfo().m_allowedCcdPenetration;
+
+                                       sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
+                                       sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
+                                       btTransform modifiedPredictedTrans = predictedTrans;
+                                       modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
+
+                                       convexSweepTest(&tmpSphere, body->getWorldTransform(), modifiedPredictedTrans, sweepResults);
+                                       if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
+                                       {
+                                               btVector3 distVec = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()) * sweepResults.m_closestHitFraction;
+                                               btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld);
+
+                                               btMutexLock(&m_predictiveManifoldsMutex);
+                                               btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body, sweepResults.m_hitCollisionObject);
+                                               m_predictiveManifolds.push_back(manifold);
+                                               btMutexUnlock(&m_predictiveManifoldsMutex);
+
+                                               btVector3 worldPointB = body->getWorldTransform().getOrigin() + distVec;
+                                               btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse() * worldPointB;
+
+                                               btManifoldPoint newPoint(btVector3(0, 0, 0), localPointB, sweepResults.m_hitNormalWorld, distance);
+
+                                               bool isPredictive = true;
+                                               int index = manifold->addManifoldPoint(newPoint, isPredictive);
+                                               btManifoldPoint& pt = manifold->getContactPoint(index);
+                                               pt.m_combinedRestitution = 0;
+                                               pt.m_combinedFriction = gCalculateCombinedFrictionCallback(body, sweepResults.m_hitCollisionObject);
+                                               pt.m_positionWorldOnA = body->getWorldTransform().getOrigin();
+                                               pt.m_positionWorldOnB = worldPointB;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void btDiscreteDynamicsWorld::releasePredictiveContacts()
+{
+       BT_PROFILE("release predictive contact manifolds");
+
+       for (int i = 0; i < m_predictiveManifolds.size(); i++)
+       {
+               btPersistentManifold* manifold = m_predictiveManifolds[i];
+               this->m_dispatcher1->releaseManifold(manifold);
+       }
+       m_predictiveManifolds.clear();
+}
+
+void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
+{
+       BT_PROFILE("createPredictiveContacts");
+       releasePredictiveContacts();
+       if (m_nonStaticRigidBodies.size() > 0)
+       {
+               createPredictiveContactsInternal(&m_nonStaticRigidBodies[0], m_nonStaticRigidBodies.size(), timeStep);
+       }
+}
+
+void btDiscreteDynamicsWorld::integrateTransformsInternal(btRigidBody** bodies, int numBodies, btScalar timeStep)
+{
+       btTransform predictedTrans;
+       for (int i = 0; i < numBodies; i++)
+       {
+               btRigidBody* body = bodies[i];
+               body->setHitFraction(1.f);
+
+               if (body->isActive() && (!body->isStaticOrKinematicObject()))
+               {
+                       body->predictIntegratedTransform(timeStep, predictedTrans);
+
+                       btScalar squareMotion = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()).length2();
+
+                       if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
+                       {
+                               BT_PROFILE("CCD motion clamping");
+                               if (body->getCollisionShape()->isConvex())
+                               {
+                                       gNumClampedCcdMotions++;
+#ifdef USE_STATIC_ONLY
+                                       class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
+                                       {
+                                       public:
+                                               StaticOnlyCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btClosestNotMeConvexResultCallback(me, fromA, toA, pairCache, dispatcher)
+                                               {
+                                               }
+
+                                               virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+                                               {
+                                                       btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
+                                                       if (!otherObj->isStaticOrKinematicObject())
+                                                               return false;
+                                                       return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
+                                               }
+                                       };
+
+                                       StaticOnlyCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
+#else
+                                       btClosestNotMeConvexResultCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
+#endif
+                                       //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+                                       btSphereShape tmpSphere(body->getCcdSweptSphereRadius());  //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+                                       sweepResults.m_allowedPenetration = getDispatchInfo().m_allowedCcdPenetration;
+
+                                       sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
+                                       sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
+                                       btTransform modifiedPredictedTrans = predictedTrans;
+                                       modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
+
+                                       convexSweepTest(&tmpSphere, body->getWorldTransform(), modifiedPredictedTrans, sweepResults);
+                                       if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
+                                       {
+                                               //printf("clamped integration to hit fraction = %f\n",fraction);
+                                               body->setHitFraction(sweepResults.m_closestHitFraction);
+                                               body->predictIntegratedTransform(timeStep * body->getHitFraction(), predictedTrans);
+                                               body->setHitFraction(0.f);
+                                               body->proceedToTransform(predictedTrans);
+
+#if 0
+                                               btVector3 linVel = body->getLinearVelocity();
+
+                                               btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep;
+                                               btScalar maxSpeedSqr = maxSpeed*maxSpeed;
+                                               if (linVel.length2()>maxSpeedSqr)
+                                               {
+                                                       linVel.normalize();
+                                                       linVel*= maxSpeed;
+                                                       body->setLinearVelocity(linVel);
+                                                       btScalar ms2 = body->getLinearVelocity().length2();
+                                                       body->predictIntegratedTransform(timeStep, predictedTrans);
+
+                                                       btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
+                                                       btScalar smt = body->getCcdSquareMotionThreshold();
+                                                       printf("sm2=%f\n",sm2);
+                                               }
+#else
+
+                                               //don't apply the collision response right now, it will happen next frame
+                                               //if you really need to, you can uncomment next 3 lines. Note that is uses zero restitution.
+                                               //btScalar appliedImpulse = 0.f;
+                                               //btScalar depth = 0.f;
+                                               //appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
+
+#endif
+
+                                               continue;
+                                       }
+                               }
+                       }
+
+                       body->proceedToTransform(predictedTrans);
+               }
+       }
+}
+
+void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+       BT_PROFILE("integrateTransforms");
+       if (m_nonStaticRigidBodies.size() > 0)
+       {
+               integrateTransformsInternal(&m_nonStaticRigidBodies[0], m_nonStaticRigidBodies.size(), timeStep);
+       }
+
+       ///this should probably be switched on by default, but it is not well tested yet
+       if (m_applySpeculativeContactRestitution)
+       {
+               BT_PROFILE("apply speculative contact restitution");
+               for (int i = 0; i < m_predictiveManifolds.size(); i++)
+               {
+                       btPersistentManifold* manifold = m_predictiveManifolds[i];
+                       btRigidBody* body0 = btRigidBody::upcast((btCollisionObject*)manifold->getBody0());
+                       btRigidBody* body1 = btRigidBody::upcast((btCollisionObject*)manifold->getBody1());
+
+                       for (int p = 0; p < manifold->getNumContacts(); p++)
+                       {
+                               const btManifoldPoint& pt = manifold->getContactPoint(p);
+                               btScalar combinedRestitution = gCalculateCombinedRestitutionCallback(body0, body1);
+
+                               if (combinedRestitution > 0 && pt.m_appliedImpulse != 0.f)
+                               //if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
+                               {
+                                       btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse * combinedRestitution;
+
+                                       const btVector3& pos1 = pt.getPositionWorldOnA();
+                                       const btVector3& pos2 = pt.getPositionWorldOnB();
+
+                                       btVector3 rel_pos0 = pos1 - body0->getWorldTransform().getOrigin();
+                                       btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin();
+
+                                       if (body0)
+                                               body0->applyImpulse(imp, rel_pos0);
+                                       if (body1)
+                                               body1->applyImpulse(-imp, rel_pos1);
+                               }
+                       }
+               }
+       }
+}
+
+void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+       BT_PROFILE("predictUnconstraintMotion");
+       for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
+       {
+               btRigidBody* body = m_nonStaticRigidBodies[i];
+               if (!body->isStaticOrKinematicObject())
+               {
+                       //don't integrate/update velocities here, it happens in the constraint solver
+
+                       body->applyDamping(timeStep);
+
+                       body->predictIntegratedTransform(timeStep, body->getInterpolationWorldTransform());
+               }
+       }
+}
+
+void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
+{
+       (void)timeStep;
+
+#ifndef BT_NO_PROFILE
+       CProfileManager::Reset();
+#endif  //BT_NO_PROFILE
+}
+
+void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
+{
+       bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0;
+       bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0;
+       btScalar dbgDrawSize = constraint->getDbgDrawSize();
+       if (dbgDrawSize <= btScalar(0.f))
+       {
+               return;
+       }
+
+       switch (constraint->getConstraintType())
+       {
+               case POINT2POINT_CONSTRAINT_TYPE:
+               {
+                       btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
+                       btTransform tr;
+                       tr.setIdentity();
+                       btVector3 pivot = p2pC->getPivotInA();
+                       pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot;
+                       tr.setOrigin(pivot);
+                       getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                       // that ideally should draw the same frame
+                       pivot = p2pC->getPivotInB();
+                       pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot;
+                       tr.setOrigin(pivot);
+                       if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+               }
+               break;
+               case HINGE_CONSTRAINT_TYPE:
+               {
+                       btHingeConstraint* pHinge = (btHingeConstraint*)constraint;
+                       btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame();
+                       if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                       tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame();
+                       if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                       btScalar minAng = pHinge->getLowerLimit();
+                       btScalar maxAng = pHinge->getUpperLimit();
+                       if (minAng == maxAng)
+                       {
+                               break;
+                       }
+                       bool drawSect = true;
+                       if (!pHinge->hasLimit())
+                       {
+                               minAng = btScalar(0.f);
+                               maxAng = SIMD_2_PI;
+                               drawSect = false;
+                       }
+                       if (drawLimits)
+                       {
+                               btVector3& center = tr.getOrigin();
+                               btVector3 normal = tr.getBasis().getColumn(2);
+                               btVector3 axis = tr.getBasis().getColumn(0);
+                               getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0, 0, 0), drawSect);
+                       }
+               }
+               break;
+               case CONETWIST_CONSTRAINT_TYPE:
+               {
+                       btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint;
+                       btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
+                       if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                       tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
+                       if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                       if (drawLimits)
+                       {
+                               //const btScalar length = btScalar(5);
+                               const btScalar length = dbgDrawSize;
+                               static int nSegments = 8 * 4;
+                               btScalar fAngleInRadians = btScalar(2. * 3.1415926) * (btScalar)(nSegments - 1) / btScalar(nSegments);
+                               btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length);
+                               pPrev = tr * pPrev;
+                               for (int i = 0; i < nSegments; i++)
+                               {
+                                       fAngleInRadians = btScalar(2. * 3.1415926) * (btScalar)i / btScalar(nSegments);
+                                       btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
+                                       pCur = tr * pCur;
+                                       getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0, 0, 0));
+
+                                       if (i % (nSegments / 8) == 0)
+                                               getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0, 0, 0));
+
+                                       pPrev = pCur;
+                               }
+                               btScalar tws = pCT->getTwistSpan();
+                               btScalar twa = pCT->getTwistAngle();
+                               bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
+                               if (useFrameB)
+                               {
+                                       tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
+                               }
+                               else
+                               {
+                                       tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
+                               }
+                               btVector3 pivot = tr.getOrigin();
+                               btVector3 normal = tr.getBasis().getColumn(0);
+                               btVector3 axis1 = tr.getBasis().getColumn(1);
+                               getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa - tws, -twa + tws, btVector3(0, 0, 0), true);
+                       }
+               }
+               break;
+               case D6_SPRING_CONSTRAINT_TYPE:
+               case D6_CONSTRAINT_TYPE:
+               {
+                       btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint;
+                       btTransform tr = p6DOF->getCalculatedTransformA();
+                       if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                       tr = p6DOF->getCalculatedTransformB();
+                       if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                       if (drawLimits)
+                       {
+                               tr = p6DOF->getCalculatedTransformA();
+                               const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
+                               btVector3 up = tr.getBasis().getColumn(2);
+                               btVector3 axis = tr.getBasis().getColumn(0);
+                               btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
+                               btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
+                               btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
+                               btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
+                               getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0, 0, 0));
+                               axis = tr.getBasis().getColumn(1);
+                               btScalar ay = p6DOF->getAngle(1);
+                               btScalar az = p6DOF->getAngle(2);
+                               btScalar cy = btCos(ay);
+                               btScalar sy = btSin(ay);
+                               btScalar cz = btCos(az);
+                               btScalar sz = btSin(az);
+                               btVector3 ref;
+                               ref[0] = cy * cz * axis[0] + cy * sz * axis[1] - sy * axis[2];
+                               ref[1] = -sz * axis[0] + cz * axis[1];
+                               ref[2] = cz * sy * axis[0] + sz * sy * axis[1] + cy * axis[2];
+                               tr = p6DOF->getCalculatedTransformB();
+                               btVector3 normal = -tr.getBasis().getColumn(0);
+                               btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
+                               btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
+                               if (minFi > maxFi)
+                               {
+                                       getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0, 0, 0), false);
+                               }
+                               else if (minFi < maxFi)
+                               {
+                                       getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0, 0, 0), true);
+                               }
+                               tr = p6DOF->getCalculatedTransformA();
+                               btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
+                               btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
+                               getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0, 0, 0));
+                       }
+               }
+               break;
+               ///note: the code for D6_SPRING_2_CONSTRAINT_TYPE is identical to D6_CONSTRAINT_TYPE, the D6_CONSTRAINT_TYPE+D6_SPRING_CONSTRAINT_TYPE will likely become obsolete/deprecated at some stage
+               case D6_SPRING_2_CONSTRAINT_TYPE:
+               {
+                       {
+                               btGeneric6DofSpring2Constraint* p6DOF = (btGeneric6DofSpring2Constraint*)constraint;
+                               btTransform tr = p6DOF->getCalculatedTransformA();
+                               if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                               tr = p6DOF->getCalculatedTransformB();
+                               if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                               if (drawLimits)
+                               {
+                                       tr = p6DOF->getCalculatedTransformA();
+                                       const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
+                                       btVector3 up = tr.getBasis().getColumn(2);
+                                       btVector3 axis = tr.getBasis().getColumn(0);
+                                       btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
+                                       btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
+                                       if (minTh <= maxTh)
+                                       {
+                                               btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
+                                               btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
+                                               getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0, 0, 0));
+                                       }
+                                       axis = tr.getBasis().getColumn(1);
+                                       btScalar ay = p6DOF->getAngle(1);
+                                       btScalar az = p6DOF->getAngle(2);
+                                       btScalar cy = btCos(ay);
+                                       btScalar sy = btSin(ay);
+                                       btScalar cz = btCos(az);
+                                       btScalar sz = btSin(az);
+                                       btVector3 ref;
+                                       ref[0] = cy * cz * axis[0] + cy * sz * axis[1] - sy * axis[2];
+                                       ref[1] = -sz * axis[0] + cz * axis[1];
+                                       ref[2] = cz * sy * axis[0] + sz * sy * axis[1] + cy * axis[2];
+                                       tr = p6DOF->getCalculatedTransformB();
+                                       btVector3 normal = -tr.getBasis().getColumn(0);
+                                       btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
+                                       btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
+                                       if (minFi > maxFi)
+                                       {
+                                               getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0, 0, 0), false);
+                                       }
+                                       else if (minFi < maxFi)
+                                       {
+                                               getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0, 0, 0), true);
+                                       }
+                                       tr = p6DOF->getCalculatedTransformA();
+                                       btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
+                                       btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
+                                       getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0, 0, 0));
+                               }
+                       }
+                       break;
+               }
+               case SLIDER_CONSTRAINT_TYPE:
+               {
+                       btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
+                       btTransform tr = pSlider->getCalculatedTransformA();
+                       if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                       tr = pSlider->getCalculatedTransformB();
+                       if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+                       if (drawLimits)
+                       {
+                               btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB();
+                               btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
+                               btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
+                               getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
+                               btVector3 normal = tr.getBasis().getColumn(0);
+                               btVector3 axis = tr.getBasis().getColumn(1);
+                               btScalar a_min = pSlider->getLowerAngLimit();
+                               btScalar a_max = pSlider->getUpperAngLimit();
+                               const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
+                               getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0, 0, 0), true);
+                       }
+               }
+               break;
+               default:
+                       break;
+       }
+       return;
+}
+
+void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+{
+       if (m_ownsConstraintSolver)
+       {
+               btAlignedFree(m_constraintSolver);
+       }
+       m_ownsConstraintSolver = false;
+       m_constraintSolver = solver;
+       m_solverIslandCallback->m_solver = solver;
+}
+
+btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver()
+{
+       return m_constraintSolver;
+}
+
+int btDiscreteDynamicsWorld::getNumConstraints() const
+{
+       return int(m_constraints.size());
+}
+btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index)
+{
+       return m_constraints[index];
+}
+const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const
+{
+       return m_constraints[index];
+}
+
+void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
+{
+       int i;
+       //serialize all collision objects
+       for (i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
+               {
+                       int len = colObj->calculateSerializeBufferSize();
+                       btChunk* chunk = serializer->allocate(len, 1);
+                       const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
+                       serializer->finalizeChunk(chunk, structType, BT_RIGIDBODY_CODE, colObj);
+               }
+       }
+
+       for (i = 0; i < m_constraints.size(); i++)
+       {
+               btTypedConstraint* constraint = m_constraints[i];
+               int size = constraint->calculateSerializeBufferSize();
+               btChunk* chunk = serializer->allocate(size, 1);
+               const char* structType = constraint->serialize(chunk->m_oldPtr, serializer);
+               serializer->finalizeChunk(chunk, structType, BT_CONSTRAINT_CODE, constraint);
+       }
+}
+
+void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serializer)
+{
+#ifdef BT_USE_DOUBLE_PRECISION
+       int len = sizeof(btDynamicsWorldDoubleData);
+       btChunk* chunk = serializer->allocate(len, 1);
+       btDynamicsWorldDoubleData* worldInfo = (btDynamicsWorldDoubleData*)chunk->m_oldPtr;
+#else   //BT_USE_DOUBLE_PRECISION
+       int len = sizeof(btDynamicsWorldFloatData);
+       btChunk* chunk = serializer->allocate(len, 1);
+       btDynamicsWorldFloatData* worldInfo = (btDynamicsWorldFloatData*)chunk->m_oldPtr;
+#endif  //BT_USE_DOUBLE_PRECISION
+
+       memset(worldInfo, 0x00, len);
+
+       m_gravity.serialize(worldInfo->m_gravity);
+       worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau;
+       worldInfo->m_solverInfo.m_damping = getSolverInfo().m_damping;
+       worldInfo->m_solverInfo.m_friction = getSolverInfo().m_friction;
+       worldInfo->m_solverInfo.m_timeStep = getSolverInfo().m_timeStep;
+
+       worldInfo->m_solverInfo.m_restitution = getSolverInfo().m_restitution;
+       worldInfo->m_solverInfo.m_maxErrorReduction = getSolverInfo().m_maxErrorReduction;
+       worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor;
+       worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp;
+
+       worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2;
+       worldInfo->m_solverInfo.m_globalCfm = getSolverInfo().m_globalCfm;
+       worldInfo->m_solverInfo.m_splitImpulsePenetrationThreshold = getSolverInfo().m_splitImpulsePenetrationThreshold;
+       worldInfo->m_solverInfo.m_splitImpulseTurnErp = getSolverInfo().m_splitImpulseTurnErp;
+
+       worldInfo->m_solverInfo.m_linearSlop = getSolverInfo().m_linearSlop;
+       worldInfo->m_solverInfo.m_warmstartingFactor = getSolverInfo().m_warmstartingFactor;
+       worldInfo->m_solverInfo.m_maxGyroscopicForce = getSolverInfo().m_maxGyroscopicForce;
+       worldInfo->m_solverInfo.m_singleAxisRollingFrictionThreshold = getSolverInfo().m_singleAxisRollingFrictionThreshold;
+
+       worldInfo->m_solverInfo.m_numIterations = getSolverInfo().m_numIterations;
+       worldInfo->m_solverInfo.m_solverMode = getSolverInfo().m_solverMode;
+       worldInfo->m_solverInfo.m_restingContactRestitutionThreshold = getSolverInfo().m_restingContactRestitutionThreshold;
+       worldInfo->m_solverInfo.m_minimumSolverBatchSize = getSolverInfo().m_minimumSolverBatchSize;
+
+       worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
+
+       
+#ifdef BT_USE_DOUBLE_PRECISION
+       const char* structType = "btDynamicsWorldDoubleData";
+#else   //BT_USE_DOUBLE_PRECISION
+       const char* structType = "btDynamicsWorldFloatData";
+#endif  //BT_USE_DOUBLE_PRECISION
+       serializer->finalizeChunk(chunk, structType, BT_DYNAMICSWORLD_CODE, worldInfo);
+}
+
+void btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
+{
+       serializer->startSerialization();
+
+       serializeDynamicsWorldInfo(serializer);
+
+       serializeCollisionObjects(serializer);
+
+       serializeRigidBodies(serializer);
+
+       serializeContactManifolds(serializer);
+
+       serializer->finishSerialization();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
new file mode 100644 (file)
index 0000000..73607c6
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DISCRETE_DYNAMICS_WORLD_H
+#define BT_DISCRETE_DYNAMICS_WORLD_H
+
+#include "btDynamicsWorld.h"
+class btDispatcher;
+class btOverlappingPairCache;
+class btConstraintSolver;
+class btSimulationIslandManager;
+class btTypedConstraint;
+class btActionInterface;
+class btPersistentManifold;
+class btIDebugDraw;
+
+struct InplaceSolverIslandCallback;
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btThreads.h"
+
+///btDiscreteDynamicsWorld provides discrete rigid body simulation
+///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
+ATTRIBUTE_ALIGNED16(class)
+btDiscreteDynamicsWorld : public btDynamicsWorld
+{
+protected:
+       btAlignedObjectArray<btTypedConstraint*> m_sortedConstraints;
+       InplaceSolverIslandCallback* m_solverIslandCallback;
+
+       btConstraintSolver* m_constraintSolver;
+
+       btSimulationIslandManager* m_islandManager;
+
+       btAlignedObjectArray<btTypedConstraint*> m_constraints;
+
+       btAlignedObjectArray<btRigidBody*> m_nonStaticRigidBodies;
+
+       btVector3 m_gravity;
+
+       //for variable timesteps
+       btScalar m_localTime;
+       btScalar m_fixedTimeStep;
+       //for variable timesteps
+
+       bool m_ownsIslandManager;
+       bool m_ownsConstraintSolver;
+       bool m_synchronizeAllMotionStates;
+       bool m_applySpeculativeContactRestitution;
+
+       btAlignedObjectArray<btActionInterface*> m_actions;
+
+       int m_profileTimings;
+
+       bool m_latencyMotionStateInterpolation;
+
+       btAlignedObjectArray<btPersistentManifold*> m_predictiveManifolds;
+       btSpinMutex m_predictiveManifoldsMutex;  // used to synchronize threads creating predictive contacts
+
+       virtual void predictUnconstraintMotion(btScalar timeStep);
+
+       void integrateTransformsInternal(btRigidBody * *bodies, int numBodies, btScalar timeStep);  // can be called in parallel
+       virtual void integrateTransforms(btScalar timeStep);
+
+       virtual void calculateSimulationIslands();
+
+       
+
+       virtual void updateActivationState(btScalar timeStep);
+
+       void updateActions(btScalar timeStep);
+
+       void startProfiling(btScalar timeStep);
+
+       virtual void internalSingleStepSimulation(btScalar timeStep);
+
+       void releasePredictiveContacts();
+       void createPredictiveContactsInternal(btRigidBody * *bodies, int numBodies, btScalar timeStep);  // can be called in parallel
+       virtual void createPredictiveContacts(btScalar timeStep);
+
+       virtual void saveKinematicState(btScalar timeStep);
+
+       void serializeRigidBodies(btSerializer * serializer);
+
+       void serializeDynamicsWorldInfo(btSerializer * serializer);
+    
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
+       btDiscreteDynamicsWorld(btDispatcher * dispatcher, btBroadphaseInterface * pairCache, btConstraintSolver * constraintSolver, btCollisionConfiguration * collisionConfiguration);
+
+       virtual ~btDiscreteDynamicsWorld();
+
+       ///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
+       virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
+
+    virtual void solveConstraints(btContactSolverInfo & solverInfo);
+    
+       virtual void synchronizeMotionStates();
+
+       ///this can be useful to synchronize a single rigid body -> graphics object
+       void synchronizeSingleMotionState(btRigidBody * body);
+
+       virtual void addConstraint(btTypedConstraint * constraint, bool disableCollisionsBetweenLinkedBodies = false);
+
+       virtual void removeConstraint(btTypedConstraint * constraint);
+
+       virtual void addAction(btActionInterface*);
+
+       virtual void removeAction(btActionInterface*);
+
+       btSimulationIslandManager* getSimulationIslandManager()
+       {
+               return m_islandManager;
+       }
+
+       const btSimulationIslandManager* getSimulationIslandManager() const
+       {
+               return m_islandManager;
+       }
+
+       btCollisionWorld* getCollisionWorld()
+       {
+               return this;
+       }
+
+       virtual void setGravity(const btVector3& gravity);
+
+       virtual btVector3 getGravity() const;
+
+       virtual void addCollisionObject(btCollisionObject * collisionObject, int collisionFilterGroup = btBroadphaseProxy::StaticFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+
+       virtual void addRigidBody(btRigidBody * body);
+
+       virtual void addRigidBody(btRigidBody * body, int group, int mask);
+
+       virtual void removeRigidBody(btRigidBody * body);
+
+       ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
+       virtual void removeCollisionObject(btCollisionObject * collisionObject);
+
+       virtual void debugDrawConstraint(btTypedConstraint * constraint);
+
+       virtual void debugDrawWorld();
+
+       virtual void setConstraintSolver(btConstraintSolver * solver);
+
+       virtual btConstraintSolver* getConstraintSolver();
+
+       virtual int getNumConstraints() const;
+
+       virtual btTypedConstraint* getConstraint(int index);
+
+       virtual const btTypedConstraint* getConstraint(int index) const;
+
+       virtual btDynamicsWorldType getWorldType() const
+       {
+               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)
+       {
+               (void)numTasks;
+       }
+
+       ///obsolete, use updateActions instead
+       virtual void updateVehicles(btScalar timeStep)
+       {
+               updateActions(timeStep);
+       }
+
+       ///obsolete, use addAction instead
+       virtual void addVehicle(btActionInterface * vehicle);
+       ///obsolete, use removeAction instead
+       virtual void removeVehicle(btActionInterface * vehicle);
+       ///obsolete, use addAction instead
+       virtual void addCharacter(btActionInterface * character);
+       ///obsolete, use removeAction instead
+       virtual void removeCharacter(btActionInterface * character);
+
+       void setSynchronizeAllMotionStates(bool synchronizeAll)
+       {
+               m_synchronizeAllMotionStates = synchronizeAll;
+       }
+       bool getSynchronizeAllMotionStates() const
+       {
+               return m_synchronizeAllMotionStates;
+       }
+
+       void setApplySpeculativeContactRestitution(bool enable)
+       {
+               m_applySpeculativeContactRestitution = enable;
+       }
+
+       bool getApplySpeculativeContactRestitution() const
+       {
+               return m_applySpeculativeContactRestitution;
+       }
+
+       ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo)
+       virtual void serialize(btSerializer * serializer);
+
+       ///Interpolate motion state between previous and current transform, instead of current and next transform.
+       ///This can relieve discontinuities in the rendering, due to penetrations
+       void setLatencyMotionStateInterpolation(bool latencyInterpolation)
+       {
+               m_latencyMotionStateInterpolation = latencyInterpolation;
+       }
+       bool getLatencyMotionStateInterpolation() const
+       {
+               return m_latencyMotionStateInterpolation;
+       }
+    
+    btAlignedObjectArray<btRigidBody*>& getNonStaticRigidBodies()
+    {
+        return m_nonStaticRigidBodies;
+    }
+    
+    const btAlignedObjectArray<btRigidBody*>& getNonStaticRigidBodies() const
+    {
+        return m_nonStaticRigidBodies;
+    }
+};
+
+#endif  //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp
new file mode 100644 (file)
index 0000000..8207b47
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btDiscreteDynamicsWorldMt.h"
+
+//collision detection
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "btSimulationIslandManagerMt.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btQuickprof.h"
+
+//rigidbody & constraints
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
+
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btMotionState.h"
+
+#include "LinearMath/btSerializer.h"
+
+///
+/// btConstraintSolverPoolMt
+///
+
+btConstraintSolverPoolMt::ThreadSolver* btConstraintSolverPoolMt::getAndLockThreadSolver()
+{
+       int i = 0;
+#if BT_THREADSAFE
+       i = btGetCurrentThreadIndex() % m_solvers.size();
+#endif  // #if BT_THREADSAFE
+       while (true)
+       {
+               ThreadSolver& solver = m_solvers[i];
+               if (solver.mutex.tryLock())
+               {
+                       return &solver;
+               }
+               // failed, try the next one
+               i = (i + 1) % m_solvers.size();
+       }
+       return NULL;
+}
+
+void btConstraintSolverPoolMt::init(btConstraintSolver** solvers, int numSolvers)
+{
+       m_solverType = BT_SEQUENTIAL_IMPULSE_SOLVER;
+       m_solvers.resize(numSolvers);
+       for (int i = 0; i < numSolvers; ++i)
+       {
+               m_solvers[i].solver = solvers[i];
+       }
+       if (numSolvers > 0)
+       {
+               m_solverType = solvers[0]->getSolverType();
+       }
+}
+
+// create the solvers for me
+btConstraintSolverPoolMt::btConstraintSolverPoolMt(int numSolvers)
+{
+       btAlignedObjectArray<btConstraintSolver*> solvers;
+       solvers.reserve(numSolvers);
+       for (int i = 0; i < numSolvers; ++i)
+       {
+               btConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
+               solvers.push_back(solver);
+       }
+       init(&solvers[0], numSolvers);
+}
+
+// pass in fully constructed solvers (destructor will delete them)
+btConstraintSolverPoolMt::btConstraintSolverPoolMt(btConstraintSolver** solvers, int numSolvers)
+{
+       init(solvers, numSolvers);
+}
+
+btConstraintSolverPoolMt::~btConstraintSolverPoolMt()
+{
+       // delete all solvers
+       for (int i = 0; i < m_solvers.size(); ++i)
+       {
+               ThreadSolver& solver = m_solvers[i];
+               delete solver.solver;
+               solver.solver = NULL;
+       }
+}
+
+///solve a group of constraints
+btScalar btConstraintSolverPoolMt::solveGroup(btCollisionObject** bodies,
+                                                                                         int numBodies,
+                                                                                         btPersistentManifold** manifolds,
+                                                                                         int numManifolds,
+                                                                                         btTypedConstraint** constraints,
+                                                                                         int numConstraints,
+                                                                                         const btContactSolverInfo& info,
+                                                                                         btIDebugDraw* debugDrawer,
+                                                                                         btDispatcher* dispatcher)
+{
+       ThreadSolver* ts = getAndLockThreadSolver();
+       ts->solver->solveGroup(bodies, numBodies, manifolds, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
+       ts->mutex.unlock();
+       return 0.0f;
+}
+
+void btConstraintSolverPoolMt::reset()
+{
+       for (int i = 0; i < m_solvers.size(); ++i)
+       {
+               ThreadSolver& solver = m_solvers[i];
+               solver.mutex.lock();
+               solver.solver->reset();
+               solver.mutex.unlock();
+       }
+}
+
+///
+/// btDiscreteDynamicsWorldMt
+///
+
+btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,
+                                                                                                        btBroadphaseInterface* pairCache,
+                                                                                                        btConstraintSolverPoolMt* solverPool,
+                                                                                                        btConstraintSolver* constraintSolverMt,
+                                                                                                        btCollisionConfiguration* collisionConfiguration)
+       : btDiscreteDynamicsWorld(dispatcher, pairCache, solverPool, collisionConfiguration)
+{
+       if (m_ownsIslandManager)
+       {
+               m_islandManager->~btSimulationIslandManager();
+               btAlignedFree(m_islandManager);
+       }
+       {
+               void* mem = btAlignedAlloc(sizeof(btSimulationIslandManagerMt), 16);
+               btSimulationIslandManagerMt* im = new (mem) btSimulationIslandManagerMt();
+               im->setMinimumSolverBatchSize(m_solverInfo.m_minimumSolverBatchSize);
+               m_islandManager = im;
+       }
+       m_constraintSolverMt = constraintSolverMt;
+}
+
+btDiscreteDynamicsWorldMt::~btDiscreteDynamicsWorldMt()
+{
+}
+
+void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo)
+{
+       BT_PROFILE("solveConstraints");
+
+       m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+
+       /// solve all the constraints for this island
+       btSimulationIslandManagerMt* im = static_cast<btSimulationIslandManagerMt*>(m_islandManager);
+       btSimulationIslandManagerMt::SolverParams solverParams;
+       solverParams.m_solverPool = m_constraintSolver;
+       solverParams.m_solverMt = m_constraintSolverMt;
+       solverParams.m_solverInfo = &solverInfo;
+       solverParams.m_debugDrawer = m_debugDrawer;
+       solverParams.m_dispatcher = getCollisionWorld()->getDispatcher();
+       im->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_constraints, solverParams);
+
+       m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
+}
+
+struct UpdaterUnconstrainedMotion : public btIParallelForBody
+{
+       btScalar timeStep;
+       btRigidBody** rigidBodies;
+
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               for (int i = iBegin; i < iEnd; ++i)
+               {
+                       btRigidBody* body = rigidBodies[i];
+                       if (!body->isStaticOrKinematicObject())
+                       {
+                               //don't integrate/update velocities here, it happens in the constraint solver
+                               body->applyDamping(timeStep);
+                               body->predictIntegratedTransform(timeStep, body->getInterpolationWorldTransform());
+                       }
+               }
+       }
+};
+
+void btDiscreteDynamicsWorldMt::predictUnconstraintMotion(btScalar timeStep)
+{
+       BT_PROFILE("predictUnconstraintMotion");
+       if (m_nonStaticRigidBodies.size() > 0)
+       {
+               UpdaterUnconstrainedMotion update;
+               update.timeStep = timeStep;
+               update.rigidBodies = &m_nonStaticRigidBodies[0];
+               int grainSize = 50;  // num of iterations per task for task scheduler
+               btParallelFor(0, m_nonStaticRigidBodies.size(), grainSize, update);
+       }
+}
+
+void btDiscreteDynamicsWorldMt::createPredictiveContacts(btScalar timeStep)
+{
+       BT_PROFILE("createPredictiveContacts");
+       releasePredictiveContacts();
+       if (m_nonStaticRigidBodies.size() > 0)
+       {
+               UpdaterCreatePredictiveContacts update;
+               update.world = this;
+               update.timeStep = timeStep;
+               update.rigidBodies = &m_nonStaticRigidBodies[0];
+               int grainSize = 50;  // num of iterations per task for task scheduler
+               btParallelFor(0, m_nonStaticRigidBodies.size(), grainSize, update);
+       }
+}
+
+void btDiscreteDynamicsWorldMt::integrateTransforms(btScalar timeStep)
+{
+       BT_PROFILE("integrateTransforms");
+       if (m_nonStaticRigidBodies.size() > 0)
+       {
+               UpdaterIntegrateTransforms update;
+               update.world = this;
+               update.timeStep = timeStep;
+               update.rigidBodies = &m_nonStaticRigidBodies[0];
+               int grainSize = 50;  // num of iterations per task for task scheduler
+               btParallelFor(0, m_nonStaticRigidBodies.size(), grainSize, update);
+       }
+}
+
+int btDiscreteDynamicsWorldMt::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
+{
+       int numSubSteps = btDiscreteDynamicsWorld::stepSimulation(timeStep, maxSubSteps, fixedTimeStep);
+       if (btITaskScheduler* scheduler = btGetTaskScheduler())
+       {
+               // tell Bullet's threads to sleep, so other threads can run
+               scheduler->sleepWorkerThreadsHint();
+       }
+       return numSubSteps;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h
new file mode 100644 (file)
index 0000000..dccf35d
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DISCRETE_DYNAMICS_WORLD_MT_H
+#define BT_DISCRETE_DYNAMICS_WORLD_MT_H
+
+#include "btDiscreteDynamicsWorld.h"
+#include "btSimulationIslandManagerMt.h"
+#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
+
+///
+/// btConstraintSolverPoolMt - masquerades as a constraint solver, but really it is a threadsafe pool of them.
+///
+///  Each solver in the pool is protected by a mutex.  When solveGroup is called from a thread,
+///  the pool looks for a solver that isn't being used by another thread, locks it, and dispatches the
+///  call to the solver.
+///  So long as there are at least as many solvers as there are hardware threads, it should never need to
+///  spin wait.
+///
+class btConstraintSolverPoolMt : public btConstraintSolver
+{
+public:
+       // create the solvers for me
+       explicit btConstraintSolverPoolMt(int numSolvers);
+
+       // pass in fully constructed solvers (destructor will delete them)
+       btConstraintSolverPoolMt(btConstraintSolver** solvers, int numSolvers);
+
+       virtual ~btConstraintSolverPoolMt();
+
+       ///solve a group of constraints
+       virtual btScalar solveGroup(btCollisionObject** bodies,
+                                                               int numBodies,
+                                                               btPersistentManifold** manifolds,
+                                                               int numManifolds,
+                                                               btTypedConstraint** constraints,
+                                                               int numConstraints,
+                                                               const btContactSolverInfo& info,
+                                                               btIDebugDraw* debugDrawer,
+                                                               btDispatcher* dispatcher) BT_OVERRIDE;
+
+       virtual void reset() BT_OVERRIDE;
+       virtual btConstraintSolverType getSolverType() const BT_OVERRIDE { return m_solverType; }
+
+private:
+       const static size_t kCacheLineSize = 128;
+       struct ThreadSolver
+       {
+               btConstraintSolver* solver;
+               btSpinMutex mutex;
+               char _cachelinePadding[kCacheLineSize - sizeof(btSpinMutex) - sizeof(void*)];  // keep mutexes from sharing a cache line
+       };
+       btAlignedObjectArray<ThreadSolver> m_solvers;
+       btConstraintSolverType m_solverType;
+
+       ThreadSolver* getAndLockThreadSolver();
+       void init(btConstraintSolver** solvers, int numSolvers);
+};
+
+///
+/// btDiscreteDynamicsWorldMt -- a version of DiscreteDynamicsWorld with some minor changes to support
+///                              solving simulation islands on multiple threads.
+///
+///  Should function exactly like btDiscreteDynamicsWorld.
+///  Also 3 methods that iterate over all of the rigidbodies can run in parallel:
+///     - predictUnconstraintMotion
+///     - integrateTransforms
+///     - createPredictiveContacts
+///
+ATTRIBUTE_ALIGNED16(class)
+btDiscreteDynamicsWorldMt : public btDiscreteDynamicsWorld
+{
+protected:
+       btConstraintSolver* m_constraintSolverMt;
+
+       virtual void solveConstraints(btContactSolverInfo & solverInfo) BT_OVERRIDE;
+
+       virtual void predictUnconstraintMotion(btScalar timeStep) BT_OVERRIDE;
+
+       struct UpdaterCreatePredictiveContacts : public btIParallelForBody
+       {
+               btScalar timeStep;
+               btRigidBody** rigidBodies;
+               btDiscreteDynamicsWorldMt* world;
+
+               void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+               {
+                       world->createPredictiveContactsInternal(&rigidBodies[iBegin], iEnd - iBegin, timeStep);
+               }
+       };
+       virtual void createPredictiveContacts(btScalar timeStep) BT_OVERRIDE;
+
+       struct UpdaterIntegrateTransforms : public btIParallelForBody
+       {
+               btScalar timeStep;
+               btRigidBody** rigidBodies;
+               btDiscreteDynamicsWorldMt* world;
+
+               void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+               {
+                       world->integrateTransformsInternal(&rigidBodies[iBegin], iEnd - iBegin, timeStep);
+               }
+       };
+       virtual void integrateTransforms(btScalar timeStep) BT_OVERRIDE;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btDiscreteDynamicsWorldMt(btDispatcher * dispatcher,
+                                                         btBroadphaseInterface * pairCache,
+                                                         btConstraintSolverPoolMt * solverPool,        // Note this should be a solver-pool for multi-threading
+                                                         btConstraintSolver * constraintSolverMt,      // single multi-threaded solver for large islands (or NULL)
+                                                         btCollisionConfiguration * collisionConfiguration);
+       virtual ~btDiscreteDynamicsWorldMt();
+
+       virtual int stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep) BT_OVERRIDE;
+};
+
+#endif  //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btDynamicsWorld.h
new file mode 100644 (file)
index 0000000..a5a4411
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DYNAMICS_WORLD_H
+#define BT_DYNAMICS_WORLD_H
+
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+class btTypedConstraint;
+class btActionInterface;
+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,
+       BT_SOFT_RIGID_DYNAMICS_WORLD = 4,
+       BT_GPU_DYNAMICS_WORLD = 5,
+       BT_SOFT_MULTIBODY_DYNAMICS_WORLD = 6,
+    BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD = 7
+};
+
+///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
+class btDynamicsWorld : public btCollisionWorld
+{
+protected:
+       btInternalTickCallback m_internalTickCallback;
+       btInternalTickCallback m_internalPreTickCallback;
+       void* m_worldUserInfo;
+
+       btContactSolverInfo m_solverInfo;
+
+public:
+       btDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* broadphase, btCollisionConfiguration* collisionConfiguration)
+               : btCollisionWorld(dispatcher, broadphase, collisionConfiguration), m_internalTickCallback(0), m_internalPreTickCallback(0), m_worldUserInfo(0)
+       {
+       }
+
+       virtual ~btDynamicsWorld()
+       {
+       }
+
+       ///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 = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.)) = 0;
+
+       virtual void debugDrawWorld() = 0;
+
+       virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies = false)
+       {
+               (void)constraint;
+               (void)disableCollisionsBetweenLinkedBodies;
+       }
+
+       virtual void removeConstraint(btTypedConstraint* constraint) { (void)constraint; }
+
+       virtual void addAction(btActionInterface* action) = 0;
+
+       virtual void removeAction(btActionInterface* action) = 0;
+
+       //once a rigidbody is added to the dynamics world, it will get this gravity assigned
+       //existing rigidbodies in the world get gravity assigned too, during this method
+       virtual void setGravity(const btVector3& gravity) = 0;
+       virtual btVector3 getGravity() const = 0;
+
+       virtual void synchronizeMotionStates() = 0;
+
+       virtual void addRigidBody(btRigidBody* body) = 0;
+
+       virtual void addRigidBody(btRigidBody* body, int group, int mask) = 0;
+
+       virtual void removeRigidBody(btRigidBody* body) = 0;
+
+       virtual void setConstraintSolver(btConstraintSolver* solver) = 0;
+
+       virtual btConstraintSolver* getConstraintSolver() = 0;
+
+       virtual int getNumConstraints() const { return 0; }
+
+       virtual btTypedConstraint* getConstraint(int index)
+       {
+               (void)index;
+               return 0;
+       }
+
+       virtual const btTypedConstraint* getConstraint(int index) const
+       {
+               (void)index;
+               return 0;
+       }
+
+       virtual btDynamicsWorldType getWorldType() const = 0;
+
+       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, bool isPreTick = false)
+       {
+               if (isPreTick)
+               {
+                       m_internalPreTickCallback = cb;
+               }
+               else
+               {
+                       m_internalTickCallback = cb;
+               }
+               m_worldUserInfo = worldUserInfo;
+       }
+
+       void setWorldUserInfo(void* worldUserInfo)
+       {
+               m_worldUserInfo = worldUserInfo;
+       }
+
+       void* getWorldUserInfo() const
+       {
+               return m_worldUserInfo;
+       }
+
+       btContactSolverInfo& getSolverInfo()
+       {
+               return m_solverInfo;
+       }
+
+       const btContactSolverInfo& getSolverInfo() const
+       {
+               return m_solverInfo;
+       }
+
+       ///obsolete, use addAction instead.
+       virtual void addVehicle(btActionInterface* vehicle) { (void)vehicle; }
+       ///obsolete, use removeAction instead
+       virtual void removeVehicle(btActionInterface* vehicle) { (void)vehicle; }
+       ///obsolete, use addAction instead.
+       virtual void addCharacter(btActionInterface* character) { (void)character; }
+       ///obsolete, use removeAction instead
+       virtual void removeCharacter(btActionInterface* character) { (void)character; }
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btDynamicsWorldDoubleData
+{
+       btContactSolverInfoDoubleData m_solverInfo;
+       btVector3DoubleData m_gravity;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btDynamicsWorldFloatData
+{
+       btContactSolverInfoFloatData m_solverInfo;
+       btVector3FloatData m_gravity;
+};
+
+#endif  //BT_DYNAMICS_WORLD_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btRigidBody.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btRigidBody.cpp
new file mode 100644 (file)
index 0000000..bf7224b
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btRigidBody.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMotionState.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "LinearMath/btSerializer.h"
+
+//'temporarily' global variables
+btScalar gDeactivationTime = btScalar(2.);
+bool gDisableDeactivation = false;
+static int uniqueId = 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)
+{
+       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.setValue(1, 1, 1);
+       m_linearFactor.setValue(1, 1, 1);
+       m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+       m_gravity_acceleration.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)),
+               setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
+
+       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)
+       {
+               m_optionalMotionState->getWorldTransform(m_worldTransform);
+       }
+       else
+       {
+               m_worldTransform = constructionInfo.m_startWorldTransform;
+       }
+
+       m_interpolationWorldTransform = m_worldTransform;
+       m_interpolationLinearVelocity.setValue(0, 0, 0);
+       m_interpolationAngularVelocity.setValue(0, 0, 0);
+
+       //moved to btCollisionObject
+       m_friction = constructionInfo.m_friction;
+       m_rollingFriction = constructionInfo.m_rollingFriction;
+       m_spinningFriction = constructionInfo.m_spinningFriction;
+
+       m_restitution = constructionInfo.m_restitution;
+
+       setCollisionShape(constructionInfo.m_collisionShape);
+       m_debugBodyId = uniqueId++;
+
+       setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
+       updateInertiaTensor();
+
+       m_rigidbodyFlags = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY;
+
+       m_deltaLinearVelocity.setZero();
+       m_deltaAngularVelocity.setZero();
+       m_invMass = m_inverseMass * m_linearFactor;
+       m_pushVelocity.setZero();
+       m_turnVelocity.setZero();
+}
+
+void btRigidBody::predictIntegratedTransform(btScalar timeStep, btTransform& predictedTransform)
+{
+       btTransformUtil::integrateTransform(m_worldTransform, m_linearVelocity, m_angularVelocity, timeStep, predictedTransform);
+}
+
+void btRigidBody::saveKinematicState(btScalar timeStep)
+{
+       //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
+       if (timeStep != btScalar(0.))
+       {
+               //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform
+               if (getMotionState())
+                       getMotionState()->getWorldTransform(m_worldTransform);
+               btVector3 linVel, angVel;
+
+               btTransformUtil::calculateVelocity(m_interpolationWorldTransform, m_worldTransform, timeStep, m_linearVelocity, m_angularVelocity);
+               m_interpolationLinearVelocity = m_linearVelocity;
+               m_interpolationAngularVelocity = m_angularVelocity;
+               m_interpolationWorldTransform = m_worldTransform;
+               //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ());
+       }
+}
+
+void btRigidBody::getAabb(btVector3& aabbMin, btVector3& aabbMax) const
+{
+       getCollisionShape()->getAabb(m_worldTransform, aabbMin, aabbMax);
+}
+
+void btRigidBody::setGravity(const btVector3& acceleration)
+{
+       if (m_inverseMass != btScalar(0.0))
+       {
+               m_gravity = acceleration * (btScalar(1.0) / m_inverseMass);
+       }
+       m_gravity_acceleration = acceleration;
+}
+
+void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
+{
+#ifdef BT_USE_OLD_DAMPING_METHOD
+       m_linearDamping = btMax(lin_damping, btScalar(0.0));
+       m_angularDamping = btMax(ang_damping, btScalar(0.0));
+#else
+       m_linearDamping = btClamped(lin_damping, btScalar(0.0), btScalar(1.0));
+       m_angularDamping = btClamped(ang_damping, btScalar(0.0), btScalar(1.0));
+#endif
+}
+
+///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
+void btRigidBody::applyDamping(btScalar timeStep)
+{
+       //On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
+       //todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
+
+#ifdef BT_USE_OLD_DAMPING_METHOD
+       m_linearVelocity *= btMax((btScalar(1.0) - timeStep * m_linearDamping), btScalar(0.0));
+       m_angularVelocity *= btMax((btScalar(1.0) - timeStep * m_angularDamping), btScalar(0.0));
+#else
+       m_linearVelocity *= btPow(btScalar(1) - m_linearDamping, timeStep);
+       m_angularVelocity *= btPow(btScalar(1) - m_angularDamping, timeStep);
+#endif
+
+       if (m_additionalDamping)
+       {
+               //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))
+               {
+                       m_angularVelocity *= m_additionalDampingFactor;
+                       m_linearVelocity *= m_additionalDampingFactor;
+               }
+
+               btScalar speed = m_linearVelocity.length();
+               if (speed < m_linearDamping)
+               {
+                       btScalar dampVel = btScalar(0.005);
+                       if (speed > dampVel)
+                       {
+                               btVector3 dir = m_linearVelocity.normalized();
+                               m_linearVelocity -= dir * dampVel;
+                       }
+                       else
+                       {
+                               m_linearVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+                       }
+               }
+
+               btScalar angSpeed = m_angularVelocity.length();
+               if (angSpeed < m_angularDamping)
+               {
+                       btScalar angDampVel = btScalar(0.005);
+                       if (angSpeed > angDampVel)
+                       {
+                               btVector3 dir = m_angularVelocity.normalized();
+                               m_angularVelocity -= dir * angDampVel;
+                       }
+                       else
+                       {
+                               m_angularVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+                       }
+               }
+       }
+}
+
+void btRigidBody::applyGravity()
+{
+       if (isStaticOrKinematicObject())
+               return;
+
+       applyCentralForce(m_gravity);
+}
+
+void btRigidBody::clearGravity()
+{
+    if (isStaticOrKinematicObject())
+        return;
+    
+    applyCentralForce(-m_gravity);
+}
+
+void btRigidBody::proceedToTransform(const btTransform& newTrans)
+{
+       setCenterOfMassTransform(newTrans);
+}
+
+void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
+{
+       if (mass == btScalar(0.))
+       {
+               m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
+               m_inverseMass = btScalar(0.);
+       }
+       else
+       {
+               m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
+               m_inverseMass = btScalar(1.0) / mass;
+       }
+
+       //Fg = m * a
+       m_gravity = mass * m_gravity_acceleration;
+
+       m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x() : btScalar(0.0),
+                                                          inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0),
+                                                          inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0));
+
+       m_invMass = m_linearFactor * m_inverseMass;
+}
+
+void btRigidBody::updateInertiaTensor()
+{
+       m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose();
+}
+
+btVector3 btRigidBody::getLocalInertia() const
+{
+       btVector3 inertiaLocal;
+       const btVector3 inertia = m_invInertiaLocal;
+       inertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x() : btScalar(0.0),
+                                                 inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0),
+                                                 inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0));
+       return inertiaLocal;
+}
+
+inline btVector3 evalEulerEqn(const btVector3& w1, const btVector3& w0, const btVector3& T, const btScalar dt,
+                                                         const btMatrix3x3& I)
+{
+       const btVector3 w2 = I * w1 + w1.cross(I * w1) * dt - (T * dt + I * w0);
+       return w2;
+}
+
+inline btMatrix3x3 evalEulerEqnDeriv(const btVector3& w1, const btVector3& w0, const btScalar dt,
+                                                                        const btMatrix3x3& I)
+{
+       btMatrix3x3 w1x, Iw1x;
+       const btVector3 Iwi = (I * w1);
+       w1.getSkewSymmetricMatrix(&w1x[0], &w1x[1], &w1x[2]);
+       Iwi.getSkewSymmetricMatrix(&Iw1x[0], &Iw1x[1], &Iw1x[2]);
+
+       const btMatrix3x3 dfw1 = I + (w1x * I - Iw1x) * dt;
+       return dfw1;
+}
+
+btVector3 btRigidBody::computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const
+{
+       btVector3 inertiaLocal = getLocalInertia();
+       btMatrix3x3 inertiaTensorWorld = getWorldTransform().getBasis().scaled(inertiaLocal) * getWorldTransform().getBasis().transpose();
+       btVector3 tmp = inertiaTensorWorld * getAngularVelocity();
+       btVector3 gf = getAngularVelocity().cross(tmp);
+       btScalar l2 = gf.length2();
+       if (l2 > maxGyroscopicForce * maxGyroscopicForce)
+       {
+               gf *= btScalar(1.) / btSqrt(l2) * maxGyroscopicForce;
+       }
+       return gf;
+}
+
+btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Body(btScalar step) const
+{
+       btVector3 idl = getLocalInertia();
+       btVector3 omega1 = getAngularVelocity();
+       btQuaternion q = getWorldTransform().getRotation();
+
+       // Convert to body coordinates
+       btVector3 omegab = quatRotate(q.inverse(), omega1);
+       btMatrix3x3 Ib;
+       Ib.setValue(idl.x(), 0, 0,
+                               0, idl.y(), 0,
+                               0, 0, idl.z());
+
+       btVector3 ibo = Ib * omegab;
+
+       // Residual vector
+       btVector3 f = step * omegab.cross(ibo);
+
+       btMatrix3x3 skew0;
+       omegab.getSkewSymmetricMatrix(&skew0[0], &skew0[1], &skew0[2]);
+       btVector3 om = Ib * omegab;
+       btMatrix3x3 skew1;
+       om.getSkewSymmetricMatrix(&skew1[0], &skew1[1], &skew1[2]);
+
+       // Jacobian
+       btMatrix3x3 J = Ib + (skew0 * Ib - skew1) * step;
+
+       //      btMatrix3x3 Jinv = J.inverse();
+       //      btVector3 omega_div = Jinv*f;
+       btVector3 omega_div = J.solve33(f);
+
+       // Single Newton-Raphson update
+       omegab = omegab - omega_div;  //Solve33(J, f);
+       // Back to world coordinates
+       btVector3 omega2 = quatRotate(q, omegab);
+       btVector3 gf = omega2 - omega1;
+       return gf;
+}
+
+btVector3 btRigidBody::computeGyroscopicImpulseImplicit_World(btScalar step) const
+{
+       // use full newton-euler equations.  common practice to drop the wxIw term. want it for better tumbling behavior.
+       // calculate using implicit euler step so it's stable.
+
+       const btVector3 inertiaLocal = getLocalInertia();
+       const btVector3 w0 = getAngularVelocity();
+
+       btMatrix3x3 I;
+
+       I = m_worldTransform.getBasis().scaled(inertiaLocal) *
+               m_worldTransform.getBasis().transpose();
+
+       // use newtons method to find implicit solution for new angular velocity (w')
+       // f(w') = -(T*step + Iw) + Iw' + w' + w'xIw'*step = 0
+       // df/dw' = I + 1xIw'*step + w'xI*step
+
+       btVector3 w1 = w0;
+
+       // one step of newton's method
+       {
+               const btVector3 fw = evalEulerEqn(w1, w0, btVector3(0, 0, 0), step, I);
+               const btMatrix3x3 dfw = evalEulerEqnDeriv(w1, w0, step, I);
+
+               btVector3 dw;
+               dw = dfw.solve33(fw);
+               //const btMatrix3x3 dfw_inv = dfw.inverse();
+               //dw = dfw_inv*fw;
+
+               w1 -= dw;
+       }
+
+       btVector3 gf = (w1 - w0);
+       return gf;
+}
+
+void btRigidBody::integrateVelocities(btScalar step)
+{
+       if (isStaticOrKinematicObject())
+               return;
+
+       m_linearVelocity += m_totalForce * (m_inverseMass * step);
+       m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step;
+
+#define MAX_ANGVEL SIMD_HALF_PI
+       /// clamp angular velocity. collision calculations will fail on higher angular velocities
+       btScalar angvel = m_angularVelocity.length();
+       if (angvel * step > MAX_ANGVEL)
+       {
+               m_angularVelocity *= (MAX_ANGVEL / step) / angvel;
+       }
+       #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+       clampVelocity(m_angularVelocity);
+       #endif
+}
+
+btQuaternion btRigidBody::getOrientation() const
+{
+       btQuaternion orn;
+       m_worldTransform.getBasis().getRotation(orn);
+       return orn;
+}
+
+void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
+{
+       if (isKinematicObject())
+       {
+               m_interpolationWorldTransform = m_worldTransform;
+       }
+       else
+       {
+               m_interpolationWorldTransform = xform;
+       }
+       m_interpolationLinearVelocity = getLinearVelocity();
+       m_interpolationAngularVelocity = getAngularVelocity();
+       m_worldTransform = xform;
+       updateInertiaTensor();
+}
+
+void btRigidBody::addConstraintRef(btTypedConstraint* c)
+{
+       ///disable collision with the 'other' body
+
+       int index = m_constraintRefs.findLinearSearch(c);
+       //don't add constraints that are already referenced
+       //btAssert(index == m_constraintRefs.size());
+       if (index == m_constraintRefs.size())
+       {
+               m_constraintRefs.push_back(c);
+               btCollisionObject* colObjA = &c->getRigidBodyA();
+               btCollisionObject* colObjB = &c->getRigidBodyB();
+               if (colObjA == this)
+               {
+                       colObjA->setIgnoreCollisionCheck(colObjB, true);
+               }
+               else
+               {
+                       colObjB->setIgnoreCollisionCheck(colObjA, true);
+               }
+       }
+}
+
+void btRigidBody::removeConstraintRef(btTypedConstraint* c)
+{
+       int index = m_constraintRefs.findLinearSearch(c);
+       //don't remove constraints that are not referenced
+       if (index < m_constraintRefs.size())
+       {
+               m_constraintRefs.remove(c);
+               btCollisionObject* colObjA = &c->getRigidBodyA();
+               btCollisionObject* colObjB = &c->getRigidBodyB();
+               if (colObjA == this)
+               {
+                       colObjA->setIgnoreCollisionCheck(colObjB, false);
+               }
+               else
+               {
+                       colObjB->setIgnoreCollisionCheck(colObjA, false);
+               }
+       }
+}
+
+int btRigidBody::calculateSerializeBufferSize() const
+{
+       int sz = sizeof(btRigidBodyData);
+       return sz;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const
+{
+       btRigidBodyData* rbd = (btRigidBodyData*)dataBuffer;
+
+       btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer);
+
+       m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld);
+       m_linearVelocity.serialize(rbd->m_linearVelocity);
+       m_angularVelocity.serialize(rbd->m_angularVelocity);
+       rbd->m_inverseMass = m_inverseMass;
+       m_angularFactor.serialize(rbd->m_angularFactor);
+       m_linearFactor.serialize(rbd->m_linearFactor);
+       m_gravity.serialize(rbd->m_gravity);
+       m_gravity_acceleration.serialize(rbd->m_gravity_acceleration);
+       m_invInertiaLocal.serialize(rbd->m_invInertiaLocal);
+       m_totalForce.serialize(rbd->m_totalForce);
+       m_totalTorque.serialize(rbd->m_totalTorque);
+       rbd->m_linearDamping = m_linearDamping;
+       rbd->m_angularDamping = m_angularDamping;
+       rbd->m_additionalDamping = m_additionalDamping;
+       rbd->m_additionalDampingFactor = m_additionalDampingFactor;
+       rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr;
+       rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr;
+       rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor;
+       rbd->m_linearSleepingThreshold = m_linearSleepingThreshold;
+       rbd->m_angularSleepingThreshold = m_angularSleepingThreshold;
+
+       // Fill padding with zeros to appease msan.
+#ifdef BT_USE_DOUBLE_PRECISION
+       memset(rbd->m_padding, 0, sizeof(rbd->m_padding));
+#endif
+
+       return btRigidBodyDataName;
+}
+
+void btRigidBody::serializeSingleObject(class btSerializer* serializer) const
+{
+       btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(), 1);
+       const char* structType = serialize(chunk->m_oldPtr, serializer);
+       serializer->finalizeChunk(chunk, structType, BT_RIGIDBODY_CODE, (void*)this);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btRigidBody.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btRigidBody.h
new file mode 100644 (file)
index 0000000..00143ef
--- /dev/null
@@ -0,0 +1,687 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_RIGIDBODY_H
+#define BT_RIGIDBODY_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btTransform.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+class btCollisionShape;
+class btMotionState;
+class btTypedConstraint;
+
+extern btScalar gDeactivationTime;
+extern bool gDisableDeactivation;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btRigidBodyData btRigidBodyDoubleData
+#define btRigidBodyDataName "btRigidBodyDoubleData"
+#else
+#define btRigidBodyData btRigidBodyFloatData
+#define btRigidBodyDataName "btRigidBodyFloatData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+enum btRigidBodyFlags
+{
+       BT_DISABLE_WORLD_GRAVITY = 1,
+       ///BT_ENABLE_GYROPSCOPIC_FORCE flags is enabled by default in Bullet 2.83 and onwards.
+       ///and it BT_ENABLE_GYROPSCOPIC_FORCE becomes equivalent to BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY
+       ///See Demos/GyroscopicDemo and computeGyroscopicImpulseImplicit
+       BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT = 2,
+       BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD = 4,
+       BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY = 8,
+       BT_ENABLE_GYROPSCOPIC_FORCE = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY,
+};
+
+///The 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 one-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
+{
+       btMatrix3x3 m_invInertiaTensorWorld;
+       btVector3 m_linearVelocity;
+       btVector3 m_angularVelocity;
+       btScalar m_inverseMass;
+       btVector3 m_linearFactor;
+
+       btVector3 m_gravity;
+       btVector3 m_gravity_acceleration;
+       btVector3 m_invInertiaLocal;
+       btVector3 m_totalForce;
+       btVector3 m_totalTorque;
+
+       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;
+
+       //keep track of typed constraints referencing this rigid body, to disable collision between linked bodies
+       btAlignedObjectArray<btTypedConstraint*> m_constraintRefs;
+
+       int m_rigidbodyFlags;
+
+       int m_debugBodyId;
+
+protected:
+       ATTRIBUTE_ALIGNED16(btVector3 m_deltaLinearVelocity);
+       btVector3 m_deltaAngularVelocity;
+       btVector3 m_angularFactor;
+       btVector3 m_invMass;
+       btVector3 m_pushVelocity;
+       btVector3 m_turnVelocity;
+
+public:
+       ///The btRigidBodyConstructionInfo structure 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;
+               ///the m_rollingFriction prevents rounded shapes, such as spheres, cylinders and capsules from rolling forever.
+               ///See Bullet/Demos/RollingFrictionDemo for usage
+               btScalar m_rollingFriction;
+               btScalar m_spinningFriction;  //torsional friction around contact normal
+
+               ///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_rollingFriction(btScalar(0)),
+                                                                                                                                                                                                                                                                                                                                          m_spinningFriction(btScalar(0)),
+                                                                                                                                                                                                                                                                                                                                          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);
+
+       ///to keep collision detection and dynamics separate we don't store a rigidbody pointer
+       ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast
+       static const btRigidBody* upcast(const btCollisionObject* colObj)
+       {
+               if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
+                       return (const btRigidBody*)colObj;
+               return 0;
+       }
+       static btRigidBody* upcast(btCollisionObject* colObj)
+       {
+               if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
+                       return (btRigidBody*)colObj;
+               return 0;
+       }
+
+       /// continuous collision detection needs prediction
+       void predictIntegratedTransform(btScalar step, btTransform& predictedTransform);
+
+       void saveKinematicState(btScalar step);
+
+       void applyGravity();
+    
+    void clearGravity();
+
+       void setGravity(const btVector3& acceleration);
+
+       const btVector3& getGravity() const
+       {
+               return m_gravity_acceleration;
+       }
+
+       void setDamping(btScalar lin_damping, btScalar ang_damping);
+
+       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;
+       }
+
+       SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
+       {
+               return m_collisionShape;
+       }
+
+       void setMassProps(btScalar mass, const btVector3& inertia);
+
+       const btVector3& getLinearFactor() const
+       {
+               return m_linearFactor;
+       }
+       void setLinearFactor(const btVector3& linearFactor)
+       {
+               m_linearFactor = linearFactor;
+               m_invMass = m_linearFactor * m_inverseMass;
+       }
+       btScalar getInvMass() const { return m_inverseMass; }
+       btScalar getMass() const { return m_inverseMass == btScalar(0.) ? btScalar(0.) : btScalar(1.0) / m_inverseMass; }
+       const btMatrix3x3& getInvInertiaTensorWorld() const
+       {
+               return m_invInertiaTensorWorld;
+       }
+
+       void integrateVelocities(btScalar step);
+
+       void setCenterOfMassTransform(const btTransform& xform);
+
+       void applyCentralForce(const btVector3& force)
+       {
+               m_totalForce += force * m_linearFactor;
+       }
+
+       const btVector3& getTotalForce() const
+       {
+               return m_totalForce;
+       };
+
+       const btVector3& getTotalTorque() const
+       {
+               return m_totalTorque;
+       };
+
+       const btVector3& getInvInertiaDiagLocal() const
+       {
+               return m_invInertiaLocal;
+       };
+
+       void setInvInertiaDiagLocal(const btVector3& diagInvInertia)
+       {
+               m_invInertiaLocal = diagInvInertia;
+       }
+
+       void setSleepingThresholds(btScalar linear, btScalar angular)
+       {
+               m_linearSleepingThreshold = linear;
+               m_angularSleepingThreshold = angular;
+       }
+
+       void applyTorque(const btVector3& torque)
+       {
+               m_totalTorque += torque * m_angularFactor;
+               #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+               clampVelocity(m_totalTorque);
+               #endif
+       }
+
+       void applyForce(const btVector3& force, const btVector3& rel_pos)
+       {
+               applyCentralForce(force);
+               applyTorque(rel_pos.cross(force * m_linearFactor));
+       }
+
+       void applyCentralImpulse(const btVector3& impulse)
+       {
+               m_linearVelocity += impulse * m_linearFactor * m_inverseMass;
+               #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+               clampVelocity(m_linearVelocity);
+               #endif
+       }
+
+       void applyTorqueImpulse(const btVector3& torque)
+       {
+               m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+               #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+               clampVelocity(m_angularVelocity);
+               #endif
+       }
+
+       void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
+       {
+               if (m_inverseMass != btScalar(0.))
+               {
+                       applyCentralImpulse(impulse);
+                       if (m_angularFactor)
+                       {
+                               applyTorqueImpulse(rel_pos.cross(impulse * m_linearFactor));
+                       }
+               }
+       }
+    
+    void applyPushImpulse(const btVector3& impulse, const btVector3& rel_pos)
+    {
+        if (m_inverseMass != btScalar(0.))
+        {
+            applyCentralPushImpulse(impulse);
+            if (m_angularFactor)
+            {
+                applyTorqueTurnImpulse(rel_pos.cross(impulse * m_linearFactor));
+            }
+        }
+    }
+    
+    btVector3 getPushVelocity() const
+    {
+        return m_pushVelocity;
+    }
+    
+    btVector3 getTurnVelocity() const
+    {
+        return m_turnVelocity;
+    }
+    
+    void setPushVelocity(const btVector3& v)
+    {
+        m_pushVelocity = v;
+    }
+
+    #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+    void clampVelocity(btVector3& v) const {
+        v.setX(
+            fmax(-BT_CLAMP_VELOCITY_TO,
+                 fmin(BT_CLAMP_VELOCITY_TO, v.getX()))
+        );
+        v.setY(
+            fmax(-BT_CLAMP_VELOCITY_TO,
+                 fmin(BT_CLAMP_VELOCITY_TO, v.getY()))
+        );
+        v.setZ(
+            fmax(-BT_CLAMP_VELOCITY_TO,
+                 fmin(BT_CLAMP_VELOCITY_TO, v.getZ()))
+        );
+    }
+    #endif
+
+    void setTurnVelocity(const btVector3& v)
+    {
+        m_turnVelocity = v;
+        #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+        clampVelocity(m_turnVelocity);
+        #endif
+    }
+    
+    void applyCentralPushImpulse(const btVector3& impulse)
+    {
+        m_pushVelocity += impulse * m_linearFactor * m_inverseMass;
+        #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+        clampVelocity(m_pushVelocity);
+        #endif
+    }
+    
+    void applyTorqueTurnImpulse(const btVector3& torque)
+    {
+        m_turnVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+        #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+        clampVelocity(m_turnVelocity);
+        #endif
+    }
+
+       void clearForces()
+       {
+               m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+               m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+       }
+
+       void updateInertiaTensor();
+
+       const btVector3& getCenterOfMassPosition() const
+       {
+               return m_worldTransform.getOrigin();
+       }
+       btQuaternion getOrientation() const;
+
+       const btTransform& getCenterOfMassTransform() const
+       {
+               return m_worldTransform;
+       }
+       const btVector3& getLinearVelocity() const
+       {
+               return m_linearVelocity;
+       }
+       const btVector3& getAngularVelocity() const
+       {
+               return m_angularVelocity;
+       }
+
+       inline void setLinearVelocity(const btVector3& lin_vel)
+       {
+               m_updateRevision++;
+               m_linearVelocity = lin_vel;
+               #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+               clampVelocity(m_linearVelocity);
+               #endif
+       }
+
+       inline void setAngularVelocity(const btVector3& ang_vel)
+       {
+               m_updateRevision++;
+               m_angularVelocity = ang_vel;
+               #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+               clampVelocity(m_angularVelocity);
+               #endif
+       }
+
+       btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
+       {
+               //we also calculate lin/ang velocity for kinematic objects
+               return m_linearVelocity + m_angularVelocity.cross(rel_pos);
+
+               //for kinematic objects, we could also use use:
+               //              return  (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep;
+       }
+    
+    btVector3 getPushVelocityInLocalPoint(const btVector3& rel_pos) const
+    {
+        //we also calculate lin/ang velocity for kinematic objects
+        return m_pushVelocity + m_turnVelocity.cross(rel_pos);
+    }
+
+       void translate(const btVector3& v)
+       {
+               m_worldTransform.getOrigin() += v;
+       }
+
+       void getAabb(btVector3& aabbMin, btVector3& aabbMax) const;
+
+       SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const
+       {
+               btVector3 r0 = pos - getCenterOfMassPosition();
+
+               btVector3 c0 = (r0).cross(normal);
+
+               btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0);
+
+               return m_inverseMass + normal.dot(vec);
+       }
+
+       SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const
+       {
+               btVector3 vec = axis * getInvInertiaTensorWorld();
+               return axis.dot(vec);
+       }
+
+       SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep)
+       {
+               if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
+                       return;
+
+               if ((getLinearVelocity().length2() < m_linearSleepingThreshold * m_linearSleepingThreshold) &&
+                       (getAngularVelocity().length2() < m_angularSleepingThreshold * m_angularSleepingThreshold))
+               {
+                       m_deactivationTime += timeStep;
+               }
+               else
+               {
+                       m_deactivationTime = btScalar(0.);
+                       setActivationState(0);
+               }
+       }
+
+       SIMD_FORCE_INLINE bool wantsSleeping()
+       {
+               if (getActivationState() == DISABLE_DEACTIVATION)
+                       return false;
+
+               //disable deactivation
+               if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
+                       return false;
+
+               if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
+                       return true;
+
+               if (m_deactivationTime > gDeactivationTime)
+               {
+                       return true;
+               }
+               return false;
+       }
+
+       const btBroadphaseProxy* getBroadphaseProxy() const
+       {
+               return m_broadphaseHandle;
+       }
+       btBroadphaseProxy* getBroadphaseProxy()
+       {
+               return m_broadphaseHandle;
+       }
+       void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy)
+       {
+               m_broadphaseHandle = broadphaseProxy;
+       }
+
+       //btMotionState allows to automatic synchronize the world transform for active objects
+       btMotionState* getMotionState()
+       {
+               return m_optionalMotionState;
+       }
+       const btMotionState* getMotionState() const
+       {
+               return m_optionalMotionState;
+       }
+       void setMotionState(btMotionState* motionState)
+       {
+               m_optionalMotionState = motionState;
+               if (m_optionalMotionState)
+                       motionState->getWorldTransform(m_worldTransform);
+       }
+
+       //for experimental overriding of friction/contact solver func
+       int m_contactSolverType;
+       int m_frictionSolverType;
+
+       void setAngularFactor(const btVector3& angFac)
+       {
+               m_updateRevision++;
+               m_angularFactor = angFac;
+       }
+
+       void setAngularFactor(btScalar angFac)
+       {
+               m_updateRevision++;
+               m_angularFactor.setValue(angFac, angFac, angFac);
+       }
+       const btVector3& getAngularFactor() const
+       {
+               return m_angularFactor;
+       }
+
+       //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase?
+       bool isInWorld() const
+       {
+               return (getBroadphaseProxy() != 0);
+       }
+
+       void addConstraintRef(btTypedConstraint* c);
+       void removeConstraintRef(btTypedConstraint* c);
+
+       btTypedConstraint* getConstraintRef(int index)
+       {
+               return m_constraintRefs[index];
+       }
+
+       int getNumConstraintRefs() const
+       {
+               return m_constraintRefs.size();
+       }
+
+       void setFlags(int flags)
+       {
+               m_rigidbodyFlags = flags;
+       }
+
+       int getFlags() const
+       {
+               return m_rigidbodyFlags;
+       }
+
+       ///perform implicit force computation in world space
+       btVector3 computeGyroscopicImpulseImplicit_World(btScalar dt) const;
+
+       ///perform implicit force computation in body space (inertial frame)
+       btVector3 computeGyroscopicImpulseImplicit_Body(btScalar step) const;
+
+       ///explicit version is best avoided, it gains energy
+       btVector3 computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const;
+       btVector3 getLocalInertia() const;
+
+       ///////////////////////////////////////////////
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
+
+       virtual void serializeSingleObject(class btSerializer* serializer) const;
+};
+
+//@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btRigidBodyFloatData
+{
+       btCollisionObjectFloatData m_collisionObjectData;
+       btMatrix3x3FloatData m_invInertiaTensorWorld;
+       btVector3FloatData m_linearVelocity;
+       btVector3FloatData m_angularVelocity;
+       btVector3FloatData m_angularFactor;
+       btVector3FloatData m_linearFactor;
+       btVector3FloatData m_gravity;
+       btVector3FloatData m_gravity_acceleration;
+       btVector3FloatData m_invInertiaLocal;
+       btVector3FloatData m_totalForce;
+       btVector3FloatData m_totalTorque;
+       float m_inverseMass;
+       float m_linearDamping;
+       float m_angularDamping;
+       float m_additionalDampingFactor;
+       float m_additionalLinearDampingThresholdSqr;
+       float m_additionalAngularDampingThresholdSqr;
+       float m_additionalAngularDampingFactor;
+       float m_linearSleepingThreshold;
+       float m_angularSleepingThreshold;
+       int m_additionalDamping;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btRigidBodyDoubleData
+{
+       btCollisionObjectDoubleData m_collisionObjectData;
+       btMatrix3x3DoubleData m_invInertiaTensorWorld;
+       btVector3DoubleData m_linearVelocity;
+       btVector3DoubleData m_angularVelocity;
+       btVector3DoubleData m_angularFactor;
+       btVector3DoubleData m_linearFactor;
+       btVector3DoubleData m_gravity;
+       btVector3DoubleData m_gravity_acceleration;
+       btVector3DoubleData m_invInertiaLocal;
+       btVector3DoubleData m_totalForce;
+       btVector3DoubleData m_totalTorque;
+       double m_inverseMass;
+       double m_linearDamping;
+       double m_angularDamping;
+       double m_additionalDampingFactor;
+       double m_additionalLinearDampingThresholdSqr;
+       double m_additionalAngularDampingThresholdSqr;
+       double m_additionalAngularDampingFactor;
+       double m_linearSleepingThreshold;
+       double m_angularSleepingThreshold;
+       int m_additionalDamping;
+       char m_padding[4];
+};
+
+#endif  //BT_RIGIDBODY_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
new file mode 100644 (file)
index 0000000..134c482
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSimpleDynamicsWorld.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+/*
+  Make sure this dummy function never changes so that it
+  can be used by probes that are checking whether the
+  library is actually installed.
+*/
+extern "C"
+{
+       void btBulletDynamicsProbe();
+       void btBulletDynamicsProbe() {}
+}
+
+btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+       : btDynamicsWorld(dispatcher, pairCache, collisionConfiguration),
+         m_constraintSolver(constraintSolver),
+         m_ownsConstraintSolver(false),
+         m_gravity(0, 0, -10)
+{
+}
+
+btSimpleDynamicsWorld::~btSimpleDynamicsWorld()
+{
+       if (m_ownsConstraintSolver)
+               btAlignedFree(m_constraintSolver);
+}
+
+int btSimpleDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
+{
+       (void)fixedTimeStep;
+       (void)maxSubSteps;
+
+       ///apply gravity, predict motion
+       predictUnconstraintMotion(timeStep);
+
+       btDispatcherInfo& dispatchInfo = getDispatchInfo();
+       dispatchInfo.m_timeStep = timeStep;
+       dispatchInfo.m_stepCount = 0;
+       dispatchInfo.m_debugDraw = getDebugDrawer();
+
+       ///perform collision detection
+       performDiscreteCollisionDetection();
+
+       ///solve contact constraints
+       int numManifolds = m_dispatcher1->getNumManifolds();
+       if (numManifolds)
+       {
+               btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer();
+
+               btContactSolverInfo infoGlobal;
+               infoGlobal.m_timeStep = timeStep;
+               m_constraintSolver->prepareSolve(0, numManifolds);
+               m_constraintSolver->solveGroup(&getCollisionObjectArray()[0], getNumCollisionObjects(), manifoldPtr, numManifolds, 0, 0, infoGlobal, m_debugDrawer, m_dispatcher1);
+               m_constraintSolver->allSolved(infoGlobal, m_debugDrawer);
+       }
+
+       ///integrate transforms
+       integrateTransforms(timeStep);
+
+       updateAabbs();
+
+       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)
+{
+       m_gravity = gravity;
+       for (int i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               btRigidBody* body = btRigidBody::upcast(colObj);
+               if (body)
+               {
+                       body->setGravity(gravity);
+               }
+       }
+}
+
+btVector3 btSimpleDynamicsWorld::getGravity() const
+{
+       return m_gravity;
+}
+
+void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body)
+{
+       btCollisionWorld::removeCollisionObject(body);
+}
+
+void btSimpleDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+       btRigidBody* body = btRigidBody::upcast(collisionObject);
+       if (body)
+               removeRigidBody(body);
+       else
+               btCollisionWorld::removeCollisionObject(collisionObject);
+}
+
+void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
+{
+       body->setGravity(m_gravity);
+
+       if (body->getCollisionShape())
+       {
+               addCollisionObject(body);
+       }
+}
+
+void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
+{
+       body->setGravity(m_gravity);
+
+       if (body->getCollisionShape())
+       {
+               addCollisionObject(body, group, mask);
+       }
+}
+
+void btSimpleDynamicsWorld::debugDrawWorld()
+{
+}
+
+void btSimpleDynamicsWorld::addAction(btActionInterface* action)
+{
+}
+
+void btSimpleDynamicsWorld::removeAction(btActionInterface* action)
+{
+}
+
+void btSimpleDynamicsWorld::updateAabbs()
+{
+       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->isStaticObject()))
+                       {
+                               btVector3 minAabb, maxAabb;
+                               colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
+                               btBroadphaseInterface* bp = getBroadphase();
+                               bp->setAabb(body->getBroadphaseHandle(), minAabb, maxAabb, m_dispatcher1);
+                       }
+               }
+       }
+}
+
+void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+       btTransform predictedTrans;
+       for (int i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               btRigidBody* body = btRigidBody::upcast(colObj);
+               if (body)
+               {
+                       if (body->isActive() && (!body->isStaticObject()))
+                       {
+                               body->predictIntegratedTransform(timeStep, predictedTrans);
+                               body->proceedToTransform(predictedTrans);
+                       }
+               }
+       }
+}
+
+void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+       for (int i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               btRigidBody* body = btRigidBody::upcast(colObj);
+               if (body)
+               {
+                       if (!body->isStaticObject())
+                       {
+                               if (body->isActive())
+                               {
+                                       body->applyGravity();
+                                       body->integrateVelocities(timeStep);
+                                       body->applyDamping(timeStep);
+                                       body->predictIntegratedTransform(timeStep, body->getInterpolationWorldTransform());
+                               }
+                       }
+               }
+       }
+}
+
+void btSimpleDynamicsWorld::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())
+               {
+                       if (body->getActivationState() != ISLAND_SLEEPING)
+                       {
+                               body->getMotionState()->setWorldTransform(body->getWorldTransform());
+                       }
+               }
+       }
+}
+
+void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+{
+       if (m_ownsConstraintSolver)
+       {
+               btAlignedFree(m_constraintSolver);
+       }
+       m_ownsConstraintSolver = false;
+       m_constraintSolver = solver;
+}
+
+btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver()
+{
+       return m_constraintSolver;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
new file mode 100644 (file)
index 0000000..46bd535
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SIMPLE_DYNAMICS_WORLD_H
+#define BT_SIMPLE_DYNAMICS_WORLD_H
+
+#include "btDynamicsWorld.h"
+
+class btDispatcher;
+class btOverlappingPairCache;
+class btConstraintSolver;
+
+///The btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds.
+///Please use btDiscreteDynamicsWorld instead
+class btSimpleDynamicsWorld : public btDynamicsWorld
+{
+protected:
+       btConstraintSolver* m_constraintSolver;
+
+       bool m_ownsConstraintSolver;
+
+       void predictUnconstraintMotion(btScalar timeStep);
+
+       void integrateTransforms(btScalar timeStep);
+
+       btVector3 m_gravity;
+
+public:
+       ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver
+       btSimpleDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration);
+
+       virtual ~btSimpleDynamicsWorld();
+
+       ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead
+       virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
+
+       virtual void setGravity(const btVector3& gravity);
+
+       virtual btVector3 getGravity() const;
+
+       virtual void addRigidBody(btRigidBody* body);
+
+       virtual void addRigidBody(btRigidBody* body, int group, int mask);
+
+       virtual void removeRigidBody(btRigidBody* body);
+
+       virtual void debugDrawWorld();
+
+       virtual void addAction(btActionInterface* action);
+
+       virtual void removeAction(btActionInterface* action);
+
+       ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
+       virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+       virtual void updateAabbs();
+
+       virtual void synchronizeMotionStates();
+
+       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/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
new file mode 100644 (file)
index 0000000..026c2a9
--- /dev/null
@@ -0,0 +1,696 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btThreads.h"
+#include "btSimulationIslandManagerMt.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h"  // for s_minimumContactManifoldsForBatching
+
+//#include <stdio.h>
+#include "LinearMath/btQuickprof.h"
+
+SIMD_FORCE_INLINE int calcBatchCost(int bodies, int manifolds, int constraints)
+{
+       // rough estimate of the cost of a batch, used for merging
+       int batchCost = bodies + 8 * manifolds + 4 * constraints;
+       return batchCost;
+}
+
+SIMD_FORCE_INLINE int calcBatchCost(const btSimulationIslandManagerMt::Island* island)
+{
+       return calcBatchCost(island->bodyArray.size(), island->manifoldArray.size(), island->constraintArray.size());
+}
+
+btSimulationIslandManagerMt::btSimulationIslandManagerMt()
+{
+       m_minimumSolverBatchSize = calcBatchCost(0, 128, 0);
+       m_batchIslandMinBodyCount = 32;
+       m_islandDispatch = parallelIslandDispatch;
+       m_batchIsland = NULL;
+}
+
+btSimulationIslandManagerMt::~btSimulationIslandManagerMt()
+{
+       for (int i = 0; i < m_allocatedIslands.size(); ++i)
+       {
+               delete m_allocatedIslands[i];
+       }
+       m_allocatedIslands.resize(0);
+       m_activeIslands.resize(0);
+       m_freeIslands.resize(0);
+}
+
+inline int getIslandId(const btPersistentManifold* lhs)
+{
+       const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
+       const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
+       int islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
+       return islandId;
+}
+
+SIMD_FORCE_INLINE int btGetConstraintIslandId1(const btTypedConstraint* lhs)
+{
+       const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
+       const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
+       int islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
+       return islandId;
+}
+
+/// function object that routes calls to operator<
+class IslandBatchSizeSortPredicate
+{
+public:
+       bool operator()(const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs) const
+       {
+               int lCost = calcBatchCost(lhs);
+               int rCost = calcBatchCost(rhs);
+               return lCost > rCost;
+       }
+};
+
+class IslandBodyCapacitySortPredicate
+{
+public:
+       bool operator()(const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs) const
+       {
+               return lhs->bodyArray.capacity() > rhs->bodyArray.capacity();
+       }
+};
+
+void btSimulationIslandManagerMt::Island::append(const Island& other)
+{
+       // append bodies
+       for (int i = 0; i < other.bodyArray.size(); ++i)
+       {
+               bodyArray.push_back(other.bodyArray[i]);
+       }
+       // append manifolds
+       for (int i = 0; i < other.manifoldArray.size(); ++i)
+       {
+               manifoldArray.push_back(other.manifoldArray[i]);
+       }
+       // append constraints
+       for (int i = 0; i < other.constraintArray.size(); ++i)
+       {
+               constraintArray.push_back(other.constraintArray[i]);
+       }
+}
+
+bool btIsBodyInIsland(const btSimulationIslandManagerMt::Island& island, const btCollisionObject* obj)
+{
+       for (int i = 0; i < island.bodyArray.size(); ++i)
+       {
+               if (island.bodyArray[i] == obj)
+               {
+                       return true;
+               }
+       }
+       return false;
+}
+
+void btSimulationIslandManagerMt::initIslandPools()
+{
+       // reset island pools
+       int numElem = getUnionFind().getNumElements();
+       m_lookupIslandFromId.resize(numElem);
+       for (int i = 0; i < m_lookupIslandFromId.size(); ++i)
+       {
+               m_lookupIslandFromId[i] = NULL;
+       }
+       m_activeIslands.resize(0);
+       m_freeIslands.resize(0);
+       // check whether allocated islands are sorted by body capacity (largest to smallest)
+       int lastCapacity = 0;
+       bool isSorted = true;
+       for (int i = 0; i < m_allocatedIslands.size(); ++i)
+       {
+               Island* island = m_allocatedIslands[i];
+               int cap = island->bodyArray.capacity();
+               if (cap > lastCapacity)
+               {
+                       isSorted = false;
+                       break;
+               }
+               lastCapacity = cap;
+       }
+       if (!isSorted)
+       {
+               m_allocatedIslands.quickSort(IslandBodyCapacitySortPredicate());
+       }
+
+       m_batchIsland = NULL;
+       // mark all islands free (but avoid deallocation)
+       for (int i = 0; i < m_allocatedIslands.size(); ++i)
+       {
+               Island* island = m_allocatedIslands[i];
+               island->bodyArray.resize(0);
+               island->manifoldArray.resize(0);
+               island->constraintArray.resize(0);
+               island->id = -1;
+               island->isSleeping = true;
+               m_freeIslands.push_back(island);
+       }
+}
+
+btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::getIsland(int id)
+{
+       btAssert(id >= 0);
+       btAssert(id < m_lookupIslandFromId.size());
+       Island* island = m_lookupIslandFromId[id];
+       if (island == NULL)
+       {
+               // search for existing island
+               for (int i = 0; i < m_activeIslands.size(); ++i)
+               {
+                       if (m_activeIslands[i]->id == id)
+                       {
+                               island = m_activeIslands[i];
+                               break;
+                       }
+               }
+               m_lookupIslandFromId[id] = island;
+       }
+       return island;
+}
+
+btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::allocateIsland(int id, int numBodies)
+{
+       Island* island = NULL;
+       int allocSize = numBodies;
+       if (numBodies < m_batchIslandMinBodyCount)
+       {
+               if (m_batchIsland)
+               {
+                       island = m_batchIsland;
+                       m_lookupIslandFromId[id] = island;
+                       // if we've made a large enough batch,
+                       if (island->bodyArray.size() + numBodies >= m_batchIslandMinBodyCount)
+                       {
+                               // next time start a new batch
+                               m_batchIsland = NULL;
+                       }
+                       return island;
+               }
+               else
+               {
+                       // need to allocate a batch island
+                       allocSize = m_batchIslandMinBodyCount * 2;
+               }
+       }
+       btAlignedObjectArray<Island*>& freeIslands = m_freeIslands;
+
+       // search for free island
+       if (freeIslands.size() > 0)
+       {
+               // try to reuse a previously allocated island
+               int iFound = freeIslands.size();
+               // linear search for smallest island that can hold our bodies
+               for (int i = freeIslands.size() - 1; i >= 0; --i)
+               {
+                       if (freeIslands[i]->bodyArray.capacity() >= allocSize)
+                       {
+                               iFound = i;
+                               island = freeIslands[i];
+                               island->id = id;
+                               break;
+                       }
+               }
+               // if found, shrink array while maintaining ordering
+               if (island)
+               {
+                       int iDest = iFound;
+                       int iSrc = iDest + 1;
+                       while (iSrc < freeIslands.size())
+                       {
+                               freeIslands[iDest++] = freeIslands[iSrc++];
+                       }
+                       freeIslands.pop_back();
+               }
+       }
+       if (island == NULL)
+       {
+               // no free island found, allocate
+               island = new Island();  // TODO: change this to use the pool allocator
+               island->id = id;
+               island->bodyArray.reserve(allocSize);
+               m_allocatedIslands.push_back(island);
+       }
+       m_lookupIslandFromId[id] = island;
+       if (numBodies < m_batchIslandMinBodyCount)
+       {
+               m_batchIsland = island;
+       }
+       m_activeIslands.push_back(island);
+       return island;
+}
+
+void btSimulationIslandManagerMt::buildIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld)
+{
+       BT_PROFILE("buildIslands");
+
+       btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+
+       //we are going to sort the unionfind array, and store the element id in the size
+       //afterwards, we clean unionfind, to make sure no-one uses it anymore
+
+       getUnionFind().sortIslands();
+       int numElem = getUnionFind().getNumElements();
+
+       int endIslandIndex = 1;
+       int startIslandIndex;
+
+       //update the sleeping state for bodies, if all are sleeping
+       for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
+       {
+               int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+               for (endIslandIndex = startIslandIndex + 1; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
+               {
+               }
+
+               //int numSleeping = 0;
+
+               bool allSleeping = true;
+
+               int idx;
+               for (idx = startIslandIndex; idx < endIslandIndex; idx++)
+               {
+                       int i = getUnionFind().getElement(idx).m_sz;
+
+                       btCollisionObject* colObj0 = collisionObjects[i];
+                       if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+                       {
+                               //                              printf("error in island management\n");
+                       }
+
+                       btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+                       if (colObj0->getIslandTag() == islandId)
+                       {
+                               if (colObj0->getActivationState() == ACTIVE_TAG ||
+                                       colObj0->getActivationState() == DISABLE_DEACTIVATION)
+                               {
+                                       allSleeping = false;
+                                       break;
+                               }
+                       }
+               }
+
+               if (allSleeping)
+               {
+                       int idx;
+                       for (idx = startIslandIndex; idx < endIslandIndex; idx++)
+                       {
+                               int i = getUnionFind().getElement(idx).m_sz;
+                               btCollisionObject* colObj0 = collisionObjects[i];
+                               if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+                               {
+                                       //                                      printf("error in island management\n");
+                               }
+
+                               btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+                               if (colObj0->getIslandTag() == islandId)
+                               {
+                                       colObj0->setActivationState(ISLAND_SLEEPING);
+                               }
+                       }
+               }
+               else
+               {
+                       int idx;
+                       for (idx = startIslandIndex; idx < endIslandIndex; idx++)
+                       {
+                               int i = getUnionFind().getElement(idx).m_sz;
+
+                               btCollisionObject* colObj0 = collisionObjects[i];
+                               if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+                               {
+                                       //                                      printf("error in island management\n");
+                               }
+
+                               btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+                               if (colObj0->getIslandTag() == islandId)
+                               {
+                                       if (colObj0->getActivationState() == ISLAND_SLEEPING)
+                                       {
+                                               colObj0->setActivationState(WANTS_DEACTIVATION);
+                                               colObj0->setDeactivationTime(0.f);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void btSimulationIslandManagerMt::addBodiesToIslands(btCollisionWorld* collisionWorld)
+{
+       btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+       int endIslandIndex = 1;
+       int startIslandIndex;
+       int numElem = getUnionFind().getNumElements();
+
+       // create explicit islands and add bodies to each
+       for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
+       {
+               int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+
+               // find end index
+               for (endIslandIndex = startIslandIndex; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
+               {
+               }
+               // check if island is sleeping
+               bool islandSleeping = true;
+               for (int iElem = startIslandIndex; iElem < endIslandIndex; iElem++)
+               {
+                       int i = getUnionFind().getElement(iElem).m_sz;
+                       btCollisionObject* colObj = collisionObjects[i];
+                       if (colObj->isActive())
+                       {
+                               islandSleeping = false;
+                       }
+               }
+               if (!islandSleeping)
+               {
+                       // want to count the number of bodies before allocating the island to optimize memory usage of the Island structures
+                       int numBodies = endIslandIndex - startIslandIndex;
+                       Island* island = allocateIsland(islandId, numBodies);
+                       island->isSleeping = false;
+
+                       // add bodies to island
+                       for (int iElem = startIslandIndex; iElem < endIslandIndex; iElem++)
+                       {
+                               int i = getUnionFind().getElement(iElem).m_sz;
+                               btCollisionObject* colObj = collisionObjects[i];
+                               island->bodyArray.push_back(colObj);
+                       }
+               }
+       }
+}
+
+void btSimulationIslandManagerMt::addManifoldsToIslands(btDispatcher* dispatcher)
+{
+       // walk all the manifolds, activating bodies touched by kinematic objects, and add each manifold to its Island
+       int maxNumManifolds = dispatcher->getNumManifolds();
+       for (int i = 0; i < maxNumManifolds; i++)
+       {
+               btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
+
+               const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
+               const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
+
+               ///@todo: check sleeping conditions!
+               if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
+                       ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
+               {
+                       //kinematic objects don't merge islands, but wake up all connected objects
+                       if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
+                       {
+                               if (colObj0->hasContactResponse())
+                                       colObj1->activate();
+                       }
+                       if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
+                       {
+                               if (colObj1->hasContactResponse())
+                                       colObj0->activate();
+                       }
+                       //filtering for response
+                       if (dispatcher->needsResponse(colObj0, colObj1))
+                       {
+                               // scatter manifolds into various islands
+                               int islandId = getIslandId(manifold);
+                               // if island not sleeping,
+                               if (Island* island = getIsland(islandId))
+                               {
+                                       island->manifoldArray.push_back(manifold);
+                               }
+                       }
+               }
+       }
+}
+
+void btSimulationIslandManagerMt::addConstraintsToIslands(btAlignedObjectArray<btTypedConstraint*>& constraints)
+{
+       // walk constraints
+       for (int i = 0; i < constraints.size(); i++)
+       {
+               // scatter constraints into various islands
+               btTypedConstraint* constraint = constraints[i];
+               if (constraint->isEnabled())
+               {
+                       int islandId = btGetConstraintIslandId1(constraint);
+                       // if island is not sleeping,
+                       if (Island* island = getIsland(islandId))
+                       {
+                               island->constraintArray.push_back(constraint);
+                       }
+               }
+       }
+}
+
+void btSimulationIslandManagerMt::mergeIslands()
+{
+       // sort islands in order of decreasing batch size
+       m_activeIslands.quickSort(IslandBatchSizeSortPredicate());
+
+       // merge small islands to satisfy minimum batch size
+       // find first small batch island
+       int destIslandIndex = m_activeIslands.size();
+       for (int i = 0; i < m_activeIslands.size(); ++i)
+       {
+               Island* island = m_activeIslands[i];
+               int batchSize = calcBatchCost(island);
+               if (batchSize < m_minimumSolverBatchSize)
+               {
+                       destIslandIndex = i;
+                       break;
+               }
+       }
+       int lastIndex = m_activeIslands.size() - 1;
+       while (destIslandIndex < lastIndex)
+       {
+               // merge islands from the back of the list
+               Island* island = m_activeIslands[destIslandIndex];
+               int numBodies = island->bodyArray.size();
+               int numManifolds = island->manifoldArray.size();
+               int numConstraints = island->constraintArray.size();
+               int firstIndex = lastIndex;
+               // figure out how many islands we want to merge and find out how many bodies, manifolds and constraints we will have
+               while (true)
+               {
+                       Island* src = m_activeIslands[firstIndex];
+                       numBodies += src->bodyArray.size();
+                       numManifolds += src->manifoldArray.size();
+                       numConstraints += src->constraintArray.size();
+                       int batchCost = calcBatchCost(numBodies, numManifolds, numConstraints);
+                       if (batchCost >= m_minimumSolverBatchSize)
+                       {
+                               break;
+                       }
+                       if (firstIndex - 1 == destIslandIndex)
+                       {
+                               break;
+                       }
+                       firstIndex--;
+               }
+               // reserve space for these pointers to minimize reallocation
+               island->bodyArray.reserve(numBodies);
+               island->manifoldArray.reserve(numManifolds);
+               island->constraintArray.reserve(numConstraints);
+               // merge islands
+               for (int i = firstIndex; i <= lastIndex; ++i)
+               {
+                       island->append(*m_activeIslands[i]);
+               }
+               // shrink array to exclude the islands that were merged from
+               m_activeIslands.resize(firstIndex);
+               lastIndex = firstIndex - 1;
+               destIslandIndex++;
+       }
+}
+
+void btSimulationIslandManagerMt::solveIsland(btConstraintSolver* solver, Island& island, const SolverParams& solverParams)
+{
+       btPersistentManifold** manifolds = island.manifoldArray.size() ? &island.manifoldArray[0] : NULL;
+       btTypedConstraint** constraintsPtr = island.constraintArray.size() ? &island.constraintArray[0] : NULL;
+       solver->solveGroup(&island.bodyArray[0],
+                                          island.bodyArray.size(),
+                                          manifolds,
+                                          island.manifoldArray.size(),
+                                          constraintsPtr,
+                                          island.constraintArray.size(),
+                                          *solverParams.m_solverInfo,
+                                          solverParams.m_debugDrawer,
+                                          solverParams.m_dispatcher);
+}
+
+void btSimulationIslandManagerMt::serialIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams)
+{
+       BT_PROFILE("serialIslandDispatch");
+       // serial dispatch
+       btAlignedObjectArray<Island*>& islands = *islandsPtr;
+       btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool;
+       for (int i = 0; i < islands.size(); ++i)
+       {
+               solveIsland(solver, *islands[i], solverParams);
+       }
+}
+
+struct UpdateIslandDispatcher : public btIParallelForBody
+{
+       btAlignedObjectArray<btSimulationIslandManagerMt::Island*>& m_islandsPtr;
+       const btSimulationIslandManagerMt::SolverParams& m_solverParams;
+
+       UpdateIslandDispatcher(btAlignedObjectArray<btSimulationIslandManagerMt::Island*>& islandsPtr, const btSimulationIslandManagerMt::SolverParams& solverParams)
+               : m_islandsPtr(islandsPtr), m_solverParams(solverParams)
+       {
+       }
+
+       void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
+       {
+               btConstraintSolver* solver = m_solverParams.m_solverPool;
+               for (int i = iBegin; i < iEnd; ++i)
+               {
+                       btSimulationIslandManagerMt::Island* island = m_islandsPtr[i];
+                       btSimulationIslandManagerMt::solveIsland(solver, *island, m_solverParams);
+               }
+       }
+};
+
+void btSimulationIslandManagerMt::parallelIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams)
+{
+       BT_PROFILE("parallelIslandDispatch");
+       //
+       // if there are islands with many contacts, it may be faster to submit these
+       // large islands *serially* to a single parallel constraint solver, and then later
+       // submit the remaining smaller islands in parallel to multiple sequential solvers.
+       //
+       // Some task schedulers do not deal well with nested parallelFor loops. One implementation
+       // of OpenMP was actually slower than doing everything single-threaded. Intel TBB
+       // on the other hand, seems to do a pretty respectable job with it.
+       //
+       // When solving islands in parallel, the worst case performance happens when there
+       // is one very large island and then perhaps a smattering of very small
+       // islands -- one worker thread takes the large island and the remaining workers
+       // tear through the smaller islands and then sit idle waiting for the first worker
+       // to finish. Solving islands in parallel works best when there are numerous small
+       // islands, roughly equal in size.
+       //
+       // By contrast, the other approach -- the parallel constraint solver -- is only
+       // able to deliver a worthwhile speedup when the island is large. For smaller islands,
+       // it is difficult to extract a useful amount of parallelism -- the overhead of grouping
+       // the constraints into batches and sending the batches to worker threads can nullify
+       // any gains from parallelism.
+       //
+
+       UpdateIslandDispatcher dispatcher(*islandsPtr, solverParams);
+       // We take advantage of the fact the islands are sorted in order of decreasing size
+       int iBegin = 0;
+       if (solverParams.m_solverMt)
+       {
+               while (iBegin < islandsPtr->size())
+               {
+                       btSimulationIslandManagerMt::Island* island = (*islandsPtr)[iBegin];
+                       if (island->manifoldArray.size() < btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching)
+                       {
+                               // OK to submit the rest of the array in parallel
+                               break;
+                       }
+                       // serial dispatch to parallel solver for large islands (if any)
+                       solveIsland(solverParams.m_solverMt, *island, solverParams);
+                       ++iBegin;
+               }
+       }
+       // parallel dispatch to sequential solvers for rest
+       btParallelFor(iBegin, islandsPtr->size(), 1, dispatcher);
+}
+
+///@todo: this is random access, it can be walked 'cache friendly'!
+void btSimulationIslandManagerMt::buildAndProcessIslands(btDispatcher* dispatcher,
+                                                                                                                btCollisionWorld* collisionWorld,
+                                                                                                                btAlignedObjectArray<btTypedConstraint*>& constraints,
+                                                                                                                const SolverParams& solverParams)
+{
+       BT_PROFILE("buildAndProcessIslands");
+       btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+
+       buildIslands(dispatcher, collisionWorld);
+
+       if (!getSplitIslands())
+       {
+               btPersistentManifold** manifolds = dispatcher->getInternalManifoldPointer();
+               int maxNumManifolds = dispatcher->getNumManifolds();
+
+               for (int i = 0; i < maxNumManifolds; i++)
+               {
+                       btPersistentManifold* manifold = manifolds[i];
+
+                       const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
+                       const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
+
+                       ///@todo: check sleeping conditions!
+                       if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
+                               ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
+                       {
+                               //kinematic objects don't merge islands, but wake up all connected objects
+                               if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
+                               {
+                                       if (colObj0->hasContactResponse())
+                                               colObj1->activate();
+                               }
+                               if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
+                               {
+                                       if (colObj1->hasContactResponse())
+                                               colObj0->activate();
+                               }
+                       }
+               }
+               btTypedConstraint** constraintsPtr = constraints.size() ? &constraints[0] : NULL;
+               btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool;
+               solver->solveGroup(&collisionObjects[0],
+                                                  collisionObjects.size(),
+                                                  manifolds,
+                                                  maxNumManifolds,
+                                                  constraintsPtr,
+                                                  constraints.size(),
+                                                  *solverParams.m_solverInfo,
+                                                  solverParams.m_debugDrawer,
+                                                  solverParams.m_dispatcher);
+       }
+       else
+       {
+               initIslandPools();
+
+               //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
+               addBodiesToIslands(collisionWorld);
+               addManifoldsToIslands(dispatcher);
+               addConstraintsToIslands(constraints);
+
+               // m_activeIslands array should now contain all non-sleeping Islands, and each Island should
+               // have all the necessary bodies, manifolds and constraints.
+
+               // if we want to merge islands with small batch counts,
+               if (m_minimumSolverBatchSize > 1)
+               {
+                       mergeIslands();
+               }
+               // dispatch islands to solver
+               m_islandDispatch(&m_activeIslands, solverParams);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h
new file mode 100644 (file)
index 0000000..dcc04cd
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SIMULATION_ISLAND_MANAGER_MT_H
+#define BT_SIMULATION_ISLAND_MANAGER_MT_H
+
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+
+class btTypedConstraint;
+class btConstraintSolver;
+struct btContactSolverInfo;
+class btIDebugDraw;
+
+///
+/// SimulationIslandManagerMt -- Multithread capable version of SimulationIslandManager
+///                       Splits the world up into islands which can be solved in parallel.
+///                       In order to solve islands in parallel, an IslandDispatch function
+///                       must be provided which will dispatch calls to multiple threads.
+///                       The amount of parallelism that can be achieved depends on the number
+///                       of islands. If only a single island exists, then no parallelism is
+///                       possible.
+///
+class btSimulationIslandManagerMt : public btSimulationIslandManager
+{
+public:
+       struct Island
+       {
+               // a simulation island consisting of bodies, manifolds and constraints,
+               // to be passed into a constraint solver.
+               btAlignedObjectArray<btCollisionObject*> bodyArray;
+               btAlignedObjectArray<btPersistentManifold*> manifoldArray;
+               btAlignedObjectArray<btTypedConstraint*> constraintArray;
+               int id;  // island id
+               bool isSleeping;
+
+               void append(const Island& other);  // add bodies, manifolds, constraints to my own
+       };
+       struct SolverParams
+       {
+               btConstraintSolver* m_solverPool;
+               btConstraintSolver* m_solverMt;
+               btContactSolverInfo* m_solverInfo;
+               btIDebugDraw* m_debugDrawer;
+               btDispatcher* m_dispatcher;
+       };
+       static void solveIsland(btConstraintSolver* solver, Island& island, const SolverParams& solverParams);
+
+       typedef void (*IslandDispatchFunc)(btAlignedObjectArray<Island*>* islands, const SolverParams& solverParams);
+       static void serialIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams);
+       static void parallelIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams);
+
+protected:
+       btAlignedObjectArray<Island*> m_allocatedIslands;    // owner of all Islands
+       btAlignedObjectArray<Island*> m_activeIslands;       // islands actively in use
+       btAlignedObjectArray<Island*> m_freeIslands;         // islands ready to be reused
+       btAlignedObjectArray<Island*> m_lookupIslandFromId;  // big lookup table to map islandId to Island pointer
+       Island* m_batchIsland;
+       int m_minimumSolverBatchSize;
+       int m_batchIslandMinBodyCount;
+       IslandDispatchFunc m_islandDispatch;
+
+       Island* getIsland(int id);
+       virtual Island* allocateIsland(int id, int numBodies);
+       virtual void initIslandPools();
+       virtual void addBodiesToIslands(btCollisionWorld* collisionWorld);
+       virtual void addManifoldsToIslands(btDispatcher* dispatcher);
+       virtual void addConstraintsToIslands(btAlignedObjectArray<btTypedConstraint*>& constraints);
+       virtual void mergeIslands();
+
+public:
+       btSimulationIslandManagerMt();
+       virtual ~btSimulationIslandManagerMt();
+
+       virtual void buildAndProcessIslands(btDispatcher* dispatcher,
+                                                                               btCollisionWorld* collisionWorld,
+                                                                               btAlignedObjectArray<btTypedConstraint*>& constraints,
+                                                                               const SolverParams& solverParams);
+
+       virtual void buildIslands(btDispatcher* dispatcher, btCollisionWorld* colWorld);
+
+       int getMinimumSolverBatchSize() const
+       {
+               return m_minimumSolverBatchSize;
+       }
+       void setMinimumSolverBatchSize(int sz)
+       {
+               m_minimumSolverBatchSize = sz;
+       }
+       IslandDispatchFunc getIslandDispatchFunction() const
+       {
+               return m_islandDispatch;
+       }
+       // allow users to set their own dispatch function for multithreaded dispatch
+       void setIslandDispatchFunction(IslandDispatchFunc func)
+       {
+               m_islandDispatch = func;
+       }
+};
+
+#endif  //BT_SIMULATION_ISLAND_MANAGER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBody.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBody.cpp
new file mode 100644 (file)
index 0000000..d7588ae
--- /dev/null
@@ -0,0 +1,2461 @@
+/*
+ * PURPOSE:
+ *   Class representing an articulated rigid body. Stores the body's
+ *   current state, allows forces and torques to be set, handles
+ *   timestepping and implements Featherstone's algorithm.
+ *   
+ * COPYRIGHT:
+ *   Copyright (C) Stephen Thompson, <stephen@solarflare.org.uk>, 2011-2013
+ *   Portions written By Erwin Coumans: connection to LCP solver, various multibody constraints, replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix)
+ *   Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements
+
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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 "btMultiBody.h"
+#include "btMultiBodyLink.h"
+#include "btMultiBodyLinkCollider.h"
+#include "btMultiBodyJointFeedback.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btSerializer.h"
+//#include "Bullet3Common/b3Logging.h"
+// #define INCLUDE_GYRO_TERM
+
+
+namespace
+{
+const btScalar INITIAL_SLEEP_EPSILON = btScalar(0.05);  // this is a squared velocity (m^2 s^-2)
+const btScalar INITIAL_SLEEP_TIMEOUT = btScalar(2);     // in seconds
+}  // namespace
+
+void btMultiBody::spatialTransform(const btMatrix3x3 &rotation_matrix,  // rotates vectors in 'from' frame to vectors in 'to' frame
+       const btVector3 &displacement,       // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates
+       const btVector3 &top_in,             // top part of input vector
+       const btVector3 &bottom_in,          // bottom part of input vector
+       btVector3 &top_out,                  // top part of output vector
+       btVector3 &bottom_out)               // bottom part of output vector
+{
+       top_out = rotation_matrix * top_in;
+       bottom_out = -displacement.cross(top_out) + rotation_matrix * bottom_in;
+}
+
+namespace
+{
+
+
+#if 0
+    void InverseSpatialTransform(const btMatrix3x3 &rotation_matrix,
+                                 const btVector3 &displacement,
+                                 const btVector3 &top_in,
+                                 const btVector3 &bottom_in,
+                                 btVector3 &top_out,
+                                 btVector3 &bottom_out)
+    {
+        top_out = rotation_matrix.transpose() * top_in;
+        bottom_out = rotation_matrix.transpose() * (bottom_in + displacement.cross(top_in));           
+    }
+
+    btScalar SpatialDotProduct(const btVector3 &a_top,
+                            const btVector3 &a_bottom,
+                            const btVector3 &b_top,
+                            const btVector3 &b_bottom)
+    {
+        return a_bottom.dot(b_top) + a_top.dot(b_bottom);
+    }
+
+       void SpatialCrossProduct(const btVector3 &a_top,
+                            const btVector3 &a_bottom,
+                            const btVector3 &b_top,
+                            const btVector3 &b_bottom,
+                                                       btVector3 &top_out,
+                                                       btVector3 &bottom_out)
+       {
+               top_out = a_top.cross(b_top);
+               bottom_out = a_bottom.cross(b_top) + a_top.cross(b_bottom);
+       }
+#endif
+
+}  // namespace
+
+//
+// Implementation of class btMultiBody
+//
+
+btMultiBody::btMultiBody(int n_links,
+                                                btScalar mass,
+                                                const btVector3 &inertia,
+                                                bool fixedBase,
+                                                bool canSleep,
+                                                bool /*deprecatedUseMultiDof*/)
+       : m_baseCollider(0),
+         m_baseName(0),
+         m_basePos(0, 0, 0),
+         m_baseQuat(0, 0, 0, 1),
+      m_basePos_interpolate(0, 0, 0),
+      m_baseQuat_interpolate(0, 0, 0, 1),
+         m_baseMass(mass),
+         m_baseInertia(inertia),
+
+         m_fixedBase(fixedBase),
+         m_awake(true),
+         m_canSleep(canSleep),
+         m_canWakeup(true),
+         m_sleepTimer(0),
+      m_sleepEpsilon(INITIAL_SLEEP_EPSILON),
+         m_sleepTimeout(INITIAL_SLEEP_TIMEOUT),
+
+         m_userObjectPointer(0),
+         m_userIndex2(-1),
+         m_userIndex(-1),
+         m_companionId(-1),
+         m_linearDamping(0.04f),
+         m_angularDamping(0.04f),
+         m_useGyroTerm(true),
+         m_maxAppliedImpulse(1000.f),
+         m_maxCoordinateVelocity(100.f),
+         m_hasSelfCollision(true),
+         __posUpdated(false),
+         m_dofCount(0),
+         m_posVarCnt(0),
+         m_useRK4(false),
+         m_useGlobalVelocities(false),
+         m_internalNeedsJointFeedback(false),
+               m_kinematic_calculate_velocity(false)
+{
+       m_cachedInertiaTopLeft.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+       m_cachedInertiaTopRight.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+       m_cachedInertiaLowerLeft.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+       m_cachedInertiaLowerRight.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
+       m_cachedInertiaValid = false;
+
+       m_links.resize(n_links);
+       m_matrixBuf.resize(n_links + 1);
+
+       m_baseForce.setValue(0, 0, 0);
+       m_baseTorque.setValue(0, 0, 0);
+
+       clearConstraintForces();
+       clearForcesAndTorques();
+}
+
+btMultiBody::~btMultiBody()
+{
+}
+
+void btMultiBody::setupFixed(int i,
+                                                        btScalar mass,
+                                                        const btVector3 &inertia,
+                                                        int parent,
+                                                        const btQuaternion &rotParentToThis,
+                                                        const btVector3 &parentComToThisPivotOffset,
+                                                        const btVector3 &thisPivotToThisComOffset, bool /*deprecatedDisableParentCollision*/)
+{
+       m_links[i].m_mass = mass;
+       m_links[i].m_inertiaLocal = inertia;
+       m_links[i].m_parent = parent;
+       m_links[i].setAxisTop(0, 0., 0., 0.);
+       m_links[i].setAxisBottom(0, btVector3(0, 0, 0));
+       m_links[i].m_zeroRotParentToThis = rotParentToThis;
+       m_links[i].m_dVector = thisPivotToThisComOffset;
+       m_links[i].m_eVector = parentComToThisPivotOffset;
+
+       m_links[i].m_jointType = btMultibodyLink::eFixed;
+       m_links[i].m_dofCount = 0;
+       m_links[i].m_posVarCount = 0;
+
+       m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+
+       m_links[i].updateCacheMultiDof();
+
+       updateLinksDofOffsets();
+}
+
+void btMultiBody::setupPrismatic(int i,
+                                                                btScalar mass,
+                                                                const btVector3 &inertia,
+                                                                int parent,
+                                                                const btQuaternion &rotParentToThis,
+                                                                const btVector3 &jointAxis,
+                                                                const btVector3 &parentComToThisPivotOffset,
+                                                                const btVector3 &thisPivotToThisComOffset,
+                                                                bool disableParentCollision)
+{
+       m_dofCount += 1;
+       m_posVarCnt += 1;
+
+       m_links[i].m_mass = mass;
+       m_links[i].m_inertiaLocal = inertia;
+       m_links[i].m_parent = parent;
+       m_links[i].m_zeroRotParentToThis = rotParentToThis;
+       m_links[i].setAxisTop(0, 0., 0., 0.);
+       m_links[i].setAxisBottom(0, jointAxis);
+       m_links[i].m_eVector = parentComToThisPivotOffset;
+       m_links[i].m_dVector = thisPivotToThisComOffset;
+       m_links[i].m_cachedRotParentToThis = rotParentToThis;
+
+       m_links[i].m_jointType = btMultibodyLink::ePrismatic;
+       m_links[i].m_dofCount = 1;
+       m_links[i].m_posVarCount = 1;
+       m_links[i].m_jointPos[0] = 0.f;
+       m_links[i].m_jointTorque[0] = 0.f;
+
+       if (disableParentCollision)
+               m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+       //
+
+       m_links[i].updateCacheMultiDof();
+
+       updateLinksDofOffsets();
+}
+
+void btMultiBody::setupRevolute(int i,
+                                                               btScalar mass,
+                                                               const btVector3 &inertia,
+                                                               int parent,
+                                                               const btQuaternion &rotParentToThis,
+                                                               const btVector3 &jointAxis,
+                                                               const btVector3 &parentComToThisPivotOffset,
+                                                               const btVector3 &thisPivotToThisComOffset,
+                                                               bool disableParentCollision)
+{
+       m_dofCount += 1;
+       m_posVarCnt += 1;
+
+       m_links[i].m_mass = mass;
+       m_links[i].m_inertiaLocal = inertia;
+       m_links[i].m_parent = parent;
+       m_links[i].m_zeroRotParentToThis = rotParentToThis;
+       m_links[i].setAxisTop(0, jointAxis);
+       m_links[i].setAxisBottom(0, jointAxis.cross(thisPivotToThisComOffset));
+       m_links[i].m_dVector = thisPivotToThisComOffset;
+       m_links[i].m_eVector = parentComToThisPivotOffset;
+
+       m_links[i].m_jointType = btMultibodyLink::eRevolute;
+       m_links[i].m_dofCount = 1;
+       m_links[i].m_posVarCount = 1;
+       m_links[i].m_jointPos[0] = 0.f;
+       m_links[i].m_jointTorque[0] = 0.f;
+
+       if (disableParentCollision)
+               m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+       //
+       m_links[i].updateCacheMultiDof();
+       //
+       updateLinksDofOffsets();
+}
+
+void btMultiBody::setupSpherical(int i,
+                                                                btScalar mass,
+                                                                const btVector3 &inertia,
+                                                                int parent,
+                                                                const btQuaternion &rotParentToThis,
+                                                                const btVector3 &parentComToThisPivotOffset,
+                                                                const btVector3 &thisPivotToThisComOffset,
+                                                                bool disableParentCollision)
+{
+       m_dofCount += 3;
+       m_posVarCnt += 4;
+
+       m_links[i].m_mass = mass;
+       m_links[i].m_inertiaLocal = inertia;
+       m_links[i].m_parent = parent;
+       m_links[i].m_zeroRotParentToThis = rotParentToThis;
+       m_links[i].m_dVector = thisPivotToThisComOffset;
+       m_links[i].m_eVector = parentComToThisPivotOffset;
+
+       m_links[i].m_jointType = btMultibodyLink::eSpherical;
+       m_links[i].m_dofCount = 3;
+       m_links[i].m_posVarCount = 4;
+       m_links[i].setAxisTop(0, 1.f, 0.f, 0.f);
+       m_links[i].setAxisTop(1, 0.f, 1.f, 0.f);
+       m_links[i].setAxisTop(2, 0.f, 0.f, 1.f);
+       m_links[i].setAxisBottom(0, m_links[i].getAxisTop(0).cross(thisPivotToThisComOffset));
+       m_links[i].setAxisBottom(1, m_links[i].getAxisTop(1).cross(thisPivotToThisComOffset));
+       m_links[i].setAxisBottom(2, m_links[i].getAxisTop(2).cross(thisPivotToThisComOffset));
+       m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f;
+       m_links[i].m_jointPos[3] = 1.f;
+       m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
+
+       if (disableParentCollision)
+               m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+       //
+       m_links[i].updateCacheMultiDof();
+       //
+       updateLinksDofOffsets();
+}
+
+void btMultiBody::setupPlanar(int i,
+                                                         btScalar mass,
+                                                         const btVector3 &inertia,
+                                                         int parent,
+                                                         const btQuaternion &rotParentToThis,
+                                                         const btVector3 &rotationAxis,
+                                                         const btVector3 &parentComToThisComOffset,
+                                                         bool disableParentCollision)
+{
+       m_dofCount += 3;
+       m_posVarCnt += 3;
+
+       m_links[i].m_mass = mass;
+       m_links[i].m_inertiaLocal = inertia;
+       m_links[i].m_parent = parent;
+       m_links[i].m_zeroRotParentToThis = rotParentToThis;
+       m_links[i].m_dVector.setZero();
+       m_links[i].m_eVector = parentComToThisComOffset;
+
+       //
+       btVector3 vecNonParallelToRotAxis(1, 0, 0);
+       if (rotationAxis.normalized().dot(vecNonParallelToRotAxis) > 0.999)
+               vecNonParallelToRotAxis.setValue(0, 1, 0);
+       //
+
+       m_links[i].m_jointType = btMultibodyLink::ePlanar;
+       m_links[i].m_dofCount = 3;
+       m_links[i].m_posVarCount = 3;
+       btVector3 n = rotationAxis.normalized();
+       m_links[i].setAxisTop(0, n[0], n[1], n[2]);
+       m_links[i].setAxisTop(1, 0, 0, 0);
+       m_links[i].setAxisTop(2, 0, 0, 0);
+       m_links[i].setAxisBottom(0, 0, 0, 0);
+       btVector3 cr = m_links[i].getAxisTop(0).cross(vecNonParallelToRotAxis);
+       m_links[i].setAxisBottom(1, cr[0], cr[1], cr[2]);
+       cr = m_links[i].getAxisBottom(1).cross(m_links[i].getAxisTop(0));
+       m_links[i].setAxisBottom(2, cr[0], cr[1], cr[2]);
+       m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f;
+       m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
+
+       if (disableParentCollision)
+               m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
+       //
+       m_links[i].updateCacheMultiDof();
+       //
+       updateLinksDofOffsets();
+
+       m_links[i].setAxisBottom(1, m_links[i].getAxisBottom(1).normalized());
+       m_links[i].setAxisBottom(2, m_links[i].getAxisBottom(2).normalized());
+}
+
+void btMultiBody::finalizeMultiDof()
+{
+       m_deltaV.resize(0);
+       m_deltaV.resize(6 + m_dofCount);
+    m_splitV.resize(0);
+    m_splitV.resize(6 + m_dofCount);
+       m_realBuf.resize(6 + m_dofCount + m_dofCount * m_dofCount + 6 + m_dofCount);  //m_dofCount for joint-space vels + m_dofCount^2 for "D" matrices + delta-pos vector (6 base "vels" + joint "vels")
+       m_vectorBuf.resize(2 * m_dofCount);                                           //two 3-vectors (i.e. one six-vector) for each system dof ("h" matrices)
+       m_matrixBuf.resize(m_links.size() + 1);
+       for (int i = 0; i < m_vectorBuf.size(); i++)
+       {
+               m_vectorBuf[i].setValue(0, 0, 0);
+       }
+       updateLinksDofOffsets();
+}
+
+int btMultiBody::getParent(int link_num) const
+{
+       return m_links[link_num].m_parent;
+}
+
+btScalar btMultiBody::getLinkMass(int i) const
+{
+       return m_links[i].m_mass;
+}
+
+const btVector3 &btMultiBody::getLinkInertia(int i) const
+{
+       return m_links[i].m_inertiaLocal;
+}
+
+btScalar btMultiBody::getJointPos(int i) const
+{
+       return m_links[i].m_jointPos[0];
+}
+
+btScalar btMultiBody::getJointVel(int i) const
+{
+       return m_realBuf[6 + m_links[i].m_dofOffset];
+}
+
+btScalar *btMultiBody::getJointPosMultiDof(int i)
+{
+       return &m_links[i].m_jointPos[0];
+}
+
+btScalar *btMultiBody::getJointVelMultiDof(int i)
+{
+       return &m_realBuf[6 + m_links[i].m_dofOffset];
+}
+
+const btScalar *btMultiBody::getJointPosMultiDof(int i) const
+{
+       return &m_links[i].m_jointPos[0];
+}
+
+const btScalar *btMultiBody::getJointVelMultiDof(int i) const
+{
+       return &m_realBuf[6 + m_links[i].m_dofOffset];
+}
+
+void btMultiBody::setJointPos(int i, btScalar q)
+{
+       m_links[i].m_jointPos[0] = q;
+       m_links[i].updateCacheMultiDof();
+}
+
+
+void btMultiBody::setJointPosMultiDof(int i, const double *q)
+{
+       for (int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
+               m_links[i].m_jointPos[pos] = (btScalar)q[pos];
+
+       m_links[i].updateCacheMultiDof();
+}
+
+void btMultiBody::setJointPosMultiDof(int i, const float *q)
+{
+       for (int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
+               m_links[i].m_jointPos[pos] = (btScalar)q[pos];
+
+       m_links[i].updateCacheMultiDof();
+}
+
+
+
+void btMultiBody::setJointVel(int i, btScalar qdot)
+{
+       m_realBuf[6 + m_links[i].m_dofOffset] = qdot;
+}
+
+void btMultiBody::setJointVelMultiDof(int i, const double *qdot)
+{
+       for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               m_realBuf[6 + m_links[i].m_dofOffset + dof] = (btScalar)qdot[dof];
+}
+
+void btMultiBody::setJointVelMultiDof(int i, const float* qdot)
+{
+       for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               m_realBuf[6 + m_links[i].m_dofOffset + dof] = (btScalar)qdot[dof];
+}
+
+const btVector3 &btMultiBody::getRVector(int i) const
+{
+       return m_links[i].m_cachedRVector;
+}
+
+const btQuaternion &btMultiBody::getParentToLocalRot(int i) const
+{
+       return m_links[i].m_cachedRotParentToThis;
+}
+
+const btVector3 &btMultiBody::getInterpolateRVector(int i) const
+{
+    return m_links[i].m_cachedRVector_interpolate;
+}
+
+const btQuaternion &btMultiBody::getInterpolateParentToLocalRot(int i) const
+{
+    return m_links[i].m_cachedRotParentToThis_interpolate;
+}
+
+btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const
+{
+       btAssert(i >= -1);
+       btAssert(i < m_links.size());
+       if ((i < -1) || (i >= m_links.size()))
+       {
+               return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
+       }
+
+       btVector3 result = local_pos;
+       while (i != -1)
+       {
+               // 'result' is in frame i. transform it to frame parent(i)
+               result += getRVector(i);
+               result = quatRotate(getParentToLocalRot(i).inverse(), result);
+               i = getParent(i);
+       }
+
+       // 'result' is now in the base frame. transform it to world frame
+       result = quatRotate(getWorldToBaseRot().inverse(), result);
+       result += getBasePos();
+
+       return result;
+}
+
+btVector3 btMultiBody::worldPosToLocal(int i, const btVector3 &world_pos) const
+{
+       btAssert(i >= -1);
+       btAssert(i < m_links.size());
+       if ((i < -1) || (i >= m_links.size()))
+       {
+               return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
+       }
+
+       if (i == -1)
+       {
+               // world to base
+               return quatRotate(getWorldToBaseRot(), (world_pos - getBasePos()));
+       }
+       else
+       {
+               // find position in parent frame, then transform to current frame
+               return quatRotate(getParentToLocalRot(i), worldPosToLocal(getParent(i), world_pos)) - getRVector(i);
+       }
+}
+
+btVector3 btMultiBody::localDirToWorld(int i, const btVector3 &local_dir) const
+{
+       btAssert(i >= -1);
+       btAssert(i < m_links.size());
+       if ((i < -1) || (i >= m_links.size()))
+       {
+               return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
+       }
+
+       btVector3 result = local_dir;
+       while (i != -1)
+       {
+               result = quatRotate(getParentToLocalRot(i).inverse(), result);
+               i = getParent(i);
+       }
+       result = quatRotate(getWorldToBaseRot().inverse(), result);
+       return result;
+}
+
+btVector3 btMultiBody::worldDirToLocal(int i, const btVector3 &world_dir) const
+{
+       btAssert(i >= -1);
+       btAssert(i < m_links.size());
+       if ((i < -1) || (i >= m_links.size()))
+       {
+               return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
+       }
+
+       if (i == -1)
+       {
+               return quatRotate(getWorldToBaseRot(), world_dir);
+       }
+       else
+       {
+               return quatRotate(getParentToLocalRot(i), worldDirToLocal(getParent(i), world_dir));
+       }
+}
+
+btMatrix3x3 btMultiBody::localFrameToWorld(int i, const btMatrix3x3 &local_frame) const
+{
+       btMatrix3x3 result = local_frame;
+       btVector3 frameInWorld0 = localDirToWorld(i, local_frame.getColumn(0));
+       btVector3 frameInWorld1 = localDirToWorld(i, local_frame.getColumn(1));
+       btVector3 frameInWorld2 = localDirToWorld(i, local_frame.getColumn(2));
+       result.setValue(frameInWorld0[0], frameInWorld1[0], frameInWorld2[0], frameInWorld0[1], frameInWorld1[1], frameInWorld2[1], frameInWorld0[2], frameInWorld1[2], frameInWorld2[2]);
+       return result;
+}
+
+void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
+{
+       int num_links = getNumLinks();
+       // Calculates the velocities of each link (and the base) in its local frame
+       const btQuaternion& base_rot = getWorldToBaseRot();
+       omega[0] = quatRotate(base_rot, getBaseOmega());
+       vel[0] = quatRotate(base_rot, getBaseVel());
+
+       for (int i = 0; i < num_links; ++i)
+       {
+               const btMultibodyLink& link = getLink(i);
+               const int parent = link.m_parent;
+
+               // transform parent vel into this frame, store in omega[i+1], vel[i+1]
+               spatialTransform(btMatrix3x3(link.m_cachedRotParentToThis), link.m_cachedRVector,
+                       omega[parent + 1], vel[parent + 1],
+                       omega[i + 1], vel[i + 1]);
+
+               // now add qidot * shat_i
+               const btScalar* jointVel = getJointVelMultiDof(i);
+               for (int dof = 0; dof < link.m_dofCount; ++dof)
+               {
+                       omega[i + 1] += jointVel[dof] * link.getAxisTop(dof);
+                       vel[i + 1] += jointVel[dof] * link.getAxisBottom(dof);
+               }
+       }
+}
+
+
+void btMultiBody::clearConstraintForces()
+{
+       m_baseConstraintForce.setValue(0, 0, 0);
+       m_baseConstraintTorque.setValue(0, 0, 0);
+
+       for (int i = 0; i < getNumLinks(); ++i)
+       {
+               m_links[i].m_appliedConstraintForce.setValue(0, 0, 0);
+               m_links[i].m_appliedConstraintTorque.setValue(0, 0, 0);
+       }
+}
+void btMultiBody::clearForcesAndTorques()
+{
+       m_baseForce.setValue(0, 0, 0);
+       m_baseTorque.setValue(0, 0, 0);
+
+       for (int i = 0; i < getNumLinks(); ++i)
+       {
+               m_links[i].m_appliedForce.setValue(0, 0, 0);
+               m_links[i].m_appliedTorque.setValue(0, 0, 0);
+               m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = m_links[i].m_jointTorque[3] = m_links[i].m_jointTorque[4] = m_links[i].m_jointTorque[5] = 0.f;
+       }
+}
+
+void btMultiBody::clearVelocities()
+{
+       for (int i = 0; i < 6 + getNumDofs(); ++i)
+       {
+               m_realBuf[i] = 0.f;
+       }
+}
+void btMultiBody::addLinkForce(int i, const btVector3 &f)
+{
+       m_links[i].m_appliedForce += f;
+}
+
+void btMultiBody::addLinkTorque(int i, const btVector3 &t)
+{
+       m_links[i].m_appliedTorque += t;
+}
+
+void btMultiBody::addLinkConstraintForce(int i, const btVector3 &f)
+{
+       m_links[i].m_appliedConstraintForce += f;
+}
+
+void btMultiBody::addLinkConstraintTorque(int i, const btVector3 &t)
+{
+       m_links[i].m_appliedConstraintTorque += t;
+}
+
+void btMultiBody::addJointTorque(int i, btScalar Q)
+{
+       m_links[i].m_jointTorque[0] += Q;
+}
+
+void btMultiBody::addJointTorqueMultiDof(int i, int dof, btScalar Q)
+{
+       m_links[i].m_jointTorque[dof] += Q;
+}
+
+void btMultiBody::addJointTorqueMultiDof(int i, const btScalar *Q)
+{
+       for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               m_links[i].m_jointTorque[dof] = Q[dof];
+}
+
+const btVector3 &btMultiBody::getLinkForce(int i) const
+{
+       return m_links[i].m_appliedForce;
+}
+
+const btVector3 &btMultiBody::getLinkTorque(int i) const
+{
+       return m_links[i].m_appliedTorque;
+}
+
+btScalar btMultiBody::getJointTorque(int i) const
+{
+       return m_links[i].m_jointTorque[0];
+}
+
+btScalar *btMultiBody::getJointTorqueMultiDof(int i)
+{
+       return &m_links[i].m_jointTorque[0];
+}
+
+bool btMultiBody::hasFixedBase() const
+{
+       return m_fixedBase || (getBaseCollider() && getBaseCollider()->isStaticObject());
+}
+
+bool btMultiBody::isBaseStaticOrKinematic() const
+{
+       return m_fixedBase || (getBaseCollider() && getBaseCollider()->isStaticOrKinematicObject());
+}
+
+bool btMultiBody::isBaseKinematic() const
+{
+       return getBaseCollider() && getBaseCollider()->isKinematicObject();
+}
+
+void btMultiBody::setBaseDynamicType(int dynamicType)
+{
+       if(getBaseCollider()) {
+               int oldFlags = getBaseCollider()->getCollisionFlags();
+               oldFlags &= ~(btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT);
+               getBaseCollider()->setCollisionFlags(oldFlags | dynamicType);
+       }
+}
+
+inline btMatrix3x3 outerProduct(const btVector3 &v0, const btVector3 &v1)  //renamed it from vecMulVecTranspose (http://en.wikipedia.org/wiki/Outer_product); maybe it should be moved to btVector3 like dot and cross?
+{
+       btVector3 row0 = btVector3(
+               v0.x() * v1.x(),
+               v0.x() * v1.y(),
+               v0.x() * v1.z());
+       btVector3 row1 = btVector3(
+               v0.y() * v1.x(),
+               v0.y() * v1.y(),
+               v0.y() * v1.z());
+       btVector3 row2 = btVector3(
+               v0.z() * v1.x(),
+               v0.z() * v1.y(),
+               v0.z() * v1.z());
+
+       btMatrix3x3 m(row0[0], row0[1], row0[2],
+                                 row1[0], row1[1], row1[2],
+                                 row2[0], row2[1], row2[2]);
+       return m;
+}
+
+#define vecMulVecTranspose(v0, v1Transposed) outerProduct(v0, v1Transposed)
+//
+
+void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
+    btAlignedObjectArray<btScalar> &scratch_r,
+    btAlignedObjectArray<btVector3> &scratch_v,
+    btAlignedObjectArray<btMatrix3x3> &scratch_m,
+       bool isConstraintPass,
+       bool jointFeedbackInWorldSpace,
+       bool jointFeedbackInJointFrame)
+{
+       // Implement Featherstone's algorithm to calculate joint accelerations (q_double_dot)
+       // and the base linear & angular accelerations.
+
+       // We apply damping forces in this routine as well as any external forces specified by the
+       // caller (via addBaseForce etc).
+
+       // output should point to an array of 6 + num_links reals.
+       // Format is: 3 angular accelerations (in world frame), 3 linear accelerations (in world frame),
+       // num_links joint acceleration values.
+
+       // We added support for multi degree of freedom (multi dof) joints.
+       // In addition we also can compute the joint reaction forces. This is performed in a second pass,
+       // so that we can include the effect of the constraint solver forces (computed in the PGS LCP solver)
+
+       m_internalNeedsJointFeedback = false;
+
+       int num_links = getNumLinks();
+
+       const btScalar DAMPING_K1_LINEAR = m_linearDamping;
+       const btScalar DAMPING_K2_LINEAR = m_linearDamping;
+
+       const btScalar DAMPING_K1_ANGULAR = m_angularDamping;
+       const btScalar DAMPING_K2_ANGULAR = m_angularDamping;
+
+       const btVector3 base_vel = getBaseVel();
+       const btVector3 base_omega = getBaseOmega();
+
+       // Temporary matrices/vectors -- use scratch space from caller
+       // so that we don't have to keep reallocating every frame
+
+       scratch_r.resize(2 * m_dofCount + 7);  //multidof? ("Y"s use it and it is used to store qdd) => 2 x m_dofCount
+       scratch_v.resize(8 * num_links + 6);
+       scratch_m.resize(4 * num_links + 4);
+
+       //btScalar * r_ptr = &scratch_r[0];
+       btScalar *output = &scratch_r[m_dofCount];  // "output" holds the q_double_dot results
+       btVector3 *v_ptr = &scratch_v[0];
+
+       // vhat_i  (top = angular, bottom = linear part)
+       btSpatialMotionVector *spatVel = (btSpatialMotionVector *)v_ptr;
+       v_ptr += num_links * 2 + 2;
+       //
+       // zhat_i^A
+       btSpatialForceVector *zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
+       v_ptr += num_links * 2 + 2;
+       //
+       // chat_i  (note NOT defined for the base)
+       btSpatialMotionVector *spatCoriolisAcc = (btSpatialMotionVector *)v_ptr;
+       v_ptr += num_links * 2;
+       //
+       // Ihat_i^A.
+       btSymmetricSpatialDyad *spatInertia = (btSymmetricSpatialDyad *)&scratch_m[num_links + 1];
+
+       // Cached 3x3 rotation matrices from parent frame to this frame.
+       btMatrix3x3 *rot_from_parent = &m_matrixBuf[0];
+       btMatrix3x3 *rot_from_world = &scratch_m[0];
+
+       // hhat_i, ahat_i
+       // hhat is NOT stored for the base (but ahat is)
+       btSpatialForceVector *h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
+       btSpatialMotionVector *spatAcc = (btSpatialMotionVector *)v_ptr;
+       v_ptr += num_links * 2 + 2;
+       //
+       // Y_i, invD_i
+       btScalar *invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
+       btScalar *Y = &scratch_r[0];
+       //
+       //aux variables
+       btSpatialMotionVector spatJointVel;         //spatial velocity due to the joint motion (i.e. without predecessors' influence)
+       btScalar D[36];                             //"D" matrix; it's dofxdof for each body so asingle 6x6 D matrix will do
+       btScalar invD_times_Y[6];                   //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
+       btSpatialMotionVector result;               //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
+       btScalar Y_minus_hT_a[6];                   //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
+       btSpatialForceVector spatForceVecTemps[6];  //6 temporary spatial force vectors
+       btSpatialTransformationMatrix fromParent;   //spatial transform from parent to child
+       btSymmetricSpatialDyad dyadTemp;            //inertia matrix temp
+       btSpatialTransformationMatrix fromWorld;
+       fromWorld.m_trnVec.setZero();
+       /////////////////
+
+       // ptr to the joint accel part of the output
+       btScalar *joint_accel = output + 6;
+
+       // Start of the algorithm proper.
+
+       // First 'upward' loop.
+       // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
+
+       rot_from_parent[0] = btMatrix3x3(m_baseQuat);  //m_baseQuat assumed to be alias!?
+
+       //create the vector of spatial velocity of the base by transforming global-coor linear and angular velocities into base-local coordinates
+       spatVel[0].setVector(rot_from_parent[0] * base_omega, rot_from_parent[0] * base_vel);
+
+       if (isBaseStaticOrKinematic())
+       {
+               zeroAccSpatFrc[0].setZero();
+       }
+       else
+       {
+               const btVector3 &baseForce = isConstraintPass ? m_baseConstraintForce : m_baseForce;
+               const btVector3 &baseTorque = isConstraintPass ? m_baseConstraintTorque : m_baseTorque;
+               //external forces
+               zeroAccSpatFrc[0].setVector(-(rot_from_parent[0] * baseTorque), -(rot_from_parent[0] * baseForce));
+
+               //adding damping terms (only)
+               const btScalar linDampMult = 1., angDampMult = 1.;
+               zeroAccSpatFrc[0].addVector(angDampMult * m_baseInertia * spatVel[0].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[0].getAngular().safeNorm()),
+                                                                       linDampMult * m_baseMass * spatVel[0].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[0].getLinear().safeNorm()));
+
+               //
+               //p += vhat x Ihat vhat - done in a simpler way
+               if (m_useGyroTerm)
+                       zeroAccSpatFrc[0].addAngular(spatVel[0].getAngular().cross(m_baseInertia * spatVel[0].getAngular()));
+               //
+               zeroAccSpatFrc[0].addLinear(m_baseMass * spatVel[0].getAngular().cross(spatVel[0].getLinear()));
+       }
+
+       //init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
+       spatInertia[0].setMatrix(btMatrix3x3(0, 0, 0, 0, 0, 0, 0, 0, 0),
+                                                        //
+                                                        btMatrix3x3(m_baseMass, 0, 0,
+                                                                                0, m_baseMass, 0,
+                                                                                0, 0, m_baseMass),
+                                                        //
+                                                        btMatrix3x3(m_baseInertia[0], 0, 0,
+                                                                                0, m_baseInertia[1], 0,
+                                                                                0, 0, m_baseInertia[2]));
+
+       rot_from_world[0] = rot_from_parent[0];
+
+       //
+       for (int i = 0; i < num_links; ++i)
+       {
+               const int parent = m_links[i].m_parent;
+               rot_from_parent[i + 1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
+               rot_from_world[i + 1] = rot_from_parent[i + 1] * rot_from_world[parent + 1];
+
+               fromParent.m_rotMat = rot_from_parent[i + 1];
+               fromParent.m_trnVec = m_links[i].m_cachedRVector;
+               fromWorld.m_rotMat = rot_from_world[i + 1];
+               fromParent.transform(spatVel[parent + 1], spatVel[i + 1]);
+
+               // now set vhat_i to its true value by doing
+               // vhat_i += qidot * shat_i
+               if (!m_useGlobalVelocities)
+               {
+                       spatJointVel.setZero();
+
+                       for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+                               spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
+
+                       // remember vhat_i is really vhat_p(i) (but in current frame) at this point     => we need to add velocity across the inboard joint
+                       spatVel[i + 1] += spatJointVel;
+
+                       //
+                       // vhat_i is vhat_p(i) transformed to local coors + the velocity across the i-th inboard joint
+                       //spatVel[i+1] = fromParent * spatVel[parent+1] + spatJointVel;
+               }
+               else
+               {
+                       fromWorld.transformRotationOnly(m_links[i].m_absFrameTotVelocity, spatVel[i + 1]);
+                       fromWorld.transformRotationOnly(m_links[i].m_absFrameLocVelocity, spatJointVel);
+               }
+
+               // we can now calculate chat_i
+               spatVel[i + 1].cross(spatJointVel, spatCoriolisAcc[i]);
+
+               // calculate zhat_i^A
+               //
+               if (isLinkAndAllAncestorsKinematic(i))
+               {
+                       zeroAccSpatFrc[i].setZero();
+               }
+               else{
+                       //external forces
+                       btVector3 linkAppliedForce = isConstraintPass ? m_links[i].m_appliedConstraintForce : m_links[i].m_appliedForce;
+                       btVector3 linkAppliedTorque = isConstraintPass ? m_links[i].m_appliedConstraintTorque : m_links[i].m_appliedTorque;
+
+                       zeroAccSpatFrc[i + 1].setVector(-(rot_from_world[i + 1] * linkAppliedTorque), -(rot_from_world[i + 1] * linkAppliedForce));
+
+#if 0  
+                       {
+
+                               b3Printf("stepVelocitiesMultiDof zeroAccSpatFrc[%d] linear:%f,%f,%f, angular:%f,%f,%f",
+                               i+1,
+                               zeroAccSpatFrc[i+1].m_topVec[0],
+                               zeroAccSpatFrc[i+1].m_topVec[1],
+                               zeroAccSpatFrc[i+1].m_topVec[2],
+
+                               zeroAccSpatFrc[i+1].m_bottomVec[0],
+                               zeroAccSpatFrc[i+1].m_bottomVec[1],
+                               zeroAccSpatFrc[i+1].m_bottomVec[2]);
+                       }
+#endif
+                       //
+                       //adding damping terms (only)
+                       btScalar linDampMult = 1., angDampMult = 1.;
+                       zeroAccSpatFrc[i + 1].addVector(angDampMult * m_links[i].m_inertiaLocal * spatVel[i + 1].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[i + 1].getAngular().safeNorm()),
+                                                                                       linDampMult * m_links[i].m_mass * spatVel[i + 1].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[i + 1].getLinear().safeNorm()));
+                       //p += vhat x Ihat vhat - done in a simpler way
+                       if (m_useGyroTerm)
+                               zeroAccSpatFrc[i + 1].addAngular(spatVel[i + 1].getAngular().cross(m_links[i].m_inertiaLocal * spatVel[i + 1].getAngular()));
+                       //
+                       zeroAccSpatFrc[i + 1].addLinear(m_links[i].m_mass * spatVel[i + 1].getAngular().cross(spatVel[i + 1].getLinear()));
+                       //
+                       //btVector3 temp = m_links[i].m_mass * spatVel[i+1].getAngular().cross(spatVel[i+1].getLinear());
+                       ////clamp parent's omega
+                       //btScalar parOmegaMod = temp.length();
+                       //btScalar parOmegaModMax = 1000;
+                       //if(parOmegaMod > parOmegaModMax)
+                       //      temp *= parOmegaModMax / parOmegaMod;
+                       //zeroAccSpatFrc[i+1].addLinear(temp);
+                       //printf("|zeroAccSpatFrc[%d]| = %.4f\n", i+1, temp.length());
+                       //temp = spatCoriolisAcc[i].getLinear();
+                       //printf("|spatCoriolisAcc[%d]| = %.4f\n", i+1, temp.length());
+               }
+
+               // calculate Ihat_i^A
+               //init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
+               spatInertia[i + 1].setMatrix(btMatrix3x3(0, 0, 0, 0, 0, 0, 0, 0, 0),
+                                                                        //
+                                                                        btMatrix3x3(m_links[i].m_mass, 0, 0,
+                                                                                                0, m_links[i].m_mass, 0,
+                                                                                                0, 0, m_links[i].m_mass),
+                                                                        //
+                                                                        btMatrix3x3(m_links[i].m_inertiaLocal[0], 0, 0,
+                                                                                                0, m_links[i].m_inertiaLocal[1], 0,
+                                                                                                0, 0, m_links[i].m_inertiaLocal[2]));
+
+               //printf("w[%d] = [%.4f %.4f %.4f]\n", i, vel_top_angular[i+1].x(), vel_top_angular[i+1].y(), vel_top_angular[i+1].z());
+               //printf("v[%d] = [%.4f %.4f %.4f]\n", i, vel_bottom_linear[i+1].x(), vel_bottom_linear[i+1].y(), vel_bottom_linear[i+1].z());
+               //printf("c[%d] = [%.4f %.4f %.4f]\n", i, coriolis_bottom_linear[i].x(), coriolis_bottom_linear[i].y(), coriolis_bottom_linear[i].z());
+       }
+
+       // 'Downward' loop.
+       // (part of TreeForwardDynamics in Mirtich.)
+       for (int i = num_links - 1; i >= 0; --i)
+       {
+               if(isLinkAndAllAncestorsKinematic(i))
+                       continue;
+               const int parent = m_links[i].m_parent;
+               fromParent.m_rotMat = rot_from_parent[i + 1];
+               fromParent.m_trnVec = m_links[i].m_cachedRVector;
+
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               {
+                       btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+                       //
+                       hDof = spatInertia[i + 1] * m_links[i].m_axes[dof];
+                       //
+                       Y[m_links[i].m_dofOffset + dof] = m_links[i].m_jointTorque[dof] - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i + 1]) - spatCoriolisAcc[i].dot(hDof);
+               }
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               {
+                       btScalar *D_row = &D[dof * m_links[i].m_dofCount];
+                       for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+                       {
+                               const btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
+                               D_row[dof2] = m_links[i].m_axes[dof].dot(hDof2);
+                       }
+               }
+
+               btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
+               switch (m_links[i].m_jointType)
+               {
+                       case btMultibodyLink::ePrismatic:
+                       case btMultibodyLink::eRevolute:
+                       {
+                               if (D[0] >= SIMD_EPSILON)
+                               {
+                                       invDi[0] = 1.0f / D[0];
+                               }
+                               else
+                               {
+                                       invDi[0] = 0;
+                               }
+                               break;
+                       }
+                       case btMultibodyLink::eSpherical:
+                       case btMultibodyLink::ePlanar:
+                       {
+                               const btMatrix3x3 D3x3(D[0], D[1], D[2], D[3], D[4], D[5], D[6], D[7], D[8]);
+                               const btMatrix3x3 invD3x3(D3x3.inverse());
+
+                               //unroll the loop?
+                               for (int row = 0; row < 3; ++row)
+                               {
+                                       for (int col = 0; col < 3; ++col)
+                                       {
+                                               invDi[row * 3 + col] = invD3x3[row][col];
+                                       }
+                               }
+
+                               break;
+                       }
+                       default:
+                       {
+                       }
+               }
+
+               //determine h*D^{-1}
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               {
+                       spatForceVecTemps[dof].setZero();
+
+                       for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+                       {
+                               const btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
+                               //
+                               spatForceVecTemps[dof] += hDof2 * invDi[dof2 * m_links[i].m_dofCount + dof];
+                       }
+               }
+
+               dyadTemp = spatInertia[i + 1];
+
+               //determine (h*D^{-1}) * h^{T}
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               {
+                       const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+                       //
+                       dyadTemp -= symmetricSpatialOuterProduct(hDof, spatForceVecTemps[dof]);
+               }
+
+               fromParent.transformInverse(dyadTemp, spatInertia[parent + 1], btSpatialTransformationMatrix::Add);
+
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               {
+                       invD_times_Y[dof] = 0.f;
+
+                       for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+                       {
+                               invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
+                       }
+               }
+
+               spatForceVecTemps[0] = zeroAccSpatFrc[i + 1] + spatInertia[i + 1] * spatCoriolisAcc[i];
+
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               {
+                       const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+                       //
+                       spatForceVecTemps[0] += hDof * invD_times_Y[dof];
+               }
+
+               fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
+
+               zeroAccSpatFrc[parent + 1] += spatForceVecTemps[1];
+       }
+
+       // Second 'upward' loop
+       // (part of TreeForwardDynamics in Mirtich)
+
+       if (isBaseStaticOrKinematic())
+       {
+               spatAcc[0].setZero();
+       }
+       else
+       {
+               if (num_links > 0)
+               {
+                       m_cachedInertiaValid = true;
+                       m_cachedInertiaTopLeft = spatInertia[0].m_topLeftMat;
+                       m_cachedInertiaTopRight = spatInertia[0].m_topRightMat;
+                       m_cachedInertiaLowerLeft = spatInertia[0].m_bottomLeftMat;
+                       m_cachedInertiaLowerRight = spatInertia[0].m_topLeftMat.transpose();
+               }
+
+               solveImatrix(zeroAccSpatFrc[0], result);
+               spatAcc[0] = -result;
+       }
+
+       // now do the loop over the m_links
+       for (int i = 0; i < num_links; ++i)
+       {
+               //      qdd = D^{-1} * (Y - h^{T}*apar) = (S^{T}*I*S)^{-1} * (tau - S^{T}*I*cor - S^{T}*zeroAccFrc - S^{T}*I*apar)
+               //      a = apar + cor + Sqdd
+               //or
+               //      qdd = D^{-1} * (Y - h^{T}*(apar+cor))
+               //      a = apar + Sqdd
+
+               const int parent = m_links[i].m_parent;
+               fromParent.m_rotMat = rot_from_parent[i + 1];
+               fromParent.m_trnVec = m_links[i].m_cachedRVector;
+
+               fromParent.transform(spatAcc[parent + 1], spatAcc[i + 1]);
+
+               if(!isLinkAndAllAncestorsKinematic(i))
+               {
+                       for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+                       {
+                               const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+                               //
+                               Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i + 1].dot(hDof);
+                       }
+                       btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
+                       //D^{-1} * (Y - h^{T}*apar)
+                       mulMatrix(invDi, Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
+
+                       spatAcc[i + 1] += spatCoriolisAcc[i];
+
+                       for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+                               spatAcc[i + 1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
+               }
+
+               if (m_links[i].m_jointFeedback)
+               {
+                       m_internalNeedsJointFeedback = true;
+
+                       btVector3 angularBotVec = (spatInertia[i + 1] * spatAcc[i + 1] + zeroAccSpatFrc[i + 1]).m_bottomVec;
+                       btVector3 linearTopVec = (spatInertia[i + 1] * spatAcc[i + 1] + zeroAccSpatFrc[i + 1]).m_topVec;
+
+                       if (jointFeedbackInJointFrame)
+                       {
+                               //shift the reaction forces to the joint frame
+                               //linear (force) component is the same
+                               //shift the angular (torque, moment) component using the relative position,  m_links[i].m_dVector
+                               angularBotVec = angularBotVec - linearTopVec.cross(m_links[i].m_dVector);
+                       }
+
+                       if (jointFeedbackInWorldSpace)
+                       {
+                               if (isConstraintPass)
+                               {
+                                       m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += m_links[i].m_cachedWorldTransform.getBasis() * angularBotVec;
+                                       m_links[i].m_jointFeedback->m_reactionForces.m_topVec += m_links[i].m_cachedWorldTransform.getBasis() * linearTopVec;
+                               }
+                               else
+                               {
+                                       m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = m_links[i].m_cachedWorldTransform.getBasis() * angularBotVec;
+                                       m_links[i].m_jointFeedback->m_reactionForces.m_topVec = m_links[i].m_cachedWorldTransform.getBasis() * linearTopVec;
+                               }
+                       }
+                       else
+                       {
+                               if (isConstraintPass)
+                               {
+                                       m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += angularBotVec;
+                                       m_links[i].m_jointFeedback->m_reactionForces.m_topVec += linearTopVec;
+                               }
+                               else
+                               {
+                                       m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = angularBotVec;
+                                       m_links[i].m_jointFeedback->m_reactionForces.m_topVec = linearTopVec;
+                               }
+                       }
+               }
+       }
+
+       // transform base accelerations back to the world frame.
+       const btVector3 omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
+       output[0] = omegadot_out[0];
+       output[1] = omegadot_out[1];
+       output[2] = omegadot_out[2];
+
+       const btVector3 vdot_out = rot_from_parent[0].transpose() * (spatAcc[0].getLinear() + spatVel[0].getAngular().cross(spatVel[0].getLinear()));
+       output[3] = vdot_out[0];
+       output[4] = vdot_out[1];
+       output[5] = vdot_out[2];
+
+       /////////////////
+       //printf("q = [");
+       //printf("%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f ", m_baseQuat.x(), m_baseQuat.y(), m_baseQuat.z(), m_baseQuat.w(), m_basePos.x(), m_basePos.y(), m_basePos.z());
+       //for(int link = 0; link < getNumLinks(); ++link)
+       //      for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
+       //              printf("%.6f ", m_links[link].m_jointPos[dof]);
+       //printf("]\n");
+       ////
+       //printf("qd = [");
+       //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
+       //      printf("%.6f ", m_realBuf[dof]);
+       //printf("]\n");
+       //printf("qdd = [");
+       //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
+       //      printf("%.6f ", output[dof]);
+       //printf("]\n");
+       /////////////////
+
+       // Final step: add the accelerations (times dt) to the velocities.
+
+       if (!isConstraintPass)
+       {
+               if (dt > 0.)
+                       applyDeltaVeeMultiDof(output, dt);
+       }
+       /////
+       //btScalar angularThres = 1;
+       //btScalar maxAngVel = 0.;
+       //bool scaleDown = 1.;
+       //for(int link = 0; link < m_links.size(); ++link)
+       //{
+       //      if(spatVel[link+1].getAngular().length() > maxAngVel)
+       //      {
+       //              maxAngVel = spatVel[link+1].getAngular().length();
+       //              scaleDown = angularThres / spatVel[link+1].getAngular().length();
+       //              break;
+       //      }
+       //}
+
+       //if(scaleDown != 1.)
+       //{
+       //      for(int link = 0; link < m_links.size(); ++link)
+       //      {
+       //              if(m_links[link].m_jointType == btMultibodyLink::eRevolute || m_links[link].m_jointType == btMultibodyLink::eSpherical)
+       //              {
+       //                      for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
+       //                              getJointVelMultiDof(link)[dof] *= scaleDown;
+       //              }
+       //      }
+       //}
+       /////
+
+       /////////////////////
+       if (m_useGlobalVelocities)
+       {
+               for (int i = 0; i < num_links; ++i)
+               {
+                       const int parent = m_links[i].m_parent;
+                       //rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);    /// <- done
+                       //rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1];                /// <- done
+
+                       fromParent.m_rotMat = rot_from_parent[i + 1];
+                       fromParent.m_trnVec = m_links[i].m_cachedRVector;
+                       fromWorld.m_rotMat = rot_from_world[i + 1];
+
+                       // vhat_i = i_xhat_p(i) * vhat_p(i)
+                       fromParent.transform(spatVel[parent + 1], spatVel[i + 1]);
+                       //nice alternative below (using operator *) but it generates temps
+                       /////////////////////////////////////////////////////////////
+
+                       // now set vhat_i to its true value by doing
+                       // vhat_i += qidot * shat_i
+                       spatJointVel.setZero();
+
+                       for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+                               spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
+
+                       // remember vhat_i is really vhat_p(i) (but in current frame) at this point     => we need to add velocity across the inboard joint
+                       spatVel[i + 1] += spatJointVel;
+
+                       fromWorld.transformInverseRotationOnly(spatVel[i + 1], m_links[i].m_absFrameTotVelocity);
+                       fromWorld.transformInverseRotationOnly(spatJointVel, m_links[i].m_absFrameLocVelocity);
+               }
+       }
+}
+
+void btMultiBody::solveImatrix(const btVector3 &rhs_top, const btVector3 &rhs_bot, btScalar result[6]) const
+{
+       int num_links = getNumLinks();
+       ///solve I * x = rhs, so the result = invI * rhs
+       if (num_links == 0)
+       {
+               // in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
+
+               if ((m_baseInertia[0] >= SIMD_EPSILON) && (m_baseInertia[1] >= SIMD_EPSILON) && (m_baseInertia[2] >= SIMD_EPSILON))
+               {
+                       result[0] = rhs_bot[0] / m_baseInertia[0];
+                       result[1] = rhs_bot[1] / m_baseInertia[1];
+                       result[2] = rhs_bot[2] / m_baseInertia[2];
+               }
+               else
+               {
+                       result[0] = 0;
+                       result[1] = 0;
+                       result[2] = 0;
+               }
+               if (m_baseMass >= SIMD_EPSILON)
+               {
+                       result[3] = rhs_top[0] / m_baseMass;
+                       result[4] = rhs_top[1] / m_baseMass;
+                       result[5] = rhs_top[2] / m_baseMass;
+               }
+               else
+               {
+                       result[3] = 0;
+                       result[4] = 0;
+                       result[5] = 0;
+               }
+       }
+       else
+       {
+               if (!m_cachedInertiaValid)
+               {
+                       for (int i = 0; i < 6; i++)
+                       {
+                               result[i] = 0.f;
+                       }
+                       return;
+               }
+               /// Special routine for calculating the inverse of a spatial inertia matrix
+               ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
+               btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse() * -1.f;
+               btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
+               btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
+               tmp = invIupper_right * m_cachedInertiaLowerRight;
+               btMatrix3x3 invI_upper_left = (tmp * Binv);
+               btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
+               tmp = m_cachedInertiaTopLeft * invI_upper_left;
+               tmp[0][0] -= 1.0;
+               tmp[1][1] -= 1.0;
+               tmp[2][2] -= 1.0;
+               btMatrix3x3 invI_lower_left = (Binv * tmp);
+
+               //multiply result = invI * rhs
+               {
+                       btVector3 vtop = invI_upper_left * rhs_top;
+                       btVector3 tmp;
+                       tmp = invIupper_right * rhs_bot;
+                       vtop += tmp;
+                       btVector3 vbot = invI_lower_left * rhs_top;
+                       tmp = invI_lower_right * rhs_bot;
+                       vbot += tmp;
+                       result[0] = vtop[0];
+                       result[1] = vtop[1];
+                       result[2] = vtop[2];
+                       result[3] = vbot[0];
+                       result[4] = vbot[1];
+                       result[5] = vbot[2];
+               }
+       }
+}
+void btMultiBody::solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const
+{
+       int num_links = getNumLinks();
+       ///solve I * x = rhs, so the result = invI * rhs
+       if (num_links == 0)
+       {
+               // in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
+               if ((m_baseInertia[0] >= SIMD_EPSILON) && (m_baseInertia[1] >= SIMD_EPSILON) && (m_baseInertia[2] >= SIMD_EPSILON))
+               {
+                       result.setAngular(rhs.getAngular() / m_baseInertia);
+               }
+               else
+               {
+                       result.setAngular(btVector3(0, 0, 0));
+               }
+               if (m_baseMass >= SIMD_EPSILON)
+               {
+                       result.setLinear(rhs.getLinear() / m_baseMass);
+               }
+               else
+               {
+                       result.setLinear(btVector3(0, 0, 0));
+               }
+       }
+       else
+       {
+               /// Special routine for calculating the inverse of a spatial inertia matrix
+               ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
+               if (!m_cachedInertiaValid)
+               {
+                       result.setLinear(btVector3(0, 0, 0));
+                       result.setAngular(btVector3(0, 0, 0));
+                       result.setVector(btVector3(0, 0, 0), btVector3(0, 0, 0));
+                       return;
+               }
+               btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse() * -1.f;
+               btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
+               btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
+               tmp = invIupper_right * m_cachedInertiaLowerRight;
+               btMatrix3x3 invI_upper_left = (tmp * Binv);
+               btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
+               tmp = m_cachedInertiaTopLeft * invI_upper_left;
+               tmp[0][0] -= 1.0;
+               tmp[1][1] -= 1.0;
+               tmp[2][2] -= 1.0;
+               btMatrix3x3 invI_lower_left = (Binv * tmp);
+
+               //multiply result = invI * rhs
+               {
+                       btVector3 vtop = invI_upper_left * rhs.getLinear();
+                       btVector3 tmp;
+                       tmp = invIupper_right * rhs.getAngular();
+                       vtop += tmp;
+                       btVector3 vbot = invI_lower_left * rhs.getLinear();
+                       tmp = invI_lower_right * rhs.getAngular();
+                       vbot += tmp;
+                       result.setVector(vtop, vbot);
+               }
+       }
+}
+
+void btMultiBody::mulMatrix(const btScalar *pA, const btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const
+{
+       for (int row = 0; row < rowsA; row++)
+       {
+               for (int col = 0; col < colsB; col++)
+               {
+                       pC[row * colsB + col] = 0.f;
+                       for (int inner = 0; inner < rowsB; inner++)
+                       {
+                               pC[row * colsB + col] += pA[row * colsA + inner] * pB[col + inner * colsB];
+                       }
+               }
+       }
+}
+
+void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
+                                                                                                btAlignedObjectArray<btScalar> &scratch_r, btAlignedObjectArray<btVector3> &scratch_v) const
+{
+       // Temporary matrices/vectors -- use scratch space from caller
+       // so that we don't have to keep reallocating every frame
+
+       int num_links = getNumLinks();
+       scratch_r.resize(m_dofCount);
+       scratch_v.resize(4 * num_links + 4);
+
+       btScalar *r_ptr = m_dofCount ? &scratch_r[0] : 0;
+       btVector3 *v_ptr = &scratch_v[0];
+
+       // zhat_i^A (scratch space)
+       btSpatialForceVector *zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
+       v_ptr += num_links * 2 + 2;
+
+       // rot_from_parent (cached from calcAccelerations)
+       const btMatrix3x3 *rot_from_parent = &m_matrixBuf[0];
+
+       // hhat (cached), accel (scratch)
+       // hhat is NOT stored for the base (but ahat is)
+       const btSpatialForceVector *h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
+       btSpatialMotionVector *spatAcc = (btSpatialMotionVector *)v_ptr;
+       v_ptr += num_links * 2 + 2;
+
+       // Y_i (scratch), invD_i (cached)
+       const btScalar *invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
+       btScalar *Y = r_ptr;
+       ////////////////
+       //aux variables
+       btScalar invD_times_Y[6];                   //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
+       btSpatialMotionVector result;               //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
+       btScalar Y_minus_hT_a[6];                   //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
+       btSpatialForceVector spatForceVecTemps[6];  //6 temporary spatial force vectors
+       btSpatialTransformationMatrix fromParent;
+       /////////////////
+
+       // First 'upward' loop.
+       // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
+
+       // Fill in zero_acc
+       // -- set to force/torque on the base, zero otherwise
+       if (isBaseStaticOrKinematic())
+       {
+               zeroAccSpatFrc[0].setZero();
+       }
+       else
+       {
+               //test forces
+               fromParent.m_rotMat = rot_from_parent[0];
+               fromParent.transformRotationOnly(btSpatialForceVector(-force[0], -force[1], -force[2], -force[3], -force[4], -force[5]), zeroAccSpatFrc[0]);
+       }
+       for (int i = 0; i < num_links; ++i)
+       {
+               zeroAccSpatFrc[i + 1].setZero();
+       }
+
+       // 'Downward' loop.
+       // (part of TreeForwardDynamics in Mirtich.)
+       for (int i = num_links - 1; i >= 0; --i)
+       {
+               if(isLinkAndAllAncestorsKinematic(i))
+                       continue;
+               const int parent = m_links[i].m_parent;
+               fromParent.m_rotMat = rot_from_parent[i + 1];
+               fromParent.m_trnVec = m_links[i].m_cachedRVector;
+
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               {
+                       Y[m_links[i].m_dofOffset + dof] = force[6 + m_links[i].m_dofOffset + dof] - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i + 1]);
+               }
+
+               btVector3 in_top, in_bottom, out_top, out_bottom;
+               const btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
+
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               {
+                       invD_times_Y[dof] = 0.f;
+
+                       for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
+                       {
+                               invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
+                       }
+               }
+
+               // Zp += pXi * (Zi + hi*Yi/Di)
+               spatForceVecTemps[0] = zeroAccSpatFrc[i + 1];
+
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               {
+                       const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+                       //
+                       spatForceVecTemps[0] += hDof * invD_times_Y[dof];
+               }
+
+               fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
+
+               zeroAccSpatFrc[parent + 1] += spatForceVecTemps[1];
+       }
+
+       // ptr to the joint accel part of the output
+       btScalar *joint_accel = output + 6;
+
+       // Second 'upward' loop
+       // (part of TreeForwardDynamics in Mirtich)
+
+       if (isBaseStaticOrKinematic())
+       {
+               spatAcc[0].setZero();
+       }
+       else
+       {
+               solveImatrix(zeroAccSpatFrc[0], result);
+               spatAcc[0] = -result;
+       }
+
+       // now do the loop over the m_links
+       for (int i = 0; i < num_links; ++i)
+       {
+               if(isLinkAndAllAncestorsKinematic(i))
+                       continue;
+               const int parent = m_links[i].m_parent;
+               fromParent.m_rotMat = rot_from_parent[i + 1];
+               fromParent.m_trnVec = m_links[i].m_cachedRVector;
+
+               fromParent.transform(spatAcc[parent + 1], spatAcc[i + 1]);
+
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+               {
+                       const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
+                       //
+                       Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i + 1].dot(hDof);
+               }
+
+               const btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
+               mulMatrix(const_cast<btScalar *>(invDi), Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
+
+               for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
+                       spatAcc[i + 1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
+       }
+
+       // transform base accelerations back to the world frame.
+       btVector3 omegadot_out;
+       omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
+       output[0] = omegadot_out[0];
+       output[1] = omegadot_out[1];
+       output[2] = omegadot_out[2];
+
+       btVector3 vdot_out;
+       vdot_out = rot_from_parent[0].transpose() * spatAcc[0].getLinear();
+       output[3] = vdot_out[0];
+       output[4] = vdot_out[1];
+       output[5] = vdot_out[2];
+
+       /////////////////
+       //printf("delta = [");
+       //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
+       //      printf("%.2f ", output[dof]);
+       //printf("]\n");
+       /////////////////
+}
+void btMultiBody::predictPositionsMultiDof(btScalar dt)
+{
+    int num_links = getNumLinks();
+               if(!isBaseKinematic())
+               {
+      // step position by adding dt * velocity
+      //btVector3 v = getBaseVel();
+      //m_basePos += dt * v;
+      //
+      btScalar *pBasePos;
+      btScalar *pBaseVel = &m_realBuf[3];  //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
+    
+       // reset to current position
+       for (int i = 0; i < 3; ++i)
+       {
+           m_basePos_interpolate[i] = m_basePos[i];
+       }
+       pBasePos = m_basePos_interpolate;
+       
+       pBasePos[0] += dt * pBaseVel[0];
+       pBasePos[1] += dt * pBaseVel[1];
+       pBasePos[2] += dt * pBaseVel[2];
+               }
+    
+    ///////////////////////////////
+    //local functor for quaternion integration (to avoid error prone redundancy)
+    struct
+    {
+        //"exponential map" based on btTransformUtil::integrateTransform(..)
+        void operator()(const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
+        {
+            //baseBody    =>    quat is alias and omega is global coor
+            //!baseBody    =>    quat is alibi and omega is local coor
+            
+            btVector3 axis;
+            btVector3 angvel;
+            
+            if (!baseBody)
+                angvel = quatRotate(quat, omega);  //if quat is not m_baseQuat, it is alibi => ok
+            else
+                angvel = omega;
+            
+            btScalar fAngle = angvel.length();
+            //limit the angular motion
+            if (fAngle * dt > ANGULAR_MOTION_THRESHOLD)
+            {
+                fAngle = btScalar(0.5) * SIMD_HALF_PI / dt;
+            }
+            
+            if (fAngle < btScalar(0.001))
+            {
+                // use Taylor's expansions of sync function
+                axis = angvel * (btScalar(0.5) * dt - (dt * dt * dt) * (btScalar(0.020833333333)) * fAngle * fAngle);
+            }
+            else
+            {
+                // sync(fAngle) = sin(c*fAngle)/t
+                axis = angvel * (btSin(btScalar(0.5) * fAngle * dt) / fAngle);
+            }
+            
+            if (!baseBody)
+                quat = btQuaternion(axis.x(), axis.y(), axis.z(), btCos(fAngle * dt * btScalar(0.5))) * quat;
+            else
+                quat = quat * btQuaternion(-axis.x(), -axis.y(), -axis.z(), btCos(fAngle * dt * btScalar(0.5)));
+            //equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();
+            
+            quat.normalize();
+        }
+    } pQuatUpdateFun;
+    ///////////////////////////////
+    
+    //pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
+    //
+               if(!isBaseKinematic())
+               {
+        btScalar *pBaseQuat;
+
+        // reset to current orientation
+        for (int i = 0; i < 4; ++i)
+        {
+            m_baseQuat_interpolate[i] = m_baseQuat[i];
+        }
+        pBaseQuat = m_baseQuat_interpolate;
+
+        btScalar *pBaseOmega = &m_realBuf[0];  //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
+        //
+        btQuaternion baseQuat;
+        baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
+        btVector3 baseOmega;
+        baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
+        pQuatUpdateFun(baseOmega, baseQuat, true, dt);
+        pBaseQuat[0] = baseQuat.x();
+        pBaseQuat[1] = baseQuat.y();
+        pBaseQuat[2] = baseQuat.z();
+        pBaseQuat[3] = baseQuat.w();
+               }
+
+    // Finally we can update m_jointPos for each of the m_links
+    for (int i = 0; i < num_links; ++i)
+    {
+        btScalar *pJointPos;
+        pJointPos = &m_links[i].m_jointPos_interpolate[0];
+        
+        if (m_links[i].m_collider && m_links[i].m_collider->isStaticOrKinematic()) 
+               {
+            switch (m_links[i].m_jointType) 
+                                               {
+                case btMultibodyLink::ePrismatic:
+                case btMultibodyLink::eRevolute:
+                {
+                    pJointPos[0] = m_links[i].m_jointPos[0];
+                    break;
+                }
+                case btMultibodyLink::eSpherical:
+                {
+                    for (int j = 0; j < 4; ++j)
+                    {
+                        pJointPos[j] = m_links[i].m_jointPos[j];
+                    }
+                    break;
+                }
+                case btMultibodyLink::ePlanar:
+                {
+                    for (int j = 0; j < 3; ++j)
+                    {
+                        pJointPos[j] = m_links[i].m_jointPos[j];
+                    }
+                    break;
+                }
+                default:
+                   break;
+            }
+        }
+        else
+        {
+            btScalar *pJointVel = getJointVelMultiDof(i); 
+
+            switch (m_links[i].m_jointType)
+            {
+                case btMultibodyLink::ePrismatic:
+                case btMultibodyLink::eRevolute:
+                {
+                    //reset to current pos
+                    pJointPos[0] = m_links[i].m_jointPos[0];
+                    btScalar jointVel = pJointVel[0];
+                    pJointPos[0] += dt * jointVel;
+                    break;
+                }
+                case btMultibodyLink::eSpherical:
+                {
+                    //reset to current pos
+
+                    for (int j = 0; j < 4; ++j)
+                    {
+                        pJointPos[j] = m_links[i].m_jointPos[j];
+                    }
+                    
+                    btVector3 jointVel;
+                    jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
+                    btQuaternion jointOri;
+                    jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
+                    pQuatUpdateFun(jointVel, jointOri, false, dt);
+                    pJointPos[0] = jointOri.x();
+                    pJointPos[1] = jointOri.y();
+                    pJointPos[2] = jointOri.z();
+                    pJointPos[3] = jointOri.w();
+                    break;
+                }
+                case btMultibodyLink::ePlanar:
+                {
+                    for (int j = 0; j < 3; ++j)
+                    {
+                        pJointPos[j] = m_links[i].m_jointPos[j];
+                    }
+                    pJointPos[0] += dt * getJointVelMultiDof(i)[0];
+                    
+                    btVector3 q0_coors_qd1qd2 = getJointVelMultiDof(i)[1] * m_links[i].getAxisBottom(1) + getJointVelMultiDof(i)[2] * m_links[i].getAxisBottom(2);
+                    btVector3 no_q0_coors_qd1qd2 = quatRotate(btQuaternion(m_links[i].getAxisTop(0), pJointPos[0]), q0_coors_qd1qd2);
+                    pJointPos[1] += m_links[i].getAxisBottom(1).dot(no_q0_coors_qd1qd2) * dt;
+                    pJointPos[2] += m_links[i].getAxisBottom(2).dot(no_q0_coors_qd1qd2) * dt;
+                    break;
+                }
+                default:
+                {
+                }
+            }
+        }
+        
+        m_links[i].updateInterpolationCacheMultiDof();
+    }
+}
+
+void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd)
+{
+       int num_links = getNumLinks();
+       if(!isBaseKinematic())
+       {
+               // step position by adding dt * velocity
+               //btVector3 v = getBaseVel();
+               //m_basePos += dt * v;
+               //
+         btScalar *pBasePos = (pq ? &pq[4] : m_basePos);
+         btScalar *pBaseVel = (pqd ? &pqd[3] : &m_realBuf[3]);  //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
+         
+               pBasePos[0] += dt * pBaseVel[0];
+               pBasePos[1] += dt * pBaseVel[1];
+               pBasePos[2] += dt * pBaseVel[2];
+       }
+
+       ///////////////////////////////
+       //local functor for quaternion integration (to avoid error prone redundancy)
+       struct
+       {
+               //"exponential map" based on btTransformUtil::integrateTransform(..)
+               void operator()(const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
+               {
+                       //baseBody      =>      quat is alias and omega is global coor
+                       //!baseBody     =>      quat is alibi and omega is local coor
+
+                       btVector3 axis;
+                       btVector3 angvel;
+
+                       if (!baseBody)
+                               angvel = quatRotate(quat, omega);  //if quat is not m_baseQuat, it is alibi => ok
+                       else
+                               angvel = omega;
+
+                       btScalar fAngle = angvel.length();
+                       //limit the angular motion
+                       if (fAngle * dt > ANGULAR_MOTION_THRESHOLD)
+                       {
+                               fAngle = btScalar(0.5) * SIMD_HALF_PI / dt;
+                       }
+
+                       if (fAngle < btScalar(0.001))
+                       {
+                               // use Taylor's expansions of sync function
+                               axis = angvel * (btScalar(0.5) * dt - (dt * dt * dt) * (btScalar(0.020833333333)) * fAngle * fAngle);
+                       }
+                       else
+                       {
+                               // sync(fAngle) = sin(c*fAngle)/t
+                               axis = angvel * (btSin(btScalar(0.5) * fAngle * dt) / fAngle);
+                       }
+
+                       if (!baseBody)
+                               quat = btQuaternion(axis.x(), axis.y(), axis.z(), btCos(fAngle * dt * btScalar(0.5))) * quat;
+                       else
+                               quat = quat * btQuaternion(-axis.x(), -axis.y(), -axis.z(), btCos(fAngle * dt * btScalar(0.5)));
+                       //equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();
+
+                       quat.normalize();
+               }
+       } pQuatUpdateFun;
+       ///////////////////////////////
+
+       //pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
+       //
+       if(!isBaseKinematic())
+       {
+               btScalar *pBaseQuat = pq ? pq : m_baseQuat;
+               btScalar *pBaseOmega = pqd ? pqd : &m_realBuf[0];  //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
+               //
+               btQuaternion baseQuat;
+               baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
+               btVector3 baseOmega;
+               baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
+               pQuatUpdateFun(baseOmega, baseQuat, true, dt);
+               pBaseQuat[0] = baseQuat.x();
+               pBaseQuat[1] = baseQuat.y();
+               pBaseQuat[2] = baseQuat.z();
+               pBaseQuat[3] = baseQuat.w();
+
+               //printf("pBaseOmega = %.4f %.4f %.4f\n", pBaseOmega->x(), pBaseOmega->y(), pBaseOmega->z());
+               //printf("pBaseVel = %.4f %.4f %.4f\n", pBaseVel->x(), pBaseVel->y(), pBaseVel->z());
+               //printf("baseQuat = %.4f %.4f %.4f %.4f\n", pBaseQuat->x(), pBaseQuat->y(), pBaseQuat->z(), pBaseQuat->w());
+       }
+
+       if (pq)
+               pq += 7;
+       if (pqd)
+               pqd += 6;
+
+       // Finally we can update m_jointPos for each of the m_links
+       for (int i = 0; i < num_links; ++i)
+       {
+               if (!(m_links[i].m_collider && m_links[i].m_collider->isStaticOrKinematic()))
+               {
+                       btScalar *pJointPos;
+                       pJointPos= (pq ? pq : &m_links[i].m_jointPos[0]);
+               
+                       btScalar *pJointVel = (pqd ? pqd : getJointVelMultiDof(i));
+
+                       switch (m_links[i].m_jointType)
+                       {
+                               case btMultibodyLink::ePrismatic:
+                               case btMultibodyLink::eRevolute:
+                               {
+                   //reset to current pos
+                                       btScalar jointVel = pJointVel[0];
+                                       pJointPos[0] += dt * jointVel;
+                                       break;
+                               }
+                               case btMultibodyLink::eSpherical:
+                               {
+                   //reset to current pos
+                                       btVector3 jointVel;
+                                       jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
+                                       btQuaternion jointOri;
+                                       jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
+                                       pQuatUpdateFun(jointVel, jointOri, false, dt);
+                                       pJointPos[0] = jointOri.x();
+                                       pJointPos[1] = jointOri.y();
+                                       pJointPos[2] = jointOri.z();
+                                       pJointPos[3] = jointOri.w();
+                                       break;
+                               }
+                               case btMultibodyLink::ePlanar:
+                               {
+                                       pJointPos[0] += dt * getJointVelMultiDof(i)[0];
+
+                                       btVector3 q0_coors_qd1qd2 = getJointVelMultiDof(i)[1] * m_links[i].getAxisBottom(1) + getJointVelMultiDof(i)[2] * m_links[i].getAxisBottom(2);
+                                       btVector3 no_q0_coors_qd1qd2 = quatRotate(btQuaternion(m_links[i].getAxisTop(0), pJointPos[0]), q0_coors_qd1qd2);
+                                       pJointPos[1] += m_links[i].getAxisBottom(1).dot(no_q0_coors_qd1qd2) * dt;
+                                       pJointPos[2] += m_links[i].getAxisBottom(2).dot(no_q0_coors_qd1qd2) * dt;
+
+                                       break;
+                               }
+                               default:
+                               {
+                               }
+                       }
+               }
+
+               m_links[i].updateCacheMultiDof(pq);
+
+               if (pq)
+                       pq += m_links[i].m_posVarCount;
+               if (pqd)
+                       pqd += m_links[i].m_dofCount;
+       }
+}
+
+void btMultiBody::fillConstraintJacobianMultiDof(int link,
+                                                                                                const btVector3 &contact_point,
+                                                                                                const btVector3 &normal_ang,
+                                                                                                const btVector3 &normal_lin,
+                                                                                                btScalar *jac,
+                                                                                                btAlignedObjectArray<btScalar> &scratch_r1,
+                                                                                                btAlignedObjectArray<btVector3> &scratch_v,
+                                                                                                btAlignedObjectArray<btMatrix3x3> &scratch_m) const
+{
+       // temporary space
+       int num_links = getNumLinks();
+       int m_dofCount = getNumDofs();
+       scratch_v.resize(3 * num_links + 3);  //(num_links + base) offsets + (num_links + base) normals_lin + (num_links + base) normals_ang
+       scratch_m.resize(num_links + 1);
+
+       btVector3 *v_ptr = &scratch_v[0];
+       btVector3 *p_minus_com_local = v_ptr;
+       v_ptr += num_links + 1;
+       btVector3 *n_local_lin = v_ptr;
+       v_ptr += num_links + 1;
+       btVector3 *n_local_ang = v_ptr;
+       v_ptr += num_links + 1;
+       btAssert(v_ptr - &scratch_v[0] == scratch_v.size());
+
+       //scratch_r.resize(m_dofCount);
+       //btScalar *results = m_dofCount > 0 ? &scratch_r[0] : 0;
+
+    scratch_r1.resize(m_dofCount+num_links);
+    btScalar * results = m_dofCount > 0 ? &scratch_r1[0] : 0;
+    btScalar* links = num_links? &scratch_r1[m_dofCount] : 0;
+    int numLinksChildToRoot=0;
+    int l = link;
+    while (l != -1)
+    {
+        links[numLinksChildToRoot++]=l;
+        l = m_links[l].m_parent;
+    }
+    
+       btMatrix3x3 *rot_from_world = &scratch_m[0];
+
+       const btVector3 p_minus_com_world = contact_point - m_basePos;
+       const btVector3 &normal_lin_world = normal_lin;  //convenience
+       const btVector3 &normal_ang_world = normal_ang;
+
+       rot_from_world[0] = btMatrix3x3(m_baseQuat);
+
+       // omega coeffients first.
+       btVector3 omega_coeffs_world;
+       omega_coeffs_world = p_minus_com_world.cross(normal_lin_world);
+       jac[0] = omega_coeffs_world[0] + normal_ang_world[0];
+       jac[1] = omega_coeffs_world[1] + normal_ang_world[1];
+       jac[2] = omega_coeffs_world[2] + normal_ang_world[2];
+       // then v coefficients
+       jac[3] = normal_lin_world[0];
+       jac[4] = normal_lin_world[1];
+       jac[5] = normal_lin_world[2];
+
+       //create link-local versions of p_minus_com and normal
+       p_minus_com_local[0] = rot_from_world[0] * p_minus_com_world;
+       n_local_lin[0] = rot_from_world[0] * normal_lin_world;
+       n_local_ang[0] = rot_from_world[0] * normal_ang_world;
+
+       // Set remaining jac values to zero for now.
+       for (int i = 6; i < 6 + m_dofCount; ++i)
+       {
+               jac[i] = 0;
+       }
+
+       // Qdot coefficients, if necessary.
+       if (num_links > 0 && link > -1)
+       {
+        // TODO: (Also, we are making 3 separate calls to this function, for the normal & the 2 friction directions,
+               // which is resulting in repeated work being done...)
+
+               // calculate required normals & positions in the local frames.
+        for (int a = 0; a < numLinksChildToRoot; a++)
+        {
+            int i = links[numLinksChildToRoot-1-a];
+               // transform to local frame
+                       const int parent = m_links[i].m_parent;
+                       const btMatrix3x3 mtx(m_links[i].m_cachedRotParentToThis);
+                       rot_from_world[i + 1] = mtx * rot_from_world[parent + 1];
+
+                       n_local_lin[i + 1] = mtx * n_local_lin[parent + 1];
+                       n_local_ang[i + 1] = mtx * n_local_ang[parent + 1];
+                       p_minus_com_local[i + 1] = mtx * p_minus_com_local[parent + 1] - m_links[i].m_cachedRVector;
+
+                       // calculate the jacobian entry
+                       switch (m_links[i].m_jointType)
+                       {
+                               case btMultibodyLink::eRevolute:
+                               {
+                                       results[m_links[i].m_dofOffset] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(0));
+                                       results[m_links[i].m_dofOffset] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(0));
+                                       break;
+                               }
+                               case btMultibodyLink::ePrismatic:
+                               {
+                                       results[m_links[i].m_dofOffset] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(0));
+                                       break;
+                               }
+                               case btMultibodyLink::eSpherical:
+                               {
+                                       results[m_links[i].m_dofOffset + 0] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(0));
+                                       results[m_links[i].m_dofOffset + 1] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(1).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(1));
+                                       results[m_links[i].m_dofOffset + 2] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(2).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(2));
+
+                                       results[m_links[i].m_dofOffset + 0] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(0));
+                                       results[m_links[i].m_dofOffset + 1] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(1));
+                                       results[m_links[i].m_dofOffset + 2] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(2));
+
+                                       break;
+                               }
+                               case btMultibodyLink::ePlanar:
+                               {
+                                       results[m_links[i].m_dofOffset + 0] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1]));  // + m_links[i].getAxisBottom(0));
+                                       results[m_links[i].m_dofOffset + 1] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(1));
+                                       results[m_links[i].m_dofOffset + 2] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(2));
+
+                                       break;
+                               }
+                               default:
+                               {
+                               }
+                       }
+               }
+
+               // Now copy through to output.
+               //printf("jac[%d] = ", link);
+               while (link != -1)
+               {
+                       for (int dof = 0; dof < m_links[link].m_dofCount; ++dof)
+                       {
+                               jac[6 + m_links[link].m_dofOffset + dof] = results[m_links[link].m_dofOffset + dof];
+                               //printf("%.2f\t", jac[6 + m_links[link].m_dofOffset + dof]);
+                       }
+
+                       link = m_links[link].m_parent;
+               }
+               //printf("]\n");
+       }
+}
+
+void btMultiBody::wakeUp()
+{
+       m_sleepTimer = 0;
+       m_awake = true;
+}
+
+void btMultiBody::goToSleep()
+{
+       m_awake = false;
+}
+
+void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep)
+{
+       extern bool gDisableDeactivation;
+       if (!m_canSleep || gDisableDeactivation)
+       {
+               m_awake = true;
+               m_sleepTimer = 0;
+               return;
+       }
+
+       
+
+       // motion is computed as omega^2 + v^2 + (sum of squares of joint velocities)
+       btScalar motion = 0;
+       {
+               for (int i = 0; i < 6 + m_dofCount; ++i)
+                       motion += m_realBuf[i] * m_realBuf[i];
+       }
+
+       if (motion < m_sleepEpsilon)
+       {
+               m_sleepTimer += timestep;
+               if (m_sleepTimer > m_sleepTimeout)
+               {
+                       goToSleep();
+               }
+       }
+       else
+       {
+               m_sleepTimer = 0;
+               if (m_canWakeup)
+               {
+                       if (!m_awake)
+                               wakeUp();
+               }
+       }
+}
+
+void btMultiBody::forwardKinematics(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
+{
+       int num_links = getNumLinks();
+
+       // Cached 3x3 rotation matrices from parent frame to this frame.
+       btMatrix3x3 *rot_from_parent = (btMatrix3x3 *)&m_matrixBuf[0];
+
+       rot_from_parent[0] = btMatrix3x3(m_baseQuat);  //m_baseQuat assumed to be alias!?
+
+       for (int i = 0; i < num_links; ++i)
+       {
+               rot_from_parent[i + 1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
+       }
+
+       int nLinks = getNumLinks();
+       ///base + num m_links
+       world_to_local.resize(nLinks + 1);
+       local_origin.resize(nLinks + 1);
+
+       world_to_local[0] = getWorldToBaseRot();
+       local_origin[0] = getBasePos();
+
+       for (int k = 0; k < getNumLinks(); k++)
+       {
+               const int parent = getParent(k);
+               world_to_local[k + 1] = getParentToLocalRot(k) * world_to_local[parent + 1];
+               local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getRVector(k)));
+       }
+
+       for (int link = 0; link < getNumLinks(); link++)
+       {
+               int index = link + 1;
+
+               btVector3 posr = local_origin[index];
+               btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
+               btTransform tr;
+               tr.setIdentity();
+               tr.setOrigin(posr);
+               tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+               getLink(link).m_cachedWorldTransform = tr;
+       }
+}
+
+void btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
+{
+       world_to_local.resize(getNumLinks() + 1);
+       local_origin.resize(getNumLinks() + 1);
+
+       world_to_local[0] = getWorldToBaseRot();
+       local_origin[0] = getBasePos();
+
+       if (getBaseCollider())
+       {
+               btVector3 posr = local_origin[0];
+               //      float pos[4]={posr.x(),posr.y(),posr.z(),1};
+               btScalar quat[4] = {-world_to_local[0].x(), -world_to_local[0].y(), -world_to_local[0].z(), world_to_local[0].w()};
+               btTransform tr;
+               tr.setIdentity();
+               tr.setOrigin(posr);
+               tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+
+               getBaseCollider()->setWorldTransform(tr);
+        getBaseCollider()->setInterpolationWorldTransform(tr);
+       }
+
+       for (int k = 0; k < getNumLinks(); k++)
+       {
+               const int parent = getParent(k);
+               world_to_local[k + 1] = getParentToLocalRot(k) * world_to_local[parent + 1];
+               local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getRVector(k)));
+       }
+
+       for (int m = 0; m < getNumLinks(); m++)
+       {
+               btMultiBodyLinkCollider *col = getLink(m).m_collider;
+               if (col)
+               {
+                       int link = col->m_link;
+                       btAssert(link == m);
+
+                       int index = link + 1;
+
+                       btVector3 posr = local_origin[index];
+                       //                      float pos[4]={posr.x(),posr.y(),posr.z(),1};
+                       btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
+                       btTransform tr;
+                       tr.setIdentity();
+                       tr.setOrigin(posr);
+                       tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+
+                       col->setWorldTransform(tr);
+            col->setInterpolationWorldTransform(tr);
+               }
+       }
+}
+
+void btMultiBody::updateCollisionObjectInterpolationWorldTransforms(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
+{
+    world_to_local.resize(getNumLinks() + 1);
+    local_origin.resize(getNumLinks() + 1);
+    
+               if(isBaseKinematic()){
+        world_to_local[0] = getWorldToBaseRot();
+        local_origin[0] = getBasePos();
+               }
+               else
+               {
+        world_to_local[0] = getInterpolateWorldToBaseRot();
+        local_origin[0] = getInterpolateBasePos();
+               }
+    
+    if (getBaseCollider())
+    {
+        btVector3 posr = local_origin[0];
+        //    float pos[4]={posr.x(),posr.y(),posr.z(),1};
+        btScalar quat[4] = {-world_to_local[0].x(), -world_to_local[0].y(), -world_to_local[0].z(), world_to_local[0].w()};
+        btTransform tr;
+        tr.setIdentity();
+        tr.setOrigin(posr);
+        tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+        
+        getBaseCollider()->setInterpolationWorldTransform(tr);
+    }
+    
+    for (int k = 0; k < getNumLinks(); k++)
+    {
+        const int parent = getParent(k);
+        world_to_local[k + 1] = getInterpolateParentToLocalRot(k) * world_to_local[parent + 1];
+        local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getInterpolateRVector(k)));
+    }
+    
+    for (int m = 0; m < getNumLinks(); m++)
+    {
+        btMultiBodyLinkCollider *col = getLink(m).m_collider;
+        if (col)
+        {
+            int link = col->m_link;
+            btAssert(link == m);
+            
+            int index = link + 1;
+            
+            btVector3 posr = local_origin[index];
+            //            float pos[4]={posr.x(),posr.y(),posr.z(),1};
+            btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
+            btTransform tr;
+            tr.setIdentity();
+            tr.setOrigin(posr);
+            tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
+            
+            col->setInterpolationWorldTransform(tr);
+        }
+    }
+}
+
+int btMultiBody::calculateSerializeBufferSize() const
+{
+       int sz = sizeof(btMultiBodyData);
+       return sz;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char *btMultiBody::serialize(void *dataBuffer, class btSerializer *serializer) const
+{
+       btMultiBodyData *mbd = (btMultiBodyData *)dataBuffer;
+       getBasePos().serialize(mbd->m_baseWorldPosition);
+       getWorldToBaseRot().inverse().serialize(mbd->m_baseWorldOrientation);
+       getBaseVel().serialize(mbd->m_baseLinearVelocity);
+       getBaseOmega().serialize(mbd->m_baseAngularVelocity);
+
+       mbd->m_baseMass = this->getBaseMass();
+       getBaseInertia().serialize(mbd->m_baseInertia);
+       {
+               char *name = (char *)serializer->findNameForPointer(m_baseName);
+               mbd->m_baseName = (char *)serializer->getUniquePointer(name);
+               if (mbd->m_baseName)
+               {
+                       serializer->serializeName(name);
+               }
+       }
+       mbd->m_numLinks = this->getNumLinks();
+       if (mbd->m_numLinks)
+       {
+               int sz = sizeof(btMultiBodyLinkData);
+               int numElem = mbd->m_numLinks;
+               btChunk *chunk = serializer->allocate(sz, numElem);
+               btMultiBodyLinkData *memPtr = (btMultiBodyLinkData *)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       memPtr->m_jointType = getLink(i).m_jointType;
+                       memPtr->m_dofCount = getLink(i).m_dofCount;
+                       memPtr->m_posVarCount = getLink(i).m_posVarCount;
+
+                       getLink(i).m_inertiaLocal.serialize(memPtr->m_linkInertia);
+
+                       getLink(i).m_absFrameTotVelocity.m_topVec.serialize(memPtr->m_absFrameTotVelocityTop);
+                       getLink(i).m_absFrameTotVelocity.m_bottomVec.serialize(memPtr->m_absFrameTotVelocityBottom);
+                       getLink(i).m_absFrameLocVelocity.m_topVec.serialize(memPtr->m_absFrameLocVelocityTop);
+                       getLink(i).m_absFrameLocVelocity.m_bottomVec.serialize(memPtr->m_absFrameLocVelocityBottom);
+
+                       memPtr->m_linkMass = getLink(i).m_mass;
+                       memPtr->m_parentIndex = getLink(i).m_parent;
+                       memPtr->m_jointDamping = getLink(i).m_jointDamping;
+                       memPtr->m_jointFriction = getLink(i).m_jointFriction;
+                       memPtr->m_jointLowerLimit = getLink(i).m_jointLowerLimit;
+                       memPtr->m_jointUpperLimit = getLink(i).m_jointUpperLimit;
+                       memPtr->m_jointMaxForce = getLink(i).m_jointMaxForce;
+                       memPtr->m_jointMaxVelocity = getLink(i).m_jointMaxVelocity;
+
+                       getLink(i).m_eVector.serialize(memPtr->m_parentComToThisPivotOffset);
+                       getLink(i).m_dVector.serialize(memPtr->m_thisPivotToThisComOffset);
+                       getLink(i).m_zeroRotParentToThis.serialize(memPtr->m_zeroRotParentToThis);
+                       btAssert(memPtr->m_dofCount <= 3);
+                       for (int dof = 0; dof < getLink(i).m_dofCount; dof++)
+                       {
+                               getLink(i).getAxisBottom(dof).serialize(memPtr->m_jointAxisBottom[dof]);
+                               getLink(i).getAxisTop(dof).serialize(memPtr->m_jointAxisTop[dof]);
+
+                               memPtr->m_jointTorque[dof] = getLink(i).m_jointTorque[dof];
+                               memPtr->m_jointVel[dof] = getJointVelMultiDof(i)[dof];
+                       }
+                       int numPosVar = getLink(i).m_posVarCount;
+                       for (int posvar = 0; posvar < numPosVar; posvar++)
+                       {
+                               memPtr->m_jointPos[posvar] = getLink(i).m_jointPos[posvar];
+                       }
+
+                       {
+                               char *name = (char *)serializer->findNameForPointer(m_links[i].m_linkName);
+                               memPtr->m_linkName = (char *)serializer->getUniquePointer(name);
+                               if (memPtr->m_linkName)
+                               {
+                                       serializer->serializeName(name);
+                               }
+                       }
+                       {
+                               char *name = (char *)serializer->findNameForPointer(m_links[i].m_jointName);
+                               memPtr->m_jointName = (char *)serializer->getUniquePointer(name);
+                               if (memPtr->m_jointName)
+                               {
+                                       serializer->serializeName(name);
+                               }
+                       }
+                       memPtr->m_linkCollider = (btCollisionObjectData *)serializer->getUniquePointer(getLink(i).m_collider);
+               }
+               serializer->finalizeChunk(chunk, btMultiBodyLinkDataName, BT_ARRAY_CODE, (void *)&m_links[0]);
+       }
+       mbd->m_links = mbd->m_numLinks ? (btMultiBodyLinkData *)serializer->getUniquePointer((void *)&m_links[0]) : 0;
+
+       // Fill padding with zeros to appease msan.
+#ifdef BT_USE_DOUBLE_PRECISION
+       memset(mbd->m_padding, 0, sizeof(mbd->m_padding));
+#endif
+
+       return btMultiBodyDataName;
+}
+
+void btMultiBody::saveKinematicState(btScalar timeStep)
+{
+       //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
+       if (m_kinematic_calculate_velocity && timeStep != btScalar(0.))
+       {
+               btVector3 linearVelocity, angularVelocity;
+               btTransformUtil::calculateVelocity(getInterpolateBaseWorldTransform(), getBaseWorldTransform(), timeStep, linearVelocity, angularVelocity);
+               setBaseVel(linearVelocity);
+               setBaseOmega(angularVelocity);
+               setInterpolateBaseWorldTransform(getBaseWorldTransform());
+       }
+}
+
+void btMultiBody::setLinkDynamicType(const int i, int type)
+{
+       if (i == -1)
+       {
+               setBaseDynamicType(type);
+       }
+       else if (i >= 0 && i < getNumLinks())
+       {
+               if (m_links[i].m_collider)
+               {
+                       m_links[i].m_collider->setDynamicType(type);
+               }
+       }
+}
+
+bool btMultiBody::isLinkStaticOrKinematic(const int i) const
+{
+       if (i == -1)
+       {
+               return isBaseStaticOrKinematic();
+       }
+       else
+       {
+               if (m_links[i].m_collider)
+                       return m_links[i].m_collider->isStaticOrKinematic();
+       }
+       return false;
+}
+
+bool btMultiBody::isLinkKinematic(const int i) const
+{
+       if (i == -1)
+       {
+               return isBaseKinematic();
+       }
+       else
+       {
+               if (m_links[i].m_collider)
+                       return m_links[i].m_collider->isKinematic();
+       }
+       return false;
+}
+
+bool btMultiBody::isLinkAndAllAncestorsStaticOrKinematic(const int i) const
+{
+       int link = i;
+       while (link != -1) {
+               if (!isLinkStaticOrKinematic(link))
+                       return false;
+               link = m_links[link].m_parent;
+       }
+       return isBaseStaticOrKinematic();
+}
+
+bool btMultiBody::isLinkAndAllAncestorsKinematic(const int i) const
+{
+       int link = i;
+       while (link != -1) {
+               if (!isLinkKinematic(link))
+                       return false;
+               link = m_links[link].m_parent;
+       }
+       return isBaseKinematic();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBody.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBody.h
new file mode 100644 (file)
index 0000000..345970d
--- /dev/null
@@ -0,0 +1,953 @@
+/*
+ * PURPOSE:
+ *   Class representing an articulated rigid body. Stores the body's
+ *   current state, allows forces and torques to be set, handles
+ *   timestepping and implements Featherstone's algorithm.
+ *   
+ * COPYRIGHT:
+ *   Copyright (C) Stephen Thompson, <stephen@solarflare.org.uk>, 2011-2013
+ *   Portions written By Erwin Coumans: connection to LCP solver, various multibody constraints, replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix)
+ *   Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements
+
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_MULTIBODY_H
+#define BT_MULTIBODY_H
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+///serialization data, don't change them if you are not familiar with the details of the serialization mechanisms
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btMultiBodyData btMultiBodyDoubleData
+#define btMultiBodyDataName "btMultiBodyDoubleData"
+#define btMultiBodyLinkData btMultiBodyLinkDoubleData
+#define btMultiBodyLinkDataName "btMultiBodyLinkDoubleData"
+#else
+#define btMultiBodyData btMultiBodyFloatData
+#define btMultiBodyDataName "btMultiBodyFloatData"
+#define btMultiBodyLinkData btMultiBodyLinkFloatData
+#define btMultiBodyLinkDataName "btMultiBodyLinkFloatData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+#include "btMultiBodyLink.h"
+class btMultiBodyLinkCollider;
+
+ATTRIBUTE_ALIGNED16(class)
+btMultiBody
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       //
+       // initialization
+       //
+
+       btMultiBody(int n_links,               // NOT including the base
+                               btScalar mass,             // mass of base
+                               const btVector3 &inertia,  // inertia of base, in base frame; assumed diagonal
+                               bool fixedBase,            // whether the base is fixed (true) or can move (false)
+                               bool canSleep, bool deprecatedMultiDof = true);
+
+       virtual ~btMultiBody();
+
+       //note: fixed link collision with parent is always disabled
+       void setupFixed(int i, //linkIndex
+                                       btScalar mass,
+                                       const btVector3 &inertia,
+                                       int parent,
+                                       const btQuaternion &rotParentToThis,
+                                       const btVector3 &parentComToThisPivotOffset,
+                                       const btVector3 &thisPivotToThisComOffset, bool deprecatedDisableParentCollision = true);
+
+       void setupPrismatic(int i,
+                                               btScalar mass,
+                                               const btVector3 &inertia,
+                                               int parent,
+                                               const btQuaternion &rotParentToThis,
+                                               const btVector3 &jointAxis,
+                                               const btVector3 &parentComToThisPivotOffset,
+                                               const btVector3 &thisPivotToThisComOffset,
+                                               bool disableParentCollision);
+
+       void setupRevolute(int i,  // 0 to num_links-1
+                                          btScalar mass,
+                                          const btVector3 &inertia,
+                                          int parentIndex,
+                                          const btQuaternion &rotParentToThis,          // rotate points in parent frame to this frame, when q = 0
+                                          const btVector3 &jointAxis,                   // in my frame
+                                          const btVector3 &parentComToThisPivotOffset,  // vector from parent COM to joint axis, in PARENT frame
+                                          const btVector3 &thisPivotToThisComOffset,    // vector from joint axis to my COM, in MY frame
+                                          bool disableParentCollision = false);
+
+       void setupSpherical(int i,  // linkIndex, 0 to num_links-1
+                                               btScalar mass,
+                                               const btVector3 &inertia,
+                                               int parent,
+                                               const btQuaternion &rotParentToThis,          // rotate points in parent frame to this frame, when q = 0
+                                               const btVector3 &parentComToThisPivotOffset,  // vector from parent COM to joint axis, in PARENT frame
+                                               const btVector3 &thisPivotToThisComOffset,    // vector from joint axis to my COM, in MY frame
+                                               bool disableParentCollision = false);
+
+       void setupPlanar(int i,  // 0 to num_links-1
+                                        btScalar mass,
+                                        const btVector3 &inertia,
+                                        int parent,
+                                        const btQuaternion &rotParentToThis,  // rotate points in parent frame to this frame, when q = 0
+                                        const btVector3 &rotationAxis,
+                                        const btVector3 &parentComToThisComOffset,  // vector from parent COM to this COM, in PARENT frame
+                                        bool disableParentCollision = false);
+
+       const btMultibodyLink &getLink(int index) const
+       {
+               return m_links[index];
+       }
+
+       btMultibodyLink &getLink(int index)
+       {
+               return m_links[index];
+       }
+
+       void setBaseCollider(btMultiBodyLinkCollider * collider)  //collider can be NULL to disable collision for the base
+       {
+               m_baseCollider = collider;
+       }
+       const btMultiBodyLinkCollider *getBaseCollider() const
+       {
+               return m_baseCollider;
+       }
+       btMultiBodyLinkCollider *getBaseCollider()
+       {
+               return m_baseCollider;
+       }
+
+       const btMultiBodyLinkCollider *getLinkCollider(int index) const
+       {
+               if (index >= 0 && index < getNumLinks())
+               {
+                       return getLink(index).m_collider;
+               }
+               return 0;
+       }
+
+       btMultiBodyLinkCollider *getLinkCollider(int index)
+       {
+               if (index >= 0 && index < getNumLinks())
+               {
+                       return getLink(index).m_collider;
+               }
+               return 0;
+       }
+
+       //
+       // get parent
+       // input: link num from 0 to num_links-1
+       // output: link num from 0 to num_links-1, OR -1 to mean the base.
+       //
+       int getParent(int link_num) const;
+
+       //
+       // get number of m_links, masses, moments of inertia
+       //
+
+       int getNumLinks() const { return m_links.size(); }
+       int getNumDofs() const { return m_dofCount; }
+       int getNumPosVars() const { return m_posVarCnt; }
+       btScalar getBaseMass() const { return m_baseMass; }
+       const btVector3 &getBaseInertia() const { return m_baseInertia; }
+       btScalar getLinkMass(int i) const;
+       const btVector3 &getLinkInertia(int i) const;
+
+       //
+       // change mass (incomplete: can only change base mass and inertia at present)
+       //
+
+       void setBaseMass(btScalar mass) { m_baseMass = mass; }
+       void setBaseInertia(const btVector3 &inertia) { m_baseInertia = inertia; }
+
+       //
+       // get/set pos/vel/rot/omega for the base link
+       //
+
+       const btVector3 &getBasePos() const 
+       { 
+               return m_basePos; 
+       }  // in world frame
+       const btVector3 getBaseVel() const
+       {
+               return btVector3(m_realBuf[3], m_realBuf[4], m_realBuf[5]);
+       }  // in world frame
+       const btQuaternion &getWorldToBaseRot() const
+       {
+               return m_baseQuat;
+       }
+    
+    const btVector3 &getInterpolateBasePos() const
+    {
+        return m_basePos_interpolate;
+    }  // in world frame
+    const btQuaternion &getInterpolateWorldToBaseRot() const
+    {
+        return m_baseQuat_interpolate;
+    }
+    
+    // rotates world vectors into base frame
+       btVector3 getBaseOmega() const { return btVector3(m_realBuf[0], m_realBuf[1], m_realBuf[2]); }  // in world frame
+
+       void setBasePos(const btVector3 &pos)
+       {
+               m_basePos = pos;
+               if(!isBaseKinematic())
+                       m_basePos_interpolate = pos;
+       }
+
+       void setInterpolateBasePos(const btVector3 &pos)
+       {
+               m_basePos_interpolate = pos;
+       }
+
+       void setBaseWorldTransform(const btTransform &tr)
+       {
+               setBasePos(tr.getOrigin());
+               setWorldToBaseRot(tr.getRotation().inverse());
+       }
+
+       btTransform getBaseWorldTransform() const
+       {
+               btTransform tr;
+               tr.setOrigin(getBasePos());
+               tr.setRotation(getWorldToBaseRot().inverse());
+               return tr;
+       }
+
+       void setInterpolateBaseWorldTransform(const btTransform &tr)
+       {
+               setInterpolateBasePos(tr.getOrigin());
+               setInterpolateWorldToBaseRot(tr.getRotation().inverse());
+       }
+
+       btTransform getInterpolateBaseWorldTransform() const
+       {
+               btTransform tr;
+               tr.setOrigin(getInterpolateBasePos());
+               tr.setRotation(getInterpolateWorldToBaseRot().inverse());
+               return tr;
+       }
+
+       void setBaseVel(const btVector3 &vel)
+       {
+               m_realBuf[3] = vel[0];
+               m_realBuf[4] = vel[1];
+               m_realBuf[5] = vel[2];
+       }
+
+       void setWorldToBaseRot(const btQuaternion &rot)
+       {
+               m_baseQuat = rot;  //m_baseQuat asumed to ba alias!?
+               if(!isBaseKinematic())
+                       m_baseQuat_interpolate = rot;
+       }
+
+       void setInterpolateWorldToBaseRot(const btQuaternion &rot)
+       {
+               m_baseQuat_interpolate = rot;
+       }
+
+       void setBaseOmega(const btVector3 &omega)
+       {
+               m_realBuf[0] = omega[0];
+               m_realBuf[1] = omega[1];
+               m_realBuf[2] = omega[2];
+       }
+
+       void saveKinematicState(btScalar timeStep);
+
+       //
+       // get/set pos/vel for child m_links (i = 0 to num_links-1)
+       //
+
+       btScalar getJointPos(int i) const;
+       btScalar getJointVel(int i) const;
+
+       btScalar *getJointVelMultiDof(int i);
+       btScalar *getJointPosMultiDof(int i);
+
+       const btScalar *getJointVelMultiDof(int i) const;
+       const btScalar *getJointPosMultiDof(int i) const;
+
+       void setJointPos(int i, btScalar q);
+       void setJointVel(int i, btScalar qdot);
+       void setJointPosMultiDof(int i, const double *q);
+       void setJointVelMultiDof(int i, const double *qdot);
+       void setJointPosMultiDof(int i, const float *q);
+       void setJointVelMultiDof(int i, const float *qdot);
+
+       //
+       // direct access to velocities as a vector of 6 + num_links elements.
+       // (omega first, then v, then joint velocities.)
+       //
+       const btScalar *getVelocityVector() const
+       {
+               return &m_realBuf[0];
+       }
+    
+    const btScalar *getDeltaVelocityVector() const
+    {
+        return &m_deltaV[0];
+    }
+    
+    const btScalar *getSplitVelocityVector() const
+    {
+        return &m_splitV[0];
+    }
+       /*    btScalar * getVelocityVector() 
+       { 
+               return &real_buf[0]; 
+       }
+  */
+
+       //
+       // get the frames of reference (positions and orientations) of the child m_links
+       // (i = 0 to num_links-1)
+       //
+
+       const btVector3 &getRVector(int i) const;              // vector from COM(parent(i)) to COM(i), in frame i's coords
+       const btQuaternion &getParentToLocalRot(int i) const;  // rotates vectors in frame parent(i) to vectors in frame i.
+    const btVector3 &getInterpolateRVector(int i) const;              // vector from COM(parent(i)) to COM(i), in frame i's coords
+    const btQuaternion &getInterpolateParentToLocalRot(int i) const;  // rotates vectors in frame parent(i) to vectors in frame i.
+
+       //
+       // transform vectors in local frame of link i to world frame (or vice versa)
+       //
+       btVector3 localPosToWorld(int i, const btVector3 &local_pos) const;
+       btVector3 localDirToWorld(int i, const btVector3 &local_dir) const;
+       btVector3 worldPosToLocal(int i, const btVector3 &world_pos) const;
+       btVector3 worldDirToLocal(int i, const btVector3 &world_dir) const;
+
+       //
+       // transform a frame in local coordinate to a frame in world coordinate
+       //
+       btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &local_frame) const;
+
+
+       //
+       // set external forces and torques. Note all external forces/torques are given in the WORLD frame.
+       //
+
+       void clearForcesAndTorques();
+       void clearConstraintForces();
+
+       void clearVelocities();
+
+       void addBaseForce(const btVector3 &f)
+       {
+               m_baseForce += f;
+       }
+       void addBaseTorque(const btVector3 &t) { m_baseTorque += t; }
+       void addLinkForce(int i, const btVector3 &f);
+       void addLinkTorque(int i, const btVector3 &t);
+
+       void addBaseConstraintForce(const btVector3 &f)
+       {
+               m_baseConstraintForce += f;
+       }
+       void addBaseConstraintTorque(const btVector3 &t) { m_baseConstraintTorque += t; }
+       void addLinkConstraintForce(int i, const btVector3 &f);
+       void addLinkConstraintTorque(int i, const btVector3 &t);
+
+       void addJointTorque(int i, btScalar Q);
+       void addJointTorqueMultiDof(int i, int dof, btScalar Q);
+       void addJointTorqueMultiDof(int i, const btScalar *Q);
+
+       const btVector3 &getBaseForce() const { return m_baseForce; }
+       const btVector3 &getBaseTorque() const { return m_baseTorque; }
+       const btVector3 &getLinkForce(int i) const;
+       const btVector3 &getLinkTorque(int i) const;
+       btScalar getJointTorque(int i) const;
+       btScalar *getJointTorqueMultiDof(int i);
+
+       //
+       // dynamics routines.
+       //
+
+       // timestep the velocities (given the external forces/torques set using addBaseForce etc).
+       // also sets up caches for calcAccelerationDeltas.
+       //
+       // Note: the caller must provide three vectors which are used as
+       // temporary scratch space. The idea here is to reduce dynamic
+       // memory allocation: the same scratch vectors can be re-used
+       // again and again for different Multibodies, instead of each
+       // btMultiBody allocating (and then deallocating) their own
+       // individual scratch buffers. This gives a considerable speed
+       // improvement, at least on Windows (where dynamic memory
+       // allocation appears to be fairly slow).
+       //
+
+       void computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
+                                                                                                                         btAlignedObjectArray<btScalar> & scratch_r,
+                                                                                                                         btAlignedObjectArray<btVector3> & scratch_v,
+                                                                                                                         btAlignedObjectArray<btMatrix3x3> & scratch_m,
+                                                                                                                         bool isConstraintPass,
+                                                              bool jointFeedbackInWorldSpace,
+                                                              bool jointFeedbackInJointFrame
+                                                              );
+
+       ///stepVelocitiesMultiDof is deprecated, use computeAccelerationsArticulatedBodyAlgorithmMultiDof instead
+       //void stepVelocitiesMultiDof(btScalar dt,
+       //                                                      btAlignedObjectArray<btScalar> & scratch_r,
+       //                                                      btAlignedObjectArray<btVector3> & scratch_v,
+       //                                                      btAlignedObjectArray<btMatrix3x3> & scratch_m,
+       //                                                      bool isConstraintPass = false)
+       //{
+       //      computeAccelerationsArticulatedBodyAlgorithmMultiDof(dt, scratch_r, scratch_v, scratch_m, isConstraintPass, false, false);
+       //}
+
+       // calcAccelerationDeltasMultiDof
+       // input: force vector (in same format as jacobian, i.e.:
+       //                      3 torque values, 3 force values, num_links joint torque values)
+       // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values
+       // (existing contents of output array are replaced)
+       // calcAccelerationDeltasMultiDof must have been called first.
+       void calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
+                                                                               btAlignedObjectArray<btScalar> &scratch_r,
+                                                                               btAlignedObjectArray<btVector3> &scratch_v) const;
+
+       void applyDeltaVeeMultiDof2(const btScalar *delta_vee, btScalar multiplier)
+       {
+               for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+               {
+                       m_deltaV[dof] += delta_vee[dof] * multiplier;
+               }
+       }
+    void applyDeltaSplitVeeMultiDof(const btScalar *delta_vee, btScalar multiplier)
+    {
+        for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+        {
+            m_splitV[dof] += delta_vee[dof] * multiplier;
+        }
+    }
+    void addSplitV()
+    {
+        applyDeltaVeeMultiDof(&m_splitV[0], 1);
+    }
+    void substractSplitV()
+    {
+        applyDeltaVeeMultiDof(&m_splitV[0], -1);
+        
+        for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+        {
+            m_splitV[dof] = 0.f;
+        }
+    }
+       void processDeltaVeeMultiDof2()
+       {
+               applyDeltaVeeMultiDof(&m_deltaV[0], 1);
+
+               for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+               {
+                       m_deltaV[dof] = 0.f;
+               }
+       }
+
+       void applyDeltaVeeMultiDof(const btScalar *delta_vee, btScalar multiplier)
+       {
+               //for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+               //      printf("%.4f ", delta_vee[dof]*multiplier);
+               //printf("\n");
+
+               //btScalar sum = 0;
+               //for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+               //{
+               //      sum += delta_vee[dof]*multiplier*delta_vee[dof]*multiplier;
+               //}
+               //btScalar l = btSqrt(sum);
+
+               //if (l>m_maxAppliedImpulse)
+               //{
+               //      multiplier *= m_maxAppliedImpulse/l;
+               //}
+
+               for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
+               {
+                       m_realBuf[dof] += delta_vee[dof] * multiplier;
+                       btClamp(m_realBuf[dof], -m_maxCoordinateVelocity, m_maxCoordinateVelocity);
+               }
+       }
+
+       // timestep the positions (given current velocities).
+       void stepPositionsMultiDof(btScalar dt, btScalar *pq = 0, btScalar *pqd = 0);
+    
+    // predict the positions
+    void predictPositionsMultiDof(btScalar dt);
+
+       //
+       // contacts
+       //
+
+       // This routine fills out a contact constraint jacobian for this body.
+       // the 'normal' supplied must be -n for body1 or +n for body2 of the contact.
+       // 'normal' & 'contact_point' are both given in world coordinates.
+
+       void fillContactJacobianMultiDof(int link,
+                                                                        const btVector3 &contact_point,
+                                                                        const btVector3 &normal,
+                                                                        btScalar *jac,
+                                                                        btAlignedObjectArray<btScalar> &scratch_r,
+                                                                        btAlignedObjectArray<btVector3> &scratch_v,
+                                                                        btAlignedObjectArray<btMatrix3x3> &scratch_m) const { fillConstraintJacobianMultiDof(link, contact_point, btVector3(0, 0, 0), normal, jac, scratch_r, scratch_v, scratch_m); }
+
+       //a more general version of fillContactJacobianMultiDof which does not assume..
+       //.. that the constraint in question is contact or, to be more precise, constrains linear velocity only
+       void fillConstraintJacobianMultiDof(int link,
+                                                                               const btVector3 &contact_point,
+                                                                               const btVector3 &normal_ang,
+                                                                               const btVector3 &normal_lin,
+                                                                               btScalar *jac,
+                                                                               btAlignedObjectArray<btScalar> &scratch_r,
+                                                                               btAlignedObjectArray<btVector3> &scratch_v,
+                                                                               btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
+
+       //
+       // sleeping
+       //
+       void setCanSleep(bool canSleep)
+       {
+               if (m_canWakeup)
+               {
+                       m_canSleep = canSleep;
+               }
+       }
+
+       bool getCanSleep() const
+       {
+               return m_canSleep;
+       }
+
+       bool getCanWakeup() const
+       {
+               return m_canWakeup;
+       }
+       
+       void setCanWakeup(bool canWakeup) 
+       {
+               m_canWakeup = canWakeup;
+       }
+       bool isAwake() const 
+       { 
+               return m_awake; 
+       }
+       void wakeUp();
+       void goToSleep();
+       void checkMotionAndSleepIfRequired(btScalar timestep);
+
+       bool hasFixedBase() const;
+
+       bool isBaseKinematic() const;
+
+       bool isBaseStaticOrKinematic() const;
+
+       // set the dynamic type in the base's collision flags.
+       void setBaseDynamicType(int dynamicType);
+
+       void setFixedBase(bool fixedBase)
+       {
+               m_fixedBase = fixedBase;
+               if(m_fixedBase)
+                       setBaseDynamicType(btCollisionObject::CF_STATIC_OBJECT);
+               else
+                       setBaseDynamicType(btCollisionObject::CF_DYNAMIC_OBJECT);
+       }
+
+       int getCompanionId() const
+       {
+               return m_companionId;
+       }
+       void setCompanionId(int id)
+       {
+               //printf("for %p setCompanionId(%d)\n",this, id);
+               m_companionId = id;
+       }
+
+       void setNumLinks(int numLinks)  //careful: when changing the number of m_links, make sure to re-initialize or update existing m_links
+       {
+               m_links.resize(numLinks);
+       }
+
+       btScalar getLinearDamping() const
+       {
+               return m_linearDamping;
+       }
+       void setLinearDamping(btScalar damp)
+       {
+               m_linearDamping = damp;
+       }
+       btScalar getAngularDamping() const
+       {
+               return m_angularDamping;
+       }
+       void setAngularDamping(btScalar damp)
+       {
+               m_angularDamping = damp;
+       }
+
+       bool getUseGyroTerm() const
+       {
+               return m_useGyroTerm;
+       }
+       void setUseGyroTerm(bool useGyro)
+       {
+               m_useGyroTerm = useGyro;
+       }
+       btScalar getMaxCoordinateVelocity() const
+       {
+               return m_maxCoordinateVelocity;
+       }
+       void setMaxCoordinateVelocity(btScalar maxVel)
+       {
+               m_maxCoordinateVelocity = maxVel;
+       }
+
+       btScalar getMaxAppliedImpulse() const
+       {
+               return m_maxAppliedImpulse;
+       }
+       void setMaxAppliedImpulse(btScalar maxImp)
+       {
+               m_maxAppliedImpulse = maxImp;
+       }
+       void setHasSelfCollision(bool hasSelfCollision)
+       {
+               m_hasSelfCollision = hasSelfCollision;
+       }
+       bool hasSelfCollision() const
+       {
+               return m_hasSelfCollision;
+       }
+
+       void finalizeMultiDof();
+
+       void useRK4Integration(bool use) { m_useRK4 = use; }
+       bool isUsingRK4Integration() const { return m_useRK4; }
+       void useGlobalVelocities(bool use) { m_useGlobalVelocities = use; }
+       bool isUsingGlobalVelocities() const { return m_useGlobalVelocities; }
+
+       bool isPosUpdated() const
+       {
+               return __posUpdated;
+       }
+       void setPosUpdated(bool updated)
+       {
+               __posUpdated = updated;
+       }
+
+       //internalNeedsJointFeedback is for internal use only
+       bool internalNeedsJointFeedback() const
+       {
+               return m_internalNeedsJointFeedback;
+       }
+       void forwardKinematics(btAlignedObjectArray<btQuaternion>& world_to_local, btAlignedObjectArray<btVector3> & local_origin);
+
+       void compTreeLinkVelocities(btVector3 * omega, btVector3 * vel) const;
+
+       void updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> & world_to_local, btAlignedObjectArray<btVector3> & local_origin);
+    void updateCollisionObjectInterpolationWorldTransforms(btAlignedObjectArray<btQuaternion> & world_to_local, btAlignedObjectArray<btVector3> & local_origin);
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char *serialize(void *dataBuffer, class btSerializer *serializer) const;
+
+       const char *getBaseName() const
+       {
+               return m_baseName;
+       }
+       ///memory of setBaseName needs to be manager by user
+       void setBaseName(const char *name)
+       {
+               m_baseName = name;
+       }
+
+       ///users can point to their objects, userPointer is not used by Bullet
+       void *getUserPointer() const
+       {
+               return m_userObjectPointer;
+       }
+
+       int getUserIndex() const
+       {
+               return m_userIndex;
+       }
+
+       int getUserIndex2() const
+       {
+               return m_userIndex2;
+       }
+       ///users can point to their objects, userPointer is not used by Bullet
+       void setUserPointer(void *userPointer)
+       {
+               m_userObjectPointer = userPointer;
+       }
+
+       ///users can point to their objects, userPointer is not used by Bullet
+       void setUserIndex(int index)
+       {
+               m_userIndex = index;
+       }
+
+       void setUserIndex2(int index)
+       {
+               m_userIndex2 = index;
+       }
+
+       static void spatialTransform(const btMatrix3x3 &rotation_matrix,  // rotates vectors in 'from' frame to vectors in 'to' frame
+               const btVector3 &displacement,     // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates
+               const btVector3 &top_in,       // top part of input vector
+               const btVector3 &bottom_in,    // bottom part of input vector
+               btVector3 &top_out,         // top part of output vector
+               btVector3 &bottom_out);      // bottom part of output vector
+
+       void setLinkDynamicType(const int i, int type);
+
+       bool isLinkStaticOrKinematic(const int i) const;
+
+       bool isLinkKinematic(const int i) const;
+
+       bool isLinkAndAllAncestorsStaticOrKinematic(const int i) const;
+
+       bool isLinkAndAllAncestorsKinematic(const int i) const;
+
+       void setSleepThreshold(btScalar sleepThreshold)
+       {
+               m_sleepEpsilon = sleepThreshold;
+       }
+
+       void setSleepTimeout(btScalar sleepTimeout)
+       {
+               this->m_sleepTimeout = sleepTimeout;
+       }
+
+
+private:
+       btMultiBody(const btMultiBody &);     // not implemented
+       void operator=(const btMultiBody &);  // not implemented
+
+       void solveImatrix(const btVector3 &rhs_top, const btVector3 &rhs_bot, btScalar result[6]) const;
+       void solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const;
+
+       void updateLinksDofOffsets()
+       {
+               int dofOffset = 0, cfgOffset = 0;
+               for (int bidx = 0; bidx < m_links.size(); ++bidx)
+               {
+                       m_links[bidx].m_dofOffset = dofOffset;
+                       m_links[bidx].m_cfgOffset = cfgOffset;
+                       dofOffset += m_links[bidx].m_dofCount;
+                       cfgOffset += m_links[bidx].m_posVarCount;
+               }
+       }
+
+       void mulMatrix(const btScalar *pA, const btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const;
+
+private:
+       btMultiBodyLinkCollider *m_baseCollider;  //can be NULL
+       const char *m_baseName;                   //memory needs to be manager by user!
+
+       btVector3 m_basePos;      // position of COM of base (world frame)
+    btVector3 m_basePos_interpolate;      // position of interpolated COM of base (world frame)
+       btQuaternion m_baseQuat;  // rotates world points into base frame
+    btQuaternion m_baseQuat_interpolate;  
+
+       btScalar m_baseMass;      // mass of the base
+       btVector3 m_baseInertia;  // inertia of the base (in local frame; diagonal)
+
+       btVector3 m_baseForce;   // external force applied to base. World frame.
+       btVector3 m_baseTorque;  // external torque applied to base. World frame.
+
+       btVector3 m_baseConstraintForce;   // external force applied to base. World frame.
+       btVector3 m_baseConstraintTorque;  // external torque applied to base. World frame.
+
+       btAlignedObjectArray<btMultibodyLink> m_links;  // array of m_links, excluding the base. index from 0 to num_links-1.
+
+       //
+       // realBuf:
+       //  offset         size            array
+       //   0              6 + num_links   v (base_omega; base_vel; joint_vels)                                        MULTIDOF [sysdof x sysdof for D matrices (TOO MUCH!) + pos_delta which is sys-cfg sized]
+       //   6+num_links    num_links       D
+       //
+       // vectorBuf:
+       //  offset         size         array
+       //   0              num_links    h_top
+       //   num_links      num_links    h_bottom
+       //
+       // matrixBuf:
+       //  offset         size         array
+       //   0              num_links+1  rot_from_parent
+       //
+    btAlignedObjectArray<btScalar> m_splitV;
+       btAlignedObjectArray<btScalar> m_deltaV;
+       btAlignedObjectArray<btScalar> m_realBuf;
+       btAlignedObjectArray<btVector3> m_vectorBuf;
+       btAlignedObjectArray<btMatrix3x3> m_matrixBuf;
+
+       btMatrix3x3 m_cachedInertiaTopLeft;
+       btMatrix3x3 m_cachedInertiaTopRight;
+       btMatrix3x3 m_cachedInertiaLowerLeft;
+       btMatrix3x3 m_cachedInertiaLowerRight;
+       bool m_cachedInertiaValid;
+
+       bool m_fixedBase;
+
+       // Sleep parameters.
+       bool m_awake;
+       bool m_canSleep;
+       bool m_canWakeup;
+       btScalar m_sleepTimer;
+       btScalar m_sleepEpsilon;
+       btScalar m_sleepTimeout;
+
+       void *m_userObjectPointer;
+       int m_userIndex2;
+       int m_userIndex;
+
+       int m_companionId;
+       btScalar m_linearDamping;
+       btScalar m_angularDamping;
+       bool m_useGyroTerm;
+       btScalar m_maxAppliedImpulse;
+       btScalar m_maxCoordinateVelocity;
+       bool m_hasSelfCollision;
+
+       bool __posUpdated;
+       int m_dofCount, m_posVarCnt;
+
+       bool m_useRK4, m_useGlobalVelocities;
+       //for global velocities, see 8.3.2B Proposed resolution in Jakub Stepien PhD Thesis
+       //https://drive.google.com/file/d/0Bz3vEa19XOYGNWdZWGpMdUdqVmZ5ZVBOaEh4ZnpNaUxxZFNV/view?usp=sharing
+
+       ///the m_needsJointFeedback gets updated/computed during the stepVelocitiesMultiDof and it for internal usage only
+       bool m_internalNeedsJointFeedback;
+
+  //If enabled, calculate the velocity based on kinematic transform changes. Currently only implemented for the base.
+       bool m_kinematic_calculate_velocity;
+};
+
+struct btMultiBodyLinkDoubleData
+{
+       btQuaternionDoubleData m_zeroRotParentToThis;
+       btVector3DoubleData m_parentComToThisPivotOffset;
+       btVector3DoubleData m_thisPivotToThisComOffset;
+       btVector3DoubleData m_jointAxisTop[6];
+       btVector3DoubleData m_jointAxisBottom[6];
+
+       btVector3DoubleData m_linkInertia;  // inertia of the base (in local frame; diagonal)
+       btVector3DoubleData m_absFrameTotVelocityTop;
+       btVector3DoubleData m_absFrameTotVelocityBottom;
+       btVector3DoubleData m_absFrameLocVelocityTop;
+       btVector3DoubleData m_absFrameLocVelocityBottom;
+
+       double m_linkMass;
+       int m_parentIndex;
+       int m_jointType;
+
+       int m_dofCount;
+       int m_posVarCount;
+       double m_jointPos[7];
+       double m_jointVel[6];
+       double m_jointTorque[6];
+
+       double m_jointDamping;
+       double m_jointFriction;
+       double m_jointLowerLimit;
+       double m_jointUpperLimit;
+       double m_jointMaxForce;
+       double m_jointMaxVelocity;
+
+       char *m_linkName;
+       char *m_jointName;
+       btCollisionObjectDoubleData *m_linkCollider;
+       char *m_paddingPtr;
+};
+
+struct btMultiBodyLinkFloatData
+{
+       btQuaternionFloatData m_zeroRotParentToThis;
+       btVector3FloatData m_parentComToThisPivotOffset;
+       btVector3FloatData m_thisPivotToThisComOffset;
+       btVector3FloatData m_jointAxisTop[6];
+       btVector3FloatData m_jointAxisBottom[6];
+       btVector3FloatData m_linkInertia;  // inertia of the base (in local frame; diagonal)
+       btVector3FloatData m_absFrameTotVelocityTop;
+       btVector3FloatData m_absFrameTotVelocityBottom;
+       btVector3FloatData m_absFrameLocVelocityTop;
+       btVector3FloatData m_absFrameLocVelocityBottom;
+
+       int m_dofCount;
+       float m_linkMass;
+       int m_parentIndex;
+       int m_jointType;
+
+       float m_jointPos[7];
+       float m_jointVel[6];
+       float m_jointTorque[6];
+       int m_posVarCount;
+       float m_jointDamping;
+       float m_jointFriction;
+       float m_jointLowerLimit;
+       float m_jointUpperLimit;
+       float m_jointMaxForce;
+       float m_jointMaxVelocity;
+
+       char *m_linkName;
+       char *m_jointName;
+       btCollisionObjectFloatData *m_linkCollider;
+       char *m_paddingPtr;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btMultiBodyDoubleData
+{
+       btVector3DoubleData m_baseWorldPosition;
+       btQuaternionDoubleData m_baseWorldOrientation;
+       btVector3DoubleData m_baseLinearVelocity;
+       btVector3DoubleData m_baseAngularVelocity;
+       btVector3DoubleData m_baseInertia;  // inertia of the base (in local frame; diagonal)
+       double m_baseMass;
+       int m_numLinks;
+       char m_padding[4];
+
+       char *m_baseName;
+       btMultiBodyLinkDoubleData *m_links;
+       btCollisionObjectDoubleData *m_baseCollider;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btMultiBodyFloatData
+{
+       btVector3FloatData m_baseWorldPosition;
+       btQuaternionFloatData m_baseWorldOrientation;
+       btVector3FloatData m_baseLinearVelocity;
+       btVector3FloatData m_baseAngularVelocity;
+
+       btVector3FloatData m_baseInertia;  // inertia of the base (in local frame; diagonal)
+       float m_baseMass;
+       int m_numLinks;
+
+       char *m_baseName;
+       btMultiBodyLinkFloatData *m_links;
+       btCollisionObjectFloatData *m_baseCollider;
+};
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
new file mode 100644 (file)
index 0000000..00d5fd5
--- /dev/null
@@ -0,0 +1,389 @@
+#include "btMultiBodyConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "btMultiBodyPoint2Point.h"  //for testing (BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST macro)
+
+btMultiBodyConstraint::btMultiBodyConstraint(btMultiBody* bodyA, btMultiBody* bodyB, int linkA, int linkB, int numRows, bool isUnilateral, int type)
+       : m_bodyA(bodyA),
+         m_bodyB(bodyB),
+         m_linkA(linkA),
+         m_linkB(linkB),
+         m_type(type),
+         m_numRows(numRows),
+         m_jacSizeA(0),
+         m_jacSizeBoth(0),
+         m_isUnilateral(isUnilateral),
+         m_numDofsFinalized(-1),
+         m_maxAppliedImpulse(100)
+{
+}
+
+void btMultiBodyConstraint::updateJacobianSizes()
+{
+       if (m_bodyA)
+       {
+               m_jacSizeA = (6 + m_bodyA->getNumDofs());
+       }
+
+       if (m_bodyB)
+       {
+               m_jacSizeBoth = m_jacSizeA + 6 + m_bodyB->getNumDofs();
+       }
+       else
+               m_jacSizeBoth = m_jacSizeA;
+}
+
+void btMultiBodyConstraint::allocateJacobiansMultiDof()
+{
+       updateJacobianSizes();
+
+       m_posOffset = ((1 + m_jacSizeBoth) * m_numRows);
+       m_data.resize((2 + m_jacSizeBoth) * m_numRows);
+}
+
+btMultiBodyConstraint::~btMultiBodyConstraint()
+{
+}
+
+void btMultiBodyConstraint::applyDeltaVee(btMultiBodyJacobianData& data, btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
+{
+       for (int i = 0; i < ndof; ++i)
+               data.m_deltaVelocities[velocityIndex + i] += delta_vee[i] * impulse;
+}
+
+btScalar btMultiBodyConstraint::fillMultiBodyConstraint(btMultiBodySolverConstraint& solverConstraint,
+                                                                                                               btMultiBodyJacobianData& data,
+                                                                                                               btScalar* jacOrgA, btScalar* jacOrgB,
+                                                                                                               const btVector3& constraintNormalAng,
+                                                                                                               const btVector3& constraintNormalLin,
+                                                                                                               const btVector3& posAworld, const btVector3& posBworld,
+                                                                                                               btScalar posError,
+                                                                                                               const btContactSolverInfo& infoGlobal,
+                                                                                                               btScalar lowerLimit, btScalar upperLimit,
+                                                                                                               bool angConstraint,
+                                                                                                               btScalar relaxation,
+                                                                                                               bool isFriction, btScalar desiredVelocity, btScalar cfmSlip,
+                                                                                                               btScalar damping)
+{
+       solverConstraint.m_multiBodyA = m_bodyA;
+       solverConstraint.m_multiBodyB = m_bodyB;
+       solverConstraint.m_linkA = m_linkA;
+       solverConstraint.m_linkB = m_linkB;
+
+       btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+       btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+
+       btSolverBody* bodyA = multiBodyA ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdA);
+       btSolverBody* bodyB = multiBodyB ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdB);
+
+       btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
+       btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
+
+       btVector3 rel_pos1, rel_pos2;  //these two used to be inited to posAworld and posBworld (respectively) but it does not seem necessary
+       if (bodyA)
+               rel_pos1 = posAworld - bodyA->getWorldTransform().getOrigin();
+       if (bodyB)
+               rel_pos2 = posBworld - bodyB->getWorldTransform().getOrigin();
+
+       if (multiBodyA)
+       {
+               if (solverConstraint.m_linkA < 0)
+               {
+                       rel_pos1 = posAworld - multiBodyA->getBasePos();
+               }
+               else
+               {
+                       rel_pos1 = posAworld - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
+               }
+
+               const int ndofA = multiBodyA->getNumDofs() + 6;
+
+               solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
+
+               if (solverConstraint.m_deltaVelAindex < 0)
+               {
+                       solverConstraint.m_deltaVelAindex = data.m_deltaVelocities.size();
+                       multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
+                       data.m_deltaVelocities.resize(data.m_deltaVelocities.size() + ndofA);
+               }
+               else
+               {
+                       btAssert(data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
+               }
+
+               //determine jacobian of this 1D constraint in terms of multibodyA's degrees of freedom
+               //resize..
+               solverConstraint.m_jacAindex = data.m_jacobians.size();
+               data.m_jacobians.resize(data.m_jacobians.size() + ndofA);
+               //copy/determine
+               if (jacOrgA)
+               {
+                       for (int i = 0; i < ndofA; i++)
+                               data.m_jacobians[solverConstraint.m_jacAindex + i] = jacOrgA[i];
+               }
+               else
+               {
+                       btScalar* jac1 = &data.m_jacobians[solverConstraint.m_jacAindex];
+                       //multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
+                       multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalAng, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
+               }
+
+               //determine the velocity response of multibodyA to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint)
+               //resize..
+               data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size() + ndofA);  //=> each constraint row has the constrained tree dofs allocated in m_deltaVelocitiesUnitImpulse
+               btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size());
+               btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+               //determine..
+               multiBodyA->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacAindex], delta, data.scratch_r, data.scratch_v);
+
+               btVector3 torqueAxis0;
+               if (angConstraint)
+               {
+                       torqueAxis0 = constraintNormalAng;
+               }
+               else
+               {
+                       torqueAxis0 = rel_pos1.cross(constraintNormalLin);
+               }
+               solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+               solverConstraint.m_contactNormal1 = constraintNormalLin;
+       }
+       else  //if(rb0)
+       {
+               btVector3 torqueAxis0;
+               if (angConstraint)
+               {
+                       torqueAxis0 = constraintNormalAng;
+               }
+               else
+               {
+                       torqueAxis0 = rel_pos1.cross(constraintNormalLin);
+               }
+               solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
+               solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+               solverConstraint.m_contactNormal1 = constraintNormalLin;
+       }
+
+       if (multiBodyB)
+       {
+               if (solverConstraint.m_linkB < 0)
+               {
+                       rel_pos2 = posBworld - multiBodyB->getBasePos();
+               }
+               else
+               {
+                       rel_pos2 = posBworld - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
+               }
+
+               const int ndofB = multiBodyB->getNumDofs() + 6;
+
+               solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
+               if (solverConstraint.m_deltaVelBindex < 0)
+               {
+                       solverConstraint.m_deltaVelBindex = data.m_deltaVelocities.size();
+                       multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
+                       data.m_deltaVelocities.resize(data.m_deltaVelocities.size() + ndofB);
+               }
+
+               //determine jacobian of this 1D constraint in terms of multibodyB's degrees of freedom
+               //resize..
+               solverConstraint.m_jacBindex = data.m_jacobians.size();
+               data.m_jacobians.resize(data.m_jacobians.size() + ndofB);
+               //copy/determine..
+               if (jacOrgB)
+               {
+                       for (int i = 0; i < ndofB; i++)
+                               data.m_jacobians[solverConstraint.m_jacBindex + i] = jacOrgB[i];
+               }
+               else
+               {
+                       //multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m);
+                       multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalAng, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m);
+               }
+
+               //determine velocity response of multibodyB to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint)
+               //resize..
+               data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
+               btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size());
+               btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+               //determine..
+               multiBodyB->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacBindex], delta, data.scratch_r, data.scratch_v);
+
+               btVector3 torqueAxis1;
+               if (angConstraint)
+               {
+                       torqueAxis1 = constraintNormalAng;
+               }
+               else
+               {
+                       torqueAxis1 = rel_pos2.cross(constraintNormalLin);
+               }
+               solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+               solverConstraint.m_contactNormal2 = -constraintNormalLin;
+       }
+       else  //if(rb1)
+       {
+               btVector3 torqueAxis1;
+               if (angConstraint)
+               {
+                       torqueAxis1 = constraintNormalAng;
+               }
+               else
+               {
+                       torqueAxis1 = rel_pos2.cross(constraintNormalLin);
+               }
+               solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
+               solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+               solverConstraint.m_contactNormal2 = -constraintNormalLin;
+       }
+       {
+               btVector3 vec;
+               btScalar denom0 = 0.f;
+               btScalar denom1 = 0.f;
+               btScalar* jacB = 0;
+               btScalar* jacA = 0;
+               btScalar* deltaVelA = 0;
+               btScalar* deltaVelB = 0;
+               int ndofA = 0;
+               //determine the "effective mass" of the constrained multibodyA with respect to this 1D constraint (i.e. 1/A[i,i])
+               if (multiBodyA)
+               {
+                       ndofA = multiBodyA->getNumDofs() + 6;
+                       jacA = &data.m_jacobians[solverConstraint.m_jacAindex];
+                       deltaVelA = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+                       for (int i = 0; i < ndofA; ++i)
+                       {
+                               btScalar j = jacA[i];
+                               btScalar l = deltaVelA[i];
+                               denom0 += j * l;
+                       }
+               }
+               else if (rb0)
+               {
+                       vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
+                       if (angConstraint)
+                       {
+                               denom0 = constraintNormalAng.dot(solverConstraint.m_angularComponentA);
+                       }
+                       else
+                       {
+                               denom0 = rb0->getInvMass() + constraintNormalLin.dot(vec);
+                       }
+               }
+               //
+               if (multiBodyB)
+               {
+                       const int ndofB = multiBodyB->getNumDofs() + 6;
+                       jacB = &data.m_jacobians[solverConstraint.m_jacBindex];
+                       deltaVelB = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+                       for (int i = 0; i < ndofB; ++i)
+                       {
+                               btScalar j = jacB[i];
+                               btScalar l = deltaVelB[i];
+                               denom1 += j * l;
+                       }
+               }
+               else if (rb1)
+               {
+                       vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
+                       if (angConstraint)
+                       {
+                               denom1 = constraintNormalAng.dot(-solverConstraint.m_angularComponentB);
+                       }
+                       else
+                       {
+                               denom1 = rb1->getInvMass() + constraintNormalLin.dot(vec);
+                       }
+               }
+
+               //
+               btScalar d = denom0 + denom1;
+               if (d > SIMD_EPSILON)
+               {
+                       solverConstraint.m_jacDiagABInv = relaxation / (d);
+               }
+               else
+               {
+                       //disable the constraint row to handle singularity/redundant constraint
+                       solverConstraint.m_jacDiagABInv = 0.f;
+               }
+       }
+
+       //compute rhs and remaining solverConstraint fields
+       btScalar penetration = isFriction ? 0 : posError;
+
+       btScalar rel_vel = 0.f;
+       int ndofA = 0;
+       int ndofB = 0;
+       {
+               btVector3 vel1, vel2;
+               if (multiBodyA)
+               {
+                       ndofA = multiBodyA->getNumDofs() + 6;
+                       btScalar* jacA = &data.m_jacobians[solverConstraint.m_jacAindex];
+                       for (int i = 0; i < ndofA; ++i)
+                               rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
+               }
+               else if (rb0)
+               {
+                       rel_vel += rb0->getLinearVelocity().dot(solverConstraint.m_contactNormal1);
+                       rel_vel += rb0->getAngularVelocity().dot(solverConstraint.m_relpos1CrossNormal);
+               }
+               if (multiBodyB)
+               {
+                       ndofB = multiBodyB->getNumDofs() + 6;
+                       btScalar* jacB = &data.m_jacobians[solverConstraint.m_jacBindex];
+                       for (int i = 0; i < ndofB; ++i)
+                               rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
+               }
+               else if (rb1)
+               {
+                       rel_vel += rb1->getLinearVelocity().dot(solverConstraint.m_contactNormal2);
+                       rel_vel += rb1->getAngularVelocity().dot(solverConstraint.m_relpos2CrossNormal);
+               }
+
+               solverConstraint.m_friction = 0.f;  //cp.m_combinedFriction;
+       }
+
+       solverConstraint.m_appliedImpulse = 0.f;
+       solverConstraint.m_appliedPushImpulse = 0.f;
+
+       {
+               btScalar positionalError = 0.f;
+               btScalar velocityError = (desiredVelocity - rel_vel) * damping;
+
+               btScalar erp = infoGlobal.m_erp2;
+
+               //split impulse is not implemented yet for btMultiBody*
+               //if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+               {
+                       erp = infoGlobal.m_erp;
+               }
+
+               positionalError = -penetration * erp / infoGlobal.m_timeStep;
+
+               btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+               btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+
+               //split impulse is not implemented yet for btMultiBody*
+
+               //  if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+               {
+                       //combine position and velocity into rhs
+                       solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+                       solverConstraint.m_rhsPenetration = 0.f;
+               }
+               /*else
+        {
+            //split position and velocity into rhs and m_rhsPenetration
+            solverConstraint.m_rhs = velocityImpulse;
+            solverConstraint.m_rhsPenetration = penetrationImpulse;
+        }
+        */
+
+               solverConstraint.m_cfm = 0.f;
+               solverConstraint.m_lowerLimit = lowerLimit;
+               solverConstraint.m_upperLimit = upperLimit;
+       }
+
+       return rel_vel;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraint.h
new file mode 100644 (file)
index 0000000..7287ccc
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MULTIBODY_CONSTRAINT_H
+#define BT_MULTIBODY_CONSTRAINT_H
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btMultiBody.h"
+
+
+//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
+enum btTypedMultiBodyConstraintType
+{
+       MULTIBODY_CONSTRAINT_LIMIT=3,
+       MULTIBODY_CONSTRAINT_1DOF_JOINT_MOTOR,
+       MULTIBODY_CONSTRAINT_GEAR,
+       MULTIBODY_CONSTRAINT_POINT_TO_POINT,
+       MULTIBODY_CONSTRAINT_SLIDER,
+       MULTIBODY_CONSTRAINT_SPHERICAL_MOTOR,
+       MULTIBODY_CONSTRAINT_FIXED,
+       MULTIBODY_CONSTRAINT_SPHERICAL_LIMIT,
+       MAX_MULTIBODY_CONSTRAINT_TYPE,
+};
+
+class btMultiBody;
+struct btSolverInfo;
+
+#include "btMultiBodySolverConstraint.h"
+
+struct btMultiBodyJacobianData
+{
+       btAlignedObjectArray<btScalar> m_jacobians;
+       btAlignedObjectArray<btScalar> m_deltaVelocitiesUnitImpulse;  //holds the joint-space response of the corresp. tree to the test impulse in each constraint space dimension
+       btAlignedObjectArray<btScalar> m_deltaVelocities;             //holds joint-space vectors of all the constrained trees accumulating the effect of corrective impulses applied in SI
+       btAlignedObjectArray<btScalar> scratch_r;
+       btAlignedObjectArray<btVector3> scratch_v;
+       btAlignedObjectArray<btMatrix3x3> scratch_m;
+       btAlignedObjectArray<btSolverBody>* m_solverBodyPool;
+       int m_fixedBodyId;
+};
+
+ATTRIBUTE_ALIGNED16(class)
+btMultiBodyConstraint
+{
+protected:
+       btMultiBody* m_bodyA;
+       btMultiBody* m_bodyB;
+       int m_linkA;
+       int m_linkB;
+
+       int m_type; //btTypedMultiBodyConstraintType
+
+       int m_numRows;
+       int m_jacSizeA;
+       int m_jacSizeBoth;
+       int m_posOffset;
+
+       bool m_isUnilateral;
+       int m_numDofsFinalized;
+       btScalar m_maxAppliedImpulse;
+
+       // warning: the data block lay out is not consistent for all constraints
+       // data block laid out as follows:
+       // cached impulses. (one per row.)
+       // jacobians. (interleaved, row1 body1 then row1 body2 then row2 body 1 etc)
+       // positions. (one per row.)
+       btAlignedObjectArray<btScalar> m_data;
+
+       void applyDeltaVee(btMultiBodyJacobianData & data, btScalar * delta_vee, btScalar impulse, int velocityIndex, int ndof);
+
+       btScalar fillMultiBodyConstraint(btMultiBodySolverConstraint & solverConstraint,
+                                                                        btMultiBodyJacobianData & data,
+                                                                        btScalar * jacOrgA, btScalar * jacOrgB,
+                                                                        const btVector3& constraintNormalAng,
+
+                                                                        const btVector3& constraintNormalLin,
+                                                                        const btVector3& posAworld, const btVector3& posBworld,
+                                                                        btScalar posError,
+                                                                        const btContactSolverInfo& infoGlobal,
+                                                                        btScalar lowerLimit, btScalar upperLimit,
+                                                                        bool angConstraint = false,
+
+                                                                        btScalar relaxation = 1.f,
+                                                                        bool isFriction = false, btScalar desiredVelocity = 0, btScalar cfmSlip = 0, btScalar damping = 1.0);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btMultiBodyConstraint(btMultiBody * bodyA, btMultiBody * bodyB, int linkA, int linkB, int numRows, bool isUnilateral, int type);
+       virtual ~btMultiBodyConstraint();
+
+       void updateJacobianSizes();
+       void allocateJacobiansMultiDof();
+
+       int getConstraintType() const
+       {
+               return m_type;
+       }
+       //many constraints have setFrameInB/setPivotInB. Will use 'getConstraintType' later.
+       virtual void setFrameInB(const btMatrix3x3& frameInB) {}
+       virtual void setPivotInB(const btVector3& pivotInB) {}
+
+       virtual void finalizeMultiDof() = 0;
+
+       virtual int getIslandIdA() const = 0;
+       virtual int getIslandIdB() const = 0;
+
+       virtual void createConstraintRows(btMultiBodyConstraintArray & constraintRows,
+                                                                         btMultiBodyJacobianData & data,
+                                                                         const btContactSolverInfo& infoGlobal) = 0;
+
+       int getNumRows() const
+       {
+               return m_numRows;
+       }
+
+       btMultiBody* getMultiBodyA()
+       {
+               return m_bodyA;
+       }
+       btMultiBody* getMultiBodyB()
+       {
+               return m_bodyB;
+       }
+
+       int getLinkA() const
+       {
+               return m_linkA;
+       }
+       int getLinkB() const
+       {
+               return m_linkB;
+       }
+       void internalSetAppliedImpulse(int dof, btScalar appliedImpulse)
+       {
+               btAssert(dof >= 0);
+               btAssert(dof < getNumRows());
+               m_data[dof] = appliedImpulse;
+       }
+
+       btScalar getAppliedImpulse(int dof)
+       {
+               btAssert(dof >= 0);
+               btAssert(dof < getNumRows());
+               return m_data[dof];
+       }
+       // current constraint position
+       // constraint is pos >= 0 for unilateral, or pos = 0 for bilateral
+       // NOTE: ignored position for friction rows.
+       btScalar getPosition(int row) const
+       {
+               return m_data[m_posOffset + row];
+       }
+
+       void setPosition(int row, btScalar pos)
+       {
+               m_data[m_posOffset + row] = pos;
+       }
+
+       bool isUnilateral() const
+       {
+               return m_isUnilateral;
+       }
+
+       // jacobian blocks.
+       // each of size 6 + num_links. (jacobian2 is null if no body2.)
+       // format: 3 'omega' coefficients, 3 'v' coefficients, then the 'qdot' coefficients.
+       btScalar* jacobianA(int row)
+       {
+               return &m_data[m_numRows + row * m_jacSizeBoth];
+       }
+       const btScalar* jacobianA(int row) const
+       {
+               return &m_data[m_numRows + (row * m_jacSizeBoth)];
+       }
+       btScalar* jacobianB(int row)
+       {
+               return &m_data[m_numRows + (row * m_jacSizeBoth) + m_jacSizeA];
+       }
+       const btScalar* jacobianB(int row) const
+       {
+               return &m_data[m_numRows + (row * m_jacSizeBoth) + m_jacSizeA];
+       }
+
+       btScalar getMaxAppliedImpulse() const
+       {
+               return m_maxAppliedImpulse;
+       }
+       void setMaxAppliedImpulse(btScalar maxImp)
+       {
+               m_maxAppliedImpulse = maxImp;
+       }
+
+       virtual void debugDraw(class btIDebugDraw * drawer) = 0;
+
+       virtual void setGearRatio(btScalar ratio) {}
+       virtual void setGearAuxLink(int gearAuxLink) {}
+       virtual void setRelativePositionTarget(btScalar relPosTarget) {}
+       virtual void setErp(btScalar erp) {}
+};
+
+#endif  //BT_MULTIBODY_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
new file mode 100644 (file)
index 0000000..2788367
--- /dev/null
@@ -0,0 +1,1752 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btMultiBodyConstraintSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "btMultiBodyLinkCollider.h"
+
+#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
+#include "btMultiBodyConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+#include "LinearMath/btQuickprof.h"
+#include "BulletDynamics/Featherstone/btMultiBodySolverConstraint.h"
+#include "LinearMath/btScalar.h"
+
+btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+       //solve featherstone non-contact constraints
+       btScalar nonContactResidual = 0;
+       //printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size());
+       for (int i = 0; i < infoGlobal.m_numNonContactInnerIterations; ++i)
+       {
+               // reset the nonContactResdual to 0 at start of each inner iteration
+               nonContactResidual = 0;
+               for (int j = 0; j < m_multiBodyNonContactConstraints.size(); j++)
+               {
+                       int index = iteration & 1 ? j : m_multiBodyNonContactConstraints.size() - 1 - j;
+
+                       btMultiBodySolverConstraint& constraint = m_multiBodyNonContactConstraints[index];
+
+                       btScalar residual = resolveSingleConstraintRowGeneric(constraint);
+                       nonContactResidual = btMax(nonContactResidual, residual * residual);
+
+                       if (constraint.m_multiBodyA)
+                               constraint.m_multiBodyA->setPosUpdated(false);
+                       if (constraint.m_multiBodyB)
+                               constraint.m_multiBodyB->setPosUpdated(false);
+               }
+       }
+       leastSquaredResidual = btMax(leastSquaredResidual, nonContactResidual);
+
+       //solve featherstone normal contact
+       for (int j0 = 0; j0 < m_multiBodyNormalContactConstraints.size(); j0++)
+       {
+               int index = j0;  //iteration&1? j0 : m_multiBodyNormalContactConstraints.size()-1-j0;
+
+               btMultiBodySolverConstraint& constraint = m_multiBodyNormalContactConstraints[index];
+               btScalar residual = 0.f;
+
+               if (iteration < infoGlobal.m_numIterations)
+               {
+                       residual = resolveSingleConstraintRowGeneric(constraint);
+               }
+
+               leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
+
+               if (constraint.m_multiBodyA)
+                       constraint.m_multiBodyA->setPosUpdated(false);
+               if (constraint.m_multiBodyB)
+                       constraint.m_multiBodyB->setPosUpdated(false);
+       }
+
+       //solve featherstone frictional contact
+       if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode & SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0))
+       {
+               for (int j1 = 0; j1 < this->m_multiBodySpinningFrictionContactConstraints.size(); j1++)
+               {
+                       if (iteration < infoGlobal.m_numIterations)
+                       {
+                               int index = j1;
+
+                               btMultiBodySolverConstraint& frictionConstraint = m_multiBodySpinningFrictionContactConstraints[index];
+                               btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
+                               //adjust friction limits here
+                               if (totalImpulse > btScalar(0))
+                               {
+                                       frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
+                                       frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
+                                       btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
+                                       leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
+
+                                       if (frictionConstraint.m_multiBodyA)
+                                               frictionConstraint.m_multiBodyA->setPosUpdated(false);
+                                       if (frictionConstraint.m_multiBodyB)
+                                               frictionConstraint.m_multiBodyB->setPosUpdated(false);
+                               }
+                       }
+               }
+
+               for (int j1 = 0; j1 < this->m_multiBodyTorsionalFrictionContactConstraints.size(); j1++)
+               {
+                       if (iteration < infoGlobal.m_numIterations)
+                       {
+                               int index = j1;  //iteration&1? j1 : m_multiBodyTorsionalFrictionContactConstraints.size()-1-j1;
+
+                               btMultiBodySolverConstraint& frictionConstraint = m_multiBodyTorsionalFrictionContactConstraints[index];
+                               btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
+                               j1++;
+                               int index2 = j1;
+                               btMultiBodySolverConstraint& frictionConstraintB = m_multiBodyTorsionalFrictionContactConstraints[index2];
+                               //adjust friction limits here
+                               if (totalImpulse > btScalar(0) && frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex)
+                               {
+                                       frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
+                                       frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
+                                       frictionConstraintB.m_lowerLimit = -(frictionConstraintB.m_friction * totalImpulse);
+                                       frictionConstraintB.m_upperLimit = frictionConstraintB.m_friction * totalImpulse;
+
+                                       btScalar residual = resolveConeFrictionConstraintRows(frictionConstraint, frictionConstraintB);
+                                       leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
+
+                                       if (frictionConstraint.m_multiBodyA)
+                                               frictionConstraint.m_multiBodyA->setPosUpdated(false);
+                                       if (frictionConstraint.m_multiBodyB)
+                                               frictionConstraint.m_multiBodyB->setPosUpdated(false);
+
+                                       if (frictionConstraintB.m_multiBodyA)
+                                               frictionConstraintB.m_multiBodyA->setPosUpdated(false);
+                                       if (frictionConstraintB.m_multiBodyB)
+                                               frictionConstraintB.m_multiBodyB->setPosUpdated(false);
+                               }
+                       }
+               }
+
+               for (int j1 = 0; j1 < this->m_multiBodyFrictionContactConstraints.size(); j1++)
+               {
+                       if (iteration < infoGlobal.m_numIterations)
+                       {
+                               int index = j1;  //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
+                               btMultiBodySolverConstraint& frictionConstraint = m_multiBodyFrictionContactConstraints[index];
+
+                               btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
+                               j1++;
+                               int index2 = j1;  //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
+                               btMultiBodySolverConstraint& frictionConstraintB = m_multiBodyFrictionContactConstraints[index2];
+                               btAssert(frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex);
+
+                               if (frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex)
+                               {
+                                       frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
+                                       frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
+                                       frictionConstraintB.m_lowerLimit = -(frictionConstraintB.m_friction * totalImpulse);
+                                       frictionConstraintB.m_upperLimit = frictionConstraintB.m_friction * totalImpulse;
+                                       btScalar residual = resolveConeFrictionConstraintRows(frictionConstraint, frictionConstraintB);
+                                       leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
+
+                                       if (frictionConstraintB.m_multiBodyA)
+                                               frictionConstraintB.m_multiBodyA->setPosUpdated(false);
+                                       if (frictionConstraintB.m_multiBodyB)
+                                               frictionConstraintB.m_multiBodyB->setPosUpdated(false);
+
+                                       if (frictionConstraint.m_multiBodyA)
+                                               frictionConstraint.m_multiBodyA->setPosUpdated(false);
+                                       if (frictionConstraint.m_multiBodyB)
+                                               frictionConstraint.m_multiBodyB->setPosUpdated(false);
+                               }
+                       }
+               }
+       }
+       else
+       {
+               for (int j1 = 0; j1 < this->m_multiBodyFrictionContactConstraints.size(); j1++)
+               {
+                       if (iteration < infoGlobal.m_numIterations)
+                       {
+                               int index = j1;  //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
+
+                               btMultiBodySolverConstraint& frictionConstraint = m_multiBodyFrictionContactConstraints[index];
+                               btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
+                               //adjust friction limits here
+                               if (totalImpulse > btScalar(0))
+                               {
+                                       frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
+                                       frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
+                                       btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
+                                       leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
+
+                                       if (frictionConstraint.m_multiBodyA)
+                                               frictionConstraint.m_multiBodyA->setPosUpdated(false);
+                                       if (frictionConstraint.m_multiBodyB)
+                                               frictionConstraint.m_multiBodyB->setPosUpdated(false);
+                               }
+                       }
+               }
+       }
+       return leastSquaredResidual;
+}
+
+btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       m_multiBodyNonContactConstraints.resize(0);
+       m_multiBodyNormalContactConstraints.resize(0);
+       m_multiBodyFrictionContactConstraints.resize(0);
+       m_multiBodyTorsionalFrictionContactConstraints.resize(0);
+       m_multiBodySpinningFrictionContactConstraints.resize(0);
+
+       m_data.m_jacobians.resize(0);
+       m_data.m_deltaVelocitiesUnitImpulse.resize(0);
+       m_data.m_deltaVelocities.resize(0);
+
+       for (int i = 0; i < numBodies; i++)
+       {
+               const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(bodies[i]);
+               if (fcA)
+               {
+                       fcA->m_multiBody->setCompanionId(-1);
+               }
+       }
+
+       btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+       return val;
+}
+
+void btMultiBodyConstraintSolver::applyDeltaVee(btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
+{
+       for (int i = 0; i < ndof; ++i)
+               m_data.m_deltaVelocities[velocityIndex + i] += delta_vee[i] * impulse;
+}
+
+btScalar btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c)
+{
+       btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
+       btScalar deltaVelADotn = 0;
+       btScalar deltaVelBDotn = 0;
+       btSolverBody* bodyA = 0;
+       btSolverBody* bodyB = 0;
+       int ndofA = 0;
+       int ndofB = 0;
+
+       if (c.m_multiBodyA)
+       {
+               ndofA = c.m_multiBodyA->getNumDofs() + 6;
+               for (int i = 0; i < ndofA; ++i)
+                       deltaVelADotn += m_data.m_jacobians[c.m_jacAindex + i] * m_data.m_deltaVelocities[c.m_deltaVelAindex + i];
+       }
+       else if (c.m_solverBodyIdA >= 0)
+       {
+               bodyA = &m_tmpSolverBodyPool[c.m_solverBodyIdA];
+               deltaVelADotn += c.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
+       }
+
+       if (c.m_multiBodyB)
+       {
+               ndofB = c.m_multiBodyB->getNumDofs() + 6;
+               for (int i = 0; i < ndofB; ++i)
+                       deltaVelBDotn += m_data.m_jacobians[c.m_jacBindex + i] * m_data.m_deltaVelocities[c.m_deltaVelBindex + i];
+       }
+       else if (c.m_solverBodyIdB >= 0)
+       {
+               bodyB = &m_tmpSolverBodyPool[c.m_solverBodyIdB];
+               deltaVelBDotn += c.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
+       }
+
+       deltaImpulse -= deltaVelADotn * c.m_jacDiagABInv;  //m_jacDiagABInv = 1./denom
+       deltaImpulse -= deltaVelBDotn * c.m_jacDiagABInv;
+       const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
+
+       if (sum < c.m_lowerLimit)
+       {
+               deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
+               c.m_appliedImpulse = c.m_lowerLimit;
+       }
+       else if (sum > c.m_upperLimit)
+       {
+               deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
+               c.m_appliedImpulse = c.m_upperLimit;
+       }
+       else
+       {
+               c.m_appliedImpulse = sum;
+       }
+
+       if (c.m_multiBodyA)
+       {
+               applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse, c.m_deltaVelAindex, ndofA);
+#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+               //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
+               //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
+               c.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse);
+#endif  //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+       }
+       else if (c.m_solverBodyIdA >= 0)
+       {
+               bodyA->internalApplyImpulse(c.m_contactNormal1 * bodyA->internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+       }
+       if (c.m_multiBodyB)
+       {
+               applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse, c.m_deltaVelBindex, ndofB);
+#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+               //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
+               //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
+               c.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse);
+#endif  //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+       }
+       else if (c.m_solverBodyIdB >= 0)
+       {
+               bodyB->internalApplyImpulse(c.m_contactNormal2 * bodyB->internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+       }
+       btScalar deltaVel = deltaImpulse / c.m_jacDiagABInv;
+       return deltaVel;
+}
+
+btScalar btMultiBodyConstraintSolver::resolveConeFrictionConstraintRows(const btMultiBodySolverConstraint& cA1, const btMultiBodySolverConstraint& cB)
+{
+       int ndofA = 0;
+       int ndofB = 0;
+       btSolverBody* bodyA = 0;
+       btSolverBody* bodyB = 0;
+       btScalar deltaImpulseB = 0.f;
+       btScalar sumB = 0.f;
+       {
+               deltaImpulseB = cB.m_rhs - btScalar(cB.m_appliedImpulse) * cB.m_cfm;
+               btScalar deltaVelADotn = 0;
+               btScalar deltaVelBDotn = 0;
+               if (cB.m_multiBodyA)
+               {
+                       ndofA = cB.m_multiBodyA->getNumDofs() + 6;
+                       for (int i = 0; i < ndofA; ++i)
+                               deltaVelADotn += m_data.m_jacobians[cB.m_jacAindex + i] * m_data.m_deltaVelocities[cB.m_deltaVelAindex + i];
+               }
+               else if (cB.m_solverBodyIdA >= 0)
+               {
+                       bodyA = &m_tmpSolverBodyPool[cB.m_solverBodyIdA];
+                       deltaVelADotn += cB.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + cB.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
+               }
+
+               if (cB.m_multiBodyB)
+               {
+                       ndofB = cB.m_multiBodyB->getNumDofs() + 6;
+                       for (int i = 0; i < ndofB; ++i)
+                               deltaVelBDotn += m_data.m_jacobians[cB.m_jacBindex + i] * m_data.m_deltaVelocities[cB.m_deltaVelBindex + i];
+               }
+               else if (cB.m_solverBodyIdB >= 0)
+               {
+                       bodyB = &m_tmpSolverBodyPool[cB.m_solverBodyIdB];
+                       deltaVelBDotn += cB.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + cB.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
+               }
+
+               deltaImpulseB -= deltaVelADotn * cB.m_jacDiagABInv;  //m_jacDiagABInv = 1./denom
+               deltaImpulseB -= deltaVelBDotn * cB.m_jacDiagABInv;
+               sumB = btScalar(cB.m_appliedImpulse) + deltaImpulseB;
+       }
+
+       btScalar deltaImpulseA = 0.f;
+       btScalar sumA = 0.f;
+       const btMultiBodySolverConstraint& cA = cA1;
+       {
+               {
+                       deltaImpulseA = cA.m_rhs - btScalar(cA.m_appliedImpulse) * cA.m_cfm;
+                       btScalar deltaVelADotn = 0;
+                       btScalar deltaVelBDotn = 0;
+                       if (cA.m_multiBodyA)
+                       {
+                               ndofA = cA.m_multiBodyA->getNumDofs() + 6;
+                               for (int i = 0; i < ndofA; ++i)
+                                       deltaVelADotn += m_data.m_jacobians[cA.m_jacAindex + i] * m_data.m_deltaVelocities[cA.m_deltaVelAindex + i];
+                       }
+                       else if (cA.m_solverBodyIdA >= 0)
+                       {
+                               bodyA = &m_tmpSolverBodyPool[cA.m_solverBodyIdA];
+                               deltaVelADotn += cA.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + cA.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
+                       }
+
+                       if (cA.m_multiBodyB)
+                       {
+                               ndofB = cA.m_multiBodyB->getNumDofs() + 6;
+                               for (int i = 0; i < ndofB; ++i)
+                                       deltaVelBDotn += m_data.m_jacobians[cA.m_jacBindex + i] * m_data.m_deltaVelocities[cA.m_deltaVelBindex + i];
+                       }
+                       else if (cA.m_solverBodyIdB >= 0)
+                       {
+                               bodyB = &m_tmpSolverBodyPool[cA.m_solverBodyIdB];
+                               deltaVelBDotn += cA.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + cA.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
+                       }
+
+                       deltaImpulseA -= deltaVelADotn * cA.m_jacDiagABInv;  //m_jacDiagABInv = 1./denom
+                       deltaImpulseA -= deltaVelBDotn * cA.m_jacDiagABInv;
+                       sumA = btScalar(cA.m_appliedImpulse) + deltaImpulseA;
+               }
+       }
+
+       if (sumA * sumA + sumB * sumB >= cA.m_lowerLimit * cB.m_lowerLimit)
+       {
+               btScalar angle = btAtan2(sumA, sumB);
+               btScalar sumAclipped = btFabs(cA.m_lowerLimit * btSin(angle));
+               btScalar sumBclipped = btFabs(cB.m_lowerLimit * btCos(angle));
+
+               if (sumA < -sumAclipped)
+               {
+                       deltaImpulseA = -sumAclipped - cA.m_appliedImpulse;
+                       cA.m_appliedImpulse = -sumAclipped;
+               }
+               else if (sumA > sumAclipped)
+               {
+                       deltaImpulseA = sumAclipped - cA.m_appliedImpulse;
+                       cA.m_appliedImpulse = sumAclipped;
+               }
+               else
+               {
+                       cA.m_appliedImpulse = sumA;
+               }
+
+               if (sumB < -sumBclipped)
+               {
+                       deltaImpulseB = -sumBclipped - cB.m_appliedImpulse;
+                       cB.m_appliedImpulse = -sumBclipped;
+               }
+               else if (sumB > sumBclipped)
+               {
+                       deltaImpulseB = sumBclipped - cB.m_appliedImpulse;
+                       cB.m_appliedImpulse = sumBclipped;
+               }
+               else
+               {
+                       cB.m_appliedImpulse = sumB;
+               }
+               //deltaImpulseA = sumAclipped-cA.m_appliedImpulse;
+               //cA.m_appliedImpulse = sumAclipped;
+               //deltaImpulseB = sumBclipped-cB.m_appliedImpulse;
+               //cB.m_appliedImpulse = sumBclipped;
+       }
+       else
+       {
+               cA.m_appliedImpulse = sumA;
+               cB.m_appliedImpulse = sumB;
+       }
+
+       if (cA.m_multiBodyA)
+       {
+               applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacAindex], deltaImpulseA, cA.m_deltaVelAindex, ndofA);
+#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+               //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
+               //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
+               cA.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacAindex], deltaImpulseA);
+#endif  //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+       }
+       else if (cA.m_solverBodyIdA >= 0)
+       {
+               bodyA->internalApplyImpulse(cA.m_contactNormal1 * bodyA->internalGetInvMass(), cA.m_angularComponentA, deltaImpulseA);
+       }
+       if (cA.m_multiBodyB)
+       {
+               applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacBindex], deltaImpulseA, cA.m_deltaVelBindex, ndofB);
+#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+               //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
+               //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
+               cA.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacBindex], deltaImpulseA);
+#endif  //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+       }
+       else if (cA.m_solverBodyIdB >= 0)
+       {
+               bodyB->internalApplyImpulse(cA.m_contactNormal2 * bodyB->internalGetInvMass(), cA.m_angularComponentB, deltaImpulseA);
+       }
+
+       if (cB.m_multiBodyA)
+       {
+               applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacAindex], deltaImpulseB, cB.m_deltaVelAindex, ndofA);
+#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+               //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
+               //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
+               cB.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacAindex], deltaImpulseB);
+#endif  //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+       }
+       else if (cB.m_solverBodyIdA >= 0)
+       {
+               bodyA->internalApplyImpulse(cB.m_contactNormal1 * bodyA->internalGetInvMass(), cB.m_angularComponentA, deltaImpulseB);
+       }
+       if (cB.m_multiBodyB)
+       {
+               applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacBindex], deltaImpulseB, cB.m_deltaVelBindex, ndofB);
+#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+               //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
+               //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
+               cB.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacBindex], deltaImpulseB);
+#endif  //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+       }
+       else if (cB.m_solverBodyIdB >= 0)
+       {
+               bodyB->internalApplyImpulse(cB.m_contactNormal2 * bodyB->internalGetInvMass(), cB.m_angularComponentB, deltaImpulseB);
+       }
+
+       btScalar deltaVel = deltaImpulseA / cA.m_jacDiagABInv + deltaImpulseB / cB.m_jacDiagABInv;
+       return deltaVel;
+}
+
+void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint, const btVector3& contactNormal, const btScalar& appliedImpulse, btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, btScalar& relaxation, bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
+{
+       BT_PROFILE("setupMultiBodyContactConstraint");
+       btVector3 rel_pos1;
+       btVector3 rel_pos2;
+
+       btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+       btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+
+       const btVector3& pos1 = cp.getPositionWorldOnA();
+       const btVector3& pos2 = cp.getPositionWorldOnB();
+
+       btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
+       btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
+
+       btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
+       btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
+
+       if (bodyA)
+               rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+       if (bodyB)
+               rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+
+       relaxation = infoGlobal.m_sor;
+
+       btScalar invTimeStep = btScalar(1) / infoGlobal.m_timeStep;
+
+       //cfm = 1 /       ( dt * kp + kd )
+       //erp = dt * kp / ( dt * kp + kd )
+
+       btScalar cfm;
+       btScalar erp;
+       if (isFriction)
+       {
+               cfm = infoGlobal.m_frictionCFM;
+               erp = infoGlobal.m_frictionERP;
+       }
+       else
+       {
+               cfm = infoGlobal.m_globalCfm;
+               erp = infoGlobal.m_erp2;
+
+               if ((cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP))
+               {
+                       if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM)
+                               cfm = cp.m_contactCFM;
+                       if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP)
+                               erp = cp.m_contactERP;
+               }
+               else
+               {
+                       if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
+                       {
+                               btScalar denom = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1);
+                               if (denom < SIMD_EPSILON)
+                               {
+                                       denom = SIMD_EPSILON;
+                               }
+                               cfm = btScalar(1) / denom;
+                               erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
+                       }
+               }
+       }
+
+       cfm *= invTimeStep;
+
+       if (multiBodyA)
+       {
+               if (solverConstraint.m_linkA < 0)
+               {
+                       rel_pos1 = pos1 - multiBodyA->getBasePos();
+               }
+               else
+               {
+                       rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
+               }
+               const int ndofA = multiBodyA->getNumDofs() + 6;
+
+               solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
+
+               if (solverConstraint.m_deltaVelAindex < 0)
+               {
+                       solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
+                       multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
+                       m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofA);
+               }
+               else
+               {
+                       btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
+               }
+
+               solverConstraint.m_jacAindex = m_data.m_jacobians.size();
+               m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofA);
+               m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofA);
+               btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
+
+               btScalar* jac1 = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+               multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), contactNormal, jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
+               btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+               multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex], delta, m_data.scratch_r, m_data.scratch_v);
+
+               btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
+               solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+               solverConstraint.m_contactNormal1 = contactNormal;
+       }
+       else
+       {
+               btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
+               solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+               solverConstraint.m_contactNormal1 = contactNormal;
+               solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
+       }
+
+       if (multiBodyB)
+       {
+               if (solverConstraint.m_linkB < 0)
+               {
+                       rel_pos2 = pos2 - multiBodyB->getBasePos();
+               }
+               else
+               {
+                       rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
+               }
+
+               const int ndofB = multiBodyB->getNumDofs() + 6;
+
+               solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
+               if (solverConstraint.m_deltaVelBindex < 0)
+               {
+                       solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
+                       multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
+                       m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofB);
+               }
+
+               solverConstraint.m_jacBindex = m_data.m_jacobians.size();
+
+               m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofB);
+               m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
+               btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
+
+               multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -contactNormal, &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
+               multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex], &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v);
+
+               btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
+               solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+               solverConstraint.m_contactNormal2 = -contactNormal;
+       }
+       else
+       {
+               btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
+               solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+               solverConstraint.m_contactNormal2 = -contactNormal;
+
+               solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
+       }
+
+       {
+               btVector3 vec;
+               btScalar denom0 = 0.f;
+               btScalar denom1 = 0.f;
+               btScalar* jacB = 0;
+               btScalar* jacA = 0;
+               btScalar* lambdaA = 0;
+               btScalar* lambdaB = 0;
+               int ndofA = 0;
+               if (multiBodyA)
+               {
+                       ndofA = multiBodyA->getNumDofs() + 6;
+                       jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+                       lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+                       for (int i = 0; i < ndofA; ++i)
+                       {
+                               btScalar j = jacA[i];
+                               btScalar l = lambdaA[i];
+                               denom0 += j * l;
+                       }
+               }
+               else
+               {
+                       if (rb0)
+                       {
+                               vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
+                               denom0 = rb0->getInvMass() + contactNormal.dot(vec);
+                       }
+               }
+               if (multiBodyB)
+               {
+                       const int ndofB = multiBodyB->getNumDofs() + 6;
+                       jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
+                       lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+                       for (int i = 0; i < ndofB; ++i)
+                       {
+                               btScalar j = jacB[i];
+                               btScalar l = lambdaB[i];
+                               denom1 += j * l;
+                       }
+               }
+               else
+               {
+                       if (rb1)
+                       {
+                               vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
+                               denom1 = rb1->getInvMass() + contactNormal.dot(vec);
+                       }
+               }
+
+               btScalar d = denom0 + denom1 + cfm;
+               if (d > SIMD_EPSILON)
+               {
+                       solverConstraint.m_jacDiagABInv = relaxation / (d);
+               }
+               else
+               {
+                       //disable the constraint row to handle singularity/redundant constraint
+                       solverConstraint.m_jacDiagABInv = 0.f;
+               }
+       }
+
+       //compute rhs and remaining solverConstraint fields
+
+       btScalar restitution = 0.f;
+       btScalar distance = 0;
+       if (!isFriction)
+       {
+               distance = cp.getDistance() + infoGlobal.m_linearSlop;
+       }
+       else
+       {
+               if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
+               {
+                       distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(contactNormal);
+               }
+       }
+
+       btScalar rel_vel = 0.f;
+       int ndofA = 0;
+       int ndofB = 0;
+       {
+               btVector3 vel1, vel2;
+               if (multiBodyA)
+               {
+                       ndofA = multiBodyA->getNumDofs() + 6;
+                       btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+                       for (int i = 0; i < ndofA; ++i)
+                               rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
+               }
+               else
+               {
+                       if (rb0)
+                       {
+                               rel_vel += (rb0->getVelocityInLocalPoint(rel_pos1) +
+                                                       (rb0->getTotalTorque() * rb0->getInvInertiaTensorWorld() * infoGlobal.m_timeStep).cross(rel_pos1) +
+                                                       rb0->getTotalForce() * rb0->getInvMass() * infoGlobal.m_timeStep)
+                                                          .dot(solverConstraint.m_contactNormal1);
+                       }
+               }
+               if (multiBodyB)
+               {
+                       ndofB = multiBodyB->getNumDofs() + 6;
+                       btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
+                       for (int i = 0; i < ndofB; ++i)
+                               rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
+               }
+               else
+               {
+                       if (rb1)
+                       {
+                               rel_vel += (rb1->getVelocityInLocalPoint(rel_pos2) +
+                                                       (rb1->getTotalTorque() * rb1->getInvInertiaTensorWorld() * infoGlobal.m_timeStep).cross(rel_pos2) +
+                                                       rb1->getTotalForce() * rb1->getInvMass() * infoGlobal.m_timeStep)
+                                                          .dot(solverConstraint.m_contactNormal2);
+                       }
+               }
+
+               solverConstraint.m_friction = cp.m_combinedFriction;
+
+               if (!isFriction)
+               {
+                       restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+                       if (restitution <= btScalar(0.))
+                       {
+                               restitution = 0.f;
+                       }
+               }
+       }
+
+       {
+               btScalar positionalError = 0.f;
+               btScalar velocityError = restitution - rel_vel;  // * damping;  //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
+               if (isFriction)
+               {
+                       positionalError = -distance * erp / infoGlobal.m_timeStep;
+               }
+               else
+               {
+                       if (distance > 0)
+                       {
+                               positionalError = 0;
+                               velocityError -= distance / infoGlobal.m_timeStep;
+                       }
+                       else
+                       {
+                               positionalError = -distance * erp / infoGlobal.m_timeStep;
+                       }
+               }
+
+               btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
+               btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+
+               if (!isFriction)
+               {
+                       //      if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+                       {
+                               //combine position and velocity into rhs
+                               solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+                               solverConstraint.m_rhsPenetration = 0.f;
+                       }
+                       /*else
+                       {
+                               //split position and velocity into rhs and m_rhsPenetration
+                               solverConstraint.m_rhs = velocityImpulse;
+                               solverConstraint.m_rhsPenetration = penetrationImpulse;
+                       }
+                       */
+                       solverConstraint.m_lowerLimit = 0;
+                       solverConstraint.m_upperLimit = 1e10f;
+               }
+               else
+               {
+                       solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
+                       solverConstraint.m_rhsPenetration = 0.f;
+                       solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
+                       solverConstraint.m_upperLimit = solverConstraint.m_friction;
+               }
+
+               solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
+       }
+        
+       if (infoGlobal.m_solverMode & SOLVER_USE_ARTICULATED_WARMSTARTING)
+       {
+               if (btFabs(cp.m_prevRHS) > 1e-5 && cp.m_prevRHS < 2* solverConstraint.m_rhs && solverConstraint.m_rhs < 2*cp.m_prevRHS)
+               {
+                       solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse / cp.m_prevRHS * solverConstraint.m_rhs * infoGlobal.m_articulatedWarmstartingFactor;
+                       if (solverConstraint.m_appliedImpulse < 0)
+                               solverConstraint.m_appliedImpulse = 0;
+               }
+               else
+               {
+                       solverConstraint.m_appliedImpulse = 0.f;
+               }
+
+               if (solverConstraint.m_appliedImpulse)
+               {
+                       if (multiBodyA)
+                       {
+                               btScalar impulse = solverConstraint.m_appliedImpulse;
+                               btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+                               multiBodyA->applyDeltaVeeMultiDof2(deltaV, impulse);
+
+                               applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
+                       }
+                       else
+                       {
+                               if (rb0)
+                                       bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass() * rb0->getLinearFactor(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
+                       }
+                       if (multiBodyB)
+                       {
+                               btScalar impulse = solverConstraint.m_appliedImpulse;
+                               btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+                               multiBodyB->applyDeltaVeeMultiDof2(deltaV, impulse);
+                               applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
+                       }
+                       else
+                       {
+                               if (rb1)
+                                       bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() * rb1->getLinearFactor(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
+                       }
+               }
+       }
+       else
+       {
+               solverConstraint.m_appliedImpulse = 0.f;
+       solverConstraint.m_appliedPushImpulse = 0.f;
+       }
+}
+
+void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint,
+                                                                                                                                                       const btVector3& constraintNormal,
+                                                                                                                                                       btManifoldPoint& cp,
+                                                                                                                                                       btScalar combinedTorsionalFriction,
+                                                                                                                                                       const btContactSolverInfo& infoGlobal,
+                                                                                                                                                       btScalar& relaxation,
+                                                                                                                                                       bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
+{
+       BT_PROFILE("setupMultiBodyRollingFrictionConstraint");
+       btVector3 rel_pos1;
+       btVector3 rel_pos2;
+
+       btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+       btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+
+       const btVector3& pos1 = cp.getPositionWorldOnA();
+       const btVector3& pos2 = cp.getPositionWorldOnB();
+
+       btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
+       btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
+
+       btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
+       btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
+
+       if (bodyA)
+               rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+       if (bodyB)
+               rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
+
+       relaxation = infoGlobal.m_sor;
+
+       // btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
+
+       if (multiBodyA)
+       {
+               if (solverConstraint.m_linkA < 0)
+               {
+                       rel_pos1 = pos1 - multiBodyA->getBasePos();
+               }
+               else
+               {
+                       rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
+               }
+               const int ndofA = multiBodyA->getNumDofs() + 6;
+
+               solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
+
+               if (solverConstraint.m_deltaVelAindex < 0)
+               {
+                       solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
+                       multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
+                       m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofA);
+               }
+               else
+               {
+                       btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
+               }
+
+               solverConstraint.m_jacAindex = m_data.m_jacobians.size();
+               m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofA);
+               m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofA);
+               btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
+
+               btScalar* jac1 = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+               multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), constraintNormal, btVector3(0, 0, 0), jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
+               btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+               multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex], delta, m_data.scratch_r, m_data.scratch_v);
+
+               btVector3 torqueAxis0 = constraintNormal;
+               solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+               solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
+       }
+       else
+       {
+               btVector3 torqueAxis0 = constraintNormal;
+               solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+               solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
+               solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
+       }
+
+       if (multiBodyB)
+       {
+               if (solverConstraint.m_linkB < 0)
+               {
+                       rel_pos2 = pos2 - multiBodyB->getBasePos();
+               }
+               else
+               {
+                       rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
+               }
+
+               const int ndofB = multiBodyB->getNumDofs() + 6;
+
+               solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
+               if (solverConstraint.m_deltaVelBindex < 0)
+               {
+                       solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
+                       multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
+                       m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofB);
+               }
+
+               solverConstraint.m_jacBindex = m_data.m_jacobians.size();
+
+               m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofB);
+               m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
+               btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
+
+               multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -constraintNormal, btVector3(0, 0, 0), &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
+               multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex], &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v);
+
+               btVector3 torqueAxis1 = -constraintNormal;
+               solverConstraint.m_relpos2CrossNormal = torqueAxis1;
+               solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
+       }
+       else
+       {
+               btVector3 torqueAxis1 = -constraintNormal;
+               solverConstraint.m_relpos2CrossNormal = torqueAxis1;
+               solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
+
+               solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
+       }
+
+       {
+               btScalar denom0 = 0.f;
+               btScalar denom1 = 0.f;
+               btScalar* jacB = 0;
+               btScalar* jacA = 0;
+               btScalar* lambdaA = 0;
+               btScalar* lambdaB = 0;
+               int ndofA = 0;
+               if (multiBodyA)
+               {
+                       ndofA = multiBodyA->getNumDofs() + 6;
+                       jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+                       lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+                       for (int i = 0; i < ndofA; ++i)
+                       {
+                               btScalar j = jacA[i];
+                               btScalar l = lambdaA[i];
+                               denom0 += j * l;
+                       }
+               }
+               else
+               {
+                       if (rb0)
+                       {
+                               btVector3 iMJaA = rb0 ? rb0->getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal : btVector3(0, 0, 0);
+                               denom0 = iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+                       }
+               }
+               if (multiBodyB)
+               {
+                       const int ndofB = multiBodyB->getNumDofs() + 6;
+                       jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
+                       lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+                       for (int i = 0; i < ndofB; ++i)
+                       {
+                               btScalar j = jacB[i];
+                               btScalar l = lambdaB[i];
+                               denom1 += j * l;
+                       }
+               }
+               else
+               {
+                       if (rb1)
+                       {
+                               btVector3 iMJaB = rb1 ? rb1->getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal : btVector3(0, 0, 0);
+                               denom1 = iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+                       }
+               }
+
+               btScalar d = denom0 + denom1 + infoGlobal.m_globalCfm;
+               if (d > SIMD_EPSILON)
+               {
+                       solverConstraint.m_jacDiagABInv = relaxation / (d);
+               }
+               else
+               {
+                       //disable the constraint row to handle singularity/redundant constraint
+                       solverConstraint.m_jacDiagABInv = 0.f;
+               }
+       }
+
+       //compute rhs and remaining solverConstraint fields
+
+       btScalar restitution = 0.f;
+       btScalar penetration = isFriction ? 0 : cp.getDistance();
+
+       btScalar rel_vel = 0.f;
+       int ndofA = 0;
+       int ndofB = 0;
+       {
+               btVector3 vel1, vel2;
+               if (multiBodyA)
+               {
+                       ndofA = multiBodyA->getNumDofs() + 6;
+                       btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
+                       for (int i = 0; i < ndofA; ++i)
+                               rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
+               }
+               else
+               {
+                       if (rb0)
+                       {
+                               btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
+                               rel_vel += solverConstraint.m_contactNormal1.dot(rb0 ? solverBodyA->m_linearVelocity + solverBodyA->m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(rb0 ? solverBodyA->m_angularVelocity : btVector3(0, 0, 0));
+                       }
+               }
+               if (multiBodyB)
+               {
+                       ndofB = multiBodyB->getNumDofs() + 6;
+                       btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
+                       for (int i = 0; i < ndofB; ++i)
+                               rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
+               }
+               else
+               {
+                       if (rb1)
+                       {
+                               btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
+                               rel_vel += solverConstraint.m_contactNormal2.dot(rb1 ? solverBodyB->m_linearVelocity + solverBodyB->m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(rb1 ? solverBodyB->m_angularVelocity : btVector3(0, 0, 0));
+                       }
+               }
+
+               solverConstraint.m_friction = combinedTorsionalFriction;
+
+               if (!isFriction)
+               {
+                       restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
+                       if (restitution <= btScalar(0.))
+                       {
+                               restitution = 0.f;
+                       }
+               }
+       }
+
+       solverConstraint.m_appliedImpulse = 0.f;
+       solverConstraint.m_appliedPushImpulse = 0.f;
+
+       {
+               btScalar velocityError = 0 - rel_vel;  // * damping;    //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
+
+               btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
+
+               solverConstraint.m_rhs = velocityImpulse;
+               solverConstraint.m_rhsPenetration = 0.f;
+               solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
+               solverConstraint.m_upperLimit = solverConstraint.m_friction;
+
+               solverConstraint.m_cfm = infoGlobal.m_globalCfm * solverConstraint.m_jacDiagABInv;
+       }
+}
+
+btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis, const btScalar& appliedImpulse, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+{
+       BT_PROFILE("addMultiBodyFrictionConstraint");
+       btMultiBodySolverConstraint& solverConstraint = m_multiBodyFrictionContactConstraints.expandNonInitializing();
+       solverConstraint.m_orgConstraint = 0;
+       solverConstraint.m_orgDofIndex = -1;
+
+       solverConstraint.m_frictionIndex = frictionIndex;
+       bool isFriction = true;
+
+       const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+       const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+
+       btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
+       btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
+
+       int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+       int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
+
+       solverConstraint.m_solverBodyIdA = solverBodyIdA;
+       solverConstraint.m_solverBodyIdB = solverBodyIdB;
+       solverConstraint.m_multiBodyA = mbA;
+       if (mbA)
+               solverConstraint.m_linkA = fcA->m_link;
+
+       solverConstraint.m_multiBodyB = mbB;
+       if (mbB)
+               solverConstraint.m_linkB = fcB->m_link;
+
+       solverConstraint.m_originalContactPoint = &cp;
+
+       setupMultiBodyContactConstraint(solverConstraint, normalAxis, 0, cp, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
+       return solverConstraint;
+}
+
+btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
+                                                                                                                                                                                                 btScalar combinedTorsionalFriction,
+                                                                                                                                                                                                 btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+{
+       BT_PROFILE("addMultiBodyRollingFrictionConstraint");
+
+       bool useTorsionalAndConeFriction = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode & SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0));
+
+       btMultiBodySolverConstraint& solverConstraint = useTorsionalAndConeFriction ? m_multiBodyTorsionalFrictionContactConstraints.expandNonInitializing() : m_multiBodyFrictionContactConstraints.expandNonInitializing();
+       solverConstraint.m_orgConstraint = 0;
+       solverConstraint.m_orgDofIndex = -1;
+
+       solverConstraint.m_frictionIndex = frictionIndex;
+       bool isFriction = true;
+
+       const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+       const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+
+       btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
+       btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
+
+       int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+       int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
+
+       solverConstraint.m_solverBodyIdA = solverBodyIdA;
+       solverConstraint.m_solverBodyIdB = solverBodyIdB;
+       solverConstraint.m_multiBodyA = mbA;
+       if (mbA)
+               solverConstraint.m_linkA = fcA->m_link;
+
+       solverConstraint.m_multiBodyB = mbB;
+       if (mbB)
+               solverConstraint.m_linkB = fcB->m_link;
+
+       solverConstraint.m_originalContactPoint = &cp;
+
+       setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
+       return solverConstraint;
+}
+
+btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodySpinningFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
+       btScalar combinedTorsionalFriction,
+       btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
+{
+       BT_PROFILE("addMultiBodyRollingFrictionConstraint");
+
+       btMultiBodySolverConstraint& solverConstraint = m_multiBodySpinningFrictionContactConstraints.expandNonInitializing();
+       solverConstraint.m_orgConstraint = 0;
+       solverConstraint.m_orgDofIndex = -1;
+
+       solverConstraint.m_frictionIndex = frictionIndex;
+       bool isFriction = true;
+
+       const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+       const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+
+       btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
+       btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
+
+       int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+       int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
+
+       solverConstraint.m_solverBodyIdA = solverBodyIdA;
+       solverConstraint.m_solverBodyIdB = solverBodyIdB;
+       solverConstraint.m_multiBodyA = mbA;
+       if (mbA)
+               solverConstraint.m_linkA = fcA->m_link;
+
+       solverConstraint.m_multiBodyB = mbB;
+       if (mbB)
+               solverConstraint.m_linkB = fcB->m_link;
+
+       solverConstraint.m_originalContactPoint = &cp;
+
+       setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
+       return solverConstraint;
+}
+void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
+{
+       const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+       const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+       
+       btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
+       btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
+
+       btCollisionObject *colObj0 = 0, *colObj1 = 0;
+
+       colObj0 = (btCollisionObject*)manifold->getBody0();
+       colObj1 = (btCollisionObject*)manifold->getBody1();
+
+       int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
+       int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
+
+       //      btSolverBody* solverBodyA = mbA ? 0 : &m_tmpSolverBodyPool[solverBodyIdA];
+       //      btSolverBody* solverBodyB = mbB ? 0 : &m_tmpSolverBodyPool[solverBodyIdB];
+
+       ///avoid collision response between two static objects
+       //      if (!solverBodyA || (solverBodyA->m_invMass.isZero() && (!solverBodyB || solverBodyB->m_invMass.isZero())))
+       //      return;
+
+       //only a single rollingFriction per manifold
+       int rollingFriction = 4;
+
+       for (int j = 0; j < manifold->getNumContacts(); j++)
+       {
+               btManifoldPoint& cp = manifold->getContactPoint(j);
+
+               if (cp.getDistance() <= manifold->getContactProcessingThreshold())
+               {
+                       btScalar relaxation;
+
+                       int frictionIndex = m_multiBodyNormalContactConstraints.size();
+
+                       btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints.expandNonInitializing();
+
+                       //              btRigidBody* rb0 = btRigidBody::upcast(colObj0);
+                       //              btRigidBody* rb1 = btRigidBody::upcast(colObj1);
+                       solverConstraint.m_orgConstraint = 0;
+                       solverConstraint.m_orgDofIndex = -1;
+                       solverConstraint.m_solverBodyIdA = solverBodyIdA;
+                       solverConstraint.m_solverBodyIdB = solverBodyIdB;
+                       solverConstraint.m_multiBodyA = mbA;
+                       if (mbA)
+                               solverConstraint.m_linkA = fcA->m_link;
+
+                       solverConstraint.m_multiBodyB = mbB;
+                       if (mbB)
+                               solverConstraint.m_linkB = fcB->m_link;
+
+                       solverConstraint.m_originalContactPoint = &cp;
+
+                       bool isFriction = false;
+                       setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB, cp.m_appliedImpulse, cp, infoGlobal, relaxation, isFriction);
+
+                       //                      const btVector3& pos1 = cp.getPositionWorldOnA();
+                       //                      const btVector3& pos2 = cp.getPositionWorldOnB();
+
+                       /////setup the friction constraints
+#define ENABLE_FRICTION
+#ifdef ENABLE_FRICTION
+                       solverConstraint.m_frictionIndex = m_multiBodyFrictionContactConstraints.size();
+
+                       ///Bullet has several options to set the friction directions
+                       ///By default, each contact has only a single friction direction that is recomputed automatically every frame
+                       ///based on the relative linear velocity.
+                       ///If the relative velocity is zero, it will automatically compute a friction direction.
+
+                       ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
+                       ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
+                       ///
+                       ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
+                       ///
+                       ///The user can manually override the friction directions for certain contacts using a contact callback,
+                       ///and set the cp.m_lateralFrictionInitialized to true
+                       ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
+                       ///this will give a conveyor belt effect
+                       ///
+
+                       btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
+                       cp.m_lateralFrictionDir1.normalize();
+                       cp.m_lateralFrictionDir2.normalize();
+
+                       if (rollingFriction > 0)
+                       {
+                               if (cp.m_combinedSpinningFriction > 0)
+                               {
+                                       addMultiBodySpinningFrictionConstraint(cp.m_normalWorldOnB, manifold, frictionIndex, cp, cp.m_combinedSpinningFriction, colObj0, colObj1, relaxation, infoGlobal);
+                               }
+                               if (cp.m_combinedRollingFriction > 0)
+                               {
+                                       applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+                                       applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+                                       applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+                                       applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+
+                                       addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, cp.m_combinedRollingFriction, colObj0, colObj1, relaxation, infoGlobal);
+                                       addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, cp.m_combinedRollingFriction, colObj0, colObj1, relaxation, infoGlobal);
+                               }
+                               rollingFriction--;
+                       }
+                       if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
+                       { /*
+                               cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
+                               btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
+                               if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
+                               {
+                                       cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel);
+                                       if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+                                       {
+                                               cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
+                                               cp.m_lateralFrictionDir2.normalize();//??
+                                               applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                               applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                               addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+                                       }
+
+                                       applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+                               } else
+                               */
+                               {
+                                       applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                       addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, cp.m_appliedImpulseLateral1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
+
+                                       if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+                                       {
+                                               applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                               applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
+                                         addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, cp.m_appliedImpulseLateral2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
+                                       }
+
+                                       if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+                                       {
+                                               cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, cp.m_appliedImpulseLateral1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
+
+                               if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+                                       addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, cp.m_appliedImpulseLateral2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
+                               solverConstraint.m_appliedImpulse = 0.f;
+                               solverConstraint.m_appliedPushImpulse = 0.f;
+      }
+
+#endif  //ENABLE_FRICTION
+               }
+               else
+               {
+                       // Reset quantities related to warmstart as 0.
+                       cp.m_appliedImpulse = 0;
+                       cp.m_prevRHS = 0;
+               }
+       }
+}
+
+void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
+{
+       for (int i = 0; i < numManifolds; i++)
+       {
+               btPersistentManifold* manifold = manifoldPtr[i];
+               const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
+               const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
+               if (!fcA && !fcB)
+               {
+                       //the contact doesn't involve any Featherstone btMultiBody, so deal with the regular btRigidBody/btCollisionObject case
+                       convertContact(manifold, infoGlobal);
+               }
+               else
+               {
+                       convertMultiBodyContact(manifold, infoGlobal);
+               }
+       }
+
+       //also convert the multibody constraints, if any
+
+       for (int i = 0; i < m_tmpNumMultiBodyConstraints; i++)
+       {
+               btMultiBodyConstraint* c = m_tmpMultiBodyConstraints[i];
+               m_data.m_solverBodyPool = &m_tmpSolverBodyPool;
+               m_data.m_fixedBodyId = m_fixedBodyId;
+
+               c->createConstraintRows(m_multiBodyNonContactConstraints, m_data, infoGlobal);
+       }
+
+       // Warmstart for noncontact constraints
+       if (infoGlobal.m_solverMode & SOLVER_USE_ARTICULATED_WARMSTARTING)
+       {
+               for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
+               {
+                       btMultiBodySolverConstraint& solverConstraint =
+                               m_multiBodyNonContactConstraints[i];
+                       solverConstraint.m_appliedImpulse =
+                               solverConstraint.m_orgConstraint->getAppliedImpulse(solverConstraint.m_orgDofIndex) *
+                               infoGlobal.m_articulatedWarmstartingFactor;
+
+                       btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
+                       btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
+                       if (solverConstraint.m_appliedImpulse)
+                       {
+                               if (multiBodyA)
+                               {
+                                       int ndofA = multiBodyA->getNumDofs() + 6;
+                                       btScalar* deltaV =
+                                               &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
+                                       btScalar impulse = solverConstraint.m_appliedImpulse;
+                                       multiBodyA->applyDeltaVeeMultiDof2(deltaV, impulse);
+                                       applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
+                               }
+                               if (multiBodyB)
+                               {
+                                       int ndofB = multiBodyB->getNumDofs() + 6;
+                                       btScalar* deltaV =
+                                               &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
+                                       btScalar impulse = solverConstraint.m_appliedImpulse;
+                                       multiBodyB->applyDeltaVeeMultiDof2(deltaV, impulse);
+                                       applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
+                               }
+                       }
+               }
+       }
+       else
+       {
+               for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
+               {
+                       btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
+                       solverConstraint.m_appliedImpulse = 0;
+               }
+       }
+}
+
+btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
+{
+       //printf("btMultiBodyConstraintSolver::solveGroup: numBodies=%d, numConstraints=%d\n", numBodies, numConstraints);
+       return btSequentialImpulseConstraintSolver::solveGroup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
+}
+
+#if 0
+static void applyJointFeedback(btMultiBodyJacobianData& data, const btMultiBodySolverConstraint& solverConstraint, int jacIndex, btMultiBody* mb, btScalar appliedImpulse)
+{
+       if (appliedImpulse!=0 && mb->internalNeedsJointFeedback())
+       {
+               //todo: get rid of those temporary memory allocations for the joint feedback
+               btAlignedObjectArray<btScalar> forceVector;
+               int numDofsPlusBase = 6+mb->getNumDofs();
+               forceVector.resize(numDofsPlusBase);
+               for (int i=0;i<numDofsPlusBase;i++)
+               {
+                       forceVector[i] = data.m_jacobians[jacIndex+i]*appliedImpulse;
+               }
+               btAlignedObjectArray<btScalar> output;
+               output.resize(numDofsPlusBase);
+               bool applyJointFeedback = true;
+               mb->calcAccelerationDeltasMultiDof(&forceVector[0],&output[0],data.scratch_r,data.scratch_v,applyJointFeedback);
+       }
+}
+#endif
+
+void btMultiBodyConstraintSolver::writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint& c, btScalar deltaTime)
+{
+#if 1
+
+       //bod->addBaseForce(m_gravity * bod->getBaseMass());
+       //bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
+
+       if (c.m_orgConstraint)
+       {
+               c.m_orgConstraint->internalSetAppliedImpulse(c.m_orgDofIndex, c.m_appliedImpulse);
+       }
+
+       if (c.m_multiBodyA)
+       {
+               c.m_multiBodyA->setCompanionId(-1);
+               btVector3 force = c.m_contactNormal1 * (c.m_appliedImpulse / deltaTime);
+               btVector3 torque = c.m_relpos1CrossNormal * (c.m_appliedImpulse / deltaTime);
+               if (c.m_linkA < 0)
+               {
+                       c.m_multiBodyA->addBaseConstraintForce(force);
+                       c.m_multiBodyA->addBaseConstraintTorque(torque);
+               }
+               else
+               {
+                       c.m_multiBodyA->addLinkConstraintForce(c.m_linkA, force);
+                       //b3Printf("force = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
+                       c.m_multiBodyA->addLinkConstraintTorque(c.m_linkA, torque);
+               }
+       }
+
+       if (c.m_multiBodyB)
+       {
+               {
+                       c.m_multiBodyB->setCompanionId(-1);
+                       btVector3 force = c.m_contactNormal2 * (c.m_appliedImpulse / deltaTime);
+                       btVector3 torque = c.m_relpos2CrossNormal * (c.m_appliedImpulse / deltaTime);
+                       if (c.m_linkB < 0)
+                       {
+                               c.m_multiBodyB->addBaseConstraintForce(force);
+                               c.m_multiBodyB->addBaseConstraintTorque(torque);
+                       }
+                       else
+                       {
+                               {
+                                       c.m_multiBodyB->addLinkConstraintForce(c.m_linkB, force);
+                                       //b3Printf("t = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
+                                       c.m_multiBodyB->addLinkConstraintTorque(c.m_linkB, torque);
+                               }
+                       }
+               }
+       }
+#endif
+
+#ifndef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+
+       if (c.m_multiBodyA)
+       {
+               c.m_multiBodyA->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], c.m_appliedImpulse);
+       }
+
+       if (c.m_multiBodyB)
+       {
+               c.m_multiBodyB->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], c.m_appliedImpulse);
+       }
+#endif
+}
+
+btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish");
+       int numPoolConstraints = m_multiBodyNormalContactConstraints.size();
+
+       //write back the delta v to the multi bodies, either as applied impulse (direct velocity change)
+       //or as applied force, so we can measure the joint reaction forces easier
+       for (int i = 0; i < numPoolConstraints; i++)
+       {
+               btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[i];
+               writeBackSolverBodyToMultiBody(solverConstraint, infoGlobal.m_timeStep);
+
+               writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex], infoGlobal.m_timeStep);
+
+               if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+               {
+                       writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex + 1], infoGlobal.m_timeStep);
+               }
+       }
+
+       for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
+       {
+               btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
+               writeBackSolverBodyToMultiBody(solverConstraint, infoGlobal.m_timeStep);
+       }
+
+
+       {
+               BT_PROFILE("warm starting write back");
+               for (int j = 0; j < numPoolConstraints; j++)
+               {
+                       const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[j];
+                       btManifoldPoint* pt = (btManifoldPoint*)solverConstraint.m_originalContactPoint;
+                       btAssert(pt);
+                       pt->m_appliedImpulse = solverConstraint.m_appliedImpulse;
+                 pt->m_prevRHS = solverConstraint.m_rhs;
+                       pt->m_appliedImpulseLateral1 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse;
+
+                       //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
+                       if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+                       {
+                               pt->m_appliedImpulseLateral2 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex + 1].m_appliedImpulse;
+                       } else
+                       {
+                               pt->m_appliedImpulseLateral2 = 0;
+                       }
+               }
+       }
+
+#if 0
+       //multibody joint feedback
+       {
+               BT_PROFILE("multi body joint feedback");
+               for (int j=0;j<numPoolConstraints;j++)
+               {
+                       const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[j];
+               
+                       //apply the joint feedback into all links of the btMultiBody
+                       //todo: double-check the signs of the applied impulse
+
+                       if(solverConstraint.m_multiBodyA && solverConstraint.m_multiBodyA->isMultiDof())
+                       {
+                               applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacAindex,solverConstraint.m_multiBodyA, solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
+                       }
+                       if(solverConstraint.m_multiBodyB && solverConstraint.m_multiBodyB->isMultiDof())
+                       {
+                               applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacBindex,solverConstraint.m_multiBodyB,solverConstraint.m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
+                       }
+#if 0
+                       if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA->isMultiDof())
+                       {
+                               applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],
+                                       m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_jacAindex,
+                                       m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA,
+                                       m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
+
+                       }
+                       if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB->isMultiDof())
+                       {
+                               applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],
+                                       m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_jacBindex,
+                                       m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB,
+                                       m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
+                       }
+               
+                       if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+                       {
+                               if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA->isMultiDof())
+                               {
+                                       applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],
+                                               m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_jacAindex,
+                                               m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA,
+                                               m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
+                               }
+
+                               if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB->isMultiDof())
+                               {
+                                       applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],
+                                               m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_jacBindex,
+                                               m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB,
+                                               m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
+                               }
+                       }
+#endif
+               }
+       
+               for (int i=0;i<m_multiBodyNonContactConstraints.size();i++)
+               {
+                       const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
+                       if(solverConstraint.m_multiBodyA && solverConstraint.m_multiBodyA->isMultiDof())
+                       {
+                               applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacAindex,solverConstraint.m_multiBodyA, solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
+                       }
+                       if(solverConstraint.m_multiBodyB && solverConstraint.m_multiBodyB->isMultiDof())
+                       {
+                               applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacBindex,solverConstraint.m_multiBodyB,solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
+                       }
+               }
+       }
+
+       numPoolConstraints = m_multiBodyNonContactConstraints.size();
+
+#if 0
+       //@todo: m_originalContactPoint is not initialized for btMultiBodySolverConstraint
+       for (int i=0;i<numPoolConstraints;i++)
+       {
+               const btMultiBodySolverConstraint& c = m_multiBodyNonContactConstraints[i];
+
+               btTypedConstraint* constr = (btTypedConstraint*)c.m_originalContactPoint;
+               btJointFeedback* fb = constr->getJointFeedback();
+               if (fb)
+               {
+                       fb->m_appliedForceBodyA += c.m_contactNormal1*c.m_appliedImpulse*constr->getRigidBodyA().getLinearFactor()/infoGlobal.m_timeStep;
+                       fb->m_appliedForceBodyB += c.m_contactNormal2*c.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep;
+                       fb->m_appliedTorqueBodyA += c.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*c.m_appliedImpulse/infoGlobal.m_timeStep;
+                       fb->m_appliedTorqueBodyB += c.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*c.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */
+                       
+               }
+
+               constr->internalSetAppliedImpulse(c.m_appliedImpulse);
+               if (btFabs(c.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
+               {
+                       constr->setEnabled(false);
+               }
+
+       }
+#endif
+#endif
+
+       return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
+}
+
+void btMultiBodyConstraintSolver::solveMultiBodyGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
+{
+       //printf("solveMultiBodyGroup: numBodies=%d, numConstraints=%d, numManifolds=%d, numMultiBodyConstraints=%d\n", numBodies, numConstraints, numManifolds, numMultiBodyConstraints);
+
+       //printf("solveMultiBodyGroup start\n");
+       m_tmpMultiBodyConstraints = multiBodyConstraints;
+       m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
+
+       btSequentialImpulseConstraintSolver::solveGroup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
+
+       m_tmpMultiBodyConstraints = 0;
+       m_tmpNumMultiBodyConstraints = 0;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
new file mode 100644 (file)
index 0000000..f584360
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MULTIBODY_CONSTRAINT_SOLVER_H
+#define BT_MULTIBODY_CONSTRAINT_SOLVER_H
+
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "btMultiBodySolverConstraint.h"
+
+#define DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+
+class btMultiBody;
+
+#include "btMultiBodyConstraint.h"
+
+ATTRIBUTE_ALIGNED16(class)
+btMultiBodyConstraintSolver : public btSequentialImpulseConstraintSolver
+{
+protected:
+       btMultiBodyConstraintArray m_multiBodyNonContactConstraints;
+
+       btMultiBodyConstraintArray m_multiBodyNormalContactConstraints;
+       btMultiBodyConstraintArray m_multiBodyFrictionContactConstraints;
+       btMultiBodyConstraintArray m_multiBodyTorsionalFrictionContactConstraints;
+       btMultiBodyConstraintArray m_multiBodySpinningFrictionContactConstraints;
+
+       btMultiBodyJacobianData m_data;
+
+       //temp storage for multi body constraints for a specific island/group called by 'solveGroup'
+       btMultiBodyConstraint** m_tmpMultiBodyConstraints;
+       int m_tmpNumMultiBodyConstraints;
+
+       btScalar resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c);
+
+       //solve 2 friction directions and clamp against the implicit friction cone
+       btScalar resolveConeFrictionConstraintRows(const btMultiBodySolverConstraint& cA1, const btMultiBodySolverConstraint& cB);
+
+       void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
+
+       btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis, const btScalar& appliedImpulse, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
+
+       btMultiBodySolverConstraint& addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
+                                                                                                                                                btScalar combinedTorsionalFriction,
+                                                                                                                                                btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
+
+       btMultiBodySolverConstraint& addMultiBodySpinningFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
+               btScalar combinedTorsionalFriction,
+               btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
+
+       void setupMultiBodyJointLimitConstraint(btMultiBodySolverConstraint & constraintRow,
+                                                                                       btScalar * jacA, btScalar * jacB,
+                                                                                       btScalar penetration, btScalar combinedFrictionCoeff, btScalar combinedRestitutionCoeff,
+                                                                                       const btContactSolverInfo& infoGlobal);
+
+       void setupMultiBodyContactConstraint(btMultiBodySolverConstraint & solverConstraint,
+                                                                                const btVector3& contactNormal,
+                     const btScalar& appliedImpulse,
+                                                                                btManifoldPoint& cp,
+                     const btContactSolverInfo& infoGlobal,
+                                                                                btScalar& relaxation,
+                                                                                bool isFriction, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
+
+       //either rolling or spinning friction
+       void setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint & solverConstraint,
+                                                                                                  const btVector3& contactNormal,
+                                                                                                  btManifoldPoint& cp,
+                                                                                                  btScalar combinedTorsionalFriction,
+                                                                                                  const btContactSolverInfo& infoGlobal,
+                                                                                                  btScalar& relaxation,
+                                                                                                  bool isFriction, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
+
+       void convertMultiBodyContact(btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
+       virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+       //      virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
+       virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+       void applyDeltaVee(btScalar * deltaV, btScalar impulse, int velocityIndex, int ndof);
+       void writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint & constraint, btScalar deltaTime);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       ///this method should not be called, it was just used during porting/integration of Featherstone btMultiBody, providing backwards compatibility but no support for btMultiBodyConstraint (only contact constraints)
+       virtual btScalar solveGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
+       virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+
+       virtual void solveMultiBodyGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
+};
+
+#endif  //BT_MULTIBODY_CONSTRAINT_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
new file mode 100644 (file)
index 0000000..e7af332
--- /dev/null
@@ -0,0 +1,895 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btMultiBodyDynamicsWorld.h"
+#include "btMultiBodyConstraintSolver.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include "LinearMath/btQuickprof.h"
+#include "btMultiBodyConstraint.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btSerializer.h"
+
+void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, int group, int mask)
+{
+       m_multiBodies.push_back(body);
+}
+
+void btMultiBodyDynamicsWorld::removeMultiBody(btMultiBody* body)
+{
+       m_multiBodies.remove(body);
+}
+
+void btMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+    btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
+    predictMultiBodyTransforms(timeStep);
+    
+}
+void btMultiBodyDynamicsWorld::calculateSimulationIslands()
+{
+       BT_PROFILE("calculateSimulationIslands");
+
+       getSimulationIslandManager()->updateActivationState(getCollisionWorld(), getCollisionWorld()->getDispatcher());
+
+       {
+               //merge islands based on speculative contact manifolds too
+               for (int i = 0; i < this->m_predictiveManifolds.size(); i++)
+               {
+                       btPersistentManifold* manifold = m_predictiveManifolds[i];
+
+                       const btCollisionObject* colObj0 = manifold->getBody0();
+                       const btCollisionObject* colObj1 = manifold->getBody1();
+
+                       if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+                               ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+                       {
+                               getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
+                       }
+               }
+       }
+
+       {
+               int i;
+               int numConstraints = int(m_constraints.size());
+               for (i = 0; i < numConstraints; i++)
+               {
+                       btTypedConstraint* constraint = m_constraints[i];
+                       if (constraint->isEnabled())
+                       {
+                               const btRigidBody* colObj0 = &constraint->getRigidBodyA();
+                               const btRigidBody* colObj1 = &constraint->getRigidBodyB();
+
+                               if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+                                       ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+                               {
+                                       getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
+                               }
+                       }
+               }
+       }
+
+       //merge islands linked by Featherstone link colliders
+       for (int i = 0; i < m_multiBodies.size(); i++)
+       {
+               btMultiBody* body = m_multiBodies[i];
+               {
+                       btMultiBodyLinkCollider* prev = body->getBaseCollider();
+
+                       for (int b = 0; b < body->getNumLinks(); b++)
+                       {
+                               btMultiBodyLinkCollider* cur = body->getLink(b).m_collider;
+
+                               if (((cur) && (!(cur)->isStaticOrKinematicObject())) &&
+                                       ((prev) && (!(prev)->isStaticOrKinematicObject())))
+                               {
+                                       int tagPrev = prev->getIslandTag();
+                                       int tagCur = cur->getIslandTag();
+                                       getSimulationIslandManager()->getUnionFind().unite(tagPrev, tagCur);
+                               }
+                               if (cur && !cur->isStaticOrKinematicObject())
+                                       prev = cur;
+                       }
+               }
+       }
+
+       //merge islands linked by multibody constraints
+       {
+               for (int i = 0; i < this->m_multiBodyConstraints.size(); i++)
+               {
+                       btMultiBodyConstraint* c = m_multiBodyConstraints[i];
+                       int tagA = c->getIslandIdA();
+                       int tagB = c->getIslandIdB();
+                       if (tagA >= 0 && tagB >= 0)
+                               getSimulationIslandManager()->getUnionFind().unite(tagA, tagB);
+               }
+       }
+
+       //Store the island id in each body
+       getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
+}
+
+void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
+{
+       BT_PROFILE("btMultiBodyDynamicsWorld::updateActivationState");
+
+       for (int i = 0; i < m_multiBodies.size(); i++)
+       {
+               btMultiBody* body = m_multiBodies[i];
+               if (body)
+               {
+                       body->checkMotionAndSleepIfRequired(timeStep);
+                       if (!body->isAwake())
+                       {
+                               btMultiBodyLinkCollider* col = body->getBaseCollider();
+                               if (col && col->getActivationState() == ACTIVE_TAG)
+                               {
+                    if (body->hasFixedBase())
+                                       {
+                        col->setActivationState(FIXED_BASE_MULTI_BODY);
+                    } else
+                                       {
+                        col->setActivationState(WANTS_DEACTIVATION);
+                    }
+                                       
+                                       col->setDeactivationTime(0.f);
+                               }
+                               for (int b = 0; b < body->getNumLinks(); b++)
+                               {
+                                       btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
+                                       if (col && col->getActivationState() == ACTIVE_TAG)
+                                       {
+                                               col->setActivationState(WANTS_DEACTIVATION);
+                                               col->setDeactivationTime(0.f);
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               btMultiBodyLinkCollider* col = body->getBaseCollider();
+                               if (col && col->getActivationState() != DISABLE_DEACTIVATION)
+                                       col->setActivationState(ACTIVE_TAG);
+
+                               for (int b = 0; b < body->getNumLinks(); b++)
+                               {
+                                       btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
+                                       if (col && col->getActivationState() != DISABLE_DEACTIVATION)
+                                               col->setActivationState(ACTIVE_TAG);
+                               }
+                       }
+               }
+       }
+
+       btDiscreteDynamicsWorld::updateActivationState(timeStep);
+}
+
+void btMultiBodyDynamicsWorld::getAnalyticsData(btAlignedObjectArray<btSolverAnalyticsData>& islandAnalyticsData) const
+{
+       islandAnalyticsData = m_solverMultiBodyIslandCallback->m_islandAnalyticsData;
+}
+
+btMultiBodyDynamicsWorld::btMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+       : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
+         m_multiBodyConstraintSolver(constraintSolver)
+{
+       //split impulse is not yet supported for Featherstone hierarchies
+       //      getSolverInfo().m_splitImpulse = false;
+       getSolverInfo().m_solverMode |= SOLVER_USE_2_FRICTION_DIRECTIONS;
+       m_solverMultiBodyIslandCallback = new MultiBodyInplaceSolverIslandCallback(constraintSolver, dispatcher);
+}
+
+btMultiBodyDynamicsWorld::~btMultiBodyDynamicsWorld()
+{
+       delete m_solverMultiBodyIslandCallback;
+}
+
+void btMultiBodyDynamicsWorld::setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
+{
+       m_multiBodyConstraintSolver = solver;
+       m_solverMultiBodyIslandCallback->setMultiBodyConstraintSolver(solver);
+       btDiscreteDynamicsWorld::setConstraintSolver(solver);
+}
+
+void btMultiBodyDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+{
+       if (solver->getSolverType() == BT_MULTIBODY_SOLVER)
+       {
+               m_multiBodyConstraintSolver = (btMultiBodyConstraintSolver*)solver;
+       }
+       btDiscreteDynamicsWorld::setConstraintSolver(solver);
+}
+
+void btMultiBodyDynamicsWorld::forwardKinematics()
+{
+       for (int b = 0; b < m_multiBodies.size(); b++)
+       {
+               btMultiBody* bod = m_multiBodies[b];
+               bod->forwardKinematics(m_scratch_world_to_local, m_scratch_local_origin);
+       }
+}
+void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
+{
+    solveExternalForces(solverInfo);
+    buildIslands();
+    solveInternalConstraints(solverInfo);
+}
+
+void btMultiBodyDynamicsWorld::buildIslands()
+{
+    m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverMultiBodyIslandCallback);
+}
+
+void btMultiBodyDynamicsWorld::solveInternalConstraints(btContactSolverInfo& solverInfo)
+{
+       /// solve all the constraints for this island
+       m_solverMultiBodyIslandCallback->processConstraints();
+       m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
+    {
+        BT_PROFILE("btMultiBody stepVelocities");
+        for (int i = 0; i < this->m_multiBodies.size(); i++)
+        {
+            btMultiBody* bod = m_multiBodies[i];
+            
+            bool isSleeping = false;
+            
+            if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+            {
+                isSleeping = true;
+            }
+            for (int b = 0; b < bod->getNumLinks(); b++)
+            {
+                if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+                    isSleeping = true;
+            }
+            
+            if (!isSleeping)
+            {
+                //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+                m_scratch_r.resize(bod->getNumLinks() + 1);  //multidof? ("Y"s use it and it is used to store qdd)
+                m_scratch_v.resize(bod->getNumLinks() + 1);
+                m_scratch_m.resize(bod->getNumLinks() + 1);
+                
+                if (bod->internalNeedsJointFeedback())
+                {
+                    if (!bod->isUsingRK4Integration())
+                    {
+                        if (bod->internalNeedsJointFeedback())
+                        {
+                            bool isConstraintPass = true;
+                            bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
+                                                                                      getSolverInfo().m_jointFeedbackInWorldSpace,
+                                                                                      getSolverInfo().m_jointFeedbackInJointFrame);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    for (int i = 0; i < this->m_multiBodies.size(); i++)
+    {
+        btMultiBody* bod = m_multiBodies[i];
+        bod->processDeltaVeeMultiDof2();
+    }
+}
+
+void btMultiBodyDynamicsWorld::solveExternalForces(btContactSolverInfo& solverInfo)
+{
+    forwardKinematics();
+    
+    BT_PROFILE("solveConstraints");
+    
+    clearMultiBodyConstraintForces();
+    
+    m_sortedConstraints.resize(m_constraints.size());
+    int i;
+    for (i = 0; i < getNumConstraints(); i++)
+    {
+        m_sortedConstraints[i] = m_constraints[i];
+    }
+    m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
+    btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
+    
+    m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
+    for (i = 0; i < m_multiBodyConstraints.size(); i++)
+    {
+        m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
+    }
+    m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
+    
+    btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
+    
+    m_solverMultiBodyIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
+    m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+    
+#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+    {
+        BT_PROFILE("btMultiBody addForce");
+        for (int i = 0; i < this->m_multiBodies.size(); i++)
+        {
+            btMultiBody* bod = m_multiBodies[i];
+            
+            bool isSleeping = false;
+            
+            if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+            {
+                isSleeping = true;
+            }
+            for (int b = 0; b < bod->getNumLinks(); b++)
+            {
+                if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+                    isSleeping = true;
+            }
+            
+            if (!isSleeping)
+            {
+                //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+                m_scratch_r.resize(bod->getNumLinks() + 1);  //multidof? ("Y"s use it and it is used to store qdd)
+                m_scratch_v.resize(bod->getNumLinks() + 1);
+                m_scratch_m.resize(bod->getNumLinks() + 1);
+                
+                bod->addBaseForce(m_gravity * bod->getBaseMass());
+                
+                for (int j = 0; j < bod->getNumLinks(); ++j)
+                {
+                    bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
+                }
+            }  //if (!isSleeping)
+        }
+    }
+#endif  //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+    
+    {
+        BT_PROFILE("btMultiBody stepVelocities");
+        for (int i = 0; i < this->m_multiBodies.size(); i++)
+        {
+            btMultiBody* bod = m_multiBodies[i];
+            
+            bool isSleeping = false;
+            
+            if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+            {
+                isSleeping = true;
+            }
+            for (int b = 0; b < bod->getNumLinks(); b++)
+            {
+                if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+                    isSleeping = true;
+            }
+            
+            if (!isSleeping)
+            {
+                //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+                m_scratch_r.resize(bod->getNumLinks() + 1);  //multidof? ("Y"s use it and it is used to store qdd)
+                m_scratch_v.resize(bod->getNumLinks() + 1);
+                m_scratch_m.resize(bod->getNumLinks() + 1);
+                bool doNotUpdatePos = false;
+                bool isConstraintPass = false;
+                {
+                    if (!bod->isUsingRK4Integration())
+                    {
+                        bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep,
+                                                                                  m_scratch_r, m_scratch_v, m_scratch_m,isConstraintPass,
+                                                                                  getSolverInfo().m_jointFeedbackInWorldSpace,
+                                                                                  getSolverInfo().m_jointFeedbackInJointFrame);
+                    }
+                    else
+                    {
+                        //
+                        int numDofs = bod->getNumDofs() + 6;
+                        int numPosVars = bod->getNumPosVars() + 7;
+                        btAlignedObjectArray<btScalar> scratch_r2;
+                        scratch_r2.resize(2 * numPosVars + 8 * numDofs);
+                        //convenience
+                        btScalar* pMem = &scratch_r2[0];
+                        btScalar* scratch_q0 = pMem;
+                        pMem += numPosVars;
+                        btScalar* scratch_qx = pMem;
+                        pMem += numPosVars;
+                        btScalar* scratch_qd0 = pMem;
+                        pMem += numDofs;
+                        btScalar* scratch_qd1 = pMem;
+                        pMem += numDofs;
+                        btScalar* scratch_qd2 = pMem;
+                        pMem += numDofs;
+                        btScalar* scratch_qd3 = pMem;
+                        pMem += numDofs;
+                        btScalar* scratch_qdd0 = pMem;
+                        pMem += numDofs;
+                        btScalar* scratch_qdd1 = pMem;
+                        pMem += numDofs;
+                        btScalar* scratch_qdd2 = pMem;
+                        pMem += numDofs;
+                        btScalar* scratch_qdd3 = pMem;
+                        pMem += numDofs;
+                        btAssert((pMem - (2 * numPosVars + 8 * numDofs)) == &scratch_r2[0]);
+                        
+                        /////
+                        //copy q0 to scratch_q0 and qd0 to scratch_qd0
+                        scratch_q0[0] = bod->getWorldToBaseRot().x();
+                        scratch_q0[1] = bod->getWorldToBaseRot().y();
+                        scratch_q0[2] = bod->getWorldToBaseRot().z();
+                        scratch_q0[3] = bod->getWorldToBaseRot().w();
+                        scratch_q0[4] = bod->getBasePos().x();
+                        scratch_q0[5] = bod->getBasePos().y();
+                        scratch_q0[6] = bod->getBasePos().z();
+                        //
+                        for (int link = 0; link < bod->getNumLinks(); ++link)
+                        {
+                            for (int dof = 0; dof < bod->getLink(link).m_posVarCount; ++dof)
+                                scratch_q0[7 + bod->getLink(link).m_cfgOffset + dof] = bod->getLink(link).m_jointPos[dof];
+                        }
+                        //
+                        for (int dof = 0; dof < numDofs; ++dof)
+                            scratch_qd0[dof] = bod->getVelocityVector()[dof];
+                        ////
+                        struct
+                        {
+                            btMultiBody* bod;
+                            btScalar *scratch_qx, *scratch_q0;
+                            
+                            void operator()()
+                            {
+                                for (int dof = 0; dof < bod->getNumPosVars() + 7; ++dof)
+                                    scratch_qx[dof] = scratch_q0[dof];
+                            }
+                        } pResetQx = {bod, scratch_qx, scratch_q0};
+                        //
+                        struct
+                        {
+                            void operator()(btScalar dt, const btScalar* pDer, const btScalar* pCurVal, btScalar* pVal, int size)
+                            {
+                                for (int i = 0; i < size; ++i)
+                                    pVal[i] = pCurVal[i] + dt * pDer[i];
+                            }
+                            
+                        } pEulerIntegrate;
+                        //
+                        struct
+                        {
+                            void operator()(btMultiBody* pBody, const btScalar* pData)
+                            {
+                                btScalar* pVel = const_cast<btScalar*>(pBody->getVelocityVector());
+                                
+                                for (int i = 0; i < pBody->getNumDofs() + 6; ++i)
+                                    pVel[i] = pData[i];
+                            }
+                        } pCopyToVelocityVector;
+                        //
+                        struct
+                        {
+                            void operator()(const btScalar* pSrc, btScalar* pDst, int start, int size)
+                            {
+                                for (int i = 0; i < size; ++i)
+                                    pDst[i] = pSrc[start + i];
+                            }
+                        } pCopy;
+                        //
+                        
+                        btScalar h = solverInfo.m_timeStep;
+#define output &m_scratch_r[bod->getNumDofs()]
+                        //calc qdd0 from: q0 & qd0
+                        bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+                                                                                  isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+                                                                                  getSolverInfo().m_jointFeedbackInJointFrame);
+                        pCopy(output, scratch_qdd0, 0, numDofs);
+                        //calc q1 = q0 + h/2 * qd0
+                        pResetQx();
+                        bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd0);
+                        //calc qd1 = qd0 + h/2 * qdd0
+                        pEulerIntegrate(btScalar(.5) * h, scratch_qdd0, scratch_qd0, scratch_qd1, numDofs);
+                        //
+                        //calc qdd1 from: q1 & qd1
+                        pCopyToVelocityVector(bod, scratch_qd1);
+                        bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+                                                                                  isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+                                                                                  getSolverInfo().m_jointFeedbackInJointFrame);
+                        pCopy(output, scratch_qdd1, 0, numDofs);
+                        //calc q2 = q0 + h/2 * qd1
+                        pResetQx();
+                        bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd1);
+                        //calc qd2 = qd0 + h/2 * qdd1
+                        pEulerIntegrate(btScalar(.5) * h, scratch_qdd1, scratch_qd0, scratch_qd2, numDofs);
+                        //
+                        //calc qdd2 from: q2 & qd2
+                        pCopyToVelocityVector(bod, scratch_qd2);
+                        bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+                                                                                  isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+                                                                                  getSolverInfo().m_jointFeedbackInJointFrame);
+                        pCopy(output, scratch_qdd2, 0, numDofs);
+                        //calc q3 = q0 + h * qd2
+                        pResetQx();
+                        bod->stepPositionsMultiDof(h, scratch_qx, scratch_qd2);
+                        //calc qd3 = qd0 + h * qdd2
+                        pEulerIntegrate(h, scratch_qdd2, scratch_qd0, scratch_qd3, numDofs);
+                        //
+                        //calc qdd3 from: q3 & qd3
+                        pCopyToVelocityVector(bod, scratch_qd3);
+                        bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
+                                                                                  isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+                                                                                  getSolverInfo().m_jointFeedbackInJointFrame);
+                        pCopy(output, scratch_qdd3, 0, numDofs);
+                        
+                        //
+                        //calc q = q0 + h/6(qd0 + 2*(qd1 + qd2) + qd3)
+                        //calc qd = qd0 + h/6(qdd0 + 2*(qdd1 + qdd2) + qdd3)
+                        btAlignedObjectArray<btScalar> delta_q;
+                        delta_q.resize(numDofs);
+                        btAlignedObjectArray<btScalar> delta_qd;
+                        delta_qd.resize(numDofs);
+                        for (int i = 0; i < numDofs; ++i)
+                        {
+                            delta_q[i] = h / btScalar(6.) * (scratch_qd0[i] + 2 * scratch_qd1[i] + 2 * scratch_qd2[i] + scratch_qd3[i]);
+                            delta_qd[i] = h / btScalar(6.) * (scratch_qdd0[i] + 2 * scratch_qdd1[i] + 2 * scratch_qdd2[i] + scratch_qdd3[i]);
+                            //delta_q[i] = h*scratch_qd0[i];
+                            //delta_qd[i] = h*scratch_qdd0[i];
+                        }
+                        //
+                        pCopyToVelocityVector(bod, scratch_qd0);
+                        bod->applyDeltaVeeMultiDof(&delta_qd[0], 1);
+                        //
+                        if (!doNotUpdatePos)
+                        {
+                            btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
+                            pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
+                            
+                            for (int i = 0; i < numDofs; ++i)
+                                pRealBuf[i] = delta_q[i];
+                            
+                            //bod->stepPositionsMultiDof(1, 0, &delta_q[0]);
+                            bod->setPosUpdated(true);
+                        }
+                        
+                        //ugly hack which resets the cached data to t0 (needed for constraint solver)
+                        {
+                            for (int link = 0; link < bod->getNumLinks(); ++link)
+                                bod->getLink(link).updateCacheMultiDof();
+                            bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m,
+                                                                                      isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
+                                                                                      getSolverInfo().m_jointFeedbackInJointFrame);
+                        }
+                    }
+                }
+                
+#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+                bod->clearForcesAndTorques();
+#endif         //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+            }  //if (!isSleeping)
+        }
+    }
+}
+
+
+void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+       btDiscreteDynamicsWorld::integrateTransforms(timeStep);
+    integrateMultiBodyTransforms(timeStep);
+}
+
+void btMultiBodyDynamicsWorld::integrateMultiBodyTransforms(btScalar timeStep)
+{
+               BT_PROFILE("btMultiBody stepPositions");
+               //integrate and update the Featherstone hierarchies
+
+               for (int b = 0; b < m_multiBodies.size(); b++)
+               {
+                       btMultiBody* bod = m_multiBodies[b];
+                       bool isSleeping = false;
+                       if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+                       {
+                               isSleeping = true;
+                       }
+                       for (int b = 0; b < bod->getNumLinks(); b++)
+                       {
+                               if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+                                       isSleeping = true;
+                       }
+
+                       if (!isSleeping)
+                       {
+                               bod->addSplitV();
+                               int nLinks = bod->getNumLinks();
+
+                               ///base + num m_links
+                if (!bod->isPosUpdated())
+                    bod->stepPositionsMultiDof(timeStep);
+                else
+                {
+                    btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
+                    pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
+
+                    bod->stepPositionsMultiDof(1, 0, pRealBuf);
+                    bod->setPosUpdated(false);
+                }
+
+
+                               m_scratch_world_to_local.resize(nLinks + 1);
+                               m_scratch_local_origin.resize(nLinks + 1);
+                bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
+                               bod->substractSplitV();
+                       }
+                       else
+                       {
+                               bod->clearVelocities();
+                       }
+               }
+}
+
+void btMultiBodyDynamicsWorld::predictMultiBodyTransforms(btScalar timeStep)
+{
+    BT_PROFILE("btMultiBody stepPositions");
+    //integrate and update the Featherstone hierarchies
+    
+    for (int b = 0; b < m_multiBodies.size(); b++)
+    {
+        btMultiBody* bod = m_multiBodies[b];
+        bool isSleeping = false;
+        if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+        {
+            isSleeping = true;
+        }
+        for (int b = 0; b < bod->getNumLinks(); b++)
+        {
+            if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+                isSleeping = true;
+        }
+        
+        if (!isSleeping)
+        {
+            int nLinks = bod->getNumLinks();
+            bod->predictPositionsMultiDof(timeStep);
+            m_scratch_world_to_local.resize(nLinks + 1);
+            m_scratch_local_origin.resize(nLinks + 1);
+            bod->updateCollisionObjectInterpolationWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
+        }
+        else
+        {
+            bod->clearVelocities();
+        }
+    }
+}
+
+void btMultiBodyDynamicsWorld::addMultiBodyConstraint(btMultiBodyConstraint* constraint)
+{
+       m_multiBodyConstraints.push_back(constraint);
+}
+
+void btMultiBodyDynamicsWorld::removeMultiBodyConstraint(btMultiBodyConstraint* constraint)
+{
+       m_multiBodyConstraints.remove(constraint);
+}
+
+void btMultiBodyDynamicsWorld::debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint)
+{
+       constraint->debugDraw(getDebugDrawer());
+}
+
+void btMultiBodyDynamicsWorld::debugDrawWorld()
+{
+       BT_PROFILE("btMultiBodyDynamicsWorld debugDrawWorld");
+
+       btDiscreteDynamicsWorld::debugDrawWorld();
+
+       bool drawConstraints = false;
+       if (getDebugDrawer())
+       {
+               int mode = getDebugDrawer()->getDebugMode();
+               if (mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
+               {
+                       drawConstraints = true;
+               }
+
+               if (drawConstraints)
+               {
+                       BT_PROFILE("btMultiBody debugDrawWorld");
+
+                       for (int c = 0; c < m_multiBodyConstraints.size(); c++)
+                       {
+                               btMultiBodyConstraint* constraint = m_multiBodyConstraints[c];
+                               debugDrawMultiBodyConstraint(constraint);
+                       }
+
+                       for (int b = 0; b < m_multiBodies.size(); b++)
+                       {
+                               btMultiBody* bod = m_multiBodies[b];
+                               bod->forwardKinematics(m_scratch_world_to_local1, m_scratch_local_origin1);
+
+                               if (mode & btIDebugDraw::DBG_DrawFrames)
+                               {
+                                       getDebugDrawer()->drawTransform(bod->getBaseWorldTransform(), 0.1);
+                               }
+
+                               for (int m = 0; m < bod->getNumLinks(); m++)
+                               {
+                                       const btTransform& tr = bod->getLink(m).m_cachedWorldTransform;
+                                       if (mode & btIDebugDraw::DBG_DrawFrames)
+                                       {
+                                               getDebugDrawer()->drawTransform(tr, 0.1);
+                                       }
+                                       //draw the joint axis
+                                       if (bod->getLink(m).m_jointType == btMultibodyLink::eRevolute)
+                                       {
+                                               btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_topVec) * 0.1;
+
+                                               btVector4 color(0, 0, 0, 1);  //1,1,1);
+                                               btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+                                               btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+                                               getDebugDrawer()->drawLine(from, to, color);
+                                       }
+                                       if (bod->getLink(m).m_jointType == btMultibodyLink::eFixed)
+                                       {
+                                               btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_bottomVec) * 0.1;
+
+                                               btVector4 color(0, 0, 0, 1);  //1,1,1);
+                                               btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+                                               btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+                                               getDebugDrawer()->drawLine(from, to, color);
+                                       }
+                                       if (bod->getLink(m).m_jointType == btMultibodyLink::ePrismatic)
+                                       {
+                                               btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_bottomVec) * 0.1;
+
+                                               btVector4 color(0, 0, 0, 1);  //1,1,1);
+                                               btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+                                               btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
+                                               getDebugDrawer()->drawLine(from, to, color);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void btMultiBodyDynamicsWorld::applyGravity()
+{
+       btDiscreteDynamicsWorld::applyGravity();
+#ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+       BT_PROFILE("btMultiBody addGravity");
+       for (int i = 0; i < this->m_multiBodies.size(); i++)
+       {
+               btMultiBody* bod = m_multiBodies[i];
+
+               bool isSleeping = false;
+
+               if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+               {
+                       isSleeping = true;
+               }
+               for (int b = 0; b < bod->getNumLinks(); b++)
+               {
+                       if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+                               isSleeping = true;
+               }
+
+               if (!isSleeping)
+               {
+                       bod->addBaseForce(m_gravity * bod->getBaseMass());
+
+                       for (int j = 0; j < bod->getNumLinks(); ++j)
+                       {
+                               bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
+                       }
+               }  //if (!isSleeping)
+       }
+#endif  //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+}
+
+void btMultiBodyDynamicsWorld::clearMultiBodyConstraintForces()
+{
+       for (int i = 0; i < this->m_multiBodies.size(); i++)
+       {
+               btMultiBody* bod = m_multiBodies[i];
+               bod->clearConstraintForces();
+       }
+}
+void btMultiBodyDynamicsWorld::clearMultiBodyForces()
+{
+       {
+               // BT_PROFILE("clearMultiBodyForces");
+               for (int i = 0; i < this->m_multiBodies.size(); i++)
+               {
+                       btMultiBody* bod = m_multiBodies[i];
+
+                       bool isSleeping = false;
+
+                       if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+                       {
+                               isSleeping = true;
+                       }
+                       for (int b = 0; b < bod->getNumLinks(); b++)
+                       {
+                               if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+                                       isSleeping = true;
+                       }
+
+                       if (!isSleeping)
+                       {
+                               btMultiBody* bod = m_multiBodies[i];
+                               bod->clearForcesAndTorques();
+                       }
+               }
+       }
+}
+void btMultiBodyDynamicsWorld::clearForces()
+{
+       btDiscreteDynamicsWorld::clearForces();
+
+#ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+       clearMultiBodyForces();
+#endif
+}
+
+void btMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
+{
+       serializer->startSerialization();
+
+       serializeDynamicsWorldInfo(serializer);
+
+       serializeMultiBodies(serializer);
+
+       serializeRigidBodies(serializer);
+
+       serializeCollisionObjects(serializer);
+
+       serializeContactManifolds(serializer);
+
+       serializer->finishSerialization();
+}
+
+void btMultiBodyDynamicsWorld::serializeMultiBodies(btSerializer* serializer)
+{
+       int i;
+       //serialize all collision objects
+       for (i = 0; i < m_multiBodies.size(); i++)
+       {
+               btMultiBody* mb = m_multiBodies[i];
+               {
+                       int len = mb->calculateSerializeBufferSize();
+                       btChunk* chunk = serializer->allocate(len, 1);
+                       const char* structType = mb->serialize(chunk->m_oldPtr, serializer);
+                       serializer->finalizeChunk(chunk, structType, BT_MULTIBODY_CODE, mb);
+               }
+       }
+
+       //serialize all multibody links (collision objects)
+       for (i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               if (colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+               {
+                       int len = colObj->calculateSerializeBufferSize();
+                       btChunk* chunk = serializer->allocate(len, 1);
+                       const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
+                       serializer->finalizeChunk(chunk, structType, BT_MB_LINKCOLLIDER_CODE, colObj);
+               }
+       }
+}
+
+void btMultiBodyDynamicsWorld::saveKinematicState(btScalar timeStep)
+{
+       btDiscreteDynamicsWorld::saveKinematicState(timeStep);
+       for(int i = 0; i < m_multiBodies.size(); i++)
+       {
+               btMultiBody* body = m_multiBodies[i];
+               if(body->isBaseKinematic())
+                       body->saveKinematicState(timeStep);
+       }
+}
+
+//
+//void btMultiBodyDynamicsWorld::setSplitIslands(bool split)
+//{
+//    m_islandManager->setSplitIslands(split);
+//}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
new file mode 100644 (file)
index 0000000..d2d76c8
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MULTIBODY_DYNAMICS_WORLD_H
+#define BT_MULTIBODY_DYNAMICS_WORLD_H
+
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+#include "BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h"
+
+#define BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
+
+class btMultiBody;
+class btMultiBodyConstraint;
+class btMultiBodyConstraintSolver;
+struct MultiBodyInplaceSolverIslandCallback;
+
+///The btMultiBodyDynamicsWorld adds Featherstone multi body dynamics to Bullet
+///This implementation is still preliminary/experimental.
+class btMultiBodyDynamicsWorld : public btDiscreteDynamicsWorld
+{
+protected:
+       btAlignedObjectArray<btMultiBody*> m_multiBodies;
+       btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
+       btAlignedObjectArray<btMultiBodyConstraint*> m_sortedMultiBodyConstraints;
+       btMultiBodyConstraintSolver* m_multiBodyConstraintSolver;
+       MultiBodyInplaceSolverIslandCallback* m_solverMultiBodyIslandCallback;
+
+       //cached data to avoid memory allocations
+       btAlignedObjectArray<btQuaternion> m_scratch_world_to_local;
+       btAlignedObjectArray<btVector3> m_scratch_local_origin;
+       btAlignedObjectArray<btQuaternion> m_scratch_world_to_local1;
+       btAlignedObjectArray<btVector3> m_scratch_local_origin1;
+       btAlignedObjectArray<btScalar> m_scratch_r;
+       btAlignedObjectArray<btVector3> m_scratch_v;
+       btAlignedObjectArray<btMatrix3x3> m_scratch_m;
+
+       virtual void calculateSimulationIslands();
+       virtual void updateActivationState(btScalar timeStep);
+       
+
+       virtual void serializeMultiBodies(btSerializer* serializer);
+
+public:
+       btMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration);
+
+       virtual ~btMultiBodyDynamicsWorld();
+    
+    virtual void solveConstraints(btContactSolverInfo& solverInfo);
+    
+       virtual void addMultiBody(btMultiBody* body, int group = btBroadphaseProxy::DefaultFilter, int mask = btBroadphaseProxy::AllFilter);
+
+       virtual void removeMultiBody(btMultiBody* body);
+
+       virtual int getNumMultibodies() const
+       {
+               return m_multiBodies.size();
+       }
+
+       btMultiBody* getMultiBody(int mbIndex)
+       {
+               return m_multiBodies[mbIndex];
+       }
+
+       const btMultiBody* getMultiBody(int mbIndex) const
+       {
+               return m_multiBodies[mbIndex];
+       }
+
+       virtual void addMultiBodyConstraint(btMultiBodyConstraint* constraint);
+
+       virtual int getNumMultiBodyConstraints() const
+       {
+               return m_multiBodyConstraints.size();
+       }
+
+       virtual btMultiBodyConstraint* getMultiBodyConstraint(int constraintIndex)
+       {
+               return m_multiBodyConstraints[constraintIndex];
+       }
+
+       virtual const btMultiBodyConstraint* getMultiBodyConstraint(int constraintIndex) const
+       {
+               return m_multiBodyConstraints[constraintIndex];
+       }
+
+       virtual void removeMultiBodyConstraint(btMultiBodyConstraint* constraint);
+
+       virtual void integrateTransforms(btScalar timeStep);
+    void integrateMultiBodyTransforms(btScalar timeStep);
+    void predictMultiBodyTransforms(btScalar timeStep);
+    
+    virtual void predictUnconstraintMotion(btScalar timeStep);
+       virtual void debugDrawWorld();
+
+       virtual void debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint);
+
+       void forwardKinematics();
+       virtual void clearForces();
+       virtual void clearMultiBodyConstraintForces();
+       virtual void clearMultiBodyForces();
+       virtual void applyGravity();
+
+       virtual void serialize(btSerializer* serializer);
+       virtual void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver);
+       virtual void setConstraintSolver(btConstraintSolver* solver);
+       virtual void getAnalyticsData(btAlignedObjectArray<struct btSolverAnalyticsData>& m_islandAnalyticsData) const;
+    
+    virtual void solveExternalForces(btContactSolverInfo& solverInfo);
+    virtual void solveInternalConstraints(btContactSolverInfo& solverInfo);
+    void buildIslands();
+
+       virtual void saveKinematicState(btScalar timeStep);
+};
+#endif  //BT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp
new file mode 100644 (file)
index 0000000..df2abbe
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#include "btMultiBodyFixedConstraint.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+#include "LinearMath/btIDebugDraw.h"
+
+#define BTMBFIXEDCONSTRAINT_DIM 6
+
+btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
+       : btMultiBodyConstraint(body, 0, link, -1, BTMBFIXEDCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_FIXED),
+         m_rigidBodyA(0),
+         m_rigidBodyB(bodyB),
+         m_pivotInA(pivotInA),
+         m_pivotInB(pivotInB),
+         m_frameInA(frameInA),
+         m_frameInB(frameInB)
+{
+       m_data.resize(BTMBFIXEDCONSTRAINT_DIM);  //at least store the applied impulses
+}
+
+btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
+       : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, BTMBFIXEDCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_FIXED),
+         m_rigidBodyA(0),
+         m_rigidBodyB(0),
+         m_pivotInA(pivotInA),
+         m_pivotInB(pivotInB),
+         m_frameInA(frameInA),
+         m_frameInB(frameInB)
+{
+       m_data.resize(BTMBFIXEDCONSTRAINT_DIM);  //at least store the applied impulses
+}
+
+void btMultiBodyFixedConstraint::finalizeMultiDof()
+{
+       //not implemented yet
+       btAssert(0);
+}
+
+btMultiBodyFixedConstraint::~btMultiBodyFixedConstraint()
+{
+}
+
+int btMultiBodyFixedConstraint::getIslandIdA() const
+{
+       if (m_rigidBodyA)
+               return m_rigidBodyA->getIslandTag();
+
+       if (m_bodyA)
+       {
+               if (m_linkA < 0)
+               {
+                       btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+                       if (col)
+                               return col->getIslandTag();
+               }
+               else
+               {
+                       if (m_bodyA->getLink(m_linkA).m_collider)
+                               return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+int btMultiBodyFixedConstraint::getIslandIdB() const
+{
+       if (m_rigidBodyB)
+               return m_rigidBodyB->getIslandTag();
+       if (m_bodyB)
+       {
+               if (m_linkB < 0)
+               {
+                       btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+                       if (col)
+                               return col->getIslandTag();
+               }
+               else
+               {
+                       if (m_bodyB->getLink(m_linkB).m_collider)
+                               return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+void btMultiBodyFixedConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal)
+{
+       int numDim = BTMBFIXEDCONSTRAINT_DIM;
+       for (int i = 0; i < numDim; i++)
+       {
+               btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+               constraintRow.m_orgConstraint = this;
+               constraintRow.m_orgDofIndex = i;
+               constraintRow.m_relpos1CrossNormal.setValue(0, 0, 0);
+               constraintRow.m_contactNormal1.setValue(0, 0, 0);
+               constraintRow.m_relpos2CrossNormal.setValue(0, 0, 0);
+               constraintRow.m_contactNormal2.setValue(0, 0, 0);
+               constraintRow.m_angularComponentA.setValue(0, 0, 0);
+               constraintRow.m_angularComponentB.setValue(0, 0, 0);
+
+               constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
+               constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
+
+               // Convert local points back to world
+               btVector3 pivotAworld = m_pivotInA;
+               btMatrix3x3 frameAworld = m_frameInA;
+               if (m_rigidBodyA)
+               {
+                       constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
+                       pivotAworld = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+                       frameAworld = frameAworld.transpose() * btMatrix3x3(m_rigidBodyA->getOrientation());
+               }
+               else
+               {
+                       if (m_bodyA)
+                       {
+                               pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+                               frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
+                       }
+               }
+               btVector3 pivotBworld = m_pivotInB;
+               btMatrix3x3 frameBworld = m_frameInB;
+               if (m_rigidBodyB)
+               {
+                       constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
+                       pivotBworld = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+                       frameBworld = frameBworld.transpose() * btMatrix3x3(m_rigidBodyB->getOrientation());
+               }
+               else
+               {
+                       if (m_bodyB)
+                       {
+                               pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+                               frameBworld = m_bodyB->localFrameToWorld(m_linkB, frameBworld);
+                       }
+               }
+
+               btMatrix3x3 relRot = frameAworld.inverse() * frameBworld;
+               btVector3 angleDiff;
+               btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot, angleDiff);
+
+               btVector3 constraintNormalLin(0, 0, 0);
+               btVector3 constraintNormalAng(0, 0, 0);
+               btScalar posError = 0.0;
+               if (i < 3)
+               {
+                       constraintNormalLin[i] = 1;
+                       posError = (pivotAworld - pivotBworld).dot(constraintNormalLin);
+                       fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+                                                                       constraintNormalLin, pivotAworld, pivotBworld,
+                                                                       posError,
+                                                                       infoGlobal,
+                                                                       -m_maxAppliedImpulse, m_maxAppliedImpulse);
+               }
+               else
+               {  //i>=3
+                       constraintNormalAng = frameAworld.getColumn(i % 3);
+                       posError = angleDiff[i % 3];
+                       fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+                                                                       constraintNormalLin, pivotAworld, pivotBworld,
+                                                                       posError,
+                                                                       infoGlobal,
+                                                                       -m_maxAppliedImpulse, m_maxAppliedImpulse, true);
+               }
+       }
+}
+
+void btMultiBodyFixedConstraint::debugDraw(class btIDebugDraw* drawer)
+{
+       btTransform tr;
+       tr.setIdentity();
+
+       if (m_rigidBodyA)
+       {
+               btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+               tr.setOrigin(pivot);
+               drawer->drawTransform(tr, 0.1);
+       }
+       if (m_bodyA)
+       {
+               btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+               tr.setOrigin(pivotAworld);
+               drawer->drawTransform(tr, 0.1);
+       }
+       if (m_rigidBodyB)
+       {
+               // that ideally should draw the same frame
+               btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+               tr.setOrigin(pivot);
+               drawer->drawTransform(tr, 0.1);
+       }
+       if (m_bodyB)
+       {
+               btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+               tr.setOrigin(pivotBworld);
+               drawer->drawTransform(tr, 0.1);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h
new file mode 100644 (file)
index 0000000..adb1cb4
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_FIXED_CONSTRAINT_H
+#define BT_MULTIBODY_FIXED_CONSTRAINT_H
+
+#include "btMultiBodyConstraint.h"
+
+class btMultiBodyFixedConstraint : public btMultiBodyConstraint
+{
+protected:
+       btRigidBody* m_rigidBodyA;
+       btRigidBody* m_rigidBodyB;
+       btVector3 m_pivotInA;
+       btVector3 m_pivotInB;
+       btMatrix3x3 m_frameInA;
+       btMatrix3x3 m_frameInB;
+
+public:
+       btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
+       btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
+
+       virtual ~btMultiBodyFixedConstraint();
+
+       virtual void finalizeMultiDof();
+
+       virtual int getIslandIdA() const;
+       virtual int getIslandIdB() const;
+
+       virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                         btMultiBodyJacobianData& data,
+                                                                         const btContactSolverInfo& infoGlobal);
+
+       const btVector3& getPivotInA() const
+       {
+               return m_pivotInA;
+       }
+
+       void setPivotInA(const btVector3& pivotInA)
+       {
+               m_pivotInA = pivotInA;
+       }
+
+       const btVector3& getPivotInB() const
+       {
+               return m_pivotInB;
+       }
+
+       virtual void setPivotInB(const btVector3& pivotInB)
+       {
+               m_pivotInB = pivotInB;
+       }
+
+       const btMatrix3x3& getFrameInA() const
+       {
+               return m_frameInA;
+       }
+
+       void setFrameInA(const btMatrix3x3& frameInA)
+       {
+               m_frameInA = frameInA;
+       }
+
+       const btMatrix3x3& getFrameInB() const
+       {
+               return m_frameInB;
+       }
+
+       virtual void setFrameInB(const btMatrix3x3& frameInB)
+       {
+               m_frameInB = frameInB;
+       }
+
+       virtual void debugDraw(class btIDebugDraw* drawer);
+};
+
+#endif  //BT_MULTIBODY_FIXED_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp
new file mode 100644 (file)
index 0000000..ee02cf9
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#include "btMultiBodyGearConstraint.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+btMultiBodyGearConstraint::btMultiBodyGearConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
+       : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, 1, false, MULTIBODY_CONSTRAINT_GEAR),
+         m_gearRatio(1),
+         m_gearAuxLink(-1),
+         m_erp(0),
+         m_relativePositionTarget(0)
+{
+}
+
+void btMultiBodyGearConstraint::finalizeMultiDof()
+{
+       allocateJacobiansMultiDof();
+
+       m_numDofsFinalized = m_jacSizeBoth;
+}
+
+btMultiBodyGearConstraint::~btMultiBodyGearConstraint()
+{
+}
+
+int btMultiBodyGearConstraint::getIslandIdA() const
+{
+       if (m_bodyA)
+       {
+               if (m_linkA < 0)
+               {
+                       btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+                       if (col)
+                               return col->getIslandTag();
+               }
+               else
+               {
+                       if (m_bodyA->getLink(m_linkA).m_collider)
+                               return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+int btMultiBodyGearConstraint::getIslandIdB() const
+{
+       if (m_bodyB)
+       {
+               if (m_linkB < 0)
+               {
+                       btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+                       if (col)
+                               return col->getIslandTag();
+               }
+               else
+               {
+                       if (m_bodyB->getLink(m_linkB).m_collider)
+                               return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+void btMultiBodyGearConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                                                        btMultiBodyJacobianData& data,
+                                                                                                        const btContactSolverInfo& infoGlobal)
+{
+       // only positions need to be updated -- data.m_jacobians and force
+       // directions were set in the ctor and never change.
+
+       if (m_numDofsFinalized != m_jacSizeBoth)
+       {
+               finalizeMultiDof();
+       }
+
+       //don't crash
+       if (m_numDofsFinalized != m_jacSizeBoth)
+               return;
+
+       if (m_maxAppliedImpulse == 0.f)
+               return;
+
+       // note: we rely on the fact that data.m_jacobians are
+       // always initialized to zero by the Constraint ctor
+       int linkDoF = 0;
+       unsigned int offsetA = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
+       unsigned int offsetB = 6 + (m_bodyB->getLink(m_linkB).m_dofOffset + linkDoF);
+
+       // row 0: the lower bound
+       jacobianA(0)[offsetA] = 1;
+       jacobianB(0)[offsetB] = m_gearRatio;
+
+       btScalar posError = 0;
+       const btVector3 dummy(0, 0, 0);
+
+       btScalar kp = 1;
+       btScalar kd = 1;
+       int numRows = getNumRows();
+
+       for (int row = 0; row < numRows; row++)
+       {
+               btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+
+               int dof = 0;
+               btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
+               btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
+               btScalar auxVel = 0;
+
+               if (m_gearAuxLink >= 0)
+               {
+                       auxVel = m_bodyA->getJointVelMultiDof(m_gearAuxLink)[dof];
+               }
+               currentVelocity += auxVel;
+               if (m_erp != 0)
+               {
+                       btScalar currentPositionA = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
+                       if (m_gearAuxLink >= 0)
+                       {
+                               currentPositionA -= m_bodyA->getJointPosMultiDof(m_gearAuxLink)[dof];
+                       }
+                       btScalar currentPositionB = m_gearRatio * m_bodyA->getJointPosMultiDof(m_linkB)[dof];
+                       btScalar diff = currentPositionB + currentPositionA;
+                       btScalar desiredPositionDiff = this->m_relativePositionTarget;
+                       posError = -m_erp * (desiredPositionDiff - diff);
+               }
+
+               btScalar desiredRelativeVelocity = auxVel;
+
+               fillMultiBodyConstraint(constraintRow, data, jacobianA(row), jacobianB(row), dummy, dummy, dummy, dummy, posError, infoGlobal, -m_maxAppliedImpulse, m_maxAppliedImpulse, false, 1, false, desiredRelativeVelocity);
+
+               constraintRow.m_orgConstraint = this;
+               constraintRow.m_orgDofIndex = row;
+               {
+                       //expect either prismatic or revolute joint type for now
+                       btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute) || (m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
+                       switch (m_bodyA->getLink(m_linkA).m_jointType)
+                       {
+                               case btMultibodyLink::eRevolute:
+                               {
+                                       constraintRow.m_contactNormal1.setZero();
+                                       constraintRow.m_contactNormal2.setZero();
+                                       btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
+                                       constraintRow.m_relpos1CrossNormal = revoluteAxisInWorld;
+                                       constraintRow.m_relpos2CrossNormal = -revoluteAxisInWorld;
+
+                                       break;
+                               }
+                               case btMultibodyLink::ePrismatic:
+                               {
+                                       btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
+                                       constraintRow.m_contactNormal1 = prismaticAxisInWorld;
+                                       constraintRow.m_contactNormal2 = -prismaticAxisInWorld;
+                                       constraintRow.m_relpos1CrossNormal.setZero();
+                                       constraintRow.m_relpos2CrossNormal.setZero();
+                                       break;
+                               }
+                               default:
+                               {
+                                       btAssert(0);
+                               }
+                       };
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h
new file mode 100644 (file)
index 0000000..31888fb
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_GEAR_CONSTRAINT_H
+#define BT_MULTIBODY_GEAR_CONSTRAINT_H
+
+#include "btMultiBodyConstraint.h"
+
+class btMultiBodyGearConstraint : public btMultiBodyConstraint
+{
+protected:
+       btRigidBody* m_rigidBodyA;
+       btRigidBody* m_rigidBodyB;
+       btVector3 m_pivotInA;
+       btVector3 m_pivotInB;
+       btMatrix3x3 m_frameInA;
+       btMatrix3x3 m_frameInB;
+       btScalar m_gearRatio;
+       int m_gearAuxLink;
+       btScalar m_erp;
+       btScalar m_relativePositionTarget;
+
+public:
+       //btMultiBodyGearConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
+       btMultiBodyGearConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
+
+       virtual ~btMultiBodyGearConstraint();
+
+       virtual void finalizeMultiDof();
+
+       virtual int getIslandIdA() const;
+       virtual int getIslandIdB() const;
+
+       virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                         btMultiBodyJacobianData& data,
+                                                                         const btContactSolverInfo& infoGlobal);
+
+       const btVector3& getPivotInA() const
+       {
+               return m_pivotInA;
+       }
+
+       void setPivotInA(const btVector3& pivotInA)
+       {
+               m_pivotInA = pivotInA;
+       }
+
+       const btVector3& getPivotInB() const
+       {
+               return m_pivotInB;
+       }
+
+       virtual void setPivotInB(const btVector3& pivotInB)
+       {
+               m_pivotInB = pivotInB;
+       }
+
+       const btMatrix3x3& getFrameInA() const
+       {
+               return m_frameInA;
+       }
+
+       void setFrameInA(const btMatrix3x3& frameInA)
+       {
+               m_frameInA = frameInA;
+       }
+
+       const btMatrix3x3& getFrameInB() const
+       {
+               return m_frameInB;
+       }
+
+       virtual void setFrameInB(const btMatrix3x3& frameInB)
+       {
+               m_frameInB = frameInB;
+       }
+
+       virtual void debugDraw(class btIDebugDraw* drawer)
+       {
+               //todo(erwincoumans)
+       }
+
+       virtual void setGearRatio(btScalar gearRatio)
+       {
+               m_gearRatio = gearRatio;
+       }
+       virtual void setGearAuxLink(int gearAuxLink)
+       {
+               m_gearAuxLink = gearAuxLink;
+       }
+       virtual void setRelativePositionTarget(btScalar relPosTarget)
+       {
+               m_relativePositionTarget = relPosTarget;
+       }
+       virtual void setErp(btScalar erp)
+       {
+               m_erp = erp;
+       }
+};
+
+#endif  //BT_MULTIBODY_GEAR_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h
new file mode 100644 (file)
index 0000000..3169b86
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H
+#define BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H
+
+#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
+#include "btMultiBodyConstraintSolver.h"
+
+SIMD_FORCE_INLINE int btGetConstraintIslandId2(const btTypedConstraint* lhs)
+{
+    int islandId;
+    
+    const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
+    const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
+    islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
+    return islandId;
+}
+class btSortConstraintOnIslandPredicate2
+{
+public:
+    bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
+    {
+        int rIslandId0, lIslandId0;
+        rIslandId0 = btGetConstraintIslandId2(rhs);
+        lIslandId0 = btGetConstraintIslandId2(lhs);
+        return lIslandId0 < rIslandId0;
+    }
+};
+
+SIMD_FORCE_INLINE int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint* lhs)
+{
+    int islandId;
+    
+    int islandTagA = lhs->getIslandIdA();
+    int islandTagB = lhs->getIslandIdB();
+    islandId = islandTagA >= 0 ? islandTagA : islandTagB;
+    return islandId;
+}
+
+class btSortMultiBodyConstraintOnIslandPredicate
+{
+public:
+    bool operator()(const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs) const
+    {
+        int rIslandId0, lIslandId0;
+        rIslandId0 = btGetMultiBodyConstraintIslandId(rhs);
+        lIslandId0 = btGetMultiBodyConstraintIslandId(lhs);
+        return lIslandId0 < rIslandId0;
+    }
+};
+
+struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
+{
+
+    btContactSolverInfo* m_solverInfo;
+    btMultiBodyConstraintSolver* m_solver;
+    btMultiBodyConstraint** m_multiBodySortedConstraints;
+    int m_numMultiBodyConstraints;
+    
+    btTypedConstraint** m_sortedConstraints;
+    int m_numConstraints;
+    btIDebugDraw* m_debugDrawer;
+    btDispatcher* m_dispatcher;
+    
+    btAlignedObjectArray<btCollisionObject*> m_bodies;
+       btAlignedObjectArray<btCollisionObject*> m_softBodies;
+    btAlignedObjectArray<btPersistentManifold*> m_manifolds;
+    btAlignedObjectArray<btTypedConstraint*> m_constraints;
+    btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
+    
+    btAlignedObjectArray<btSolverAnalyticsData> m_islandAnalyticsData;
+    
+    MultiBodyInplaceSolverIslandCallback(btMultiBodyConstraintSolver* solver,
+                                         btDispatcher* dispatcher)
+    : m_solverInfo(NULL),
+    m_solver(solver),
+    m_multiBodySortedConstraints(NULL),
+    m_numConstraints(0),
+    m_debugDrawer(NULL),
+    m_dispatcher(dispatcher)
+    {
+    }
+    
+    MultiBodyInplaceSolverIslandCallback& operator=(const MultiBodyInplaceSolverIslandCallback& other)
+    {
+        btAssert(0);
+        (void)other;
+        return *this;
+    }
+    
+    SIMD_FORCE_INLINE virtual void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
+    {
+        m_islandAnalyticsData.clear();
+        btAssert(solverInfo);
+        m_solverInfo = solverInfo;
+        
+        m_multiBodySortedConstraints = sortedMultiBodyConstraints;
+        m_numMultiBodyConstraints = numMultiBodyConstraints;
+        m_sortedConstraints = sortedConstraints;
+        m_numConstraints = numConstraints;
+        
+        m_debugDrawer = debugDrawer;
+        m_bodies.resize(0);
+        m_manifolds.resize(0);
+        m_constraints.resize(0);
+        m_multiBodyConstraints.resize(0);
+    }
+    
+    void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
+    {
+        m_solver = solver;
+    }
+    
+    virtual void processIsland(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifolds, int numManifolds, int islandId)
+    {
+        if (islandId < 0)
+        {
+            ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
+            m_solver->solveMultiBodyGroup(bodies, numBodies, manifolds, numManifolds, m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
+            if (m_solverInfo->m_reportSolverAnalytics&1)
+            {
+                m_solver->m_analyticsData.m_islandId = islandId;
+                m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+            }
+        }
+        else
+        {
+            //also add all non-contact constraints/joints for this island
+            btTypedConstraint** startConstraint = 0;
+            btMultiBodyConstraint** startMultiBodyConstraint = 0;
+            
+            int numCurConstraints = 0;
+            int numCurMultiBodyConstraints = 0;
+            
+            int i;
+            
+            //find the first constraint for this island
+            
+            for (i = 0; i < m_numConstraints; i++)
+            {
+                if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
+                {
+                    startConstraint = &m_sortedConstraints[i];
+                    break;
+                }
+            }
+            //count the number of constraints in this island
+            for (; i < m_numConstraints; i++)
+            {
+                if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
+                {
+                    numCurConstraints++;
+                }
+            }
+            
+            for (i = 0; i < m_numMultiBodyConstraints; i++)
+            {
+                if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
+                {
+                    startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
+                    break;
+                }
+            }
+            //count the number of multi body constraints in this island
+            for (; i < m_numMultiBodyConstraints; i++)
+            {
+                if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
+                {
+                    numCurMultiBodyConstraints++;
+                }
+            }
+            
+            //if (m_solverInfo->m_minimumSolverBatchSize<=1)
+            //{
+            //    m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
+            //} else
+            {
+                for (i = 0; i < numBodies; i++)
+                               {
+                                       bool isSoftBodyType = (bodies[i]->getInternalType() & btCollisionObject::CO_SOFT_BODY);
+                                       if (!isSoftBodyType)
+                                       {
+                                               m_bodies.push_back(bodies[i]);
+                                       }
+                                       else
+                                       {
+                                               m_softBodies.push_back(bodies[i]);
+                                       }
+                               }
+                for (i = 0; i < numManifolds; i++)
+                    m_manifolds.push_back(manifolds[i]);
+                for (i = 0; i < numCurConstraints; i++)
+                    m_constraints.push_back(startConstraint[i]);
+                
+                for (i = 0; i < numCurMultiBodyConstraints; i++)
+                    m_multiBodyConstraints.push_back(startMultiBodyConstraint[i]);
+                
+                if ((m_multiBodyConstraints.size() + m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
+                {
+                    processConstraints(islandId);
+                }
+                else
+                {
+                    //printf("deferred\n");
+                }
+            }
+        }
+    }
+    
+    virtual void processConstraints(int islandId=-1)
+    {
+        btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
+        btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
+        btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
+        btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
+        
+        //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
+        
+        m_solver->solveMultiBodyGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
+        if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics&1))
+        {
+            m_solver->m_analyticsData.m_islandId = islandId;
+            m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+        }
+        m_bodies.resize(0);
+               m_softBodies.resize(0);
+        m_manifolds.resize(0);
+        m_constraints.resize(0);
+        m_multiBodyConstraints.resize(0);
+    }
+};
+
+
+#endif /*BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H */
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h
new file mode 100644 (file)
index 0000000..d943019
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+Copyright (c) 2015 Google Inc.
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MULTIBODY_JOINT_FEEDBACK_H
+#define BT_MULTIBODY_JOINT_FEEDBACK_H
+
+#include "LinearMath/btSpatialAlgebra.h"
+
+struct btMultiBodyJointFeedback
+{
+       btSpatialForceVector m_reactionForces;
+};
+
+#endif  //BT_MULTIBODY_JOINT_FEEDBACK_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp
new file mode 100644 (file)
index 0000000..94b36ac
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#include "btMultiBodyJointLimitConstraint.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+btMultiBodyJointLimitConstraint::btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper)
+       //:btMultiBodyConstraint(body,0,link,-1,2,true),
+       : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 2, true, MULTIBODY_CONSTRAINT_LIMIT),
+         m_lowerBound(lower),
+         m_upperBound(upper)
+{
+}
+
+void btMultiBodyJointLimitConstraint::finalizeMultiDof()
+{
+       // the data.m_jacobians never change, so may as well
+       // initialize them here
+
+       allocateJacobiansMultiDof();
+
+       unsigned int offset = 6 + m_bodyA->getLink(m_linkA).m_dofOffset;
+
+       // row 0: the lower bound
+       jacobianA(0)[offset] = 1;
+       // row 1: the upper bound
+       //jacobianA(1)[offset] = -1;
+       jacobianB(1)[offset] = -1;
+
+       m_numDofsFinalized = m_jacSizeBoth;
+}
+
+btMultiBodyJointLimitConstraint::~btMultiBodyJointLimitConstraint()
+{
+}
+
+int btMultiBodyJointLimitConstraint::getIslandIdA() const
+{
+       if (m_bodyA)
+       {
+               if (m_linkA < 0)
+               {
+                       btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+                       if (col)
+                               return col->getIslandTag();
+               }
+               else
+               {
+                       if (m_bodyA->getLink(m_linkA).m_collider)
+                               return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+int btMultiBodyJointLimitConstraint::getIslandIdB() const
+{
+       if (m_bodyB)
+       {
+               if (m_linkB < 0)
+               {
+                       btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+                       if (col)
+                               return col->getIslandTag();
+               }
+               else
+               {
+                       if (m_bodyB->getLink(m_linkB).m_collider)
+                               return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+void btMultiBodyJointLimitConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                                                                  btMultiBodyJacobianData& data,
+                                                                                                                  const btContactSolverInfo& infoGlobal)
+{
+       // only positions need to be updated -- data.m_jacobians and force
+       // directions were set in the ctor and never change.
+
+       if (m_numDofsFinalized != m_jacSizeBoth)
+       {
+               finalizeMultiDof();
+       }
+
+       // row 0: the lower bound
+       setPosition(0, m_bodyA->getJointPos(m_linkA) - m_lowerBound);  //multidof: this is joint-type dependent
+
+       // row 1: the upper bound
+       setPosition(1, m_upperBound - m_bodyA->getJointPos(m_linkA));
+
+       for (int row = 0; row < getNumRows(); row++)
+       {
+               btScalar penetration = getPosition(row);
+
+               //todo: consider adding some safety threshold here
+               if (penetration > 0)
+               {
+                       continue;
+               }
+               btScalar direction = row ? -1 : 1;
+
+               btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+               constraintRow.m_orgConstraint = this;
+               constraintRow.m_orgDofIndex = row;
+
+               constraintRow.m_multiBodyA = m_bodyA;
+               constraintRow.m_multiBodyB = m_bodyB;
+               const btScalar posError = 0;  //why assume it's zero?
+               const btVector3 dummy(0, 0, 0);
+
+               btScalar rel_vel = fillMultiBodyConstraint(constraintRow, data, jacobianA(row), jacobianB(row), dummy, dummy, dummy, dummy, posError, infoGlobal, 0, m_maxAppliedImpulse);
+
+               {
+                       //expect either prismatic or revolute joint type for now
+                       btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute) || (m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
+                       switch (m_bodyA->getLink(m_linkA).m_jointType)
+                       {
+                               case btMultibodyLink::eRevolute:
+                               {
+                                       constraintRow.m_contactNormal1.setZero();
+                                       constraintRow.m_contactNormal2.setZero();
+                                       btVector3 revoluteAxisInWorld = direction * quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
+                                       constraintRow.m_relpos1CrossNormal = revoluteAxisInWorld;
+                                       constraintRow.m_relpos2CrossNormal = -revoluteAxisInWorld;
+
+                                       break;
+                               }
+                               case btMultibodyLink::ePrismatic:
+                               {
+                                       btVector3 prismaticAxisInWorld = direction * quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
+                                       constraintRow.m_contactNormal1 = prismaticAxisInWorld;
+                                       constraintRow.m_contactNormal2 = -prismaticAxisInWorld;
+                                       constraintRow.m_relpos1CrossNormal.setZero();
+                                       constraintRow.m_relpos2CrossNormal.setZero();
+
+                                       break;
+                               }
+                               default:
+                               {
+                                       btAssert(0);
+                               }
+                       };
+               }
+
+               {
+                       btScalar positionalError = 0.f;
+                       btScalar velocityError = -rel_vel;  // * damping;
+                       btScalar erp = infoGlobal.m_erp2;
+                       if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+                       {
+                               erp = infoGlobal.m_erp;
+                       }
+                       if (penetration > 0)
+                       {
+                               positionalError = 0;
+                               velocityError = -penetration / infoGlobal.m_timeStep;
+                       }
+                       else
+                       {
+                               positionalError = -penetration * erp / infoGlobal.m_timeStep;
+                       }
+
+                       btScalar penetrationImpulse = positionalError * constraintRow.m_jacDiagABInv;
+                       btScalar velocityImpulse = velocityError * constraintRow.m_jacDiagABInv;
+                       if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+                       {
+                               //combine position and velocity into rhs
+                               constraintRow.m_rhs = penetrationImpulse + velocityImpulse;
+                               constraintRow.m_rhsPenetration = 0.f;
+                       }
+                       else
+                       {
+                               //split position and velocity into rhs and m_rhsPenetration
+                               constraintRow.m_rhs = velocityImpulse;
+                               constraintRow.m_rhsPenetration = penetrationImpulse;
+                       }
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h
new file mode 100644 (file)
index 0000000..b810692
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H
+#define BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H
+
+#include "btMultiBodyConstraint.h"
+struct btSolverInfo;
+
+class btMultiBodyJointLimitConstraint : public btMultiBodyConstraint
+{
+protected:
+       btScalar m_lowerBound;
+       btScalar m_upperBound;
+
+public:
+       btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper);
+       virtual ~btMultiBodyJointLimitConstraint();
+
+       virtual void finalizeMultiDof();
+
+       virtual int getIslandIdA() const;
+       virtual int getIslandIdB() const;
+
+       virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                         btMultiBodyJacobianData& data,
+                                                                         const btContactSolverInfo& infoGlobal);
+
+       virtual void debugDraw(class btIDebugDraw* drawer)
+       {
+               //todo(erwincoumans)
+       }
+       btScalar getLowerBound() const
+       {
+               return m_lowerBound;
+       }
+       btScalar getUpperBound() const
+       {
+               return m_upperBound;
+       }
+       void setLowerBound(btScalar lower)
+       {
+               m_lowerBound = lower;
+       }
+       void setUpperBound(btScalar upper)
+       {
+               m_upperBound = upper;
+       }
+};
+
+#endif  //BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp
new file mode 100644 (file)
index 0000000..fec9b03
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#include "btMultiBodyJointMotor.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse)
+       : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 1, true, MULTIBODY_CONSTRAINT_1DOF_JOINT_MOTOR),
+         m_desiredVelocity(desiredVelocity),
+         m_desiredPosition(0),
+         m_kd(1.),
+         m_kp(0),
+         m_erp(1),
+         m_rhsClamp(SIMD_INFINITY)
+{
+       m_maxAppliedImpulse = maxMotorImpulse;
+       // the data.m_jacobians never change, so may as well
+       // initialize them here
+}
+
+void btMultiBodyJointMotor::finalizeMultiDof()
+{
+       allocateJacobiansMultiDof();
+       // note: we rely on the fact that data.m_jacobians are
+       // always initialized to zero by the Constraint ctor
+       int linkDoF = 0;
+       unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
+
+       // row 0: the lower bound
+       // row 0: the lower bound
+       jacobianA(0)[offset] = 1;
+
+       m_numDofsFinalized = m_jacSizeBoth;
+}
+
+btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, int linkDoF, btScalar desiredVelocity, btScalar maxMotorImpulse)
+       //:btMultiBodyConstraint(body,0,link,-1,1,true),
+       : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 1, true, MULTIBODY_CONSTRAINT_1DOF_JOINT_MOTOR),
+         m_desiredVelocity(desiredVelocity),
+         m_desiredPosition(0),
+         m_kd(1.),
+         m_kp(0),
+         m_erp(1),
+         m_rhsClamp(SIMD_INFINITY)
+{
+       btAssert(linkDoF < body->getLink(link).m_dofCount);
+
+       m_maxAppliedImpulse = maxMotorImpulse;
+}
+btMultiBodyJointMotor::~btMultiBodyJointMotor()
+{
+}
+
+int btMultiBodyJointMotor::getIslandIdA() const
+{
+       if (this->m_linkA < 0)
+       {
+               btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+               if (col)
+                       return col->getIslandTag();
+       }
+       else
+       {
+               if (m_bodyA->getLink(m_linkA).m_collider)
+               {
+                       return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+int btMultiBodyJointMotor::getIslandIdB() const
+{
+       if (m_linkB < 0)
+       {
+               btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+               if (col)
+                       return col->getIslandTag();
+       }
+       else
+       {
+               if (m_bodyB->getLink(m_linkB).m_collider)
+               {
+                       return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+void btMultiBodyJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                                                btMultiBodyJacobianData& data,
+                                                                                                const btContactSolverInfo& infoGlobal)
+{
+       // only positions need to be updated -- data.m_jacobians and force
+       // directions were set in the ctor and never change.
+
+       if (m_numDofsFinalized != m_jacSizeBoth)
+       {
+               finalizeMultiDof();
+       }
+
+       //don't crash
+       if (m_numDofsFinalized != m_jacSizeBoth)
+               return;
+
+       if (m_maxAppliedImpulse == 0.f)
+               return;
+
+       const btScalar posError = 0;
+       const btVector3 dummy(0, 0, 0);
+
+       for (int row = 0; row < getNumRows(); row++)
+       {
+               btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+
+               int dof = 0;
+               btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
+               btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
+               btScalar positionStabiliationTerm = m_erp * (m_desiredPosition - currentPosition) / infoGlobal.m_timeStep;
+
+               btScalar velocityError = (m_desiredVelocity - currentVelocity);
+               btScalar rhs = m_kp * positionStabiliationTerm + currentVelocity + m_kd * velocityError;
+               if (rhs > m_rhsClamp)
+               {
+                       rhs = m_rhsClamp;
+               }
+               if (rhs < -m_rhsClamp)
+               {
+                       rhs = -m_rhsClamp;
+               }
+
+               fillMultiBodyConstraint(constraintRow, data, jacobianA(row), jacobianB(row), dummy, dummy, dummy, dummy, posError, infoGlobal, -m_maxAppliedImpulse, m_maxAppliedImpulse, false, 1, false, rhs);
+               constraintRow.m_orgConstraint = this;
+               constraintRow.m_orgDofIndex = row;
+               {
+                       //expect either prismatic or revolute joint type for now
+                       btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute) || (m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
+                       switch (m_bodyA->getLink(m_linkA).m_jointType)
+                       {
+                               case btMultibodyLink::eRevolute:
+                               {
+                                       constraintRow.m_contactNormal1.setZero();
+                                       constraintRow.m_contactNormal2.setZero();
+                                       btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
+                                       constraintRow.m_relpos1CrossNormal = revoluteAxisInWorld;
+                                       constraintRow.m_relpos2CrossNormal = -revoluteAxisInWorld;
+
+                                       break;
+                               }
+                               case btMultibodyLink::ePrismatic:
+                               {
+                                       btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
+                                       constraintRow.m_contactNormal1 = prismaticAxisInWorld;
+                                       constraintRow.m_contactNormal2 = -prismaticAxisInWorld;
+                                       constraintRow.m_relpos1CrossNormal.setZero();
+                                       constraintRow.m_relpos2CrossNormal.setZero();
+
+                                       break;
+                               }
+                               default:
+                               {
+                                       btAssert(0);
+                               }
+                       };
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyJointMotor.h
new file mode 100644 (file)
index 0000000..1aca363
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_JOINT_MOTOR_H
+#define BT_MULTIBODY_JOINT_MOTOR_H
+
+#include "btMultiBodyConstraint.h"
+struct btSolverInfo;
+
+class btMultiBodyJointMotor : public btMultiBodyConstraint
+{
+protected:
+       btScalar m_desiredVelocity;
+       btScalar m_desiredPosition;
+       btScalar m_kd;
+       btScalar m_kp;
+       btScalar m_erp;
+       btScalar m_rhsClamp;  //maximum error
+
+public:
+       btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse);
+       btMultiBodyJointMotor(btMultiBody* body, int link, int linkDoF, btScalar desiredVelocity, btScalar maxMotorImpulse);
+       virtual ~btMultiBodyJointMotor();
+       virtual void finalizeMultiDof();
+
+       virtual int getIslandIdA() const;
+       virtual int getIslandIdB() const;
+
+       virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                         btMultiBodyJacobianData& data,
+                                                                         const btContactSolverInfo& infoGlobal);
+
+       virtual void setVelocityTarget(btScalar velTarget, btScalar kd = 1.f)
+       {
+               m_desiredVelocity = velTarget;
+               m_kd = kd;
+       }
+
+       virtual void setPositionTarget(btScalar posTarget, btScalar kp = 1.f)
+       {
+               m_desiredPosition = posTarget;
+               m_kp = kp;
+       }
+
+       virtual void setErp(btScalar erp)
+       {
+               m_erp = erp;
+       }
+       virtual btScalar getErp() const
+       {
+               return m_erp;
+       }
+       virtual void setRhsClamp(btScalar rhsClamp)
+       {
+               m_rhsClamp = rhsClamp;
+       }
+       virtual void debugDraw(class btIDebugDraw* drawer)
+       {
+               //todo(erwincoumans)
+       }
+};
+
+#endif  //BT_MULTIBODY_JOINT_MOTOR_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyLink.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyLink.h
new file mode 100644 (file)
index 0000000..5a14293
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MULTIBODY_LINK_H
+#define BT_MULTIBODY_LINK_H
+
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btVector3.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+enum btMultiBodyLinkFlags
+{
+       BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION = 1,
+       BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION = 2,
+};
+
+//both defines are now permanently enabled
+#define BT_MULTIBODYLINK_INCLUDE_PLANAR_JOINTS
+#define TEST_SPATIAL_ALGEBRA_LAYER
+
+//
+// Various spatial helper functions
+//
+
+//namespace {
+
+#include "LinearMath/btSpatialAlgebra.h"
+
+//}
+
+//
+// Link struct
+//
+
+struct btMultibodyLink
+{
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btScalar m_mass;           // mass of link
+       btVector3 m_inertiaLocal;  // inertia of link (local frame; diagonal)
+
+       int m_parent;  // index of the parent link (assumed to be < index of this link), or -1 if parent is the base link.
+
+       btQuaternion m_zeroRotParentToThis;  // rotates vectors in parent-frame to vectors in local-frame (when q=0). constant.
+
+       btVector3 m_dVector;  // vector from the inboard joint pos to this link's COM. (local frame.) constant.
+                                                 //this is set to zero for planar joint (see also m_eVector comment)
+
+       // m_eVector is constant, but depends on the joint type:
+       // revolute, fixed, prismatic, spherical: vector from parent's COM to the pivot point, in PARENT's frame.
+       // planar: vector from COM of parent to COM of this link, WHEN Q = 0. (local frame.)
+       // todo: fix the planar so it is consistent with the other joints
+
+       btVector3 m_eVector;
+
+       btSpatialMotionVector m_absFrameTotVelocity, m_absFrameLocVelocity;
+
+       enum eFeatherstoneJointType
+       {
+               eRevolute = 0,
+               ePrismatic = 1,
+               eSpherical = 2,
+               ePlanar = 3,
+               eFixed = 4,
+               eInvalid
+       };
+
+       // "axis" = spatial joint axis (Mirtich Defn 9 p104). (expressed in local frame.) constant.
+       // for prismatic: m_axesTop[0] = zero;
+       //                m_axesBottom[0] = unit vector along the joint axis.
+       // for revolute: m_axesTop[0] = unit vector along the rotation axis (u);
+       //               m_axesBottom[0] = u cross m_dVector (i.e. COM linear motion due to the rotation at the joint)
+       //
+       // for spherical: m_axesTop[0][1][2] (u1,u2,u3) form a 3x3 identity matrix (3 rotation axes)
+       //                                m_axesBottom[0][1][2] cross u1,u2,u3 (i.e. COM linear motion due to the rotation at the joint)
+       //
+       // for planar: m_axesTop[0] = unit vector along the rotation axis (u); defines the plane of motion
+       //                         m_axesTop[1][2] = zero
+       //                         m_axesBottom[0] = zero
+       //                         m_axesBottom[1][2] = unit vectors along the translational axes on that plane
+       btSpatialMotionVector m_axes[6];
+       void setAxisTop(int dof, const btVector3 &axis) { m_axes[dof].m_topVec = axis; }
+       void setAxisBottom(int dof, const btVector3 &axis)
+       {
+               m_axes[dof].m_bottomVec = axis;
+       }
+       void setAxisTop(int dof, const btScalar &x, const btScalar &y, const btScalar &z)
+       {
+               m_axes[dof].m_topVec.setValue(x, y, z);
+       }
+       void setAxisBottom(int dof, const btScalar &x, const btScalar &y, const btScalar &z)
+       {
+               m_axes[dof].m_bottomVec.setValue(x, y, z);
+       }
+       const btVector3 &getAxisTop(int dof) const { return m_axes[dof].m_topVec; }
+       const btVector3 &getAxisBottom(int dof) const { return m_axes[dof].m_bottomVec; }
+
+       int m_dofOffset, m_cfgOffset;
+
+       btQuaternion m_cachedRotParentToThis;  // rotates vectors in parent frame to vectors in local frame
+       btVector3 m_cachedRVector;             // vector from COM of parent to COM of this link, in local frame.
+    
+    // predicted verstion
+    btQuaternion m_cachedRotParentToThis_interpolate;  // rotates vectors in parent frame to vectors in local frame
+    btVector3 m_cachedRVector_interpolate;             // vector from COM of parent to COM of this link, in local frame.
+
+       btVector3 m_appliedForce;   // In WORLD frame
+       btVector3 m_appliedTorque;  // In WORLD frame
+
+       btVector3 m_appliedConstraintForce;   // In WORLD frame
+       btVector3 m_appliedConstraintTorque;  // In WORLD frame
+
+       btScalar m_jointPos[7];
+    btScalar m_jointPos_interpolate[7];
+
+       //m_jointTorque is the joint torque applied by the user using 'addJointTorque'.
+       //It gets set to zero after each internal stepSimulation call
+       btScalar m_jointTorque[6];
+
+       class btMultiBodyLinkCollider *m_collider;
+       int m_flags;
+
+       int m_dofCount, m_posVarCount;  //redundant but handy
+
+       eFeatherstoneJointType m_jointType;
+
+       struct btMultiBodyJointFeedback *m_jointFeedback;
+
+       btTransform m_cachedWorldTransform;  //this cache is updated when calling btMultiBody::forwardKinematics
+
+       const char *m_linkName;   //m_linkName memory needs to be managed by the developer/user!
+       const char *m_jointName;  //m_jointName memory needs to be managed by the developer/user!
+       const void *m_userPtr;    //m_userPtr ptr needs to be managed by the developer/user!
+
+       btScalar m_jointDamping;      //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual damping.
+       btScalar m_jointFriction;     //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual friction using a velocity motor.
+       btScalar m_jointLowerLimit;   //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+       btScalar m_jointUpperLimit;   //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+       btScalar m_jointMaxForce;     //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+       btScalar m_jointMaxVelocity;  //todo: implement this internally. It is unused for now, it is set by a URDF loader.
+
+       // ctor: set some sensible defaults
+       btMultibodyLink()
+               : m_mass(1),
+                 m_parent(-1),
+                 m_zeroRotParentToThis(0, 0, 0, 1),
+                 m_cachedRotParentToThis(0, 0, 0, 1),
+          m_cachedRotParentToThis_interpolate(0, 0, 0, 1),
+                 m_collider(0),
+                 m_flags(0),
+                 m_dofCount(0),
+                 m_posVarCount(0),
+                 m_jointType(btMultibodyLink::eInvalid),
+                 m_jointFeedback(0),
+                 m_linkName(0),
+                 m_jointName(0),
+                 m_userPtr(0),
+                 m_jointDamping(0),
+                 m_jointFriction(0),
+                 m_jointLowerLimit(0),
+                 m_jointUpperLimit(0),
+                 m_jointMaxForce(0),
+                 m_jointMaxVelocity(0)
+       {
+               m_inertiaLocal.setValue(1, 1, 1);
+               setAxisTop(0, 0., 0., 0.);
+               setAxisBottom(0, 1., 0., 0.);
+               m_dVector.setValue(0, 0, 0);
+               m_eVector.setValue(0, 0, 0);
+               m_cachedRVector.setValue(0, 0, 0);
+        m_cachedRVector_interpolate.setValue(0, 0, 0);
+               m_appliedForce.setValue(0, 0, 0);
+               m_appliedTorque.setValue(0, 0, 0);
+               m_appliedConstraintForce.setValue(0, 0, 0);
+               m_appliedConstraintTorque.setValue(0, 0, 0);
+               //
+               m_jointPos[0] = m_jointPos[1] = m_jointPos[2] = m_jointPos[4] = m_jointPos[5] = m_jointPos[6] = 0.f;
+               m_jointPos[3] = 1.f;  //"quat.w"
+               m_jointTorque[0] = m_jointTorque[1] = m_jointTorque[2] = m_jointTorque[3] = m_jointTorque[4] = m_jointTorque[5] = 0.f;
+               m_cachedWorldTransform.setIdentity();
+       }
+
+       // routine to update m_cachedRotParentToThis and m_cachedRVector
+       void updateCacheMultiDof(btScalar *pq = 0)
+       {
+        btScalar *pJointPos = (pq ? pq : &m_jointPos[0]);
+        btQuaternion& cachedRot = m_cachedRotParentToThis;
+        btVector3& cachedVector = m_cachedRVector;
+               switch (m_jointType)
+               {
+                       case eRevolute:
+                       {
+                               cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+                               cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
+
+                               break;
+                       }
+                       case ePrismatic:
+                       {
+                               // m_cachedRotParentToThis never changes, so no need to update
+                               cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
+
+                               break;
+                       }
+                       case eSpherical:
+                       {
+                               cachedRot = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
+                               cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
+
+                               break;
+                       }
+                       case ePlanar:
+                       {
+                               cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+                               cachedVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(cachedRot, m_eVector);
+
+                               break;
+                       }
+                       case eFixed:
+                       {
+                               cachedRot = m_zeroRotParentToThis;
+                               cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
+
+                               break;
+                       }
+                       default:
+                       {
+                               //invalid type
+                               btAssert(0);
+                       }
+               }
+        m_cachedRotParentToThis_interpolate = m_cachedRotParentToThis;
+        m_cachedRVector_interpolate = m_cachedRVector;
+       }
+    
+    void updateInterpolationCacheMultiDof()
+    {
+        btScalar *pJointPos = &m_jointPos_interpolate[0];
+        
+        btQuaternion& cachedRot = m_cachedRotParentToThis_interpolate;
+        btVector3& cachedVector = m_cachedRVector_interpolate;
+        switch (m_jointType)
+        {
+            case eRevolute:
+            {
+                cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+                cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
+                
+                break;
+            }
+            case ePrismatic:
+            {
+                // m_cachedRotParentToThis never changes, so no need to update
+                cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
+                
+                break;
+            }
+            case eSpherical:
+            {
+                cachedRot = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
+                cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
+                
+                break;
+            }
+            case ePlanar:
+            {
+                cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
+                cachedVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(cachedRot, m_eVector);
+                
+                break;
+            }
+            case eFixed:
+            {
+                cachedRot = m_zeroRotParentToThis;
+                cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
+                
+                break;
+            }
+            default:
+            {
+                //invalid type
+                btAssert(0);
+            }
+        }
+    }
+
+
+};
+
+#endif  //BT_MULTIBODY_LINK_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
new file mode 100644 (file)
index 0000000..3dc35a5
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_FEATHERSTONE_LINK_COLLIDER_H
+#define BT_FEATHERSTONE_LINK_COLLIDER_H
+
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+#include "btMultiBody.h"
+#include "LinearMath/btSerializer.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btMultiBodyLinkColliderData btMultiBodyLinkColliderDoubleData
+#define btMultiBodyLinkColliderDataName "btMultiBodyLinkColliderDoubleData"
+#else
+#define btMultiBodyLinkColliderData btMultiBodyLinkColliderFloatData
+#define btMultiBodyLinkColliderDataName "btMultiBodyLinkColliderFloatData"
+#endif
+
+class btMultiBodyLinkCollider : public btCollisionObject
+{
+       //protected:
+public:
+       btMultiBody* m_multiBody;
+       int m_link;
+
+       virtual ~btMultiBodyLinkCollider()
+       {
+
+       }
+       btMultiBodyLinkCollider(btMultiBody* multiBody, int link)
+               : m_multiBody(multiBody),
+                 m_link(link)
+       {
+               m_checkCollideWith = true;
+               //we need to remove the 'CF_STATIC_OBJECT' flag, otherwise links/base doesn't merge islands
+               //this means that some constraints might point to bodies that are not in the islands, causing crashes
+               //if (link>=0 || (multiBody && !multiBody->hasFixedBase()))
+               {
+                       m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
+               }
+               // else
+               //{
+               //      m_collisionFlags |= (btCollisionObject::CF_STATIC_OBJECT);
+               //}
+
+               m_internalType = CO_FEATHERSTONE_LINK;
+       }
+       static btMultiBodyLinkCollider* upcast(btCollisionObject* colObj)
+       {
+               if (colObj->getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK)
+                       return (btMultiBodyLinkCollider*)colObj;
+               return 0;
+       }
+       static const btMultiBodyLinkCollider* upcast(const btCollisionObject* colObj)
+       {
+               if (colObj->getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK)
+                       return (btMultiBodyLinkCollider*)colObj;
+               return 0;
+       }
+
+       virtual bool checkCollideWithOverride(const btCollisionObject* co) const
+       {
+               const btMultiBodyLinkCollider* other = btMultiBodyLinkCollider::upcast(co);
+               if (!other)
+                       return true;
+               if (other->m_multiBody != this->m_multiBody)
+                       return true;
+               if (!m_multiBody->hasSelfCollision())
+                       return false;
+
+               //check if 'link' has collision disabled
+               if (m_link >= 0)
+               {
+                       const btMultibodyLink& link = m_multiBody->getLink(this->m_link);
+                       if (link.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION)
+                       {
+                               int parent_of_this = m_link;
+                               while (1)
+                               {
+                                       if (parent_of_this == -1)
+                                               break;
+                                       parent_of_this = m_multiBody->getLink(parent_of_this).m_parent;
+                                       if (parent_of_this == other->m_link)
+                                       {
+                                               return false;
+                                       }
+                               }
+                       }
+                       else if (link.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION)
+                       {
+                               if (link.m_parent == other->m_link)
+                                       return false;
+                       }
+               }
+
+               if (other->m_link >= 0)
+               {
+                       const btMultibodyLink& otherLink = other->m_multiBody->getLink(other->m_link);
+                       if (otherLink.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION)
+                       {
+                               int parent_of_other = other->m_link;
+                               while (1)
+                               {
+                                       if (parent_of_other == -1)
+                                               break;
+                                       parent_of_other = m_multiBody->getLink(parent_of_other).m_parent;
+                                       if (parent_of_other == this->m_link)
+                                               return false;
+                               }
+                       }
+                       else if (otherLink.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION)
+                       {
+                               if (otherLink.m_parent == this->m_link)
+                                       return false;
+                       }
+               }
+               return true;
+       }
+
+       bool isStaticOrKinematic() const
+       {
+               return isStaticOrKinematicObject();
+       }
+
+       bool isKinematic() const
+       {
+               return isKinematicObject();
+       }
+
+       void setDynamicType(int dynamicType)
+       {
+               int oldFlags = getCollisionFlags();
+               oldFlags &= ~(btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT);
+               setCollisionFlags(oldFlags | dynamicType);
+       }
+
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
+};
+
+// clang-format off
+
+struct btMultiBodyLinkColliderFloatData
+{
+       btCollisionObjectFloatData m_colObjData;
+       btMultiBodyFloatData    *m_multiBody;
+       int                     m_link;
+       char            m_padding[4];
+};
+
+struct btMultiBodyLinkColliderDoubleData
+{
+       btCollisionObjectDoubleData m_colObjData;
+       btMultiBodyDoubleData           *m_multiBody;
+       int                     m_link;
+       char            m_padding[4];
+};
+
+// clang-format on
+
+SIMD_FORCE_INLINE int btMultiBodyLinkCollider::calculateSerializeBufferSize() const
+{
+       return sizeof(btMultiBodyLinkColliderData);
+}
+
+SIMD_FORCE_INLINE const char* btMultiBodyLinkCollider::serialize(void* dataBuffer, class btSerializer* serializer) const
+{
+       btMultiBodyLinkColliderData* dataOut = (btMultiBodyLinkColliderData*)dataBuffer;
+       btCollisionObject::serialize(&dataOut->m_colObjData, serializer);
+
+       dataOut->m_link = this->m_link;
+       dataOut->m_multiBody = (btMultiBodyData*)serializer->getUniquePointer(m_multiBody);
+
+       // Fill padding with zeros to appease msan.
+       memset(dataOut->m_padding, 0, sizeof(dataOut->m_padding));
+
+       return btMultiBodyLinkColliderDataName;
+}
+
+#endif  //BT_FEATHERSTONE_LINK_COLLIDER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp
new file mode 100644 (file)
index 0000000..f2186a9
--- /dev/null
@@ -0,0 +1,966 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2018 Google Inc. http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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/Featherstone/btMultiBodyMLCPConstraintSolver.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+#include "BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h"
+
+#define DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+
+static bool interleaveContactAndFriction1 = false;
+
+struct btJointNode1
+{
+       int jointIndex;          // pointer to enclosing dxJoint object
+       int otherBodyIndex;      // *other* body this joint is connected to
+       int nextJointNodeIndex;  //-1 for null
+       int constraintRowIndex;
+};
+
+// Helper function to compute a delta velocity in the constraint space.
+static btScalar computeDeltaVelocityInConstraintSpace(
+       const btVector3& angularDeltaVelocity,
+       const btVector3& contactNormal,
+       btScalar invMass,
+       const btVector3& angularJacobian,
+       const btVector3& linearJacobian)
+{
+       return angularDeltaVelocity.dot(angularJacobian) + contactNormal.dot(linearJacobian) * invMass;
+}
+
+// Faster version of computeDeltaVelocityInConstraintSpace that can be used when contactNormal and linearJacobian are
+// identical.
+static btScalar computeDeltaVelocityInConstraintSpace(
+       const btVector3& angularDeltaVelocity,
+       btScalar invMass,
+       const btVector3& angularJacobian)
+{
+       return angularDeltaVelocity.dot(angularJacobian) + invMass;
+}
+
+// Helper function to compute a delta velocity in the constraint space.
+static btScalar computeDeltaVelocityInConstraintSpace(const btScalar* deltaVelocity, const btScalar* jacobian, int size)
+{
+       btScalar result = 0;
+       for (int i = 0; i < size; ++i)
+               result += deltaVelocity[i] * jacobian[i];
+
+       return result;
+}
+
+static btScalar computeConstraintMatrixDiagElementMultiBody(
+       const btAlignedObjectArray<btSolverBody>& solverBodyPool,
+       const btMultiBodyJacobianData& data,
+       const btMultiBodySolverConstraint& constraint)
+{
+       btScalar ret = 0;
+
+       const btMultiBody* multiBodyA = constraint.m_multiBodyA;
+       const btMultiBody* multiBodyB = constraint.m_multiBodyB;
+
+       if (multiBodyA)
+       {
+               const btScalar* jacA = &data.m_jacobians[constraint.m_jacAindex];
+               const btScalar* deltaA = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacAindex];
+               const int ndofA = multiBodyA->getNumDofs() + 6;
+               ret += computeDeltaVelocityInConstraintSpace(deltaA, jacA, ndofA);
+       }
+       else
+       {
+               const int solverBodyIdA = constraint.m_solverBodyIdA;
+               btAssert(solverBodyIdA != -1);
+               const btSolverBody* solverBodyA = &solverBodyPool[solverBodyIdA];
+               const btScalar invMassA = solverBodyA->m_originalBody ? solverBodyA->m_originalBody->getInvMass() : 0.0;
+               ret += computeDeltaVelocityInConstraintSpace(
+                       constraint.m_relpos1CrossNormal,
+                       invMassA,
+                       constraint.m_angularComponentA);
+       }
+
+       if (multiBodyB)
+       {
+               const btScalar* jacB = &data.m_jacobians[constraint.m_jacBindex];
+               const btScalar* deltaB = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacBindex];
+               const int ndofB = multiBodyB->getNumDofs() + 6;
+               ret += computeDeltaVelocityInConstraintSpace(deltaB, jacB, ndofB);
+       }
+       else
+       {
+               const int solverBodyIdB = constraint.m_solverBodyIdB;
+               btAssert(solverBodyIdB != -1);
+               const btSolverBody* solverBodyB = &solverBodyPool[solverBodyIdB];
+               const btScalar invMassB = solverBodyB->m_originalBody ? solverBodyB->m_originalBody->getInvMass() : 0.0;
+               ret += computeDeltaVelocityInConstraintSpace(
+                       constraint.m_relpos2CrossNormal,
+                       invMassB,
+                       constraint.m_angularComponentB);
+       }
+
+       return ret;
+}
+
+static btScalar computeConstraintMatrixOffDiagElementMultiBody(
+       const btAlignedObjectArray<btSolverBody>& solverBodyPool,
+       const btMultiBodyJacobianData& data,
+       const btMultiBodySolverConstraint& constraint,
+       const btMultiBodySolverConstraint& offDiagConstraint)
+{
+       btScalar offDiagA = btScalar(0);
+
+       const btMultiBody* multiBodyA = constraint.m_multiBodyA;
+       const btMultiBody* multiBodyB = constraint.m_multiBodyB;
+       const btMultiBody* offDiagMultiBodyA = offDiagConstraint.m_multiBodyA;
+       const btMultiBody* offDiagMultiBodyB = offDiagConstraint.m_multiBodyB;
+
+       // Assumed at least one system is multibody
+       btAssert(multiBodyA || multiBodyB);
+       btAssert(offDiagMultiBodyA || offDiagMultiBodyB);
+
+       if (offDiagMultiBodyA)
+       {
+               const btScalar* offDiagJacA = &data.m_jacobians[offDiagConstraint.m_jacAindex];
+
+               if (offDiagMultiBodyA == multiBodyA)
+               {
+                       const int ndofA = multiBodyA->getNumDofs() + 6;
+                       const btScalar* deltaA = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacAindex];
+                       offDiagA += computeDeltaVelocityInConstraintSpace(deltaA, offDiagJacA, ndofA);
+               }
+               else if (offDiagMultiBodyA == multiBodyB)
+               {
+                       const int ndofB = multiBodyB->getNumDofs() + 6;
+                       const btScalar* deltaB = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacBindex];
+                       offDiagA += computeDeltaVelocityInConstraintSpace(deltaB, offDiagJacA, ndofB);
+               }
+       }
+       else
+       {
+               const int solverBodyIdA = constraint.m_solverBodyIdA;
+               const int solverBodyIdB = constraint.m_solverBodyIdB;
+
+               const int offDiagSolverBodyIdA = offDiagConstraint.m_solverBodyIdA;
+               btAssert(offDiagSolverBodyIdA != -1);
+
+               if (offDiagSolverBodyIdA == solverBodyIdA)
+               {
+                       btAssert(solverBodyIdA != -1);
+                       const btSolverBody* solverBodyA = &solverBodyPool[solverBodyIdA];
+                       const btScalar invMassA = solverBodyA->m_originalBody ? solverBodyA->m_originalBody->getInvMass() : 0.0;
+                       offDiagA += computeDeltaVelocityInConstraintSpace(
+                               offDiagConstraint.m_relpos1CrossNormal,
+                               offDiagConstraint.m_contactNormal1,
+                               invMassA, constraint.m_angularComponentA,
+                               constraint.m_contactNormal1);
+               }
+               else if (offDiagSolverBodyIdA == solverBodyIdB)
+               {
+                       btAssert(solverBodyIdB != -1);
+                       const btSolverBody* solverBodyB = &solverBodyPool[solverBodyIdB];
+                       const btScalar invMassB = solverBodyB->m_originalBody ? solverBodyB->m_originalBody->getInvMass() : 0.0;
+                       offDiagA += computeDeltaVelocityInConstraintSpace(
+                               offDiagConstraint.m_relpos1CrossNormal,
+                               offDiagConstraint.m_contactNormal1,
+                               invMassB,
+                               constraint.m_angularComponentB,
+                               constraint.m_contactNormal2);
+               }
+       }
+
+       if (offDiagMultiBodyB)
+       {
+               const btScalar* offDiagJacB = &data.m_jacobians[offDiagConstraint.m_jacBindex];
+
+               if (offDiagMultiBodyB == multiBodyA)
+               {
+                       const int ndofA = multiBodyA->getNumDofs() + 6;
+                       const btScalar* deltaA = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacAindex];
+                       offDiagA += computeDeltaVelocityInConstraintSpace(deltaA, offDiagJacB, ndofA);
+               }
+               else if (offDiagMultiBodyB == multiBodyB)
+               {
+                       const int ndofB = multiBodyB->getNumDofs() + 6;
+                       const btScalar* deltaB = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacBindex];
+                       offDiagA += computeDeltaVelocityInConstraintSpace(deltaB, offDiagJacB, ndofB);
+               }
+       }
+       else
+       {
+               const int solverBodyIdA = constraint.m_solverBodyIdA;
+               const int solverBodyIdB = constraint.m_solverBodyIdB;
+
+               const int offDiagSolverBodyIdB = offDiagConstraint.m_solverBodyIdB;
+               btAssert(offDiagSolverBodyIdB != -1);
+
+               if (offDiagSolverBodyIdB == solverBodyIdA)
+               {
+                       btAssert(solverBodyIdA != -1);
+                       const btSolverBody* solverBodyA = &solverBodyPool[solverBodyIdA];
+                       const btScalar invMassA = solverBodyA->m_originalBody ? solverBodyA->m_originalBody->getInvMass() : 0.0;
+                       offDiagA += computeDeltaVelocityInConstraintSpace(
+                               offDiagConstraint.m_relpos2CrossNormal,
+                               offDiagConstraint.m_contactNormal2,
+                               invMassA, constraint.m_angularComponentA,
+                               constraint.m_contactNormal1);
+               }
+               else if (offDiagSolverBodyIdB == solverBodyIdB)
+               {
+                       btAssert(solverBodyIdB != -1);
+                       const btSolverBody* solverBodyB = &solverBodyPool[solverBodyIdB];
+                       const btScalar invMassB = solverBodyB->m_originalBody ? solverBodyB->m_originalBody->getInvMass() : 0.0;
+                       offDiagA += computeDeltaVelocityInConstraintSpace(
+                               offDiagConstraint.m_relpos2CrossNormal,
+                               offDiagConstraint.m_contactNormal2,
+                               invMassB, constraint.m_angularComponentB,
+                               constraint.m_contactNormal2);
+               }
+       }
+
+       return offDiagA;
+}
+
+void btMultiBodyMLCPConstraintSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
+{
+       createMLCPFastRigidBody(infoGlobal);
+       createMLCPFastMultiBody(infoGlobal);
+}
+
+void btMultiBodyMLCPConstraintSolver::createMLCPFastRigidBody(const btContactSolverInfo& infoGlobal)
+{
+       int numContactRows = interleaveContactAndFriction1 ? 3 : 1;
+
+       int numConstraintRows = m_allConstraintPtrArray.size();
+
+       if (numConstraintRows == 0)
+               return;
+
+       int n = numConstraintRows;
+       {
+               BT_PROFILE("init b (rhs)");
+               m_b.resize(numConstraintRows);
+               m_bSplit.resize(numConstraintRows);
+               m_b.setZero();
+               m_bSplit.setZero();
+               for (int i = 0; i < numConstraintRows; i++)
+               {
+                       btScalar jacDiag = m_allConstraintPtrArray[i]->m_jacDiagABInv;
+                       if (!btFuzzyZero(jacDiag))
+                       {
+                               btScalar rhs = m_allConstraintPtrArray[i]->m_rhs;
+                               btScalar rhsPenetration = m_allConstraintPtrArray[i]->m_rhsPenetration;
+                               m_b[i] = rhs / jacDiag;
+                               m_bSplit[i] = rhsPenetration / jacDiag;
+                       }
+               }
+       }
+
+       //      btScalar* w = 0;
+       //      int nub = 0;
+
+       m_lo.resize(numConstraintRows);
+       m_hi.resize(numConstraintRows);
+
+       {
+               BT_PROFILE("init lo/ho");
+
+               for (int i = 0; i < numConstraintRows; i++)
+               {
+                       if (0)  //m_limitDependencies[i]>=0)
+                       {
+                               m_lo[i] = -BT_INFINITY;
+                               m_hi[i] = BT_INFINITY;
+                       }
+                       else
+                       {
+                               m_lo[i] = m_allConstraintPtrArray[i]->m_lowerLimit;
+                               m_hi[i] = m_allConstraintPtrArray[i]->m_upperLimit;
+                       }
+               }
+       }
+
+       //
+       int m = m_allConstraintPtrArray.size();
+
+       int numBodies = m_tmpSolverBodyPool.size();
+       btAlignedObjectArray<int> bodyJointNodeArray;
+       {
+               BT_PROFILE("bodyJointNodeArray.resize");
+               bodyJointNodeArray.resize(numBodies, -1);
+       }
+       btAlignedObjectArray<btJointNode1> jointNodeArray;
+       {
+               BT_PROFILE("jointNodeArray.reserve");
+               jointNodeArray.reserve(2 * m_allConstraintPtrArray.size());
+       }
+
+       btMatrixXu& J3 = m_scratchJ3;
+       {
+               BT_PROFILE("J3.resize");
+               J3.resize(2 * m, 8);
+       }
+       btMatrixXu& JinvM3 = m_scratchJInvM3;
+       {
+               BT_PROFILE("JinvM3.resize/setZero");
+
+               JinvM3.resize(2 * m, 8);
+               JinvM3.setZero();
+               J3.setZero();
+       }
+       int cur = 0;
+       int rowOffset = 0;
+       btAlignedObjectArray<int>& ofs = m_scratchOfs;
+       {
+               BT_PROFILE("ofs resize");
+               ofs.resize(0);
+               ofs.resizeNoInitialize(m_allConstraintPtrArray.size());
+       }
+       {
+               BT_PROFILE("Compute J and JinvM");
+               int c = 0;
+
+               int numRows = 0;
+
+               for (int i = 0; i < m_allConstraintPtrArray.size(); i += numRows, c++)
+               {
+                       ofs[c] = rowOffset;
+                       int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
+                       int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
+                       btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+                       btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+                       numRows = i < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows;
+                       if (orgBodyA)
+                       {
+                               {
+                                       int slotA = -1;
+                                       //find free jointNode slot for sbA
+                                       slotA = jointNodeArray.size();
+                                       jointNodeArray.expand();  //NonInitializing();
+                                       int prevSlot = bodyJointNodeArray[sbA];
+                                       bodyJointNodeArray[sbA] = slotA;
+                                       jointNodeArray[slotA].nextJointNodeIndex = prevSlot;
+                                       jointNodeArray[slotA].jointIndex = c;
+                                       jointNodeArray[slotA].constraintRowIndex = i;
+                                       jointNodeArray[slotA].otherBodyIndex = orgBodyB ? sbB : -1;
+                               }
+                               for (int row = 0; row < numRows; row++, cur++)
+                               {
+                                       btVector3 normalInvMass = m_allConstraintPtrArray[i + row]->m_contactNormal1 * orgBodyA->getInvMass();
+                                       btVector3 relPosCrossNormalInvInertia = m_allConstraintPtrArray[i + row]->m_relpos1CrossNormal * orgBodyA->getInvInertiaTensorWorld();
+
+                                       for (int r = 0; r < 3; r++)
+                                       {
+                                               J3.setElem(cur, r, m_allConstraintPtrArray[i + row]->m_contactNormal1[r]);
+                                               J3.setElem(cur, r + 4, m_allConstraintPtrArray[i + row]->m_relpos1CrossNormal[r]);
+                                               JinvM3.setElem(cur, r, normalInvMass[r]);
+                                               JinvM3.setElem(cur, r + 4, relPosCrossNormalInvInertia[r]);
+                                       }
+                                       J3.setElem(cur, 3, 0);
+                                       JinvM3.setElem(cur, 3, 0);
+                                       J3.setElem(cur, 7, 0);
+                                       JinvM3.setElem(cur, 7, 0);
+                               }
+                       }
+                       else
+                       {
+                               cur += numRows;
+                       }
+                       if (orgBodyB)
+                       {
+                               {
+                                       int slotB = -1;
+                                       //find free jointNode slot for sbA
+                                       slotB = jointNodeArray.size();
+                                       jointNodeArray.expand();  //NonInitializing();
+                                       int prevSlot = bodyJointNodeArray[sbB];
+                                       bodyJointNodeArray[sbB] = slotB;
+                                       jointNodeArray[slotB].nextJointNodeIndex = prevSlot;
+                                       jointNodeArray[slotB].jointIndex = c;
+                                       jointNodeArray[slotB].otherBodyIndex = orgBodyA ? sbA : -1;
+                                       jointNodeArray[slotB].constraintRowIndex = i;
+                               }
+
+                               for (int row = 0; row < numRows; row++, cur++)
+                               {
+                                       btVector3 normalInvMassB = m_allConstraintPtrArray[i + row]->m_contactNormal2 * orgBodyB->getInvMass();
+                                       btVector3 relPosInvInertiaB = m_allConstraintPtrArray[i + row]->m_relpos2CrossNormal * orgBodyB->getInvInertiaTensorWorld();
+
+                                       for (int r = 0; r < 3; r++)
+                                       {
+                                               J3.setElem(cur, r, m_allConstraintPtrArray[i + row]->m_contactNormal2[r]);
+                                               J3.setElem(cur, r + 4, m_allConstraintPtrArray[i + row]->m_relpos2CrossNormal[r]);
+                                               JinvM3.setElem(cur, r, normalInvMassB[r]);
+                                               JinvM3.setElem(cur, r + 4, relPosInvInertiaB[r]);
+                                       }
+                                       J3.setElem(cur, 3, 0);
+                                       JinvM3.setElem(cur, 3, 0);
+                                       J3.setElem(cur, 7, 0);
+                                       JinvM3.setElem(cur, 7, 0);
+                               }
+                       }
+                       else
+                       {
+                               cur += numRows;
+                       }
+                       rowOffset += numRows;
+               }
+       }
+
+       //compute JinvM = J*invM.
+       const btScalar* JinvM = JinvM3.getBufferPointer();
+
+       const btScalar* Jptr = J3.getBufferPointer();
+       {
+               BT_PROFILE("m_A.resize");
+               m_A.resize(n, n);
+       }
+
+       {
+               BT_PROFILE("m_A.setZero");
+               m_A.setZero();
+       }
+       int c = 0;
+       {
+               int numRows = 0;
+               BT_PROFILE("Compute A");
+               for (int i = 0; i < m_allConstraintPtrArray.size(); i += numRows, c++)
+               {
+                       int row__ = ofs[c];
+                       int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
+                       int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
+                       //      btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+                       //      btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+                       numRows = i < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows;
+
+                       const btScalar* JinvMrow = JinvM + 2 * 8 * (size_t)row__;
+
+                       {
+                               int startJointNodeA = bodyJointNodeArray[sbA];
+                               while (startJointNodeA >= 0)
+                               {
+                                       int j0 = jointNodeArray[startJointNodeA].jointIndex;
+                                       int cr0 = jointNodeArray[startJointNodeA].constraintRowIndex;
+                                       if (j0 < c)
+                                       {
+                                               int numRowsOther = cr0 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j0].m_numConstraintRows : numContactRows;
+                                               size_t ofsother = (m_allConstraintPtrArray[cr0]->m_solverBodyIdB == sbA) ? 8 * numRowsOther : 0;
+                                               //printf("%d joint i %d and j0: %d: ",count++,i,j0);
+                                               m_A.multiplyAdd2_p8r(JinvMrow,
+                                                                                        Jptr + 2 * 8 * (size_t)ofs[j0] + ofsother, numRows, numRowsOther, row__, ofs[j0]);
+                                       }
+                                       startJointNodeA = jointNodeArray[startJointNodeA].nextJointNodeIndex;
+                               }
+                       }
+
+                       {
+                               int startJointNodeB = bodyJointNodeArray[sbB];
+                               while (startJointNodeB >= 0)
+                               {
+                                       int j1 = jointNodeArray[startJointNodeB].jointIndex;
+                                       int cj1 = jointNodeArray[startJointNodeB].constraintRowIndex;
+
+                                       if (j1 < c)
+                                       {
+                                               int numRowsOther = cj1 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j1].m_numConstraintRows : numContactRows;
+                                               size_t ofsother = (m_allConstraintPtrArray[cj1]->m_solverBodyIdB == sbB) ? 8 * numRowsOther : 0;
+                                               m_A.multiplyAdd2_p8r(JinvMrow + 8 * (size_t)numRows,
+                                                                                        Jptr + 2 * 8 * (size_t)ofs[j1] + ofsother, numRows, numRowsOther, row__, ofs[j1]);
+                                       }
+                                       startJointNodeB = jointNodeArray[startJointNodeB].nextJointNodeIndex;
+                               }
+                       }
+               }
+
+               {
+                       BT_PROFILE("compute diagonal");
+                       // compute diagonal blocks of m_A
+
+                       int row__ = 0;
+                       int numJointRows = m_allConstraintPtrArray.size();
+
+                       int jj = 0;
+                       for (; row__ < numJointRows;)
+                       {
+                               //int sbA = m_allConstraintPtrArray[row__]->m_solverBodyIdA;
+                               int sbB = m_allConstraintPtrArray[row__]->m_solverBodyIdB;
+                               //      btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+                               btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+                               const unsigned int infom = row__ < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[jj].m_numConstraintRows : numContactRows;
+
+                               const btScalar* JinvMrow = JinvM + 2 * 8 * (size_t)row__;
+                               const btScalar* Jrow = Jptr + 2 * 8 * (size_t)row__;
+                               m_A.multiply2_p8r(JinvMrow, Jrow, infom, infom, row__, row__);
+                               if (orgBodyB)
+                               {
+                                       m_A.multiplyAdd2_p8r(JinvMrow + 8 * (size_t)infom, Jrow + 8 * (size_t)infom, infom, infom, row__, row__);
+                               }
+                               row__ += infom;
+                               jj++;
+                       }
+               }
+       }
+
+       if (1)
+       {
+               // add cfm to the diagonal of m_A
+               for (int i = 0; i < m_A.rows(); ++i)
+               {
+                       m_A.setElem(i, i, m_A(i, i) + infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
+               }
+       }
+
+       ///fill the upper triangle of the matrix, to make it symmetric
+       {
+               BT_PROFILE("fill the upper triangle ");
+               m_A.copyLowerToUpperTriangle();
+       }
+
+       {
+               BT_PROFILE("resize/init x");
+               m_x.resize(numConstraintRows);
+               m_xSplit.resize(numConstraintRows);
+
+               if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+               {
+                       for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
+                       {
+                               const btSolverConstraint& c = *m_allConstraintPtrArray[i];
+                               m_x[i] = c.m_appliedImpulse;
+                               m_xSplit[i] = c.m_appliedPushImpulse;
+                       }
+               }
+               else
+               {
+                       m_x.setZero();
+                       m_xSplit.setZero();
+               }
+       }
+}
+
+void btMultiBodyMLCPConstraintSolver::createMLCPFastMultiBody(const btContactSolverInfo& infoGlobal)
+{
+       const int multiBodyNumConstraints = m_multiBodyAllConstraintPtrArray.size();
+
+       if (multiBodyNumConstraints == 0)
+               return;
+
+       // 1. Compute b
+       {
+               BT_PROFILE("init b (rhs)");
+
+               m_multiBodyB.resize(multiBodyNumConstraints);
+               m_multiBodyB.setZero();
+
+               for (int i = 0; i < multiBodyNumConstraints; ++i)
+               {
+                       const btMultiBodySolverConstraint& constraint = *m_multiBodyAllConstraintPtrArray[i];
+                       const btScalar jacDiag = constraint.m_jacDiagABInv;
+
+                       if (!btFuzzyZero(jacDiag))
+                       {
+                               // Note that rhsPenetration is currently always zero because the split impulse hasn't been implemented for multibody yet.
+                               const btScalar rhs = constraint.m_rhs;
+                               m_multiBodyB[i] = rhs / jacDiag;
+                       }
+               }
+       }
+
+       // 2. Compute lo and hi
+       {
+               BT_PROFILE("init lo/ho");
+
+               m_multiBodyLo.resize(multiBodyNumConstraints);
+               m_multiBodyHi.resize(multiBodyNumConstraints);
+
+               for (int i = 0; i < multiBodyNumConstraints; ++i)
+               {
+                       const btMultiBodySolverConstraint& constraint = *m_multiBodyAllConstraintPtrArray[i];
+                       m_multiBodyLo[i] = constraint.m_lowerLimit;
+                       m_multiBodyHi[i] = constraint.m_upperLimit;
+               }
+       }
+
+       // 3. Construct A matrix by using the impulse testing
+       {
+               BT_PROFILE("Compute A");
+
+               {
+                       BT_PROFILE("m_A.resize");
+                       m_multiBodyA.resize(multiBodyNumConstraints, multiBodyNumConstraints);
+               }
+
+               for (int i = 0; i < multiBodyNumConstraints; ++i)
+               {
+                       // Compute the diagonal of A, which is A(i, i)
+                       const btMultiBodySolverConstraint& constraint = *m_multiBodyAllConstraintPtrArray[i];
+                       const btScalar diagA = computeConstraintMatrixDiagElementMultiBody(m_tmpSolverBodyPool, m_data, constraint);
+                       m_multiBodyA.setElem(i, i, diagA);
+
+                       // Computes the off-diagonals of A:
+                       //   a. The rest of i-th row of A, from A(i, i+1) to A(i, n)
+                       //   b. The rest of i-th column of A, from A(i+1, i) to A(n, i)
+                       for (int j = i + 1; j < multiBodyNumConstraints; ++j)
+                       {
+                               const btMultiBodySolverConstraint& offDiagConstraint = *m_multiBodyAllConstraintPtrArray[j];
+                               const btScalar offDiagA = computeConstraintMatrixOffDiagElementMultiBody(m_tmpSolverBodyPool, m_data, constraint, offDiagConstraint);
+
+                               // Set the off-diagonal values of A. Note that A is symmetric.
+                               m_multiBodyA.setElem(i, j, offDiagA);
+                               m_multiBodyA.setElem(j, i, offDiagA);
+                       }
+               }
+       }
+
+       // Add CFM to the diagonal of m_A
+       for (int i = 0; i < m_multiBodyA.rows(); ++i)
+       {
+               m_multiBodyA.setElem(i, i, m_multiBodyA(i, i) + infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
+       }
+
+       // 4. Initialize x
+       {
+               BT_PROFILE("resize/init x");
+
+               m_multiBodyX.resize(multiBodyNumConstraints);
+
+               if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+               {
+                       for (int i = 0; i < multiBodyNumConstraints; ++i)
+                       {
+                               const btMultiBodySolverConstraint& constraint = *m_multiBodyAllConstraintPtrArray[i];
+                               m_multiBodyX[i] = constraint.m_appliedImpulse;
+                       }
+               }
+               else
+               {
+                       m_multiBodyX.setZero();
+               }
+       }
+}
+
+bool btMultiBodyMLCPConstraintSolver::solveMLCP(const btContactSolverInfo& infoGlobal)
+{
+       bool result = true;
+
+       if (m_A.rows() != 0)
+       {
+               // If using split impulse, we solve 2 separate (M)LCPs
+               if (infoGlobal.m_splitImpulse)
+               {
+                       const btMatrixXu Acopy = m_A;
+                       const btAlignedObjectArray<int> limitDependenciesCopy = m_limitDependencies;
+                       // TODO(JS): Do we really need these copies when solveMLCP takes them as const?
+
+                       result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo, m_hi, m_limitDependencies, infoGlobal.m_numIterations);
+                       if (result)
+                               result = m_solver->solveMLCP(Acopy, m_bSplit, m_xSplit, m_lo, m_hi, limitDependenciesCopy, infoGlobal.m_numIterations);
+               }
+               else
+               {
+                       result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo, m_hi, m_limitDependencies, infoGlobal.m_numIterations);
+               }
+       }
+
+       if (!result)
+               return false;
+
+       if (m_multiBodyA.rows() != 0)
+       {
+               result = m_solver->solveMLCP(m_multiBodyA, m_multiBodyB, m_multiBodyX, m_multiBodyLo, m_multiBodyHi, m_multiBodyLimitDependencies, infoGlobal.m_numIterations);
+       }
+
+       return result;
+}
+
+btScalar btMultiBodyMLCPConstraintSolver::solveGroupCacheFriendlySetup(
+       btCollisionObject** bodies,
+       int numBodies,
+       btPersistentManifold** manifoldPtr,
+       int numManifolds,
+       btTypedConstraint** constraints,
+       int numConstraints,
+       const btContactSolverInfo& infoGlobal,
+       btIDebugDraw* debugDrawer)
+{
+       // 1. Setup for rigid-bodies
+       btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(
+               bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+       // 2. Setup for multi-bodies
+       //   a. Collect all different kinds of constraint as pointers into one array, m_allConstraintPtrArray
+       //   b. Set the index array for frictional contact constraints, m_limitDependencies
+       {
+               BT_PROFILE("gather constraint data");
+
+               int dindex = 0;
+
+               const int numRigidBodyConstraints = m_tmpSolverNonContactConstraintPool.size() + m_tmpSolverContactConstraintPool.size() + m_tmpSolverContactFrictionConstraintPool.size();
+               const int numMultiBodyConstraints = m_multiBodyNonContactConstraints.size() + m_multiBodyNormalContactConstraints.size() + m_multiBodyFrictionContactConstraints.size();
+
+               m_allConstraintPtrArray.resize(0);
+               m_multiBodyAllConstraintPtrArray.resize(0);
+
+               // i. Setup for rigid bodies
+
+               m_limitDependencies.resize(numRigidBodyConstraints);
+
+               for (int i = 0; i < m_tmpSolverNonContactConstraintPool.size(); ++i)
+               {
+                       m_allConstraintPtrArray.push_back(&m_tmpSolverNonContactConstraintPool[i]);
+                       m_limitDependencies[dindex++] = -1;
+               }
+
+               int firstContactConstraintOffset = dindex;
+
+               // The btSequentialImpulseConstraintSolver moves all friction constraints at the very end, we can also interleave them instead
+               if (interleaveContactAndFriction1)
+               {
+                       for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
+                       {
+                               const int numFrictionPerContact = m_tmpSolverContactConstraintPool.size() == m_tmpSolverContactFrictionConstraintPool.size() ? 1 : 2;
+
+                               m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
+                               m_limitDependencies[dindex++] = -1;
+                               m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact]);
+                               int findex = (m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact].m_frictionIndex * (1 + numFrictionPerContact));
+                               m_limitDependencies[dindex++] = findex + firstContactConstraintOffset;
+                               if (numFrictionPerContact == 2)
+                               {
+                                       m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact + 1]);
+                                       m_limitDependencies[dindex++] = findex + firstContactConstraintOffset;
+                               }
+                       }
+               }
+               else
+               {
+                       for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
+                       {
+                               m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
+                               m_limitDependencies[dindex++] = -1;
+                       }
+                       for (int i = 0; i < m_tmpSolverContactFrictionConstraintPool.size(); i++)
+                       {
+                               m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i]);
+                               m_limitDependencies[dindex++] = m_tmpSolverContactFrictionConstraintPool[i].m_frictionIndex + firstContactConstraintOffset;
+                       }
+               }
+
+               if (!m_allConstraintPtrArray.size())
+               {
+                       m_A.resize(0, 0);
+                       m_b.resize(0);
+                       m_x.resize(0);
+                       m_lo.resize(0);
+                       m_hi.resize(0);
+               }
+
+               // ii. Setup for multibodies
+
+               dindex = 0;
+
+               m_multiBodyLimitDependencies.resize(numMultiBodyConstraints);
+
+               for (int i = 0; i < m_multiBodyNonContactConstraints.size(); ++i)
+               {
+                       m_multiBodyAllConstraintPtrArray.push_back(&m_multiBodyNonContactConstraints[i]);
+                       m_multiBodyLimitDependencies[dindex++] = -1;
+               }
+
+               firstContactConstraintOffset = dindex;
+
+               // The btSequentialImpulseConstraintSolver moves all friction constraints at the very end, we can also interleave them instead
+               if (interleaveContactAndFriction1)
+               {
+                       for (int i = 0; i < m_multiBodyNormalContactConstraints.size(); ++i)
+                       {
+                               const int numtiBodyNumFrictionPerContact = m_multiBodyNormalContactConstraints.size() == m_multiBodyFrictionContactConstraints.size() ? 1 : 2;
+
+                               m_multiBodyAllConstraintPtrArray.push_back(&m_multiBodyNormalContactConstraints[i]);
+                               m_multiBodyLimitDependencies[dindex++] = -1;
+
+                               btMultiBodySolverConstraint& frictionContactConstraint1 = m_multiBodyFrictionContactConstraints[i * numtiBodyNumFrictionPerContact];
+                               m_multiBodyAllConstraintPtrArray.push_back(&frictionContactConstraint1);
+
+                               const int findex = (frictionContactConstraint1.m_frictionIndex * (1 + numtiBodyNumFrictionPerContact)) + firstContactConstraintOffset;
+
+                               m_multiBodyLimitDependencies[dindex++] = findex;
+
+                               if (numtiBodyNumFrictionPerContact == 2)
+                               {
+                                       btMultiBodySolverConstraint& frictionContactConstraint2 = m_multiBodyFrictionContactConstraints[i * numtiBodyNumFrictionPerContact + 1];
+                                       m_multiBodyAllConstraintPtrArray.push_back(&frictionContactConstraint2);
+
+                                       m_multiBodyLimitDependencies[dindex++] = findex;
+                               }
+                       }
+               }
+               else
+               {
+                       for (int i = 0; i < m_multiBodyNormalContactConstraints.size(); ++i)
+                       {
+                               m_multiBodyAllConstraintPtrArray.push_back(&m_multiBodyNormalContactConstraints[i]);
+                               m_multiBodyLimitDependencies[dindex++] = -1;
+                       }
+                       for (int i = 0; i < m_multiBodyFrictionContactConstraints.size(); ++i)
+                       {
+                               m_multiBodyAllConstraintPtrArray.push_back(&m_multiBodyFrictionContactConstraints[i]);
+                               m_multiBodyLimitDependencies[dindex++] = m_multiBodyFrictionContactConstraints[i].m_frictionIndex + firstContactConstraintOffset;
+                       }
+               }
+
+               if (!m_multiBodyAllConstraintPtrArray.size())
+               {
+                       m_multiBodyA.resize(0, 0);
+                       m_multiBodyB.resize(0);
+                       m_multiBodyX.resize(0);
+                       m_multiBodyLo.resize(0);
+                       m_multiBodyHi.resize(0);
+               }
+       }
+
+       // Construct MLCP terms
+       {
+               BT_PROFILE("createMLCPFast");
+               createMLCPFast(infoGlobal);
+       }
+
+       return btScalar(0);
+}
+
+btScalar btMultiBodyMLCPConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       bool result = true;
+       {
+               BT_PROFILE("solveMLCP");
+               result = solveMLCP(infoGlobal);
+       }
+
+       // Fallback to btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations if the solution isn't valid.
+       if (!result)
+       {
+               m_fallback++;
+               return btMultiBodyConstraintSolver::solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+       }
+
+       {
+               BT_PROFILE("process MLCP results");
+
+               for (int i = 0; i < m_allConstraintPtrArray.size(); ++i)
+               {
+                       const btSolverConstraint& c = *m_allConstraintPtrArray[i];
+
+                       const btScalar deltaImpulse = m_x[i] - c.m_appliedImpulse;
+                       c.m_appliedImpulse = m_x[i];
+
+                       int sbA = c.m_solverBodyIdA;
+                       int sbB = c.m_solverBodyIdB;
+
+                       btSolverBody& solverBodyA = m_tmpSolverBodyPool[sbA];
+                       btSolverBody& solverBodyB = m_tmpSolverBodyPool[sbB];
+
+                       solverBodyA.internalApplyImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+                       solverBodyB.internalApplyImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+
+                       if (infoGlobal.m_splitImpulse)
+                       {
+                               const btScalar deltaPushImpulse = m_xSplit[i] - c.m_appliedPushImpulse;
+                               solverBodyA.internalApplyPushImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaPushImpulse);
+                               solverBodyB.internalApplyPushImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaPushImpulse);
+                               c.m_appliedPushImpulse = m_xSplit[i];
+                       }
+               }
+
+               for (int i = 0; i < m_multiBodyAllConstraintPtrArray.size(); ++i)
+               {
+                       btMultiBodySolverConstraint& c = *m_multiBodyAllConstraintPtrArray[i];
+
+                       const btScalar deltaImpulse = m_multiBodyX[i] - c.m_appliedImpulse;
+                       c.m_appliedImpulse = m_multiBodyX[i];
+
+                       btMultiBody* multiBodyA = c.m_multiBodyA;
+                       if (multiBodyA)
+                       {
+                               const int ndofA = multiBodyA->getNumDofs() + 6;
+                               applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse, c.m_deltaVelAindex, ndofA);
+#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+                               //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
+                               //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
+                               multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse);
+#endif  // DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+                       }
+                       else
+                       {
+                               const int sbA = c.m_solverBodyIdA;
+                               btSolverBody& solverBodyA = m_tmpSolverBodyPool[sbA];
+                               solverBodyA.internalApplyImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+                       }
+
+                       btMultiBody* multiBodyB = c.m_multiBodyB;
+                       if (multiBodyB)
+                       {
+                               const int ndofB = multiBodyB->getNumDofs() + 6;
+                               applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse, c.m_deltaVelBindex, ndofB);
+#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+                               //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
+                               //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
+                               multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse);
+#endif  // DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
+                       }
+                       else
+                       {
+                               const int sbB = c.m_solverBodyIdB;
+                               btSolverBody& solverBodyB = m_tmpSolverBodyPool[sbB];
+                               solverBodyB.internalApplyImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+                       }
+               }
+       }
+
+       return btScalar(0);
+}
+
+btMultiBodyMLCPConstraintSolver::btMultiBodyMLCPConstraintSolver(btMLCPSolverInterface* solver)
+       : m_solver(solver), m_fallback(0)
+{
+       // Do nothing
+}
+
+btMultiBodyMLCPConstraintSolver::~btMultiBodyMLCPConstraintSolver()
+{
+       // Do nothing
+}
+
+void btMultiBodyMLCPConstraintSolver::setMLCPSolver(btMLCPSolverInterface* solver)
+{
+       m_solver = solver;
+}
+
+int btMultiBodyMLCPConstraintSolver::getNumFallbacks() const
+{
+       return m_fallback;
+}
+
+void btMultiBodyMLCPConstraintSolver::setNumFallbacks(int num)
+{
+       m_fallback = num;
+}
+
+btConstraintSolverType btMultiBodyMLCPConstraintSolver::getSolverType() const
+{
+       return BT_MLCP_SOLVER;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h
new file mode 100644 (file)
index 0000000..77fdb86
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2018 Google Inc. http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MULTIBODY_MLCP_CONSTRAINT_SOLVER_H
+#define BT_MULTIBODY_MLCP_CONSTRAINT_SOLVER_H
+
+#include "LinearMath/btMatrixX.h"
+#include "LinearMath/btThreads.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
+
+class btMLCPSolverInterface;
+class btMultiBody;
+
+class btMultiBodyMLCPConstraintSolver : public btMultiBodyConstraintSolver
+{
+protected:
+       /// \name MLCP Formulation for Rigid Bodies
+       /// \{
+
+       /// A matrix in the MLCP formulation
+       btMatrixXu m_A;
+
+       /// b vector in the MLCP formulation.
+       btVectorXu m_b;
+
+       /// Constraint impulse, which is an output of MLCP solving.
+       btVectorXu m_x;
+
+       /// Lower bound of constraint impulse, \c m_x.
+       btVectorXu m_lo;
+
+       /// Upper bound of constraint impulse, \c m_x.
+       btVectorXu m_hi;
+
+       /// \}
+
+       /// \name Cache Variables for Split Impulse for Rigid Bodies
+       /// When using 'split impulse' we solve two separate (M)LCPs
+       /// \{
+
+       /// Split impulse Cache vector corresponding to \c m_b.
+       btVectorXu m_bSplit;
+
+       /// Split impulse cache vector corresponding to \c m_x.
+       btVectorXu m_xSplit;
+
+       /// \}
+
+       /// \name MLCP Formulation for Multibodies
+       /// \{
+
+       /// A matrix in the MLCP formulation
+       btMatrixXu m_multiBodyA;
+
+       /// b vector in the MLCP formulation.
+       btVectorXu m_multiBodyB;
+
+       /// Constraint impulse, which is an output of MLCP solving.
+       btVectorXu m_multiBodyX;
+
+       /// Lower bound of constraint impulse, \c m_x.
+       btVectorXu m_multiBodyLo;
+
+       /// Upper bound of constraint impulse, \c m_x.
+       btVectorXu m_multiBodyHi;
+
+       /// \}
+
+       /// Indices of normal contact constraint associated with frictional contact constraint for rigid bodies.
+       ///
+       /// This is used by the MLCP solver to update the upper bounds of frictional contact impulse given intermediate
+       /// normal contact impulse. For example, i-th element represents the index of a normal constraint that is
+       /// accosiated with i-th frictional contact constraint if i-th constraint is a frictional contact constraint.
+       /// Otherwise, -1.
+       btAlignedObjectArray<int> m_limitDependencies;
+
+       /// Indices of normal contact constraint associated with frictional contact constraint for multibodies.
+       ///
+       /// This is used by the MLCP solver to update the upper bounds of frictional contact impulse given intermediate
+       /// normal contact impulse. For example, i-th element represents the index of a normal constraint that is
+       /// accosiated with i-th frictional contact constraint if i-th constraint is a frictional contact constraint.
+       /// Otherwise, -1.
+       btAlignedObjectArray<int> m_multiBodyLimitDependencies;
+
+       /// Array of all the rigid body constraints
+       btAlignedObjectArray<btSolverConstraint*> m_allConstraintPtrArray;
+
+       /// Array of all the multibody constraints
+       btAlignedObjectArray<btMultiBodySolverConstraint*> m_multiBodyAllConstraintPtrArray;
+
+       /// MLCP solver
+       btMLCPSolverInterface* m_solver;
+
+       /// Count of fallbacks of using btSequentialImpulseConstraintSolver, which happens when the MLCP solver fails.
+       int m_fallback;
+
+       /// \name MLCP Scratch Variables
+       /// The following scratch variables are not stateful -- contents are cleared prior to each use.
+       /// They are only cached here to avoid extra memory allocations and deallocations and to ensure
+       /// that multiple instances of the solver can be run in parallel.
+       ///
+       /// \{
+
+       /// Cache variable for constraint Jacobian matrix.
+       btMatrixXu m_scratchJ3;
+
+       /// Cache variable for constraint Jacobian times inverse mass matrix.
+       btMatrixXu m_scratchJInvM3;
+
+       /// Cache variable for offsets.
+       btAlignedObjectArray<int> m_scratchOfs;
+
+       /// \}
+
+       /// Constructs MLCP terms, which are \c m_A, \c m_b, \c m_lo, and \c m_hi.
+       virtual void createMLCPFast(const btContactSolverInfo& infoGlobal);
+
+       /// Constructs MLCP terms for constraints of two rigid bodies
+       void createMLCPFastRigidBody(const btContactSolverInfo& infoGlobal);
+
+       /// Constructs MLCP terms for constraints of two multi-bodies or one rigid body and one multibody
+       void createMLCPFastMultiBody(const btContactSolverInfo& infoGlobal);
+
+       /// Solves MLCP and returns the success
+       virtual bool solveMLCP(const btContactSolverInfo& infoGlobal);
+
+       // Documentation inherited
+       btScalar solveGroupCacheFriendlySetup(
+               btCollisionObject** bodies,
+               int numBodies,
+               btPersistentManifold** manifoldPtr,
+               int numManifolds,
+               btTypedConstraint** constraints,
+               int numConstraints,
+               const btContactSolverInfo& infoGlobal,
+               btIDebugDraw* debugDrawer) BT_OVERRIDE;
+
+       // Documentation inherited
+       btScalar solveGroupCacheFriendlyIterations(
+               btCollisionObject** bodies,
+               int numBodies,
+               btPersistentManifold** manifoldPtr,
+               int numManifolds,
+               btTypedConstraint** constraints,
+               int numConstraints,
+               const btContactSolverInfo& infoGlobal,
+               btIDebugDraw* debugDrawer) ;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR()
+
+       /// Constructor
+       ///
+       /// \param[in] solver MLCP solver. Assumed it's not null.
+       /// \param[in] maxLCPSize Maximum size of LCP to solve using MLCP solver. If the MLCP size exceeds this number, sequaltial impulse method will be used.
+       explicit btMultiBodyMLCPConstraintSolver(btMLCPSolverInterface* solver);
+
+       /// Destructor
+       virtual ~btMultiBodyMLCPConstraintSolver();
+
+       /// Sets MLCP solver. Assumed it's not null.
+       void setMLCPSolver(btMLCPSolverInterface* solver);
+
+       /// Returns the number of fallbacks of using btSequentialImpulseConstraintSolver, which happens when the MLCP
+       /// solver fails.
+       int getNumFallbacks() const;
+
+       /// Sets the number of fallbacks. This function may be used to reset the number to zero.
+       void setNumFallbacks(int num);
+
+       /// Returns the constraint solver type.
+       virtual btConstraintSolverType getSolverType() const;
+};
+
+#endif  // BT_MULTIBODY_MLCP_CONSTRAINT_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp
new file mode 100644 (file)
index 0000000..f51e69d
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#include "btMultiBodyPoint2Point.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btIDebugDraw.h"
+
+#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
+#define BTMBP2PCONSTRAINT_DIM 3
+#else
+#define BTMBP2PCONSTRAINT_DIM 6
+#endif
+
+btMultiBodyPoint2Point::btMultiBodyPoint2Point(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB)
+       : btMultiBodyConstraint(body, 0, link, -1, BTMBP2PCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_POINT_TO_POINT),
+         m_rigidBodyA(0),
+         m_rigidBodyB(bodyB),
+         m_pivotInA(pivotInA),
+         m_pivotInB(pivotInB)
+{
+       m_data.resize(BTMBP2PCONSTRAINT_DIM);  //at least store the applied impulses
+}
+
+btMultiBodyPoint2Point::btMultiBodyPoint2Point(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB)
+       : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, BTMBP2PCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_POINT_TO_POINT),
+         m_rigidBodyA(0),
+         m_rigidBodyB(0),
+         m_pivotInA(pivotInA),
+         m_pivotInB(pivotInB)
+{
+       m_data.resize(BTMBP2PCONSTRAINT_DIM);  //at least store the applied impulses
+}
+
+void btMultiBodyPoint2Point::finalizeMultiDof()
+{
+       //not implemented yet
+       btAssert(0);
+}
+
+btMultiBodyPoint2Point::~btMultiBodyPoint2Point()
+{
+}
+
+int btMultiBodyPoint2Point::getIslandIdA() const
+{
+       if (m_rigidBodyA)
+               return m_rigidBodyA->getIslandTag();
+
+       if (m_bodyA)
+       {
+               if (m_linkA < 0)
+               {
+                       btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+                       if (col)
+                               return col->getIslandTag();
+               }
+               else
+               {
+                       if (m_bodyA->getLink(m_linkA).m_collider)
+                               return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+int btMultiBodyPoint2Point::getIslandIdB() const
+{
+       if (m_rigidBodyB)
+               return m_rigidBodyB->getIslandTag();
+       if (m_bodyB)
+       {
+               if (m_linkB < 0)
+               {
+                       btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+                       if (col)
+                               return col->getIslandTag();
+               }
+               else
+               {
+                       if (m_bodyB->getLink(m_linkB).m_collider)
+                               return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+void btMultiBodyPoint2Point::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                                                 btMultiBodyJacobianData& data,
+                                                                                                 const btContactSolverInfo& infoGlobal)
+{
+       //      int i=1;
+       int numDim = BTMBP2PCONSTRAINT_DIM;
+       for (int i = 0; i < numDim; i++)
+       {
+               btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+               //memset(&constraintRow,0xffffffff,sizeof(btMultiBodySolverConstraint));
+               constraintRow.m_orgConstraint = this;
+               constraintRow.m_orgDofIndex = i;
+               constraintRow.m_relpos1CrossNormal.setValue(0, 0, 0);
+               constraintRow.m_contactNormal1.setValue(0, 0, 0);
+               constraintRow.m_relpos2CrossNormal.setValue(0, 0, 0);
+               constraintRow.m_contactNormal2.setValue(0, 0, 0);
+               constraintRow.m_angularComponentA.setValue(0, 0, 0);
+               constraintRow.m_angularComponentB.setValue(0, 0, 0);
+
+               constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
+               constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
+
+               btVector3 contactNormalOnB(0, 0, 0);
+#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
+               contactNormalOnB[i] = -1;
+#else
+               contactNormalOnB[i % 3] = -1;
+#endif
+
+               // Convert local points back to world
+               btVector3 pivotAworld = m_pivotInA;
+               if (m_rigidBodyA)
+               {
+                       constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
+                       pivotAworld = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+               }
+               else
+               {
+                       if (m_bodyA)
+                               pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+               }
+               btVector3 pivotBworld = m_pivotInB;
+               if (m_rigidBodyB)
+               {
+                       constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
+                       pivotBworld = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+               }
+               else
+               {
+                       if (m_bodyB)
+                               pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+               }
+
+               btScalar posError = i < 3 ? (pivotAworld - pivotBworld).dot(contactNormalOnB) : 0;
+
+#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
+
+               fillMultiBodyConstraint(constraintRow, data, 0, 0, btVector3(0, 0, 0),
+                                                               contactNormalOnB, pivotAworld, pivotBworld,  //sucks but let it be this way "for the time being"
+                                                               posError,
+                                                               infoGlobal,
+                                                               -m_maxAppliedImpulse, m_maxAppliedImpulse);
+               //@todo: support the case of btMultiBody versus btRigidBody,
+               //see btPoint2PointConstraint::getInfo2NonVirtual
+#else
+               const btVector3 dummy(0, 0, 0);
+
+               btAssert(m_bodyA->isMultiDof());
+
+               btScalar* jac1 = jacobianA(i);
+               const btVector3& normalAng = i >= 3 ? contactNormalOnB : dummy;
+               const btVector3& normalLin = i < 3 ? contactNormalOnB : dummy;
+
+               m_bodyA->filConstraintJacobianMultiDof(m_linkA, pivotAworld, normalAng, normalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
+
+               fillMultiBodyConstraint(constraintRow, data, jac1, 0,
+                                                               dummy, dummy, dummy,  //sucks but let it be this way "for the time being"
+                                                               posError,
+                                                               infoGlobal,
+                                                               -m_maxAppliedImpulse, m_maxAppliedImpulse);
+#endif
+       }
+}
+
+void btMultiBodyPoint2Point::debugDraw(class btIDebugDraw* drawer)
+{
+       btTransform tr;
+       tr.setIdentity();
+
+       if (m_rigidBodyA)
+       {
+               btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+               tr.setOrigin(pivot);
+               drawer->drawTransform(tr, 0.1);
+       }
+       if (m_bodyA)
+       {
+               btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+               tr.setOrigin(pivotAworld);
+               drawer->drawTransform(tr, 0.1);
+       }
+       if (m_rigidBodyB)
+       {
+               // that ideally should draw the same frame
+               btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+               tr.setOrigin(pivot);
+               drawer->drawTransform(tr, 0.1);
+       }
+       if (m_bodyB)
+       {
+               btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+               tr.setOrigin(pivotBworld);
+               drawer->drawTransform(tr, 0.1);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h
new file mode 100644 (file)
index 0000000..ef03a55
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_POINT2POINT_H
+#define BT_MULTIBODY_POINT2POINT_H
+
+#include "btMultiBodyConstraint.h"
+
+//#define BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
+
+ATTRIBUTE_ALIGNED16(class)
+btMultiBodyPoint2Point : public btMultiBodyConstraint
+{
+protected:
+       btRigidBody* m_rigidBodyA;
+       btRigidBody* m_rigidBodyB;
+       btVector3 m_pivotInA;
+       btVector3 m_pivotInB;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btMultiBodyPoint2Point(btMultiBody * body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB);
+       btMultiBodyPoint2Point(btMultiBody * bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB);
+
+       virtual ~btMultiBodyPoint2Point();
+
+       virtual void finalizeMultiDof();
+
+       virtual int getIslandIdA() const;
+       virtual int getIslandIdB() const;
+
+       virtual void createConstraintRows(btMultiBodyConstraintArray & constraintRows,
+                                                                         btMultiBodyJacobianData & data,
+                                                                         const btContactSolverInfo& infoGlobal);
+
+       const btVector3& getPivotInB() const
+       {
+               return m_pivotInB;
+       }
+
+       virtual void setPivotInB(const btVector3& pivotInB)
+       {
+               m_pivotInB = pivotInB;
+       }
+
+       virtual void debugDraw(class btIDebugDraw * drawer);
+};
+
+#endif  //BT_MULTIBODY_POINT2POINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp
new file mode 100644 (file)
index 0000000..48ec1d5
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#include "btMultiBodySliderConstraint.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+#include "LinearMath/btIDebugDraw.h"
+
+#define BTMBSLIDERCONSTRAINT_DIM 5
+#define EPSILON 0.000001
+
+btMultiBodySliderConstraint::btMultiBodySliderConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis)
+       : btMultiBodyConstraint(body, 0, link, -1, BTMBSLIDERCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_SLIDER),
+         m_rigidBodyA(0),
+         m_rigidBodyB(bodyB),
+         m_pivotInA(pivotInA),
+         m_pivotInB(pivotInB),
+         m_frameInA(frameInA),
+         m_frameInB(frameInB),
+         m_jointAxis(jointAxis)
+{
+       m_data.resize(BTMBSLIDERCONSTRAINT_DIM);  //at least store the applied impulses
+}
+
+btMultiBodySliderConstraint::btMultiBodySliderConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis)
+       : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, BTMBSLIDERCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_SLIDER),
+         m_rigidBodyA(0),
+         m_rigidBodyB(0),
+         m_pivotInA(pivotInA),
+         m_pivotInB(pivotInB),
+         m_frameInA(frameInA),
+         m_frameInB(frameInB),
+         m_jointAxis(jointAxis)
+{
+       m_data.resize(BTMBSLIDERCONSTRAINT_DIM);  //at least store the applied impulses
+}
+
+void btMultiBodySliderConstraint::finalizeMultiDof()
+{
+       //not implemented yet
+       btAssert(0);
+}
+
+btMultiBodySliderConstraint::~btMultiBodySliderConstraint()
+{
+}
+
+int btMultiBodySliderConstraint::getIslandIdA() const
+{
+       if (m_rigidBodyA)
+               return m_rigidBodyA->getIslandTag();
+
+       if (m_bodyA)
+       {
+               if (m_linkA < 0)
+               {
+                       btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+                       if (col)
+                               return col->getIslandTag();
+               }
+               else
+               {
+                       if (m_bodyA->getLink(m_linkA).m_collider)
+                               return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+int btMultiBodySliderConstraint::getIslandIdB() const
+{
+       if (m_rigidBodyB)
+               return m_rigidBodyB->getIslandTag();
+       if (m_bodyB)
+       {
+               if (m_linkB < 0)
+               {
+                       btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+                       if (col)
+                               return col->getIslandTag();
+               }
+               else
+               {
+                       if (m_bodyB->getLink(m_linkB).m_collider)
+                               return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+void btMultiBodySliderConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal)
+{
+       // Convert local points back to world
+       btVector3 pivotAworld = m_pivotInA;
+       btMatrix3x3 frameAworld = m_frameInA;
+       btVector3 jointAxis = m_jointAxis;
+       if (m_rigidBodyA)
+       {
+               pivotAworld = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+               frameAworld = m_frameInA.transpose() * btMatrix3x3(m_rigidBodyA->getOrientation());
+               jointAxis = quatRotate(m_rigidBodyA->getOrientation(), m_jointAxis);
+       }
+       else if (m_bodyA)
+       {
+               pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+               frameAworld = m_bodyA->localFrameToWorld(m_linkA, m_frameInA);
+               jointAxis = m_bodyA->localDirToWorld(m_linkA, m_jointAxis);
+       }
+       btVector3 pivotBworld = m_pivotInB;
+       btMatrix3x3 frameBworld = m_frameInB;
+       if (m_rigidBodyB)
+       {
+               pivotBworld = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+               frameBworld = m_frameInB.transpose() * btMatrix3x3(m_rigidBodyB->getOrientation());
+       }
+       else if (m_bodyB)
+       {
+               pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+               frameBworld = m_bodyB->localFrameToWorld(m_linkB, m_frameInB);
+       }
+
+       btVector3 constraintAxis[2];
+       for (int i = 0; i < 3; ++i)
+       {
+               constraintAxis[0] = frameAworld.getColumn(i).cross(jointAxis);
+               if (constraintAxis[0].safeNorm() > EPSILON)
+               {
+                       constraintAxis[0] = constraintAxis[0].normalized();
+                       constraintAxis[1] = jointAxis.cross(constraintAxis[0]);
+                       constraintAxis[1] = constraintAxis[1].normalized();
+                       break;
+               }
+       }
+
+       btMatrix3x3 relRot = frameAworld.inverse() * frameBworld;
+       btVector3 angleDiff;
+       btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot, angleDiff);
+
+       int numDim = BTMBSLIDERCONSTRAINT_DIM;
+       for (int i = 0; i < numDim; i++)
+       {
+               btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+               constraintRow.m_orgConstraint = this;
+               constraintRow.m_orgDofIndex = i;
+               constraintRow.m_relpos1CrossNormal.setValue(0, 0, 0);
+               constraintRow.m_contactNormal1.setValue(0, 0, 0);
+               constraintRow.m_relpos2CrossNormal.setValue(0, 0, 0);
+               constraintRow.m_contactNormal2.setValue(0, 0, 0);
+               constraintRow.m_angularComponentA.setValue(0, 0, 0);
+               constraintRow.m_angularComponentB.setValue(0, 0, 0);
+
+               constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
+               constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
+
+               if (m_rigidBodyA)
+               {
+                       constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
+               }
+               if (m_rigidBodyB)
+               {
+                       constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
+               }
+
+               btVector3 constraintNormalLin(0, 0, 0);
+               btVector3 constraintNormalAng(0, 0, 0);
+               btScalar posError = 0.0;
+               if (i < 2)
+               {
+                       constraintNormalLin = constraintAxis[i];
+                       posError = (pivotAworld - pivotBworld).dot(constraintNormalLin);
+                       fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+                                                                       constraintNormalLin, pivotAworld, pivotBworld,
+                                                                       posError,
+                                                                       infoGlobal,
+                                                                       -m_maxAppliedImpulse, m_maxAppliedImpulse);
+               }
+               else
+               {  //i>=2
+                       constraintNormalAng = frameAworld.getColumn(i % 3);
+                       posError = angleDiff[i % 3];
+                       fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+                                                                       constraintNormalLin, pivotAworld, pivotBworld,
+                                                                       posError,
+                                                                       infoGlobal,
+                                                                       -m_maxAppliedImpulse, m_maxAppliedImpulse, true);
+               }
+       }
+}
+
+void btMultiBodySliderConstraint::debugDraw(class btIDebugDraw* drawer)
+{
+       btTransform tr;
+       tr.setIdentity();
+
+       if (m_rigidBodyA)
+       {
+               btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
+               tr.setOrigin(pivot);
+               drawer->drawTransform(tr, 0.1);
+       }
+       if (m_bodyA)
+       {
+               btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
+               tr.setOrigin(pivotAworld);
+               drawer->drawTransform(tr, 0.1);
+       }
+       if (m_rigidBodyB)
+       {
+               // that ideally should draw the same frame
+               btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
+               tr.setOrigin(pivot);
+               drawer->drawTransform(tr, 0.1);
+       }
+       if (m_bodyB)
+       {
+               btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
+               tr.setOrigin(pivotBworld);
+               drawer->drawTransform(tr, 0.1);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h
new file mode 100644 (file)
index 0000000..b192b6f
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_SLIDER_CONSTRAINT_H
+#define BT_MULTIBODY_SLIDER_CONSTRAINT_H
+
+#include "btMultiBodyConstraint.h"
+
+class btMultiBodySliderConstraint : public btMultiBodyConstraint
+{
+protected:
+       btRigidBody* m_rigidBodyA;
+       btRigidBody* m_rigidBodyB;
+       btVector3 m_pivotInA;
+       btVector3 m_pivotInB;
+       btMatrix3x3 m_frameInA;
+       btMatrix3x3 m_frameInB;
+       btVector3 m_jointAxis;
+
+public:
+       btMultiBodySliderConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis);
+       btMultiBodySliderConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis);
+
+       virtual ~btMultiBodySliderConstraint();
+
+       virtual void finalizeMultiDof();
+
+       virtual int getIslandIdA() const;
+       virtual int getIslandIdB() const;
+
+       virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                         btMultiBodyJacobianData& data,
+                                                                         const btContactSolverInfo& infoGlobal);
+
+       const btVector3& getPivotInA() const
+       {
+               return m_pivotInA;
+       }
+
+       void setPivotInA(const btVector3& pivotInA)
+       {
+               m_pivotInA = pivotInA;
+       }
+
+       const btVector3& getPivotInB() const
+       {
+               return m_pivotInB;
+       }
+
+       virtual void setPivotInB(const btVector3& pivotInB)
+       {
+               m_pivotInB = pivotInB;
+       }
+
+       const btMatrix3x3& getFrameInA() const
+       {
+               return m_frameInA;
+       }
+
+       void setFrameInA(const btMatrix3x3& frameInA)
+       {
+               m_frameInA = frameInA;
+       }
+
+       const btMatrix3x3& getFrameInB() const
+       {
+               return m_frameInB;
+       }
+
+       virtual void setFrameInB(const btMatrix3x3& frameInB)
+       {
+               m_frameInB = frameInB;
+       }
+
+       const btVector3& getJointAxis() const
+       {
+               return m_jointAxis;
+       }
+
+       void setJointAxis(const btVector3& jointAxis)
+       {
+               m_jointAxis = jointAxis;
+       }
+
+       virtual void debugDraw(class btIDebugDraw* drawer);
+};
+
+#endif  //BT_MULTIBODY_SLIDER_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h
new file mode 100644 (file)
index 0000000..deed3e2
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MULTIBODY_SOLVER_CONSTRAINT_H
+#define BT_MULTIBODY_SOLVER_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+class btMultiBody;
+class btMultiBodyConstraint;
+#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
+ATTRIBUTE_ALIGNED16(struct)
+btMultiBodySolverConstraint
+{
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btMultiBodySolverConstraint() : m_solverBodyIdA(-1), m_multiBodyA(0), m_linkA(-1), m_solverBodyIdB(-1), m_multiBodyB(0), m_linkB(-1), m_orgConstraint(0), m_orgDofIndex(-1)
+       {
+       }
+
+       int m_deltaVelAindex;  //more generic version of m_relpos1CrossNormal/m_contactNormal1
+       int m_jacAindex;
+       int m_deltaVelBindex;
+       int m_jacBindex;
+
+       btVector3 m_relpos1CrossNormal;
+       btVector3 m_contactNormal1;
+       btVector3 m_relpos2CrossNormal;
+       btVector3 m_contactNormal2;  //usually m_contactNormal2 == -m_contactNormal1, but not always
+
+       btVector3 m_angularComponentA;
+       btVector3 m_angularComponentB;
+
+       mutable btSimdScalar m_appliedPushImpulse;
+       mutable btSimdScalar m_appliedImpulse;
+
+       btScalar m_friction;
+       btScalar m_jacDiagABInv;
+       btScalar m_rhs;
+       btScalar m_cfm;
+
+       btScalar m_lowerLimit;
+       btScalar m_upperLimit;
+       btScalar m_rhsPenetration;
+       union {
+               void* m_originalContactPoint;
+               btScalar m_unusedPadding4;
+       };
+
+       int m_overrideNumSolverIterations;
+       int m_frictionIndex;
+
+       int m_solverBodyIdA;
+       btMultiBody* m_multiBodyA;
+       int m_linkA;
+
+       int m_solverBodyIdB;
+       btMultiBody* m_multiBodyB;
+       int m_linkB;
+
+       //for writing back applied impulses
+       btMultiBodyConstraint* m_orgConstraint;
+       int m_orgDofIndex;
+
+       enum btSolverConstraintType
+       {
+               BT_SOLVER_CONTACT_1D = 0,
+               BT_SOLVER_FRICTION_1D
+       };
+};
+
+typedef btAlignedObjectArray<btMultiBodySolverConstraint> btMultiBodyConstraintArray;
+
+#endif  //BT_MULTIBODY_SOLVER_CONSTRAINT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointLimit.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointLimit.cpp
new file mode 100644 (file)
index 0000000..27c7520
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2018 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#include "btMultiBodySphericalJointLimit.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "LinearMath/btTransformUtil.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+#include "LinearMath/btIDebugDraw.h"
+
+btMultiBodySphericalJointLimit::btMultiBodySphericalJointLimit(btMultiBody* body, int link, 
+       btScalar swingxRange,
+       btScalar swingyRange,
+       btScalar twistRange,
+       btScalar maxAppliedImpulse)
+       : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 3, true, MULTIBODY_CONSTRAINT_SPHERICAL_LIMIT),
+       m_desiredVelocity(0, 0, 0),
+       m_desiredPosition(0,0,0,1),
+       m_use_multi_dof_params(false),
+       m_kd(1., 1., 1.),
+       m_kp(0.2, 0.2, 0.2),
+       m_erp(1),
+       m_rhsClamp(SIMD_INFINITY),
+       m_maxAppliedImpulseMultiDof(maxAppliedImpulse, maxAppliedImpulse, maxAppliedImpulse),
+       m_pivotA(m_bodyA->getLink(link).m_eVector),
+       m_pivotB(m_bodyB->getLink(link).m_eVector),
+       m_swingxRange(swingxRange),
+       m_swingyRange(swingyRange),
+       m_twistRange(twistRange)
+
+{
+
+       m_maxAppliedImpulse = maxAppliedImpulse;
+}
+
+
+void btMultiBodySphericalJointLimit::finalizeMultiDof()
+{
+       allocateJacobiansMultiDof();
+       // note: we rely on the fact that data.m_jacobians are
+       // always initialized to zero by the Constraint ctor
+       int linkDoF = 0;
+       unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
+
+       // row 0: the lower bound
+       // row 0: the lower bound
+       jacobianA(0)[offset] = 1;
+
+       jacobianB(1)[offset] = -1;
+
+       m_numDofsFinalized = m_jacSizeBoth;
+}
+
+
+btMultiBodySphericalJointLimit::~btMultiBodySphericalJointLimit()
+{
+}
+
+int btMultiBodySphericalJointLimit::getIslandIdA() const
+{
+       if (this->m_linkA < 0)
+       {
+               btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+               if (col)
+                       return col->getIslandTag();
+       }
+       else
+       {
+               if (m_bodyA->getLink(m_linkA).m_collider)
+               {
+                       return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+int btMultiBodySphericalJointLimit::getIslandIdB() const
+{
+       if (m_linkB < 0)
+       {
+               btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+               if (col)
+                       return col->getIslandTag();
+       }
+       else
+       {
+               if (m_bodyB->getLink(m_linkB).m_collider)
+               {
+                       return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+void btMultiBodySphericalJointLimit::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                                                btMultiBodyJacobianData& data,
+                                                                                                const btContactSolverInfo& infoGlobal)
+{
+       // only positions need to be updated -- data.m_jacobians and force
+       // directions were set in the ctor and never change.
+
+       if (m_numDofsFinalized != m_jacSizeBoth)
+       {
+               finalizeMultiDof();
+       }
+
+       //don't crash
+       if (m_numDofsFinalized != m_jacSizeBoth)
+               return;
+       
+
+       if (m_maxAppliedImpulse == 0.f)
+               return;
+
+       const btScalar posError = 0;
+       const btVector3 zero(0, 0, 0);
+
+       
+       btVector3 axis[3] = { btVector3(1, 0, 0), btVector3(0, 1, 0), btVector3(0, 0, 1) };
+       
+       btQuaternion currentQuat(m_bodyA->getJointPosMultiDof(m_linkA)[0],
+               m_bodyA->getJointPosMultiDof(m_linkA)[1],
+               m_bodyA->getJointPosMultiDof(m_linkA)[2],
+               m_bodyA->getJointPosMultiDof(m_linkA)[3]);
+
+       btQuaternion refQuat = m_desiredPosition;
+       btVector3 vTwist(0,0,1);
+       
+       btVector3 vConeNoTwist = quatRotate(currentQuat, vTwist);
+       vConeNoTwist.normalize();
+       btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist);
+       qABCone.normalize();
+       btQuaternion qABTwist = qABCone.inverse() * currentQuat;
+       qABTwist.normalize();
+       btQuaternion desiredQuat = qABTwist;
+
+
+       btQuaternion relRot = currentQuat.inverse() * desiredQuat;
+       btVector3 angleDiff;
+       btGeneric6DofSpring2Constraint::matrixToEulerXYZ(btMatrix3x3(relRot), angleDiff);
+       
+       btScalar limitRanges[3] = {m_swingxRange, m_swingyRange, m_twistRange};
+       
+       /// twist axis/angle
+       btQuaternion qMinTwist = qABTwist;
+       btScalar twistAngle = qABTwist.getAngle();
+
+       if (twistAngle > SIMD_PI)  // long way around. flip quat and recalculate.
+       {
+               qMinTwist = -(qABTwist);
+               twistAngle = qMinTwist.getAngle();
+       }
+       btVector3 vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z());
+       if (twistAngle > SIMD_EPSILON)
+               vTwistAxis.normalize();
+       
+       if (vTwistAxis.dot(vTwist)<0)
+               twistAngle*=-1.;
+
+       angleDiff[2] = twistAngle;
+
+
+       for (int row = 0; row < getNumRows(); row++)
+       {
+               btScalar allowed = limitRanges[row];
+               btScalar damp = 1;
+               if((angleDiff[row]>-allowed)&&(angleDiff[row]<allowed))
+               {
+                       angleDiff[row]=0;
+                       damp=0;
+
+               } else
+               {
+                       if (angleDiff[row]>allowed)
+                       {
+                               angleDiff[row]-=allowed;
+                               
+                       }
+                       if (angleDiff[row]<-allowed)
+                       {
+                               angleDiff[row]+=allowed;
+                               
+                       } 
+               }
+               
+
+               int dof = row;
+               
+               btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
+               btScalar desiredVelocity = this->m_desiredVelocity[row];
+               
+               double kd = m_use_multi_dof_params ? m_kd[row % 3] : m_kd[0];
+               btScalar velocityError = (desiredVelocity - currentVelocity) * kd;
+
+               btMatrix3x3 frameAworld;
+               frameAworld.setIdentity();
+               frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
+               btScalar posError = 0;
+               {
+                       btAssert(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eSpherical);
+                       switch (m_bodyA->getLink(m_linkA).m_jointType)
+                       {
+                               case btMultibodyLink::eSpherical:
+                               {
+                                       btVector3 constraintNormalAng = frameAworld.getColumn(row % 3);
+                                       double kp = m_use_multi_dof_params ? m_kp[row % 3] : m_kp[0];
+                                       posError = kp*angleDiff[row % 3];
+                                       double max_applied_impulse = m_use_multi_dof_params ? m_maxAppliedImpulseMultiDof[row % 3] : m_maxAppliedImpulse;
+                                       //should multiply by time step
+                                       //max_applied_impulse *= infoGlobal.m_timeStep
+
+                                       double min_applied_impulse = -max_applied_impulse;
+                                       
+
+                                       if (posError>0)
+                                               max_applied_impulse=0;
+                                       else
+                                               min_applied_impulse=0;
+
+                                       if (btFabs(posError)>SIMD_EPSILON)
+                                       {
+                                               btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+                                               fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+                                                       zero, zero, zero,//pure angular, so zero out linear parts
+                                                       posError,
+                                                       infoGlobal,
+                                                       min_applied_impulse, max_applied_impulse, true,
+                                                       1.0, false, 0, 0,
+                                                       damp);
+                                               constraintRow.m_orgConstraint = this;
+                                               constraintRow.m_orgDofIndex = row;
+                                       }
+                                       break;
+                               }
+                               default:
+                               {
+                                       btAssert(0);
+                               }
+                       };
+               }
+       }
+}
+
+
+void btMultiBodySphericalJointLimit::debugDraw(class btIDebugDraw* drawer)
+{
+       btTransform tr;
+       tr.setIdentity();
+       if (m_bodyB)
+       {
+               btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotB);
+               tr.setOrigin(pivotBworld);
+               drawer->drawTransform(tr, 0.1);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointLimit.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointLimit.h
new file mode 100644 (file)
index 0000000..b82db6a
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2018 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_SPHERICAL_JOINT_LIMIT_H
+#define BT_MULTIBODY_SPHERICAL_JOINT_LIMIT_H
+
+#include "btMultiBodyConstraint.h"
+struct btSolverInfo;
+
+class btMultiBodySphericalJointLimit : public btMultiBodyConstraint
+{
+protected:
+       btVector3 m_desiredVelocity;
+       btQuaternion m_desiredPosition;
+       bool m_use_multi_dof_params;
+       btVector3 m_kd;
+       btVector3 m_kp;
+       btScalar m_erp;
+       btScalar m_rhsClamp;  //maximum error
+       btVector3 m_maxAppliedImpulseMultiDof;
+       btVector3 m_pivotA;
+       btVector3 m_pivotB;
+       btScalar m_swingxRange;
+       btScalar m_swingyRange;
+       btScalar m_twistRange;
+
+public:
+       btMultiBodySphericalJointLimit(btMultiBody* body, int link, 
+               btScalar swingxRange,
+               btScalar swingyRange,
+               btScalar twistRange,
+               btScalar maxAppliedImpulse);
+       
+       virtual ~btMultiBodySphericalJointLimit();
+       virtual void finalizeMultiDof();
+
+       virtual int getIslandIdA() const;
+       virtual int getIslandIdB() const;
+
+       virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                         btMultiBodyJacobianData& data,
+                                                                         const btContactSolverInfo& infoGlobal);
+
+       virtual void setVelocityTarget(const btVector3& velTarget, btScalar kd = 1.0)
+       {
+               m_desiredVelocity = velTarget;
+               m_kd = btVector3(kd, kd, kd);
+               m_use_multi_dof_params = false;
+       }
+
+       virtual void setVelocityTargetMultiDof(const btVector3& velTarget, const btVector3& kd = btVector3(1.0, 1.0, 1.0))
+       {
+               m_desiredVelocity = velTarget;
+               m_kd = kd;
+               m_use_multi_dof_params = true;
+       }
+
+       virtual void setPositionTarget(const btQuaternion& posTarget, btScalar kp =1.f)
+       {
+               m_desiredPosition = posTarget;
+               m_kp = btVector3(kp, kp, kp);
+               m_use_multi_dof_params = false;
+       }
+
+       virtual void setPositionTargetMultiDof(const btQuaternion& posTarget, const btVector3& kp = btVector3(1.f, 1.f, 1.f))
+       {
+               m_desiredPosition = posTarget;
+               m_kp = kp;
+               m_use_multi_dof_params = true;
+       }
+
+       virtual void setErp(btScalar erp)
+       {
+               m_erp = erp;
+       }
+       virtual btScalar getErp() const
+       {
+               return m_erp;
+       }
+       virtual void setRhsClamp(btScalar rhsClamp)
+       {
+               m_rhsClamp = rhsClamp;
+       }
+
+       btScalar getMaxAppliedImpulseMultiDof(int i) const
+       {
+               return m_maxAppliedImpulseMultiDof[i];
+       }
+
+       void setMaxAppliedImpulseMultiDof(const btVector3& maxImp)
+       {
+               m_maxAppliedImpulseMultiDof = maxImp;
+               m_use_multi_dof_params = true;
+       }
+
+
+       virtual void debugDraw(class btIDebugDraw* drawer);
+
+};
+
+#endif  //BT_MULTIBODY_SPHERICAL_JOINT_LIMIT_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp
new file mode 100644 (file)
index 0000000..00a7ef3
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2018 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#include "btMultiBodySphericalJointMotor.h"
+#include "btMultiBody.h"
+#include "btMultiBodyLinkCollider.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "LinearMath/btTransformUtil.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
+
+btMultiBodySphericalJointMotor::btMultiBodySphericalJointMotor(btMultiBody* body, int link, btScalar maxMotorImpulse)
+       : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 3, true, MULTIBODY_CONSTRAINT_SPHERICAL_MOTOR),
+       m_desiredVelocity(0, 0, 0),
+       m_desiredPosition(0,0,0,1),
+       m_use_multi_dof_params(false),
+       m_kd(1., 1., 1.),
+       m_kp(0.2, 0.2, 0.2),
+       m_erp(1),
+       m_rhsClamp(SIMD_INFINITY),
+       m_maxAppliedImpulseMultiDof(maxMotorImpulse, maxMotorImpulse, maxMotorImpulse),
+       m_damping(1.0, 1.0, 1.0)
+{
+
+       m_maxAppliedImpulse = maxMotorImpulse;
+}
+
+
+void btMultiBodySphericalJointMotor::finalizeMultiDof()
+{
+       allocateJacobiansMultiDof();
+       // note: we rely on the fact that data.m_jacobians are
+       // always initialized to zero by the Constraint ctor
+       int linkDoF = 0;
+       unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
+
+       // row 0: the lower bound
+       // row 0: the lower bound
+       jacobianA(0)[offset] = 1;
+
+       m_numDofsFinalized = m_jacSizeBoth;
+}
+
+
+btMultiBodySphericalJointMotor::~btMultiBodySphericalJointMotor()
+{
+}
+
+int btMultiBodySphericalJointMotor::getIslandIdA() const
+{
+       if (this->m_linkA < 0)
+       {
+               btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
+               if (col)
+                       return col->getIslandTag();
+       }
+       else
+       {
+               if (m_bodyA->getLink(m_linkA).m_collider)
+               {
+                       return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+int btMultiBodySphericalJointMotor::getIslandIdB() const
+{
+       if (m_linkB < 0)
+       {
+               btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
+               if (col)
+                       return col->getIslandTag();
+       }
+       else
+       {
+               if (m_bodyB->getLink(m_linkB).m_collider)
+               {
+                       return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
+               }
+       }
+       return -1;
+}
+
+void btMultiBodySphericalJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                                                btMultiBodyJacobianData& data,
+                                                                                                const btContactSolverInfo& infoGlobal)
+{
+       // only positions need to be updated -- data.m_jacobians and force
+       // directions were set in the ctor and never change.
+
+       if (m_numDofsFinalized != m_jacSizeBoth)
+       {
+               finalizeMultiDof();
+       }
+
+       //don't crash
+       if (m_numDofsFinalized != m_jacSizeBoth)
+               return;
+       
+
+       if (m_maxAppliedImpulse == 0.f)
+               return;
+
+       const btScalar posError = 0;
+       const btVector3 dummy(0, 0, 0);
+
+       
+       btVector3 axis[3] = { btVector3(1, 0, 0), btVector3(0, 1, 0), btVector3(0, 0, 1) };
+       
+       btQuaternion desiredQuat = m_desiredPosition;
+       btQuaternion currentQuat(m_bodyA->getJointPosMultiDof(m_linkA)[0],
+               m_bodyA->getJointPosMultiDof(m_linkA)[1],
+               m_bodyA->getJointPosMultiDof(m_linkA)[2],
+               m_bodyA->getJointPosMultiDof(m_linkA)[3]);
+
+btQuaternion relRot = currentQuat.inverse() * desiredQuat;
+       btVector3 angleDiff;
+       btGeneric6DofSpring2Constraint::matrixToEulerXYZ(btMatrix3x3(relRot), angleDiff);
+
+
+
+       for (int row = 0; row < getNumRows(); row++)
+       {
+               btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
+
+               int dof = row;
+               
+               btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
+               btScalar desiredVelocity = this->m_desiredVelocity[row];
+               
+               double kd = m_use_multi_dof_params ? m_kd[row % 3] : m_kd[0];
+               btScalar velocityError = (desiredVelocity - currentVelocity) * kd;
+
+               btMatrix3x3 frameAworld;
+               frameAworld.setIdentity();
+               frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
+               btScalar posError = 0;
+               {
+                       btAssert(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eSpherical);
+                       switch (m_bodyA->getLink(m_linkA).m_jointType)
+                       {
+                               case btMultibodyLink::eSpherical:
+                               {
+                                       btVector3 constraintNormalAng = frameAworld.getColumn(row % 3);
+                                       double kp = m_use_multi_dof_params ? m_kp[row % 3] : m_kp[0];
+                                       posError = kp*angleDiff[row % 3];
+                                       double max_applied_impulse = m_use_multi_dof_params ? m_maxAppliedImpulseMultiDof[row % 3] : m_maxAppliedImpulse;
+                                       fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
+                                               btVector3(0,0,0), dummy, dummy,
+                                               posError,
+                                               infoGlobal,
+                                               -max_applied_impulse, max_applied_impulse, true,
+                                               1.0, false, 0, 0,
+                                               m_damping[row % 3]);
+                                       constraintRow.m_orgConstraint = this;
+                                       constraintRow.m_orgDofIndex = row;
+                                       break;
+                               }
+                               default:
+                               {
+                                       btAssert(0);
+                               }
+                       };
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h
new file mode 100644 (file)
index 0000000..bdeccc2
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2018 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 written by Erwin Coumans
+
+#ifndef BT_MULTIBODY_SPHERICAL_JOINT_MOTOR_H
+#define BT_MULTIBODY_SPHERICAL_JOINT_MOTOR_H
+
+#include "btMultiBodyConstraint.h"
+struct btSolverInfo;
+
+class btMultiBodySphericalJointMotor : public btMultiBodyConstraint
+{
+protected:
+       btVector3 m_desiredVelocity;
+       btQuaternion m_desiredPosition;
+       bool m_use_multi_dof_params;
+       btVector3 m_kd;
+       btVector3 m_kp;
+       btScalar m_erp;
+       btScalar m_rhsClamp;  //maximum error
+       btVector3 m_maxAppliedImpulseMultiDof;
+       btVector3 m_damping;
+
+public:
+       btMultiBodySphericalJointMotor(btMultiBody* body, int link, btScalar maxMotorImpulse);
+       
+       virtual ~btMultiBodySphericalJointMotor();
+       virtual void finalizeMultiDof();
+
+       virtual int getIslandIdA() const;
+       virtual int getIslandIdB() const;
+
+       virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
+                                                                         btMultiBodyJacobianData& data,
+                                                                         const btContactSolverInfo& infoGlobal);
+
+       virtual void setVelocityTarget(const btVector3& velTarget, btScalar kd = 1.0)
+       {
+               m_desiredVelocity = velTarget;
+               m_kd = btVector3(kd, kd, kd);
+               m_use_multi_dof_params = false;
+       }
+
+       virtual void setVelocityTargetMultiDof(const btVector3& velTarget, const btVector3& kd = btVector3(1.0, 1.0, 1.0))
+       {
+               m_desiredVelocity = velTarget;
+               m_kd = kd;
+               m_use_multi_dof_params = true;
+       }
+
+       virtual void setPositionTarget(const btQuaternion& posTarget, btScalar kp =1.f)
+       {
+               m_desiredPosition = posTarget;
+               m_kp = btVector3(kp, kp, kp);
+               m_use_multi_dof_params = false;
+       }
+
+       virtual void setPositionTargetMultiDof(const btQuaternion& posTarget, const btVector3& kp = btVector3(1.f, 1.f, 1.f))
+       {
+               m_desiredPosition = posTarget;
+               m_kp = kp;
+               m_use_multi_dof_params = true;
+       }
+
+       virtual void setErp(btScalar erp)
+       {
+               m_erp = erp;
+       }
+       virtual btScalar getErp() const
+       {
+               return m_erp;
+       }
+       virtual void setRhsClamp(btScalar rhsClamp)
+       {
+               m_rhsClamp = rhsClamp;
+       }
+
+       btScalar getMaxAppliedImpulseMultiDof(int i) const
+       {
+               return m_maxAppliedImpulseMultiDof[i];
+       }
+
+       void setMaxAppliedImpulseMultiDof(const btVector3& maxImp)
+       {
+               m_maxAppliedImpulseMultiDof = maxImp;
+               m_use_multi_dof_params = true;
+       }
+
+       btScalar getDamping(int i) const
+       {
+               return m_damping[i];
+       }
+
+       void setDamping(const btVector3& damping)
+       {
+               m_damping = damping;
+       }
+
+       virtual void debugDraw(class btIDebugDraw* drawer)
+       {
+               //todo(erwincoumans)
+       }
+};
+
+#endif  //BT_MULTIBODY_SPHERICAL_JOINT_MOTOR_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp
new file mode 100644 (file)
index 0000000..98ecdc0
--- /dev/null
@@ -0,0 +1,2158 @@
+/*************************************************************************
+*                                                                       *
+* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+* All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+*                                                                       *
+* This library is free software; you can redistribute it and/or         *
+* modify it under the terms of EITHER:                                  *
+*   (1) The GNU Lesser General Public License as published by the Free  *
+*       Software Foundation; either version 2.1 of the License, or (at  *
+*       your option) any later version. The text of the GNU Lesser      *
+*       General Public License is included with this library in the     *
+*       file LICENSE.TXT.                                               *
+*   (2) The BSD-style license that is included with this library in     *
+*       the file LICENSE-BSD.TXT.                                       *
+*                                                                       *
+* This library is distributed in the hope that it will be useful,       *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+* LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+*                                                                       *
+*************************************************************************/
+
+/*
+
+
+THE ALGORITHM
+-------------
+
+solve A*x = b+w, with x and w subject to certain LCP conditions.
+each x(i),w(i) must lie on one of the three line segments in the following
+diagram. each line segment corresponds to one index set :
+
+     w(i)
+     /|\      |           :
+      |       |           :
+      |       |i in N     :
+  w>0 |       |state[i]=0 :
+      |       |           :
+      |       |           :  i in C
+  w=0 +       +-----------------------+
+      |                   :           |
+      |                   :           |
+  w<0 |                   :           |i in N
+      |                   :           |state[i]=1
+      |                   :           |
+      |                   :           |
+      +-------|-----------|-----------|----------> x(i)
+             lo           0           hi
+
+the Dantzig algorithm proceeds as follows:
+  for i=1:n
+    * if (x(i),w(i)) is not on the line, push x(i) and w(i) positive or
+      negative towards the line. as this is done, the other (x(j),w(j))
+      for j<i are constrained to be on the line. if any (x,w) reaches the
+      end of a line segment then it is switched between index sets.
+    * i is added to the appropriate index set depending on what line segment
+      it hits.
+
+we restrict lo(i) <= 0 and hi(i) >= 0. this makes the algorithm a bit
+simpler, because the starting point for x(i),w(i) is always on the dotted
+line x=0 and x will only ever increase in one direction, so it can only hit
+two out of the three line segments.
+
+
+NOTES
+-----
+
+this is an implementation of "lcp_dantzig2_ldlt.m" and "lcp_dantzig_lohi.m".
+the implementation is split into an LCP problem object (btLCP) and an LCP
+driver function. most optimization occurs in the btLCP object.
+
+a naive implementation of the algorithm requires either a lot of data motion
+or a lot of permutation-array lookup, because we are constantly re-ordering
+rows and columns. to avoid this and make a more optimized algorithm, a
+non-trivial data structure is used to represent the matrix A (this is
+implemented in the fast version of the btLCP object).
+
+during execution of this algorithm, some indexes in A are clamped (set C),
+some are non-clamped (set N), and some are "don't care" (where x=0).
+A,x,b,w (and other problem vectors) are permuted such that the clamped
+indexes are first, the unclamped indexes are next, and the don't-care
+indexes are last. this permutation is recorded in the array `p'.
+initially p = 0..n-1, and as the rows and columns of A,x,b,w are swapped,
+the corresponding elements of p are swapped.
+
+because the C and N elements are grouped together in the rows of A, we can do
+lots of work with a fast dot product function. if A,x,etc were not permuted
+and we only had a permutation array, then those dot products would be much
+slower as we would have a permutation array lookup in some inner loops.
+
+A is accessed through an array of row pointers, so that element (i,j) of the
+permuted matrix is A[i][j]. this makes row swapping fast. for column swapping
+we still have to actually move the data.
+
+during execution of this algorithm we maintain an L*D*L' factorization of
+the clamped submatrix of A (call it `AC') which is the top left nC*nC
+submatrix of A. there are two ways we could arrange the rows/columns in AC.
+
+(1) AC is always permuted such that L*D*L' = AC. this causes a problem
+when a row/column is removed from C, because then all the rows/columns of A
+between the deleted index and the end of C need to be rotated downward.
+this results in a lot of data motion and slows things down.
+(2) L*D*L' is actually a factorization of a *permutation* of AC (which is
+itself a permutation of the underlying A). this is what we do - the
+permutation is recorded in the vector C. call this permutation A[C,C].
+when a row/column is removed from C, all we have to do is swap two
+rows/columns and manipulate C.
+
+*/
+
+#include "btDantzigLCP.h"
+
+#include <string.h>  //memcpy
+
+bool s_error = false;
+
+//***************************************************************************
+// code generation parameters
+
+#define btLCP_FAST  // use fast btLCP object
+
+// option 1 : matrix row pointers (less data copying)
+#define BTROWPTRS
+#define BTATYPE btScalar **
+#define BTAROW(i) (m_A[i])
+
+// option 2 : no matrix row pointers (slightly faster inner loops)
+//#define NOROWPTRS
+//#define BTATYPE btScalar *
+//#define BTAROW(i) (m_A+(i)*m_nskip)
+
+#define BTNUB_OPTIMIZATIONS
+
+/* solve L*X=B, with B containing 1 right hand sides.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * B is an n*1 matrix that contains the right hand sides.
+ * B is stored by columns and its leading dimension is also lskip.
+ * B is overwritten with X.
+ * this processes blocks of 2*2.
+ * if this is in the factorizer source file, n must be a multiple of 2.
+ */
+
+static void btSolveL1_1(const btScalar *L, btScalar *B, int n, int lskip1)
+{
+       /* declare variables - Z matrix, p and q vectors, etc */
+       btScalar Z11, m11, Z21, m21, p1, q1, p2, *ex;
+       const btScalar *ell;
+       int i, j;
+       /* compute all 2 x 1 blocks of X */
+       for (i = 0; i < n; i += 2)
+       {
+               /* compute all 2 x 1 block of X, from rows i..i+2-1 */
+               /* set the Z matrix to 0 */
+               Z11 = 0;
+               Z21 = 0;
+               ell = L + i * lskip1;
+               ex = B;
+               /* the inner loop that computes outer products and adds them to Z */
+               for (j = i - 2; j >= 0; j -= 2)
+               {
+                       /* compute outer product and add it to the Z matrix */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       m11 = p1 * q1;
+                       p2 = ell[lskip1];
+                       m21 = p2 * q1;
+                       Z11 += m11;
+                       Z21 += m21;
+                       /* compute outer product and add it to the Z matrix */
+                       p1 = ell[1];
+                       q1 = ex[1];
+                       m11 = p1 * q1;
+                       p2 = ell[1 + lskip1];
+                       m21 = p2 * q1;
+                       /* advance pointers */
+                       ell += 2;
+                       ex += 2;
+                       Z11 += m11;
+                       Z21 += m21;
+                       /* end of inner loop */
+               }
+               /* compute left-over iterations */
+               j += 2;
+               for (; j > 0; j--)
+               {
+                       /* compute outer product and add it to the Z matrix */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       m11 = p1 * q1;
+                       p2 = ell[lskip1];
+                       m21 = p2 * q1;
+                       /* advance pointers */
+                       ell += 1;
+                       ex += 1;
+                       Z11 += m11;
+                       Z21 += m21;
+               }
+               /* finish computing the X(i) block */
+               Z11 = ex[0] - Z11;
+               ex[0] = Z11;
+               p1 = ell[lskip1];
+               Z21 = ex[1] - Z21 - p1 * Z11;
+               ex[1] = Z21;
+               /* end of outer loop */
+       }
+}
+
+/* solve L*X=B, with B containing 2 right hand sides.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * B is an n*2 matrix that contains the right hand sides.
+ * B is stored by columns and its leading dimension is also lskip.
+ * B is overwritten with X.
+ * this processes blocks of 2*2.
+ * if this is in the factorizer source file, n must be a multiple of 2.
+ */
+
+static void btSolveL1_2(const btScalar *L, btScalar *B, int n, int lskip1)
+{
+       /* declare variables - Z matrix, p and q vectors, etc */
+       btScalar Z11, m11, Z12, m12, Z21, m21, Z22, m22, p1, q1, p2, q2, *ex;
+       const btScalar *ell;
+       int i, j;
+       /* compute all 2 x 2 blocks of X */
+       for (i = 0; i < n; i += 2)
+       {
+               /* compute all 2 x 2 block of X, from rows i..i+2-1 */
+               /* set the Z matrix to 0 */
+               Z11 = 0;
+               Z12 = 0;
+               Z21 = 0;
+               Z22 = 0;
+               ell = L + i * lskip1;
+               ex = B;
+               /* the inner loop that computes outer products and adds them to Z */
+               for (j = i - 2; j >= 0; j -= 2)
+               {
+                       /* compute outer product and add it to the Z matrix */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       m11 = p1 * q1;
+                       q2 = ex[lskip1];
+                       m12 = p1 * q2;
+                       p2 = ell[lskip1];
+                       m21 = p2 * q1;
+                       m22 = p2 * q2;
+                       Z11 += m11;
+                       Z12 += m12;
+                       Z21 += m21;
+                       Z22 += m22;
+                       /* compute outer product and add it to the Z matrix */
+                       p1 = ell[1];
+                       q1 = ex[1];
+                       m11 = p1 * q1;
+                       q2 = ex[1 + lskip1];
+                       m12 = p1 * q2;
+                       p2 = ell[1 + lskip1];
+                       m21 = p2 * q1;
+                       m22 = p2 * q2;
+                       /* advance pointers */
+                       ell += 2;
+                       ex += 2;
+                       Z11 += m11;
+                       Z12 += m12;
+                       Z21 += m21;
+                       Z22 += m22;
+                       /* end of inner loop */
+               }
+               /* compute left-over iterations */
+               j += 2;
+               for (; j > 0; j--)
+               {
+                       /* compute outer product and add it to the Z matrix */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       m11 = p1 * q1;
+                       q2 = ex[lskip1];
+                       m12 = p1 * q2;
+                       p2 = ell[lskip1];
+                       m21 = p2 * q1;
+                       m22 = p2 * q2;
+                       /* advance pointers */
+                       ell += 1;
+                       ex += 1;
+                       Z11 += m11;
+                       Z12 += m12;
+                       Z21 += m21;
+                       Z22 += m22;
+               }
+               /* finish computing the X(i) block */
+               Z11 = ex[0] - Z11;
+               ex[0] = Z11;
+               Z12 = ex[lskip1] - Z12;
+               ex[lskip1] = Z12;
+               p1 = ell[lskip1];
+               Z21 = ex[1] - Z21 - p1 * Z11;
+               ex[1] = Z21;
+               Z22 = ex[1 + lskip1] - Z22 - p1 * Z12;
+               ex[1 + lskip1] = Z22;
+               /* end of outer loop */
+       }
+}
+
+void btFactorLDLT(btScalar *A, btScalar *d, int n, int nskip1)
+{
+       int i, j;
+       btScalar sum, *ell, *dee, dd, p1, p2, q1, q2, Z11, m11, Z21, m21, Z22, m22;
+       if (n < 1) return;
+
+       for (i = 0; i <= n - 2; i += 2)
+       {
+               /* solve L*(D*l)=a, l is scaled elements in 2 x i block at A(i,0) */
+               btSolveL1_2(A, A + i * nskip1, i, nskip1);
+               /* scale the elements in a 2 x i block at A(i,0), and also */
+               /* compute Z = the outer product matrix that we'll need. */
+               Z11 = 0;
+               Z21 = 0;
+               Z22 = 0;
+               ell = A + i * nskip1;
+               dee = d;
+               for (j = i - 6; j >= 0; j -= 6)
+               {
+                       p1 = ell[0];
+                       p2 = ell[nskip1];
+                       dd = dee[0];
+                       q1 = p1 * dd;
+                       q2 = p2 * dd;
+                       ell[0] = q1;
+                       ell[nskip1] = q2;
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m22 = p2 * q2;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z22 += m22;
+                       p1 = ell[1];
+                       p2 = ell[1 + nskip1];
+                       dd = dee[1];
+                       q1 = p1 * dd;
+                       q2 = p2 * dd;
+                       ell[1] = q1;
+                       ell[1 + nskip1] = q2;
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m22 = p2 * q2;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z22 += m22;
+                       p1 = ell[2];
+                       p2 = ell[2 + nskip1];
+                       dd = dee[2];
+                       q1 = p1 * dd;
+                       q2 = p2 * dd;
+                       ell[2] = q1;
+                       ell[2 + nskip1] = q2;
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m22 = p2 * q2;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z22 += m22;
+                       p1 = ell[3];
+                       p2 = ell[3 + nskip1];
+                       dd = dee[3];
+                       q1 = p1 * dd;
+                       q2 = p2 * dd;
+                       ell[3] = q1;
+                       ell[3 + nskip1] = q2;
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m22 = p2 * q2;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z22 += m22;
+                       p1 = ell[4];
+                       p2 = ell[4 + nskip1];
+                       dd = dee[4];
+                       q1 = p1 * dd;
+                       q2 = p2 * dd;
+                       ell[4] = q1;
+                       ell[4 + nskip1] = q2;
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m22 = p2 * q2;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z22 += m22;
+                       p1 = ell[5];
+                       p2 = ell[5 + nskip1];
+                       dd = dee[5];
+                       q1 = p1 * dd;
+                       q2 = p2 * dd;
+                       ell[5] = q1;
+                       ell[5 + nskip1] = q2;
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m22 = p2 * q2;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z22 += m22;
+                       ell += 6;
+                       dee += 6;
+               }
+               /* compute left-over iterations */
+               j += 6;
+               for (; j > 0; j--)
+               {
+                       p1 = ell[0];
+                       p2 = ell[nskip1];
+                       dd = dee[0];
+                       q1 = p1 * dd;
+                       q2 = p2 * dd;
+                       ell[0] = q1;
+                       ell[nskip1] = q2;
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m22 = p2 * q2;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z22 += m22;
+                       ell++;
+                       dee++;
+               }
+               /* solve for diagonal 2 x 2 block at A(i,i) */
+               Z11 = ell[0] - Z11;
+               Z21 = ell[nskip1] - Z21;
+               Z22 = ell[1 + nskip1] - Z22;
+               dee = d + i;
+               /* factorize 2 x 2 block Z,dee */
+               /* factorize row 1 */
+               dee[0] = btRecip(Z11);
+               /* factorize row 2 */
+               sum = 0;
+               q1 = Z21;
+               q2 = q1 * dee[0];
+               Z21 = q2;
+               sum += q1 * q2;
+               dee[1] = btRecip(Z22 - sum);
+               /* done factorizing 2 x 2 block */
+               ell[nskip1] = Z21;
+       }
+       /* compute the (less than 2) rows at the bottom */
+       switch (n - i)
+       {
+               case 0:
+                       break;
+
+               case 1:
+                       btSolveL1_1(A, A + i * nskip1, i, nskip1);
+                       /* scale the elements in a 1 x i block at A(i,0), and also */
+                       /* compute Z = the outer product matrix that we'll need. */
+                       Z11 = 0;
+                       ell = A + i * nskip1;
+                       dee = d;
+                       for (j = i - 6; j >= 0; j -= 6)
+                       {
+                               p1 = ell[0];
+                               dd = dee[0];
+                               q1 = p1 * dd;
+                               ell[0] = q1;
+                               m11 = p1 * q1;
+                               Z11 += m11;
+                               p1 = ell[1];
+                               dd = dee[1];
+                               q1 = p1 * dd;
+                               ell[1] = q1;
+                               m11 = p1 * q1;
+                               Z11 += m11;
+                               p1 = ell[2];
+                               dd = dee[2];
+                               q1 = p1 * dd;
+                               ell[2] = q1;
+                               m11 = p1 * q1;
+                               Z11 += m11;
+                               p1 = ell[3];
+                               dd = dee[3];
+                               q1 = p1 * dd;
+                               ell[3] = q1;
+                               m11 = p1 * q1;
+                               Z11 += m11;
+                               p1 = ell[4];
+                               dd = dee[4];
+                               q1 = p1 * dd;
+                               ell[4] = q1;
+                               m11 = p1 * q1;
+                               Z11 += m11;
+                               p1 = ell[5];
+                               dd = dee[5];
+                               q1 = p1 * dd;
+                               ell[5] = q1;
+                               m11 = p1 * q1;
+                               Z11 += m11;
+                               ell += 6;
+                               dee += 6;
+                       }
+                       /* compute left-over iterations */
+                       j += 6;
+                       for (; j > 0; j--)
+                       {
+                               p1 = ell[0];
+                               dd = dee[0];
+                               q1 = p1 * dd;
+                               ell[0] = q1;
+                               m11 = p1 * q1;
+                               Z11 += m11;
+                               ell++;
+                               dee++;
+                       }
+                       /* solve for diagonal 1 x 1 block at A(i,i) */
+                       Z11 = ell[0] - Z11;
+                       dee = d + i;
+                       /* factorize 1 x 1 block Z,dee */
+                       /* factorize row 1 */
+                       dee[0] = btRecip(Z11);
+                       /* done factorizing 1 x 1 block */
+                       break;
+
+                       //default: *((char*)0)=0;  /* this should never happen! */
+       }
+}
+
+/* solve L*X=B, with B containing 1 right hand sides.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * B is an n*1 matrix that contains the right hand sides.
+ * B is stored by columns and its leading dimension is also lskip.
+ * B is overwritten with X.
+ * this processes blocks of 4*4.
+ * if this is in the factorizer source file, n must be a multiple of 4.
+ */
+
+void btSolveL1(const btScalar *L, btScalar *B, int n, int lskip1)
+{
+       /* declare variables - Z matrix, p and q vectors, etc */
+       btScalar Z11, Z21, Z31, Z41, p1, q1, p2, p3, p4, *ex;
+       const btScalar *ell;
+       int lskip2, lskip3, i, j;
+       /* compute lskip values */
+       lskip2 = 2 * lskip1;
+       lskip3 = 3 * lskip1;
+       /* compute all 4 x 1 blocks of X */
+       for (i = 0; i <= n - 4; i += 4)
+       {
+               /* compute all 4 x 1 block of X, from rows i..i+4-1 */
+               /* set the Z matrix to 0 */
+               Z11 = 0;
+               Z21 = 0;
+               Z31 = 0;
+               Z41 = 0;
+               ell = L + i * lskip1;
+               ex = B;
+               /* the inner loop that computes outer products and adds them to Z */
+               for (j = i - 12; j >= 0; j -= 12)
+               {
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       p2 = ell[lskip1];
+                       p3 = ell[lskip2];
+                       p4 = ell[lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[1];
+                       q1 = ex[1];
+                       p2 = ell[1 + lskip1];
+                       p3 = ell[1 + lskip2];
+                       p4 = ell[1 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[2];
+                       q1 = ex[2];
+                       p2 = ell[2 + lskip1];
+                       p3 = ell[2 + lskip2];
+                       p4 = ell[2 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[3];
+                       q1 = ex[3];
+                       p2 = ell[3 + lskip1];
+                       p3 = ell[3 + lskip2];
+                       p4 = ell[3 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[4];
+                       q1 = ex[4];
+                       p2 = ell[4 + lskip1];
+                       p3 = ell[4 + lskip2];
+                       p4 = ell[4 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[5];
+                       q1 = ex[5];
+                       p2 = ell[5 + lskip1];
+                       p3 = ell[5 + lskip2];
+                       p4 = ell[5 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[6];
+                       q1 = ex[6];
+                       p2 = ell[6 + lskip1];
+                       p3 = ell[6 + lskip2];
+                       p4 = ell[6 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[7];
+                       q1 = ex[7];
+                       p2 = ell[7 + lskip1];
+                       p3 = ell[7 + lskip2];
+                       p4 = ell[7 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[8];
+                       q1 = ex[8];
+                       p2 = ell[8 + lskip1];
+                       p3 = ell[8 + lskip2];
+                       p4 = ell[8 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[9];
+                       q1 = ex[9];
+                       p2 = ell[9 + lskip1];
+                       p3 = ell[9 + lskip2];
+                       p4 = ell[9 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[10];
+                       q1 = ex[10];
+                       p2 = ell[10 + lskip1];
+                       p3 = ell[10 + lskip2];
+                       p4 = ell[10 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* load p and q values */
+                       p1 = ell[11];
+                       q1 = ex[11];
+                       p2 = ell[11 + lskip1];
+                       p3 = ell[11 + lskip2];
+                       p4 = ell[11 + lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* advance pointers */
+                       ell += 12;
+                       ex += 12;
+                       /* end of inner loop */
+               }
+               /* compute left-over iterations */
+               j += 12;
+               for (; j > 0; j--)
+               {
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       p2 = ell[lskip1];
+                       p3 = ell[lskip2];
+                       p4 = ell[lskip3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       Z21 += p2 * q1;
+                       Z31 += p3 * q1;
+                       Z41 += p4 * q1;
+                       /* advance pointers */
+                       ell += 1;
+                       ex += 1;
+               }
+               /* finish computing the X(i) block */
+               Z11 = ex[0] - Z11;
+               ex[0] = Z11;
+               p1 = ell[lskip1];
+               Z21 = ex[1] - Z21 - p1 * Z11;
+               ex[1] = Z21;
+               p1 = ell[lskip2];
+               p2 = ell[1 + lskip2];
+               Z31 = ex[2] - Z31 - p1 * Z11 - p2 * Z21;
+               ex[2] = Z31;
+               p1 = ell[lskip3];
+               p2 = ell[1 + lskip3];
+               p3 = ell[2 + lskip3];
+               Z41 = ex[3] - Z41 - p1 * Z11 - p2 * Z21 - p3 * Z31;
+               ex[3] = Z41;
+               /* end of outer loop */
+       }
+       /* compute rows at end that are not a multiple of block size */
+       for (; i < n; i++)
+       {
+               /* compute all 1 x 1 block of X, from rows i..i+1-1 */
+               /* set the Z matrix to 0 */
+               Z11 = 0;
+               ell = L + i * lskip1;
+               ex = B;
+               /* the inner loop that computes outer products and adds them to Z */
+               for (j = i - 12; j >= 0; j -= 12)
+               {
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[1];
+                       q1 = ex[1];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[2];
+                       q1 = ex[2];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[3];
+                       q1 = ex[3];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[4];
+                       q1 = ex[4];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[5];
+                       q1 = ex[5];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[6];
+                       q1 = ex[6];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[7];
+                       q1 = ex[7];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[8];
+                       q1 = ex[8];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[9];
+                       q1 = ex[9];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[10];
+                       q1 = ex[10];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* load p and q values */
+                       p1 = ell[11];
+                       q1 = ex[11];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* advance pointers */
+                       ell += 12;
+                       ex += 12;
+                       /* end of inner loop */
+               }
+               /* compute left-over iterations */
+               j += 12;
+               for (; j > 0; j--)
+               {
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       /* compute outer product and add it to the Z matrix */
+                       Z11 += p1 * q1;
+                       /* advance pointers */
+                       ell += 1;
+                       ex += 1;
+               }
+               /* finish computing the X(i) block */
+               Z11 = ex[0] - Z11;
+               ex[0] = Z11;
+       }
+}
+
+/* solve L^T * x=b, with b containing 1 right hand side.
+ * L is an n*n lower triangular matrix with ones on the diagonal.
+ * L is stored by rows and its leading dimension is lskip.
+ * b is an n*1 matrix that contains the right hand side.
+ * b is overwritten with x.
+ * this processes blocks of 4.
+ */
+
+void btSolveL1T(const btScalar *L, btScalar *B, int n, int lskip1)
+{
+       /* declare variables - Z matrix, p and q vectors, etc */
+       btScalar Z11, m11, Z21, m21, Z31, m31, Z41, m41, p1, q1, p2, p3, p4, *ex;
+       const btScalar *ell;
+       int lskip2, i, j;
+       //  int lskip3;
+       /* special handling for L and B because we're solving L1 *transpose* */
+       L = L + (n - 1) * (lskip1 + 1);
+       B = B + n - 1;
+       lskip1 = -lskip1;
+       /* compute lskip values */
+       lskip2 = 2 * lskip1;
+       //lskip3 = 3*lskip1;
+       /* compute all 4 x 1 blocks of X */
+       for (i = 0; i <= n - 4; i += 4)
+       {
+               /* compute all 4 x 1 block of X, from rows i..i+4-1 */
+               /* set the Z matrix to 0 */
+               Z11 = 0;
+               Z21 = 0;
+               Z31 = 0;
+               Z41 = 0;
+               ell = L - i;
+               ex = B;
+               /* the inner loop that computes outer products and adds them to Z */
+               for (j = i - 4; j >= 0; j -= 4)
+               {
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       p2 = ell[-1];
+                       p3 = ell[-2];
+                       p4 = ell[-3];
+                       /* compute outer product and add it to the Z matrix */
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m31 = p3 * q1;
+                       m41 = p4 * q1;
+                       ell += lskip1;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z31 += m31;
+                       Z41 += m41;
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[-1];
+                       p2 = ell[-1];
+                       p3 = ell[-2];
+                       p4 = ell[-3];
+                       /* compute outer product and add it to the Z matrix */
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m31 = p3 * q1;
+                       m41 = p4 * q1;
+                       ell += lskip1;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z31 += m31;
+                       Z41 += m41;
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[-2];
+                       p2 = ell[-1];
+                       p3 = ell[-2];
+                       p4 = ell[-3];
+                       /* compute outer product and add it to the Z matrix */
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m31 = p3 * q1;
+                       m41 = p4 * q1;
+                       ell += lskip1;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z31 += m31;
+                       Z41 += m41;
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[-3];
+                       p2 = ell[-1];
+                       p3 = ell[-2];
+                       p4 = ell[-3];
+                       /* compute outer product and add it to the Z matrix */
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m31 = p3 * q1;
+                       m41 = p4 * q1;
+                       ell += lskip1;
+                       ex -= 4;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z31 += m31;
+                       Z41 += m41;
+                       /* end of inner loop */
+               }
+               /* compute left-over iterations */
+               j += 4;
+               for (; j > 0; j--)
+               {
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       p2 = ell[-1];
+                       p3 = ell[-2];
+                       p4 = ell[-3];
+                       /* compute outer product and add it to the Z matrix */
+                       m11 = p1 * q1;
+                       m21 = p2 * q1;
+                       m31 = p3 * q1;
+                       m41 = p4 * q1;
+                       ell += lskip1;
+                       ex -= 1;
+                       Z11 += m11;
+                       Z21 += m21;
+                       Z31 += m31;
+                       Z41 += m41;
+               }
+               /* finish computing the X(i) block */
+               Z11 = ex[0] - Z11;
+               ex[0] = Z11;
+               p1 = ell[-1];
+               Z21 = ex[-1] - Z21 - p1 * Z11;
+               ex[-1] = Z21;
+               p1 = ell[-2];
+               p2 = ell[-2 + lskip1];
+               Z31 = ex[-2] - Z31 - p1 * Z11 - p2 * Z21;
+               ex[-2] = Z31;
+               p1 = ell[-3];
+               p2 = ell[-3 + lskip1];
+               p3 = ell[-3 + lskip2];
+               Z41 = ex[-3] - Z41 - p1 * Z11 - p2 * Z21 - p3 * Z31;
+               ex[-3] = Z41;
+               /* end of outer loop */
+       }
+       /* compute rows at end that are not a multiple of block size */
+       for (; i < n; i++)
+       {
+               /* compute all 1 x 1 block of X, from rows i..i+1-1 */
+               /* set the Z matrix to 0 */
+               Z11 = 0;
+               ell = L - i;
+               ex = B;
+               /* the inner loop that computes outer products and adds them to Z */
+               for (j = i - 4; j >= 0; j -= 4)
+               {
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       /* compute outer product and add it to the Z matrix */
+                       m11 = p1 * q1;
+                       ell += lskip1;
+                       Z11 += m11;
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[-1];
+                       /* compute outer product and add it to the Z matrix */
+                       m11 = p1 * q1;
+                       ell += lskip1;
+                       Z11 += m11;
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[-2];
+                       /* compute outer product and add it to the Z matrix */
+                       m11 = p1 * q1;
+                       ell += lskip1;
+                       Z11 += m11;
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[-3];
+                       /* compute outer product and add it to the Z matrix */
+                       m11 = p1 * q1;
+                       ell += lskip1;
+                       ex -= 4;
+                       Z11 += m11;
+                       /* end of inner loop */
+               }
+               /* compute left-over iterations */
+               j += 4;
+               for (; j > 0; j--)
+               {
+                       /* load p and q values */
+                       p1 = ell[0];
+                       q1 = ex[0];
+                       /* compute outer product and add it to the Z matrix */
+                       m11 = p1 * q1;
+                       ell += lskip1;
+                       ex -= 1;
+                       Z11 += m11;
+               }
+               /* finish computing the X(i) block */
+               Z11 = ex[0] - Z11;
+               ex[0] = Z11;
+       }
+}
+
+void btVectorScale(btScalar *a, const btScalar *d, int n)
+{
+       btAssert(a && d && n >= 0);
+       for (int i = 0; i < n; i++)
+       {
+               a[i] *= d[i];
+       }
+}
+
+void btSolveLDLT(const btScalar *L, const btScalar *d, btScalar *b, int n, int nskip)
+{
+       btAssert(L && d && b && n > 0 && nskip >= n);
+       btSolveL1(L, b, n, nskip);
+       btVectorScale(b, d, n);
+       btSolveL1T(L, b, n, nskip);
+}
+
+//***************************************************************************
+
+// swap row/column i1 with i2 in the n*n matrix A. the leading dimension of
+// A is nskip. this only references and swaps the lower triangle.
+// if `do_fast_row_swaps' is nonzero and row pointers are being used, then
+// rows will be swapped by exchanging row pointers. otherwise the data will
+// be copied.
+
+static void btSwapRowsAndCols(BTATYPE A, int n, int i1, int i2, int nskip,
+                                                         int do_fast_row_swaps)
+{
+       btAssert(A && n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n &&
+                        nskip >= n && i1 < i2);
+
+#ifdef BTROWPTRS
+       btScalar *A_i1 = A[i1];
+       btScalar *A_i2 = A[i2];
+       for (int i = i1 + 1; i < i2; ++i)
+       {
+               btScalar *A_i_i1 = A[i] + i1;
+               A_i1[i] = *A_i_i1;
+               *A_i_i1 = A_i2[i];
+       }
+       A_i1[i2] = A_i1[i1];
+       A_i1[i1] = A_i2[i1];
+       A_i2[i1] = A_i2[i2];
+       // swap rows, by swapping row pointers
+       if (do_fast_row_swaps)
+       {
+               A[i1] = A_i2;
+               A[i2] = A_i1;
+       }
+       else
+       {
+               // Only swap till i2 column to match A plain storage variant.
+               for (int k = 0; k <= i2; ++k)
+               {
+                       btScalar tmp = A_i1[k];
+                       A_i1[k] = A_i2[k];
+                       A_i2[k] = tmp;
+               }
+       }
+       // swap columns the hard way
+       for (int j = i2 + 1; j < n; ++j)
+       {
+               btScalar *A_j = A[j];
+               btScalar tmp = A_j[i1];
+               A_j[i1] = A_j[i2];
+               A_j[i2] = tmp;
+       }
+#else
+       btScalar *A_i1 = A + i1 * nskip;
+       btScalar *A_i2 = A + i2 * nskip;
+       for (int k = 0; k < i1; ++k)
+       {
+               btScalar tmp = A_i1[k];
+               A_i1[k] = A_i2[k];
+               A_i2[k] = tmp;
+       }
+       btScalar *A_i = A_i1 + nskip;
+       for (int i = i1 + 1; i < i2; A_i += nskip, ++i)
+       {
+               btScalar tmp = A_i2[i];
+               A_i2[i] = A_i[i1];
+               A_i[i1] = tmp;
+       }
+       {
+               btScalar tmp = A_i1[i1];
+               A_i1[i1] = A_i2[i2];
+               A_i2[i2] = tmp;
+       }
+       btScalar *A_j = A_i2 + nskip;
+       for (int j = i2 + 1; j < n; A_j += nskip, ++j)
+       {
+               btScalar tmp = A_j[i1];
+               A_j[i1] = A_j[i2];
+               A_j[i2] = tmp;
+       }
+#endif
+}
+
+// swap two indexes in the n*n LCP problem. i1 must be <= i2.
+
+static void btSwapProblem(BTATYPE A, btScalar *x, btScalar *b, btScalar *w, btScalar *lo,
+                                                 btScalar *hi, int *p, bool *state, int *findex,
+                                                 int n, int i1, int i2, int nskip,
+                                                 int do_fast_row_swaps)
+{
+       btScalar tmpr;
+       int tmpi;
+       bool tmpb;
+       btAssert(n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n && nskip >= n && i1 <= i2);
+       if (i1 == i2) return;
+
+       btSwapRowsAndCols(A, n, i1, i2, nskip, do_fast_row_swaps);
+
+       tmpr = x[i1];
+       x[i1] = x[i2];
+       x[i2] = tmpr;
+
+       tmpr = b[i1];
+       b[i1] = b[i2];
+       b[i2] = tmpr;
+
+       tmpr = w[i1];
+       w[i1] = w[i2];
+       w[i2] = tmpr;
+
+       tmpr = lo[i1];
+       lo[i1] = lo[i2];
+       lo[i2] = tmpr;
+
+       tmpr = hi[i1];
+       hi[i1] = hi[i2];
+       hi[i2] = tmpr;
+
+       tmpi = p[i1];
+       p[i1] = p[i2];
+       p[i2] = tmpi;
+
+       tmpb = state[i1];
+       state[i1] = state[i2];
+       state[i2] = tmpb;
+
+       if (findex)
+       {
+               tmpi = findex[i1];
+               findex[i1] = findex[i2];
+               findex[i2] = tmpi;
+       }
+}
+
+//***************************************************************************
+// btLCP manipulator object. this represents an n*n LCP problem.
+//
+// two index sets C and N are kept. each set holds a subset of
+// the variable indexes 0..n-1. an index can only be in one set.
+// initially both sets are empty.
+//
+// the index set C is special: solutions to A(C,C)\A(C,i) can be generated.
+
+//***************************************************************************
+// fast implementation of btLCP. see the above definition of btLCP for
+// interface comments.
+//
+// `p' records the permutation of A,x,b,w,etc. p is initially 1:n and is
+// permuted as the other vectors/matrices are permuted.
+//
+// A,x,b,w,lo,hi,state,findex,p,c are permuted such that sets C,N have
+// contiguous indexes. the don't-care indexes follow N.
+//
+// an L*D*L' factorization is maintained of A(C,C), and whenever indexes are
+// added or removed from the set C the factorization is updated.
+// thus L*D*L'=A[C,C], i.e. a permuted top left nC*nC submatrix of A.
+// the leading dimension of the matrix L is always `nskip'.
+//
+// at the start there may be other indexes that are unbounded but are not
+// included in `nub'. btLCP will permute the matrix so that absolutely all
+// unbounded vectors are at the start. thus there may be some initial
+// permutation.
+//
+// the algorithms here assume certain patterns, particularly with respect to
+// index transfer.
+
+#ifdef btLCP_FAST
+
+struct btLCP
+{
+       const int m_n;
+       const int m_nskip;
+       int m_nub;
+       int m_nC, m_nN;                                                         // size of each index set
+       BTATYPE const m_A;                                                      // A rows
+       btScalar *const m_x, *const m_b, *const m_w, *const m_lo, *const m_hi;  // permuted LCP problem data
+       btScalar *const m_L, *const m_d;                                        // L*D*L' factorization of set C
+       btScalar *const m_Dell, *const m_ell, *const m_tmp;
+       bool *const m_state;
+       int *const m_findex, *const m_p, *const m_C;
+
+       btLCP(int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w,
+                 btScalar *_lo, btScalar *_hi, btScalar *l, btScalar *_d,
+                 btScalar *_Dell, btScalar *_ell, btScalar *_tmp,
+                 bool *_state, int *_findex, int *p, int *c, btScalar **Arows);
+       int getNub() const { return m_nub; }
+       void transfer_i_to_C(int i);
+       void transfer_i_to_N(int i) { m_nN++; }  // because we can assume C and N span 1:i-1
+       void transfer_i_from_N_to_C(int i);
+       void transfer_i_from_C_to_N(int i, btAlignedObjectArray<btScalar> &scratch);
+       int numC() const { return m_nC; }
+       int numN() const { return m_nN; }
+       int indexC(int i) const { return i; }
+       int indexN(int i) const { return i + m_nC; }
+       btScalar Aii(int i) const { return BTAROW(i)[i]; }
+       btScalar AiC_times_qC(int i, btScalar *q) const { return btLargeDot(BTAROW(i), q, m_nC); }
+       btScalar AiN_times_qN(int i, btScalar *q) const { return btLargeDot(BTAROW(i) + m_nC, q + m_nC, m_nN); }
+       void pN_equals_ANC_times_qC(btScalar *p, btScalar *q);
+       void pN_plusequals_ANi(btScalar *p, int i, int sign = 1);
+       void pC_plusequals_s_times_qC(btScalar *p, btScalar s, btScalar *q);
+       void pN_plusequals_s_times_qN(btScalar *p, btScalar s, btScalar *q);
+       void solve1(btScalar *a, int i, int dir = 1, int only_transfer = 0);
+       void unpermute();
+};
+
+btLCP::btLCP(int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w,
+                        btScalar *_lo, btScalar *_hi, btScalar *l, btScalar *_d,
+                        btScalar *_Dell, btScalar *_ell, btScalar *_tmp,
+                        bool *_state, int *_findex, int *p, int *c, btScalar **Arows) : m_n(_n), m_nskip(_nskip), m_nub(_nub), m_nC(0), m_nN(0),
+#ifdef BTROWPTRS
+                                                                                                                                                        m_A(Arows),
+#else
+                                                                                                                                                        m_A(_Adata),
+#endif
+                                                                                                                                                        m_x(_x),
+                                                                                                                                                        m_b(_b),
+                                                                                                                                                        m_w(_w),
+                                                                                                                                                        m_lo(_lo),
+                                                                                                                                                        m_hi(_hi),
+                                                                                                                                                        m_L(l),
+                                                                                                                                                        m_d(_d),
+                                                                                                                                                        m_Dell(_Dell),
+                                                                                                                                                        m_ell(_ell),
+                                                                                                                                                        m_tmp(_tmp),
+                                                                                                                                                        m_state(_state),
+                                                                                                                                                        m_findex(_findex),
+                                                                                                                                                        m_p(p),
+                                                                                                                                                        m_C(c)
+{
+       {
+               btSetZero(m_x, m_n);
+       }
+
+       {
+#ifdef BTROWPTRS
+               // make matrix row pointers
+               btScalar *aptr = _Adata;
+               BTATYPE A = m_A;
+               const int n = m_n, nskip = m_nskip;
+               for (int k = 0; k < n; aptr += nskip, ++k) A[k] = aptr;
+#endif
+       }
+
+       {
+               int *p = m_p;
+               const int n = m_n;
+               for (int k = 0; k < n; ++k) p[k] = k;  // initially unpermuted
+       }
+
+       /*
+  // for testing, we can do some random swaps in the area i > nub
+  {
+    const int n = m_n;
+    const int nub = m_nub;
+    if (nub < n) {
+    for (int k=0; k<100; k++) {
+      int i1,i2;
+      do {
+        i1 = dRandInt(n-nub)+nub;
+        i2 = dRandInt(n-nub)+nub;
+      }
+      while (i1 > i2); 
+      //printf ("--> %d %d\n",i1,i2);
+      btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,m_findex,n,i1,i2,m_nskip,0);
+    }
+  }
+  */
+
+       // permute the problem so that *all* the unbounded variables are at the
+       // start, i.e. look for unbounded variables not included in `nub'. we can
+       // potentially push up `nub' this way and get a bigger initial factorization.
+       // note that when we swap rows/cols here we must not just swap row pointers,
+       // as the initial factorization relies on the data being all in one chunk.
+       // variables that have findex >= 0 are *not* considered to be unbounded even
+       // if lo=-inf and hi=inf - this is because these limits may change during the
+       // solution process.
+
+       {
+               int *findex = m_findex;
+               btScalar *lo = m_lo, *hi = m_hi;
+               const int n = m_n;
+               for (int k = m_nub; k < n; ++k)
+               {
+                       if (findex && findex[k] >= 0) continue;
+                       if (lo[k] == -BT_INFINITY && hi[k] == BT_INFINITY)
+                       {
+                               btSwapProblem(m_A, m_x, m_b, m_w, lo, hi, m_p, m_state, findex, n, m_nub, k, m_nskip, 0);
+                               m_nub++;
+                       }
+               }
+       }
+
+       // if there are unbounded variables at the start, factorize A up to that
+       // point and solve for x. this puts all indexes 0..nub-1 into C.
+       if (m_nub > 0)
+       {
+               const int nub = m_nub;
+               {
+                       btScalar *Lrow = m_L;
+                       const int nskip = m_nskip;
+                       for (int j = 0; j < nub; Lrow += nskip, ++j) memcpy(Lrow, BTAROW(j), (j + 1) * sizeof(btScalar));
+               }
+               btFactorLDLT(m_L, m_d, nub, m_nskip);
+               memcpy(m_x, m_b, nub * sizeof(btScalar));
+               btSolveLDLT(m_L, m_d, m_x, nub, m_nskip);
+               btSetZero(m_w, nub);
+               {
+                       int *C = m_C;
+                       for (int k = 0; k < nub; ++k) C[k] = k;
+               }
+               m_nC = nub;
+       }
+
+       // permute the indexes > nub such that all findex variables are at the end
+       if (m_findex)
+       {
+               const int nub = m_nub;
+               int *findex = m_findex;
+               int num_at_end = 0;
+               for (int k = m_n - 1; k >= nub; k--)
+               {
+                       if (findex[k] >= 0)
+                       {
+                               btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, m_p, m_state, findex, m_n, k, m_n - 1 - num_at_end, m_nskip, 1);
+                               num_at_end++;
+                       }
+               }
+       }
+
+       // print info about indexes
+       /*
+  {
+    const int n = m_n;
+    const int nub = m_nub;
+    for (int k=0; k<n; k++) {
+      if (k<nub) printf ("C");
+      else if (m_lo[k]==-BT_INFINITY && m_hi[k]==BT_INFINITY) printf ("c");
+      else printf (".");
+    }
+    printf ("\n");
+  }
+  */
+}
+
+void btLCP::transfer_i_to_C(int i)
+{
+       {
+               if (m_nC > 0)
+               {
+                       // ell,Dell were computed by solve1(). note, ell = D \ L1solve (L,A(i,C))
+                       {
+                               const int nC = m_nC;
+                               btScalar *const Ltgt = m_L + nC * m_nskip, *ell = m_ell;
+                               for (int j = 0; j < nC; ++j) Ltgt[j] = ell[j];
+                       }
+                       const int nC = m_nC;
+                       m_d[nC] = btRecip(BTAROW(i)[i] - btLargeDot(m_ell, m_Dell, nC));
+               }
+               else
+               {
+                       m_d[0] = btRecip(BTAROW(i)[i]);
+               }
+
+               btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, m_p, m_state, m_findex, m_n, m_nC, i, m_nskip, 1);
+
+               const int nC = m_nC;
+               m_C[nC] = nC;
+               m_nC = nC + 1;  // nC value is outdated after this line
+       }
+}
+
+void btLCP::transfer_i_from_N_to_C(int i)
+{
+       {
+               if (m_nC > 0)
+               {
+                       {
+                               btScalar *const aptr = BTAROW(i);
+                               btScalar *Dell = m_Dell;
+                               const int *C = m_C;
+#ifdef BTNUB_OPTIMIZATIONS
+                               // if nub>0, initial part of aptr unpermuted
+                               const int nub = m_nub;
+                               int j = 0;
+                               for (; j < nub; ++j) Dell[j] = aptr[j];
+                               const int nC = m_nC;
+                               for (; j < nC; ++j) Dell[j] = aptr[C[j]];
+#else
+                               const int nC = m_nC;
+                               for (int j = 0; j < nC; ++j) Dell[j] = aptr[C[j]];
+#endif
+                       }
+                       btSolveL1(m_L, m_Dell, m_nC, m_nskip);
+                       {
+                               const int nC = m_nC;
+                               btScalar *const Ltgt = m_L + nC * m_nskip;
+                               btScalar *ell = m_ell, *Dell = m_Dell, *d = m_d;
+                               for (int j = 0; j < nC; ++j) Ltgt[j] = ell[j] = Dell[j] * d[j];
+                       }
+                       const int nC = m_nC;
+                       m_d[nC] = btRecip(BTAROW(i)[i] - btLargeDot(m_ell, m_Dell, nC));
+               }
+               else
+               {
+                       m_d[0] = btRecip(BTAROW(i)[i]);
+               }
+
+               btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, m_p, m_state, m_findex, m_n, m_nC, i, m_nskip, 1);
+
+               const int nC = m_nC;
+               m_C[nC] = nC;
+               m_nN--;
+               m_nC = nC + 1;  // nC value is outdated after this line
+       }
+
+       // @@@ TO DO LATER
+       // if we just finish here then we'll go back and re-solve for
+       // delta_x. but actually we can be more efficient and incrementally
+       // update delta_x here. but if we do this, we wont have ell and Dell
+       // to use in updating the factorization later.
+}
+
+void btRemoveRowCol(btScalar *A, int n, int nskip, int r)
+{
+       btAssert(A && n > 0 && nskip >= n && r >= 0 && r < n);
+       if (r >= n - 1) return;
+       if (r > 0)
+       {
+               {
+                       const size_t move_size = (n - r - 1) * sizeof(btScalar);
+                       btScalar *Adst = A + r;
+                       for (int i = 0; i < r; Adst += nskip, ++i)
+                       {
+                               btScalar *Asrc = Adst + 1;
+                               memmove(Adst, Asrc, move_size);
+                       }
+               }
+               {
+                       const size_t cpy_size = r * sizeof(btScalar);
+                       btScalar *Adst = A + r * nskip;
+                       for (int i = r; i < (n - 1); ++i)
+                       {
+                               btScalar *Asrc = Adst + nskip;
+                               memcpy(Adst, Asrc, cpy_size);
+                               Adst = Asrc;
+                       }
+               }
+       }
+       {
+               const size_t cpy_size = (n - r - 1) * sizeof(btScalar);
+               btScalar *Adst = A + r * (nskip + 1);
+               for (int i = r; i < (n - 1); ++i)
+               {
+                       btScalar *Asrc = Adst + (nskip + 1);
+                       memcpy(Adst, Asrc, cpy_size);
+                       Adst = Asrc - 1;
+               }
+       }
+}
+
+void btLDLTAddTL(btScalar *L, btScalar *d, const btScalar *a, int n, int nskip, btAlignedObjectArray<btScalar> &scratch)
+{
+       btAssert(L && d && a && n > 0 && nskip >= n);
+
+       if (n < 2) return;
+       scratch.resize(2 * nskip);
+       btScalar *W1 = &scratch[0];
+
+       btScalar *W2 = W1 + nskip;
+
+       W1[0] = btScalar(0.0);
+       W2[0] = btScalar(0.0);
+       for (int j = 1; j < n; ++j)
+       {
+               W1[j] = W2[j] = (btScalar)(a[j] * SIMDSQRT12);
+       }
+       btScalar W11 = (btScalar)((btScalar(0.5) * a[0] + 1) * SIMDSQRT12);
+       btScalar W21 = (btScalar)((btScalar(0.5) * a[0] - 1) * SIMDSQRT12);
+
+       btScalar alpha1 = btScalar(1.0);
+       btScalar alpha2 = btScalar(1.0);
+
+       {
+               btScalar dee = d[0];
+               btScalar alphanew = alpha1 + (W11 * W11) * dee;
+               btAssert(alphanew != btScalar(0.0));
+               dee /= alphanew;
+               btScalar gamma1 = W11 * dee;
+               dee *= alpha1;
+               alpha1 = alphanew;
+               alphanew = alpha2 - (W21 * W21) * dee;
+               dee /= alphanew;
+               //btScalar gamma2 = W21 * dee;
+               alpha2 = alphanew;
+               btScalar k1 = btScalar(1.0) - W21 * gamma1;
+               btScalar k2 = W21 * gamma1 * W11 - W21;
+               btScalar *ll = L + nskip;
+               for (int p = 1; p < n; ll += nskip, ++p)
+               {
+                       btScalar Wp = W1[p];
+                       btScalar ell = *ll;
+                       W1[p] = Wp - W11 * ell;
+                       W2[p] = k1 * Wp + k2 * ell;
+               }
+       }
+
+       btScalar *ll = L + (nskip + 1);
+       for (int j = 1; j < n; ll += nskip + 1, ++j)
+       {
+               btScalar k1 = W1[j];
+               btScalar k2 = W2[j];
+
+               btScalar dee = d[j];
+               btScalar alphanew = alpha1 + (k1 * k1) * dee;
+               btAssert(alphanew != btScalar(0.0));
+               dee /= alphanew;
+               btScalar gamma1 = k1 * dee;
+               dee *= alpha1;
+               alpha1 = alphanew;
+               alphanew = alpha2 - (k2 * k2) * dee;
+               dee /= alphanew;
+               btScalar gamma2 = k2 * dee;
+               dee *= alpha2;
+               d[j] = dee;
+               alpha2 = alphanew;
+
+               btScalar *l = ll + nskip;
+               for (int p = j + 1; p < n; l += nskip, ++p)
+               {
+                       btScalar ell = *l;
+                       btScalar Wp = W1[p] - k1 * ell;
+                       ell += gamma1 * Wp;
+                       W1[p] = Wp;
+                       Wp = W2[p] - k2 * ell;
+                       ell -= gamma2 * Wp;
+                       W2[p] = Wp;
+                       *l = ell;
+               }
+       }
+}
+
+#define _BTGETA(i, j) (A[i][j])
+//#define _GETA(i,j) (A[(i)*nskip+(j)])
+#define BTGETA(i, j) ((i > j) ? _BTGETA(i, j) : _BTGETA(j, i))
+
+inline size_t btEstimateLDLTAddTLTmpbufSize(int nskip)
+{
+       return nskip * 2 * sizeof(btScalar);
+}
+
+void btLDLTRemove(btScalar **A, const int *p, btScalar *L, btScalar *d,
+                                 int n1, int n2, int r, int nskip, btAlignedObjectArray<btScalar> &scratch)
+{
+       btAssert(A && p && L && d && n1 > 0 && n2 > 0 && r >= 0 && r < n2 &&
+                        n1 >= n2 && nskip >= n1);
+#ifdef BT_DEBUG
+       for (int i = 0; i < n2; ++i)
+               btAssert(p[i] >= 0 && p[i] < n1);
+#endif
+
+       if (r == n2 - 1)
+       {
+               return;  // deleting last row/col is easy
+       }
+       else
+       {
+               size_t LDLTAddTL_size = btEstimateLDLTAddTLTmpbufSize(nskip);
+               btAssert(LDLTAddTL_size % sizeof(btScalar) == 0);
+               scratch.resize(nskip * 2 + n2);
+               btScalar *tmp = &scratch[0];
+               if (r == 0)
+               {
+                       btScalar *a = (btScalar *)((char *)tmp + LDLTAddTL_size);
+                       const int p_0 = p[0];
+                       for (int i = 0; i < n2; ++i)
+                       {
+                               a[i] = -BTGETA(p[i], p_0);
+                       }
+                       a[0] += btScalar(1.0);
+                       btLDLTAddTL(L, d, a, n2, nskip, scratch);
+               }
+               else
+               {
+                       btScalar *t = (btScalar *)((char *)tmp + LDLTAddTL_size);
+                       {
+                               btScalar *Lcurr = L + r * nskip;
+                               for (int i = 0; i < r; ++Lcurr, ++i)
+                               {
+                                       btAssert(d[i] != btScalar(0.0));
+                                       t[i] = *Lcurr / d[i];
+                               }
+                       }
+                       btScalar *a = t + r;
+                       {
+                               btScalar *Lcurr = L + r * nskip;
+                               const int *pp_r = p + r, p_r = *pp_r;
+                               const int n2_minus_r = n2 - r;
+                               for (int i = 0; i < n2_minus_r; Lcurr += nskip, ++i)
+                               {
+                                       a[i] = btLargeDot(Lcurr, t, r) - BTGETA(pp_r[i], p_r);
+                               }
+                       }
+                       a[0] += btScalar(1.0);
+                       btLDLTAddTL(L + r * nskip + r, d + r, a, n2 - r, nskip, scratch);
+               }
+       }
+
+       // snip out row/column r from L and d
+       btRemoveRowCol(L, n2, nskip, r);
+       if (r < (n2 - 1)) memmove(d + r, d + r + 1, (n2 - r - 1) * sizeof(btScalar));
+}
+
+void btLCP::transfer_i_from_C_to_N(int i, btAlignedObjectArray<btScalar> &scratch)
+{
+       {
+               int *C = m_C;
+               // remove a row/column from the factorization, and adjust the
+               // indexes (black magic!)
+               int last_idx = -1;
+               const int nC = m_nC;
+               int j = 0;
+               for (; j < nC; ++j)
+               {
+                       if (C[j] == nC - 1)
+                       {
+                               last_idx = j;
+                       }
+                       if (C[j] == i)
+                       {
+                               btLDLTRemove(m_A, C, m_L, m_d, m_n, nC, j, m_nskip, scratch);
+                               int k;
+                               if (last_idx == -1)
+                               {
+                                       for (k = j + 1; k < nC; ++k)
+                                       {
+                                               if (C[k] == nC - 1)
+                                               {
+                                                       break;
+                                               }
+                                       }
+                                       btAssert(k < nC);
+                               }
+                               else
+                               {
+                                       k = last_idx;
+                               }
+                               C[k] = C[j];
+                               if (j < (nC - 1)) memmove(C + j, C + j + 1, (nC - j - 1) * sizeof(int));
+                               break;
+                       }
+               }
+               btAssert(j < nC);
+
+               btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, m_p, m_state, m_findex, m_n, i, nC - 1, m_nskip, 1);
+
+               m_nN++;
+               m_nC = nC - 1;  // nC value is outdated after this line
+       }
+}
+
+void btLCP::pN_equals_ANC_times_qC(btScalar *p, btScalar *q)
+{
+       // we could try to make this matrix-vector multiplication faster using
+       // outer product matrix tricks, e.g. with the dMultidotX() functions.
+       // but i tried it and it actually made things slower on random 100x100
+       // problems because of the overhead involved. so we'll stick with the
+       // simple method for now.
+       const int nC = m_nC;
+       btScalar *ptgt = p + nC;
+       const int nN = m_nN;
+       for (int i = 0; i < nN; ++i)
+       {
+               ptgt[i] = btLargeDot(BTAROW(i + nC), q, nC);
+       }
+}
+
+void btLCP::pN_plusequals_ANi(btScalar *p, int i, int sign)
+{
+       const int nC = m_nC;
+       btScalar *aptr = BTAROW(i) + nC;
+       btScalar *ptgt = p + nC;
+       if (sign > 0)
+       {
+               const int nN = m_nN;
+               for (int j = 0; j < nN; ++j) ptgt[j] += aptr[j];
+       }
+       else
+       {
+               const int nN = m_nN;
+               for (int j = 0; j < nN; ++j) ptgt[j] -= aptr[j];
+       }
+}
+
+void btLCP::pC_plusequals_s_times_qC(btScalar *p, btScalar s, btScalar *q)
+{
+       const int nC = m_nC;
+       for (int i = 0; i < nC; ++i)
+       {
+               p[i] += s * q[i];
+       }
+}
+
+void btLCP::pN_plusequals_s_times_qN(btScalar *p, btScalar s, btScalar *q)
+{
+       const int nC = m_nC;
+       btScalar *ptgt = p + nC, *qsrc = q + nC;
+       const int nN = m_nN;
+       for (int i = 0; i < nN; ++i)
+       {
+               ptgt[i] += s * qsrc[i];
+       }
+}
+
+void btLCP::solve1(btScalar *a, int i, int dir, int only_transfer)
+{
+       // the `Dell' and `ell' that are computed here are saved. if index i is
+       // later added to the factorization then they can be reused.
+       //
+       // @@@ question: do we need to solve for entire delta_x??? yes, but
+       //     only if an x goes below 0 during the step.
+
+       if (m_nC > 0)
+       {
+               {
+                       btScalar *Dell = m_Dell;
+                       int *C = m_C;
+                       btScalar *aptr = BTAROW(i);
+#ifdef BTNUB_OPTIMIZATIONS
+                       // if nub>0, initial part of aptr[] is guaranteed unpermuted
+                       const int nub = m_nub;
+                       int j = 0;
+                       for (; j < nub; ++j) Dell[j] = aptr[j];
+                       const int nC = m_nC;
+                       for (; j < nC; ++j) Dell[j] = aptr[C[j]];
+#else
+                       const int nC = m_nC;
+                       for (int j = 0; j < nC; ++j) Dell[j] = aptr[C[j]];
+#endif
+               }
+               btSolveL1(m_L, m_Dell, m_nC, m_nskip);
+               {
+                       btScalar *ell = m_ell, *Dell = m_Dell, *d = m_d;
+                       const int nC = m_nC;
+                       for (int j = 0; j < nC; ++j) ell[j] = Dell[j] * d[j];
+               }
+
+               if (!only_transfer)
+               {
+                       btScalar *tmp = m_tmp, *ell = m_ell;
+                       {
+                               const int nC = m_nC;
+                               for (int j = 0; j < nC; ++j) tmp[j] = ell[j];
+                       }
+                       btSolveL1T(m_L, tmp, m_nC, m_nskip);
+                       if (dir > 0)
+                       {
+                               int *C = m_C;
+                               btScalar *tmp = m_tmp;
+                               const int nC = m_nC;
+                               for (int j = 0; j < nC; ++j) a[C[j]] = -tmp[j];
+                       }
+                       else
+                       {
+                               int *C = m_C;
+                               btScalar *tmp = m_tmp;
+                               const int nC = m_nC;
+                               for (int j = 0; j < nC; ++j) a[C[j]] = tmp[j];
+                       }
+               }
+       }
+}
+
+void btLCP::unpermute()
+{
+       // now we have to un-permute x and w
+       {
+               memcpy(m_tmp, m_x, m_n * sizeof(btScalar));
+               btScalar *x = m_x, *tmp = m_tmp;
+               const int *p = m_p;
+               const int n = m_n;
+               for (int j = 0; j < n; ++j) x[p[j]] = tmp[j];
+       }
+       {
+               memcpy(m_tmp, m_w, m_n * sizeof(btScalar));
+               btScalar *w = m_w, *tmp = m_tmp;
+               const int *p = m_p;
+               const int n = m_n;
+               for (int j = 0; j < n; ++j) w[p[j]] = tmp[j];
+       }
+}
+
+#endif  // btLCP_FAST
+
+//***************************************************************************
+// an optimized Dantzig LCP driver routine for the lo-hi LCP problem.
+
+bool btSolveDantzigLCP(int n, btScalar *A, btScalar *x, btScalar *b,
+                                          btScalar *outer_w, int nub, btScalar *lo, btScalar *hi, int *findex, btDantzigScratchMemory &scratchMem)
+{
+       s_error = false;
+
+       //      printf("btSolveDantzigLCP n=%d\n",n);
+       btAssert(n > 0 && A && x && b && lo && hi && nub >= 0 && nub <= n);
+       btAssert(outer_w);
+
+#ifdef BT_DEBUG
+       {
+               // check restrictions on lo and hi
+               for (int k = 0; k < n; ++k)
+                       btAssert(lo[k] <= 0 && hi[k] >= 0);
+       }
+#endif
+
+       // if all the variables are unbounded then we can just factor, solve,
+       // and return
+       if (nub >= n)
+       {
+               int nskip = (n);
+               btFactorLDLT(A, outer_w, n, nskip);
+               btSolveLDLT(A, outer_w, b, n, nskip);
+               memcpy(x, b, n * sizeof(btScalar));
+
+               return !s_error;
+       }
+
+       const int nskip = (n);
+       scratchMem.L.resize(n * nskip);
+
+       scratchMem.d.resize(n);
+
+       btScalar *w = outer_w;
+       scratchMem.delta_w.resize(n);
+       scratchMem.delta_x.resize(n);
+       scratchMem.Dell.resize(n);
+       scratchMem.ell.resize(n);
+       scratchMem.Arows.resize(n);
+       scratchMem.p.resize(n);
+       scratchMem.C.resize(n);
+
+       // for i in N, state[i] is 0 if x(i)==lo(i) or 1 if x(i)==hi(i)
+       scratchMem.state.resize(n);
+
+       // create LCP object. note that tmp is set to delta_w to save space, this
+       // optimization relies on knowledge of how tmp is used, so be careful!
+       btLCP lcp(n, nskip, nub, A, x, b, w, lo, hi, &scratchMem.L[0], &scratchMem.d[0], &scratchMem.Dell[0], &scratchMem.ell[0], &scratchMem.delta_w[0], &scratchMem.state[0], findex, &scratchMem.p[0], &scratchMem.C[0], &scratchMem.Arows[0]);
+       int adj_nub = lcp.getNub();
+
+       // loop over all indexes adj_nub..n-1. for index i, if x(i),w(i) satisfy the
+       // LCP conditions then i is added to the appropriate index set. otherwise
+       // x(i),w(i) is driven either +ve or -ve to force it to the valid region.
+       // as we drive x(i), x(C) is also adjusted to keep w(C) at zero.
+       // while driving x(i) we maintain the LCP conditions on the other variables
+       // 0..i-1. we do this by watching out for other x(i),w(i) values going
+       // outside the valid region, and then switching them between index sets
+       // when that happens.
+
+       bool hit_first_friction_index = false;
+       for (int i = adj_nub; i < n; ++i)
+       {
+               s_error = false;
+               // the index i is the driving index and indexes i+1..n-1 are "dont care",
+               // i.e. when we make changes to the system those x's will be zero and we
+               // don't care what happens to those w's. in other words, we only consider
+               // an (i+1)*(i+1) sub-problem of A*x=b+w.
+
+               // if we've hit the first friction index, we have to compute the lo and
+               // hi values based on the values of x already computed. we have been
+               // permuting the indexes, so the values stored in the findex vector are
+               // no longer valid. thus we have to temporarily unpermute the x vector.
+               // for the purposes of this computation, 0*infinity = 0 ... so if the
+               // contact constraint's normal force is 0, there should be no tangential
+               // force applied.
+
+               if (!hit_first_friction_index && findex && findex[i] >= 0)
+               {
+                       // un-permute x into delta_w, which is not being used at the moment
+                       for (int j = 0; j < n; ++j) scratchMem.delta_w[scratchMem.p[j]] = x[j];
+
+                       // set lo and hi values
+                       for (int k = i; k < n; ++k)
+                       {
+                               btScalar wfk = scratchMem.delta_w[findex[k]];
+                               if (wfk == 0)
+                               {
+                                       hi[k] = 0;
+                                       lo[k] = 0;
+                               }
+                               else
+                               {
+                                       hi[k] = btFabs(hi[k] * wfk);
+                                       lo[k] = -hi[k];
+                               }
+                       }
+                       hit_first_friction_index = true;
+               }
+
+               // thus far we have not even been computing the w values for indexes
+               // greater than i, so compute w[i] now.
+               w[i] = lcp.AiC_times_qC(i, x) + lcp.AiN_times_qN(i, x) - b[i];
+
+               // if lo=hi=0 (which can happen for tangential friction when normals are
+               // 0) then the index will be assigned to set N with some state. however,
+               // set C's line has zero size, so the index will always remain in set N.
+               // with the "normal" switching logic, if w changed sign then the index
+               // would have to switch to set C and then back to set N with an inverted
+               // state. this is pointless, and also computationally expensive. to
+               // prevent this from happening, we use the rule that indexes with lo=hi=0
+               // will never be checked for set changes. this means that the state for
+               // these indexes may be incorrect, but that doesn't matter.
+
+               // see if x(i),w(i) is in a valid region
+               if (lo[i] == 0 && w[i] >= 0)
+               {
+                       lcp.transfer_i_to_N(i);
+                       scratchMem.state[i] = false;
+               }
+               else if (hi[i] == 0 && w[i] <= 0)
+               {
+                       lcp.transfer_i_to_N(i);
+                       scratchMem.state[i] = true;
+               }
+               else if (w[i] == 0)
+               {
+                       // this is a degenerate case. by the time we get to this test we know
+                       // that lo != 0, which means that lo < 0 as lo is not allowed to be +ve,
+                       // and similarly that hi > 0. this means that the line segment
+                       // corresponding to set C is at least finite in extent, and we are on it.
+                       // NOTE: we must call lcp.solve1() before lcp.transfer_i_to_C()
+                       lcp.solve1(&scratchMem.delta_x[0], i, 0, 1);
+
+                       lcp.transfer_i_to_C(i);
+               }
+               else
+               {
+                       // we must push x(i) and w(i)
+                       for (;;)
+                       {
+                               int dir;
+                               btScalar dirf;
+                               // find direction to push on x(i)
+                               if (w[i] <= 0)
+                               {
+                                       dir = 1;
+                                       dirf = btScalar(1.0);
+                               }
+                               else
+                               {
+                                       dir = -1;
+                                       dirf = btScalar(-1.0);
+                               }
+
+                               // compute: delta_x(C) = -dir*A(C,C)\A(C,i)
+                               lcp.solve1(&scratchMem.delta_x[0], i, dir);
+
+                               // note that delta_x[i] = dirf, but we wont bother to set it
+
+                               // compute: delta_w = A*delta_x ... note we only care about
+                               // delta_w(N) and delta_w(i), the rest is ignored
+                               lcp.pN_equals_ANC_times_qC(&scratchMem.delta_w[0], &scratchMem.delta_x[0]);
+                               lcp.pN_plusequals_ANi(&scratchMem.delta_w[0], i, dir);
+                               scratchMem.delta_w[i] = lcp.AiC_times_qC(i, &scratchMem.delta_x[0]) + lcp.Aii(i) * dirf;
+
+                               // find largest step we can take (size=s), either to drive x(i),w(i)
+                               // to the valid LCP region or to drive an already-valid variable
+                               // outside the valid region.
+
+                               int cmd = 1;  // index switching command
+                               int si = 0;   // si = index to switch if cmd>3
+                               btScalar s = -w[i] / scratchMem.delta_w[i];
+                               if (dir > 0)
+                               {
+                                       if (hi[i] < BT_INFINITY)
+                                       {
+                                               btScalar s2 = (hi[i] - x[i]) * dirf;  // was (hi[i]-x[i])/dirf  // step to x(i)=hi(i)
+                                               if (s2 < s)
+                                               {
+                                                       s = s2;
+                                                       cmd = 3;
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       if (lo[i] > -BT_INFINITY)
+                                       {
+                                               btScalar s2 = (lo[i] - x[i]) * dirf;  // was (lo[i]-x[i])/dirf  // step to x(i)=lo(i)
+                                               if (s2 < s)
+                                               {
+                                                       s = s2;
+                                                       cmd = 2;
+                                               }
+                                       }
+                               }
+
+                               {
+                                       const int numN = lcp.numN();
+                                       for (int k = 0; k < numN; ++k)
+                                       {
+                                               const int indexN_k = lcp.indexN(k);
+                                               if (!scratchMem.state[indexN_k] ? scratchMem.delta_w[indexN_k] < 0 : scratchMem.delta_w[indexN_k] > 0)
+                                               {
+                                                       // don't bother checking if lo=hi=0
+                                                       if (lo[indexN_k] == 0 && hi[indexN_k] == 0) continue;
+                                                       btScalar s2 = -w[indexN_k] / scratchMem.delta_w[indexN_k];
+                                                       if (s2 < s)
+                                                       {
+                                                               s = s2;
+                                                               cmd = 4;
+                                                               si = indexN_k;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               {
+                                       const int numC = lcp.numC();
+                                       for (int k = adj_nub; k < numC; ++k)
+                                       {
+                                               const int indexC_k = lcp.indexC(k);
+                                               if (scratchMem.delta_x[indexC_k] < 0 && lo[indexC_k] > -BT_INFINITY)
+                                               {
+                                                       btScalar s2 = (lo[indexC_k] - x[indexC_k]) / scratchMem.delta_x[indexC_k];
+                                                       if (s2 < s)
+                                                       {
+                                                               s = s2;
+                                                               cmd = 5;
+                                                               si = indexC_k;
+                                                       }
+                                               }
+                                               if (scratchMem.delta_x[indexC_k] > 0 && hi[indexC_k] < BT_INFINITY)
+                                               {
+                                                       btScalar s2 = (hi[indexC_k] - x[indexC_k]) / scratchMem.delta_x[indexC_k];
+                                                       if (s2 < s)
+                                                       {
+                                                               s = s2;
+                                                               cmd = 6;
+                                                               si = indexC_k;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               //static char* cmdstring[8] = {0,"->C","->NL","->NH","N->C",
+                               //                           "C->NL","C->NH"};
+                               //printf ("cmd=%d (%s), si=%d\n",cmd,cmdstring[cmd],(cmd>3) ? si : i);
+
+                               // if s <= 0 then we've got a problem. if we just keep going then
+                               // we're going to get stuck in an infinite loop. instead, just cross
+                               // our fingers and exit with the current solution.
+                               if (s <= btScalar(0.0))
+                               {
+                                       //          printf("LCP internal error, s <= 0 (s=%.4e)",(double)s);
+                                       if (i < n)
+                                       {
+                                               btSetZero(x + i, n - i);
+                                               btSetZero(w + i, n - i);
+                                       }
+                                       s_error = true;
+                                       break;
+                               }
+
+                               // apply x = x + s * delta_x
+                               lcp.pC_plusequals_s_times_qC(x, s, &scratchMem.delta_x[0]);
+                               x[i] += s * dirf;
+
+                               // apply w = w + s * delta_w
+                               lcp.pN_plusequals_s_times_qN(w, s, &scratchMem.delta_w[0]);
+                               w[i] += s * scratchMem.delta_w[i];
+
+                               //        void *tmpbuf;
+                               // switch indexes between sets if necessary
+                               switch (cmd)
+                               {
+                                       case 1:  // done
+                                               w[i] = 0;
+                                               lcp.transfer_i_to_C(i);
+                                               break;
+                                       case 2:  // done
+                                               x[i] = lo[i];
+                                               scratchMem.state[i] = false;
+                                               lcp.transfer_i_to_N(i);
+                                               break;
+                                       case 3:  // done
+                                               x[i] = hi[i];
+                                               scratchMem.state[i] = true;
+                                               lcp.transfer_i_to_N(i);
+                                               break;
+                                       case 4:  // keep going
+                                               w[si] = 0;
+                                               lcp.transfer_i_from_N_to_C(si);
+                                               break;
+                                       case 5:  // keep going
+                                               x[si] = lo[si];
+                                               scratchMem.state[si] = false;
+                                               lcp.transfer_i_from_C_to_N(si, scratchMem.m_scratch);
+                                               break;
+                                       case 6:  // keep going
+                                               x[si] = hi[si];
+                                               scratchMem.state[si] = true;
+                                               lcp.transfer_i_from_C_to_N(si, scratchMem.m_scratch);
+                                               break;
+                               }
+
+                               if (cmd <= 3) break;
+                       }  // for (;;)
+               }      // else
+
+               if (s_error)
+               {
+                       break;
+               }
+       }  // for (int i=adj_nub; i<n; ++i)
+
+       lcp.unpermute();
+
+       return !s_error;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btDantzigLCP.h
new file mode 100644 (file)
index 0000000..8d9b2a1
--- /dev/null
@@ -0,0 +1,73 @@
+/*************************************************************************
+ *                                                                       *
+ * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
+ *                                                                       *
+ * This library is free software; you can redistribute it and/or         *
+ * modify it under the terms of                                          * 
+ *   The BSD-style license that is included with this library in         *
+ *   the file LICENSE-BSD.TXT.                                           *
+ *                                                                       *
+ * This library is distributed in the hope that it will be useful,       *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
+ *                                                                       *
+ *************************************************************************/
+
+/*
+
+given (A,b,lo,hi), solve the LCP problem: A*x = b+w, where each x(i),w(i)
+satisfies one of
+       (1) x = lo, w >= 0
+       (2) x = hi, w <= 0
+       (3) lo < x < hi, w = 0
+A is a matrix of dimension n*n, everything else is a vector of size n*1.
+lo and hi can be +/- dInfinity as needed. the first `nub' variables are
+unbounded, i.e. hi and lo are assumed to be +/- dInfinity.
+
+we restrict lo(i) <= 0 and hi(i) >= 0.
+
+the original data (A,b) may be modified by this function.
+
+if the `findex' (friction index) parameter is nonzero, it points to an array
+of index values. in this case constraints that have findex[i] >= 0 are
+special. all non-special constraints are solved for, then the lo and hi values
+for the special constraints are set:
+  hi[i] = abs( hi[i] * x[findex[i]] )
+  lo[i] = -hi[i]
+and the solution continues. this mechanism allows a friction approximation
+to be implemented. the first `nub' variables are assumed to have findex < 0.
+
+*/
+
+#ifndef _BT_LCP_H_
+#define _BT_LCP_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct btDantzigScratchMemory
+{
+       btAlignedObjectArray<btScalar> m_scratch;
+       btAlignedObjectArray<btScalar> L;
+       btAlignedObjectArray<btScalar> d;
+       btAlignedObjectArray<btScalar> delta_w;
+       btAlignedObjectArray<btScalar> delta_x;
+       btAlignedObjectArray<btScalar> Dell;
+       btAlignedObjectArray<btScalar> ell;
+       btAlignedObjectArray<btScalar *> Arows;
+       btAlignedObjectArray<int> p;
+       btAlignedObjectArray<int> C;
+       btAlignedObjectArray<bool> state;
+};
+
+//return false if solving failed
+bool btSolveDantzigLCP(int n, btScalar *A, btScalar *x, btScalar *b, btScalar *w,
+                                          int nub, btScalar *lo, btScalar *hi, int *findex, btDantzigScratchMemory &scratch);
+
+#endif  //_BT_LCP_H_
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btDantzigSolver.h
new file mode 100644 (file)
index 0000000..1f66975
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_DANTZIG_SOLVER_H
+#define BT_DANTZIG_SOLVER_H
+
+#include "btMLCPSolverInterface.h"
+#include "btDantzigLCP.h"
+
+class btDantzigSolver : public btMLCPSolverInterface
+{
+protected:
+       btScalar m_acceptableUpperLimitSolution;
+
+       btAlignedObjectArray<char> m_tempBuffer;
+
+       btAlignedObjectArray<btScalar> m_A;
+       btAlignedObjectArray<btScalar> m_b;
+       btAlignedObjectArray<btScalar> m_x;
+       btAlignedObjectArray<btScalar> m_lo;
+       btAlignedObjectArray<btScalar> m_hi;
+       btAlignedObjectArray<int> m_dependencies;
+       btDantzigScratchMemory m_scratchMemory;
+
+public:
+       btDantzigSolver()
+               : m_acceptableUpperLimitSolution(btScalar(1000))
+       {
+       }
+
+       virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+       {
+               bool result = true;
+               int n = b.rows();
+               if (n)
+               {
+                       int nub = 0;
+                       btAlignedObjectArray<btScalar> ww;
+                       ww.resize(n);
+
+                       const btScalar* Aptr = A.getBufferPointer();
+                       m_A.resize(n * n);
+                       for (int i = 0; i < n * n; i++)
+                       {
+                               m_A[i] = Aptr[i];
+                       }
+
+                       m_b.resize(n);
+                       m_x.resize(n);
+                       m_lo.resize(n);
+                       m_hi.resize(n);
+                       m_dependencies.resize(n);
+                       for (int i = 0; i < n; i++)
+                       {
+                               m_lo[i] = lo[i];
+                               m_hi[i] = hi[i];
+                               m_b[i] = b[i];
+                               m_x[i] = x[i];
+                               m_dependencies[i] = limitDependency[i];
+                       }
+
+                       result = btSolveDantzigLCP(n, &m_A[0], &m_x[0], &m_b[0], &ww[0], nub, &m_lo[0], &m_hi[0], &m_dependencies[0], m_scratchMemory);
+                       if (!result)
+                               return result;
+
+                       //                      printf("numAllocas = %d\n",numAllocas);
+                       for (int i = 0; i < n; i++)
+                       {
+                               volatile btScalar xx = m_x[i];
+                               if (xx != m_x[i])
+                                       return false;
+                               if (x[i] >= m_acceptableUpperLimitSolution)
+                               {
+                                       return false;
+                               }
+
+                               if (x[i] <= -m_acceptableUpperLimitSolution)
+                               {
+                                       return false;
+                               }
+                       }
+
+                       for (int i = 0; i < n; i++)
+                       {
+                               x[i] = m_x[i];
+                       }
+               }
+
+               return result;
+       }
+};
+
+#endif  //BT_DANTZIG_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp
new file mode 100644 (file)
index 0000000..1007d04
--- /dev/null
@@ -0,0 +1,393 @@
+/* Copyright (C) 2004-2013 MBSim Development Team
+
+Code was converted for the Bullet Continuous Collision Detection and Physics Library
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//The original version is here
+//https://code.google.com/p/mbsim-env/source/browse/trunk/kernel/mbsim/numerics/linear_complementarity_problem/lemke_algorithm.cc
+//This file is re-distributed under the ZLib license, with permission of the original author
+//Math library was replaced from fmatvec to a the file src/LinearMath/btMatrixX.h
+//STL/std::vector replaced by btAlignedObjectArray
+
+#include "btLemkeAlgorithm.h"
+
+#undef BT_DEBUG_OSTREAM
+#ifdef BT_DEBUG_OSTREAM
+using namespace std;
+#endif  //BT_DEBUG_OSTREAM
+
+btScalar btMachEps()
+{
+       static bool calculated = false;
+       static btScalar machEps = btScalar(1.);
+       if (!calculated)
+       {
+               do
+               {
+                       machEps /= btScalar(2.0);
+                       // If next epsilon yields 1, then break, because current
+                       // epsilon is the machine epsilon.
+               } while ((btScalar)(1.0 + (machEps / btScalar(2.0))) != btScalar(1.0));
+               //              printf( "\nCalculated Machine epsilon: %G\n", machEps );
+               calculated = true;
+       }
+       return machEps;
+}
+
+btScalar btEpsRoot()
+{
+       static btScalar epsroot = 0.;
+       static bool alreadyCalculated = false;
+
+       if (!alreadyCalculated)
+       {
+               epsroot = btSqrt(btMachEps());
+               alreadyCalculated = true;
+       }
+       return epsroot;
+}
+
+btVectorXu btLemkeAlgorithm::solve(unsigned int maxloops /* = 0*/)
+{
+       steps = 0;
+
+       int dim = m_q.size();
+#ifdef BT_DEBUG_OSTREAM
+       if (DEBUGLEVEL >= 1)
+       {
+               cout << "Dimension = " << dim << endl;
+       }
+#endif  //BT_DEBUG_OSTREAM
+
+       btVectorXu solutionVector(2 * dim);
+       solutionVector.setZero();
+
+       //, INIT, 0.);
+
+       btMatrixXu ident(dim, dim);
+       ident.setIdentity();
+#ifdef BT_DEBUG_OSTREAM
+       cout << m_M << std::endl;
+#endif
+
+       btMatrixXu mNeg = m_M.negative();
+
+       btMatrixXu A(dim, 2 * dim + 2);
+       //
+       A.setSubMatrix(0, 0, dim - 1, dim - 1, ident);
+       A.setSubMatrix(0, dim, dim - 1, 2 * dim - 1, mNeg);
+       A.setSubMatrix(0, 2 * dim, dim - 1, 2 * dim, -1.f);
+       A.setSubMatrix(0, 2 * dim + 1, dim - 1, 2 * dim + 1, m_q);
+
+#ifdef BT_DEBUG_OSTREAM
+       cout << A << std::endl;
+#endif  //BT_DEBUG_OSTREAM
+
+       //   btVectorXu q_;
+       //   q_ >> A(0, 2 * dim + 1, dim - 1, 2 * dim + 1);
+
+       btAlignedObjectArray<int> basis;
+       //At first, all w-values are in the basis
+       for (int i = 0; i < dim; i++)
+               basis.push_back(i);
+
+       int pivotRowIndex = -1;
+       btScalar minValue = 1e30f;
+       bool greaterZero = true;
+       for (int i = 0; i < dim; i++)
+       {
+               btScalar v = A(i, 2 * dim + 1);
+               if (v < minValue)
+               {
+                       minValue = v;
+                       pivotRowIndex = i;
+               }
+               if (v < 0)
+                       greaterZero = false;
+       }
+
+       //  int pivotRowIndex = q_.minIndex();//minIndex(q_);     // first row is that with lowest q-value
+       int z0Row = pivotRowIndex;    // remember the col of z0 for ending algorithm afterwards
+       int pivotColIndex = 2 * dim;  // first col is that of z0
+
+#ifdef BT_DEBUG_OSTREAM
+       if (DEBUGLEVEL >= 3)
+       {
+               //  cout << "A: " << A << endl;
+               cout << "pivotRowIndex " << pivotRowIndex << endl;
+               cout << "pivotColIndex " << pivotColIndex << endl;
+               cout << "Basis: ";
+               for (int i = 0; i < basis.size(); i++)
+                       cout << basis[i] << " ";
+               cout << endl;
+       }
+#endif  //BT_DEBUG_OSTREAM
+
+       if (!greaterZero)
+       {
+               if (maxloops == 0)
+               {
+                       maxloops = 100;
+                       //        maxloops = UINT_MAX; //TODO: not a really nice way, problem is: maxloops should be 2^dim (=1<<dim), but this could exceed UINT_MAX and thus the result would be 0 and therefore the lemke algorithm wouldn't start but probably would find a solution within less then UINT_MAX steps. Therefore this constant is used as a upper border right now...
+               }
+
+               /*start looping*/
+               for (steps = 0; steps < maxloops; steps++)
+               {
+                       GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
+#ifdef BT_DEBUG_OSTREAM
+                       if (DEBUGLEVEL >= 3)
+                       {
+                               //  cout << "A: " << A << endl;
+                               cout << "pivotRowIndex " << pivotRowIndex << endl;
+                               cout << "pivotColIndex " << pivotColIndex << endl;
+                               cout << "Basis: ";
+                               for (int i = 0; i < basis.size(); i++)
+                                       cout << basis[i] << " ";
+                               cout << endl;
+                       }
+#endif  //BT_DEBUG_OSTREAM
+
+                       int pivotColIndexOld = pivotColIndex;
+
+                       /*find new column index */
+                       if (basis[pivotRowIndex] < dim)  //if a w-value left the basis get in the correspondent z-value
+                               pivotColIndex = basis[pivotRowIndex] + dim;
+                       else
+                               //else do it the other way round and get in the corresponding w-value
+                               pivotColIndex = basis[pivotRowIndex] - dim;
+
+                       /*the column becomes part of the basis*/
+                       basis[pivotRowIndex] = pivotColIndexOld;
+                       bool isRayTermination = false;
+                       pivotRowIndex = findLexicographicMinimum(A, pivotColIndex, z0Row, isRayTermination);
+                       if (isRayTermination)
+                       {
+                               break; // ray termination
+                       }
+                       if (z0Row == pivotRowIndex)
+                       {  //if z0 leaves the basis the solution is found --> one last elimination step is necessary
+                               GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
+                               basis[pivotRowIndex] = pivotColIndex;  //update basis
+                               break;
+                       }
+               }
+#ifdef BT_DEBUG_OSTREAM
+               if (DEBUGLEVEL >= 1)
+               {
+                       cout << "Number of loops: " << steps << endl;
+                       cout << "Number of maximal loops: " << maxloops << endl;
+               }
+#endif  //BT_DEBUG_OSTREAM
+
+               if (!validBasis(basis))
+               {
+                       info = -1;
+#ifdef BT_DEBUG_OSTREAM
+                       if (DEBUGLEVEL >= 1)
+                               cerr << "Lemke-Algorithm ended with Ray-Termination (no valid solution)." << endl;
+#endif  //BT_DEBUG_OSTREAM
+
+                       return solutionVector;
+               }
+       }
+#ifdef BT_DEBUG_OSTREAM
+       if (DEBUGLEVEL >= 2)
+       {
+               // cout << "A: " << A << endl;
+               cout << "pivotRowIndex " << pivotRowIndex << endl;
+               cout << "pivotColIndex " << pivotColIndex << endl;
+       }
+#endif  //BT_DEBUG_OSTREAM
+
+       for (int i = 0; i < basis.size(); i++)
+       {
+               solutionVector[basis[i]] = A(i, 2 * dim + 1);  //q_[i];
+       }
+
+       info = 0;
+
+       return solutionVector;
+}
+
+int btLemkeAlgorithm::findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex, const int& z0Row, bool& isRayTermination)
+{
+       isRayTermination = false;
+       btAlignedObjectArray<int> activeRows;
+
+        bool firstRow = true;
+       btScalar currentMin = 0.0;
+
+       int dim = A.rows();
+
+       for (int row = 0; row < dim; row++)
+       {
+               const btScalar denom = A(row, pivotColIndex);
+
+               if (denom > btMachEps())
+               {
+                       const btScalar q = A(row, dim + dim + 1) / denom;
+                       if (firstRow)
+                       {
+                               currentMin = q;
+                               activeRows.push_back(row);
+                               firstRow = false;
+                       }
+                       else if (fabs(currentMin - q) < btMachEps())
+                       {
+                               activeRows.push_back(row);
+                       }
+                       else if (currentMin > q)
+                       {
+                               currentMin = q;
+                               activeRows.clear();
+                               activeRows.push_back(row);
+                       }
+               }
+       }
+
+       if (activeRows.size() == 0)
+       {
+               isRayTermination = true;
+               return 0;
+       }
+       else if (activeRows.size() == 1)
+       {
+               return activeRows[0];
+       }
+
+       // if there are multiple rows, check if they contain the row for z_0.
+       for (int i = 0; i < activeRows.size(); i++)
+       {
+               if (activeRows[i] == z0Row)
+               {
+                       return z0Row;
+               }
+       }
+
+       // look through the columns of the inverse of the basic matrix from left to right until the tie is broken.
+       for (int col = 0; col < dim ; col++)
+       {
+               btAlignedObjectArray<int> activeRowsCopy(activeRows);
+               activeRows.clear();
+               firstRow = true;
+               for (int i = 0; i<activeRowsCopy.size();i++)
+               {
+                       const int row = activeRowsCopy[i];
+
+                       // denom is positive here as an invariant.
+                       const btScalar denom = A(row, pivotColIndex);
+                       const btScalar ratio = A(row, col) / denom;
+                       if (firstRow)
+                       {
+                               currentMin = ratio;
+                               activeRows.push_back(row);
+                               firstRow = false;
+                       }
+                       else if (fabs(currentMin - ratio) < btMachEps())
+                       {
+                               activeRows.push_back(row);
+                       }
+                       else if (currentMin > ratio)
+                       {
+                               currentMin = ratio;
+                               activeRows.clear();
+                               activeRows.push_back(row);
+                       }
+               }
+
+               if (activeRows.size() == 1)
+               {
+                       return activeRows[0];
+               }
+       }
+       // must not reach here.
+       isRayTermination = true;
+       return 0;
+}
+
+void btLemkeAlgorithm::GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis)
+{
+       btScalar a = -1 / A(pivotRowIndex, pivotColumnIndex);
+#ifdef BT_DEBUG_OSTREAM
+       cout << A << std::endl;
+#endif
+
+       for (int i = 0; i < A.rows(); i++)
+       {
+               if (i != pivotRowIndex)
+               {
+                       for (int j = 0; j < A.cols(); j++)
+                       {
+                               if (j != pivotColumnIndex)
+                               {
+                                       btScalar v = A(i, j);
+                                       v += A(pivotRowIndex, j) * A(i, pivotColumnIndex) * a;
+                                       A.setElem(i, j, v);
+                               }
+                       }
+               }
+       }
+
+#ifdef BT_DEBUG_OSTREAM
+       cout << A << std::endl;
+#endif  //BT_DEBUG_OSTREAM
+       for (int i = 0; i < A.cols(); i++)
+       {
+               A.mulElem(pivotRowIndex, i, -a);
+       }
+#ifdef BT_DEBUG_OSTREAM
+       cout << A << std::endl;
+#endif  //#ifdef BT_DEBUG_OSTREAM
+
+       for (int i = 0; i < A.rows(); i++)
+       {
+               if (i != pivotRowIndex)
+               {
+                       A.setElem(i, pivotColumnIndex, 0);
+               }
+       }
+#ifdef BT_DEBUG_OSTREAM
+       cout << A << std::endl;
+#endif  //#ifdef BT_DEBUG_OSTREAM
+}
+
+bool btLemkeAlgorithm::greaterZero(const btVectorXu& vector)
+{
+       bool isGreater = true;
+       for (int i = 0; i < vector.size(); i++)
+       {
+               if (vector[i] < 0)
+               {
+                       isGreater = false;
+                       break;
+               }
+       }
+
+       return isGreater;
+}
+
+bool btLemkeAlgorithm::validBasis(const btAlignedObjectArray<int>& basis)
+{
+       bool isValid = true;
+       for (int i = 0; i < basis.size(); i++)
+       {
+               if (basis[i] >= basis.size() * 2)
+               {  //then z0 is in the base
+                       isValid = false;
+                       break;
+               }
+       }
+
+       return isValid;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h
new file mode 100644 (file)
index 0000000..6c498dd
--- /dev/null
@@ -0,0 +1,101 @@
+/* Copyright (C) 2004-2013 MBSim Development Team
+
+Code was converted for the Bullet Continuous Collision Detection and Physics Library
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//The original version is here
+//https://code.google.com/p/mbsim-env/source/browse/trunk/kernel/mbsim/numerics/linear_complementarity_problem/lemke_algorithm.cc
+//This file is re-distributed under the ZLib license, with permission of the original author (Kilian Grundl)
+//Math library was replaced from fmatvec to a the file src/LinearMath/btMatrixX.h
+//STL/std::vector replaced by btAlignedObjectArray
+
+#ifndef BT_NUMERICS_LEMKE_ALGORITHM_H_
+#define BT_NUMERICS_LEMKE_ALGORITHM_H_
+
+#include "LinearMath/btMatrixX.h"
+
+#include <vector>  //todo: replace by btAlignedObjectArray
+
+class btLemkeAlgorithm
+{
+public:
+       btLemkeAlgorithm(const btMatrixXu& M_, const btVectorXu& q_, const int& DEBUGLEVEL_ = 0) : DEBUGLEVEL(DEBUGLEVEL_)
+       {
+               setSystem(M_, q_);
+       }
+
+       /* GETTER / SETTER */
+       /**
+   * \brief return info of solution process
+   */
+       int getInfo()
+       {
+               return info;
+       }
+
+       /**
+   * \brief get the number of steps until the solution was found
+   */
+       int getSteps(void)
+       {
+               return steps;
+       }
+
+       /**
+   * \brief set system with Matrix M and vector q
+   */
+       void setSystem(const btMatrixXu& M_, const btVectorXu& q_)
+       {
+               m_M = M_;
+               m_q = q_;
+       }
+       /***************************************************/
+
+       /**
+   * \brief solve algorithm adapted from : Fast Implementation of Lemke’s Algorithm for Rigid Body Contact Simulation (John E. Lloyd)
+   */
+       btVectorXu solve(unsigned int maxloops = 0);
+
+       virtual ~btLemkeAlgorithm()
+       {
+       }
+
+protected:
+       int findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex, const int& z0Row, bool& isRayTermination);
+       void GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis);
+       bool greaterZero(const btVectorXu& vector);
+       bool validBasis(const btAlignedObjectArray<int>& basis);
+
+       btMatrixXu m_M;
+       btVectorXu m_q;
+
+       /**
+   * \brief number of steps until the Lemke algorithm found a solution
+   */
+       unsigned int steps;
+
+       /**
+   * \brief define level of debug output
+   */
+       int DEBUGLEVEL;
+
+       /**
+   * \brief did the algorithm find a solution
+   *
+   * -1 : not successful
+   *  0 : successful
+   */
+       int info;
+};
+
+#endif /* BT_NUMERICS_LEMKE_ALGORITHM_H_ */
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btLemkeSolver.h b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btLemkeSolver.h
new file mode 100644 (file)
index 0000000..f18c4ea
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_LEMKE_SOLVER_H
+#define BT_LEMKE_SOLVER_H
+
+#include "btMLCPSolverInterface.h"
+#include "btLemkeAlgorithm.h"
+
+///The btLemkeSolver is based on "Fast Implementation of Lemke’s Algorithm for Rigid Body Contact Simulation (John E. Lloyd) "
+///It is a slower but more accurate solver. Increase the m_maxLoops for better convergence, at the cost of more CPU time.
+///The original implementation of the btLemkeAlgorithm was done by Kilian Grundl from the MBSim team
+class btLemkeSolver : public btMLCPSolverInterface
+{
+protected:
+public:
+       btScalar m_maxValue;
+       int m_debugLevel;
+       int m_maxLoops;
+       bool m_useLoHighBounds;
+
+       btLemkeSolver()
+               : m_maxValue(100000),
+                 m_debugLevel(0),
+                 m_maxLoops(1000),
+                 m_useLoHighBounds(true)
+       {
+       }
+       virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+       {
+               if (m_useLoHighBounds)
+               {
+                       BT_PROFILE("btLemkeSolver::solveMLCP");
+                       int n = A.rows();
+                       if (0 == n)
+                               return true;
+
+                       bool fail = false;
+
+                       btVectorXu solution(n);
+                       btVectorXu q1;
+                       q1.resize(n);
+                       for (int row = 0; row < n; row++)
+                       {
+                               q1[row] = -b[row];
+                       }
+
+                       //              cout << "A" << endl;
+                       //              cout << A << endl;
+
+                       /////////////////////////////////////
+
+                       //slow matrix inversion, replace with LU decomposition
+                       btMatrixXu A1;
+                       btMatrixXu B(n, n);
+                       {
+                               //BT_PROFILE("inverse(slow)");
+                               A1.resize(A.rows(), A.cols());
+                               for (int row = 0; row < A.rows(); row++)
+                               {
+                                       for (int col = 0; col < A.cols(); col++)
+                                       {
+                                               A1.setElem(row, col, A(row, col));
+                                       }
+                               }
+
+                               btMatrixXu matrix;
+                               matrix.resize(n, 2 * n);
+                               for (int row = 0; row < n; row++)
+                               {
+                                       for (int col = 0; col < n; col++)
+                                       {
+                                               matrix.setElem(row, col, A1(row, col));
+                                       }
+                               }
+
+                               btScalar ratio, a;
+                               int i, j, k;
+                               for (i = 0; i < n; i++)
+                               {
+                                       for (j = n; j < 2 * n; j++)
+                                       {
+                                               if (i == (j - n))
+                                                       matrix.setElem(i, j, 1.0);
+                                               else
+                                                       matrix.setElem(i, j, 0.0);
+                                       }
+                               }
+                               for (i = 0; i < n; i++)
+                               {
+                                       for (j = 0; j < n; j++)
+                                       {
+                                               if (i != j)
+                                               {
+                                                       btScalar v = matrix(i, i);
+                                                       if (btFuzzyZero(v))
+                                                       {
+                                                               a = 0.000001f;
+                                                       }
+                                                       ratio = matrix(j, i) / matrix(i, i);
+                                                       for (k = 0; k < 2 * n; k++)
+                                                       {
+                                                               matrix.addElem(j, k, -ratio * matrix(i, k));
+                                                       }
+                                               }
+                                       }
+                               }
+                               for (i = 0; i < n; i++)
+                               {
+                                       a = matrix(i, i);
+                                       if (btFuzzyZero(a))
+                                       {
+                                               a = 0.000001f;
+                                       }
+                                       btScalar invA = 1.f / a;
+                                       for (j = 0; j < 2 * n; j++)
+                                       {
+                                               matrix.mulElem(i, j, invA);
+                                       }
+                               }
+
+                               for (int row = 0; row < n; row++)
+                               {
+                                       for (int col = 0; col < n; col++)
+                                       {
+                                               B.setElem(row, col, matrix(row, n + col));
+                                       }
+                               }
+                       }
+
+                       btMatrixXu b1(n, 1);
+
+                       btMatrixXu M(n * 2, n * 2);
+                       for (int row = 0; row < n; row++)
+                       {
+                               b1.setElem(row, 0, -b[row]);
+                               for (int col = 0; col < n; col++)
+                               {
+                                       btScalar v = B(row, col);
+                                       M.setElem(row, col, v);
+                                       M.setElem(n + row, n + col, v);
+                                       M.setElem(n + row, col, -v);
+                                       M.setElem(row, n + col, -v);
+                               }
+                       }
+
+                       btMatrixXu Bb1 = B * b1;
+                       //              q = [ (-B*b1 - lo)'   (hi + B*b1)' ]'
+
+                       btVectorXu qq;
+                       qq.resize(n * 2);
+                       for (int row = 0; row < n; row++)
+                       {
+                               qq[row] = -Bb1(row, 0) - lo[row];
+                               qq[n + row] = Bb1(row, 0) + hi[row];
+                       }
+
+                       btVectorXu z1;
+
+                       btMatrixXu y1;
+                       y1.resize(n, 1);
+                       btLemkeAlgorithm lemke(M, qq, m_debugLevel);
+                       {
+                               //BT_PROFILE("lemke.solve");
+                               lemke.setSystem(M, qq);
+                               z1 = lemke.solve(m_maxLoops);
+                       }
+                       for (int row = 0; row < n; row++)
+                       {
+                               y1.setElem(row, 0, z1[2 * n + row] - z1[3 * n + row]);
+                       }
+                       btMatrixXu y1_b1(n, 1);
+                       for (int i = 0; i < n; i++)
+                       {
+                               y1_b1.setElem(i, 0, y1(i, 0) - b1(i, 0));
+                       }
+
+                       btMatrixXu x1;
+
+                       x1 = B * (y1_b1);
+
+                       for (int row = 0; row < n; row++)
+                       {
+                               solution[row] = x1(row, 0);  //n];
+                       }
+
+                       int errorIndexMax = -1;
+                       int errorIndexMin = -1;
+                       float errorValueMax = -1e30;
+                       float errorValueMin = 1e30;
+
+                       for (int i = 0; i < n; i++)
+                       {
+                               x[i] = solution[i];
+                               volatile btScalar check = x[i];
+                               if (x[i] != check)
+                               {
+                                       //printf("Lemke result is #NAN\n");
+                                       x.setZero();
+                                       return false;
+                               }
+
+                               //this is some hack/safety mechanism, to discard invalid solutions from the Lemke solver
+                               //we need to figure out why it happens, and fix it, or detect it properly)
+                               if (x[i] > m_maxValue)
+                               {
+                                       if (x[i] > errorValueMax)
+                                       {
+                                               fail = true;
+                                               errorIndexMax = i;
+                                               errorValueMax = x[i];
+                                       }
+                                       ////printf("x[i] = %f,",x[i]);
+                               }
+                               if (x[i] < -m_maxValue)
+                               {
+                                       if (x[i] < errorValueMin)
+                                       {
+                                               errorIndexMin = i;
+                                               errorValueMin = x[i];
+                                               fail = true;
+                                               //printf("x[i] = %f,",x[i]);
+                                       }
+                               }
+                       }
+                       if (fail)
+                       {
+                               int m_errorCountTimes = 0;
+                               if (errorIndexMin < 0)
+                                       errorValueMin = 0.f;
+                               if (errorIndexMax < 0)
+                                       errorValueMax = 0.f;
+                               m_errorCountTimes++;
+                               //      printf("Error (x[%d] = %f, x[%d] = %f), resetting %d times\n", errorIndexMin,errorValueMin, errorIndexMax, errorValueMax, errorCountTimes++);
+                               for (int i = 0; i < n; i++)
+                               {
+                                       x[i] = 0.f;
+                               }
+                       }
+                       return !fail;
+               }
+               else
+
+               {
+                       int dimension = A.rows();
+                       if (0 == dimension)
+                               return true;
+
+                       //              printf("================ solving using Lemke/Newton/Fixpoint\n");
+
+                       btVectorXu q;
+                       q.resize(dimension);
+                       for (int row = 0; row < dimension; row++)
+                       {
+                               q[row] = -b[row];
+                       }
+
+                       btLemkeAlgorithm lemke(A, q, m_debugLevel);
+
+                       lemke.setSystem(A, q);
+
+                       btVectorXu solution = lemke.solve(m_maxLoops);
+
+                       //check solution
+
+                       bool fail = false;
+                       int errorIndexMax = -1;
+                       int errorIndexMin = -1;
+                       float errorValueMax = -1e30;
+                       float errorValueMin = 1e30;
+
+                       for (int i = 0; i < dimension; i++)
+                       {
+                               x[i] = solution[i + dimension];
+                               volatile btScalar check = x[i];
+                               if (x[i] != check)
+                               {
+                                       x.setZero();
+                                       return false;
+                               }
+
+                               //this is some hack/safety mechanism, to discard invalid solutions from the Lemke solver
+                               //we need to figure out why it happens, and fix it, or detect it properly)
+                               if (x[i] > m_maxValue)
+                               {
+                                       if (x[i] > errorValueMax)
+                                       {
+                                               fail = true;
+                                               errorIndexMax = i;
+                                               errorValueMax = x[i];
+                                       }
+                                       ////printf("x[i] = %f,",x[i]);
+                               }
+                               if (x[i] < -m_maxValue)
+                               {
+                                       if (x[i] < errorValueMin)
+                                       {
+                                               errorIndexMin = i;
+                                               errorValueMin = x[i];
+                                               fail = true;
+                                               //printf("x[i] = %f,",x[i]);
+                                       }
+                               }
+                       }
+                       if (fail)
+                       {
+                               static int errorCountTimes = 0;
+                               if (errorIndexMin < 0)
+                                       errorValueMin = 0.f;
+                               if (errorIndexMax < 0)
+                                       errorValueMax = 0.f;
+                               printf("Error (x[%d] = %f, x[%d] = %f), resetting %d times\n", errorIndexMin, errorValueMin, errorIndexMax, errorValueMax, errorCountTimes++);
+                               for (int i = 0; i < dimension; i++)
+                               {
+                                       x[i] = 0.f;
+                               }
+                       }
+
+                       return !fail;
+               }
+               return true;
+       }
+};
+
+#endif  //BT_LEMKE_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp
new file mode 100644 (file)
index 0000000..ed4e0b6
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#include "btMLCPSolver.h"
+#include "LinearMath/btMatrixX.h"
+#include "LinearMath/btQuickprof.h"
+#include "btSolveProjectedGaussSeidel.h"
+
+btMLCPSolver::btMLCPSolver(btMLCPSolverInterface* solver)
+       : m_solver(solver),
+         m_fallback(0)
+{
+}
+
+btMLCPSolver::~btMLCPSolver()
+{
+}
+
+bool gUseMatrixMultiply = false;
+bool interleaveContactAndFriction = false;
+
+btScalar btMLCPSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodiesUnUsed, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodiesUnUsed, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+       {
+               BT_PROFILE("gather constraint data");
+
+               int numFrictionPerContact = m_tmpSolverContactConstraintPool.size() == m_tmpSolverContactFrictionConstraintPool.size() ? 1 : 2;
+
+               //      int numBodies = m_tmpSolverBodyPool.size();
+               m_allConstraintPtrArray.resize(0);
+               m_limitDependencies.resize(m_tmpSolverNonContactConstraintPool.size() + m_tmpSolverContactConstraintPool.size() + m_tmpSolverContactFrictionConstraintPool.size());
+               btAssert(m_limitDependencies.size() == m_tmpSolverNonContactConstraintPool.size() + m_tmpSolverContactConstraintPool.size() + m_tmpSolverContactFrictionConstraintPool.size());
+               //      printf("m_limitDependencies.size() = %d\n",m_limitDependencies.size());
+
+               int dindex = 0;
+               for (int i = 0; i < m_tmpSolverNonContactConstraintPool.size(); i++)
+               {
+                       m_allConstraintPtrArray.push_back(&m_tmpSolverNonContactConstraintPool[i]);
+                       m_limitDependencies[dindex++] = -1;
+               }
+
+               ///The btSequentialImpulseConstraintSolver moves all friction constraints at the very end, we can also interleave them instead
+
+               int firstContactConstraintOffset = dindex;
+
+               if (interleaveContactAndFriction)
+               {
+                       for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
+                       {
+                               m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
+                               m_limitDependencies[dindex++] = -1;
+                               m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact]);
+                               int findex = (m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact].m_frictionIndex * (1 + numFrictionPerContact));
+                               m_limitDependencies[dindex++] = findex + firstContactConstraintOffset;
+                               if (numFrictionPerContact == 2)
+                               {
+                                       m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact + 1]);
+                                       m_limitDependencies[dindex++] = findex + firstContactConstraintOffset;
+                               }
+                       }
+               }
+               else
+               {
+                       for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
+                       {
+                               m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
+                               m_limitDependencies[dindex++] = -1;
+                       }
+                       for (int i = 0; i < m_tmpSolverContactFrictionConstraintPool.size(); i++)
+                       {
+                               m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i]);
+                               m_limitDependencies[dindex++] = m_tmpSolverContactFrictionConstraintPool[i].m_frictionIndex + firstContactConstraintOffset;
+                       }
+               }
+
+               if (!m_allConstraintPtrArray.size())
+               {
+                       m_A.resize(0, 0);
+                       m_b.resize(0);
+                       m_x.resize(0);
+                       m_lo.resize(0);
+                       m_hi.resize(0);
+                       return 0.f;
+               }
+       }
+
+       if (gUseMatrixMultiply)
+       {
+               BT_PROFILE("createMLCP");
+               createMLCP(infoGlobal);
+       }
+       else
+       {
+               BT_PROFILE("createMLCPFast");
+               createMLCPFast(infoGlobal);
+       }
+
+       return 0.f;
+}
+
+bool btMLCPSolver::solveMLCP(const btContactSolverInfo& infoGlobal)
+{
+       bool result = true;
+
+       if (m_A.rows() == 0)
+               return true;
+
+       //if using split impulse, we solve 2 separate (M)LCPs
+       if (infoGlobal.m_splitImpulse)
+       {
+               btMatrixXu Acopy = m_A;
+               btAlignedObjectArray<int> limitDependenciesCopy = m_limitDependencies;
+               //              printf("solve first LCP\n");
+               result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo, m_hi, m_limitDependencies, infoGlobal.m_numIterations);
+               if (result)
+                       result = m_solver->solveMLCP(Acopy, m_bSplit, m_xSplit, m_lo, m_hi, limitDependenciesCopy, infoGlobal.m_numIterations);
+       }
+       else
+       {
+               result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo, m_hi, m_limitDependencies, infoGlobal.m_numIterations);
+       }
+       return result;
+}
+
+struct btJointNode
+{
+       int jointIndex;          // pointer to enclosing dxJoint object
+       int otherBodyIndex;      // *other* body this joint is connected to
+       int nextJointNodeIndex;  //-1 for null
+       int constraintRowIndex;
+};
+
+void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
+{
+       int numContactRows = interleaveContactAndFriction ? 3 : 1;
+
+       int numConstraintRows = m_allConstraintPtrArray.size();
+       int n = numConstraintRows;
+       {
+               BT_PROFILE("init b (rhs)");
+               m_b.resize(numConstraintRows);
+               m_bSplit.resize(numConstraintRows);
+               m_b.setZero();
+               m_bSplit.setZero();
+               for (int i = 0; i < numConstraintRows; i++)
+               {
+                       btScalar jacDiag = m_allConstraintPtrArray[i]->m_jacDiagABInv;
+                       if (!btFuzzyZero(jacDiag))
+                       {
+                               btScalar rhs = m_allConstraintPtrArray[i]->m_rhs;
+                               btScalar rhsPenetration = m_allConstraintPtrArray[i]->m_rhsPenetration;
+                               m_b[i] = rhs / jacDiag;
+                               m_bSplit[i] = rhsPenetration / jacDiag;
+                       }
+               }
+       }
+
+       //      btScalar* w = 0;
+       //      int nub = 0;
+
+       m_lo.resize(numConstraintRows);
+       m_hi.resize(numConstraintRows);
+
+       {
+               BT_PROFILE("init lo/ho");
+
+               for (int i = 0; i < numConstraintRows; i++)
+               {
+                       if (0)  //m_limitDependencies[i]>=0)
+                       {
+                               m_lo[i] = -BT_INFINITY;
+                               m_hi[i] = BT_INFINITY;
+                       }
+                       else
+                       {
+                               m_lo[i] = m_allConstraintPtrArray[i]->m_lowerLimit;
+                               m_hi[i] = m_allConstraintPtrArray[i]->m_upperLimit;
+                       }
+               }
+       }
+
+       //
+       int m = m_allConstraintPtrArray.size();
+
+       int numBodies = m_tmpSolverBodyPool.size();
+       btAlignedObjectArray<int> bodyJointNodeArray;
+       {
+               BT_PROFILE("bodyJointNodeArray.resize");
+               bodyJointNodeArray.resize(numBodies, -1);
+       }
+       btAlignedObjectArray<btJointNode> jointNodeArray;
+       {
+               BT_PROFILE("jointNodeArray.reserve");
+               jointNodeArray.reserve(2 * m_allConstraintPtrArray.size());
+       }
+
+       btMatrixXu& J3 = m_scratchJ3;
+       {
+               BT_PROFILE("J3.resize");
+               J3.resize(2 * m, 8);
+       }
+       btMatrixXu& JinvM3 = m_scratchJInvM3;
+       {
+               BT_PROFILE("JinvM3.resize/setZero");
+
+               JinvM3.resize(2 * m, 8);
+               JinvM3.setZero();
+               J3.setZero();
+       }
+       int cur = 0;
+       int rowOffset = 0;
+       btAlignedObjectArray<int>& ofs = m_scratchOfs;
+       {
+               BT_PROFILE("ofs resize");
+               ofs.resize(0);
+               ofs.resizeNoInitialize(m_allConstraintPtrArray.size());
+       }
+       {
+               BT_PROFILE("Compute J and JinvM");
+               int c = 0;
+
+               int numRows = 0;
+
+               for (int i = 0; i < m_allConstraintPtrArray.size(); i += numRows, c++)
+               {
+                       ofs[c] = rowOffset;
+                       int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
+                       int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
+                       btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+                       btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+                       numRows = i < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows;
+                       if (orgBodyA)
+                       {
+                               {
+                                       int slotA = -1;
+                                       //find free jointNode slot for sbA
+                                       slotA = jointNodeArray.size();
+                                       jointNodeArray.expand();  //NonInitializing();
+                                       int prevSlot = bodyJointNodeArray[sbA];
+                                       bodyJointNodeArray[sbA] = slotA;
+                                       jointNodeArray[slotA].nextJointNodeIndex = prevSlot;
+                                       jointNodeArray[slotA].jointIndex = c;
+                                       jointNodeArray[slotA].constraintRowIndex = i;
+                                       jointNodeArray[slotA].otherBodyIndex = orgBodyB ? sbB : -1;
+                               }
+                               for (int row = 0; row < numRows; row++, cur++)
+                               {
+                                       btVector3 normalInvMass = m_allConstraintPtrArray[i + row]->m_contactNormal1 * orgBodyA->getInvMass();
+                                       btVector3 relPosCrossNormalInvInertia = m_allConstraintPtrArray[i + row]->m_relpos1CrossNormal * orgBodyA->getInvInertiaTensorWorld();
+
+                                       for (int r = 0; r < 3; r++)
+                                       {
+                                               J3.setElem(cur, r, m_allConstraintPtrArray[i + row]->m_contactNormal1[r]);
+                                               J3.setElem(cur, r + 4, m_allConstraintPtrArray[i + row]->m_relpos1CrossNormal[r]);
+                                               JinvM3.setElem(cur, r, normalInvMass[r]);
+                                               JinvM3.setElem(cur, r + 4, relPosCrossNormalInvInertia[r]);
+                                       }
+                                       J3.setElem(cur, 3, 0);
+                                       JinvM3.setElem(cur, 3, 0);
+                                       J3.setElem(cur, 7, 0);
+                                       JinvM3.setElem(cur, 7, 0);
+                               }
+                       }
+                       else
+                       {
+                               cur += numRows;
+                       }
+                       if (orgBodyB)
+                       {
+                               {
+                                       int slotB = -1;
+                                       //find free jointNode slot for sbA
+                                       slotB = jointNodeArray.size();
+                                       jointNodeArray.expand();  //NonInitializing();
+                                       int prevSlot = bodyJointNodeArray[sbB];
+                                       bodyJointNodeArray[sbB] = slotB;
+                                       jointNodeArray[slotB].nextJointNodeIndex = prevSlot;
+                                       jointNodeArray[slotB].jointIndex = c;
+                                       jointNodeArray[slotB].otherBodyIndex = orgBodyA ? sbA : -1;
+                                       jointNodeArray[slotB].constraintRowIndex = i;
+                               }
+
+                               for (int row = 0; row < numRows; row++, cur++)
+                               {
+                                       btVector3 normalInvMassB = m_allConstraintPtrArray[i + row]->m_contactNormal2 * orgBodyB->getInvMass();
+                                       btVector3 relPosInvInertiaB = m_allConstraintPtrArray[i + row]->m_relpos2CrossNormal * orgBodyB->getInvInertiaTensorWorld();
+
+                                       for (int r = 0; r < 3; r++)
+                                       {
+                                               J3.setElem(cur, r, m_allConstraintPtrArray[i + row]->m_contactNormal2[r]);
+                                               J3.setElem(cur, r + 4, m_allConstraintPtrArray[i + row]->m_relpos2CrossNormal[r]);
+                                               JinvM3.setElem(cur, r, normalInvMassB[r]);
+                                               JinvM3.setElem(cur, r + 4, relPosInvInertiaB[r]);
+                                       }
+                                       J3.setElem(cur, 3, 0);
+                                       JinvM3.setElem(cur, 3, 0);
+                                       J3.setElem(cur, 7, 0);
+                                       JinvM3.setElem(cur, 7, 0);
+                               }
+                       }
+                       else
+                       {
+                               cur += numRows;
+                       }
+                       rowOffset += numRows;
+               }
+       }
+
+       //compute JinvM = J*invM.
+       const btScalar* JinvM = JinvM3.getBufferPointer();
+
+       const btScalar* Jptr = J3.getBufferPointer();
+       {
+               BT_PROFILE("m_A.resize");
+               m_A.resize(n, n);
+       }
+
+       {
+               BT_PROFILE("m_A.setZero");
+               m_A.setZero();
+       }
+       int c = 0;
+       {
+               int numRows = 0;
+               BT_PROFILE("Compute A");
+               for (int i = 0; i < m_allConstraintPtrArray.size(); i += numRows, c++)
+               {
+                       int row__ = ofs[c];
+                       int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
+                       int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
+                       //      btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+                       //      btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+                       numRows = i < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows;
+
+                       const btScalar* JinvMrow = JinvM + 2 * 8 * (size_t)row__;
+
+                       {
+                               int startJointNodeA = bodyJointNodeArray[sbA];
+                               while (startJointNodeA >= 0)
+                               {
+                                       int j0 = jointNodeArray[startJointNodeA].jointIndex;
+                                       int cr0 = jointNodeArray[startJointNodeA].constraintRowIndex;
+                                       if (j0 < c)
+                                       {
+                                               int numRowsOther = cr0 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j0].m_numConstraintRows : numContactRows;
+                                               size_t ofsother = (m_allConstraintPtrArray[cr0]->m_solverBodyIdB == sbA) ? 8 * numRowsOther : 0;
+                                               //printf("%d joint i %d and j0: %d: ",count++,i,j0);
+                                               m_A.multiplyAdd2_p8r(JinvMrow,
+                                                                                        Jptr + 2 * 8 * (size_t)ofs[j0] + ofsother, numRows, numRowsOther, row__, ofs[j0]);
+                                       }
+                                       startJointNodeA = jointNodeArray[startJointNodeA].nextJointNodeIndex;
+                               }
+                       }
+
+                       {
+                               int startJointNodeB = bodyJointNodeArray[sbB];
+                               while (startJointNodeB >= 0)
+                               {
+                                       int j1 = jointNodeArray[startJointNodeB].jointIndex;
+                                       int cj1 = jointNodeArray[startJointNodeB].constraintRowIndex;
+
+                                       if (j1 < c)
+                                       {
+                                               int numRowsOther = cj1 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j1].m_numConstraintRows : numContactRows;
+                                               size_t ofsother = (m_allConstraintPtrArray[cj1]->m_solverBodyIdB == sbB) ? 8 * numRowsOther : 0;
+                                               m_A.multiplyAdd2_p8r(JinvMrow + 8 * (size_t)numRows,
+                                                                                        Jptr + 2 * 8 * (size_t)ofs[j1] + ofsother, numRows, numRowsOther, row__, ofs[j1]);
+                                       }
+                                       startJointNodeB = jointNodeArray[startJointNodeB].nextJointNodeIndex;
+                               }
+                       }
+               }
+
+               {
+                       BT_PROFILE("compute diagonal");
+                       // compute diagonal blocks of m_A
+
+                       int row__ = 0;
+                       int numJointRows = m_allConstraintPtrArray.size();
+
+                       int jj = 0;
+                       for (; row__ < numJointRows;)
+                       {
+                               //int sbA = m_allConstraintPtrArray[row__]->m_solverBodyIdA;
+                               int sbB = m_allConstraintPtrArray[row__]->m_solverBodyIdB;
+                               //      btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+                               btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+                               const unsigned int infom = row__ < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[jj].m_numConstraintRows : numContactRows;
+
+                               const btScalar* JinvMrow = JinvM + 2 * 8 * (size_t)row__;
+                               const btScalar* Jrow = Jptr + 2 * 8 * (size_t)row__;
+                               m_A.multiply2_p8r(JinvMrow, Jrow, infom, infom, row__, row__);
+                               if (orgBodyB)
+                               {
+                                       m_A.multiplyAdd2_p8r(JinvMrow + 8 * (size_t)infom, Jrow + 8 * (size_t)infom, infom, infom, row__, row__);
+                               }
+                               row__ += infom;
+                               jj++;
+                       }
+               }
+       }
+
+       if (1)
+       {
+               // add cfm to the diagonal of m_A
+               for (int i = 0; i < m_A.rows(); ++i)
+               {
+                       m_A.setElem(i, i, m_A(i, i) + infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
+               }
+       }
+
+       ///fill the upper triangle of the matrix, to make it symmetric
+       {
+               BT_PROFILE("fill the upper triangle ");
+               m_A.copyLowerToUpperTriangle();
+       }
+
+       {
+               BT_PROFILE("resize/init x");
+               m_x.resize(numConstraintRows);
+               m_xSplit.resize(numConstraintRows);
+
+               if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+               {
+                       for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
+                       {
+                               const btSolverConstraint& c = *m_allConstraintPtrArray[i];
+                               m_x[i] = c.m_appliedImpulse;
+                               m_xSplit[i] = c.m_appliedPushImpulse;
+                       }
+               }
+               else
+               {
+                       m_x.setZero();
+                       m_xSplit.setZero();
+               }
+       }
+}
+
+void btMLCPSolver::createMLCP(const btContactSolverInfo& infoGlobal)
+{
+       int numBodies = this->m_tmpSolverBodyPool.size();
+       int numConstraintRows = m_allConstraintPtrArray.size();
+
+       m_b.resize(numConstraintRows);
+       if (infoGlobal.m_splitImpulse)
+               m_bSplit.resize(numConstraintRows);
+
+       m_bSplit.setZero();
+       m_b.setZero();
+
+       for (int i = 0; i < numConstraintRows; i++)
+       {
+               if (m_allConstraintPtrArray[i]->m_jacDiagABInv)
+               {
+                       m_b[i] = m_allConstraintPtrArray[i]->m_rhs / m_allConstraintPtrArray[i]->m_jacDiagABInv;
+                       if (infoGlobal.m_splitImpulse)
+                               m_bSplit[i] = m_allConstraintPtrArray[i]->m_rhsPenetration / m_allConstraintPtrArray[i]->m_jacDiagABInv;
+               }
+       }
+
+       btMatrixXu& Minv = m_scratchMInv;
+       Minv.resize(6 * numBodies, 6 * numBodies);
+       Minv.setZero();
+       for (int i = 0; i < numBodies; i++)
+       {
+               const btSolverBody& rb = m_tmpSolverBodyPool[i];
+               const btVector3& invMass = rb.m_invMass;
+               setElem(Minv, i * 6 + 0, i * 6 + 0, invMass[0]);
+               setElem(Minv, i * 6 + 1, i * 6 + 1, invMass[1]);
+               setElem(Minv, i * 6 + 2, i * 6 + 2, invMass[2]);
+               btRigidBody* orgBody = m_tmpSolverBodyPool[i].m_originalBody;
+
+               for (int r = 0; r < 3; r++)
+                       for (int c = 0; c < 3; c++)
+                               setElem(Minv, i * 6 + 3 + r, i * 6 + 3 + c, orgBody ? orgBody->getInvInertiaTensorWorld()[r][c] : 0);
+       }
+
+       btMatrixXu& J = m_scratchJ;
+       J.resize(numConstraintRows, 6 * numBodies);
+       J.setZero();
+
+       m_lo.resize(numConstraintRows);
+       m_hi.resize(numConstraintRows);
+
+       for (int i = 0; i < numConstraintRows; i++)
+       {
+               m_lo[i] = m_allConstraintPtrArray[i]->m_lowerLimit;
+               m_hi[i] = m_allConstraintPtrArray[i]->m_upperLimit;
+
+               int bodyIndex0 = m_allConstraintPtrArray[i]->m_solverBodyIdA;
+               int bodyIndex1 = m_allConstraintPtrArray[i]->m_solverBodyIdB;
+               if (m_tmpSolverBodyPool[bodyIndex0].m_originalBody)
+               {
+                       setElem(J, i, 6 * bodyIndex0 + 0, m_allConstraintPtrArray[i]->m_contactNormal1[0]);
+                       setElem(J, i, 6 * bodyIndex0 + 1, m_allConstraintPtrArray[i]->m_contactNormal1[1]);
+                       setElem(J, i, 6 * bodyIndex0 + 2, m_allConstraintPtrArray[i]->m_contactNormal1[2]);
+                       setElem(J, i, 6 * bodyIndex0 + 3, m_allConstraintPtrArray[i]->m_relpos1CrossNormal[0]);
+                       setElem(J, i, 6 * bodyIndex0 + 4, m_allConstraintPtrArray[i]->m_relpos1CrossNormal[1]);
+                       setElem(J, i, 6 * bodyIndex0 + 5, m_allConstraintPtrArray[i]->m_relpos1CrossNormal[2]);
+               }
+               if (m_tmpSolverBodyPool[bodyIndex1].m_originalBody)
+               {
+                       setElem(J, i, 6 * bodyIndex1 + 0, m_allConstraintPtrArray[i]->m_contactNormal2[0]);
+                       setElem(J, i, 6 * bodyIndex1 + 1, m_allConstraintPtrArray[i]->m_contactNormal2[1]);
+                       setElem(J, i, 6 * bodyIndex1 + 2, m_allConstraintPtrArray[i]->m_contactNormal2[2]);
+                       setElem(J, i, 6 * bodyIndex1 + 3, m_allConstraintPtrArray[i]->m_relpos2CrossNormal[0]);
+                       setElem(J, i, 6 * bodyIndex1 + 4, m_allConstraintPtrArray[i]->m_relpos2CrossNormal[1]);
+                       setElem(J, i, 6 * bodyIndex1 + 5, m_allConstraintPtrArray[i]->m_relpos2CrossNormal[2]);
+               }
+       }
+
+       btMatrixXu& J_transpose = m_scratchJTranspose;
+       J_transpose = J.transpose();
+
+       btMatrixXu& tmp = m_scratchTmp;
+       //Minv.printMatrix("Minv=");
+       {
+               {
+                       BT_PROFILE("J*Minv");
+                       tmp = J * Minv;
+               }
+               {
+                       BT_PROFILE("J*tmp");
+                       m_A = tmp * J_transpose;
+               }
+       }
+       //J.printMatrix("J");
+       if (1)
+       {
+               // add cfm to the diagonal of m_A
+               for (int i = 0; i < m_A.rows(); ++i)
+               {
+                       m_A.setElem(i, i, m_A(i, i) + infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
+               }
+       }
+
+       m_x.resize(numConstraintRows);
+       if (infoGlobal.m_splitImpulse)
+               m_xSplit.resize(numConstraintRows);
+       //      m_x.setZero();
+
+       for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
+       {
+               const btSolverConstraint& c = *m_allConstraintPtrArray[i];
+               m_x[i] = c.m_appliedImpulse;
+               if (infoGlobal.m_splitImpulse)
+                       m_xSplit[i] = c.m_appliedPushImpulse;
+       }
+}
+
+btScalar btMLCPSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       bool result = true;
+       {
+               BT_PROFILE("solveMLCP");
+               //              printf("m_A(%d,%d)\n", m_A.rows(),m_A.cols());
+               result = solveMLCP(infoGlobal);
+       }
+
+       //check if solution is valid, and otherwise fallback to btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations
+       if (result)
+       {
+               BT_PROFILE("process MLCP results");
+               for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
+               {
+                       {
+                               btSolverConstraint& c = *m_allConstraintPtrArray[i];
+                               int sbA = c.m_solverBodyIdA;
+                               int sbB = c.m_solverBodyIdB;
+                               //btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
+                               //      btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
+
+                               btSolverBody& solverBodyA = m_tmpSolverBodyPool[sbA];
+                               btSolverBody& solverBodyB = m_tmpSolverBodyPool[sbB];
+
+                               {
+                                       btScalar deltaImpulse = m_x[i] - c.m_appliedImpulse;
+                                       c.m_appliedImpulse = m_x[i];
+                                       solverBodyA.internalApplyImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+                                       solverBodyB.internalApplyImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+                               }
+
+                               if (infoGlobal.m_splitImpulse)
+                               {
+                                       btScalar deltaImpulse = m_xSplit[i] - c.m_appliedPushImpulse;
+                                       solverBodyA.internalApplyPushImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
+                                       solverBodyB.internalApplyPushImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
+                                       c.m_appliedPushImpulse = m_xSplit[i];
+                               }
+                       }
+               }
+       }
+       else
+       {
+               //      printf("m_fallback = %d\n",m_fallback);
+               m_fallback++;
+               btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+       }
+
+       return 0.f;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btMLCPSolver.h
new file mode 100644 (file)
index 0000000..510ae59
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_MLCP_SOLVER_H
+#define BT_MLCP_SOLVER_H
+
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "LinearMath/btMatrixX.h"
+#include "BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h"
+
+class btMLCPSolver : public btSequentialImpulseConstraintSolver
+{
+protected:
+       btMatrixXu m_A;
+       btVectorXu m_b;
+       btVectorXu m_x;
+       btVectorXu m_lo;
+       btVectorXu m_hi;
+
+       ///when using 'split impulse' we solve two separate (M)LCPs
+       btVectorXu m_bSplit;
+       btVectorXu m_xSplit;
+       btVectorXu m_bSplit1;
+       btVectorXu m_xSplit2;
+
+       btAlignedObjectArray<int> m_limitDependencies;
+       btAlignedObjectArray<btSolverConstraint*> m_allConstraintPtrArray;
+       btMLCPSolverInterface* m_solver;
+       int m_fallback;
+
+       /// The following scratch variables are not stateful -- contents are cleared prior to each use.
+       /// They are only cached here to avoid extra memory allocations and deallocations and to ensure
+       /// that multiple instances of the solver can be run in parallel.
+       btMatrixXu m_scratchJ3;
+       btMatrixXu m_scratchJInvM3;
+       btAlignedObjectArray<int> m_scratchOfs;
+       btMatrixXu m_scratchMInv;
+       btMatrixXu m_scratchJ;
+       btMatrixXu m_scratchJTranspose;
+       btMatrixXu m_scratchTmp;
+
+       virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+       virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+
+       virtual void createMLCP(const btContactSolverInfo& infoGlobal);
+       virtual void createMLCPFast(const btContactSolverInfo& infoGlobal);
+
+       //return true is it solves the problem successfully
+       virtual bool solveMLCP(const btContactSolverInfo& infoGlobal);
+
+public:
+       btMLCPSolver(btMLCPSolverInterface* solver);
+       virtual ~btMLCPSolver();
+
+       void setMLCPSolver(btMLCPSolverInterface* solver)
+       {
+               m_solver = solver;
+       }
+
+       int getNumFallbacks() const
+       {
+               return m_fallback;
+       }
+       void setNumFallbacks(int num)
+       {
+               m_fallback = num;
+       }
+
+       virtual btConstraintSolverType getSolverType() const
+       {
+               return BT_MLCP_SOLVER;
+       }
+};
+
+#endif  //BT_MLCP_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h
new file mode 100644 (file)
index 0000000..6b0465b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_MLCP_SOLVER_INTERFACE_H
+#define BT_MLCP_SOLVER_INTERFACE_H
+
+#include "LinearMath/btMatrixX.h"
+
+class btMLCPSolverInterface
+{
+public:
+       virtual ~btMLCPSolverInterface()
+       {
+       }
+
+       //return true is it solves the problem successfully
+       virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true) = 0;
+};
+
+#endif  //BT_MLCP_SOLVER_INTERFACE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btPATHSolver.h b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btPATHSolver.h
new file mode 100644 (file)
index 0000000..7f8eec3
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_PATH_SOLVER_H
+#define BT_PATH_SOLVER_H
+
+//#define BT_USE_PATH
+#ifdef BT_USE_PATH
+
+extern "C"
+{
+#include "PATH/SimpleLCP.h"
+#include "PATH/License.h"
+#include "PATH/Error_Interface.h"
+};
+void __stdcall MyError(Void *data, Char *msg)
+{
+       printf("Path Error: %s\n", msg);
+}
+void __stdcall MyWarning(Void *data, Char *msg)
+{
+       printf("Path Warning: %s\n", msg);
+}
+
+Error_Interface e;
+
+#include "btMLCPSolverInterface.h"
+#include "Dantzig/lcp.h"
+
+class btPathSolver : public btMLCPSolverInterface
+{
+public:
+       btPathSolver()
+       {
+               License_SetString("2069810742&Courtesy_License&&&USR&2013&14_12_2011&1000&PATH&GEN&31_12_2013&0_0_0&0&0_0");
+               e.error_data = 0;
+               e.warning = MyWarning;
+               e.error = MyError;
+               Error_SetInterface(&e);
+       }
+
+       virtual bool solveMLCP(const btMatrixXu &A, const btVectorXu &b, btVectorXu &x, const btVectorXu &lo, const btVectorXu &hi, const btAlignedObjectArray<int> &limitDependency, int numIterations, bool useSparsity = true)
+       {
+               MCP_Termination status;
+
+               int numVariables = b.rows();
+               if (0 == numVariables)
+                       return true;
+
+               /*       - variables - the number of variables in the problem
+                       - m_nnz - the number of nonzeros in the M matrix
+                       - m_i - a vector of size m_nnz containing the row indices for M
+                       - m_j - a vector of size m_nnz containing the column indices for M
+                       - m_ij - a vector of size m_nnz containing the data for M
+                       - q - a vector of size variables
+                       - lb - a vector of size variables containing the lower bounds on x
+                       - ub - a vector of size variables containing the upper bounds on x
+                       */
+               btAlignedObjectArray<double> values;
+               btAlignedObjectArray<int> rowIndices;
+               btAlignedObjectArray<int> colIndices;
+
+               for (int i = 0; i < A.rows(); i++)
+               {
+                       for (int j = 0; j < A.cols(); j++)
+                       {
+                               if (A(i, j) != 0.f)
+                               {
+                                       //add 1, because Path starts at 1, instead of 0
+                                       rowIndices.push_back(i + 1);
+                                       colIndices.push_back(j + 1);
+                                       values.push_back(A(i, j));
+                               }
+                       }
+               }
+               int numNonZero = rowIndices.size();
+               btAlignedObjectArray<double> zResult;
+               zResult.resize(numVariables);
+               btAlignedObjectArray<double> rhs;
+               btAlignedObjectArray<double> upperBounds;
+               btAlignedObjectArray<double> lowerBounds;
+               for (int i = 0; i < numVariables; i++)
+               {
+                       upperBounds.push_back(hi[i]);
+                       lowerBounds.push_back(lo[i]);
+                       rhs.push_back(-b[i]);
+               }
+
+               SimpleLCP(numVariables, numNonZero, &rowIndices[0], &colIndices[0], &values[0], &rhs[0], &lowerBounds[0], &upperBounds[0], &status, &zResult[0]);
+
+               if (status != MCP_Solved)
+               {
+                       static const char *gReturnMsgs[] = {
+                               "Invalid return",
+                               "MCP_Solved: The problem was solved",
+                               "MCP_NoProgress: A stationary point was found",
+                               "MCP_MajorIterationLimit: Major iteration limit met",
+                               "MCP_MinorIterationLimit: Cumulative minor iteration limit met",
+                               "MCP_TimeLimit: Ran out of time",
+                               "MCP_UserInterrupt: Control-C, typically",
+                               "MCP_BoundError: Problem has a bound error",
+                               "MCP_DomainError: Could not find starting point",
+                               "MCP_Infeasible: Problem has no solution",
+                               "MCP_Error: An error occurred within the code",
+                               "MCP_LicenseError: License could not be found",
+                               "MCP_OK"};
+
+                       printf("ERROR: The PATH MCP solver failed: %s\n", gReturnMsgs[(unsigned int)status]);  // << std::endl;
+                       printf("using Projected Gauss Seidel fallback\n");
+
+                       return false;
+               }
+               else
+               {
+                       for (int i = 0; i < numVariables; i++)
+                       {
+                               x[i] = zResult[i];
+                               //check for #NAN
+                               if (x[i] != zResult[i])
+                                       return false;
+                       }
+                       return true;
+               }
+       }
+};
+
+#endif  //BT_USE_PATH
+
+#endif  //BT_PATH_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h b/dali-physics/third-party/bullet3/src/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h
new file mode 100644 (file)
index 0000000..c3f4ec3
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
+#define BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
+
+#include "btMLCPSolverInterface.h"
+
+///This solver is mainly for debug/learning purposes: it is functionally equivalent to the btSequentialImpulseConstraintSolver solver, but much slower (it builds the full LCP matrix)
+class btSolveProjectedGaussSeidel : public btMLCPSolverInterface
+{
+public:
+       btScalar m_leastSquaresResidualThreshold;
+       btScalar m_leastSquaresResidual;
+
+       btSolveProjectedGaussSeidel()
+               : m_leastSquaresResidualThreshold(0),
+                 m_leastSquaresResidual(0)
+       {
+       }
+
+       virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
+       {
+               if (!A.rows())
+                       return true;
+               //the A matrix is sparse, so compute the non-zero elements
+               A.rowComputeNonZeroElements();
+
+               //A is a m-n matrix, m rows, n columns
+               btAssert(A.rows() == b.rows());
+
+               int i, j, numRows = A.rows();
+
+               btScalar delta;
+
+               for (int k = 0; k < numIterations; k++)
+               {
+                       m_leastSquaresResidual = 0.f;
+                       for (i = 0; i < numRows; i++)
+                       {
+                               delta = 0.0f;
+                               if (useSparsity)
+                               {
+                                       for (int h = 0; h < A.m_rowNonZeroElements1[i].size(); h++)
+                                       {
+                                               j = A.m_rowNonZeroElements1[i][h];
+                                               if (j != i)  //skip main diagonal
+                                               {
+                                                       delta += A(i, j) * x[j];
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       for (j = 0; j < i; j++)
+                                               delta += A(i, j) * x[j];
+                                       for (j = i + 1; j < numRows; j++)
+                                               delta += A(i, j) * x[j];
+                               }
+
+                               btScalar aDiag = A(i, i);
+                               btScalar xOld = x[i];
+                               x[i] = (b[i] - delta) / aDiag;
+                               btScalar s = 1.f;
+
+                               if (limitDependency[i] >= 0)
+                               {
+                                       s = x[limitDependency[i]];
+                                       if (s < 0)
+                                               s = 1;
+                               }
+
+                               if (x[i] < lo[i] * s)
+                                       x[i] = lo[i] * s;
+                               if (x[i] > hi[i] * s)
+                                       x[i] = hi[i] * s;
+                               btScalar diff = x[i] - xOld;
+                               m_leastSquaresResidual += diff * diff;
+                       }
+
+                       btScalar eps = m_leastSquaresResidualThreshold;
+                       if ((m_leastSquaresResidual < eps) || (k >= (numIterations - 1)))
+                       {
+#ifdef VERBOSE_PRINTF_RESIDUAL
+                               printf("totalLenSqr = %f at iteration #%d\n", m_leastSquaresResidual, k);
+#endif
+                               break;
+                       }
+               }
+               return true;
+       }
+};
+
+#endif  //BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp
new file mode 100644 (file)
index 0000000..cbb41ec
--- /dev/null
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans https://bulletphysics.org
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability 
+ * of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+*/
+
+#include "LinearMath/btVector3.h"
+#include "btRaycastVehicle.h"
+
+#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btJacobianEntry.h"
+#include "LinearMath/btQuaternion.h"
+#include "BulletDynamics/Dynamics/btDynamicsWorld.h"
+#include "btVehicleRaycaster.h"
+#include "btWheelInfo.h"
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
+
+#define ROLLING_INFLUENCE_FIX
+
+btRigidBody& btActionInterface::getFixedBody()
+{
+       static btRigidBody s_fixed(0, 0, 0);
+       s_fixed.setMassProps(btScalar(0.), btVector3(btScalar(0.), btScalar(0.), btScalar(0.)));
+       return s_fixed;
+}
+
+btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning, btRigidBody* chassis, btVehicleRaycaster* raycaster)
+       : m_vehicleRaycaster(raycaster),
+         m_pitchControl(btScalar(0.))
+{
+       m_chassisBody = chassis;
+       m_indexRightAxis = 0;
+       m_indexUpAxis = 2;
+       m_indexForwardAxis = 1;
+       defaultInit(tuning);
+}
+
+void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning)
+{
+       (void)tuning;
+       m_currentVehicleSpeedKmHour = btScalar(0.);
+       m_steeringValue = btScalar(0.);
+}
+
+btRaycastVehicle::~btRaycastVehicle()
+{
+}
+
+//
+// basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed
+//
+btWheelInfo& btRaycastVehicle::addWheel(const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0, const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius, const btVehicleTuning& tuning, bool isFrontWheel)
+{
+       btWheelInfoConstructionInfo ci;
+
+       ci.m_chassisConnectionCS = connectionPointCS;
+       ci.m_wheelDirectionCS = wheelDirectionCS0;
+       ci.m_wheelAxleCS = wheelAxleCS;
+       ci.m_suspensionRestLength = suspensionRestLength;
+       ci.m_wheelRadius = wheelRadius;
+       ci.m_suspensionStiffness = tuning.m_suspensionStiffness;
+       ci.m_wheelsDampingCompression = tuning.m_suspensionCompression;
+       ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping;
+       ci.m_frictionSlip = tuning.m_frictionSlip;
+       ci.m_bIsFrontWheel = isFrontWheel;
+       ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm;
+       ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce;
+
+       m_wheelInfo.push_back(btWheelInfo(ci));
+
+       btWheelInfo& wheel = m_wheelInfo[getNumWheels() - 1];
+
+       updateWheelTransformsWS(wheel, false);
+       updateWheelTransform(getNumWheels() - 1, false);
+       return wheel;
+}
+
+const btTransform& btRaycastVehicle::getWheelTransformWS(int wheelIndex) const
+{
+       btAssert(wheelIndex < getNumWheels());
+       const btWheelInfo& wheel = m_wheelInfo[wheelIndex];
+       return wheel.m_worldTransform;
+}
+
+void btRaycastVehicle::updateWheelTransform(int wheelIndex, bool interpolatedTransform)
+{
+       btWheelInfo& wheel = m_wheelInfo[wheelIndex];
+       updateWheelTransformsWS(wheel, interpolatedTransform);
+       btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
+       const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS;
+       btVector3 fwd = up.cross(right);
+       fwd = fwd.normalize();
+       //      up = right.cross(fwd);
+       //      up.normalize();
+
+       //rotate around steering over de wheelAxleWS
+       btScalar steering = wheel.m_steering;
+
+       btQuaternion steeringOrn(up, steering);  //wheel.m_steering);
+       btMatrix3x3 steeringMat(steeringOrn);
+
+       btQuaternion rotatingOrn(right, -wheel.m_rotation);
+       btMatrix3x3 rotatingMat(rotatingOrn);
+
+       btMatrix3x3 basis2;
+       basis2[0][m_indexRightAxis] = -right[0];
+       basis2[1][m_indexRightAxis] = -right[1];
+       basis2[2][m_indexRightAxis] = -right[2];
+
+       basis2[0][m_indexUpAxis] = up[0];
+       basis2[1][m_indexUpAxis] = up[1];
+       basis2[2][m_indexUpAxis] = up[2];
+
+       basis2[0][m_indexForwardAxis] = fwd[0];
+       basis2[1][m_indexForwardAxis] = fwd[1];
+       basis2[2][m_indexForwardAxis] = fwd[2];
+
+       wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2);
+       wheel.m_worldTransform.setOrigin(
+               wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength);
+}
+
+void btRaycastVehicle::resetSuspension()
+{
+       int i;
+       for (i = 0; i < m_wheelInfo.size(); i++)
+       {
+               btWheelInfo& wheel = m_wheelInfo[i];
+               wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
+               wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+
+               wheel.m_raycastInfo.m_contactNormalWS = -wheel.m_raycastInfo.m_wheelDirectionWS;
+               //wheel_info.setContactFriction(btScalar(0.0));
+               wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
+       }
+}
+
+void btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel, bool interpolatedTransform)
+{
+       wheel.m_raycastInfo.m_isInContact = false;
+
+       btTransform chassisTrans = getChassisWorldTransform();
+       if (interpolatedTransform && (getRigidBody()->getMotionState()))
+       {
+               getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
+       }
+
+       wheel.m_raycastInfo.m_hardPointWS = chassisTrans(wheel.m_chassisConnectionPointCS);
+       wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS;
+       wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS;
+}
+
+btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
+{
+       updateWheelTransformsWS(wheel, false);
+
+       btScalar depth = -1;
+
+       btScalar raylen = wheel.getSuspensionRestLength() + wheel.m_wheelsRadius;
+
+       btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
+       const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
+       wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
+       const btVector3& target = wheel.m_raycastInfo.m_contactPointWS;
+
+       btScalar param = btScalar(0.);
+
+       btVehicleRaycaster::btVehicleRaycasterResult rayResults;
+
+       btAssert(m_vehicleRaycaster);
+
+       void* object = m_vehicleRaycaster->castRay(source, target, rayResults);
+
+       wheel.m_raycastInfo.m_groundObject = 0;
+
+       if (object)
+       {
+               param = rayResults.m_distFraction;
+               depth = raylen * rayResults.m_distFraction;
+               wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
+               wheel.m_raycastInfo.m_isInContact = true;
+
+               wheel.m_raycastInfo.m_groundObject = &getFixedBody();  ///@todo for driving on dynamic/movable objects!;
+               //wheel.m_raycastInfo.m_groundObject = object;
+
+               btScalar hitDistance = param * raylen;
+               wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius;
+               //clamp on max suspension travel
+
+               btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm * btScalar(0.01);
+               btScalar maxSuspensionLength = wheel.getSuspensionRestLength() + wheel.m_maxSuspensionTravelCm * btScalar(0.01);
+               if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
+               {
+                       wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
+               }
+               if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength)
+               {
+                       wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
+               }
+
+               wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld;
+
+               btScalar denominator = wheel.m_raycastInfo.m_contactNormalWS.dot(wheel.m_raycastInfo.m_wheelDirectionWS);
+
+               btVector3 chassis_velocity_at_contactPoint;
+               btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
+
+               chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
+
+               btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot(chassis_velocity_at_contactPoint);
+
+               if (denominator >= btScalar(-0.1))
+               {
+                       wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+                       wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
+               }
+               else
+               {
+                       btScalar inv = btScalar(-1.) / denominator;
+                       wheel.m_suspensionRelativeVelocity = projVel * inv;
+                       wheel.m_clippedInvContactDotSuspension = inv;
+               }
+       }
+       else
+       {
+               //put wheel info as in rest position
+               wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
+               wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+               wheel.m_raycastInfo.m_contactNormalWS = -wheel.m_raycastInfo.m_wheelDirectionWS;
+               wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
+       }
+
+       return depth;
+}
+
+const btTransform& btRaycastVehicle::getChassisWorldTransform() const
+{
+       /*if (getRigidBody()->getMotionState())
+       {
+               btTransform chassisWorldTrans;
+               getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans);
+               return chassisWorldTrans;
+       }
+       */
+
+       return getRigidBody()->getCenterOfMassTransform();
+}
+
+void btRaycastVehicle::updateVehicle(btScalar step)
+{
+       {
+               for (int i = 0; i < getNumWheels(); i++)
+               {
+                       updateWheelTransform(i, false);
+               }
+       }
+
+       m_currentVehicleSpeedKmHour = btScalar(3.6) * getRigidBody()->getLinearVelocity().length();
+
+       const btTransform& chassisTrans = getChassisWorldTransform();
+
+       btVector3 forwardW(
+               chassisTrans.getBasis()[0][m_indexForwardAxis],
+               chassisTrans.getBasis()[1][m_indexForwardAxis],
+               chassisTrans.getBasis()[2][m_indexForwardAxis]);
+
+       if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.))
+       {
+               m_currentVehicleSpeedKmHour *= btScalar(-1.);
+       }
+
+       //
+       // simulate suspension
+       //
+
+       int i = 0;
+       for (i = 0; i < m_wheelInfo.size(); i++)
+       {
+               //btScalar depth;
+               //depth =
+               rayCast(m_wheelInfo[i]);
+       }
+
+       updateSuspension(step);
+
+       for (i = 0; i < m_wheelInfo.size(); i++)
+       {
+               //apply suspension force
+               btWheelInfo& wheel = m_wheelInfo[i];
+
+               btScalar suspensionForce = wheel.m_wheelsSuspensionForce;
+
+               if (suspensionForce > wheel.m_maxSuspensionForce)
+               {
+                       suspensionForce = wheel.m_maxSuspensionForce;
+               }
+               btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
+               btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
+
+               getRigidBody()->applyImpulse(impulse, relpos);
+       }
+
+       updateFriction(step);
+
+       for (i = 0; i < m_wheelInfo.size(); i++)
+       {
+               btWheelInfo& wheel = m_wheelInfo[i];
+               btVector3 relpos = wheel.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
+               btVector3 vel = getRigidBody()->getVelocityInLocalPoint(relpos);
+
+               if (wheel.m_raycastInfo.m_isInContact)
+               {
+                       const btTransform& chassisWorldTransform = getChassisWorldTransform();
+
+                       btVector3 fwd(
+                               chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
+                               chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
+                               chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);
+
+                       btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
+                       fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
+
+                       btScalar proj2 = fwd.dot(vel);
+
+                       wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
+                       wheel.m_rotation += wheel.m_deltaRotation;
+               }
+               else
+               {
+                       wheel.m_rotation += wheel.m_deltaRotation;
+               }
+
+               wheel.m_deltaRotation *= btScalar(0.99);  //damping of rotation when not in contact
+       }
+}
+
+void btRaycastVehicle::setSteeringValue(btScalar steering, int wheel)
+{
+       btAssert(wheel >= 0 && wheel < getNumWheels());
+
+       btWheelInfo& wheelInfo = getWheelInfo(wheel);
+       wheelInfo.m_steering = steering;
+}
+
+btScalar btRaycastVehicle::getSteeringValue(int wheel) const
+{
+       return getWheelInfo(wheel).m_steering;
+}
+
+void btRaycastVehicle::applyEngineForce(btScalar force, int wheel)
+{
+       btAssert(wheel >= 0 && wheel < getNumWheels());
+       btWheelInfo& wheelInfo = getWheelInfo(wheel);
+       wheelInfo.m_engineForce = force;
+}
+
+const btWheelInfo& btRaycastVehicle::getWheelInfo(int index) const
+{
+       btAssert((index >= 0) && (index < getNumWheels()));
+
+       return m_wheelInfo[index];
+}
+
+btWheelInfo& btRaycastVehicle::getWheelInfo(int index)
+{
+       btAssert((index >= 0) && (index < getNumWheels()));
+
+       return m_wheelInfo[index];
+}
+
+void btRaycastVehicle::setBrake(btScalar brake, int wheelIndex)
+{
+       btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels()));
+       getWheelInfo(wheelIndex).m_brake = brake;
+}
+
+void btRaycastVehicle::updateSuspension(btScalar deltaTime)
+{
+       (void)deltaTime;
+
+       btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass();
+
+       for (int w_it = 0; w_it < getNumWheels(); w_it++)
+       {
+               btWheelInfo& wheel_info = m_wheelInfo[w_it];
+
+               if (wheel_info.m_raycastInfo.m_isInContact)
+               {
+                       btScalar force;
+                       //      Spring
+                       {
+                               btScalar susp_length = wheel_info.getSuspensionRestLength();
+                               btScalar current_length = wheel_info.m_raycastInfo.m_suspensionLength;
+
+                               btScalar length_diff = (susp_length - current_length);
+
+                               force = wheel_info.m_suspensionStiffness * length_diff * wheel_info.m_clippedInvContactDotSuspension;
+                       }
+
+                       // Damper
+                       {
+                               btScalar projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
+                               {
+                                       btScalar susp_damping;
+                                       if (projected_rel_vel < btScalar(0.0))
+                                       {
+                                               susp_damping = wheel_info.m_wheelsDampingCompression;
+                                       }
+                                       else
+                                       {
+                                               susp_damping = wheel_info.m_wheelsDampingRelaxation;
+                                       }
+                                       force -= susp_damping * projected_rel_vel;
+                               }
+                       }
+
+                       // RESULT
+                       wheel_info.m_wheelsSuspensionForce = force * chassisMass;
+                       if (wheel_info.m_wheelsSuspensionForce < btScalar(0.))
+                       {
+                               wheel_info.m_wheelsSuspensionForce = btScalar(0.);
+                       }
+               }
+               else
+               {
+                       wheel_info.m_wheelsSuspensionForce = btScalar(0.0);
+               }
+       }
+}
+
+struct btWheelContactPoint
+{
+       btRigidBody* m_body0;
+       btRigidBody* m_body1;
+       btVector3 m_frictionPositionWorld;
+       btVector3 m_frictionDirectionWorld;
+       btScalar m_jacDiagABInv;
+       btScalar m_maxImpulse;
+
+       btWheelContactPoint(btRigidBody* body0, btRigidBody* body1, const btVector3& frictionPosWorld, const btVector3& frictionDirectionWorld, btScalar maxImpulse)
+               : m_body0(body0),
+                 m_body1(body1),
+                 m_frictionPositionWorld(frictionPosWorld),
+                 m_frictionDirectionWorld(frictionDirectionWorld),
+                 m_maxImpulse(maxImpulse)
+       {
+               btScalar denom0 = body0->computeImpulseDenominator(frictionPosWorld, frictionDirectionWorld);
+               btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld, frictionDirectionWorld);
+               btScalar relaxation = 1.f;
+               m_jacDiagABInv = relaxation / (denom0 + denom1);
+       }
+};
+
+btScalar calcRollingFriction(btWheelContactPoint& contactPoint, int numWheelsOnGround);
+btScalar calcRollingFriction(btWheelContactPoint& contactPoint, int numWheelsOnGround)
+{
+       btScalar j1 = 0.f;
+
+       const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
+
+       btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition();
+       btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition();
+
+       btScalar maxImpulse = contactPoint.m_maxImpulse;
+
+       btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1);
+       btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2);
+       btVector3 vel = vel1 - vel2;
+
+       btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
+
+       // calculate j that moves us to zero relative velocity
+       j1 = -vrel * contactPoint.m_jacDiagABInv / btScalar(numWheelsOnGround);
+       btSetMin(j1, maxImpulse);
+       btSetMax(j1, -maxImpulse);
+
+       return j1;
+}
+
+btScalar sideFrictionStiffness2 = btScalar(1.0);
+void btRaycastVehicle::updateFriction(btScalar timeStep)
+{
+       //calculate the impulse, so that the wheels don't move sidewards
+       int numWheel = getNumWheels();
+       if (!numWheel)
+               return;
+
+       m_forwardWS.resize(numWheel);
+       m_axle.resize(numWheel);
+       m_forwardImpulse.resize(numWheel);
+       m_sideImpulse.resize(numWheel);
+
+       int numWheelsOnGround = 0;
+
+       //collapse all those loops into one!
+       for (int i = 0; i < getNumWheels(); i++)
+       {
+               btWheelInfo& wheelInfo = m_wheelInfo[i];
+               class btRigidBody* groundObject = (class btRigidBody*)wheelInfo.m_raycastInfo.m_groundObject;
+               if (groundObject)
+                       numWheelsOnGround++;
+               m_sideImpulse[i] = btScalar(0.);
+               m_forwardImpulse[i] = btScalar(0.);
+       }
+
+       {
+               for (int i = 0; i < getNumWheels(); i++)
+               {
+                       btWheelInfo& wheelInfo = m_wheelInfo[i];
+
+                       class btRigidBody* groundObject = (class btRigidBody*)wheelInfo.m_raycastInfo.m_groundObject;
+
+                       if (groundObject)
+                       {
+                               const btTransform& wheelTrans = getWheelTransformWS(i);
+
+                               btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
+                               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 = m_axle[i].dot(surfNormalWS);
+                               m_axle[i] -= surfNormalWS * proj;
+                               m_axle[i] = m_axle[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.), m_axle[i], m_sideImpulse[i], timeStep);
+
+                               m_sideImpulse[i] *= sideFrictionStiffness2;
+                       }
+               }
+       }
+
+       btScalar sideFactor = btScalar(1.);
+       btScalar fwdFactor = 0.5;
+
+       bool sliding = false;
+       {
+               for (int wheel = 0; wheel < getNumWheels(); wheel++)
+               {
+                       btWheelInfo& wheelInfo = m_wheelInfo[wheel];
+                       class btRigidBody* groundObject = (class btRigidBody*)wheelInfo.m_raycastInfo.m_groundObject;
+
+                       btScalar rollingFriction = 0.f;
+
+                       if (groundObject)
+                       {
+                               if (wheelInfo.m_engineForce != 0.f)
+                               {
+                                       rollingFriction = wheelInfo.m_engineForce * timeStep;
+                               }
+                               else
+                               {
+                                       btScalar defaultRollingFrictionImpulse = 0.f;
+                                       btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
+                                       btWheelContactPoint contactPt(m_chassisBody, groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, m_forwardWS[wheel], maxImpulse);
+                                       btAssert(numWheelsOnGround > 0);
+                                       rollingFriction = calcRollingFriction(contactPt, numWheelsOnGround);
+                               }
+                       }
+
+                       //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
+
+                       m_forwardImpulse[wheel] = btScalar(0.);
+                       m_wheelInfo[wheel].m_skidInfo = btScalar(1.);
+
+                       if (groundObject)
+                       {
+                               m_wheelInfo[wheel].m_skidInfo = btScalar(1.);
+
+                               btScalar maximp = wheelInfo.m_wheelsSuspensionForce * timeStep * wheelInfo.m_frictionSlip;
+                               btScalar maximpSide = maximp;
+
+                               btScalar maximpSquared = maximp * maximpSide;
+
+                               m_forwardImpulse[wheel] = rollingFriction;  //wheelInfo.m_engineForce* timeStep;
+
+                               btScalar x = (m_forwardImpulse[wheel]) * fwdFactor;
+                               btScalar y = (m_sideImpulse[wheel]) * sideFactor;
+
+                               btScalar impulseSquared = (x * x + y * y);
+
+                               if (impulseSquared > maximpSquared)
+                               {
+                                       sliding = true;
+
+                                       btScalar factor = maximp / btSqrt(impulseSquared);
+
+                                       m_wheelInfo[wheel].m_skidInfo *= factor;
+                               }
+                       }
+               }
+       }
+
+       if (sliding)
+       {
+               for (int wheel = 0; wheel < getNumWheels(); wheel++)
+               {
+                       if (m_sideImpulse[wheel] != btScalar(0.))
+                       {
+                               if (m_wheelInfo[wheel].m_skidInfo < btScalar(1.))
+                               {
+                                       m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
+                                       m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
+                               }
+                       }
+               }
+       }
+
+       // apply the impulses
+       {
+               for (int wheel = 0; wheel < getNumWheels(); wheel++)
+               {
+                       btWheelInfo& wheelInfo = m_wheelInfo[wheel];
+
+                       btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
+                                                               m_chassisBody->getCenterOfMassPosition();
+
+                       if (m_forwardImpulse[wheel] != btScalar(0.))
+                       {
+                               m_chassisBody->applyImpulse(m_forwardWS[wheel] * (m_forwardImpulse[wheel]), rel_pos);
+                       }
+                       if (m_sideImpulse[wheel] != btScalar(0.))
+                       {
+                               class btRigidBody* groundObject = (class btRigidBody*)m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
+
+                               btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS -
+                                                                        groundObject->getCenterOfMassPosition();
+
+                               btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
+
+#if defined ROLLING_INFLUENCE_FIX  // fix. It only worked if car's up was along Y - VT.
+                               btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
+                               rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f - wheelInfo.m_rollInfluence));
+#else
+                               rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
+#endif
+                               m_chassisBody->applyImpulse(sideImp, rel_pos);
+
+                               //apply friction impulse on the ground
+                               groundObject->applyImpulse(-sideImp, rel_pos2);
+                       }
+               }
+       }
+}
+
+void btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer)
+{
+       for (int v = 0; v < this->getNumWheels(); v++)
+       {
+               btVector3 wheelColor(0, 1, 1);
+               if (getWheelInfo(v).m_raycastInfo.m_isInContact)
+               {
+                       wheelColor.setValue(0, 0, 1);
+               }
+               else
+               {
+                       wheelColor.setValue(1, 0, 1);
+               }
+
+               btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin();
+
+               btVector3 axle = btVector3(
+                       getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()],
+                       getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()],
+                       getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]);
+
+               //debug wheels (cylinders)
+               debugDrawer->drawLine(wheelPosWS, wheelPosWS + axle, wheelColor);
+               debugDrawer->drawLine(wheelPosWS, getWheelInfo(v).m_raycastInfo.m_contactPointWS, wheelColor);
+       }
+}
+
+void* btDefaultVehicleRaycaster::castRay(const btVector3& from, const btVector3& to, btVehicleRaycasterResult& result)
+{
+       //      RayResultCallback& resultCallback;
+
+       btCollisionWorld::ClosestRayResultCallback rayCallback(from, to);
+
+       m_dynamicsWorld->rayTest(from, to, rayCallback);
+
+       if (rayCallback.hasHit())
+       {
+               const btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
+               if (body && body->hasContactResponse())
+               {
+                       result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
+                       result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
+                       result.m_hitNormalInWorld.normalize();
+                       result.m_distFraction = rayCallback.m_closestHitFraction;
+                       return (void*)body;
+               }
+       }
+       return 0;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btRaycastVehicle.h
new file mode 100644 (file)
index 0000000..b4a92b0
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans https://bulletphysics.org
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability 
+ * of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+*/
+#ifndef BT_RAYCASTVEHICLE_H
+#define BT_RAYCASTVEHICLE_H
+
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "btVehicleRaycaster.h"
+class btDynamicsWorld;
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btWheelInfo.h"
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+
+//class btVehicleTuning;
+
+///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle.
+class btRaycastVehicle : public btActionInterface
+{
+       btAlignedObjectArray<btVector3> m_forwardWS;
+       btAlignedObjectArray<btVector3> m_axle;
+       btAlignedObjectArray<btScalar> m_forwardImpulse;
+       btAlignedObjectArray<btScalar> m_sideImpulse;
+
+       ///backwards compatibility
+       int m_userConstraintType;
+       int m_userConstraintId;
+
+public:
+       class btVehicleTuning
+       {
+       public:
+               btVehicleTuning()
+                       : m_suspensionStiffness(btScalar(5.88)),
+                         m_suspensionCompression(btScalar(0.83)),
+                         m_suspensionDamping(btScalar(0.88)),
+                         m_maxSuspensionTravelCm(btScalar(500.)),
+                         m_frictionSlip(btScalar(10.5)),
+                         m_maxSuspensionForce(btScalar(6000.))
+               {
+               }
+               btScalar m_suspensionStiffness;
+               btScalar m_suspensionCompression;
+               btScalar m_suspensionDamping;
+               btScalar m_maxSuspensionTravelCm;
+               btScalar m_frictionSlip;
+               btScalar m_maxSuspensionForce;
+       };
+
+private:
+       btVehicleRaycaster* m_vehicleRaycaster;
+       btScalar m_pitchControl;
+       btScalar m_steeringValue;
+       btScalar m_currentVehicleSpeedKmHour;
+
+       btRigidBody* m_chassisBody;
+
+       int m_indexRightAxis;
+       int m_indexUpAxis;
+       int m_indexForwardAxis;
+
+       void defaultInit(const btVehicleTuning& tuning);
+
+public:
+       //constructor to create a car from an existing rigidbody
+       btRaycastVehicle(const btVehicleTuning& tuning, btRigidBody* chassis, btVehicleRaycaster* raycaster);
+
+       virtual ~btRaycastVehicle();
+
+       ///btActionInterface interface
+       virtual void updateAction(btCollisionWorld* collisionWorld, btScalar step)
+       {
+               (void)collisionWorld;
+               updateVehicle(step);
+       }
+
+       ///btActionInterface interface
+       void debugDraw(btIDebugDraw* debugDrawer);
+
+       const btTransform& getChassisWorldTransform() const;
+
+       btScalar rayCast(btWheelInfo& wheel);
+
+       virtual void updateVehicle(btScalar step);
+
+       void resetSuspension();
+
+       btScalar getSteeringValue(int wheel) const;
+
+       void setSteeringValue(btScalar steering, int wheel);
+
+       void applyEngineForce(btScalar force, int wheel);
+
+       const btTransform& getWheelTransformWS(int wheelIndex) const;
+
+       void updateWheelTransform(int wheelIndex, bool interpolatedTransform = true);
+
+       //      void    setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth);
+
+       btWheelInfo& addWheel(const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0, const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius, const btVehicleTuning& tuning, bool isFrontWheel);
+
+       inline int getNumWheels() const
+       {
+               return int(m_wheelInfo.size());
+       }
+
+       btAlignedObjectArray<btWheelInfo> m_wheelInfo;
+
+       const btWheelInfo& getWheelInfo(int index) const;
+
+       btWheelInfo& getWheelInfo(int index);
+
+       void updateWheelTransformsWS(btWheelInfo& wheel, bool interpolatedTransform = true);
+
+       void setBrake(btScalar brake, int wheelIndex);
+
+       void setPitchControl(btScalar pitch)
+       {
+               m_pitchControl = pitch;
+       }
+
+       void updateSuspension(btScalar deltaTime);
+
+       virtual void updateFriction(btScalar timeStep);
+
+       inline btRigidBody* getRigidBody()
+       {
+               return m_chassisBody;
+       }
+
+       const btRigidBody* getRigidBody() const
+       {
+               return m_chassisBody;
+       }
+
+       inline int getRightAxis() const
+       {
+               return m_indexRightAxis;
+       }
+       inline int getUpAxis() const
+       {
+               return m_indexUpAxis;
+       }
+
+       inline int getForwardAxis() const
+       {
+               return m_indexForwardAxis;
+       }
+
+       ///Worldspace forward vector
+       btVector3 getForwardVector() const
+       {
+               const btTransform& chassisTrans = getChassisWorldTransform();
+
+               btVector3 forwardW(
+                       chassisTrans.getBasis()[0][m_indexForwardAxis],
+                       chassisTrans.getBasis()[1][m_indexForwardAxis],
+                       chassisTrans.getBasis()[2][m_indexForwardAxis]);
+
+               return forwardW;
+       }
+
+       ///Velocity of vehicle (positive if velocity vector has same direction as foward vector)
+       btScalar getCurrentSpeedKmHour() const
+       {
+               return m_currentVehicleSpeedKmHour;
+       }
+
+       virtual void setCoordinateSystem(int rightIndex, int upIndex, int forwardIndex)
+       {
+               m_indexRightAxis = rightIndex;
+               m_indexUpAxis = upIndex;
+               m_indexForwardAxis = forwardIndex;
+       }
+
+       ///backwards compatibility
+       int getUserConstraintType() const
+       {
+               return m_userConstraintType;
+       }
+
+       void setUserConstraintType(int userConstraintType)
+       {
+               m_userConstraintType = userConstraintType;
+       };
+
+       void setUserConstraintId(int uid)
+       {
+               m_userConstraintId = uid;
+       }
+
+       int getUserConstraintId() const
+       {
+               return m_userConstraintId;
+       }
+};
+
+class btDefaultVehicleRaycaster : public btVehicleRaycaster
+{
+       btDynamicsWorld* m_dynamicsWorld;
+
+public:
+       btDefaultVehicleRaycaster(btDynamicsWorld* world)
+               : m_dynamicsWorld(world)
+       {
+       }
+
+       virtual void* castRay(const btVector3& from, const btVector3& to, btVehicleRaycasterResult& result);
+};
+
+#endif  //BT_RAYCASTVEHICLE_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btVehicleRaycaster.h
new file mode 100644 (file)
index 0000000..2c44ce5
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://bulletphysics.org
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability 
+ * of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+*/
+#ifndef BT_VEHICLE_RAYCASTER_H
+#define BT_VEHICLE_RAYCASTER_H
+
+#include "LinearMath/btVector3.h"
+
+/// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting
+struct btVehicleRaycaster
+{
+       virtual ~btVehicleRaycaster()
+       {
+       }
+       struct btVehicleRaycasterResult
+       {
+               btVehicleRaycasterResult() : m_distFraction(btScalar(-1.)){};
+               btVector3 m_hitPointInWorld;
+               btVector3 m_hitNormalInWorld;
+               btScalar m_distFraction;
+       };
+
+       virtual void* castRay(const btVector3& from, const btVector3& to, btVehicleRaycasterResult& result) = 0;
+};
+
+#endif  //BT_VEHICLE_RAYCASTER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btWheelInfo.cpp b/dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btWheelInfo.cpp
new file mode 100644 (file)
index 0000000..5313215
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans https://bulletphysics.org
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability 
+ * of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+*/
+#include "btWheelInfo.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"  // for pointvelocity
+
+btScalar btWheelInfo::getSuspensionRestLength() const
+{
+       return m_suspensionRestLength1;
+}
+
+void btWheelInfo::updateWheel(const btRigidBody& chassis, RaycastInfo& raycastInfo)
+{
+       (void)raycastInfo;
+
+       if (m_raycastInfo.m_isInContact)
+
+       {
+               btScalar project = m_raycastInfo.m_contactNormalWS.dot(m_raycastInfo.m_wheelDirectionWS);
+               btVector3 chassis_velocity_at_contactPoint;
+               btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition();
+               chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint(relpos);
+               btScalar projVel = m_raycastInfo.m_contactNormalWS.dot(chassis_velocity_at_contactPoint);
+               if (project >= btScalar(-0.1))
+               {
+                       m_suspensionRelativeVelocity = btScalar(0.0);
+                       m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
+               }
+               else
+               {
+                       btScalar inv = btScalar(-1.) / project;
+                       m_suspensionRelativeVelocity = projVel * inv;
+                       m_clippedInvContactDotSuspension = inv;
+               }
+       }
+
+       else  // Not in contact : position wheel in a nice (rest length) position
+       {
+               m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength();
+               m_suspensionRelativeVelocity = btScalar(0.0);
+               m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS;
+               m_clippedInvContactDotSuspension = btScalar(1.0);
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btWheelInfo.h b/dali-physics/third-party/bullet3/src/BulletDynamics/Vehicle/btWheelInfo.h
new file mode 100644 (file)
index 0000000..68f6142
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans https://bulletphysics.org
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability 
+ * of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+*/
+#ifndef BT_WHEEL_INFO_H
+#define BT_WHEEL_INFO_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+
+class btRigidBody;
+
+struct btWheelInfoConstructionInfo
+{
+       btVector3 m_chassisConnectionCS;
+       btVector3 m_wheelDirectionCS;
+       btVector3 m_wheelAxleCS;
+       btScalar m_suspensionRestLength;
+       btScalar m_maxSuspensionTravelCm;
+       btScalar m_wheelRadius;
+
+       btScalar m_suspensionStiffness;
+       btScalar m_wheelsDampingCompression;
+       btScalar m_wheelsDampingRelaxation;
+       btScalar m_frictionSlip;
+       btScalar m_maxSuspensionForce;
+       bool m_bIsFrontWheel;
+};
+
+/// btWheelInfo contains information per wheel about friction and suspension.
+struct btWheelInfo
+{
+       struct RaycastInfo
+       {
+               //set by raycaster
+               btVector3 m_contactNormalWS;  //contactnormal
+               btVector3 m_contactPointWS;   //raycast hitpoint
+               btScalar m_suspensionLength;
+               btVector3 m_hardPointWS;       //raycast starting point
+               btVector3 m_wheelDirectionWS;  //direction in worldspace
+               btVector3 m_wheelAxleWS;       // axle in worldspace
+               bool m_isInContact;
+               void* m_groundObject;  //could be general void* ptr
+       };
+
+       RaycastInfo m_raycastInfo;
+
+       btTransform m_worldTransform;
+
+       btVector3 m_chassisConnectionPointCS;  //const
+       btVector3 m_wheelDirectionCS;          //const
+       btVector3 m_wheelAxleCS;               // const or modified by steering
+       btScalar m_suspensionRestLength1;      //const
+       btScalar m_maxSuspensionTravelCm;
+       btScalar getSuspensionRestLength() const;
+       btScalar m_wheelsRadius;              //const
+       btScalar m_suspensionStiffness;       //const
+       btScalar m_wheelsDampingCompression;  //const
+       btScalar m_wheelsDampingRelaxation;   //const
+       btScalar m_frictionSlip;
+       btScalar m_steering;
+       btScalar m_rotation;
+       btScalar m_deltaRotation;
+       btScalar m_rollInfluence;
+       btScalar m_maxSuspensionForce;
+
+       btScalar m_engineForce;
+
+       btScalar m_brake;
+
+       bool m_bIsFrontWheel;
+
+       void* m_clientInfo;  //can be used to store pointer to sync transforms...
+
+       btWheelInfo() {}
+
+       btWheelInfo(btWheelInfoConstructionInfo& ci)
+
+       {
+               m_suspensionRestLength1 = ci.m_suspensionRestLength;
+               m_maxSuspensionTravelCm = ci.m_maxSuspensionTravelCm;
+
+               m_wheelsRadius = ci.m_wheelRadius;
+               m_suspensionStiffness = ci.m_suspensionStiffness;
+               m_wheelsDampingCompression = ci.m_wheelsDampingCompression;
+               m_wheelsDampingRelaxation = ci.m_wheelsDampingRelaxation;
+               m_chassisConnectionPointCS = ci.m_chassisConnectionCS;
+               m_wheelDirectionCS = ci.m_wheelDirectionCS;
+               m_wheelAxleCS = ci.m_wheelAxleCS;
+               m_frictionSlip = ci.m_frictionSlip;
+               m_steering = btScalar(0.);
+               m_engineForce = btScalar(0.);
+               m_rotation = btScalar(0.);
+               m_deltaRotation = btScalar(0.);
+               m_brake = btScalar(0.);
+               m_rollInfluence = btScalar(0.1);
+               m_bIsFrontWheel = ci.m_bIsFrontWheel;
+               m_maxSuspensionForce = ci.m_maxSuspensionForce;
+       }
+
+       void updateWheel(const btRigidBody& chassis, RaycastInfo& raycastInfo);
+
+       btScalar m_clippedInvContactDotSuspension;
+       btScalar m_suspensionRelativeVelocity;
+       //calculated by suspension
+       btScalar m_wheelsSuspensionForce;
+       btScalar m_skidInfo;
+};
+
+#endif  //BT_WHEEL_INFO_H
diff --git a/dali-physics/third-party/bullet3/src/BulletDynamics/premake4.lua b/dali-physics/third-party/bullet3/src/BulletDynamics/premake4.lua
new file mode 100644 (file)
index 0000000..fdaf051
--- /dev/null
@@ -0,0 +1,24 @@
+       project "BulletDynamics"
+       kind "StaticLib"
+       includedirs {
+               "..",
+       }
+    if os.is("Linux") then
+        buildoptions{"-fPIC"}
+    end
+       files {
+               "Dynamics/*.cpp",
+                "Dynamics/*.h",
+                "ConstraintSolver/*.cpp",
+                "ConstraintSolver/*.h",
+                "Featherstone/*.cpp",
+                "Featherstone/*.h",
+                "MLCPSolvers/*.cpp",
+                "MLCPSolvers/*.h",
+                "Vehicle/*.cpp",
+                "Vehicle/*.h",
+                "Character/*.cpp",
+                "Character/*.h"
+
+       }
+
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/CMakeLists.txt b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3331c27
--- /dev/null
@@ -0,0 +1,66 @@
+INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src  )
+
+SET(BulletInverseDynamics_SRCS
+       IDMath.cpp
+       MultiBodyTree.cpp
+       details/MultiBodyTreeInitCache.cpp
+       details/MultiBodyTreeImpl.cpp
+)
+
+SET(BulletInverseDynamicsRoot_HDRS
+       IDConfig.hpp
+       IDConfigEigen.hpp
+       IDMath.hpp
+       IDConfigBuiltin.hpp
+       IDErrorMessages.hpp
+       MultiBodyTree.hpp
+)
+SET(BulletInverseDynamicsDetails_HDRS
+       details/IDEigenInterface.hpp
+       details/IDMatVec.hpp
+       details/IDLinearMathInterface.hpp
+       details/MultiBodyTreeImpl.hpp
+       details/MultiBodyTreeInitCache.hpp
+)
+
+SET(BulletInverseDynamics_HDRS
+       ${BulletInverseDynamicsRoot_HDRS}
+       ${BulletInverseDynamicsDetails_HDRS}
+)
+
+
+ADD_LIBRARY(BulletInverseDynamics ${BulletInverseDynamics_SRCS} ${BulletInverseDynamics_HDRS})
+SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES SOVERSION ${BULLET_VERSION})
+IF (BUILD_SHARED_LIBS)
+  TARGET_LINK_LIBRARIES(BulletInverseDynamics Bullet3Common LinearMath)
+ENDIF (BUILD_SHARED_LIBS)
+
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               #INSTALL of other files requires CMake 2.6
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS BulletInverseDynamics DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS BulletInverseDynamics RUNTIME DESTINATION bin
+                                                               LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                                               ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+                               INSTALL(FILES ../btBulletCollisionCommon.h
+DESTINATION ${INCLUDE_INSTALL_DIR}/BulletInverseDynamics)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES FRAMEWORK true)
+
+                       SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES PUBLIC_HEADER "${BulletInverseDynamicsRoot_HDRS}")
+                       # Have to list out sub-directories manually:
+                       SET_PROPERTY(SOURCE ${BulletInverseDynamicsDetails_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/details)
+
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDConfig.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDConfig.hpp
new file mode 100644 (file)
index 0000000..b662b80
--- /dev/null
@@ -0,0 +1,107 @@
+///@file Configuration for Inverse Dynamics Library,
+///      such as choice of linear algebra library and underlying scalar type
+#ifndef IDCONFIG_HPP_
+#define IDCONFIG_HPP_
+
+// If true, enable jacobian calculations.
+// This adds a 3xN matrix to every body, + 2 3-Vectors.
+// so it is not advised for large systems if it is not absolutely necessary.
+// Also, this is not required for standard inverse dynamics calculations.
+// Will only work with vector math libraries that support 3xN matrices.
+#define BT_ID_WITH_JACOBIANS
+
+// If we have a custom configuration, compile without using other parts of bullet.
+#ifdef BT_CUSTOM_INVERSE_DYNAMICS_CONFIG_H
+#include <cmath>
+#define BT_ID_WO_BULLET
+#define BT_ID_SQRT(x) std::sqrt(x)
+#define BT_ID_FABS(x) std::fabs(x)
+#define BT_ID_COS(x) std::cos(x)
+#define BT_ID_SIN(x) std::sin(x)
+#define BT_ID_ATAN2(x, y) std::atan2(x, y)
+#define BT_ID_POW(x, y) std::pow(x, y)
+#define BT_ID_SNPRINTF snprintf
+#define BT_ID_PI M_PI
+#define BT_ID_USE_DOUBLE_PRECISION
+#else
+#define BT_ID_SQRT(x) btSqrt(x)
+#define BT_ID_FABS(x) btFabs(x)
+#define BT_ID_COS(x) btCos(x)
+#define BT_ID_SIN(x) btSin(x)
+#define BT_ID_ATAN2(x, y) btAtan2(x, y)
+#define BT_ID_POW(x, y) btPow(x, y)
+#define BT_ID_PI SIMD_PI
+#ifdef _WIN32
+#define BT_ID_SNPRINTF _snprintf
+#else
+#define BT_ID_SNPRINTF snprintf
+#endif  //
+#endif
+// error messages
+#include "IDErrorMessages.hpp"
+
+#ifdef BT_CUSTOM_INVERSE_DYNAMICS_CONFIG_H
+/*
+#include "IDConfigEigen.hpp"
+#include "IDConfigBuiltin.hpp"
+*/
+#define INVDYN_INCLUDE_HELPER_2(x) #x
+#define INVDYN_INCLUDE_HELPER(x) INVDYN_INCLUDE_HELPER_2(x)
+#include INVDYN_INCLUDE_HELPER(BT_CUSTOM_INVERSE_DYNAMICS_CONFIG_H)
+#ifndef btInverseDynamics
+#error "custom inverse dynamics config, but no custom namespace defined"
+#endif
+
+#define BT_ID_MAX(a, b) std::max(a, b)
+#define BT_ID_MIN(a, b) std::min(a, b)
+
+#else
+#define btInverseDynamics btInverseDynamicsBullet3
+// Use default configuration with bullet's types
+// Use the same scalar type as rest of bullet library
+#include "LinearMath/btScalar.h"
+typedef btScalar idScalar;
+#include "LinearMath/btMinMax.h"
+#define BT_ID_MAX(a, b) btMax(a, b)
+#define BT_ID_MIN(a, b) btMin(a, b)
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define BT_ID_USE_DOUBLE_PRECISION
+#endif
+
+#ifndef BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
+
+// use bullet types for arrays and array indices
+#include "Bullet3Common/b3AlignedObjectArray.h"
+// this is to make it work with C++2003, otherwise we could do this:
+// template <typename T>
+// using idArray = b3AlignedObjectArray<T>;
+template <typename T>
+struct idArray
+{
+       typedef b3AlignedObjectArray<T> type;
+};
+typedef int idArrayIdx;
+#define ID_DECLARE_ALIGNED_ALLOCATOR() B3_DECLARE_ALIGNED_ALLOCATOR()
+
+#else  // BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
+
+#include "LinearMath/btAlignedObjectArray.h"
+template <typename T>
+struct idArray
+{
+       typedef btAlignedObjectArray<T> type;
+};
+typedef int idArrayIdx;
+#define ID_DECLARE_ALIGNED_ALLOCATOR() BT_DECLARE_ALIGNED_ALLOCATOR()
+
+#endif  // BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
+
+// use bullet's allocator functions
+#define idMalloc btAllocFunc
+#define idFree btFreeFunc
+
+#define ID_LINEAR_MATH_USE_BULLET
+#include "details/IDLinearMathInterface.hpp"
+#endif
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDConfigBuiltin.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDConfigBuiltin.hpp
new file mode 100644 (file)
index 0000000..6392367
--- /dev/null
@@ -0,0 +1,38 @@
+///@file Configuration for Inverse Dynamics Library without external dependencies
+#ifndef INVDYNCONFIG_BUILTIN_HPP_
+#define INVDYNCONFIG_BUILTIN_HPP_
+#define btInverseDynamics btInverseDynamicsBuiltin
+#ifdef BT_USE_DOUBLE_PRECISION
+// choose double/single precision version
+typedef double idScalar;
+#else
+typedef float idScalar;
+#endif
+// use std::vector for arrays
+#include <vector>
+// this is to make it work with C++2003, otherwise we could do this
+// template <typename T>
+// using idArray = std::vector<T>;
+template <typename T>
+struct idArray
+{
+       typedef std::vector<T> type;
+};
+typedef std::vector<int>::size_type idArrayIdx;
+// default to standard malloc/free
+#include <cstdlib>
+#define idMalloc ::malloc
+#define idFree ::free
+// currently not aligned at all...
+#define ID_DECLARE_ALIGNED_ALLOCATOR()                                                     \
+       inline void* operator new(std::size_t sizeInBytes) { return idMalloc(sizeInBytes); }   \
+       inline void operator delete(void* ptr) { idFree(ptr); }                                \
+       inline void* operator new(std::size_t, void* ptr) { return ptr; }                      \
+       inline void operator delete(void*, void*) {}                                           \
+       inline void* operator new[](std::size_t sizeInBytes) { return idMalloc(sizeInBytes); } \
+       inline void operator delete[](void* ptr) { idFree(ptr); }                              \
+       inline void* operator new[](std::size_t, void* ptr) { return ptr; }                    \
+       inline void operator delete[](void*, void*) {}
+
+#include "details/IDMatVec.hpp"
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDConfigEigen.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDConfigEigen.hpp
new file mode 100644 (file)
index 0000000..cfb308e
--- /dev/null
@@ -0,0 +1,32 @@
+///@file Configuration for Inverse Dynamics Library with Eigen
+#ifndef INVDYNCONFIG_EIGEN_HPP_
+#define INVDYNCONFIG_EIGEN_HPP_
+#define btInverseDynamics btInverseDynamicsEigen
+#ifdef BT_USE_DOUBLE_PRECISION
+// choose double/single precision version
+typedef double idScalar;
+#else
+typedef float idScalar;
+#endif
+
+// use std::vector for arrays
+#include <vector>
+// this is to make it work with C++2003, otherwise we could do this
+// template <typename T>
+// using idArray = std::vector<T>;
+template <typename T>
+struct idArray
+{
+       typedef std::vector<T> type;
+};
+typedef std::vector<int>::size_type idArrayIdx;
+// default to standard malloc/free
+#include <cstdlib>
+#define ID_DECLARE_ALIGNED_ALLOCATOR() EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+// Note on interfaces:
+// Eigen::Matrix has data(), to get c-array storage
+// HOWEVER: default storage is column-major!
+#define ID_LINEAR_MATH_USE_EIGEN
+#include "Eigen/Eigen"
+#include "details/IDEigenInterface.hpp"
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDErrorMessages.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDErrorMessages.hpp
new file mode 100644 (file)
index 0000000..5a98f01
--- /dev/null
@@ -0,0 +1,31 @@
+///@file error message utility functions
+#ifndef IDUTILS_HPP_
+#define IDUTILS_HPP_
+#include <cstring>
+/// name of file being compiled, without leading path components
+#define __INVDYN_FILE_WO_DIR__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+#if !defined(BT_ID_WO_BULLET) && !defined(BT_USE_INVERSE_DYNAMICS_WITH_BULLET2)
+#include "Bullet3Common/b3Logging.h"
+#define bt_id_error_message(...) b3Error(__VA_ARGS__)
+#define bt_id_warning_message(...) b3Warning(__VA_ARGS__)
+#define id_printf(...) b3Printf(__VA_ARGS__)
+#else  // BT_ID_WO_BULLET
+#include <cstdio>
+/// print error message with file/line information
+#define bt_id_error_message(...)                                             \
+       do                                                                       \
+       {                                                                        \
+               fprintf(stderr, "[Error:%s:%d] ", __INVDYN_FILE_WO_DIR__, __LINE__); \
+               fprintf(stderr, __VA_ARGS__);                                        \
+       } while (0)
+/// print warning message with file/line information
+#define bt_id_warning_message(...)                                             \
+       do                                                                         \
+       {                                                                          \
+               fprintf(stderr, "[Warning:%s:%d] ", __INVDYN_FILE_WO_DIR__, __LINE__); \
+               fprintf(stderr, __VA_ARGS__);                                          \
+       } while (0)
+#define id_printf(...) printf(__VA_ARGS__)
+#endif  // BT_ID_WO_BULLET
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDMath.cpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDMath.cpp
new file mode 100644 (file)
index 0000000..0c3f5c9
--- /dev/null
@@ -0,0 +1,510 @@
+#include "IDMath.hpp"
+
+#include <cmath>
+#include <limits>
+
+namespace btInverseDynamics
+{
+static const idScalar kIsZero = 5 * std::numeric_limits<idScalar>::epsilon();
+// requirements for axis length deviation from 1.0
+// experimentally set from random euler angle rotation matrices
+static const idScalar kAxisLengthEpsilon = 10 * kIsZero;
+
+void setZero(vec3 &v)
+{
+       v(0) = 0;
+       v(1) = 0;
+       v(2) = 0;
+}
+
+void setZero(vecx &v)
+{
+       for (int i = 0; i < v.size(); i++)
+       {
+               v(i) = 0;
+       }
+}
+
+void setZero(mat33 &m)
+{
+       m(0, 0) = 0;
+       m(0, 1) = 0;
+       m(0, 2) = 0;
+       m(1, 0) = 0;
+       m(1, 1) = 0;
+       m(1, 2) = 0;
+       m(2, 0) = 0;
+       m(2, 1) = 0;
+       m(2, 2) = 0;
+}
+
+void skew(vec3 &v, mat33 *result)
+{
+       (*result)(0, 0) = 0.0;
+       (*result)(0, 1) = -v(2);
+       (*result)(0, 2) = v(1);
+       (*result)(1, 0) = v(2);
+       (*result)(1, 1) = 0.0;
+       (*result)(1, 2) = -v(0);
+       (*result)(2, 0) = -v(1);
+       (*result)(2, 1) = v(0);
+       (*result)(2, 2) = 0.0;
+}
+
+idScalar maxAbs(const vecx &v)
+{
+       idScalar result = 0.0;
+       for (int i = 0; i < v.size(); i++)
+       {
+               const idScalar tmp = BT_ID_FABS(v(i));
+               if (tmp > result)
+               {
+                       result = tmp;
+               }
+       }
+       return result;
+}
+
+idScalar maxAbs(const vec3 &v)
+{
+       idScalar result = 0.0;
+       for (int i = 0; i < 3; i++)
+       {
+               const idScalar tmp = BT_ID_FABS(v(i));
+               if (tmp > result)
+               {
+                       result = tmp;
+               }
+       }
+       return result;
+}
+
+#if (defined BT_ID_HAVE_MAT3X)
+idScalar maxAbsMat3x(const mat3x &m)
+{
+       // only used for tests -- so just loop here for portability
+       idScalar result = 0.0;
+       for (idArrayIdx col = 0; col < m.cols(); col++)
+       {
+               for (idArrayIdx row = 0; row < 3; row++)
+               {
+                       result = BT_ID_MAX(result, std::fabs(m(row, col)));
+               }
+       }
+       return result;
+}
+
+void mul(const mat33 &a, const mat3x &b, mat3x *result)
+{
+       if (b.cols() != result->cols())
+       {
+               bt_id_error_message("size missmatch. b.cols()= %d, result->cols()= %d\n",
+                                                       static_cast<int>(b.cols()), static_cast<int>(result->cols()));
+               abort();
+       }
+
+       for (idArrayIdx col = 0; col < b.cols(); col++)
+       {
+               const idScalar x = a(0, 0) * b(0, col) + a(0, 1) * b(1, col) + a(0, 2) * b(2, col);
+               const idScalar y = a(1, 0) * b(0, col) + a(1, 1) * b(1, col) + a(1, 2) * b(2, col);
+               const idScalar z = a(2, 0) * b(0, col) + a(2, 1) * b(1, col) + a(2, 2) * b(2, col);
+               setMat3xElem(0, col, x, result);
+               setMat3xElem(1, col, y, result);
+               setMat3xElem(2, col, z, result);
+       }
+}
+void add(const mat3x &a, const mat3x &b, mat3x *result)
+{
+       if (a.cols() != b.cols())
+       {
+               bt_id_error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
+                                                       static_cast<int>(a.cols()), static_cast<int>(b.cols()));
+               abort();
+       }
+       for (idArrayIdx col = 0; col < b.cols(); col++)
+       {
+               for (idArrayIdx row = 0; row < 3; row++)
+               {
+                       setMat3xElem(row, col, a(row, col) + b(row, col), result);
+               }
+       }
+}
+void sub(const mat3x &a, const mat3x &b, mat3x *result)
+{
+       if (a.cols() != b.cols())
+       {
+               bt_id_error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
+                                                       static_cast<int>(a.cols()), static_cast<int>(b.cols()));
+               abort();
+       }
+       for (idArrayIdx col = 0; col < b.cols(); col++)
+       {
+               for (idArrayIdx row = 0; row < 3; row++)
+               {
+                       setMat3xElem(row, col, a(row, col) - b(row, col), result);
+               }
+       }
+}
+#endif
+
+mat33 transformX(const idScalar &alpha)
+{
+       mat33 T;
+       const idScalar cos_alpha = BT_ID_COS(alpha);
+       const idScalar sin_alpha = BT_ID_SIN(alpha);
+       // [1  0 0]
+       // [0  c s]
+       // [0 -s c]
+       T(0, 0) = 1.0;
+       T(0, 1) = 0.0;
+       T(0, 2) = 0.0;
+
+       T(1, 0) = 0.0;
+       T(1, 1) = cos_alpha;
+       T(1, 2) = sin_alpha;
+
+       T(2, 0) = 0.0;
+       T(2, 1) = -sin_alpha;
+       T(2, 2) = cos_alpha;
+
+       return T;
+}
+
+mat33 transformY(const idScalar &beta)
+{
+       mat33 T;
+       const idScalar cos_beta = BT_ID_COS(beta);
+       const idScalar sin_beta = BT_ID_SIN(beta);
+       // [c 0 -s]
+       // [0 1  0]
+       // [s 0  c]
+       T(0, 0) = cos_beta;
+       T(0, 1) = 0.0;
+       T(0, 2) = -sin_beta;
+
+       T(1, 0) = 0.0;
+       T(1, 1) = 1.0;
+       T(1, 2) = 0.0;
+
+       T(2, 0) = sin_beta;
+       T(2, 1) = 0.0;
+       T(2, 2) = cos_beta;
+
+       return T;
+}
+
+mat33 transformZ(const idScalar &gamma)
+{
+       mat33 T;
+       const idScalar cos_gamma = BT_ID_COS(gamma);
+       const idScalar sin_gamma = BT_ID_SIN(gamma);
+       // [ c s 0]
+       // [-s c 0]
+       // [ 0 0 1]
+       T(0, 0) = cos_gamma;
+       T(0, 1) = sin_gamma;
+       T(0, 2) = 0.0;
+
+       T(1, 0) = -sin_gamma;
+       T(1, 1) = cos_gamma;
+       T(1, 2) = 0.0;
+
+       T(2, 0) = 0.0;
+       T(2, 1) = 0.0;
+       T(2, 2) = 1.0;
+
+       return T;
+}
+
+mat33 tildeOperator(const vec3 &v)
+{
+       mat33 m;
+       m(0, 0) = 0.0;
+       m(0, 1) = -v(2);
+       m(0, 2) = v(1);
+       m(1, 0) = v(2);
+       m(1, 1) = 0.0;
+       m(1, 2) = -v(0);
+       m(2, 0) = -v(1);
+       m(2, 1) = v(0);
+       m(2, 2) = 0.0;
+       return m;
+}
+
+void getVecMatFromDH(idScalar theta, idScalar d, idScalar a, idScalar alpha, vec3 *r, mat33 *T)
+{
+       const idScalar sa = BT_ID_SIN(alpha);
+       const idScalar ca = BT_ID_COS(alpha);
+       const idScalar st = BT_ID_SIN(theta);
+       const idScalar ct = BT_ID_COS(theta);
+
+       (*r)(0) = a;
+       (*r)(1) = -sa * d;
+       (*r)(2) = ca * d;
+
+       (*T)(0, 0) = ct;
+       (*T)(0, 1) = -st;
+       (*T)(0, 2) = 0.0;
+
+       (*T)(1, 0) = st * ca;
+       (*T)(1, 1) = ct * ca;
+       (*T)(1, 2) = -sa;
+
+       (*T)(2, 0) = st * sa;
+       (*T)(2, 1) = ct * sa;
+       (*T)(2, 2) = ca;
+}
+
+void bodyTParentFromAxisAngle(const vec3 &axis, const idScalar &angle, mat33 *T)
+{
+       const idScalar c = BT_ID_COS(angle);
+       const idScalar s = -BT_ID_SIN(angle);
+       const idScalar one_m_c = 1.0 - c;
+
+       const idScalar &x = axis(0);
+       const idScalar &y = axis(1);
+       const idScalar &z = axis(2);
+
+       (*T)(0, 0) = x * x * one_m_c + c;
+       (*T)(0, 1) = x * y * one_m_c - z * s;
+       (*T)(0, 2) = x * z * one_m_c + y * s;
+
+       (*T)(1, 0) = x * y * one_m_c + z * s;
+       (*T)(1, 1) = y * y * one_m_c + c;
+       (*T)(1, 2) = y * z * one_m_c - x * s;
+
+       (*T)(2, 0) = x * z * one_m_c - y * s;
+       (*T)(2, 1) = y * z * one_m_c + x * s;
+       (*T)(2, 2) = z * z * one_m_c + c;
+}
+
+bool isPositiveDefinite(const mat33 &m)
+{
+       // test if all upper left determinants are positive
+       if (m(0, 0) <= 0)
+       {  // upper 1x1
+               return false;
+       }
+       if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) <= 0)
+       {  // upper 2x2
+               return false;
+       }
+       if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
+                m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
+                m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0)
+       {
+               return false;
+       }
+       return true;
+}
+
+bool isPositiveSemiDefinite(const mat33 &m)
+{
+       // test if all upper left determinants are positive
+       if (m(0, 0) < 0)
+       {  // upper 1x1
+               return false;
+       }
+       if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < 0)
+       {  // upper 2x2
+               return false;
+       }
+       if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
+                m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
+                m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0)
+       {
+               return false;
+       }
+       return true;
+}
+
+bool isPositiveSemiDefiniteFuzzy(const mat33 &m)
+{
+       // test if all upper left determinants are positive
+       if (m(0, 0) < -kIsZero)
+       {  // upper 1x1
+               return false;
+       }
+       if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < -kIsZero)
+       {  // upper 2x2
+               return false;
+       }
+       if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
+                m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
+                m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < -kIsZero)
+       {
+               return false;
+       }
+       return true;
+}
+
+idScalar determinant(const mat33 &m)
+{
+       return m(0, 0) * m(1, 1) * m(2, 2) + m(0, 1) * m(1, 2) * m(2, 0) + m(0, 2) * m(1, 0) * m(2, 1) -
+                  m(0, 2) * m(1, 1) * m(2, 0) - m(0, 0) * m(1, 2) * m(2, 1) - m(0, 1) * m(1, 0) * m(2, 2);
+}
+
+bool isValidInertiaMatrix(const mat33 &I, const int index, bool has_fixed_joint)
+{
+       // TODO(Thomas) do we really want this?
+       //                        in cases where the inertia tensor about the center of mass is zero,
+       //                        the determinant of the inertia tensor about the joint axis is almost
+       //                        zero and can have a very small negative value.
+       if (!isPositiveSemiDefiniteFuzzy(I))
+       {
+               bt_id_error_message(
+                       "invalid inertia matrix for body %d, not positive definite "
+                       "(fixed joint)\n",
+                       index);
+               bt_id_error_message(
+                       "matrix is:\n"
+                       "[%.20e %.20e %.20e;\n"
+                       "%.20e %.20e %.20e;\n"
+                       "%.20e %.20e %.20e]\n",
+                       I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+                       I(2, 2));
+
+               return false;
+       }
+
+       // check triangle inequality, must have I(i,i)+I(j,j)>=I(k,k)
+       if (!has_fixed_joint)
+       {
+               if (I(0, 0) + I(1, 1) < I(2, 2))
+               {
+                       bt_id_error_message("invalid inertia tensor for body %d, I(0,0) + I(1,1) < I(2,2)\n", index);
+                       bt_id_error_message(
+                               "matrix is:\n"
+                               "[%.20e %.20e %.20e;\n"
+                               "%.20e %.20e %.20e;\n"
+                               "%.20e %.20e %.20e]\n",
+                               I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+                               I(2, 2));
+                       return false;
+               }
+               if (I(0, 0) + I(1, 1) < I(2, 2))
+               {
+                       bt_id_error_message("invalid inertia tensor for body %d, I(0,0) + I(1,1) < I(2,2)\n", index);
+                       bt_id_error_message(
+                               "matrix is:\n"
+                               "[%.20e %.20e %.20e;\n"
+                               "%.20e %.20e %.20e;\n"
+                               "%.20e %.20e %.20e]\n",
+                               I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+                               I(2, 2));
+                       return false;
+               }
+               if (I(1, 1) + I(2, 2) < I(0, 0))
+               {
+                       bt_id_error_message("invalid inertia tensor for body %d, I(1,1) + I(2,2) < I(0,0)\n", index);
+                       bt_id_error_message(
+                               "matrix is:\n"
+                               "[%.20e %.20e %.20e;\n"
+                               "%.20e %.20e %.20e;\n"
+                               "%.20e %.20e %.20e]\n",
+                               I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
+                               I(2, 2));
+                       return false;
+               }
+       }
+       // check positive/zero diagonal elements
+       for (int i = 0; i < 3; i++)
+       {
+               if (I(i, i) < 0)
+               {  // accept zero
+                       bt_id_error_message("invalid inertia tensor, I(%d,%d)= %e <0\n", i, i, I(i, i));
+                       return false;
+               }
+       }
+       // check symmetry
+       if (BT_ID_FABS(I(1, 0) - I(0, 1)) > kIsZero)
+       {
+               bt_id_error_message(
+                       "invalid inertia tensor for body %d I(1,0)!=I(0,1). I(1,0)-I(0,1)= "
+                       "%e\n",
+                       index, I(1, 0) - I(0, 1));
+               return false;
+       }
+       if (BT_ID_FABS(I(2, 0) - I(0, 2)) > kIsZero)
+       {
+               bt_id_error_message(
+                       "invalid inertia tensor for body %d I(2,0)!=I(0,2). I(2,0)-I(0,2)= "
+                       "%e\n",
+                       index, I(2, 0) - I(0, 2));
+               return false;
+       }
+       if (BT_ID_FABS(I(1, 2) - I(2, 1)) > kIsZero)
+       {
+               bt_id_error_message("invalid inertia tensor body %d I(1,2)!=I(2,1). I(1,2)-I(2,1)= %e\n", index,
+                                                       I(1, 2) - I(2, 1));
+               return false;
+       }
+       return true;
+}
+
+bool isValidTransformMatrix(const mat33 &m)
+{
+#define print_mat(x)                                                                                   \
+       bt_id_error_message("matrix is [%e, %e, %e; %e, %e, %e; %e, %e, %e]\n", x(0, 0), x(0, 1), x(0, 2), \
+                                               x(1, 0), x(1, 1), x(1, 2), x(2, 0), x(2, 1), x(2, 2))
+
+       // check for unit length column vectors
+       for (int i = 0; i < 3; i++)
+       {
+               const idScalar length_minus_1 =
+                       BT_ID_FABS(m(0, i) * m(0, i) + m(1, i) * m(1, i) + m(2, i) * m(2, i) - 1.0);
+               if (length_minus_1 > kAxisLengthEpsilon)
+               {
+                       bt_id_error_message(
+                               "Not a valid rotation matrix (column %d not unit length)\n"
+                               "column = [%.18e %.18e %.18e]\n"
+                               "length-1.0= %.18e\n",
+                               i, m(0, i), m(1, i), m(2, i), length_minus_1);
+                       print_mat(m);
+                       return false;
+               }
+       }
+       // check for orthogonal column vectors
+       if (BT_ID_FABS(m(0, 0) * m(0, 1) + m(1, 0) * m(1, 1) + m(2, 0) * m(2, 1)) > kAxisLengthEpsilon)
+       {
+               bt_id_error_message("Not a valid rotation matrix (columns 0 and 1 not orthogonal)\n");
+               print_mat(m);
+               return false;
+       }
+       if (BT_ID_FABS(m(0, 0) * m(0, 2) + m(1, 0) * m(1, 2) + m(2, 0) * m(2, 2)) > kAxisLengthEpsilon)
+       {
+               bt_id_error_message("Not a valid rotation matrix (columns 0 and 2 not orthogonal)\n");
+               print_mat(m);
+               return false;
+       }
+       if (BT_ID_FABS(m(0, 1) * m(0, 2) + m(1, 1) * m(1, 2) + m(2, 1) * m(2, 2)) > kAxisLengthEpsilon)
+       {
+               bt_id_error_message("Not a valid rotation matrix (columns 0 and 2 not orthogonal)\n");
+               print_mat(m);
+               return false;
+       }
+       // check determinant (rotation not reflection)
+       if (determinant(m) <= 0)
+       {
+               bt_id_error_message("Not a valid rotation matrix (determinant <=0)\n");
+               print_mat(m);
+               return false;
+       }
+       return true;
+}
+
+bool isUnitVector(const vec3 &vector)
+{
+       return BT_ID_FABS(vector(0) * vector(0) + vector(1) * vector(1) + vector(2) * vector(2) - 1.0) <
+                  kIsZero;
+}
+
+vec3 rpyFromMatrix(const mat33 &rot)
+{
+       vec3 rpy;
+       rpy(2) = BT_ID_ATAN2(-rot(1, 0), rot(0, 0));
+       rpy(0) = BT_ID_ATAN2(-rot(2, 0), rot(2, 2));
+       rpy(1) = BT_ID_ATAN2(rot(2, 0), BT_ID_COS(rpy(2)) * rot(0, 0) - BT_ID_SIN(rpy(0)) * rot(1, 0));
+       return rpy;
+}
+}  // namespace btInverseDynamics
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDMath.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/IDMath.hpp
new file mode 100644 (file)
index 0000000..40bee53
--- /dev/null
@@ -0,0 +1,100 @@
+/// @file Math utility functions used in inverse dynamics library.
+///       Defined here as they may not be provided by the math library.
+
+#ifndef IDMATH_HPP_
+#define IDMATH_HPP_
+#include "IDConfig.hpp"
+
+namespace btInverseDynamics
+{
+/// set all elements to zero
+void setZero(vec3& v);
+/// set all elements to zero
+void setZero(vecx& v);
+/// set all elements to zero
+void setZero(mat33& m);
+/// create a skew symmetric matrix from a vector (useful for cross product abstraction, e.g. v x a = V * a)
+void skew(vec3& v, mat33* result);
+/// return maximum absolute value
+idScalar maxAbs(const vecx& v);
+#ifndef ID_LINEAR_MATH_USE_EIGEN
+/// return maximum absolute value
+idScalar maxAbs(const vec3& v);
+#endif  //ID_LINEAR_MATH_USE_EIGEN
+
+#if (defined BT_ID_HAVE_MAT3X)
+idScalar maxAbsMat3x(const mat3x& m);
+void setZero(mat3x& m);
+// define math functions on mat3x here to avoid allocations in operators.
+void mul(const mat33& a, const mat3x& b, mat3x* result);
+void add(const mat3x& a, const mat3x& b, mat3x* result);
+void sub(const mat3x& a, const mat3x& b, mat3x* result);
+#endif
+
+/// get offset vector & transform matrix from DH parameters
+/// TODO: add documentation
+void getVecMatFromDH(idScalar theta, idScalar d, idScalar a, idScalar alpha, vec3* r, mat33* T);
+
+/// Check if a 3x3 matrix is positive definite
+/// @param m a 3x3 matrix
+/// @return true if m>0, false otherwise
+bool isPositiveDefinite(const mat33& m);
+
+/// Check if a 3x3 matrix is positive semi definite
+/// @param m a 3x3 matrix
+/// @return true if m>=0, false otherwise
+bool isPositiveSemiDefinite(const mat33& m);
+/// Check if a 3x3 matrix is positive semi definite within numeric limits
+/// @param m a 3x3 matrix
+/// @return true if m>=-eps, false otherwise
+bool isPositiveSemiDefiniteFuzzy(const mat33& m);
+
+/// Determinant of 3x3 matrix
+/// NOTE: implemented here for portability, as determinant operation
+///       will be implemented differently for various matrix/vector libraries
+/// @param m a 3x3 matrix
+/// @return det(m)
+idScalar determinant(const mat33& m);
+
+/// Test if a 3x3 matrix satisfies some properties of inertia matrices
+/// @param I a 3x3 matrix
+/// @param index body index (for error messages)
+/// @param has_fixed_joint: if true, positive semi-definite matrices are accepted
+/// @return true if I satisfies inertia matrix properties, false otherwise.
+bool isValidInertiaMatrix(const mat33& I, int index, bool has_fixed_joint);
+
+/// Check if a 3x3 matrix is a valid transform (rotation) matrix
+/// @param m a 3x3 matrix
+/// @return true if m is a rotation matrix, false otherwise
+bool isValidTransformMatrix(const mat33& m);
+/// Transform matrix from parent to child frame,
+/// when the child frame is rotated about @param axis by @angle
+/// (mathematically positive)
+/// @param axis the axis of rotation
+/// @param angle rotation angle
+/// @param T pointer to transform matrix
+void bodyTParentFromAxisAngle(const vec3& axis, const idScalar& angle, mat33* T);
+
+/// Check if this is a unit vector
+/// @param vector
+/// @return true if |vector|=1 within numeric limits
+bool isUnitVector(const vec3& vector);
+
+/// @input a vector in R^3
+/// @returns corresponding spin tensor
+mat33 tildeOperator(const vec3& v);
+/// @param alpha angle in radians
+/// @returns transform matrix for ratation with @param alpha about x-axis
+mat33 transformX(const idScalar& alpha);
+/// @param beta angle in radians
+/// @returns transform matrix for ratation with @param beta about y-axis
+mat33 transformY(const idScalar& beta);
+/// @param gamma angle in radians
+/// @returns transform matrix for ratation with @param gamma about z-axis
+mat33 transformZ(const idScalar& gamma);
+///calculate rpy angles (x-y-z Euler angles) from a given rotation matrix
+/// @param rot rotation matrix
+/// @returns x-y-z Euler angles
+vec3 rpyFromMatrix(const mat33& rot);
+}  // namespace btInverseDynamics
+#endif  // IDMATH_HPP_
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/MultiBodyTree.cpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/MultiBodyTree.cpp
new file mode 100644 (file)
index 0000000..9326b0d
--- /dev/null
@@ -0,0 +1,548 @@
+#include "MultiBodyTree.hpp"
+
+#include <cmath>
+#include <limits>
+#include <vector>
+
+#include "IDMath.hpp"
+#include "details/MultiBodyTreeImpl.hpp"
+#include "details/MultiBodyTreeInitCache.hpp"
+
+namespace btInverseDynamics
+{
+MultiBodyTree::MultiBodyTree()
+       : m_is_finalized(false),
+         m_mass_parameters_are_valid(true),
+         m_accept_invalid_mass_parameters(false),
+         m_impl(0x0),
+         m_init_cache(0x0)
+{
+       m_init_cache = new InitCache();
+}
+
+MultiBodyTree::~MultiBodyTree()
+{
+       delete m_impl;
+       delete m_init_cache;
+}
+
+void MultiBodyTree::setAcceptInvalidMassParameters(bool flag)
+{
+       m_accept_invalid_mass_parameters = flag;
+}
+
+bool MultiBodyTree::getAcceptInvalidMassProperties() const
+{
+       return m_accept_invalid_mass_parameters;
+}
+
+int MultiBodyTree::getBodyOrigin(const int body_index, vec3 *world_origin) const
+{
+       return m_impl->getBodyOrigin(body_index, world_origin);
+}
+
+int MultiBodyTree::getBodyCoM(const int body_index, vec3 *world_com) const
+{
+       return m_impl->getBodyCoM(body_index, world_com);
+}
+
+int MultiBodyTree::getBodyTransform(const int body_index, mat33 *world_T_body) const
+{
+       return m_impl->getBodyTransform(body_index, world_T_body);
+}
+int MultiBodyTree::getBodyAngularVelocity(const int body_index, vec3 *world_omega) const
+{
+       return m_impl->getBodyAngularVelocity(body_index, world_omega);
+}
+int MultiBodyTree::getBodyLinearVelocity(const int body_index, vec3 *world_velocity) const
+{
+       return m_impl->getBodyLinearVelocity(body_index, world_velocity);
+}
+
+int MultiBodyTree::getBodyLinearVelocityCoM(const int body_index, vec3 *world_velocity) const
+{
+       return m_impl->getBodyLinearVelocityCoM(body_index, world_velocity);
+}
+
+int MultiBodyTree::getBodyAngularAcceleration(const int body_index, vec3 *world_dot_omega) const
+{
+       return m_impl->getBodyAngularAcceleration(body_index, world_dot_omega);
+}
+int MultiBodyTree::getBodyLinearAcceleration(const int body_index, vec3 *world_acceleration) const
+{
+       return m_impl->getBodyLinearAcceleration(body_index, world_acceleration);
+}
+
+int MultiBodyTree::getParentRParentBodyRef(const int body_index, vec3 *r) const
+{
+       return m_impl->getParentRParentBodyRef(body_index, r);
+}
+
+int MultiBodyTree::getBodyTParentRef(const int body_index, mat33 *T) const
+{
+       return m_impl->getBodyTParentRef(body_index, T);
+}
+
+int MultiBodyTree::getBodyAxisOfMotion(const int body_index, vec3 *axis) const
+{
+       return m_impl->getBodyAxisOfMotion(body_index, axis);
+}
+
+void MultiBodyTree::printTree() { m_impl->printTree(); }
+void MultiBodyTree::printTreeData() { m_impl->printTreeData(); }
+
+int MultiBodyTree::numBodies() const { return m_impl->m_num_bodies; }
+
+int MultiBodyTree::numDoFs() const { return m_impl->m_num_dofs; }
+
+int MultiBodyTree::calculateInverseDynamics(const vecx &q, const vecx &u, const vecx &dot_u,
+                                                                                       vecx *joint_forces)
+{
+       if (false == m_is_finalized)
+       {
+               bt_id_error_message("system has not been initialized\n");
+               return -1;
+       }
+       if (-1 == m_impl->calculateInverseDynamics(q, u, dot_u, joint_forces))
+       {
+               bt_id_error_message("error in inverse dynamics calculation\n");
+               return -1;
+       }
+       return 0;
+}
+
+int MultiBodyTree::calculateMassMatrix(const vecx &q, const bool update_kinematics,
+                                                                          const bool initialize_matrix,
+                                                                          const bool set_lower_triangular_matrix, matxx *mass_matrix)
+{
+       if (false == m_is_finalized)
+       {
+               bt_id_error_message("system has not been initialized\n");
+               return -1;
+       }
+       if (-1 ==
+               m_impl->calculateMassMatrix(q, update_kinematics, initialize_matrix,
+                                                                       set_lower_triangular_matrix, mass_matrix))
+       {
+               bt_id_error_message("error in mass matrix calculation\n");
+               return -1;
+       }
+       return 0;
+}
+
+int MultiBodyTree::calculateMassMatrix(const vecx &q, matxx *mass_matrix)
+{
+       return calculateMassMatrix(q, true, true, true, mass_matrix);
+}
+
+int MultiBodyTree::calculateKinematics(const vecx &q, const vecx &u, const vecx &dot_u)
+{
+       vec3 world_gravity(m_impl->m_world_gravity);
+       // temporarily set gravity to zero, to ensure we get the actual accelerations
+       setZero(m_impl->m_world_gravity);
+
+       if (false == m_is_finalized)
+       {
+               bt_id_error_message("system has not been initialized\n");
+               return -1;
+       }
+       if (-1 == m_impl->calculateKinematics(q, u, dot_u,
+                                                                                 MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY_ACCELERATION))
+       {
+               bt_id_error_message("error in kinematics calculation\n");
+               return -1;
+       }
+
+       m_impl->m_world_gravity = world_gravity;
+       return 0;
+}
+
+int MultiBodyTree::calculatePositionKinematics(const vecx &q)
+{
+       if (false == m_is_finalized)
+       {
+               bt_id_error_message("system has not been initialized\n");
+               return -1;
+       }
+       if (-1 == m_impl->calculateKinematics(q, q, q,
+                                                                                 MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY))
+       {
+               bt_id_error_message("error in kinematics calculation\n");
+               return -1;
+       }
+       return 0;
+}
+
+int MultiBodyTree::calculatePositionAndVelocityKinematics(const vecx &q, const vecx &u)
+{
+       if (false == m_is_finalized)
+       {
+               bt_id_error_message("system has not been initialized\n");
+               return -1;
+       }
+       if (-1 == m_impl->calculateKinematics(q, u, u,
+                                                                                 MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY))
+       {
+               bt_id_error_message("error in kinematics calculation\n");
+               return -1;
+       }
+       return 0;
+}
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+int MultiBodyTree::calculateJacobians(const vecx &q, const vecx &u)
+{
+       if (false == m_is_finalized)
+       {
+               bt_id_error_message("system has not been initialized\n");
+               return -1;
+       }
+       if (-1 == m_impl->calculateJacobians(q, u,
+                                                                                MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY))
+       {
+               bt_id_error_message("error in jacobian calculation\n");
+               return -1;
+       }
+       return 0;
+}
+
+int MultiBodyTree::calculateJacobians(const vecx &q)
+{
+       if (false == m_is_finalized)
+       {
+               bt_id_error_message("system has not been initialized\n");
+               return -1;
+       }
+       if (-1 == m_impl->calculateJacobians(q, q,
+                                                                                MultiBodyTree::MultiBodyImpl::POSITION_ONLY))
+       {
+               bt_id_error_message("error in jacobian calculation\n");
+               return -1;
+       }
+       return 0;
+}
+
+int MultiBodyTree::getBodyDotJacobianTransU(const int body_index, vec3 *world_dot_jac_trans_u) const
+{
+       return m_impl->getBodyDotJacobianTransU(body_index, world_dot_jac_trans_u);
+}
+
+int MultiBodyTree::getBodyDotJacobianRotU(const int body_index, vec3 *world_dot_jac_rot_u) const
+{
+       return m_impl->getBodyDotJacobianRotU(body_index, world_dot_jac_rot_u);
+}
+
+int MultiBodyTree::getBodyJacobianTrans(const int body_index, mat3x *world_jac_trans) const
+{
+       return m_impl->getBodyJacobianTrans(body_index, world_jac_trans);
+}
+
+int MultiBodyTree::getBodyJacobianRot(const int body_index, mat3x *world_jac_rot) const
+{
+       return m_impl->getBodyJacobianRot(body_index, world_jac_rot);
+}
+
+#endif
+
+int MultiBodyTree::addBody(int body_index, int parent_index, JointType joint_type,
+                                                  const vec3 &parent_r_parent_body_ref, const mat33 &body_T_parent_ref,
+                                                  const vec3 &body_axis_of_motion_, idScalar mass,
+                                                  const vec3 &body_r_body_com, const mat33 &body_I_body,
+                                                  const int user_int, void *user_ptr)
+{
+       if (body_index < 0)
+       {
+               bt_id_error_message("body index must be positive (got %d)\n", body_index);
+               return -1;
+       }
+       vec3 body_axis_of_motion(body_axis_of_motion_);
+       switch (joint_type)
+       {
+               case REVOLUTE:
+               case PRISMATIC:
+                       // check if axis is unit vector
+                       if (!isUnitVector(body_axis_of_motion))
+                       {
+                               bt_id_warning_message(
+                                       "axis of motion not a unit axis ([%f %f %f]), will use normalized vector\n",
+                                       body_axis_of_motion(0), body_axis_of_motion(1), body_axis_of_motion(2));
+                               idScalar length = BT_ID_SQRT(BT_ID_POW(body_axis_of_motion(0), 2) +
+                                                                                        BT_ID_POW(body_axis_of_motion(1), 2) +
+                                                                                        BT_ID_POW(body_axis_of_motion(2), 2));
+                               if (length < BT_ID_SQRT(std::numeric_limits<idScalar>::min()))
+                               {
+                                       bt_id_error_message("axis of motion vector too short (%e)\n", length);
+                                       return -1;
+                               }
+                               body_axis_of_motion = (1.0 / length) * body_axis_of_motion;
+                       }
+                       break;
+               case FIXED:
+                       break;
+               case FLOATING:
+                       break;
+               case SPHERICAL:
+                       break;
+               default:
+                       bt_id_error_message("unknown joint type %d\n", joint_type);
+                       return -1;
+       }
+
+       // sanity check for mass properties. Zero mass is OK.
+       if (mass < 0)
+       {
+               m_mass_parameters_are_valid = false;
+               bt_id_error_message("Body %d has invalid mass %e\n", body_index, mass);
+               if (!m_accept_invalid_mass_parameters)
+               {
+                       return -1;
+               }
+       }
+
+       if (!isValidInertiaMatrix(body_I_body, body_index, FIXED == joint_type))
+       {
+               m_mass_parameters_are_valid = false;
+               // error message printed in function call
+               if (!m_accept_invalid_mass_parameters)
+               {
+                       return -1;
+               }
+       }
+
+       if (!isValidTransformMatrix(body_T_parent_ref))
+       {
+               return -1;
+       }
+
+       return m_init_cache->addBody(body_index, parent_index, joint_type, parent_r_parent_body_ref,
+                                                                body_T_parent_ref, body_axis_of_motion, mass, body_r_body_com,
+                                                                body_I_body, user_int, user_ptr);
+}
+
+int MultiBodyTree::getParentIndex(const int body_index, int *parent_index) const
+{
+       return m_impl->getParentIndex(body_index, parent_index);
+}
+
+int MultiBodyTree::getUserInt(const int body_index, int *user_int) const
+{
+       return m_impl->getUserInt(body_index, user_int);
+}
+
+int MultiBodyTree::getUserPtr(const int body_index, void **user_ptr) const
+{
+       return m_impl->getUserPtr(body_index, user_ptr);
+}
+
+int MultiBodyTree::setUserInt(const int body_index, const int user_int)
+{
+       return m_impl->setUserInt(body_index, user_int);
+}
+
+int MultiBodyTree::setUserPtr(const int body_index, void *const user_ptr)
+{
+       return m_impl->setUserPtr(body_index, user_ptr);
+}
+
+int MultiBodyTree::finalize()
+{
+       const int &num_bodies = m_init_cache->numBodies();
+       const int &num_dofs = m_init_cache->numDoFs();
+
+       if (num_dofs < 0)
+       {
+               bt_id_error_message("Need num_dofs>=1, but num_dofs= %d\n", num_dofs);
+               //return -1;
+       }
+
+       // 1 allocate internal MultiBody structure
+       m_impl = new MultiBodyImpl(num_bodies, num_dofs);
+
+       // 2 build new index set assuring index(parent) < index(child)
+       if (-1 == m_init_cache->buildIndexSets())
+       {
+               return -1;
+       }
+       m_init_cache->getParentIndexArray(&m_impl->m_parent_index);
+
+       // 3 setup internal kinematic and dynamic data
+       for (int index = 0; index < num_bodies; index++)
+       {
+               InertiaData inertia;
+               JointData joint;
+               if (-1 == m_init_cache->getInertiaData(index, &inertia))
+               {
+                       return -1;
+               }
+               if (-1 == m_init_cache->getJointData(index, &joint))
+               {
+                       return -1;
+               }
+
+               RigidBody &rigid_body = m_impl->m_body_list[index];
+
+               rigid_body.m_mass = inertia.m_mass;
+               rigid_body.m_body_mass_com = inertia.m_mass * inertia.m_body_pos_body_com;
+               rigid_body.m_body_I_body = inertia.m_body_I_body;
+               rigid_body.m_joint_type = joint.m_type;
+               rigid_body.m_parent_pos_parent_body_ref = joint.m_parent_pos_parent_child_ref;
+               rigid_body.m_body_T_parent_ref = joint.m_child_T_parent_ref;
+               rigid_body.m_parent_pos_parent_body_ref = joint.m_parent_pos_parent_child_ref;
+               rigid_body.m_joint_type = joint.m_type;
+
+               int user_int;
+               if (-1 == m_init_cache->getUserInt(index, &user_int))
+               {
+                       return -1;
+               }
+               if (-1 == m_impl->setUserInt(index, user_int))
+               {
+                       return -1;
+               }
+
+               void *user_ptr;
+               if (-1 == m_init_cache->getUserPtr(index, &user_ptr))
+               {
+                       return -1;
+               }
+               if (-1 == m_impl->setUserPtr(index, user_ptr))
+               {
+                       return -1;
+               }
+
+               // Set joint Jacobians. Note that the dimension is always 3x1 here to avoid variable sized
+               // matrices.
+               switch (rigid_body.m_joint_type)
+               {
+                       case REVOLUTE:
+                               rigid_body.m_Jac_JR(0) = joint.m_child_axis_of_motion(0);
+                               rigid_body.m_Jac_JR(1) = joint.m_child_axis_of_motion(1);
+                               rigid_body.m_Jac_JR(2) = joint.m_child_axis_of_motion(2);
+                               rigid_body.m_Jac_JT(0) = 0.0;
+                               rigid_body.m_Jac_JT(1) = 0.0;
+                               rigid_body.m_Jac_JT(2) = 0.0;
+                               break;
+                       case PRISMATIC:
+                               rigid_body.m_Jac_JR(0) = 0.0;
+                               rigid_body.m_Jac_JR(1) = 0.0;
+                               rigid_body.m_Jac_JR(2) = 0.0;
+                               rigid_body.m_Jac_JT(0) = joint.m_child_axis_of_motion(0);
+                               rigid_body.m_Jac_JT(1) = joint.m_child_axis_of_motion(1);
+                               rigid_body.m_Jac_JT(2) = joint.m_child_axis_of_motion(2);
+                               break;
+                       case FIXED:
+                               // NOTE/TODO: dimension really should be zero ..
+                               rigid_body.m_Jac_JR(0) = 0.0;
+                               rigid_body.m_Jac_JR(1) = 0.0;
+                               rigid_body.m_Jac_JR(2) = 0.0;
+                               rigid_body.m_Jac_JT(0) = 0.0;
+                               rigid_body.m_Jac_JT(1) = 0.0;
+                               rigid_body.m_Jac_JT(2) = 0.0;
+                               break;
+                       case SPHERICAL:
+                               // NOTE/TODO: this is not really correct.
+                               // the Jacobians should be 3x3 matrices here !
+                               rigid_body.m_Jac_JR(0) = 0.0;
+                               rigid_body.m_Jac_JR(1) = 0.0;
+                               rigid_body.m_Jac_JR(2) = 0.0;
+                               rigid_body.m_Jac_JT(0) = 0.0;
+                               rigid_body.m_Jac_JT(1) = 0.0;
+                               rigid_body.m_Jac_JT(2) = 0.0;
+                               break;
+                       case FLOATING:
+                               // NOTE/TODO: this is not really correct.
+                               // the Jacobians should be 3x3 matrices here !
+                               rigid_body.m_Jac_JR(0) = 0.0;
+                               rigid_body.m_Jac_JR(1) = 0.0;
+                               rigid_body.m_Jac_JR(2) = 0.0;
+                               rigid_body.m_Jac_JT(0) = 0.0;
+                               rigid_body.m_Jac_JT(1) = 0.0;
+                               rigid_body.m_Jac_JT(2) = 0.0;
+                               break;
+                       default:
+                               bt_id_error_message("unsupported joint type %d\n", rigid_body.m_joint_type);
+                               return -1;
+               }
+       }
+
+       // 4 assign degree of freedom indices & build per-joint-type index arrays
+       if (-1 == m_impl->generateIndexSets())
+       {
+               bt_id_error_message("generating index sets\n");
+               return -1;
+       }
+
+       // 5 do some pre-computations ..
+       m_impl->calculateStaticData();
+
+       // 6. make sure all user forces are set to zero, as this might not happen
+       //      in the vector ctors.
+       m_impl->clearAllUserForcesAndMoments();
+
+       m_is_finalized = true;
+       return 0;
+}
+
+int MultiBodyTree::setGravityInWorldFrame(const vec3 &gravity)
+{
+       return m_impl->setGravityInWorldFrame(gravity);
+}
+
+int MultiBodyTree::getJointType(const int body_index, JointType *joint_type) const
+{
+       return m_impl->getJointType(body_index, joint_type);
+}
+
+int MultiBodyTree::getJointTypeStr(const int body_index, const char **joint_type) const
+{
+       return m_impl->getJointTypeStr(body_index, joint_type);
+}
+
+int MultiBodyTree::getDoFOffset(const int body_index, int *q_offset) const
+{
+       return m_impl->getDoFOffset(body_index, q_offset);
+}
+
+int MultiBodyTree::setBodyMass(const int body_index, idScalar mass)
+{
+       return m_impl->setBodyMass(body_index, mass);
+}
+
+int MultiBodyTree::setBodyFirstMassMoment(const int body_index, const vec3 &first_mass_moment)
+{
+       return m_impl->setBodyFirstMassMoment(body_index, first_mass_moment);
+}
+
+int MultiBodyTree::setBodySecondMassMoment(const int body_index, const mat33 &second_mass_moment)
+{
+       return m_impl->setBodySecondMassMoment(body_index, second_mass_moment);
+}
+
+int MultiBodyTree::getBodyMass(const int body_index, idScalar *mass) const
+{
+       return m_impl->getBodyMass(body_index, mass);
+}
+
+int MultiBodyTree::getBodyFirstMassMoment(const int body_index, vec3 *first_mass_moment) const
+{
+       return m_impl->getBodyFirstMassMoment(body_index, first_mass_moment);
+}
+
+int MultiBodyTree::getBodySecondMassMoment(const int body_index, mat33 *second_mass_moment) const
+{
+       return m_impl->getBodySecondMassMoment(body_index, second_mass_moment);
+}
+
+void MultiBodyTree::clearAllUserForcesAndMoments() { m_impl->clearAllUserForcesAndMoments(); }
+
+int MultiBodyTree::addUserForce(const int body_index, const vec3 &body_force)
+{
+       return m_impl->addUserForce(body_index, body_force);
+}
+
+int MultiBodyTree::addUserMoment(const int body_index, const vec3 &body_moment)
+{
+       return m_impl->addUserMoment(body_index, body_moment);
+}
+
+}  // namespace btInverseDynamics
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/MultiBodyTree.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/MultiBodyTree.hpp
new file mode 100644 (file)
index 0000000..7b852f9
--- /dev/null
@@ -0,0 +1,367 @@
+#ifndef MULTIBODYTREE_HPP_
+#define MULTIBODYTREE_HPP_
+
+#include "IDConfig.hpp"
+#include "IDMath.hpp"
+
+namespace btInverseDynamics
+{
+/// Enumeration of supported joint types
+enum JointType
+{
+       /// no degree of freedom, moves with parent
+       FIXED = 0,
+       /// one rotational degree of freedom relative to parent
+       REVOLUTE,
+       /// one translational degree of freedom relative to parent
+       PRISMATIC,
+       /// six degrees of freedom relative to parent
+       FLOATING,
+       /// three degrees of freedom, relative to parent
+       SPHERICAL
+};
+
+/// Interface class for calculating inverse dynamics for tree structured
+/// multibody systems
+///
+/// Note on degrees of freedom
+/// The q vector contains the generalized coordinate set defining the tree's configuration.
+/// Every joint adds elements that define the corresponding link's frame pose relative to
+/// its parent. For the joint types that is:
+///    - FIXED:         none
+///    - REVOLUTE:  angle of rotation [rad]
+///    - PRISMATIC: displacement [m]
+///    - FLOATING:  Euler x-y-z angles [rad] and displacement in body-fixed frame of parent [m]
+///                             (in that order)
+/// - SPHERICAL: Euler x-y-z angles [rad]
+/// The u vector contains the generalized speeds, which are
+///    - FIXED:         none
+///    - REVOLUTE:  time derivative of angle of rotation [rad/s]
+///    - PRISMATIC: time derivative of displacement [m/s]
+///    - FLOATING:  angular velocity [rad/s] (*not* time derivative of rpy angles)
+///                             and time derivative of displacement in parent frame [m/s]
+//     - SPHERICAL:  angular velocity [rad/s]
+///
+/// The q and u vectors are obtained by stacking contributions of all bodies in one
+/// vector in the order of body indices.
+///
+/// Note on generalized forces: analogous to u, i.e.,
+///     - FIXED:        none
+///     - REVOLUTE:  moment [Nm], about joint axis
+///     - PRISMATIC: force  [N], along joint axis
+///     - FLOATING:  moment vector [Nm] and force vector [N], both in body-fixed frame
+///                              (in that order)
+///  - SPHERICAL: moment vector [Nm] 
+/// TODO - force element interface (friction, springs, dampers, etc)
+///      - gears and motor inertia
+class MultiBodyTree
+{
+public:
+       ID_DECLARE_ALIGNED_ALLOCATOR();
+       /// The contructor.
+       /// Initialization & allocation is via addBody and buildSystem calls.
+       MultiBodyTree();
+       /// the destructor. This also deallocates all memory
+       ~MultiBodyTree();
+
+       /// Add body to the system. this allocates memory and not real-time safe.
+       /// This only adds the data to an initial cache. After all bodies have been
+       /// added,
+       /// the system is setup using the buildSystem call
+       /// @param body_index index of the body to be added. Must >=0, <number of bodies,
+       ///             and index of parent must be < index of body
+       /// @param parent_index index of the parent body
+       ///             The root of the tree has index 0 and its parent (the world frame)
+       ///             is assigned index -1
+       ///             the rotation and translation relative to the parent are taken as
+       ///             pose of the root body relative to the world frame. Other parameters
+       ///             are ignored
+       /// @param JointType type of joint connecting the body to the parent
+       /// @param mass the mass of the body
+       /// @param body_r_body_com the center of mass of the body relative to and
+       /// described in
+       ///             the body fixed frame, which is located in the joint axis connecting
+       /// the body to its parent
+       /// @param body_I_body the moment of inertia of the body w.r.t the body-fixed
+       /// frame
+       ///             (ie, the reference point is the origin of the body-fixed frame and
+       /// the matrix is written
+       ///              w.r.t. those unit vectors)
+       /// @param parent_r_parent_body_ref position of joint relative to the parent
+       /// body's reference frame
+       ///             for q=0, written in the parent bodies reference frame
+       /// @param body_axis_of_motion translation/rotation axis in body-fixed frame.
+       ///             Ignored for joints that are not revolute or prismatic.
+       ///             must be a unit vector.
+       /// @param body_T_parent_ref transform matrix from parent to body reference
+       /// frame for q=0.
+       ///             This is the matrix transforming a vector represented in the
+       /// parent's reference frame into one represented
+       ///             in this body's reference frame.
+       ///             ie, if parent_vec is a vector in R^3 whose components are w.r.t to
+       /// the parent's reference frame,
+       ///             then the same vector written w.r.t. this body's frame (for q=0) is
+       /// given by
+       ///             body_vec = parent_R_body_ref * parent_vec
+       /// @param user_ptr pointer to user data
+       /// @param user_int pointer to user integer
+       /// @return 0 on success, -1 on error
+       int addBody(int body_index, int parent_index, JointType joint_type,
+                               const vec3& parent_r_parent_body_ref, const mat33& body_T_parent_ref,
+                               const vec3& body_axis_of_motion, idScalar mass, const vec3& body_r_body_com,
+                               const mat33& body_I_body, const int user_int, void* user_ptr);
+       /// set policy for invalid mass properties
+       /// @param flag if true, invalid mass properties are accepted,
+       ///             the default is false
+       void setAcceptInvalidMassParameters(bool flag);
+       /// @return the mass properties policy flag
+       bool getAcceptInvalidMassProperties() const;
+       /// build internal data structures
+       /// call this after all bodies have been added via addBody
+       /// @return 0 on success, -1 on error
+       int finalize();
+       /// pretty print ascii description of tree to stdout
+       void printTree();
+       /// print tree data to stdout
+       void printTreeData();
+       /// Calculate joint forces for given generalized state & derivatives.
+       /// This also updates kinematic terms computed in calculateKinematics.
+       /// If gravity is not set to zero, acceleration terms will contain
+       /// gravitational acceleration.
+       /// @param q generalized coordinates
+       /// @param u generalized velocities. In the general case, u=T(q)*dot(q) and dim(q)>=dim(u)
+       /// @param dot_u time derivative of u
+       /// @param joint_forces this is where the resulting joint forces will be
+       ///             stored. dim(joint_forces) = dim(u)
+       /// @return 0 on success, -1 on error
+       int calculateInverseDynamics(const vecx& q, const vecx& u, const vecx& dot_u,
+                                                                vecx* joint_forces);
+       /// Calculate joint space mass matrix
+       /// @param q generalized coordinates
+       /// @param initialize_matrix if true, initialize mass matrix with zero.
+       ///             If mass_matrix is initialized to zero externally and only used
+       ///             for mass matrix computations for the same system, it is safe to
+       ///             set this to false.
+       /// @param set_lower_triangular_matrix if true, the lower triangular section of mass_matrix
+       ///             is also populated, otherwise not.
+       /// @param mass_matrix matrix for storing the output (should be dim(q)xdim(q))
+       /// @return -1 on error, 0 on success
+       int calculateMassMatrix(const vecx& q, const bool update_kinematics,
+                                                       const bool initialize_matrix, const bool set_lower_triangular_matrix,
+                                                       matxx* mass_matrix);
+
+       /// Calculate joint space mass matrix.
+       /// This version will update kinematics, initialize all mass_matrix elements to zero and
+       /// populate all mass matrix entries.
+       /// @param q generalized coordinates
+       /// @param mass_matrix matrix for storing the output (should be dim(q)xdim(q))
+       /// @return -1 on error, 0 on success
+       int calculateMassMatrix(const vecx& q, matxx* mass_matrix);
+
+       /// Calculates kinematics also calculated in calculateInverseDynamics,
+       /// but not dynamics.
+       /// This function ensures that correct accelerations are computed that do not
+       /// contain gravitational acceleration terms.
+       /// Does not calculate Jacobians, but only vector quantities (positions, velocities & accelerations)
+       int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u);
+       /// Calculate position kinematics
+       int calculatePositionKinematics(const vecx& q);
+       /// Calculate position and velocity kinematics
+       int calculatePositionAndVelocityKinematics(const vecx& q, const vecx& u);
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+       /// Calculate Jacobians (dvel/du), as well as velocity-dependent accelearation components
+       /// d(Jacobian)/dt*u
+       /// This function assumes that calculateInverseDynamics was called, or calculateKinematics,
+       /// or calculatePositionAndVelocityKinematics
+       int calculateJacobians(const vecx& q, const vecx& u);
+       /// Calculate Jacobians (dvel/du)
+       /// This function assumes that calculateInverseDynamics was called, or
+       /// one of the calculateKineamtics functions
+       int calculateJacobians(const vecx& q);
+#endif  // BT_ID_HAVE_MAT3X
+
+       /// set gravitational acceleration
+       /// the default is [0;0;-9.8] in the world frame
+       /// @param gravity the gravitational acceleration in world frame
+       /// @return 0 on success, -1 on error
+       int setGravityInWorldFrame(const vec3& gravity);
+       /// returns number of bodies in tree
+       int numBodies() const;
+       /// returns number of mechanical degrees of freedom (dimension of q-vector)
+       int numDoFs() const;
+       /// get origin of a body-fixed frame, represented in world frame
+       /// @param body_index index for frame/body
+       /// @param world_origin pointer for return data
+       /// @return 0 on success, -1 on error
+       int getBodyOrigin(const int body_index, vec3* world_origin) const;
+       /// get center of mass of a body, represented in world frame
+       /// @param body_index index for frame/body
+       /// @param world_com pointer for return data
+       /// @return 0 on success, -1 on error
+       int getBodyCoM(const int body_index, vec3* world_com) const;
+       /// get transform from of a body-fixed frame to the world frame
+       /// @param body_index index for frame/body
+       /// @param world_T_body pointer for return data
+       /// @return 0 on success, -1 on error
+       int getBodyTransform(const int body_index, mat33* world_T_body) const;
+       /// get absolute angular velocity for a body, represented in the world frame
+       /// @param body_index index for frame/body
+       /// @param world_omega pointer for return data
+       /// @return 0 on success, -1 on error
+       int getBodyAngularVelocity(const int body_index, vec3* world_omega) const;
+       /// get linear velocity of a body, represented in world frame
+       /// @param body_index index for frame/body
+       /// @param world_velocity pointer for return data
+       /// @return 0 on success, -1 on error
+       int getBodyLinearVelocity(const int body_index, vec3* world_velocity) const;
+       /// get linear velocity of a body's CoM, represented in world frame
+       /// (not required for inverse dynamics, provided for convenience)
+       /// @param body_index index for frame/body
+       /// @param world_vel_com pointer for return data
+       /// @return 0 on success, -1 on error
+       int getBodyLinearVelocityCoM(const int body_index, vec3* world_velocity) const;
+       /// get origin of a body-fixed frame, represented in world frame
+       /// @param body_index index for frame/body
+       /// @param world_origin pointer for return data
+       /// @return 0 on success, -1 on error
+       int getBodyAngularAcceleration(const int body_index, vec3* world_dot_omega) const;
+       /// get origin of a body-fixed frame, represented in world frame
+       /// NOTE: this will include the gravitational acceleration, so the actual acceleration is
+       /// obtainened by setting gravitational acceleration to zero, or subtracting it.
+       /// @param body_index index for frame/body
+       /// @param world_origin pointer for return data
+       /// @return 0 on success, -1 on error
+       int getBodyLinearAcceleration(const int body_index, vec3* world_acceleration) const;
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+       // get translational jacobian, in world frame (dworld_velocity/du)
+       int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const;
+       // get rotational jacobian, in world frame (dworld_omega/du)
+       int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
+       // get product of translational jacobian derivative * generatlized velocities
+       int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const;
+       // get product of rotational jacobian derivative * generatlized velocities
+       int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
+#endif  // BT_ID_HAVE_MAT3X
+
+       /// returns the (internal) index of body
+       /// @param body_index is the index of a body
+       /// @param parent_index pointer to where parent index will be stored
+       /// @return 0 on success, -1 on error
+       int getParentIndex(const int body_index, int* parent_index) const;
+       /// get joint type
+       /// @param body_index index of the body
+       /// @param joint_type the corresponding joint type
+       /// @return 0 on success, -1 on failure
+       int getJointType(const int body_index, JointType* joint_type) const;
+       /// get joint type as string
+       /// @param body_index index of the body
+       /// @param joint_type string naming the corresponding joint type
+       /// @return 0 on success, -1 on failure
+       int getJointTypeStr(const int body_index, const char** joint_type) const;
+       /// get offset translation to parent body (see addBody)
+       /// @param body_index index of the body
+       /// @param r the offset translation (see above)
+       /// @return 0 on success, -1 on failure
+       int getParentRParentBodyRef(const int body_index, vec3* r) const;
+       /// get offset rotation to parent body (see addBody)
+       /// @param body_index index of the body
+       /// @param T the transform (see above)
+       /// @return 0 on success, -1 on failure
+       int getBodyTParentRef(const int body_index, mat33* T) const;
+       /// get axis of motion (see addBody)
+       /// @param body_index index of the body
+       /// @param axis the axis (see above)
+       /// @return 0 on success, -1 on failure
+       int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
+       /// get offset for degrees of freedom of this body into the q-vector
+       /// @param body_index index of the body
+       /// @param q_offset offset the q vector
+       /// @return -1 on error, 0 on success
+       int getDoFOffset(const int body_index, int* q_offset) const;
+       /// get user integer. not used by the library.
+       /// @param body_index index of the body
+       /// @param user_int   the user integer
+       /// @return 0 on success, -1 on error
+       int getUserInt(const int body_index, int* user_int) const;
+       /// get user pointer. not used by the library.
+       /// @param body_index index of the body
+       /// @param user_ptr   the user pointer
+       /// @return 0 on success, -1 on error
+       int getUserPtr(const int body_index, void** user_ptr) const;
+       /// set user integer. not used by the library.
+       /// @param body_index index of the body
+       /// @param user_int   the user integer
+       /// @return 0 on success, -1 on error
+       int setUserInt(const int body_index, const int user_int);
+       /// set user pointer. not used by the library.
+       /// @param body_index index of the body
+       /// @param user_ptr   the user pointer
+       /// @return 0 on success, -1 on error
+       int setUserPtr(const int body_index, void* const user_ptr);
+       /// set mass for a body
+       /// @param body_index index of the body
+       /// @param mass the mass to set
+       /// @return 0 on success, -1 on failure
+       int setBodyMass(const int body_index, const idScalar mass);
+       /// set first moment of mass for a body
+       /// (mass * center of mass, in body fixed frame, relative to joint)
+       /// @param body_index index of the body
+       /// @param first_mass_moment the vector to set
+       /// @return 0 on success, -1 on failure
+       int setBodyFirstMassMoment(const int body_index, const vec3& first_mass_moment);
+       /// set second moment of mass for a body
+       /// (moment of inertia, in body fixed frame, relative to joint)
+       /// @param body_index index of the body
+       /// @param second_mass_moment the inertia matrix
+       /// @return 0 on success, -1 on failure
+       int setBodySecondMassMoment(const int body_index, const mat33& second_mass_moment);
+       /// get mass for a body
+       /// @param body_index index of the body
+       /// @param mass the mass
+       /// @return 0 on success, -1 on failure
+       int getBodyMass(const int body_index, idScalar* mass) const;
+       /// get first moment of mass for a body
+       /// (mass * center of mass, in body fixed frame, relative to joint)
+       /// @param body_index index of the body
+       /// @param first_moment the vector
+       /// @return 0 on success, -1 on failure
+       int getBodyFirstMassMoment(const int body_index, vec3* first_mass_moment) const;
+       /// get second moment of mass for a body
+       /// (moment of inertia, in body fixed frame, relative to joint)
+       /// @param body_index index of the body
+       /// @param second_mass_moment the inertia matrix
+       /// @return 0 on success, -1 on failure
+       int getBodySecondMassMoment(const int body_index, mat33* second_mass_moment) const;
+       /// set all user forces and moments to zero
+       void clearAllUserForcesAndMoments();
+       /// Add an external force to a body, acting at the origin of the body-fixed frame.
+       /// Calls to addUserForce are cumulative. Set the user force and moment to zero
+       /// via clearAllUserForcesAndMoments()
+       /// @param body_force the force represented in the body-fixed frame of reference
+       /// @return 0 on success, -1 on error
+       int addUserForce(const int body_index, const vec3& body_force);
+       /// Add an external moment to a body.
+       /// Calls to addUserMoment are cumulative. Set the user force and moment to zero
+       /// via clearAllUserForcesAndMoments()
+       /// @param body_moment the moment represented in the body-fixed frame of reference
+       /// @return 0 on success, -1 on error
+       int addUserMoment(const int body_index, const vec3& body_moment);
+
+private:
+       // flag indicating if system has been initialized
+       bool m_is_finalized;
+       // flag indicating if mass properties are physically valid
+       bool m_mass_parameters_are_valid;
+       // flag defining if unphysical mass parameters are accepted
+       bool m_accept_invalid_mass_parameters;
+       // This struct implements the inverse dynamics calculations
+       class MultiBodyImpl;
+       MultiBodyImpl* m_impl;
+       // cache data structure for initialization
+       class InitCache;
+       InitCache* m_init_cache;
+};
+}  // namespace btInverseDynamics
+#endif  // MULTIBODYTREE_HPP_
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/IDEigenInterface.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/IDEigenInterface.hpp
new file mode 100644 (file)
index 0000000..fe4f102
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef INVDYNEIGENINTERFACE_HPP_
+#define INVDYNEIGENINTERFACE_HPP_
+#include "../IDConfig.hpp"
+namespace btInverseDynamics
+{
+#define BT_ID_HAVE_MAT3X
+
+#ifdef BT_USE_DOUBLE_PRECISION
+typedef Eigen::Matrix<double, Eigen::Dynamic, 1, Eigen::DontAlign> vecx;
+typedef Eigen::Matrix<double, 3, 1, Eigen::DontAlign> vec3;
+typedef Eigen::Matrix<double, 3, 3, Eigen::DontAlign> mat33;
+typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> matxx;
+typedef Eigen::Matrix<double, 3, Eigen::Dynamic, Eigen::DontAlign> mat3x;
+#else
+typedef Eigen::Matrix<float, Eigen::Dynamic, 1, Eigen::DontAlign> vecx;
+typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> vec3;
+typedef Eigen::Matrix<float, 3, 3, Eigen::DontAlign> mat33;
+typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> matxx;
+typedef Eigen::Matrix<float, 3, Eigen::Dynamic, Eigen::DontAlign> mat3x;
+#endif
+
+inline void resize(mat3x &m, Eigen::Index size)
+{
+       m.resize(3, size);
+       m.setZero();
+}
+
+inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx *m)
+{
+       (*m)(row, col) = val;
+}
+
+inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x *m)
+{
+       (*m)(row, col) = val;
+}
+
+}  // namespace btInverseDynamics
+#endif  // INVDYNEIGENINTERFACE_HPP_
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/IDLinearMathInterface.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/IDLinearMathInterface.hpp
new file mode 100644 (file)
index 0000000..0c398a3
--- /dev/null
@@ -0,0 +1,202 @@
+#ifndef IDLINEARMATHINTERFACE_HPP_
+#define IDLINEARMATHINTERFACE_HPP_
+
+#include <cstdlib>
+
+#include "../IDConfig.hpp"
+
+#include "../../LinearMath/btMatrix3x3.h"
+#include "../../LinearMath/btVector3.h"
+#include "../../LinearMath/btMatrixX.h"
+#define BT_ID_HAVE_MAT3X
+
+namespace btInverseDynamics
+{
+class vec3;
+class vecx;
+class mat33;
+typedef btMatrixX<idScalar> matxx;
+
+class vec3 : public btVector3
+{
+public:
+       vec3() : btVector3() {}
+       vec3(const btVector3& btv) { *this = btv; }
+       idScalar& operator()(int i) { return (*this)[i]; }
+       const idScalar& operator()(int i) const { return (*this)[i]; }
+       int size() const { return 3; }
+       const vec3& operator=(const btVector3& rhs)
+       {
+               *static_cast<btVector3*>(this) = rhs;
+               return *this;
+       }
+};
+
+class mat33 : public btMatrix3x3
+{
+public:
+       mat33() : btMatrix3x3() {}
+       mat33(const btMatrix3x3& btm) { *this = btm; }
+       idScalar& operator()(int i, int j) { return (*this)[i][j]; }
+       const idScalar& operator()(int i, int j) const { return (*this)[i][j]; }
+       const mat33& operator=(const btMatrix3x3& rhs)
+       {
+               *static_cast<btMatrix3x3*>(this) = rhs;
+               return *this;
+       }
+       friend mat33 operator*(const idScalar& s, const mat33& a);
+       friend mat33 operator/(const mat33& a, const idScalar& s);
+};
+
+inline mat33 operator/(const mat33& a, const idScalar& s) { return a * (1.0 / s); }
+
+inline mat33 operator*(const idScalar& s, const mat33& a) { return a * s; }
+
+class vecx : public btVectorX<idScalar>
+{
+public:
+       vecx(int size) : btVectorX<idScalar>(size) {}
+       const vecx& operator=(const btVectorX<idScalar>& rhs)
+       {
+               *static_cast<btVectorX<idScalar>*>(this) = rhs;
+               return *this;
+       }
+
+       idScalar& operator()(int i) { return (*this)[i]; }
+       const idScalar& operator()(int i) const { return (*this)[i]; }
+
+       friend vecx operator*(const vecx& a, const idScalar& s);
+       friend vecx operator*(const idScalar& s, const vecx& a);
+
+       friend vecx operator+(const vecx& a, const vecx& b);
+       friend vecx operator-(const vecx& a, const vecx& b);
+       friend vecx operator/(const vecx& a, const idScalar& s);
+};
+
+inline vecx operator*(const vecx& a, const idScalar& s)
+{
+       vecx result(a.size());
+       for (int i = 0; i < result.size(); i++)
+       {
+               result(i) = a(i) * s;
+       }
+       return result;
+}
+inline vecx operator*(const idScalar& s, const vecx& a) { return a * s; }
+inline vecx operator+(const vecx& a, const vecx& b)
+{
+       vecx result(a.size());
+       // TODO: error handling for a.size() != b.size()??
+       if (a.size() != b.size())
+       {
+               bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
+               abort();
+       }
+       for (int i = 0; i < a.size(); i++)
+       {
+               result(i) = a(i) + b(i);
+       }
+
+       return result;
+}
+
+inline vecx operator-(const vecx& a, const vecx& b)
+{
+       vecx result(a.size());
+       // TODO: error handling for a.size() != b.size()??
+       if (a.size() != b.size())
+       {
+               bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
+               abort();
+       }
+       for (int i = 0; i < a.size(); i++)
+       {
+               result(i) = a(i) - b(i);
+       }
+       return result;
+}
+inline vecx operator/(const vecx& a, const idScalar& s)
+{
+       vecx result(a.size());
+       for (int i = 0; i < result.size(); i++)
+       {
+               result(i) = a(i) / s;
+       }
+
+       return result;
+}
+
+// use btMatrixX to implement 3xX matrix
+class mat3x : public matxx
+{
+public:
+       mat3x() {}
+       mat3x(const mat3x& rhs)
+       {
+               matxx::resize(rhs.rows(), rhs.cols());
+               *this = rhs;
+       }
+       mat3x(int rows, int cols) : matxx(3, cols)
+       {
+       }
+       void operator=(const mat3x& rhs)
+       {
+               if (m_cols != rhs.m_cols)
+               {
+                       bt_id_error_message("size missmatch, cols= %d but rhs.cols= %d\n", cols(), rhs.cols());
+                       abort();
+               }
+               for (int i = 0; i < rows(); i++)
+               {
+                       for (int k = 0; k < cols(); k++)
+                       {
+                               setElem(i, k, rhs(i, k));
+                       }
+               }
+       }
+       void setZero()
+       {
+               matxx::setZero();
+       }
+};
+
+inline vec3 operator*(const mat3x& a, const vecx& b)
+{
+       vec3 result;
+       if (a.cols() != b.size())
+       {
+               bt_id_error_message("size missmatch. a.cols()= %d, b.size()= %d\n", a.cols(), b.size());
+               abort();
+       }
+       result(0) = 0.0;
+       result(1) = 0.0;
+       result(2) = 0.0;
+       for (int i = 0; i < b.size(); i++)
+       {
+               for (int k = 0; k < 3; k++)
+               {
+                       result(k) += a(k, i) * b(i);
+               }
+       }
+       return result;
+}
+
+inline void resize(mat3x& m, idArrayIdx size)
+{
+       m.resize(3, size);
+       m.setZero();
+}
+
+inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx* m)
+{
+       m->setElem(row, col, val);
+}
+
+inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x* m)
+{
+       m->setElem(row, col, val);
+}
+
+}  // namespace btInverseDynamics
+
+#endif  // IDLINEARMATHINTERFACE_HPP_
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/IDMatVec.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/IDMatVec.hpp
new file mode 100644 (file)
index 0000000..1c78609
--- /dev/null
@@ -0,0 +1,489 @@
+/// @file Built-In Matrix-Vector functions
+#ifndef IDMATVEC_HPP_
+#define IDMATVEC_HPP_
+
+#include <cstdlib>
+
+#include "../IDConfig.hpp"
+#define BT_ID_HAVE_MAT3X
+
+namespace btInverseDynamics
+{
+class vec3;
+class vecx;
+class mat33;
+class matxx;
+class mat3x;
+
+/// This is a very basic implementation to enable stand-alone use of the library.
+/// The implementation is not really optimized and misses many features that you would
+/// want from a "fully featured" linear math library.
+class vec3
+{
+public:
+       idScalar& operator()(int i) { return m_data[i]; }
+       const idScalar& operator()(int i) const { return m_data[i]; }
+       const int size() const { return 3; }
+       const vec3& operator=(const vec3& rhs);
+       const vec3& operator+=(const vec3& b);
+       const vec3& operator-=(const vec3& b);
+       vec3 cross(const vec3& b) const;
+       idScalar dot(const vec3& b) const;
+
+       friend vec3 operator*(const mat33& a, const vec3& b);
+       friend vec3 operator*(const vec3& a, const idScalar& s);
+       friend vec3 operator*(const idScalar& s, const vec3& a);
+
+       friend vec3 operator+(const vec3& a, const vec3& b);
+       friend vec3 operator-(const vec3& a, const vec3& b);
+       friend vec3 operator/(const vec3& a, const idScalar& s);
+
+private:
+       idScalar m_data[3];
+};
+
+class mat33
+{
+public:
+       idScalar& operator()(int i, int j) { return m_data[3 * i + j]; }
+       const idScalar& operator()(int i, int j) const { return m_data[3 * i + j]; }
+       const mat33& operator=(const mat33& rhs);
+       mat33 transpose() const;
+       const mat33& operator+=(const mat33& b);
+       const mat33& operator-=(const mat33& b);
+
+       friend mat33 operator*(const mat33& a, const mat33& b);
+       friend vec3 operator*(const mat33& a, const vec3& b);
+       friend mat33 operator*(const mat33& a, const idScalar& s);
+       friend mat33 operator*(const idScalar& s, const mat33& a);
+       friend mat33 operator+(const mat33& a, const mat33& b);
+       friend mat33 operator-(const mat33& a, const mat33& b);
+       friend mat33 operator/(const mat33& a, const idScalar& s);
+
+private:
+       // layout is [0,1,2;3,4,5;6,7,8]
+       idScalar m_data[9];
+};
+
+class vecx
+{
+public:
+       vecx(int size) : m_size(size)
+       {
+               m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * size));
+       }
+       ~vecx() { idFree(m_data); }
+       const vecx& operator=(const vecx& rhs);
+       idScalar& operator()(int i) { return m_data[i]; }
+       const idScalar& operator()(int i) const { return m_data[i]; }
+       const int& size() const { return m_size; }
+
+       friend vecx operator*(const vecx& a, const idScalar& s);
+       friend vecx operator*(const idScalar& s, const vecx& a);
+
+       friend vecx operator+(const vecx& a, const vecx& b);
+       friend vecx operator-(const vecx& a, const vecx& b);
+       friend vecx operator/(const vecx& a, const idScalar& s);
+
+private:
+       int m_size;
+       idScalar* m_data;
+};
+
+class matxx
+{
+public:
+       matxx()
+       {
+               m_data = 0x0;
+               m_cols = 0;
+               m_rows = 0;
+       }
+       matxx(int rows, int cols) : m_rows(rows), m_cols(cols)
+       {
+               m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * rows * cols));
+       }
+       ~matxx() { idFree(m_data); }
+       idScalar& operator()(int row, int col) { return m_data[row * m_cols + col]; }
+       const idScalar& operator()(int row, int col) const { return m_data[row * m_cols + col]; }
+       const int& rows() const { return m_rows; }
+       const int& cols() const { return m_cols; }
+
+private:
+       int m_rows;
+       int m_cols;
+       idScalar* m_data;
+};
+
+class mat3x
+{
+public:
+       mat3x()
+       {
+               m_data = 0x0;
+               m_cols = 0;
+       }
+       mat3x(const mat3x& rhs)
+       {
+               m_cols = rhs.m_cols;
+               allocate();
+               *this = rhs;
+       }
+       mat3x(int rows, int cols) : m_cols(cols)
+       {
+               allocate();
+       };
+       void operator=(const mat3x& rhs)
+       {
+               if (m_cols != rhs.m_cols)
+               {
+                       bt_id_error_message("size missmatch, cols= %d but rhs.cols= %d\n", cols(), rhs.cols());
+                       abort();
+               }
+               for (int i = 0; i < 3 * m_cols; i++)
+               {
+                       m_data[i] = rhs.m_data[i];
+               }
+       }
+
+       ~mat3x()
+       {
+               free();
+       }
+       idScalar& operator()(int row, int col) { return m_data[row * m_cols + col]; }
+       const idScalar& operator()(int row, int col) const { return m_data[row * m_cols + col]; }
+       int rows() const { return m_rows; }
+       const int& cols() const { return m_cols; }
+       void resize(int rows, int cols)
+       {
+               m_cols = cols;
+               free();
+               allocate();
+       }
+       void setZero()
+       {
+               memset(m_data, 0x0, sizeof(idScalar) * m_rows * m_cols);
+       }
+       // avoid operators that would allocate -- use functions sub/add/mul in IDMath.hpp instead
+private:
+       void allocate() { m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * m_rows * m_cols)); }
+       void free() { idFree(m_data); }
+       enum
+       {
+               m_rows = 3
+       };
+       int m_cols;
+       idScalar* m_data;
+};
+
+inline void resize(mat3x& m, idArrayIdx size)
+{
+       m.resize(3, size);
+       m.setZero();
+}
+
+//////////////////////////////////////////////////
+// Implementations
+inline const vec3& vec3::operator=(const vec3& rhs)
+{
+       if (&rhs != this)
+       {
+               memcpy(m_data, rhs.m_data, 3 * sizeof(idScalar));
+       }
+       return *this;
+}
+
+inline vec3 vec3::cross(const vec3& b) const
+{
+       vec3 result;
+       result.m_data[0] = m_data[1] * b.m_data[2] - m_data[2] * b.m_data[1];
+       result.m_data[1] = m_data[2] * b.m_data[0] - m_data[0] * b.m_data[2];
+       result.m_data[2] = m_data[0] * b.m_data[1] - m_data[1] * b.m_data[0];
+
+       return result;
+}
+
+inline idScalar vec3::dot(const vec3& b) const
+{
+       return m_data[0] * b.m_data[0] + m_data[1] * b.m_data[1] + m_data[2] * b.m_data[2];
+}
+
+inline const mat33& mat33::operator=(const mat33& rhs)
+{
+       if (&rhs != this)
+       {
+               memcpy(m_data, rhs.m_data, 9 * sizeof(idScalar));
+       }
+       return *this;
+}
+inline mat33 mat33::transpose() const
+{
+       mat33 result;
+       result.m_data[0] = m_data[0];
+       result.m_data[1] = m_data[3];
+       result.m_data[2] = m_data[6];
+       result.m_data[3] = m_data[1];
+       result.m_data[4] = m_data[4];
+       result.m_data[5] = m_data[7];
+       result.m_data[6] = m_data[2];
+       result.m_data[7] = m_data[5];
+       result.m_data[8] = m_data[8];
+
+       return result;
+}
+
+inline mat33 operator*(const mat33& a, const mat33& b)
+{
+       mat33 result;
+       result.m_data[0] =
+               a.m_data[0] * b.m_data[0] + a.m_data[1] * b.m_data[3] + a.m_data[2] * b.m_data[6];
+       result.m_data[1] =
+               a.m_data[0] * b.m_data[1] + a.m_data[1] * b.m_data[4] + a.m_data[2] * b.m_data[7];
+       result.m_data[2] =
+               a.m_data[0] * b.m_data[2] + a.m_data[1] * b.m_data[5] + a.m_data[2] * b.m_data[8];
+       result.m_data[3] =
+               a.m_data[3] * b.m_data[0] + a.m_data[4] * b.m_data[3] + a.m_data[5] * b.m_data[6];
+       result.m_data[4] =
+               a.m_data[3] * b.m_data[1] + a.m_data[4] * b.m_data[4] + a.m_data[5] * b.m_data[7];
+       result.m_data[5] =
+               a.m_data[3] * b.m_data[2] + a.m_data[4] * b.m_data[5] + a.m_data[5] * b.m_data[8];
+       result.m_data[6] =
+               a.m_data[6] * b.m_data[0] + a.m_data[7] * b.m_data[3] + a.m_data[8] * b.m_data[6];
+       result.m_data[7] =
+               a.m_data[6] * b.m_data[1] + a.m_data[7] * b.m_data[4] + a.m_data[8] * b.m_data[7];
+       result.m_data[8] =
+               a.m_data[6] * b.m_data[2] + a.m_data[7] * b.m_data[5] + a.m_data[8] * b.m_data[8];
+
+       return result;
+}
+
+inline const mat33& mat33::operator+=(const mat33& b)
+{
+       for (int i = 0; i < 9; i++)
+       {
+               m_data[i] += b.m_data[i];
+       }
+
+       return *this;
+}
+
+inline const mat33& mat33::operator-=(const mat33& b)
+{
+       for (int i = 0; i < 9; i++)
+       {
+               m_data[i] -= b.m_data[i];
+       }
+       return *this;
+}
+
+inline vec3 operator*(const mat33& a, const vec3& b)
+{
+       vec3 result;
+
+       result.m_data[0] =
+               a.m_data[0] * b.m_data[0] + a.m_data[1] * b.m_data[1] + a.m_data[2] * b.m_data[2];
+       result.m_data[1] =
+               a.m_data[3] * b.m_data[0] + a.m_data[4] * b.m_data[1] + a.m_data[5] * b.m_data[2];
+       result.m_data[2] =
+               a.m_data[6] * b.m_data[0] + a.m_data[7] * b.m_data[1] + a.m_data[8] * b.m_data[2];
+
+       return result;
+}
+
+inline const vec3& vec3::operator+=(const vec3& b)
+{
+       for (int i = 0; i < 3; i++)
+       {
+               m_data[i] += b.m_data[i];
+       }
+       return *this;
+}
+
+inline const vec3& vec3::operator-=(const vec3& b)
+{
+       for (int i = 0; i < 3; i++)
+       {
+               m_data[i] -= b.m_data[i];
+       }
+       return *this;
+}
+
+inline mat33 operator*(const mat33& a, const idScalar& s)
+{
+       mat33 result;
+       for (int i = 0; i < 9; i++)
+       {
+               result.m_data[i] = a.m_data[i] * s;
+       }
+       return result;
+}
+
+inline mat33 operator*(const idScalar& s, const mat33& a) { return a * s; }
+
+inline vec3 operator*(const vec3& a, const idScalar& s)
+{
+       vec3 result;
+       for (int i = 0; i < 3; i++)
+       {
+               result.m_data[i] = a.m_data[i] * s;
+       }
+       return result;
+}
+inline vec3 operator*(const idScalar& s, const vec3& a) { return a * s; }
+
+inline mat33 operator+(const mat33& a, const mat33& b)
+{
+       mat33 result;
+       for (int i = 0; i < 9; i++)
+       {
+               result.m_data[i] = a.m_data[i] + b.m_data[i];
+       }
+       return result;
+}
+inline vec3 operator+(const vec3& a, const vec3& b)
+{
+       vec3 result;
+       for (int i = 0; i < 3; i++)
+       {
+               result.m_data[i] = a.m_data[i] + b.m_data[i];
+       }
+       return result;
+}
+
+inline mat33 operator-(const mat33& a, const mat33& b)
+{
+       mat33 result;
+       for (int i = 0; i < 9; i++)
+       {
+               result.m_data[i] = a.m_data[i] - b.m_data[i];
+       }
+       return result;
+}
+inline vec3 operator-(const vec3& a, const vec3& b)
+{
+       vec3 result;
+       for (int i = 0; i < 3; i++)
+       {
+               result.m_data[i] = a.m_data[i] - b.m_data[i];
+       }
+       return result;
+}
+
+inline mat33 operator/(const mat33& a, const idScalar& s)
+{
+       mat33 result;
+       for (int i = 0; i < 9; i++)
+       {
+               result.m_data[i] = a.m_data[i] / s;
+       }
+       return result;
+}
+
+inline vec3 operator/(const vec3& a, const idScalar& s)
+{
+       vec3 result;
+       for (int i = 0; i < 3; i++)
+       {
+               result.m_data[i] = a.m_data[i] / s;
+       }
+       return result;
+}
+
+inline const vecx& vecx::operator=(const vecx& rhs)
+{
+       if (size() != rhs.size())
+       {
+               bt_id_error_message("size missmatch, size()= %d but rhs.size()= %d\n", size(), rhs.size());
+               abort();
+       }
+       if (&rhs != this)
+       {
+               memcpy(m_data, rhs.m_data, rhs.size() * sizeof(idScalar));
+       }
+       return *this;
+}
+inline vecx operator*(const vecx& a, const idScalar& s)
+{
+       vecx result(a.size());
+       for (int i = 0; i < result.size(); i++)
+       {
+               result.m_data[i] = a.m_data[i] * s;
+       }
+       return result;
+}
+inline vecx operator*(const idScalar& s, const vecx& a) { return a * s; }
+inline vecx operator+(const vecx& a, const vecx& b)
+{
+       vecx result(a.size());
+       // TODO: error handling for a.size() != b.size()??
+       if (a.size() != b.size())
+       {
+               bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
+               abort();
+       }
+       for (int i = 0; i < a.size(); i++)
+       {
+               result.m_data[i] = a.m_data[i] + b.m_data[i];
+       }
+
+       return result;
+}
+inline vecx operator-(const vecx& a, const vecx& b)
+{
+       vecx result(a.size());
+       // TODO: error handling for a.size() != b.size()??
+       if (a.size() != b.size())
+       {
+               bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
+               abort();
+       }
+       for (int i = 0; i < a.size(); i++)
+       {
+               result.m_data[i] = a.m_data[i] - b.m_data[i];
+       }
+       return result;
+}
+inline vecx operator/(const vecx& a, const idScalar& s)
+{
+       vecx result(a.size());
+       for (int i = 0; i < result.size(); i++)
+       {
+               result.m_data[i] = a.m_data[i] / s;
+       }
+
+       return result;
+}
+
+inline vec3 operator*(const mat3x& a, const vecx& b)
+{
+       vec3 result;
+       if (a.cols() != b.size())
+       {
+               bt_id_error_message("size missmatch. a.cols()= %d, b.size()= %d\n", a.cols(), b.size());
+               abort();
+       }
+       result(0) = 0.0;
+       result(1) = 0.0;
+       result(2) = 0.0;
+       for (int i = 0; i < b.size(); i++)
+       {
+               for (int k = 0; k < 3; k++)
+               {
+                       result(k) += a(k, i) * b(i);
+               }
+       }
+       return result;
+}
+
+inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx* m)
+{
+       (*m)(row, col) = val;
+}
+
+inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x* m)
+{
+       (*m)(row, col) = val;
+}
+
+}  // namespace btInverseDynamics
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
new file mode 100644 (file)
index 0000000..ec9a562
--- /dev/null
@@ -0,0 +1,1286 @@
+#include "MultiBodyTreeImpl.hpp"
+
+namespace btInverseDynamics
+{
+MultiBodyTree::MultiBodyImpl::MultiBodyImpl(int num_bodies_, int num_dofs_)
+       : m_num_bodies(num_bodies_), m_num_dofs(num_dofs_)
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+         ,
+         m_m3x(3, m_num_dofs)
+#endif
+{
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+       resize(m_m3x, m_num_dofs);
+#endif
+       m_body_list.resize(num_bodies_);
+       m_parent_index.resize(num_bodies_);
+       m_child_indices.resize(num_bodies_);
+       m_user_int.resize(num_bodies_);
+       m_user_ptr.resize(num_bodies_);
+
+       m_world_gravity(0) = 0.0;
+       m_world_gravity(1) = 0.0;
+       m_world_gravity(2) = -9.8;
+}
+
+const char *MultiBodyTree::MultiBodyImpl::jointTypeToString(const JointType &type) const
+{
+       switch (type)
+       {
+               case FIXED:
+                       return "fixed";
+               case REVOLUTE:
+                       return "revolute";
+               case PRISMATIC:
+                       return "prismatic";
+               case FLOATING:
+                       return "floating";
+               case SPHERICAL:
+                       return "spherical";
+       }
+       return "error: invalid";
+}
+
+inline void indent(const int &level)
+{
+       for (int j = 0; j < level; j++)
+               id_printf("  ");  // indent
+}
+
+void MultiBodyTree::MultiBodyImpl::printTree()
+{
+       id_printf("body %.2d[%s]: root\n", 0, jointTypeToString(m_body_list[0].m_joint_type));
+       printTree(0, 0);
+}
+
+void MultiBodyTree::MultiBodyImpl::printTreeData()
+{
+       for (idArrayIdx i = 0; i < m_body_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[i];
+               id_printf("body: %d\n", static_cast<int>(i));
+               id_printf("type: %s\n", jointTypeToString(body.m_joint_type));
+               id_printf("q_index= %d\n", body.m_q_index);
+               id_printf("Jac_JR= [%f;%f;%f]\n", body.m_Jac_JR(0), body.m_Jac_JR(1), body.m_Jac_JR(2));
+               id_printf("Jac_JT= [%f;%f;%f]\n", body.m_Jac_JT(0), body.m_Jac_JT(1), body.m_Jac_JT(2));
+
+               id_printf("mass = %f\n", body.m_mass);
+               id_printf("mass * com = [%f %f %f]\n", body.m_body_mass_com(0), body.m_body_mass_com(1),
+                                 body.m_body_mass_com(2));
+               id_printf(
+                       "I_o= [%f %f %f;\n"
+                       "         %f %f %f;\n"
+                       "         %f %f %f]\n",
+                       body.m_body_I_body(0, 0), body.m_body_I_body(0, 1), body.m_body_I_body(0, 2),
+                       body.m_body_I_body(1, 0), body.m_body_I_body(1, 1), body.m_body_I_body(1, 2),
+                       body.m_body_I_body(2, 0), body.m_body_I_body(2, 1), body.m_body_I_body(2, 2));
+
+               id_printf("parent_pos_parent_body_ref= [%f %f %f]\n", body.m_parent_pos_parent_body_ref(0),
+                                 body.m_parent_pos_parent_body_ref(1), body.m_parent_pos_parent_body_ref(2));
+       }
+}
+int MultiBodyTree::MultiBodyImpl::bodyNumDoFs(const JointType &type) const
+{
+       switch (type)
+       {
+               case FIXED:
+                       return 0;
+               case REVOLUTE:
+               case PRISMATIC:
+                       return 1;
+               case FLOATING:
+                       return 6;
+               case SPHERICAL:
+                       return 3;
+       }
+       bt_id_error_message("unknown joint type %d\n", type);
+       return 0;
+}
+
+void MultiBodyTree::MultiBodyImpl::printTree(int index, int indentation)
+{
+       // this is adapted from URDF2Bullet.
+       // TODO: fix this and print proper graph (similar to git --log --graph)
+       int num_children = m_child_indices[index].size();
+
+       indentation += 2;
+       int count = 0;
+
+       for (int i = 0; i < num_children; i++)
+       {
+               int child_index = m_child_indices[index][i];
+               indent(indentation);
+               id_printf("body %.2d[%s]: %.2d is child no. %d (qi= %d .. %d) \n", index,
+                                 jointTypeToString(m_body_list[index].m_joint_type), child_index, (count++) + 1,
+                                 m_body_list[index].m_q_index,
+                                 m_body_list[index].m_q_index + bodyNumDoFs(m_body_list[index].m_joint_type));
+               // first grandchild
+               printTree(child_index, indentation);
+       }
+}
+
+int MultiBodyTree::MultiBodyImpl::setGravityInWorldFrame(const vec3 &gravity)
+{
+       m_world_gravity = gravity;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::generateIndexSets()
+{
+       m_body_revolute_list.resize(0);
+       m_body_prismatic_list.resize(0);
+       int q_index = 0;
+       for (idArrayIdx i = 0; i < m_body_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[i];
+               body.m_q_index = -1;
+               switch (body.m_joint_type)
+               {
+                       case REVOLUTE:
+                               m_body_revolute_list.push_back(i);
+                               body.m_q_index = q_index;
+                               q_index++;
+                               break;
+                       case PRISMATIC:
+                               m_body_prismatic_list.push_back(i);
+                               body.m_q_index = q_index;
+                               q_index++;
+                               break;
+                       case FIXED:
+                               // do nothing
+                               break;
+                       case FLOATING:
+                               m_body_floating_list.push_back(i);
+                               body.m_q_index = q_index;
+                               q_index += 6;
+                               break;
+                       case SPHERICAL:
+                               m_body_spherical_list.push_back(i);
+                               body.m_q_index = q_index;
+                               q_index += 3;
+                               break;
+                       default:
+                               bt_id_error_message("unsupported joint type %d\n", body.m_joint_type);
+                               return -1;
+               }
+       }
+       // sanity check
+       if (q_index != m_num_dofs)
+       {
+               bt_id_error_message("internal error, q_index= %d but num_dofs %d\n", q_index, m_num_dofs);
+               return -1;
+       }
+
+       m_child_indices.resize(m_body_list.size());
+
+       for (idArrayIdx child = 1; child < m_parent_index.size(); child++)
+       {
+               const int &parent = m_parent_index[child];
+               if (parent >= 0 && parent < (static_cast<int>(m_parent_index.size()) - 1))
+               {
+                       m_child_indices[parent].push_back(child);
+               }
+               else
+               {
+                       if (-1 == parent)
+                       {
+                               // multiple bodies are directly linked to the environment, ie, not a single root
+                               bt_id_error_message("building index sets parent(%zu)= -1 (multiple roots)\n", child);
+                       }
+                       else
+                       {
+                               // should never happen
+                               bt_id_error_message(
+                                       "building index sets. parent_index[%zu]= %d, but m_parent_index.size()= %d\n",
+                                       child, parent, static_cast<int>(m_parent_index.size()));
+                       }
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+void MultiBodyTree::MultiBodyImpl::calculateStaticData()
+{
+       // relative kinematics that are not a function of q, u, dot_u
+       for (idArrayIdx i = 0; i < m_body_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[i];
+               switch (body.m_joint_type)
+               {
+                       case REVOLUTE:
+                               body.m_parent_vel_rel(0) = 0;
+                               body.m_parent_vel_rel(1) = 0;
+                               body.m_parent_vel_rel(2) = 0;
+                               body.m_parent_acc_rel(0) = 0;
+                               body.m_parent_acc_rel(1) = 0;
+                               body.m_parent_acc_rel(2) = 0;
+                               body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
+                               break;
+                       case PRISMATIC:
+                               body.m_body_T_parent = body.m_body_T_parent_ref;
+                               body.m_parent_Jac_JT = body.m_body_T_parent_ref.transpose() * body.m_Jac_JT;
+                               body.m_body_ang_vel_rel(0) = 0;
+                               body.m_body_ang_vel_rel(1) = 0;
+                               body.m_body_ang_vel_rel(2) = 0;
+                               body.m_body_ang_acc_rel(0) = 0;
+                               body.m_body_ang_acc_rel(1) = 0;
+                               body.m_body_ang_acc_rel(2) = 0;
+                               break;
+                       case FIXED:
+                               body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
+                               body.m_body_T_parent = body.m_body_T_parent_ref;
+                               body.m_body_ang_vel_rel(0) = 0;
+                               body.m_body_ang_vel_rel(1) = 0;
+                               body.m_body_ang_vel_rel(2) = 0;
+                               body.m_parent_vel_rel(0) = 0;
+                               body.m_parent_vel_rel(1) = 0;
+                               body.m_parent_vel_rel(2) = 0;
+                               body.m_body_ang_acc_rel(0) = 0;
+                               body.m_body_ang_acc_rel(1) = 0;
+                               body.m_body_ang_acc_rel(2) = 0;
+                               body.m_parent_acc_rel(0) = 0;
+                               body.m_parent_acc_rel(1) = 0;
+                               body.m_parent_acc_rel(2) = 0;
+                               break;
+                       case FLOATING:
+                               // no static data
+                               break;
+                       case SPHERICAL:
+                               //todo: review
+                               body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
+                               body.m_parent_vel_rel(0) = 0;
+                               body.m_parent_vel_rel(1) = 0;
+                               body.m_parent_vel_rel(2) = 0;
+                               body.m_parent_acc_rel(0) = 0;
+                               body.m_parent_acc_rel(1) = 0;
+                               body.m_parent_acc_rel(2) = 0;
+                               break;
+               }
+
+                       // resize & initialize jacobians to zero.
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+               body.m_body_dot_Jac_T_u(0) = 0.0;
+               body.m_body_dot_Jac_T_u(1) = 0.0;
+               body.m_body_dot_Jac_T_u(2) = 0.0;
+               body.m_body_dot_Jac_R_u(0) = 0.0;
+               body.m_body_dot_Jac_R_u(1) = 0.0;
+               body.m_body_dot_Jac_R_u(2) = 0.0;
+               resize(body.m_body_Jac_T, m_num_dofs);
+               resize(body.m_body_Jac_R, m_num_dofs);
+               body.m_body_Jac_T.setZero();
+               body.m_body_Jac_R.setZero();
+#endif  //
+       }
+}
+
+int MultiBodyTree::MultiBodyImpl::calculateInverseDynamics(const vecx &q, const vecx &u,
+                                                                                                                  const vecx &dot_u, vecx *joint_forces)
+{
+       if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs ||
+               joint_forces->size() != m_num_dofs)
+       {
+               bt_id_error_message(
+                       "wrong vector dimension. system has %d DOFs,\n"
+                       "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d, dim(joint_forces)= %d\n",
+                       m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
+                       static_cast<int>(dot_u.size()), static_cast<int>(joint_forces->size()));
+               return -1;
+       }
+       // 1. relative kinematics
+       if (-1 == calculateKinematics(q, u, dot_u, POSITION_VELOCITY_ACCELERATION))
+       {
+               bt_id_error_message("error in calculateKinematics\n");
+               return -1;
+       }
+       // 2. update contributions to equations of motion for every body.
+       for (idArrayIdx i = 0; i < m_body_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[i];
+               // 3.4 update dynamic terms (rate of change of angular & linear momentum)
+               body.m_eom_lhs_rotational =
+                       body.m_body_I_body * body.m_body_ang_acc + body.m_body_mass_com.cross(body.m_body_acc) +
+                       body.m_body_ang_vel.cross(body.m_body_I_body * body.m_body_ang_vel) -
+                       body.m_body_moment_user;
+               body.m_eom_lhs_translational =
+                       body.m_body_ang_acc.cross(body.m_body_mass_com) + body.m_mass * body.m_body_acc +
+                       body.m_body_ang_vel.cross(body.m_body_ang_vel.cross(body.m_body_mass_com)) -
+                       body.m_body_force_user;
+       }
+
+       // 3. calculate full set of forces at parent joint
+       // (not directly calculating the joint force along the free direction
+       // simplifies inclusion of fixed joints.
+       // An alternative would be to fuse bodies in a pre-processing step,
+       // but that would make changing masses online harder (eg, payload masses
+       // added with fixed  joints to a gripper)
+       // Also, this enables adding zero weight bodies as a way to calculate frame poses
+       // for force elements, etc.
+
+       for (int body_idx = m_body_list.size() - 1; body_idx >= 0; body_idx--)
+       {
+               // sum of forces and moments acting on this body from its children
+               vec3 sum_f_children;
+               vec3 sum_m_children;
+               setZero(sum_f_children);
+               setZero(sum_m_children);
+               for (idArrayIdx child_list_idx = 0; child_list_idx < m_child_indices[body_idx].size();
+                        child_list_idx++)
+               {
+                       const RigidBody &child = m_body_list[m_child_indices[body_idx][child_list_idx]];
+                       vec3 child_joint_force_in_this_frame =
+                               child.m_body_T_parent.transpose() * child.m_force_at_joint;
+                       sum_f_children -= child_joint_force_in_this_frame;
+                       sum_m_children -= child.m_body_T_parent.transpose() * child.m_moment_at_joint +
+                                                         child.m_parent_pos_parent_body.cross(child_joint_force_in_this_frame);
+               }
+               RigidBody &body = m_body_list[body_idx];
+
+               body.m_force_at_joint = body.m_eom_lhs_translational - sum_f_children;
+               body.m_moment_at_joint = body.m_eom_lhs_rotational - sum_m_children;
+       }
+
+       // 4. Calculate Joint forces.
+       // These are the components of force_at_joint/moment_at_joint
+       // in the free directions given by Jac_JT/Jac_JR
+       // 4.1 revolute joints
+       for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[m_body_revolute_list[i]];
+               // (*joint_forces)(body.m_q_index) = body.m_Jac_JR.transpose() * body.m_moment_at_joint;
+               (*joint_forces)(body.m_q_index) = body.m_Jac_JR.dot(body.m_moment_at_joint);
+       }
+       // 4.2 for prismatic joints
+       for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[m_body_prismatic_list[i]];
+               // (*joint_forces)(body.m_q_index) = body.m_Jac_JT.transpose() * body.m_force_at_joint;
+               (*joint_forces)(body.m_q_index) = body.m_Jac_JT.dot(body.m_force_at_joint);
+       }
+       // 4.3 floating bodies (6-DoF joints)
+       for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[m_body_floating_list[i]];
+               (*joint_forces)(body.m_q_index + 0) = body.m_moment_at_joint(0);
+               (*joint_forces)(body.m_q_index + 1) = body.m_moment_at_joint(1);
+               (*joint_forces)(body.m_q_index + 2) = body.m_moment_at_joint(2);
+
+               (*joint_forces)(body.m_q_index + 3) = body.m_force_at_joint(0);
+               (*joint_forces)(body.m_q_index + 4) = body.m_force_at_joint(1);
+               (*joint_forces)(body.m_q_index + 5) = body.m_force_at_joint(2);
+       }
+
+       // 4.4 spherical bodies (3-DoF joints)
+       for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
+       {
+               //todo: review
+               RigidBody &body = m_body_list[m_body_spherical_list[i]];
+               (*joint_forces)(body.m_q_index + 0) = body.m_moment_at_joint(0);
+               (*joint_forces)(body.m_q_index + 1) = body.m_moment_at_joint(1);
+               (*joint_forces)(body.m_q_index + 2) = body.m_moment_at_joint(2);
+       }
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::calculateKinematics(const vecx &q, const vecx &u, const vecx &dot_u,
+                                                                                                         const KinUpdateType type)
+{
+       if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs)
+       {
+               bt_id_error_message(
+                       "wrong vector dimension. system has %d DOFs,\n"
+                       "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d\n",
+                       m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
+                       static_cast<int>(dot_u.size()));
+               return -1;
+       }
+       if (type != POSITION_ONLY && type != POSITION_VELOCITY && type != POSITION_VELOCITY_ACCELERATION)
+       {
+               bt_id_error_message("invalid type %d\n", type);
+               return -1;
+       }
+
+       // 1. update relative kinematics
+       // 1.1 for revolute
+       for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[m_body_revolute_list[i]];
+               mat33 T;
+               bodyTParentFromAxisAngle(body.m_Jac_JR, q(body.m_q_index), &T);
+               body.m_body_T_parent = T * body.m_body_T_parent_ref;
+               if (type >= POSITION_VELOCITY)
+               {
+                       body.m_body_ang_vel_rel = body.m_Jac_JR * u(body.m_q_index);
+               }
+               if (type >= POSITION_VELOCITY_ACCELERATION)
+               {
+                       body.m_body_ang_acc_rel = body.m_Jac_JR * dot_u(body.m_q_index);
+               }
+       }
+       // 1.2 for prismatic
+       for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[m_body_prismatic_list[i]];
+               body.m_parent_pos_parent_body =
+                       body.m_parent_pos_parent_body_ref + body.m_parent_Jac_JT * q(body.m_q_index);
+               if (type >= POSITION_VELOCITY)
+               {
+                       body.m_parent_vel_rel =
+                               body.m_body_T_parent_ref.transpose() * body.m_Jac_JT * u(body.m_q_index);
+               }
+               if (type >= POSITION_VELOCITY_ACCELERATION)
+               {
+                       body.m_parent_acc_rel = body.m_parent_Jac_JT * dot_u(body.m_q_index);
+               }
+       }
+       // 1.3 fixed joints: nothing to do
+       // 1.4 6dof joints:
+       for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[m_body_floating_list[i]];
+
+               body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
+                                                          transformY(q(body.m_q_index + 1)) *
+                                                          transformX(q(body.m_q_index));
+               body.m_parent_pos_parent_body(0) = q(body.m_q_index + 3);
+               body.m_parent_pos_parent_body(1) = q(body.m_q_index + 4);
+               body.m_parent_pos_parent_body(2) = q(body.m_q_index + 5);
+               body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
+
+               if (type >= POSITION_VELOCITY)
+               {
+                       body.m_body_ang_vel_rel(0) = u(body.m_q_index + 0);
+                       body.m_body_ang_vel_rel(1) = u(body.m_q_index + 1);
+                       body.m_body_ang_vel_rel(2) = u(body.m_q_index + 2);
+
+                       body.m_parent_vel_rel(0) = u(body.m_q_index + 3);
+                       body.m_parent_vel_rel(1) = u(body.m_q_index + 4);
+                       body.m_parent_vel_rel(2) = u(body.m_q_index + 5);
+
+                       body.m_parent_vel_rel = body.m_body_T_parent.transpose() * body.m_parent_vel_rel;
+               }
+               if (type >= POSITION_VELOCITY_ACCELERATION)
+               {
+                       body.m_body_ang_acc_rel(0) = dot_u(body.m_q_index + 0);
+                       body.m_body_ang_acc_rel(1) = dot_u(body.m_q_index + 1);
+                       body.m_body_ang_acc_rel(2) = dot_u(body.m_q_index + 2);
+
+                       body.m_parent_acc_rel(0) = dot_u(body.m_q_index + 3);
+                       body.m_parent_acc_rel(1) = dot_u(body.m_q_index + 4);
+                       body.m_parent_acc_rel(2) = dot_u(body.m_q_index + 5);
+
+                       body.m_parent_acc_rel = body.m_body_T_parent.transpose() * body.m_parent_acc_rel;
+               }
+       }
+       
+       for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
+       {
+               //todo: review
+               RigidBody &body = m_body_list[m_body_spherical_list[i]];
+
+               mat33 T;
+
+               T = transformX(q(body.m_q_index)) *
+                               transformY(q(body.m_q_index + 1)) *
+                               transformZ(q(body.m_q_index + 2));
+               body.m_body_T_parent = T * body.m_body_T_parent_ref;
+                       
+               body.m_parent_pos_parent_body(0)=0;
+               body.m_parent_pos_parent_body(1)=0;
+               body.m_parent_pos_parent_body(2)=0;
+               
+               body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
+
+               if (type >= POSITION_VELOCITY)
+               {
+                       body.m_body_ang_vel_rel(0) = u(body.m_q_index + 0);
+                       body.m_body_ang_vel_rel(1) = u(body.m_q_index + 1);
+                       body.m_body_ang_vel_rel(2) = u(body.m_q_index + 2);
+                       body.m_parent_vel_rel = body.m_body_T_parent.transpose() * body.m_parent_vel_rel;
+               }
+               if (type >= POSITION_VELOCITY_ACCELERATION)
+               {
+                       body.m_body_ang_acc_rel(0) = dot_u(body.m_q_index + 0);
+                       body.m_body_ang_acc_rel(1) = dot_u(body.m_q_index + 1);
+                       body.m_body_ang_acc_rel(2) = dot_u(body.m_q_index + 2);
+                       body.m_parent_acc_rel = body.m_body_T_parent.transpose() * body.m_parent_acc_rel;
+               }
+       }
+
+       // 2. absolute kinematic quantities (vector valued)
+       // NOTE: this should be optimized by specializing for different body types
+       // (e.g., relative rotation is always zero for prismatic joints, etc.)
+
+       // calculations for root body
+       {
+               RigidBody &body = m_body_list[0];
+               // 3.1 update absolute positions and orientations:
+               // will be required if we add force elements (eg springs between bodies,
+               // or contacts)
+               // not required right now, added here for debugging purposes
+               body.m_body_pos = body.m_body_T_parent * body.m_parent_pos_parent_body;
+               body.m_body_T_world = body.m_body_T_parent;
+
+               if (type >= POSITION_VELOCITY)
+               {
+                       // 3.2 update absolute velocities
+                       body.m_body_ang_vel = body.m_body_ang_vel_rel;
+                       body.m_body_vel = body.m_parent_vel_rel;
+               }
+               if (type >= POSITION_VELOCITY_ACCELERATION)
+               {
+                       // 3.3 update absolute accelerations
+                       // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
+                       body.m_body_ang_acc = body.m_body_ang_acc_rel;
+                       body.m_body_acc = body.m_body_T_parent * body.m_parent_acc_rel;
+                       // add gravitational acceleration to root body
+                       // this is an efficient way to add gravitational terms,
+                       // but it does mean that the kinematics are no longer
+                       // correct at the acceleration level
+                       // NOTE: To get correct acceleration kinematics, just set world_gravity to zero
+                       body.m_body_acc = body.m_body_acc - body.m_body_T_parent * m_world_gravity;
+               }
+       }
+
+       for (idArrayIdx i = 1; i < m_body_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[i];
+               RigidBody &parent = m_body_list[m_parent_index[i]];
+               // 2.1 update absolute positions and orientations:
+               // will be required if we add force elements (eg springs between bodies,
+               // or contacts)  not required right now added here for debugging purposes
+               body.m_body_pos =
+                       body.m_body_T_parent * (parent.m_body_pos + body.m_parent_pos_parent_body);
+               body.m_body_T_world = body.m_body_T_parent * parent.m_body_T_world;
+
+               if (type >= POSITION_VELOCITY)
+               {
+                       // 2.2 update absolute velocities
+                       body.m_body_ang_vel =
+                               body.m_body_T_parent * parent.m_body_ang_vel + body.m_body_ang_vel_rel;
+
+                       body.m_body_vel =
+                               body.m_body_T_parent *
+                               (parent.m_body_vel + parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body) +
+                                body.m_parent_vel_rel);
+               }
+               if (type >= POSITION_VELOCITY_ACCELERATION)
+               {
+                       // 2.3 update absolute accelerations
+                       // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
+                       body.m_body_ang_acc =
+                               body.m_body_T_parent * parent.m_body_ang_acc -
+                               body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel) +
+                               body.m_body_ang_acc_rel;
+                       body.m_body_acc =
+                               body.m_body_T_parent *
+                               (parent.m_body_acc + parent.m_body_ang_acc.cross(body.m_parent_pos_parent_body) +
+                                parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
+                                2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel) + body.m_parent_acc_rel);
+               }
+       }
+
+       return 0;
+}
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+
+void MultiBodyTree::MultiBodyImpl::addRelativeJacobianComponent(RigidBody &body)
+{
+       const int &idx = body.m_q_index;
+       switch (body.m_joint_type)
+       {
+               case FIXED:
+                       break;
+               case REVOLUTE:
+                       setMat3xElem(0, idx, body.m_Jac_JR(0), &body.m_body_Jac_R);
+                       setMat3xElem(1, idx, body.m_Jac_JR(1), &body.m_body_Jac_R);
+                       setMat3xElem(2, idx, body.m_Jac_JR(2), &body.m_body_Jac_R);
+                       break;
+               case PRISMATIC:
+                       setMat3xElem(0, idx, body.m_body_T_parent_ref(0, 0) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 0) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 0) * body.m_Jac_JT(2),
+                                                &body.m_body_Jac_T);
+                       setMat3xElem(1, idx, body.m_body_T_parent_ref(0, 1) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 1) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 1) * body.m_Jac_JT(2),
+                                                &body.m_body_Jac_T);
+                       setMat3xElem(2, idx, body.m_body_T_parent_ref(0, 2) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 2) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 2) * body.m_Jac_JT(2),
+                                                &body.m_body_Jac_T);
+                       break;
+               case FLOATING:
+                       setMat3xElem(0, idx + 0, 1.0, &body.m_body_Jac_R);
+                       setMat3xElem(1, idx + 1, 1.0, &body.m_body_Jac_R);
+                       setMat3xElem(2, idx + 2, 1.0, &body.m_body_Jac_R);
+                       // body_Jac_T = body_T_parent.transpose();
+                       setMat3xElem(0, idx + 3, body.m_body_T_parent(0, 0), &body.m_body_Jac_T);
+                       setMat3xElem(0, idx + 4, body.m_body_T_parent(1, 0), &body.m_body_Jac_T);
+                       setMat3xElem(0, idx + 5, body.m_body_T_parent(2, 0), &body.m_body_Jac_T);
+
+                       setMat3xElem(1, idx + 3, body.m_body_T_parent(0, 1), &body.m_body_Jac_T);
+                       setMat3xElem(1, idx + 4, body.m_body_T_parent(1, 1), &body.m_body_Jac_T);
+                       setMat3xElem(1, idx + 5, body.m_body_T_parent(2, 1), &body.m_body_Jac_T);
+
+                       setMat3xElem(2, idx + 3, body.m_body_T_parent(0, 2), &body.m_body_Jac_T);
+                       setMat3xElem(2, idx + 4, body.m_body_T_parent(1, 2), &body.m_body_Jac_T);
+                       setMat3xElem(2, idx + 5, body.m_body_T_parent(2, 2), &body.m_body_Jac_T);
+
+                       break;
+               case SPHERICAL:
+                       //todo: review
+                       setMat3xElem(0, idx + 0, 1.0, &body.m_body_Jac_R);
+                       setMat3xElem(1, idx + 1, 1.0, &body.m_body_Jac_R);
+                       setMat3xElem(2, idx + 2, 1.0, &body.m_body_Jac_R);
+                       break;
+       }
+}
+
+int MultiBodyTree::MultiBodyImpl::calculateJacobians(const vecx &q, const vecx &u, const KinUpdateType type)
+{
+       if (q.size() != m_num_dofs || u.size() != m_num_dofs)
+       {
+               bt_id_error_message(
+                       "wrong vector dimension. system has %d DOFs,\n"
+                       "but dim(q)= %d, dim(u)= %d\n",
+                       m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()));
+               return -1;
+       }
+       if (type != POSITION_ONLY && type != POSITION_VELOCITY)
+       {
+               bt_id_error_message("invalid type %d\n", type);
+               return -1;
+       }
+
+       addRelativeJacobianComponent(m_body_list[0]);
+       for (idArrayIdx i = 1; i < m_body_list.size(); i++)
+       {
+               RigidBody &body = m_body_list[i];
+               RigidBody &parent = m_body_list[m_parent_index[i]];
+
+               mul(body.m_body_T_parent, parent.m_body_Jac_R, &body.m_body_Jac_R);
+               body.m_body_Jac_T = parent.m_body_Jac_T;
+               mul(tildeOperator(body.m_parent_pos_parent_body), parent.m_body_Jac_R, &m_m3x);
+               sub(body.m_body_Jac_T, m_m3x, &body.m_body_Jac_T);
+
+               addRelativeJacobianComponent(body);
+               mul(body.m_body_T_parent, body.m_body_Jac_T, &body.m_body_Jac_T);
+
+               if (type >= POSITION_VELOCITY)
+               {
+                       body.m_body_dot_Jac_R_u = body.m_body_T_parent * parent.m_body_dot_Jac_R_u -
+                                                                         body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel);
+                       body.m_body_dot_Jac_T_u = body.m_body_T_parent *
+                                                                         (parent.m_body_dot_Jac_T_u + parent.m_body_dot_Jac_R_u.cross(body.m_parent_pos_parent_body) +
+                                                                          parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
+                                                                          2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel));
+               }
+       }
+       return 0;
+}
+#endif
+
+static inline void setThreeDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT)
+{
+       switch (dof)
+       {
+               // rotational part
+               case 0:
+                       Jac_JR(0) = 1;
+                       Jac_JR(1) = 0;
+                       Jac_JR(2) = 0;
+                       setZero(Jac_JT);
+                       break;
+               case 1:
+                       Jac_JR(0) = 0;
+                       Jac_JR(1) = 1;
+                       Jac_JR(2) = 0;
+                       setZero(Jac_JT);
+                       break;
+               case 2:
+                       Jac_JR(0) = 0;
+                       Jac_JR(1) = 0;
+                       Jac_JR(2) = 1;
+                       setZero(Jac_JT);
+                       break;
+       }
+}
+
+static inline void setSixDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT)
+{
+       switch (dof)
+       {
+               // rotational part
+               case 0:
+                       Jac_JR(0) = 1;
+                       Jac_JR(1) = 0;
+                       Jac_JR(2) = 0;
+                       setZero(Jac_JT);
+                       break;
+               case 1:
+                       Jac_JR(0) = 0;
+                       Jac_JR(1) = 1;
+                       Jac_JR(2) = 0;
+                       setZero(Jac_JT);
+                       break;
+               case 2:
+                       Jac_JR(0) = 0;
+                       Jac_JR(1) = 0;
+                       Jac_JR(2) = 1;
+                       setZero(Jac_JT);
+                       break;
+               // translational part
+               case 3:
+                       setZero(Jac_JR);
+                       Jac_JT(0) = 1;
+                       Jac_JT(1) = 0;
+                       Jac_JT(2) = 0;
+                       break;
+               case 4:
+                       setZero(Jac_JR);
+                       Jac_JT(0) = 0;
+                       Jac_JT(1) = 1;
+                       Jac_JT(2) = 0;
+                       break;
+               case 5:
+                       setZero(Jac_JR);
+                       Jac_JT(0) = 0;
+                       Jac_JT(1) = 0;
+                       Jac_JT(2) = 1;
+                       break;
+       }
+}
+
+static inline int jointNumDoFs(const JointType &type)
+{
+       switch (type)
+       {
+               case FIXED:
+                       return 0;
+               case REVOLUTE:
+               case PRISMATIC:
+                       return 1;
+               case FLOATING:
+                       return 6;
+               case SPHERICAL:
+                       return 3;
+       }
+       // this should never happen
+       bt_id_error_message("invalid joint type\n");
+       // TODO add configurable abort/crash function
+       abort();
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool update_kinematics,
+                                                                                                         const bool initialize_matrix,
+                                                                                                         const bool set_lower_triangular_matrix,
+                                                                                                         matxx *mass_matrix)
+{
+       // This calculates the joint space mass matrix for the multibody system.
+       // The algorithm is essentially an implementation of "method 3"
+       // in "Efficient Dynamic Simulation of Robotic Mechanisms" (Walker and Orin, 1982)
+       // (Later named "Composite Rigid Body Algorithm" by Featherstone).
+       //
+       // This implementation, however, handles branched systems and uses a formulation centered
+       // on the origin of the body-fixed frame to avoid re-computing various quantities at the com.
+
+       if (q.size() != m_num_dofs || mass_matrix->rows() != m_num_dofs ||
+               mass_matrix->cols() != m_num_dofs)
+       {
+               bt_id_error_message(
+                       "Dimension error. System has %d DOFs,\n"
+                       "but dim(q)= %d, dim(mass_matrix)= %d x %d\n",
+                       m_num_dofs, static_cast<int>(q.size()), static_cast<int>(mass_matrix->rows()),
+                       static_cast<int>(mass_matrix->cols()));
+               return -1;
+       }
+
+       // TODO add optimized zeroing function?
+       if (initialize_matrix)
+       {
+               for (int i = 0; i < m_num_dofs; i++)
+               {
+                       for (int j = 0; j < m_num_dofs; j++)
+                       {
+                               setMatxxElem(i, j, 0.0, mass_matrix);
+                       }
+               }
+       }
+
+       if (update_kinematics)
+       {
+               // 1. update relative kinematics
+               // 1.1 for revolute joints
+               for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
+               {
+                       RigidBody &body = m_body_list[m_body_revolute_list[i]];
+                       // from reference orientation (q=0) of body-fixed frame to current orientation
+                       mat33 body_T_body_ref;
+                       bodyTParentFromAxisAngle(body.m_Jac_JR, q(body.m_q_index), &body_T_body_ref);
+                       body.m_body_T_parent = body_T_body_ref * body.m_body_T_parent_ref;
+               }
+               // 1.2 for prismatic joints
+               for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
+               {
+                       RigidBody &body = m_body_list[m_body_prismatic_list[i]];
+                       // body.m_body_T_parent= fixed
+                       body.m_parent_pos_parent_body =
+                               body.m_parent_pos_parent_body_ref + body.m_parent_Jac_JT * q(body.m_q_index);
+               }
+               // 1.3 fixed joints: nothing to do
+               // 1.4 6dof joints:
+               for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
+               {
+                       RigidBody &body = m_body_list[m_body_floating_list[i]];
+
+                       body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
+                                                                  transformY(q(body.m_q_index + 1)) *
+                                                                  transformX(q(body.m_q_index));
+                       body.m_parent_pos_parent_body(0) = q(body.m_q_index + 3);
+                       body.m_parent_pos_parent_body(1) = q(body.m_q_index + 4);
+                       body.m_parent_pos_parent_body(2) = q(body.m_q_index + 5);
+
+                       body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
+               }
+
+               for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
+               {
+                       //todo: review
+                       RigidBody &body = m_body_list[m_body_spherical_list[i]];
+
+                       mat33 T;
+
+                       T = transformX(q(body.m_q_index)) *
+                               transformY(q(body.m_q_index + 1)) *
+                               transformZ(q(body.m_q_index + 2));
+                       body.m_body_T_parent = T * body.m_body_T_parent_ref;
+
+                       body.m_parent_pos_parent_body(0)=0;
+                       body.m_parent_pos_parent_body(1)=0;
+                       body.m_parent_pos_parent_body(2)=0;
+                       
+                       body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
+               }
+       }
+       for (int i = m_body_list.size() - 1; i >= 0; i--)
+       {
+               RigidBody &body = m_body_list[i];
+               // calculate mass, center of mass and inertia of "composite rigid body",
+               // ie, sub-tree starting at current body
+               body.m_subtree_mass = body.m_mass;
+               body.m_body_subtree_mass_com = body.m_body_mass_com;
+               body.m_body_subtree_I_body = body.m_body_I_body;
+
+               for (idArrayIdx c = 0; c < m_child_indices[i].size(); c++)
+               {
+                       RigidBody &child = m_body_list[m_child_indices[i][c]];
+                       mat33 body_T_child = child.m_body_T_parent.transpose();
+
+                       body.m_subtree_mass += child.m_subtree_mass;
+                       body.m_body_subtree_mass_com += body_T_child * child.m_body_subtree_mass_com +
+                                                                                       child.m_parent_pos_parent_body * child.m_subtree_mass;
+                       body.m_body_subtree_I_body +=
+                               body_T_child * child.m_body_subtree_I_body * child.m_body_T_parent;
+
+                       if (child.m_subtree_mass > 0)
+                       {
+                               // Shift the reference point for the child subtree inertia using the
+                               // Huygens-Steiner ("parallel axis") theorem.
+                               // (First shift from child origin to child com, then from there to this body's
+                               // origin)
+                               vec3 r_com = body_T_child * child.m_body_subtree_mass_com / child.m_subtree_mass;
+                               mat33 tilde_r_child_com = tildeOperator(r_com);
+                               mat33 tilde_r_body_com = tildeOperator(child.m_parent_pos_parent_body + r_com);
+                               body.m_body_subtree_I_body +=
+                                       child.m_subtree_mass *
+                                       (tilde_r_child_com * tilde_r_child_com - tilde_r_body_com * tilde_r_body_com);
+                       }
+               }
+       }
+
+       for (int i = m_body_list.size() - 1; i >= 0; i--)
+       {
+               const RigidBody &body = m_body_list[i];
+
+               // determine DoF-range for body
+               const int q_index_min = body.m_q_index;
+               const int q_index_max = q_index_min + jointNumDoFs(body.m_joint_type) - 1;
+               // loop over the DoFs used by this body
+               // local joint jacobians (ok as is for 1-DoF joints)
+               vec3 Jac_JR = body.m_Jac_JR;
+               vec3 Jac_JT = body.m_Jac_JT;
+               for (int col = q_index_max; col >= q_index_min; col--)
+               {
+                       // set jacobians for 6-DoF joints
+                       if (FLOATING == body.m_joint_type)
+                       {
+                               setSixDoFJacobians(col - q_index_min, Jac_JR, Jac_JT);
+                       }
+                       if (SPHERICAL == body.m_joint_type)
+                       {
+                               //todo: review
+                               setThreeDoFJacobians(col - q_index_min, Jac_JR, Jac_JT);
+                       }
+
+                       vec3 body_eom_rot =
+                               body.m_body_subtree_I_body * Jac_JR + body.m_body_subtree_mass_com.cross(Jac_JT);
+                       vec3 body_eom_trans =
+                               body.m_subtree_mass * Jac_JT - body.m_body_subtree_mass_com.cross(Jac_JR);
+                       setMatxxElem(col, col, Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans), mass_matrix);
+
+                       // rest of the mass matrix column upwards
+                       {
+                               // 1. for multi-dof joints, rest of the dofs of this body
+                               for (int row = col - 1; row >= q_index_min; row--)
+                               {
+                                       if (SPHERICAL == body.m_joint_type)
+                                       {
+                                               //todo: review
+                                               setThreeDoFJacobians(row - q_index_min, Jac_JR, Jac_JT);
+                                               const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
+                                               setMatxxElem(col, row, Mrc, mass_matrix);
+                                       }
+                                       if (FLOATING == body.m_joint_type)
+                                       {
+                                               setSixDoFJacobians(row - q_index_min, Jac_JR, Jac_JT);
+                                               const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
+                                               setMatxxElem(col, row, Mrc, mass_matrix);
+                                       }
+                               }
+                               // 2. ancestor dofs
+                               int child_idx = i;
+                               int parent_idx = m_parent_index[i];
+                               while (parent_idx >= 0)
+                               {
+                                       const RigidBody &child_body = m_body_list[child_idx];
+                                       const RigidBody &parent_body = m_body_list[parent_idx];
+
+                                       const mat33 parent_T_child = child_body.m_body_T_parent.transpose();
+                                       body_eom_rot = parent_T_child * body_eom_rot;
+                                       body_eom_trans = parent_T_child * body_eom_trans;
+                                       body_eom_rot += child_body.m_parent_pos_parent_body.cross(body_eom_trans);
+
+                                       const int parent_body_q_index_min = parent_body.m_q_index;
+                                       const int parent_body_q_index_max =
+                                               parent_body_q_index_min + jointNumDoFs(parent_body.m_joint_type) - 1;
+                                       vec3 Jac_JR = parent_body.m_Jac_JR;
+                                       vec3 Jac_JT = parent_body.m_Jac_JT;
+                                       for (int row = parent_body_q_index_max; row >= parent_body_q_index_min; row--)
+                                       {
+                                               if (SPHERICAL == parent_body.m_joint_type)
+                                               {
+                                                       //todo: review
+                                                       setThreeDoFJacobians(row - parent_body_q_index_min, Jac_JR, Jac_JT);
+                                               }
+                                               // set jacobians for 6-DoF joints
+                                               if (FLOATING == parent_body.m_joint_type)
+                                               {
+                                                       setSixDoFJacobians(row - parent_body_q_index_min, Jac_JR, Jac_JT);
+                                               }
+                                               const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
+                                               setMatxxElem(col, row, Mrc, mass_matrix);
+                                       }
+
+                                       child_idx = parent_idx;
+                                       parent_idx = m_parent_index[child_idx];
+                               }
+                       }
+               }
+       }
+
+       if (set_lower_triangular_matrix)
+       {
+               for (int col = 0; col < m_num_dofs; col++)
+               {
+                       for (int row = 0; row < col; row++)
+                       {
+                               setMatxxElem(row, col, (*mass_matrix)(col, row), mass_matrix);
+                       }
+               }
+       }
+       return 0;
+}
+
+// utility macro
+#define CHECK_IF_BODY_INDEX_IS_VALID(index)                                                  \
+       do                                                                                       \
+       {                                                                                        \
+               if (index < 0 || index >= m_num_bodies)                                              \
+               {                                                                                    \
+                       bt_id_error_message("invalid index %d (num_bodies= %d)\n", index, m_num_bodies); \
+                       return -1;                                                                       \
+               }                                                                                    \
+       } while (0)
+
+int MultiBodyTree::MultiBodyImpl::getParentIndex(const int body_index, int *p)
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *p = m_parent_index[body_index];
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getUserInt(const int body_index, int *user_int) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *user_int = m_user_int[body_index];
+       return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getUserPtr(const int body_index, void **user_ptr) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *user_ptr = m_user_ptr[body_index];
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::setUserInt(const int body_index, const int user_int)
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       m_user_int[body_index] = user_int;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::setUserPtr(const int body_index, void *const user_ptr)
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       m_user_ptr[body_index] = user_ptr;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyOrigin(int body_index, vec3 *world_origin) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       *world_origin = body.m_body_T_world.transpose() * body.m_body_pos;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyCoM(int body_index, vec3 *world_com) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       if (body.m_mass > 0)
+       {
+               *world_com = body.m_body_T_world.transpose() *
+                                        (body.m_body_pos + body.m_body_mass_com / body.m_mass);
+       }
+       else
+       {
+               *world_com = body.m_body_T_world.transpose() * (body.m_body_pos);
+       }
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyTransform(int body_index, mat33 *world_T_body) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       *world_T_body = body.m_body_T_world.transpose();
+       return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodyAngularVelocity(int body_index, vec3 *world_omega) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       *world_omega = body.m_body_T_world.transpose() * body.m_body_ang_vel;
+       return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocity(int body_index,
+                                                                                                               vec3 *world_velocity) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       *world_velocity = body.m_body_T_world.transpose() * body.m_body_vel;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocityCoM(int body_index,
+                                                                                                                  vec3 *world_velocity) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       vec3 com;
+       if (body.m_mass > 0)
+       {
+               com = body.m_body_mass_com / body.m_mass;
+       }
+       else
+       {
+               com(0) = 0;
+               com(1) = 0;
+               com(2) = 0;
+       }
+
+       *world_velocity =
+               body.m_body_T_world.transpose() * (body.m_body_vel + body.m_body_ang_vel.cross(com));
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyAngularAcceleration(int body_index,
+                                                                                                                        vec3 *world_dot_omega) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       *world_dot_omega = body.m_body_T_world.transpose() * body.m_body_ang_acc;
+       return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodyLinearAcceleration(int body_index,
+                                                                                                                       vec3 *world_acceleration) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       *world_acceleration = body.m_body_T_world.transpose() * body.m_body_acc;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getJointType(const int body_index, JointType *joint_type) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *joint_type = m_body_list[body_index].m_joint_type;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getJointTypeStr(const int body_index,
+                                                                                                 const char **joint_type) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *joint_type = jointTypeToString(m_body_list[body_index].m_joint_type);
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getParentRParentBodyRef(const int body_index, vec3 *r) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *r = m_body_list[body_index].m_parent_pos_parent_body_ref;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyTParentRef(const int body_index, mat33 *T) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *T = m_body_list[body_index].m_body_T_parent_ref;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyAxisOfMotion(const int body_index, vec3 *axis) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       if (m_body_list[body_index].m_joint_type == REVOLUTE)
+       {
+               *axis = m_body_list[body_index].m_Jac_JR;
+               return 0;
+       }
+       if (m_body_list[body_index].m_joint_type == PRISMATIC)
+       {
+               *axis = m_body_list[body_index].m_Jac_JT;
+               return 0;
+       }
+       setZero(*axis);
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getDoFOffset(const int body_index, int *q_index) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *q_index = m_body_list[body_index].m_q_index;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::setBodyMass(const int body_index, const idScalar mass)
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       m_body_list[body_index].m_mass = mass;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::setBodyFirstMassMoment(const int body_index,
+                                                                                                                const vec3 &first_mass_moment)
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       m_body_list[body_index].m_body_mass_com = first_mass_moment;
+       return 0;
+}
+int MultiBodyTree::MultiBodyImpl::setBodySecondMassMoment(const int body_index,
+                                                                                                                 const mat33 &second_mass_moment)
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       m_body_list[body_index].m_body_I_body = second_mass_moment;
+       return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodyMass(const int body_index, idScalar *mass) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *mass = m_body_list[body_index].m_mass;
+       return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodyFirstMassMoment(const int body_index,
+                                                                                                                vec3 *first_mass_moment) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *first_mass_moment = m_body_list[body_index].m_body_mass_com;
+       return 0;
+}
+int MultiBodyTree::MultiBodyImpl::getBodySecondMassMoment(const int body_index,
+                                                                                                                 mat33 *second_mass_moment) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       *second_mass_moment = m_body_list[body_index].m_body_I_body;
+       return 0;
+}
+
+void MultiBodyTree::MultiBodyImpl::clearAllUserForcesAndMoments()
+{
+       for (int index = 0; index < m_num_bodies; index++)
+       {
+               RigidBody &body = m_body_list[index];
+               setZero(body.m_body_force_user);
+               setZero(body.m_body_moment_user);
+       }
+}
+
+int MultiBodyTree::MultiBodyImpl::addUserForce(const int body_index, const vec3 &body_force)
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       m_body_list[body_index].m_body_force_user += body_force;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::addUserMoment(const int body_index, const vec3 &body_moment)
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       m_body_list[body_index].m_body_moment_user += body_moment;
+       return 0;
+}
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianTransU(const int body_index, vec3 *world_dot_jac_trans_u) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       *world_dot_jac_trans_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_T_u;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianRotU(const int body_index, vec3 *world_dot_jac_rot_u) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       *world_dot_jac_rot_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_R_u;
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyJacobianTrans(const int body_index, mat3x *world_jac_trans) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       mul(body.m_body_T_world.transpose(), body.m_body_Jac_T, world_jac_trans);
+       return 0;
+}
+
+int MultiBodyTree::MultiBodyImpl::getBodyJacobianRot(const int body_index, mat3x *world_jac_rot) const
+{
+       CHECK_IF_BODY_INDEX_IS_VALID(body_index);
+       const RigidBody &body = m_body_list[body_index];
+       mul(body.m_body_T_world.transpose(), body.m_body_Jac_R, world_jac_rot);
+       return 0;
+}
+
+#endif
+}  // namespace btInverseDynamics
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp
new file mode 100644 (file)
index 0000000..eabdbe1
--- /dev/null
@@ -0,0 +1,288 @@
+// The structs and classes defined here provide a basic inverse fynamics implementation used
+// by MultiBodyTree
+// User interaction should be through MultiBodyTree
+
+#ifndef MULTI_BODY_REFERENCE_IMPL_HPP_
+#define MULTI_BODY_REFERENCE_IMPL_HPP_
+
+#include "../IDConfig.hpp"
+#include "../MultiBodyTree.hpp"
+
+namespace btInverseDynamics
+{
+/// Structure for for rigid body mass properties, connectivity and kinematic state
+/// all vectors and matrices are in body-fixed frame, if not indicated otherwise.
+/// The body-fixed frame is located in the joint connecting the body to its parent.
+struct RigidBody
+{
+       ID_DECLARE_ALIGNED_ALLOCATOR();
+       // 1 Inertial properties
+       /// Mass
+       idScalar m_mass;
+       /// Mass times center of gravity in body-fixed frame
+       vec3 m_body_mass_com;
+       /// Moment of inertia w.r.t. body-fixed frame
+       mat33 m_body_I_body;
+
+       // 2 dynamic properties
+       /// Left-hand side of the body equation of motion, translational part
+       vec3 m_eom_lhs_translational;
+       /// Left-hand side of the body equation of motion, rotational part
+       vec3 m_eom_lhs_rotational;
+       /// Force acting at the joint when the body is cut from its parent;
+       /// includes impressed joint force in J_JT direction,
+       /// as well as constraint force,
+       /// in body-fixed frame
+       vec3 m_force_at_joint;
+       /// Moment acting at the joint when the body is cut from its parent;
+       /// includes impressed joint moment in J_JR direction, and constraint moment
+       /// in body-fixed frame
+       vec3 m_moment_at_joint;
+       /// external (user provided) force acting at the body-fixed frame's origin, written in that
+       /// frame
+       vec3 m_body_force_user;
+       /// external (user provided) moment acting at the body-fixed frame's origin, written in that
+       /// frame
+       vec3 m_body_moment_user;
+       // 3 absolute kinematic properties
+       /// Position of body-fixed frame relative to world frame
+       /// this is currently only for debugging purposes
+       vec3 m_body_pos;
+       /// Absolute velocity of body-fixed frame
+       vec3 m_body_vel;
+       /// Absolute acceleration of body-fixed frame
+       /// NOTE: if gravitational acceleration is not zero, this is the accelation PLUS gravitational
+       /// acceleration!
+       vec3 m_body_acc;
+       /// Absolute angular velocity
+       vec3 m_body_ang_vel;
+       /// Absolute angular acceleration
+       /// NOTE: if gravitational acceleration is not zero, this is the accelation PLUS gravitational
+       /// acceleration!
+       vec3 m_body_ang_acc;
+
+       // 4 relative kinematic properties.
+       // these are in the parent body frame
+       /// Transform from world to body-fixed frame;
+       /// this is currently only for debugging purposes
+       mat33 m_body_T_world;
+       /// Transform from parent to body-fixed frame
+       mat33 m_body_T_parent;
+       /// Vector from parent to child frame in parent frame
+       vec3 m_parent_pos_parent_body;
+       /// Relative angular velocity
+       vec3 m_body_ang_vel_rel;
+       /// Relative linear velocity
+       vec3 m_parent_vel_rel;
+       /// Relative angular acceleration
+       vec3 m_body_ang_acc_rel;
+       /// Relative linear acceleration
+       vec3 m_parent_acc_rel;
+
+       // 5 Data describing the joint type and geometry
+       /// Type of joint
+       JointType m_joint_type;
+       /// Position of joint frame (body-fixed frame at q=0) relative to the parent frame
+       /// Components are in body-fixed frame of the parent
+       vec3 m_parent_pos_parent_body_ref;
+       /// Orientation of joint frame (body-fixed frame at q=0) relative to the parent frame
+       mat33 m_body_T_parent_ref;
+       /// Joint rotational Jacobian, ie, the partial derivative of the body-fixed frames absolute
+       /// angular velocity w.r.t. the generalized velocity of this body's relative degree of freedom.
+       /// For revolute joints this is the joint axis, for prismatic joints it is a null matrix.
+       /// (NOTE: dimensions will have to be dynamic for additional joint types!)
+       vec3 m_Jac_JR;
+       /// Joint translational Jacobian, ie, the partial derivative of the body-fixed frames absolute
+       /// linear velocity w.r.t. the generalized velocity of this body's relative degree of freedom.
+       /// For prismatic joints this is the joint axis, for revolute joints it is a null matrix.
+       /// (NOTE: dimensions might have to be dynamic for additional joint types!)
+       vec3 m_Jac_JT;
+       /// m_Jac_JT in the parent frame, it, m_body_T_parent_ref.transpose()*m_Jac_JT
+       vec3 m_parent_Jac_JT;
+       /// Start of index range for the position degree(s) of freedom describing this body's motion
+       /// relative to
+       /// its parent. The indices are wrt the multibody system's q-vector of generalized coordinates.
+       int m_q_index;
+
+       // 6 Scratch data for mass matrix computation using "composite rigid body algorithm"
+       /// mass of the subtree rooted in this body
+       idScalar m_subtree_mass;
+       /// center of mass * mass for subtree rooted in this body, in body-fixed frame
+       vec3 m_body_subtree_mass_com;
+       /// moment of inertia of subtree rooted in this body, w.r.t. body origin, in body-fixed frame
+       mat33 m_body_subtree_I_body;
+
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+       /// translational jacobian in body-fixed frame d(m_body_vel)/du
+       mat3x m_body_Jac_T;
+       /// rotationsl jacobian in body-fixed frame d(m_body_ang_vel)/du
+       mat3x m_body_Jac_R;
+       /// components of linear acceleration depending on u
+       /// (same as is d(m_Jac_T)/dt*u)
+       vec3 m_body_dot_Jac_T_u;
+       /// components of angular acceleration depending on u
+       /// (same as is d(m_Jac_T)/dt*u)
+       vec3 m_body_dot_Jac_R_u;
+#endif
+};
+
+/// The MBS implements a tree structured multibody system
+class MultiBodyTree::MultiBodyImpl
+{
+       friend class MultiBodyTree;
+
+public:
+       ID_DECLARE_ALIGNED_ALLOCATOR();
+
+       enum KinUpdateType
+       {
+               POSITION_ONLY,
+               POSITION_VELOCITY,
+               POSITION_VELOCITY_ACCELERATION
+       };
+
+       /// constructor
+       /// @param num_bodies the number of bodies in the system
+       /// @param num_dofs number of degrees of freedom in the system
+       MultiBodyImpl(int num_bodies_, int num_dofs_);
+
+       /// \copydoc MultiBodyTree::calculateInverseDynamics
+       int calculateInverseDynamics(const vecx& q, const vecx& u, const vecx& dot_u,
+                                                                vecx* joint_forces);
+       ///\copydoc MultiBodyTree::calculateMassMatrix
+       int calculateMassMatrix(const vecx& q, const bool update_kinematics,
+                                                       const bool initialize_matrix, const bool set_lower_triangular_matrix,
+                                                       matxx* mass_matrix);
+       /// calculate kinematics (vector quantities)
+       /// Depending on type, update positions only, positions & velocities, or positions, velocities
+       /// and accelerations.
+       int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u, const KinUpdateType type);
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+       /// calculate jacobians and (if type == POSITION_VELOCITY), also velocity-dependent accelration terms.
+       int calculateJacobians(const vecx& q, const vecx& u, const KinUpdateType type);
+       /// \copydoc MultiBodyTree::getBodyDotJacobianTransU
+       int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const;
+       /// \copydoc MultiBodyTree::getBodyDotJacobianRotU
+       int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
+       /// \copydoc MultiBodyTree::getBodyJacobianTrans
+       int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const;
+       /// \copydoc MultiBodyTree::getBodyJacobianRot
+       int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
+       /// Add relative Jacobian component from motion relative to parent body
+       /// @param body the body to add the Jacobian component for
+       void addRelativeJacobianComponent(RigidBody& body);
+#endif
+       /// generate additional index sets from the parent_index array
+       /// @return -1 on error, 0 on success
+       int generateIndexSets();
+       /// set gravity acceleration in world frame
+       /// @param gravity gravity vector in the world frame
+       /// @return 0 on success, -1 on error
+       int setGravityInWorldFrame(const vec3& gravity);
+       /// pretty print tree
+       void printTree();
+       /// print tree data
+       void printTreeData();
+       /// initialize fixed data
+       void calculateStaticData();
+       /// \copydoc MultiBodyTree::getBodyFrame
+       int getBodyFrame(const int index, vec3* world_origin, mat33* body_T_world) const;
+       /// \copydoc MultiBodyTree::getParentIndex
+       int getParentIndex(const int body_index, int* m_parent_index);
+       /// \copydoc MultiBodyTree::getJointType
+       int getJointType(const int body_index, JointType* joint_type) const;
+       /// \copydoc MultiBodyTree::getJointTypeStr
+       int getJointTypeStr(const int body_index, const char** joint_type) const;
+       /// \copydoc MultiBodyTree::getParentRParentBodyRef
+       int getParentRParentBodyRef(const int body_index, vec3* r) const;
+       /// \copydoc MultiBodyTree::getBodyTParentRef
+       int getBodyTParentRef(const int body_index, mat33* T) const;
+       /// \copydoc MultiBodyTree::getBodyAxisOfMotion
+       int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
+       /// \copydoc MultiBodyTree:getDoFOffset
+       int getDoFOffset(const int body_index, int* q_index) const;
+       /// \copydoc MultiBodyTree::getBodyOrigin
+       int getBodyOrigin(const int body_index, vec3* world_origin) const;
+       /// \copydoc MultiBodyTree::getBodyCoM
+       int getBodyCoM(const int body_index, vec3* world_com) const;
+       /// \copydoc MultiBodyTree::getBodyTransform
+       int getBodyTransform(const int body_index, mat33* world_T_body) const;
+       /// \copydoc MultiBodyTree::getBodyAngularVelocity
+       int getBodyAngularVelocity(const int body_index, vec3* world_omega) const;
+       /// \copydoc MultiBodyTree::getBodyLinearVelocity
+       int getBodyLinearVelocity(const int body_index, vec3* world_velocity) const;
+       /// \copydoc MultiBodyTree::getBodyLinearVelocityCoM
+       int getBodyLinearVelocityCoM(const int body_index, vec3* world_velocity) const;
+       /// \copydoc MultiBodyTree::getBodyAngularAcceleration
+       int getBodyAngularAcceleration(const int body_index, vec3* world_dot_omega) const;
+       /// \copydoc MultiBodyTree::getBodyLinearAcceleration
+       int getBodyLinearAcceleration(const int body_index, vec3* world_acceleration) const;
+       /// \copydoc MultiBodyTree::getUserInt
+       int getUserInt(const int body_index, int* user_int) const;
+       /// \copydoc MultiBodyTree::getUserPtr
+       int getUserPtr(const int body_index, void** user_ptr) const;
+       /// \copydoc MultiBodyTree::setUserInt
+       int setUserInt(const int body_index, const int user_int);
+       /// \copydoc MultiBodyTree::setUserPtr
+       int setUserPtr(const int body_index, void* const user_ptr);
+       ///\copydoc MultiBodytTree::setBodyMass
+       int setBodyMass(const int body_index, const idScalar mass);
+       ///\copydoc MultiBodytTree::setBodyFirstMassMoment
+       int setBodyFirstMassMoment(const int body_index, const vec3& first_mass_moment);
+       ///\copydoc MultiBodytTree::setBodySecondMassMoment
+       int setBodySecondMassMoment(const int body_index, const mat33& second_mass_moment);
+       ///\copydoc MultiBodytTree::getBodyMass
+       int getBodyMass(const int body_index, idScalar* mass) const;
+       ///\copydoc MultiBodytTree::getBodyFirstMassMoment
+       int getBodyFirstMassMoment(const int body_index, vec3* first_mass_moment) const;
+       ///\copydoc MultiBodytTree::getBodySecondMassMoment
+       int getBodySecondMassMoment(const int body_index, mat33* second_mass_moment) const;
+       /// \copydoc MultiBodyTree::clearAllUserForcesAndMoments
+       void clearAllUserForcesAndMoments();
+       /// \copydoc MultiBodyTree::addUserForce
+       int addUserForce(const int body_index, const vec3& body_force);
+       /// \copydoc MultiBodyTree::addUserMoment
+       int addUserMoment(const int body_index, const vec3& body_moment);
+
+private:
+       // debug function. print tree structure to stdout
+       void printTree(int index, int indentation);
+       // get string representation of JointType (for debugging)
+       const char* jointTypeToString(const JointType& type) const;
+       // get number of degrees of freedom from joint type
+       int bodyNumDoFs(const JointType& type) const;
+       // number of bodies in the system
+       int m_num_bodies;
+       // number of degrees of freedom
+       int m_num_dofs;
+       // Gravitational acceleration (in world frame)
+       vec3 m_world_gravity;
+       // vector of bodies in the system
+       // body 0 is used as an environment body and is allways fixed.
+       // The bodies are ordered such that a parent body always has an index
+       // smaller than its child.
+       idArray<RigidBody>::type m_body_list;
+       // Parent_index[i] is the index for i's parent body in body_list.
+       // This fully describes the tree.
+       idArray<int>::type m_parent_index;
+       // child_indices[i] contains a vector of indices of
+       // all children of the i-th body
+       idArray<idArray<int>::type>::type m_child_indices;
+       // Indices of rotary joints
+       idArray<int>::type m_body_revolute_list;
+       // Indices of prismatic joints
+       idArray<int>::type m_body_prismatic_list;
+       // Indices of floating joints
+       idArray<int>::type m_body_floating_list;
+       // Indices of spherical joints
+       idArray<int>::type m_body_spherical_list;
+       // a user-provided integer
+       idArray<int>::type m_user_int;
+       // a user-provided pointer
+       idArray<void*>::type m_user_ptr;
+#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
+       mat3x m_m3x;
+#endif
+};
+}  // namespace btInverseDynamics
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp
new file mode 100644 (file)
index 0000000..a718db0
--- /dev/null
@@ -0,0 +1,131 @@
+#include "MultiBodyTreeInitCache.hpp"
+
+namespace btInverseDynamics
+{
+MultiBodyTree::InitCache::InitCache()
+{
+       m_inertias.resize(0);
+       m_joints.resize(0);
+       m_num_dofs = 0;
+       m_root_index = -1;
+}
+
+int MultiBodyTree::InitCache::addBody(const int body_index, const int parent_index,
+                                                                         const JointType joint_type,
+                                                                         const vec3& parent_r_parent_body_ref,
+                                                                         const mat33& body_T_parent_ref,
+                                                                         const vec3& body_axis_of_motion, const idScalar mass,
+                                                                         const vec3& body_r_body_com, const mat33& body_I_body,
+                                                                         const int user_int, void* user_ptr)
+{
+       switch (joint_type)
+       {
+               case REVOLUTE:
+               case PRISMATIC:
+                       m_num_dofs += 1;
+                       break;
+               case FIXED:
+                       // does not add a degree of freedom
+                       // m_num_dofs+=0;
+                       break;
+               case SPHERICAL:
+                       m_num_dofs += 3;
+                       break;
+               case FLOATING:
+                       m_num_dofs += 6;
+                       break;
+               default:
+                       bt_id_error_message("unknown joint type %d\n", joint_type);
+                       return -1;
+       }
+
+       if (-1 == parent_index)
+       {
+               if (m_root_index >= 0)
+               {
+                       bt_id_error_message("trying to add body %d as root, but already added %d as root body\n",
+                                                               body_index, m_root_index);
+                       return -1;
+               }
+               m_root_index = body_index;
+       }
+
+       JointData joint;
+       joint.m_child = body_index;
+       joint.m_parent = parent_index;
+       joint.m_type = joint_type;
+       joint.m_parent_pos_parent_child_ref = parent_r_parent_body_ref;
+       joint.m_child_T_parent_ref = body_T_parent_ref;
+       joint.m_child_axis_of_motion = body_axis_of_motion;
+
+       InertiaData body;
+       body.m_mass = mass;
+       body.m_body_pos_body_com = body_r_body_com;
+       body.m_body_I_body = body_I_body;
+
+       m_inertias.push_back(body);
+       m_joints.push_back(joint);
+       m_user_int.push_back(user_int);
+       m_user_ptr.push_back(user_ptr);
+       return 0;
+}
+int MultiBodyTree::InitCache::getInertiaData(const int index, InertiaData* inertia) const
+{
+       if (index < 0 || index > static_cast<int>(m_inertias.size()))
+       {
+               bt_id_error_message("index out of range\n");
+               return -1;
+       }
+
+       *inertia = m_inertias[index];
+       return 0;
+}
+
+int MultiBodyTree::InitCache::getUserInt(const int index, int* user_int) const
+{
+       if (index < 0 || index > static_cast<int>(m_user_int.size()))
+       {
+               bt_id_error_message("index out of range\n");
+               return -1;
+       }
+       *user_int = m_user_int[index];
+       return 0;
+}
+
+int MultiBodyTree::InitCache::getUserPtr(const int index, void** user_ptr) const
+{
+       if (index < 0 || index > static_cast<int>(m_user_ptr.size()))
+       {
+               bt_id_error_message("index out of range\n");
+               return -1;
+       }
+       *user_ptr = m_user_ptr[index];
+       return 0;
+}
+
+int MultiBodyTree::InitCache::getJointData(const int index, JointData* joint) const
+{
+       if (index < 0 || index > static_cast<int>(m_joints.size()))
+       {
+               bt_id_error_message("index out of range\n");
+               return -1;
+       }
+       *joint = m_joints[index];
+       return 0;
+}
+
+int MultiBodyTree::InitCache::buildIndexSets()
+{
+       // NOTE: This function assumes that proper indices were provided
+       //         User2InternalIndex from utils can be used to facilitate this.
+
+       m_parent_index.resize(numBodies());
+       for (idArrayIdx j = 0; j < m_joints.size(); j++)
+       {
+               const JointData& joint = m_joints[j];
+               m_parent_index[joint.m_child] = joint.m_parent;
+       }
+
+       return 0;
+}
+}  // namespace btInverseDynamics
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp
new file mode 100644 (file)
index 0000000..dbdb3ff
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef MULTIBODYTREEINITCACHE_HPP_
+#define MULTIBODYTREEINITCACHE_HPP_
+
+#include "../IDConfig.hpp"
+#include "../IDMath.hpp"
+#include "../MultiBodyTree.hpp"
+
+namespace btInverseDynamics
+{
+/// Mass properties of a rigid body
+struct InertiaData
+{
+       ID_DECLARE_ALIGNED_ALLOCATOR();
+
+       /// mass
+       idScalar m_mass;
+       /// vector from body-fixed frame to center of mass,
+       /// in body-fixed frame, multiplied by the mass
+       vec3 m_body_pos_body_com;
+       /// moment of inertia w.r.t. the origin of the body-fixed
+       /// frame, represented in that frame
+       mat33 m_body_I_body;
+};
+
+/// Joint properties
+struct JointData
+{
+       ID_DECLARE_ALIGNED_ALLOCATOR();
+
+       /// type of joint
+       JointType m_type;
+       /// index of parent body
+       int m_parent;
+       /// index of child body
+       int m_child;
+       /// vector from parent's body-fixed frame to child's body-fixed
+       /// frame for q=0, written in the parent's body fixed frame
+       vec3 m_parent_pos_parent_child_ref;
+       /// Transform matrix converting vectors written in the parent's frame
+       /// into vectors written in the child's frame for q=0
+       /// ie, child_vector = child_T_parent_ref * parent_vector;
+       mat33 m_child_T_parent_ref;
+       /// Axis of motion for 1 degree-of-freedom joints,
+       /// written in the child's frame
+       /// For revolute joints, the q-value is positive for a positive
+       /// rotation about this axis.
+       /// For prismatic joints, the q-value is positive for a positive
+       /// translation is this direction.
+       vec3 m_child_axis_of_motion;
+};
+
+/// Data structure to store data passed by the user.
+/// This is used in MultiBodyTree::finalize to build internal data structures.
+class MultiBodyTree::InitCache
+{
+public:
+       ID_DECLARE_ALIGNED_ALLOCATOR();
+       /// constructor
+       InitCache();
+       ///\copydoc MultiBodyTree::addBody
+       int addBody(const int body_index, const int parent_index, const JointType joint_type,
+                               const vec3 &parent_r_parent_body_ref, const mat33 &body_T_parent_ref,
+                               const vec3 &body_axis_of_motion, idScalar mass, const vec3 &body_r_body_com,
+                               const mat33 &body_I_body, const int user_int, void *user_ptr);
+       /// build index arrays
+       /// @return 0 on success, -1 on failure
+       int buildIndexSets();
+       /// @return number of degrees of freedom
+       int numDoFs() const { return m_num_dofs; }
+       /// @return number of bodies
+       int numBodies() const { return m_inertias.size(); }
+       /// get inertia data for index
+       /// @param index of the body
+       /// @param inertia pointer for return data
+       /// @return 0 on success, -1 on failure
+       int getInertiaData(const int index, InertiaData *inertia) const;
+       /// get joint data for index
+       /// @param index of the body
+       /// @param joint pointer for return data
+       /// @return 0 on success, -1 on failure
+       int getJointData(const int index, JointData *joint) const;
+       /// get parent index array (paren_index[i] is the index of the parent of i)
+       /// @param parent_index pointer for return data
+       void getParentIndexArray(idArray<int>::type *parent_index) { *parent_index = m_parent_index; }
+       /// get user integer
+       /// @param index body index
+       /// @param user_int user integer
+       /// @return 0 on success, -1 on failure
+       int getUserInt(const int index, int *user_int) const;
+       /// get user pointer
+       /// @param index body index
+       /// @param user_int user pointer
+       /// @return 0 on success, -1 on failure
+       int getUserPtr(const int index, void **user_ptr) const;
+
+private:
+       // vector of bodies
+       idArray<InertiaData>::type m_inertias;
+       // vector of joints
+       idArray<JointData>::type m_joints;
+       // number of mechanical degrees of freedom
+       int m_num_dofs;
+       // parent index array
+       idArray<int>::type m_parent_index;
+       // user integers
+       idArray<int>::type m_user_int;
+       // user pointers
+       idArray<void *>::type m_user_ptr;
+       // index of root body (or -1 if not set)
+       int m_root_index;
+};
+}  // namespace btInverseDynamics
+#endif  // MULTIBODYTREEINITCACHE_HPP_
diff --git a/dali-physics/third-party/bullet3/src/BulletInverseDynamics/premake4.lua b/dali-physics/third-party/bullet3/src/BulletInverseDynamics/premake4.lua
new file mode 100644 (file)
index 0000000..fdd176b
--- /dev/null
@@ -0,0 +1,15 @@
+       project "BulletInverseDynamics"
+
+       kind "StaticLib"
+    if os.is("Linux") then
+        buildoptions{"-fPIC"}
+    end
+       includedirs {
+               "..",
+       }
+       files {
+               "IDMath.cpp",
+               "MultiBodyTree.cpp",
+               "details/MultiBodyTreeInitCache.cpp",
+               "details/MultiBodyTreeImpl.cpp",
+       }
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBody.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBody.cpp
new file mode 100644 (file)
index 0000000..feb30d5
--- /dev/null
@@ -0,0 +1,792 @@
+#include "btReducedDeformableBody.h"
+#include "../btSoftBodyInternals.h"
+#include "btReducedDeformableBodyHelpers.h"
+#include "LinearMath/btTransformUtil.h"
+#include <iostream>
+#include <fstream>
+
+btReducedDeformableBody::btReducedDeformableBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
+ : btSoftBody(worldInfo, node_count, x, m), m_rigidOnly(false)
+{
+  // reduced deformable
+  m_reducedModel = true;
+  m_nReduced = 0;
+  m_nFull = 0;
+  m_nodeIndexOffset = 0;
+
+  m_transform_lock = false;
+  m_ksScale = 1.0;
+  m_rhoScale = 1.0;
+
+  // rigid motion
+  m_linearVelocity.setZero();
+       m_angularVelocity.setZero();
+  m_internalDeltaLinearVelocity.setZero();
+  m_internalDeltaAngularVelocity.setZero();
+  m_angularVelocityFromReduced.setZero();
+  m_internalDeltaAngularVelocityFromReduced.setZero();
+       m_angularFactor.setValue(1, 1, 1);
+       m_linearFactor.setValue(1, 1, 1);
+  // m_invInertiaLocal.setValue(1, 1, 1);
+  m_invInertiaLocal.setIdentity();
+  m_mass = 0.0;
+  m_inverseMass = 0.0;
+
+  m_linearDamping = 0;
+  m_angularDamping = 0;
+
+  // Rayleigh damping
+  m_dampingAlpha = 0;
+  m_dampingBeta = 0;
+
+  m_rigidTransformWorld.setIdentity();
+}
+
+void btReducedDeformableBody::setReducedModes(int num_modes, int full_size)
+{
+  m_nReduced = num_modes;
+  m_nFull = full_size;
+  m_reducedDofs.resize(m_nReduced, 0);
+  m_reducedDofsBuffer.resize(m_nReduced, 0);
+  m_reducedVelocity.resize(m_nReduced, 0);
+  m_reducedVelocityBuffer.resize(m_nReduced, 0);
+  m_reducedForceElastic.resize(m_nReduced, 0);
+  m_reducedForceDamping.resize(m_nReduced, 0);
+  m_reducedForceExternal.resize(m_nReduced, 0);
+  m_internalDeltaReducedVelocity.resize(m_nReduced, 0);
+  m_nodalMass.resize(full_size, 0);
+  m_localMomentArm.resize(m_nFull);
+}
+
+void btReducedDeformableBody::setMassProps(const tDenseArray& mass_array)
+{
+  btScalar total_mass = 0;
+  btVector3 CoM(0, 0, 0);
+       for (int i = 0; i < m_nFull; ++i)
+       {
+               m_nodalMass[i] = m_rhoScale * mass_array[i];
+               m_nodes[i].m_im = mass_array[i] > 0 ? 1.0 / (m_rhoScale * mass_array[i]) : 0;
+               total_mass += m_rhoScale * mass_array[i];
+
+    CoM += m_nodalMass[i] * m_nodes[i].m_x;
+       }
+  // total rigid body mass
+  m_mass = total_mass;
+  m_inverseMass = total_mass > 0 ? 1.0 / total_mass : 0;
+  // original CoM
+  m_initialCoM = CoM / total_mass;
+}
+
+void btReducedDeformableBody::setInertiaProps()
+{
+  // make sure the initial CoM is at the origin (0,0,0)
+  // for (int i = 0; i < m_nFull; ++i)
+  // {
+  //   m_nodes[i].m_x -= m_initialCoM;
+  // }
+  // m_initialCoM.setZero();
+  m_rigidTransformWorld.setOrigin(m_initialCoM);
+  m_interpolationWorldTransform = m_rigidTransformWorld;
+  
+  updateLocalInertiaTensorFromNodes();
+
+  // update world inertia tensor
+  btMatrix3x3 rotation;
+  rotation.setIdentity();
+  updateInitialInertiaTensor(rotation);
+  updateInertiaTensor();
+  m_interpolateInvInertiaTensorWorld = m_invInertiaTensorWorld;
+}
+
+void btReducedDeformableBody::setRigidVelocity(const btVector3& v)
+{
+  m_linearVelocity = v;
+}
+
+void btReducedDeformableBody::setRigidAngularVelocity(const btVector3& omega)
+{
+  m_angularVelocity = omega;
+}
+
+void btReducedDeformableBody::setStiffnessScale(const btScalar ks)
+{
+  m_ksScale = ks;
+}
+
+void btReducedDeformableBody::setMassScale(const btScalar rho)
+{
+  m_rhoScale = rho;
+}
+
+void btReducedDeformableBody::setFixedNodes(const int n_node)
+{
+  m_fixedNodes.push_back(n_node);
+  m_nodes[n_node].m_im = 0;   // set inverse mass to be zero for the constraint solver.
+}
+
+void btReducedDeformableBody::setDamping(const btScalar alpha, const btScalar beta)
+{
+  m_dampingAlpha = alpha;
+  m_dampingBeta = beta;
+}
+
+void btReducedDeformableBody::internalInitialization()
+{
+  // zeroing
+  endOfTimeStepZeroing();
+  // initialize rest position
+  updateRestNodalPositions();
+  // initialize local nodal moment arm form the CoM
+  updateLocalMomentArm();
+  // initialize projection matrix
+  updateExternalForceProjectMatrix(false);
+}
+
+void btReducedDeformableBody::updateLocalMomentArm()
+{
+  TVStack delta_x;
+  delta_x.resize(m_nFull);
+
+  for (int i = 0; i < m_nFull; ++i)
+  {
+    for (int k = 0; k < 3; ++k)
+    {
+      // compute displacement
+      delta_x[i][k] = 0;
+      for (int j = 0; j < m_nReduced; ++j) 
+      {
+        delta_x[i][k] += m_modes[j][3 * i + k] * m_reducedDofs[j];
+      }
+    }
+    // get new moment arm Sq + x0
+    m_localMomentArm[i] = m_x0[i] - m_initialCoM + delta_x[i];
+  }
+}
+
+void btReducedDeformableBody::updateExternalForceProjectMatrix(bool initialized)
+{
+  // if not initialized, need to compute both P_A and Cq
+  // otherwise, only need to udpate Cq
+  if (!initialized)
+  {
+    // resize
+    m_projPA.resize(m_nReduced);
+    m_projCq.resize(m_nReduced);
+
+    m_STP.resize(m_nReduced);
+    m_MrInvSTP.resize(m_nReduced);
+
+    // P_A
+    for (int r = 0; r < m_nReduced; ++r)
+    {
+      m_projPA[r].resize(3 * m_nFull, 0);
+      for (int i = 0; i < m_nFull; ++i)
+      {
+        btMatrix3x3 mass_scaled_i = Diagonal(1) - Diagonal(m_nodalMass[i] / m_mass);
+        btVector3 s_ri(m_modes[r][3 * i], m_modes[r][3 * i + 1], m_modes[r][3 * i + 2]);
+        btVector3 prod_i = mass_scaled_i * s_ri;
+
+        for (int k = 0; k < 3; ++k)
+          m_projPA[r][3 * i + k] = prod_i[k];
+
+        // btScalar ratio = m_nodalMass[i] / m_mass;
+        // m_projPA[r] += btVector3(- m_modes[r][3 * i] * ratio,
+        //                          - m_modes[r][3 * i + 1] * ratio,
+        //                          - m_modes[r][3 * i + 2] * ratio);
+      }
+    }
+  }
+
+  // C(q) is updated once per position update
+  for (int r = 0; r < m_nReduced; ++r)
+  {
+       m_projCq[r].resize(3 * m_nFull, 0);
+    for (int i = 0; i < m_nFull; ++i)
+    {
+      btMatrix3x3 r_star = Cross(m_localMomentArm[i]);
+      btVector3 s_ri(m_modes[r][3 * i], m_modes[r][3 * i + 1], m_modes[r][3 * i + 2]);
+      btVector3 prod_i = r_star * m_invInertiaTensorWorld * r_star * s_ri;
+
+      for (int k = 0; k < 3; ++k)
+        m_projCq[r][3 * i + k] = m_nodalMass[i] * prod_i[k];
+
+      // btVector3 si(m_modes[r][3 * i], m_modes[r][3 * i + 1], m_modes[r][3 * i + 2]);
+      // m_projCq[r] += m_nodalMass[i] * si.cross(m_localMomentArm[i]);
+    }
+  }
+}
+
+void btReducedDeformableBody::endOfTimeStepZeroing()
+{
+  for (int i = 0; i < m_nReduced; ++i)
+  {
+    m_reducedForceElastic[i] = 0;
+    m_reducedForceDamping[i] = 0;
+    m_reducedForceExternal[i] = 0;
+    m_internalDeltaReducedVelocity[i] = 0;
+    m_reducedDofsBuffer[i] = m_reducedDofs[i];
+    m_reducedVelocityBuffer[i] = m_reducedVelocity[i];
+  }
+  // std::cout << "zeroed!\n";
+}
+
+void btReducedDeformableBody::applyInternalVelocityChanges()
+{
+  m_linearVelocity += m_internalDeltaLinearVelocity;
+  m_angularVelocity += m_internalDeltaAngularVelocity;
+  m_internalDeltaLinearVelocity.setZero();
+  m_internalDeltaAngularVelocity.setZero();
+  for (int r = 0; r < m_nReduced; ++r)
+  {
+    m_reducedVelocity[r] += m_internalDeltaReducedVelocity[r];
+    m_internalDeltaReducedVelocity[r] = 0;
+  }
+}
+
+void btReducedDeformableBody::predictIntegratedTransform(btScalar dt, btTransform& predictedTransform)
+{
+       btTransformUtil::integrateTransform(m_rigidTransformWorld, m_linearVelocity, m_angularVelocity, dt, predictedTransform);
+}
+
+void btReducedDeformableBody::updateReducedDofs(btScalar solverdt)
+{
+  for (int r = 0; r < m_nReduced; ++r)
+  { 
+    m_reducedDofs[r] = m_reducedDofsBuffer[r] + solverdt * m_reducedVelocity[r];
+  }
+}
+
+void btReducedDeformableBody::mapToFullPosition(const btTransform& ref_trans)
+{
+  btVector3 origin = ref_trans.getOrigin();
+  btMatrix3x3 rotation = ref_trans.getBasis();
+  
+
+  for (int i = 0; i < m_nFull; ++i)
+  {
+    m_nodes[i].m_x = rotation * m_localMomentArm[i] + origin;
+    m_nodes[i].m_q = m_nodes[i].m_x;
+  }
+}
+
+void btReducedDeformableBody::updateReducedVelocity(btScalar solverdt)
+{
+  // update reduced velocity
+  for (int r = 0; r < m_nReduced; ++r)
+  {
+    // the reduced mass is always identity!
+    btScalar delta_v = 0;
+    delta_v = solverdt * (m_reducedForceElastic[r] + m_reducedForceDamping[r]);
+    // delta_v = solverdt * (m_reducedForceElastic[r] + m_reducedForceDamping[r] + m_reducedForceExternal[r]);
+    m_reducedVelocity[r] = m_reducedVelocityBuffer[r] + delta_v;
+  }
+}
+
+void btReducedDeformableBody::mapToFullVelocity(const btTransform& ref_trans)
+{
+  // compute the reduced contribution to the angular velocity
+  // btVector3 sum_linear(0, 0, 0);
+  // btVector3 sum_angular(0, 0, 0);
+  // m_linearVelocityFromReduced.setZero();
+  // m_angularVelocityFromReduced.setZero();
+  // for (int i = 0; i < m_nFull; ++i)
+  // {
+  //   btVector3 r_com = ref_trans.getBasis() * m_localMomentArm[i];
+  //   btMatrix3x3 r_star = Cross(r_com);
+
+  //   btVector3 v_from_reduced(0, 0, 0);
+  //   for (int k = 0; k < 3; ++k)
+  //   {
+  //     for (int r = 0; r < m_nReduced; ++r)
+  //     {
+  //       v_from_reduced[k] += m_modes[r][3 * i + k] * m_reducedVelocity[r];
+  //     }
+  //   }
+
+  //   btVector3 delta_linear = m_nodalMass[i] * v_from_reduced;
+  //   btVector3 delta_angular = m_nodalMass[i] * (r_star * ref_trans.getBasis() * v_from_reduced);
+  //   sum_linear += delta_linear;
+  //   sum_angular += delta_angular;
+  //   // std::cout << "delta_linear: " << delta_linear[0] << "\t" << delta_linear[1] << "\t" << delta_linear[2] << "\n";
+  //   // std::cout << "delta_angular: " << delta_angular[0] << "\t" << delta_angular[1] << "\t" << delta_angular[2] << "\n";
+  //   // std::cout << "sum_linear: " << sum_linear[0] << "\t" << sum_linear[1] << "\t" << sum_linear[2] << "\n";
+  //   // std::cout << "sum_angular: " << sum_angular[0] << "\t" << sum_angular[1] << "\t" << sum_angular[2] << "\n";
+  // }
+  // m_linearVelocityFromReduced = 1.0 / m_mass * (ref_trans.getBasis() * sum_linear);
+  // m_angularVelocityFromReduced = m_interpolateInvInertiaTensorWorld * sum_angular;
+
+  // m_linearVelocity -= m_linearVelocityFromReduced;
+  // m_angularVelocity -= m_angularVelocityFromReduced;
+
+  for (int i = 0; i < m_nFull; ++i)
+  {
+    m_nodes[i].m_v = computeNodeFullVelocity(ref_trans, i);
+  }
+}
+
+const btVector3 btReducedDeformableBody::computeTotalAngularMomentum() const
+{
+  btVector3 L_rigid = m_invInertiaTensorWorld.inverse() * m_angularVelocity;
+  btVector3 L_reduced(0, 0, 0);
+  btMatrix3x3 omega_prime_star = Cross(m_angularVelocityFromReduced);
+
+  for (int i = 0; i < m_nFull; ++i)
+  {
+    btVector3 r_com = m_rigidTransformWorld.getBasis() * m_localMomentArm[i];
+    btMatrix3x3 r_star = Cross(r_com);
+
+    btVector3 v_from_reduced(0, 0, 0);
+    for (int k = 0; k < 3; ++k)
+    {
+      for (int r = 0; r < m_nReduced; ++r)
+      {
+        v_from_reduced[k] += m_modes[r][3 * i + k] * m_reducedVelocity[r];
+      }
+    }
+
+    L_reduced += m_nodalMass[i] * (r_star * (m_rigidTransformWorld.getBasis() * v_from_reduced - omega_prime_star * r_com));
+    // L_reduced += m_nodalMass[i] * (r_star * (m_rigidTransformWorld.getBasis() * v_from_reduced));
+  }
+  return L_rigid + L_reduced;
+}
+
+const btVector3 btReducedDeformableBody::computeNodeFullVelocity(const btTransform& ref_trans, int n_node) const
+{
+  btVector3 v_from_reduced(0, 0, 0);
+  btVector3 r_com = ref_trans.getBasis() * m_localMomentArm[n_node];
+  // compute velocity contributed by the reduced velocity
+  for (int k = 0; k < 3; ++k)
+  {
+    for (int r = 0; r < m_nReduced; ++r)
+    {
+      v_from_reduced[k] += m_modes[r][3 * n_node + k] * m_reducedVelocity[r];
+    }
+  }
+  // get new velocity
+  btVector3 vel = m_angularVelocity.cross(r_com) + 
+                  ref_trans.getBasis() * v_from_reduced +
+                  m_linearVelocity;
+  return vel;
+}
+
+const btVector3 btReducedDeformableBody::internalComputeNodeDeltaVelocity(const btTransform& ref_trans, int n_node) const
+{
+  btVector3 deltaV_from_reduced(0, 0, 0);
+  btVector3 r_com = ref_trans.getBasis() * m_localMomentArm[n_node];
+
+  // compute velocity contributed by the reduced velocity
+  for (int k = 0; k < 3; ++k)
+  {
+    for (int r = 0; r < m_nReduced; ++r)
+    {
+      deltaV_from_reduced[k] += m_modes[r][3 * n_node + k] * m_internalDeltaReducedVelocity[r];
+    }
+  }
+
+  // get delta velocity
+  btVector3 deltaV = m_internalDeltaAngularVelocity.cross(r_com) + 
+                     ref_trans.getBasis() * deltaV_from_reduced +
+                     m_internalDeltaLinearVelocity;
+  return deltaV;
+}
+
+void btReducedDeformableBody::proceedToTransform(btScalar dt, bool end_of_time_step)
+{
+  btTransformUtil::integrateTransform(m_rigidTransformWorld, m_linearVelocity, m_angularVelocity, dt, m_interpolationWorldTransform);
+  updateInertiaTensor();
+  // m_interpolateInvInertiaTensorWorld = m_interpolationWorldTransform.getBasis().scaled(m_invInertiaLocal) * m_interpolationWorldTransform.getBasis().transpose();
+  m_rigidTransformWorld = m_interpolationWorldTransform;
+  m_invInertiaTensorWorld = m_interpolateInvInertiaTensorWorld;
+}
+
+void btReducedDeformableBody::transformTo(const btTransform& trs)
+{
+       btTransform current_transform = getRigidTransform();
+       btTransform new_transform(trs.getBasis() * current_transform.getBasis().transpose(),
+                            trs.getOrigin() - current_transform.getOrigin());
+  transform(new_transform);
+}
+
+void btReducedDeformableBody::transform(const btTransform& trs)
+{
+  m_transform_lock = true;
+
+  // transform mesh
+  {
+    const btScalar margin = getCollisionShape()->getMargin();
+    ATTRIBUTE_ALIGNED16(btDbvtVolume)
+    vol;
+
+    btVector3 CoM = m_rigidTransformWorld.getOrigin();
+    btVector3 translation = trs.getOrigin();
+    btMatrix3x3 rotation = trs.getBasis();
+
+    for (int i = 0; i < m_nodes.size(); ++i)
+    {
+      Node& n = m_nodes[i];
+      n.m_x = rotation * (n.m_x - CoM) + CoM + translation;
+      n.m_q = rotation * (n.m_q - CoM) + CoM + translation;
+      n.m_n = rotation * n.m_n;
+      vol = btDbvtVolume::FromCR(n.m_x, margin);
+
+      m_ndbvt.update(n.m_leaf, vol);
+    }
+    updateNormals();
+    updateBounds();
+    updateConstants();
+  }
+
+  // update modes
+  updateModesByRotation(trs.getBasis());
+
+  // update inertia tensor
+  updateInitialInertiaTensor(trs.getBasis());
+  updateInertiaTensor();
+  m_interpolateInvInertiaTensorWorld = m_invInertiaTensorWorld;
+  
+  // update rigid frame (No need to update the rotation. Nodes have already been updated.)
+  m_rigidTransformWorld.setOrigin(m_initialCoM + trs.getOrigin());
+  m_interpolationWorldTransform = m_rigidTransformWorld;
+  m_initialCoM = m_rigidTransformWorld.getOrigin();
+
+  internalInitialization();
+}
+
+void btReducedDeformableBody::scale(const btVector3& scl)
+{
+  // Scaling the mesh after transform is applied is not allowed
+  btAssert(!m_transform_lock);
+
+  // scale the mesh
+  {
+    const btScalar margin = getCollisionShape()->getMargin();
+    ATTRIBUTE_ALIGNED16(btDbvtVolume)
+    vol;
+
+    btVector3 CoM = m_rigidTransformWorld.getOrigin();
+
+    for (int i = 0; i < m_nodes.size(); ++i)
+    {
+      Node& n = m_nodes[i];
+      n.m_x = (n.m_x - CoM) * scl + CoM;
+      n.m_q = (n.m_q - CoM) * scl + CoM;
+      vol = btDbvtVolume::FromCR(n.m_x, margin);
+      m_ndbvt.update(n.m_leaf, vol);
+    }
+    updateNormals();
+    updateBounds();
+    updateConstants();
+    initializeDmInverse();
+  }
+
+  // update inertia tensor
+  updateLocalInertiaTensorFromNodes();
+
+  btMatrix3x3 id;
+  id.setIdentity();
+  updateInitialInertiaTensor(id);   // there is no rotation, but the local inertia tensor has changed
+  updateInertiaTensor();
+  m_interpolateInvInertiaTensorWorld = m_invInertiaTensorWorld;
+
+  internalInitialization();
+}
+
+void btReducedDeformableBody::setTotalMass(btScalar mass, bool fromfaces)
+{
+  // Changing the total mass after transform is applied is not allowed
+  btAssert(!m_transform_lock);
+
+  btScalar scale_ratio = mass / m_mass;
+
+  // update nodal mass
+  for (int i = 0; i < m_nFull; ++i)
+  {
+    m_nodalMass[i] *= scale_ratio;
+  }
+  m_mass = mass;
+  m_inverseMass = mass > 0 ? 1.0 / mass : 0;
+
+  // update inertia tensors
+  updateLocalInertiaTensorFromNodes();
+
+  btMatrix3x3 id;
+  id.setIdentity();
+  updateInitialInertiaTensor(id);   // there is no rotation, but the local inertia tensor has changed
+  updateInertiaTensor();
+  m_interpolateInvInertiaTensorWorld = m_invInertiaTensorWorld;
+
+  internalInitialization();
+}
+
+void btReducedDeformableBody::updateRestNodalPositions()
+{
+  // update reset nodal position
+  m_x0.resize(m_nFull);
+  for (int i = 0; i < m_nFull; ++i)
+  {
+    m_x0[i] = m_nodes[i].m_x;
+  }
+}
+
+// reference notes:
+// https://ocw.mit.edu/courses/aeronautics-and-astronautics/16-07-dynamics-fall-2009/lecture-notes/MIT16_07F09_Lec26.pdf
+void btReducedDeformableBody::updateLocalInertiaTensorFromNodes()
+{
+  btMatrix3x3 inertia_tensor;
+  inertia_tensor.setZero();
+
+  for (int p = 0; p < m_nFull; ++p)
+  {
+    btMatrix3x3 particle_inertia;
+    particle_inertia.setZero();
+
+    btVector3 r = m_nodes[p].m_x - m_initialCoM;
+
+    particle_inertia[0][0] = m_nodalMass[p] * (r[1] * r[1] + r[2] * r[2]);
+    particle_inertia[1][1] = m_nodalMass[p] * (r[0] * r[0] + r[2] * r[2]);
+    particle_inertia[2][2] = m_nodalMass[p] * (r[0] * r[0] + r[1] * r[1]);
+
+    particle_inertia[0][1] = - m_nodalMass[p] * (r[0] * r[1]);
+    particle_inertia[0][2] = - m_nodalMass[p] * (r[0] * r[2]);
+    particle_inertia[1][2] = - m_nodalMass[p] * (r[1] * r[2]);
+
+    particle_inertia[1][0] = particle_inertia[0][1];
+    particle_inertia[2][0] = particle_inertia[0][2];
+    particle_inertia[2][1] = particle_inertia[1][2];
+
+    inertia_tensor += particle_inertia;
+  }
+  m_invInertiaLocal = inertia_tensor.inverse();
+}
+
+void btReducedDeformableBody::updateInitialInertiaTensor(const btMatrix3x3& rotation)
+{
+  // m_invInertiaTensorWorldInitial = rotation.scaled(m_invInertiaLocal) * rotation.transpose();
+  m_invInertiaTensorWorldInitial = rotation * m_invInertiaLocal * rotation.transpose();
+}
+
+void btReducedDeformableBody::updateModesByRotation(const btMatrix3x3& rotation)
+{
+  for (int r = 0; r < m_nReduced; ++r)
+  {
+    for (int i = 0; i < m_nFull; ++i)
+    {
+      btVector3 nodal_disp(m_modes[r][3 * i], m_modes[r][3 * i + 1], m_modes[r][3 * i + 2]);
+      nodal_disp = rotation * nodal_disp;
+
+      for (int k = 0; k < 3; ++k)
+      {
+        m_modes[r][3 * i + k] = nodal_disp[k];
+      }
+    }
+  }
+}
+
+void btReducedDeformableBody::updateInertiaTensor()
+{
+       m_invInertiaTensorWorld = m_rigidTransformWorld.getBasis() * m_invInertiaTensorWorldInitial * m_rigidTransformWorld.getBasis().transpose();
+}
+
+void btReducedDeformableBody::applyDamping(btScalar timeStep)
+{
+  m_linearVelocity *= btScalar(1) - m_linearDamping;
+  m_angularDamping *= btScalar(1) - m_angularDamping;
+}
+
+void btReducedDeformableBody::applyCentralImpulse(const btVector3& impulse)
+{
+  m_linearVelocity += impulse * m_linearFactor * m_inverseMass;
+  #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+  clampVelocity(m_linearVelocity);
+  #endif
+}
+
+void btReducedDeformableBody::applyTorqueImpulse(const btVector3& torque)
+{
+  m_angularVelocity += m_interpolateInvInertiaTensorWorld * torque * m_angularFactor;
+  #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+  clampVelocity(m_angularVelocity);
+  #endif
+}
+
+void btReducedDeformableBody::internalApplyRigidImpulse(const btVector3& impulse, const btVector3& rel_pos)
+{
+  if (m_inverseMass == btScalar(0.))
+  {
+    std::cout << "something went wrong...probably didn't initialize?\n";
+    btAssert(false);
+  }
+  // delta linear velocity
+  m_internalDeltaLinearVelocity += impulse * m_linearFactor * m_inverseMass;
+  // delta angular velocity
+  btVector3 torque = rel_pos.cross(impulse * m_linearFactor);
+  m_internalDeltaAngularVelocity += m_interpolateInvInertiaTensorWorld * torque * m_angularFactor;
+}
+
+btVector3 btReducedDeformableBody::getRelativePos(int n_node)
+{
+  btMatrix3x3 rotation = m_interpolationWorldTransform.getBasis();
+  btVector3 ri = rotation * m_localMomentArm[n_node];
+  return ri;
+}
+
+btMatrix3x3 btReducedDeformableBody::getImpulseFactor(int n_node)
+{
+  // relative position
+  btMatrix3x3 rotation = m_interpolationWorldTransform.getBasis();
+  btVector3 ri = rotation * m_localMomentArm[n_node];
+  btMatrix3x3 ri_skew = Cross(ri);
+
+  // calculate impulse factor
+  // rigid part
+  btScalar inv_mass = m_nodalMass[n_node] > btScalar(0) ? btScalar(1) / m_mass : btScalar(0);
+  btMatrix3x3 K1 = Diagonal(inv_mass);
+  K1 -= ri_skew * m_interpolateInvInertiaTensorWorld * ri_skew;
+
+  // reduced deformable part
+  btMatrix3x3 SA;
+  SA.setZero();
+  for (int i = 0; i < 3; ++i)
+  {
+    for (int j = 0; j < 3; ++j)
+    {
+      for (int r = 0; r < m_nReduced; ++r)
+      {
+        SA[i][j] += m_modes[r][3 * n_node + i] * (m_projPA[r][3 * n_node + j] + m_projCq[r][3 * n_node + j]);
+      }
+    }
+  }
+  btMatrix3x3 RSARinv = rotation * SA * rotation.transpose();
+
+
+  TVStack omega_helper; // Sum_i m_i r*_i R S_i
+  omega_helper.resize(m_nReduced);
+  for (int r = 0; r < m_nReduced; ++r)
+  {
+    omega_helper[r].setZero();
+    for (int i = 0; i < m_nFull; ++i)
+    {
+      btMatrix3x3 mi_rstar_i = rotation * Cross(m_localMomentArm[i]) * m_nodalMass[i];
+      btVector3 s_ri(m_modes[r][3 * i], m_modes[r][3 * i + 1], m_modes[r][3 * i + 2]);
+      omega_helper[r] += mi_rstar_i * rotation * s_ri;
+    }
+  }
+
+  btMatrix3x3 sum_multiply_A;
+  sum_multiply_A.setZero();
+  for (int i = 0; i < 3; ++i)
+  {
+    for (int j = 0; j < 3; ++j)
+    {
+      for (int r = 0; r < m_nReduced; ++r)
+      {
+        sum_multiply_A[i][j] += omega_helper[r][i] * (m_projPA[r][3 * n_node + j] + m_projCq[r][3 * n_node + j]);
+      }
+    }
+  }
+
+  btMatrix3x3 K2 = RSARinv + ri_skew * m_interpolateInvInertiaTensorWorld * sum_multiply_A * rotation.transpose();
+
+  return m_rigidOnly ? K1 : K1 + K2;
+}
+
+void btReducedDeformableBody::internalApplyFullSpaceImpulse(const btVector3& impulse, const btVector3& rel_pos, int n_node, btScalar dt)
+{
+  if (!m_rigidOnly)
+  {
+    // apply impulse force
+    applyFullSpaceNodalForce(impulse / dt, n_node);
+
+    // update delta damping force
+    tDenseArray reduced_vel_tmp;
+    reduced_vel_tmp.resize(m_nReduced);
+    for (int r = 0; r < m_nReduced; ++r)
+    {
+      reduced_vel_tmp[r] = m_reducedVelocity[r] + m_internalDeltaReducedVelocity[r];
+    }
+    applyReducedDampingForce(reduced_vel_tmp);
+    // applyReducedDampingForce(m_internalDeltaReducedVelocity);
+
+    // delta reduced velocity
+    for (int r = 0; r < m_nReduced; ++r)
+    {
+      // The reduced mass is always identity!
+      m_internalDeltaReducedVelocity[r] += dt * (m_reducedForceDamping[r] + m_reducedForceExternal[r]);
+    }
+  }
+
+  internalApplyRigidImpulse(impulse, rel_pos);
+}
+
+void btReducedDeformableBody::applyFullSpaceNodalForce(const btVector3& f_ext, int n_node)
+{
+  // f_local = R^-1 * f_ext //TODO: interpoalted transfrom
+  // btVector3 f_local = m_rigidTransformWorld.getBasis().transpose() * f_ext;
+  btVector3 f_local = m_interpolationWorldTransform.getBasis().transpose() * f_ext;
+
+  // f_ext_r = [S^T * P]_{n_node} * f_local
+  tDenseArray f_ext_r;
+  f_ext_r.resize(m_nReduced, 0);
+  for (int r = 0; r < m_nReduced; ++r)
+  {
+    m_reducedForceExternal[r] = 0;
+    for (int k = 0; k < 3; ++k)
+    {
+      f_ext_r[r] += (m_projPA[r][3 * n_node + k] + m_projCq[r][3 * n_node + k]) * f_local[k];
+    }
+
+    m_reducedForceExternal[r] += f_ext_r[r];
+  }
+}
+
+void btReducedDeformableBody::applyRigidGravity(const btVector3& gravity, btScalar dt)
+{
+  // update rigid frame velocity
+  m_linearVelocity += dt * gravity;
+}
+
+void btReducedDeformableBody::applyReducedElasticForce(const tDenseArray& reduce_dofs)
+{
+  for (int r = 0; r < m_nReduced; ++r) 
+  {
+    m_reducedForceElastic[r] = - m_ksScale * m_Kr[r] * reduce_dofs[r];
+  }
+}
+
+void btReducedDeformableBody::applyReducedDampingForce(const tDenseArray& reduce_vel)
+{
+  for (int r = 0; r < m_nReduced; ++r) 
+  {
+    m_reducedForceDamping[r] = - m_dampingBeta * m_ksScale * m_Kr[r] * reduce_vel[r];
+  }
+}
+
+btScalar btReducedDeformableBody::getTotalMass() const
+{
+  return m_mass;
+}
+
+btTransform& btReducedDeformableBody::getRigidTransform()
+{
+  return m_rigidTransformWorld;
+}
+
+const btVector3& btReducedDeformableBody::getLinearVelocity() const
+{
+  return m_linearVelocity;
+}
+
+const btVector3& btReducedDeformableBody::getAngularVelocity() const
+{
+  return m_angularVelocity;
+}
+
+void btReducedDeformableBody::disableReducedModes(const bool rigid_only)
+{
+  m_rigidOnly = rigid_only;
+}
+
+bool btReducedDeformableBody::isReducedModesOFF() const
+{
+  return m_rigidOnly;
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBody.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBody.h
new file mode 100644 (file)
index 0000000..8968fb0
--- /dev/null
@@ -0,0 +1,257 @@
+#ifndef BT_REDUCED_SOFT_BODY_H
+#define BT_REDUCED_SOFT_BODY_H
+
+#include "../btSoftBody.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btTransform.h"
+
+// Reduced deformable body is a simplified deformable object embedded in a rigid frame.
+class btReducedDeformableBody : public btSoftBody
+{
+ public:
+  //
+  //  Typedefs
+  //
+  typedef btAlignedObjectArray<btVector3> TVStack;
+  // typedef btAlignedObjectArray<btMatrix3x3> tBlockDiagMatrix;
+  typedef btAlignedObjectArray<btScalar> tDenseArray;
+  typedef btAlignedObjectArray<btAlignedObjectArray<btScalar> > tDenseMatrix;
+
+ private:
+  // flag to turn off the reduced modes
+  bool m_rigidOnly;
+
+  // Flags for transform. Once transform is applied, users cannot scale the mesh or change its total mass.
+  bool m_transform_lock;
+
+  // scaling factors
+  btScalar m_rhoScale;         // mass density scale
+  btScalar m_ksScale;          // stiffness scale
+
+  // projection matrix
+  tDenseMatrix m_projPA;        // Eqn. 4.11 from Rahul Sheth's thesis
+  tDenseMatrix m_projCq;
+  tDenseArray m_STP;
+  tDenseArray m_MrInvSTP;
+
+  TVStack m_localMomentArm; // Sq + x0
+
+  btVector3 m_internalDeltaLinearVelocity;
+  btVector3 m_internalDeltaAngularVelocity;
+  tDenseArray m_internalDeltaReducedVelocity;
+  
+  btVector3 m_linearVelocityFromReduced;  // contribution to the linear velocity from reduced velocity
+  btVector3 m_angularVelocityFromReduced; // contribution to the angular velocity from reduced velocity
+  btVector3 m_internalDeltaAngularVelocityFromReduced;
+
+ protected:
+  // rigid frame
+  btScalar m_mass;          // total mass of the rigid frame
+  btScalar m_inverseMass;   // inverse of the total mass of the rigid frame
+  btVector3 m_linearVelocity;
+  btVector3 m_angularVelocity;
+  btScalar m_linearDamping;    // linear damping coefficient
+  btScalar m_angularDamping;    // angular damping coefficient
+  btVector3 m_linearFactor;
+  btVector3 m_angularFactor;
+  // btVector3 m_invInertiaLocal;
+  btMatrix3x3 m_invInertiaLocal;
+  btTransform m_rigidTransformWorld;
+  btMatrix3x3 m_invInertiaTensorWorldInitial;
+  btMatrix3x3 m_invInertiaTensorWorld;
+  btMatrix3x3 m_interpolateInvInertiaTensorWorld;
+  btVector3 m_initialCoM;  // initial center of mass (original of the m_rigidTransformWorld)
+
+  // damping
+  btScalar m_dampingAlpha;
+  btScalar m_dampingBeta;
+
+ public:
+  //
+  //  Fields
+  //
+
+  // reduced space
+  int m_nReduced;
+  int m_nFull;
+  tDenseMatrix m_modes;                                                                                                                // modes of the reduced deformable model. Each inner array is a mode, outer array size = n_modes
+  tDenseArray m_reducedDofs;                              // Reduced degree of freedom
+  tDenseArray m_reducedDofsBuffer;     // Reduced degree of freedom at t^n
+  tDenseArray m_reducedVelocity;                  // Reduced velocity array
+  tDenseArray m_reducedVelocityBuffer; // Reduced velocity array at t^n
+  tDenseArray m_reducedForceExternal;          // reduced external force
+  tDenseArray m_reducedForceElastic;           // reduced internal elastic force
+  tDenseArray m_reducedForceDamping;           // reduced internal damping force
+  tDenseArray m_eigenvalues;           // eigenvalues of the reduce deformable model
+  tDenseArray m_Kr;    // reduced stiffness matrix
+  
+  // full space
+  TVStack m_x0;                                                                         // Rest position
+  tDenseArray m_nodalMass;           // Mass on each node
+  btAlignedObjectArray<int> m_fixedNodes; // index of the fixed nodes
+  int m_nodeIndexOffset;             // offset of the node index needed for contact solver when there are multiple reduced deformable body in the world.
+
+  // contacts
+  btAlignedObjectArray<int> m_contactNodesList;
+
+  //
+  // Api
+  //
+  btReducedDeformableBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m);
+
+  ~btReducedDeformableBody() {}
+
+  //
+  // initializing helpers
+  //
+  void internalInitialization();
+
+  void setReducedModes(int num_modes, int full_size);
+
+  void setMassProps(const tDenseArray& mass_array);
+
+  void setInertiaProps();
+
+  void setRigidVelocity(const btVector3& v);
+
+  void setRigidAngularVelocity(const btVector3& omega);
+
+  void setStiffnessScale(const btScalar ks);
+
+  void setMassScale(const btScalar rho);
+
+  void setFixedNodes(const int n_node);
+
+  void setDamping(const btScalar alpha, const btScalar beta);
+
+  void disableReducedModes(const bool rigid_only);
+
+  virtual void setTotalMass(btScalar mass, bool fromfaces = false);
+
+  //
+  // various internal updates
+  //
+  virtual void transformTo(const btTransform& trs);
+  virtual void transform(const btTransform& trs);
+  // caution: 
+  // need to use scale before using transform, because the scale is performed in the local frame 
+  // (i.e., may have some rotation already, but the m_rigidTransformWorld doesn't have this info)
+  virtual void scale(const btVector3& scl);
+
+ private:
+  void updateRestNodalPositions();
+
+  void updateInitialInertiaTensor(const btMatrix3x3& rotation);
+
+  void updateLocalInertiaTensorFromNodes();
+
+  void updateInertiaTensor();
+
+  void updateModesByRotation(const btMatrix3x3& rotation);
+ public:
+  void updateLocalMomentArm();
+
+  void predictIntegratedTransform(btScalar dt, btTransform& predictedTransform);
+
+  // update the external force projection matrix 
+  void updateExternalForceProjectMatrix(bool initialized);
+
+  void endOfTimeStepZeroing();
+
+  void applyInternalVelocityChanges();
+
+  //
+  // position and velocity update related
+  //
+
+  // compute reduced degree of freedoms
+  void updateReducedDofs(btScalar solverdt);
+
+  // compute reduced velocity update (for explicit time stepping)
+  void updateReducedVelocity(btScalar solverdt);
+
+  // map to full degree of freedoms
+  void mapToFullPosition(const btTransform& ref_trans);
+
+  // compute full space velocity from the reduced velocity
+  void mapToFullVelocity(const btTransform& ref_trans);
+
+  // compute total angular momentum
+  const btVector3 computeTotalAngularMomentum() const;
+
+  // get a single node's full space velocity from the reduced velocity
+  const btVector3 computeNodeFullVelocity(const btTransform& ref_trans, int n_node) const;
+
+  // get a single node's all delta velocity
+  const btVector3 internalComputeNodeDeltaVelocity(const btTransform& ref_trans, int n_node) const;
+
+  //
+  // rigid motion related
+  //
+  void applyDamping(btScalar timeStep);
+
+  void applyCentralImpulse(const btVector3& impulse);
+
+  void applyTorqueImpulse(const btVector3& torque);
+
+  void proceedToTransform(btScalar dt, bool end_of_time_step);
+
+  //
+  // force related
+  //
+
+  // apply impulse to the rigid frame
+  void internalApplyRigidImpulse(const btVector3& impulse, const btVector3& rel_pos);
+
+  // apply impulse to nodes in the full space
+  void internalApplyFullSpaceImpulse(const btVector3& impulse, const btVector3& rel_pos, int n_node, btScalar dt);
+
+  // apply nodal external force in the full space
+  void applyFullSpaceNodalForce(const btVector3& f_ext, int n_node);
+
+  // apply gravity to the rigid frame
+  void applyRigidGravity(const btVector3& gravity, btScalar dt);
+
+  // apply reduced elastic force
+  void applyReducedElasticForce(const tDenseArray& reduce_dofs);
+
+  // apply reduced damping force
+  void applyReducedDampingForce(const tDenseArray& reduce_vel);
+
+  // calculate the impulse factor
+  virtual btMatrix3x3 getImpulseFactor(int n_node);
+
+  // get relative position from a node to the CoM of the rigid frame
+  btVector3 getRelativePos(int n_node);
+
+  //
+  // accessors
+  //
+  bool isReducedModesOFF() const;
+  btScalar getTotalMass() const;
+  btTransform& getRigidTransform();
+  const btVector3& getLinearVelocity() const;
+       const btVector3& getAngularVelocity() const;
+
+  #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
+  void clampVelocity(btVector3& v) const {
+      v.setX(
+          fmax(-BT_CLAMP_VELOCITY_TO,
+                fmin(BT_CLAMP_VELOCITY_TO, v.getX()))
+      );
+      v.setY(
+          fmax(-BT_CLAMP_VELOCITY_TO,
+                fmin(BT_CLAMP_VELOCITY_TO, v.getY()))
+      );
+      v.setZ(
+          fmax(-BT_CLAMP_VELOCITY_TO,
+                fmin(BT_CLAMP_VELOCITY_TO, v.getZ()))
+      );
+  }
+  #endif
+};
+
+#endif // BT_REDUCED_SOFT_BODY_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodyHelpers.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodyHelpers.cpp
new file mode 100644 (file)
index 0000000..0f95bc5
--- /dev/null
@@ -0,0 +1,215 @@
+#include "btReducedDeformableBodyHelpers.h"
+#include "../btSoftBodyHelpers.h"
+#include <iostream>
+#include <string>
+#include <sstream>
+
+btReducedDeformableBody* btReducedDeformableBodyHelpers::createReducedDeformableObject(btSoftBodyWorldInfo& worldInfo, const std::string& file_path, const std::string& vtk_file, const int num_modes, bool rigid_only) {
+       std::string filename = file_path + vtk_file;
+       btReducedDeformableBody* rsb = btReducedDeformableBodyHelpers::createFromVtkFile(worldInfo, filename.c_str());
+       
+       rsb->setReducedModes(num_modes, rsb->m_nodes.size());
+       btReducedDeformableBodyHelpers::readReducedDeformableInfoFromFiles(rsb, file_path.c_str());
+       
+       rsb->disableReducedModes(rigid_only);
+
+       return rsb;
+}
+
+btReducedDeformableBody* btReducedDeformableBodyHelpers::createFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file)
+{
+       std::ifstream fs;
+       fs.open(vtk_file);
+       btAssert(fs);
+
+       typedef btAlignedObjectArray<int> Index;
+       std::string line;
+       btAlignedObjectArray<btVector3> X;
+       btVector3 position;
+       btAlignedObjectArray<Index> indices;
+       bool reading_points = false;
+       bool reading_tets = false;
+       size_t n_points = 0;
+       size_t n_tets = 0;
+       size_t x_count = 0;
+       size_t indices_count = 0;
+       while (std::getline(fs, line))
+       {
+               std::stringstream ss(line);
+               if (line.size() == (size_t)(0))
+               {
+               }
+               else if (line.substr(0, 6) == "POINTS")
+               {
+                       reading_points = true;
+                       reading_tets = false;
+                       ss.ignore(128, ' ');  // ignore "POINTS"
+                       ss >> n_points;
+                       X.resize(n_points);
+               }
+               else if (line.substr(0, 5) == "CELLS")
+               {
+                       reading_points = false;
+                       reading_tets = true;
+                       ss.ignore(128, ' ');  // ignore "CELLS"
+                       ss >> n_tets;
+                       indices.resize(n_tets);
+               }
+               else if (line.substr(0, 10) == "CELL_TYPES")
+               {
+                       reading_points = false;
+                       reading_tets = false;
+               }
+               else if (reading_points)
+               {
+                       btScalar p;
+                       ss >> p;
+                       position.setX(p);
+                       ss >> p;
+                       position.setY(p);
+                       ss >> p;
+                       position.setZ(p);
+                       //printf("v %f %f %f\n", position.getX(), position.getY(), position.getZ());
+                       X[x_count++] = position;
+               }
+               else if (reading_tets)
+               {
+                       int d;
+                       ss >> d;
+                       if (d != 4)
+                       {
+                               printf("Load deformable failed: Only Tetrahedra are supported in VTK file.\n");
+                               fs.close();
+                               return 0;
+                       }
+                       ss.ignore(128, ' ');  // ignore "4"
+                       Index tet;
+                       tet.resize(4);
+                       for (size_t i = 0; i < 4; i++)
+                       {
+                               ss >> tet[i];
+                               //printf("%d ", tet[i]);
+                       }
+                       //printf("\n");
+                       indices[indices_count++] = tet;
+               }
+       }
+       btReducedDeformableBody* rsb = new btReducedDeformableBody(&worldInfo, n_points, &X[0], 0);
+
+       for (int i = 0; i < n_tets; ++i)
+       {
+               const Index& ni = indices[i];
+               rsb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
+               {
+                       rsb->appendLink(ni[0], ni[1], 0, true);
+                       rsb->appendLink(ni[1], ni[2], 0, true);
+                       rsb->appendLink(ni[2], ni[0], 0, true);
+                       rsb->appendLink(ni[0], ni[3], 0, true);
+                       rsb->appendLink(ni[1], ni[3], 0, true);
+                       rsb->appendLink(ni[2], ni[3], 0, true);
+               }
+       }
+
+       btSoftBodyHelpers::generateBoundaryFaces(rsb);
+       rsb->initializeDmInverse();
+       rsb->m_tetraScratches.resize(rsb->m_tetras.size());
+       rsb->m_tetraScratchesTn.resize(rsb->m_tetras.size());
+       printf("Nodes:  %u\r\n", rsb->m_nodes.size());
+       printf("Links:  %u\r\n", rsb->m_links.size());
+       printf("Faces:  %u\r\n", rsb->m_faces.size());
+       printf("Tetras: %u\r\n", rsb->m_tetras.size());
+
+       fs.close();
+
+       return rsb;
+}
+
+void btReducedDeformableBodyHelpers::readReducedDeformableInfoFromFiles(btReducedDeformableBody* rsb, const char* file_path)
+{
+       // read in eigenmodes, stiffness and mass matrices
+       std::string eigenvalues_file = std::string(file_path) + "eigenvalues.bin";
+       btReducedDeformableBodyHelpers::readBinaryVec(rsb->m_eigenvalues, rsb->m_nReduced, eigenvalues_file.c_str());
+
+       std::string Kr_file = std::string(file_path) + "K_r_diag_mat.bin";
+       btReducedDeformableBodyHelpers::readBinaryVec(rsb->m_Kr,  rsb->m_nReduced, Kr_file.c_str());
+
+       // std::string Mr_file = std::string(file_path) + "M_r_diag_mat.bin";
+       // btReducedDeformableBodyHelpers::readBinaryVec(rsb->m_Mr, rsb->m_nReduced, Mr_file.c_str());
+
+       std::string modes_file = std::string(file_path) + "modes.bin";
+       btReducedDeformableBodyHelpers::readBinaryMat(rsb->m_modes, rsb->m_nReduced, 3 * rsb->m_nFull, modes_file.c_str());
+       
+       // read in full nodal mass
+       std::string M_file = std::string(file_path) + "M_diag_mat.bin";
+       btAlignedObjectArray<btScalar> mass_array;
+       btReducedDeformableBodyHelpers::readBinaryVec(mass_array, rsb->m_nFull, M_file.c_str());
+       rsb->setMassProps(mass_array);
+       
+       // calculate the inertia tensor in the local frame 
+       rsb->setInertiaProps();
+
+       // other internal initialization
+       rsb->internalInitialization();
+}
+
+// read in a vector from the binary file
+void btReducedDeformableBodyHelpers::readBinaryVec(btReducedDeformableBody::tDenseArray& vec, 
+                                                                                                                                                                        const unsigned int n_size,                             // #entries read
+                                                                                                                                                                                const char* file)
+{
+       std::ifstream f_in(file, std::ios::in | std::ios::binary);
+       // first get size
+       unsigned int size=0;
+       f_in.read((char*)&size, 4);//sizeof(unsigned int));
+       btAssert(size >= n_size);       // make sure the #requested mode is smaller than the #available modes
+
+       // read data
+       vec.resize(n_size);
+       double temp;
+       for (unsigned int i = 0; i < n_size; ++i)
+       {
+               f_in.read((char*)&temp, sizeof(double));
+               vec[i] = btScalar(temp);
+       }
+  f_in.close();
+}
+
+// read in a matrix from the binary file
+void btReducedDeformableBodyHelpers::readBinaryMat(btReducedDeformableBody::tDenseMatrix& mat, 
+                                                                                                                                                                                const unsigned int n_modes,            // #modes, outer array size
+                                                                                                                                                                                const unsigned int n_full,             // inner array size
+                                                                                                                                                                                const char* file)
+{
+       std::ifstream f_in(file, std::ios::in | std::ios::binary);
+       // first get size
+       unsigned int v_size=0;
+       f_in.read((char*)&v_size, 4);//sizeof(unsigned int));
+       btAssert(v_size >= n_modes * n_full);   // make sure the #requested mode is smaller than the #available modes
+
+       // read data
+       mat.resize(n_modes);
+       for (int i = 0; i < n_modes; ++i) 
+       {
+               for (int j = 0; j < n_full; ++j)
+               {
+                       double temp;
+                       f_in.read((char*)&temp, sizeof(double));
+
+                       if (mat[i].size() != n_modes)
+                               mat[i].resize(n_full);
+                       mat[i][j] = btScalar(temp);
+               }
+       }
+  f_in.close();
+}
+
+void btReducedDeformableBodyHelpers::calculateLocalInertia(btVector3& inertia, const btScalar mass, const btVector3& half_extents, const btVector3& margin)
+{
+       btScalar lx = btScalar(2.) * (half_extents[0] + margin[0]);
+       btScalar ly = btScalar(2.) * (half_extents[1] + margin[1]);
+       btScalar lz = btScalar(2.) * (half_extents[2] + margin[2]);
+
+       inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
+                                                                  mass / (btScalar(12.0)) * (lx * lx + lz * lz),
+                                                                  mass / (btScalar(12.0)) * (lx * lx + ly * ly));
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodyHelpers.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodyHelpers.h
new file mode 100644 (file)
index 0000000..2b259a9
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef BT_REDUCED_SOFT_BODY_HELPERS_H
+#define BT_REDUCED_SOFT_BODY_HELPERS_H
+
+#include "btReducedDeformableBody.h"
+#include <string>
+
+struct btReducedDeformableBodyHelpers
+{
+       // create a reduced deformable object
+       static btReducedDeformableBody* createReducedDeformableObject(btSoftBodyWorldInfo& worldInfo, const std::string& file_path, const std::string& vtk_file, const int num_modes, bool rigid_only);
+       // read in geometry info from Vtk file
+  static btReducedDeformableBody* createFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file);
+       // read in all reduced files
+       static void readReducedDeformableInfoFromFiles(btReducedDeformableBody* rsb, const char* file_path);
+       // read in a binary vector
+       static void readBinaryVec(btReducedDeformableBody::tDenseArray& vec, const unsigned int n_size, const char* file);
+       // read in a binary matrix
+       static void readBinaryMat(btReducedDeformableBody::tDenseMatrix& mat, const unsigned int n_modes, const unsigned int n_full, const char* file);
+       
+       // calculate the local inertia tensor for a box shape reduced deformable object
+       static void calculateLocalInertia(btVector3& inertia, const btScalar mass, const btVector3& half_extents, const btVector3& margin);
+};
+
+
+#endif // BT_REDUCED_SOFT_BODY_HELPERS_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodySolver.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodySolver.cpp
new file mode 100644 (file)
index 0000000..1418cc2
--- /dev/null
@@ -0,0 +1,325 @@
+#include "btReducedDeformableBodySolver.h"
+#include "btReducedDeformableBody.h"
+
+btReducedDeformableBodySolver::btReducedDeformableBodySolver()
+{
+  m_ascendOrder = true;
+  m_reducedSolver = true;
+  m_dampingAlpha = 0;
+  m_dampingBeta = 0;
+  m_gravity = btVector3(0, 0, 0);
+}
+
+void btReducedDeformableBodySolver::setGravity(const btVector3& gravity)
+{
+  m_gravity = gravity;
+}
+
+void btReducedDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody*>& bodies, btScalar dt)
+{
+  m_softBodies.copyFromArray(bodies);
+       bool nodeUpdated = updateNodes();
+
+       if (nodeUpdated)
+       {
+               m_dv.resize(m_numNodes, btVector3(0, 0, 0));
+               m_ddv.resize(m_numNodes, btVector3(0, 0, 0));
+               m_residual.resize(m_numNodes, btVector3(0, 0, 0));
+               m_backupVelocity.resize(m_numNodes, btVector3(0, 0, 0));
+       }
+
+       // need to setZero here as resize only set value for newly allocated items
+       for (int i = 0; i < m_numNodes; ++i)
+       {
+               m_dv[i].setZero();
+               m_ddv[i].setZero();
+               m_residual[i].setZero();
+       }
+
+       if (dt > 0)
+       {
+               m_dt = dt;
+       }
+       m_objective->reinitialize(nodeUpdated, dt);
+
+  int N = bodies.size();
+       if (nodeUpdated)
+       {
+               m_staticConstraints.resize(N);
+               m_nodeRigidConstraints.resize(N);
+               // m_faceRigidConstraints.resize(N);
+       }
+       for (int i = 0; i < N; ++i)
+       {
+               m_staticConstraints[i].clear();
+               m_nodeRigidConstraints[i].clear();
+               // m_faceRigidConstraints[i].clear();
+       }
+
+  for (int i = 0; i < m_softBodies.size(); ++i)
+  {
+    btReducedDeformableBody* rsb = static_cast<btReducedDeformableBody*>(m_softBodies[i]);
+    rsb->m_contactNodesList.clear();
+  }
+
+  // set node index offsets
+  int sum = 0;
+  for (int i = 0; i < m_softBodies.size(); ++i)
+  {
+    btReducedDeformableBody* rsb = static_cast<btReducedDeformableBody*>(m_softBodies[i]);
+    rsb->m_nodeIndexOffset = sum;
+    sum += rsb->m_nodes.size();
+  }
+
+       btDeformableBodySolver::updateSoftBodies();
+}
+
+void btReducedDeformableBodySolver::predictMotion(btScalar solverdt)
+{
+  applyExplicitForce(solverdt);
+
+  // predict new mesh location
+  predictReduceDeformableMotion(solverdt);
+
+  //TODO: check if there is anything missed from btDeformableBodySolver::predictDeformableMotion
+}
+
+void btReducedDeformableBodySolver::predictReduceDeformableMotion(btScalar solverdt)
+{
+  for (int i = 0; i < m_softBodies.size(); ++i)
+  {
+    btReducedDeformableBody* rsb = static_cast<btReducedDeformableBody*>(m_softBodies[i]);
+    if (!rsb->isActive())
+    {
+      continue;
+    }
+
+    // clear contacts variables
+               rsb->m_nodeRigidContacts.resize(0);
+               rsb->m_faceRigidContacts.resize(0);
+               rsb->m_faceNodeContacts.resize(0);
+    
+    // calculate inverse mass matrix for all nodes
+    for (int j = 0; j < rsb->m_nodes.size(); ++j)
+    {
+      if (rsb->m_nodes[j].m_im > 0)
+      {
+        rsb->m_nodes[j].m_effectiveMass_inv = rsb->m_nodes[j].m_effectiveMass.inverse();
+      }
+    }
+
+    // rigid motion: t, R at time^*
+    rsb->predictIntegratedTransform(solverdt, rsb->getInterpolationWorldTransform());
+
+    // update reduced dofs at time^*
+    // rsb->updateReducedDofs(solverdt);
+
+    // update local moment arm at time^*
+    // rsb->updateLocalMomentArm();
+    // rsb->updateExternalForceProjectMatrix(true);
+
+    // predict full space velocity at time^* (needed for constraints)
+    rsb->mapToFullVelocity(rsb->getInterpolationWorldTransform());
+
+    // update full space nodal position at time^*
+    rsb->mapToFullPosition(rsb->getInterpolationWorldTransform());
+
+    // update bounding box
+    rsb->updateBounds();
+
+    // update tree
+    rsb->updateNodeTree(true, true);
+    if (!rsb->m_fdbvt.empty())
+    {
+      rsb->updateFaceTree(true, true);
+    }
+  }
+}
+
+void btReducedDeformableBodySolver::applyExplicitForce(btScalar solverdt)
+{
+  for (int i = 0; i < m_softBodies.size(); ++i)
+  {
+    btReducedDeformableBody* rsb = static_cast<btReducedDeformableBody*>(m_softBodies[i]);
+
+    // apply gravity to the rigid frame, get m_linearVelocity at time^*
+    rsb->applyRigidGravity(m_gravity, solverdt);
+
+    if (!rsb->isReducedModesOFF())
+    {
+      // add internal force (elastic force & damping force)
+      rsb->applyReducedElasticForce(rsb->m_reducedDofsBuffer);
+      rsb->applyReducedDampingForce(rsb->m_reducedVelocityBuffer);
+
+      // get reduced velocity at time^* 
+      rsb->updateReducedVelocity(solverdt);
+    }
+
+    // apply damping (no need at this point)
+    // rsb->applyDamping(solverdt);
+  }
+}
+
+void btReducedDeformableBodySolver::applyTransforms(btScalar timeStep)
+{
+  for (int i = 0; i < m_softBodies.size(); ++i)
+  {
+    btReducedDeformableBody* rsb = static_cast<btReducedDeformableBody*>(m_softBodies[i]);
+
+    // rigid motion
+    rsb->proceedToTransform(timeStep, true);
+
+    if (!rsb->isReducedModesOFF())
+    {
+      // update reduced dofs for time^n+1
+      rsb->updateReducedDofs(timeStep);
+
+      // update local moment arm for time^n+1
+      rsb->updateLocalMomentArm();
+      rsb->updateExternalForceProjectMatrix(true);
+    }
+
+    // update mesh nodal positions for time^n+1
+    rsb->mapToFullPosition(rsb->getRigidTransform());
+
+    // update mesh nodal velocity
+    rsb->mapToFullVelocity(rsb->getRigidTransform());
+
+    // end of time step clean up and update
+    rsb->endOfTimeStepZeroing();
+
+    // update the rendering mesh
+    rsb->interpolateRenderMesh();
+  }
+}
+
+void btReducedDeformableBodySolver::setConstraints(const btContactSolverInfo& infoGlobal)
+{
+  for (int i = 0; i < m_softBodies.size(); ++i)
+  {
+    btReducedDeformableBody* rsb = static_cast<btReducedDeformableBody*>(m_softBodies[i]);
+    if (!rsb->isActive())
+               {
+                       continue;
+               }
+
+    // set fixed constraints
+    for (int j = 0; j < rsb->m_fixedNodes.size(); ++j)
+               {
+      int i_node = rsb->m_fixedNodes[j];
+                       if (rsb->m_nodes[i_node].m_im == 0)
+                       {
+        for (int k = 0; k < 3; ++k)
+        {
+          btVector3 dir(0, 0, 0);
+          dir[k] = 1;
+          btReducedDeformableStaticConstraint static_constraint(rsb, &rsb->m_nodes[i_node], rsb->getRelativePos(i_node), rsb->m_x0[i_node], dir, infoGlobal, m_dt);
+          m_staticConstraints[i].push_back(static_constraint);
+        }
+                       }
+               }
+    btAssert(rsb->m_fixedNodes.size() * 3 == m_staticConstraints[i].size());
+
+    // set Deformable Node vs. Rigid constraint
+               for (int j = 0; j < rsb->m_nodeRigidContacts.size(); ++j)
+               {
+                       const btSoftBody::DeformableNodeRigidContact& contact = rsb->m_nodeRigidContacts[j];
+                       // skip fixed points
+                       if (contact.m_node->m_im == 0)
+                       {
+                               continue;
+                       }
+                       btReducedDeformableNodeRigidContactConstraint constraint(rsb, contact, infoGlobal, m_dt);
+                       m_nodeRigidConstraints[i].push_back(constraint);
+      rsb->m_contactNodesList.push_back(contact.m_node->index - rsb->m_nodeIndexOffset);
+               }
+    // std::cout << "contact node list size: " << rsb->m_contactNodesList.size() << "\n";
+    // std::cout << "#contact nodes: " << m_nodeRigidConstraints[i].size() << "\n";
+
+  }
+}
+
+btScalar btReducedDeformableBodySolver::solveContactConstraints(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
+{
+  btScalar residualSquare = 0;
+
+  for (int i = 0; i < m_softBodies.size(); ++i)
+  {
+    btAlignedObjectArray<int> m_orderNonContactConstraintPool;
+    btAlignedObjectArray<int> m_orderContactConstraintPool;
+
+    btReducedDeformableBody* rsb = static_cast<btReducedDeformableBody*>(m_softBodies[i]);
+
+    // shuffle the order of applying constraint
+    m_orderNonContactConstraintPool.resize(m_staticConstraints[i].size());
+    m_orderContactConstraintPool.resize(m_nodeRigidConstraints[i].size());
+    if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
+    {
+      // fixed constraint order
+      for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+      {
+        m_orderNonContactConstraintPool[j] = m_ascendOrder ? j : m_staticConstraints[i].size() - 1 - j;
+      }
+      // contact constraint order
+      for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+      {
+        m_orderContactConstraintPool[j] = m_ascendOrder ? j : m_nodeRigidConstraints[i].size() - 1 - j;
+      }
+
+      m_ascendOrder = m_ascendOrder ? false : true;
+    }
+    else
+    {
+      for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+      {
+        m_orderNonContactConstraintPool[j] = j;
+      }
+      // contact constraint order
+      for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+      {
+        m_orderContactConstraintPool[j] = j;
+      }
+    }
+
+    // handle fixed constraint
+    for (int k = 0; k < m_staticConstraints[i].size(); ++k)
+    {
+      btReducedDeformableStaticConstraint& constraint = m_staticConstraints[i][m_orderNonContactConstraintPool[k]];
+      btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+      residualSquare = btMax(residualSquare, localResidualSquare);
+    }
+
+    // handle contact constraint
+
+    // node vs rigid contact
+    // std::cout << "!!#contact_nodes: " << m_nodeRigidConstraints[i].size() << '\n';
+    for (int k = 0; k < m_nodeRigidConstraints[i].size(); ++k)
+    {
+      btReducedDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[i][m_orderContactConstraintPool[k]];
+      btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+      residualSquare = btMax(residualSquare, localResidualSquare);
+    }
+
+    // face vs rigid contact
+    // for (int k = 0; k < m_faceRigidConstraints[i].size(); ++k)
+    // {
+    //         btReducedDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[i][k];
+    //         btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+    //         residualSquare = btMax(residualSquare, localResidualSquare);
+    // }
+  }
+
+  
+       return residualSquare;
+}
+
+void btReducedDeformableBodySolver::deformableBodyInternalWriteBack()
+{
+  // reduced deformable update
+  for (int i = 0; i < m_softBodies.size(); ++i)
+  {
+    btReducedDeformableBody* rsb = static_cast<btReducedDeformableBody*>(m_softBodies[i]);
+    rsb->applyInternalVelocityChanges();
+  }
+  m_ascendOrder = true;
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodySolver.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableBodySolver.h
new file mode 100644 (file)
index 0000000..04c171f
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef BT_REDUCED_DEFORMABLE_BODY_DYNAMICS_WORLD_H
+#define BT_REDUCED_DEFORMABLE_BODY_DYNAMICS_WORLD_H
+
+#include "BulletSoftBody/btDeformableBodySolver.h"
+#include "btReducedDeformableContactConstraint.h"
+
+class btReducedDeformableBody;
+
+class btReducedDeformableBodySolver : public btDeformableBodySolver
+{
+ protected:
+  bool m_ascendOrder;
+  btScalar m_dampingAlpha;
+  btScalar m_dampingBeta;
+
+  btVector3 m_gravity;
+
+  void predictReduceDeformableMotion(btScalar solverdt);
+
+  void applyExplicitForce(btScalar solverdt);
+
+ public:
+  btAlignedObjectArray<btAlignedObjectArray<btReducedDeformableStaticConstraint> > m_staticConstraints;
+  btAlignedObjectArray<btAlignedObjectArray<btReducedDeformableNodeRigidContactConstraint> > m_nodeRigidConstraints;
+  btAlignedObjectArray<btAlignedObjectArray<btReducedDeformableFaceRigidContactConstraint> > m_faceRigidConstraints;
+  
+  btReducedDeformableBodySolver();
+  ~btReducedDeformableBodySolver() {}
+
+  virtual void setGravity(const btVector3& gravity);
+
+  virtual SolverTypes getSolverType() const
+  {
+    return REDUCED_DEFORMABLE_SOLVER;
+  }
+
+  // resize/clear data structures
+       virtual void reinitialize(const btAlignedObjectArray<btSoftBody*>& bodies, btScalar dt);
+
+  virtual void predictMotion(btScalar solverdt);
+
+  virtual void applyTransforms(btScalar timeStep);
+
+  // set up contact constraints
+       virtual void setConstraints(const btContactSolverInfo& infoGlobal);
+
+  // solve all constraints (fixed and contact)
+  virtual btScalar solveContactConstraints(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal);
+
+  // apply all the delta velocities
+  virtual void deformableBodyInternalWriteBack();
+
+  // virtual void setProjection() {}
+
+  // virtual void setLagrangeMultiplier() {}
+
+  // virtual void setupDeformableSolve(bool implicit);
+
+};
+
+#endif // BT_REDUCED_DEFORMABLE_BODY_DYNAMICS_WORLD_H
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableContactConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableContactConstraint.cpp
new file mode 100644 (file)
index 0000000..3c78d2d
--- /dev/null
@@ -0,0 +1,579 @@
+#include "btReducedDeformableContactConstraint.h"
+#include <iostream>
+
+// ================= static constraints ===================
+btReducedDeformableStaticConstraint::btReducedDeformableStaticConstraint(
+  btReducedDeformableBody* rsb, 
+  btSoftBody::Node* node,
+       const btVector3& ri,
+       const btVector3& x0,
+       const btVector3& dir,
+  const btContactSolverInfo& infoGlobal,
+       btScalar dt)
+  : m_rsb(rsb), m_ri(ri), m_targetPos(x0), m_impulseDirection(dir), m_dt(dt), btDeformableStaticConstraint(node, infoGlobal)
+{
+       m_erp = 0.2;
+       m_appliedImpulse = 0;
+
+       // get impulse factor
+  m_impulseFactorMatrix = rsb->getImpulseFactor(m_node->index);
+       m_impulseFactor = (m_impulseFactorMatrix * m_impulseDirection).dot(m_impulseDirection);
+
+       btScalar vel_error = btDot(-m_node->m_v, m_impulseDirection);
+       btScalar pos_error = btDot(m_targetPos - m_node->m_x, m_impulseDirection);
+
+       m_rhs = (vel_error + m_erp * pos_error / m_dt) / m_impulseFactor;
+}
+
+btScalar btReducedDeformableStaticConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
+{
+       // target velocity of fixed constraint is 0
+       btVector3 deltaVa = getDeltaVa();
+       btScalar deltaV_rel = btDot(deltaVa, m_impulseDirection);
+  btScalar deltaImpulse = m_rhs - deltaV_rel / m_impulseFactor;
+       m_appliedImpulse = m_appliedImpulse + deltaImpulse;
+
+       btVector3 impulse = deltaImpulse * m_impulseDirection;
+       applyImpulse(impulse);
+
+       // calculate residual
+       btScalar residualSquare = m_impulseFactor * deltaImpulse;
+       residualSquare *= residualSquare;
+
+       return residualSquare;
+}
+  
+// this calls reduced deformable body's internalApplyFullSpaceImpulse
+void btReducedDeformableStaticConstraint::applyImpulse(const btVector3& impulse)
+{
+       // apply full space impulse
+       m_rsb->internalApplyFullSpaceImpulse(impulse, m_ri, m_node->index, m_dt);
+}
+
+btVector3 btReducedDeformableStaticConstraint::getDeltaVa() const
+{
+       return m_rsb->internalComputeNodeDeltaVelocity(m_rsb->getInterpolationWorldTransform(), m_node->index);
+}
+
+// ================= base contact constraints ===================
+btReducedDeformableRigidContactConstraint::btReducedDeformableRigidContactConstraint(
+  btReducedDeformableBody* rsb, 
+  const btSoftBody::DeformableRigidContact& c, 
+  const btContactSolverInfo& infoGlobal,
+       btScalar dt)
+  : m_rsb(rsb), m_dt(dt), btDeformableRigidContactConstraint(c, infoGlobal)
+{
+       m_nodeQueryIndex = 0;
+       m_appliedNormalImpulse = 0;
+  m_appliedTangentImpulse = 0;
+       m_rhs = 0;
+       m_rhs_tangent = 0;
+       m_cfm = infoGlobal.m_deformable_cfm;
+       m_cfm_friction = 0;
+       m_erp = infoGlobal.m_deformable_erp;
+       m_erp_friction = infoGlobal.m_deformable_erp;
+       m_friction = infoGlobal.m_friction;
+
+       m_collideStatic = m_contact->m_cti.m_colObj->isStaticObject();
+       m_collideMultibody = (m_contact->m_cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK);
+}
+
+void btReducedDeformableRigidContactConstraint::setSolverBody(const int bodyId, btSolverBody& solver_body)
+{
+       if (!m_collideMultibody)
+       {
+               m_solverBodyId = bodyId;
+               m_solverBody = &solver_body;
+               m_linearComponentNormal = -m_contactNormalA * m_solverBody->internalGetInvMass();
+               btVector3       torqueAxis = -m_relPosA.cross(m_contactNormalA);
+               m_angularComponentNormal = m_solverBody->m_originalBody->getInvInertiaTensorWorld() * torqueAxis;
+               
+               m_linearComponentTangent = m_contactTangent * m_solverBody->internalGetInvMass();
+               btVector3 torqueAxisTangent = m_relPosA.cross(m_contactTangent);
+               m_angularComponentTangent = m_solverBody->m_originalBody->getInvInertiaTensorWorld() * torqueAxisTangent;
+       }
+}
+
+btVector3 btReducedDeformableRigidContactConstraint::getVa() const
+{
+       btVector3 Va(0, 0, 0);
+       if (!m_collideStatic)
+       {
+               Va = btDeformableRigidContactConstraint::getVa();
+       }
+       return Va;
+}
+
+btScalar btReducedDeformableRigidContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
+{
+       // btVector3 Va = getVa();
+       // btVector3 deltaVa = Va - m_bufferVelocityA;
+       // if (!m_collideStatic)
+       // {
+               // std::cout << "moving collision!!!\n";
+               // std::cout << "relPosA: " << m_relPosA[0] << "\t" << m_relPosA[1] << "\t" << m_relPosA[2] << "\n";
+               // std::cout << "moving rigid linear_vel: " << m_solverBody->m_originalBody->getLinearVelocity()[0] << '\t'
+               //  << m_solverBody->m_originalBody->getLinearVelocity()[1] << '\t'
+               //   << m_solverBody->m_originalBody->getLinearVelocity()[2] << '\n';
+       // }
+       btVector3 deltaVa = getDeltaVa();
+       btVector3 deltaVb = getDeltaVb();
+
+       // if (!m_collideStatic)
+       // {
+       //      std::cout << "deltaVa: " << deltaVa[0] << '\t' << deltaVa[1] << '\t' << deltaVa[2] << '\n';
+       //      std::cout << "deltaVb: " << deltaVb[0] << '\t' << deltaVb[1] << '\t' << deltaVb[2] << '\n';
+       // }
+
+       // get delta relative velocity and magnitude (i.e., how much impulse has been applied?)
+       btVector3 deltaV_rel = deltaVa - deltaVb;
+       btScalar deltaV_rel_normal = -btDot(deltaV_rel, m_contactNormalA);
+
+       // if (!m_collideStatic)
+       // {
+       //      std::cout << "deltaV_rel: " << deltaV_rel[0] << '\t' << deltaV_rel[1] << '\t' << deltaV_rel[2] << "\n";
+       //      std::cout << "deltaV_rel_normal: " << deltaV_rel_normal << "\n";
+       //      std::cout << "normal_A: " << m_contactNormalA[0] << '\t' << m_contactNormalA[1] << '\t' << m_contactNormalA[2] << '\n';
+       // }
+       
+       // get the normal impulse to be applied
+       btScalar deltaImpulse = m_rhs - m_appliedNormalImpulse * m_cfm - deltaV_rel_normal / m_normalImpulseFactor;
+       // if (!m_collideStatic)
+       // {
+       //      std::cout << "m_rhs: " << m_rhs << '\t' << "m_appliedNormalImpulse: "  << m_appliedNormalImpulse << "\n";
+       //      std::cout << "m_normalImpulseFactor: " << m_normalImpulseFactor << '\n';
+       // }
+
+       {
+               // cumulative impulse that has been applied
+               btScalar sum = m_appliedNormalImpulse + deltaImpulse;
+               // if the cumulative impulse is pushing the object into the rigid body, set it zero
+               if (sum < 0)
+               {
+                       deltaImpulse = -m_appliedNormalImpulse;
+                       m_appliedNormalImpulse = 0;
+               }
+               else
+               {
+                       m_appliedNormalImpulse = sum;
+               }       
+       }
+
+       // if (!m_collideStatic)
+       // {
+       //      std::cout << "m_appliedNormalImpulse: " << m_appliedNormalImpulse << '\n';
+       //      std::cout << "deltaImpulse: " << deltaImpulse << '\n';
+       // }
+
+       // residual is the nodal normal velocity change in current iteration
+       btScalar residualSquare = deltaImpulse * m_normalImpulseFactor; // get residual
+       residualSquare *= residualSquare;
+
+       
+       // apply Coulomb friction (based on delta velocity, |dv_t| = |dv_n * friction|)
+       btScalar deltaImpulse_tangent = 0;
+       btScalar deltaImpulse_tangent2 = 0;
+       {
+               // calculate how much impulse is needed
+               // btScalar deltaV_rel_tangent = btDot(deltaV_rel, m_contactTangent);
+               // btScalar impulse_changed = deltaV_rel_tangent * m_tangentImpulseFactorInv;
+               // deltaImpulse_tangent = m_rhs_tangent - impulse_changed;
+
+               // btScalar sum = m_appliedTangentImpulse + deltaImpulse_tangent;
+               btScalar lower_limit = - m_appliedNormalImpulse * m_friction;
+               btScalar upper_limit = m_appliedNormalImpulse * m_friction;
+               // if (sum > upper_limit)
+               // {
+               //      deltaImpulse_tangent = upper_limit - m_appliedTangentImpulse;
+               //      m_appliedTangentImpulse = upper_limit;
+               // }
+               // else if (sum < lower_limit)
+               // {
+               //      deltaImpulse_tangent = lower_limit - m_appliedTangentImpulse;
+               //      m_appliedTangentImpulse = lower_limit;
+               // }
+               // else
+               // {
+               //      m_appliedTangentImpulse = sum;
+               // }
+               // 
+               calculateTangentialImpulse(deltaImpulse_tangent, m_appliedTangentImpulse, m_rhs_tangent,
+                                                                                                                        m_tangentImpulseFactorInv, m_contactTangent, lower_limit, upper_limit, deltaV_rel);
+               
+               if (m_collideMultibody)
+               {
+                       calculateTangentialImpulse(deltaImpulse_tangent2, m_appliedTangentImpulse2, m_rhs_tangent2,
+                                                                                                                          m_tangentImpulseFactorInv2, m_contactTangent2, lower_limit, upper_limit, deltaV_rel);
+               }
+                                                                                                                        
+
+               if (!m_collideStatic)
+               {
+                       // std::cout << "m_contactTangent: " << m_contactTangent[0] << "\t"  << m_contactTangent[1] << "\t"  << m_contactTangent[2] << "\n";
+                       // std::cout << "deltaV_rel_tangent: " << deltaV_rel_tangent << '\n';
+                       // std::cout << "deltaImpulseTangent: " << deltaImpulse_tangent << '\n';
+                       // std::cout << "m_appliedTangentImpulse: " << m_appliedTangentImpulse << '\n';
+               }
+       }
+
+       // get the total impulse vector
+       btVector3 impulse_normal = deltaImpulse * m_contactNormalA;
+       btVector3 impulse_tangent = deltaImpulse_tangent * (-m_contactTangent);
+       btVector3 impulse_tangent2 = deltaImpulse_tangent2 * (-m_contactTangent2);
+       btVector3 impulse = impulse_normal + impulse_tangent + impulse_tangent2;
+
+       applyImpulse(impulse);
+       
+       // apply impulse to the rigid/multibodies involved and change their velocities
+       if (!m_collideStatic)
+       {
+               // std::cout << "linear_component: " << m_linearComponentNormal[0] << '\t'
+               //                                                                                                                                      << m_linearComponentNormal[1] << '\t'
+               //                                                                                                                                      << m_linearComponentNormal[2] << '\n';
+               // std::cout << "angular_component: " << m_angularComponentNormal[0] << '\t'
+               //                                                                                                                                      << m_angularComponentNormal[1] << '\t'
+               //                                                                                                                                      << m_angularComponentNormal[2] << '\n';
+
+               if (!m_collideMultibody)                // collision with rigid body
+               {
+                       // std::cout << "rigid impulse applied!!\n";
+                       // std::cout << "delta Linear: " << m_solverBody->getDeltaLinearVelocity()[0] << '\t'
+                       // << m_solverBody->getDeltaLinearVelocity()[1] << '\t'
+                       //      << m_solverBody->getDeltaLinearVelocity()[2] << '\n';
+                       // std::cout << "delta Angular: " << m_solverBody->getDeltaAngularVelocity()[0] << '\t'
+                       // << m_solverBody->getDeltaAngularVelocity()[1] << '\t'
+                       //      << m_solverBody->getDeltaAngularVelocity()[2] << '\n';
+
+                       m_solverBody->internalApplyImpulse(m_linearComponentNormal, m_angularComponentNormal, deltaImpulse);
+                       m_solverBody->internalApplyImpulse(m_linearComponentTangent, m_angularComponentTangent, deltaImpulse_tangent);
+
+                       // std::cout << "after\n";
+                       // std::cout << "rigid impulse applied!!\n";
+                       // std::cout << "delta Linear: " << m_solverBody->getDeltaLinearVelocity()[0] << '\t'
+                       // << m_solverBody->getDeltaLinearVelocity()[1] << '\t'
+                       //      << m_solverBody->getDeltaLinearVelocity()[2] << '\n';
+                       // std::cout << "delta Angular: " << m_solverBody->getDeltaAngularVelocity()[0] << '\t'
+                       // << m_solverBody->getDeltaAngularVelocity()[1] << '\t'
+                       //      << m_solverBody->getDeltaAngularVelocity()[2] << '\n';
+               }
+               else            // collision with multibody
+               {
+                       btMultiBodyLinkCollider* multibodyLinkCol = 0;
+                       multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(m_contact->m_cti.m_colObj);
+                       if (multibodyLinkCol)
+                       {
+                               const btScalar* deltaV_normal = &m_contact->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+                               // apply normal component of the impulse
+                               multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, -deltaImpulse);
+                               
+                               // const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+                               // std::cout << "deltaV_normal: ";
+                               // for (int i = 0; i < ndof; ++i)
+                               // {
+                               //      std::cout << i << "\t" << deltaV_normal[i] << '\n';
+                               // }
+
+                               if (impulse_tangent.norm() > SIMD_EPSILON)
+                               {
+                                       // apply tangential component of the impulse
+                                       const btScalar* deltaV_t1 = &m_contact->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+                                       multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, deltaImpulse_tangent);
+                                       const btScalar* deltaV_t2 = &m_contact->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+                                       multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, deltaImpulse_tangent2);
+                               }
+                       }
+               }
+       }
+       return residualSquare;
+}
+
+void btReducedDeformableRigidContactConstraint::calculateTangentialImpulse(btScalar& deltaImpulse_tangent, 
+                                                                                                                                                                                                                                                                                                        btScalar& appliedImpulse, 
+                                                                                                                                                                                                                                                                                                        const btScalar rhs_tangent,
+                                                                                                                                                                                                                                                                                                        const btScalar tangentImpulseFactorInv,
+                                                                                                                                                                                                                                                                                                        const btVector3& tangent,
+                                                                                                                                                                                                                                                                                                        const btScalar lower_limit,
+                                                                                                                                                                                                                                                                                                        const btScalar upper_limit,
+                                                                                                                                                                                                                                                                                                        const btVector3& deltaV_rel)
+{
+       btScalar deltaV_rel_tangent = btDot(deltaV_rel, tangent);
+       btScalar impulse_changed = deltaV_rel_tangent * tangentImpulseFactorInv;
+       deltaImpulse_tangent = rhs_tangent - m_cfm_friction * appliedImpulse - impulse_changed;
+
+       btScalar sum = appliedImpulse + deltaImpulse_tangent;
+       if (sum > upper_limit)
+       {
+               deltaImpulse_tangent = upper_limit - appliedImpulse;
+               appliedImpulse = upper_limit;
+       }
+       else if (sum < lower_limit)
+       {
+               deltaImpulse_tangent = lower_limit - appliedImpulse;
+               appliedImpulse = lower_limit;
+       }
+       else
+       {
+               appliedImpulse = sum;
+       }
+}
+
+// ================= node vs rigid constraints ===================
+btReducedDeformableNodeRigidContactConstraint::btReducedDeformableNodeRigidContactConstraint(
+  btReducedDeformableBody* rsb, 
+  const btSoftBody::DeformableNodeRigidContact& contact, 
+  const btContactSolverInfo& infoGlobal,
+       btScalar dt)
+  : m_node(contact.m_node), btReducedDeformableRigidContactConstraint(rsb, contact, infoGlobal, dt)
+{
+       m_contactNormalA = contact.m_cti.m_normal;
+  m_contactNormalB = -contact.m_cti.m_normal;
+
+       if (contact.m_node->index < rsb->m_nodes.size())
+       {
+               m_nodeQueryIndex = contact.m_node->index;
+       }
+       else
+       {
+               m_nodeQueryIndex = m_node->index - rsb->m_nodeIndexOffset;
+       }
+
+       if (m_contact->m_cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+       {
+               m_relPosA = contact.m_c1;
+       }
+       else
+       {
+               m_relPosA = btVector3(0,0,0);
+       }
+       m_relPosB = m_node->m_x - m_rsb->getRigidTransform().getOrigin();
+
+       if (m_collideStatic)            // colliding with static object, only consider reduced deformable body's impulse factor
+       {
+               m_impulseFactor = m_rsb->getImpulseFactor(m_nodeQueryIndex);
+       }
+       else            // colliding with dynamic object, consider both reduced deformable and rigid body's impulse factors
+       {
+               m_impulseFactor = m_rsb->getImpulseFactor(m_nodeQueryIndex) + contact.m_c0;
+       }
+
+       m_normalImpulseFactor = (m_impulseFactor * m_contactNormalA).dot(m_contactNormalA);
+       m_tangentImpulseFactor = 0;
+
+       warmStarting();
+}
+
+void btReducedDeformableNodeRigidContactConstraint::warmStarting()
+{
+       btVector3 va = getVa();
+       btVector3 vb = getVb();
+       m_bufferVelocityA = va;
+       m_bufferVelocityB = vb;
+
+       // we define the (+) direction of errors to be the outward surface normal of the rigid object
+       btVector3 v_rel = vb - va;
+       // get tangent direction of the relative velocity
+       btVector3 v_tangent = v_rel - v_rel.dot(m_contactNormalA) * m_contactNormalA;
+       if (v_tangent.norm() < SIMD_EPSILON)
+       {
+               m_contactTangent = btVector3(0, 0, 0);
+               // tangent impulse factor
+               m_tangentImpulseFactor = 0;
+               m_tangentImpulseFactorInv = 0;
+       }
+       else
+       {
+               if (!m_collideMultibody)
+               {
+                       m_contactTangent = v_tangent.normalized();
+                       m_contactTangent2.setZero();
+                       // tangent impulse factor 1
+                       m_tangentImpulseFactor = (m_impulseFactor * m_contactTangent).dot(m_contactTangent);
+                       m_tangentImpulseFactorInv = btScalar(1) / m_tangentImpulseFactor;
+                       // tangent impulse factor 2
+                       m_tangentImpulseFactor2 = 0;
+                       m_tangentImpulseFactorInv2 = 0;
+               }
+               else    // multibody requires 2 contact directions
+               {
+                       m_contactTangent = m_contact->t1;
+                       m_contactTangent2 = m_contact->t2;
+
+                       // tangent impulse factor 1
+                       m_tangentImpulseFactor = (m_impulseFactor * m_contactTangent).dot(m_contactTangent);
+                       m_tangentImpulseFactorInv = btScalar(1) / m_tangentImpulseFactor;
+                       // tangent impulse factor 2
+                       m_tangentImpulseFactor2 = (m_impulseFactor * m_contactTangent2).dot(m_contactTangent2);
+                       m_tangentImpulseFactorInv2 = btScalar(1) / m_tangentImpulseFactor2;
+               }
+       }
+
+
+       // initial guess for normal impulse
+       {
+               btScalar velocity_error = btDot(v_rel, m_contactNormalA);       // magnitude of relative velocity
+               btScalar position_error = 0;
+               if (m_penetration > 0)
+               {
+                       velocity_error += m_penetration / m_dt;
+               }
+               else
+               {
+                       // add penetration correction vel
+                       position_error = m_penetration * m_erp / m_dt;
+               }
+               // get the initial estimate of impulse magnitude to be applied
+               m_rhs = -(velocity_error + position_error) / m_normalImpulseFactor;
+       }
+
+       // initial guess for tangential impulse
+       {
+               btScalar velocity_error = btDot(v_rel, m_contactTangent);
+               m_rhs_tangent = velocity_error * m_tangentImpulseFactorInv;
+
+               if (m_collideMultibody)
+               {
+                       btScalar velocity_error2 = btDot(v_rel, m_contactTangent2);
+                       m_rhs_tangent2 = velocity_error2 * m_tangentImpulseFactorInv2;
+               }
+       }
+
+       // warm starting
+       // applyImpulse(m_rhs * m_contactNormalA);
+       // if (!m_collideStatic)
+       // {
+       //      const btSoftBody::sCti& cti = m_contact->m_cti;
+       //      if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+       //      {
+       //              m_solverBody->internalApplyImpulse(m_linearComponentNormal, m_angularComponentNormal, -m_rhs);
+       //      }
+       // }
+}
+
+btVector3 btReducedDeformableNodeRigidContactConstraint::getVb() const
+{
+       return m_node->m_v;
+}
+
+btVector3 btReducedDeformableNodeRigidContactConstraint::getDeltaVa() const
+{
+       btVector3 deltaVa(0, 0, 0);
+       if (!m_collideStatic)
+       {
+               if (!m_collideMultibody)                // for rigid body
+               {
+                       deltaVa = m_solverBody->internalGetDeltaLinearVelocity() + m_solverBody->internalGetDeltaAngularVelocity().cross(m_relPosA);
+               }
+               else            // for multibody
+               {
+                       btMultiBodyLinkCollider* multibodyLinkCol = 0;
+                       multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(m_contact->m_cti.m_colObj);
+                       if (multibodyLinkCol)
+                       {
+                               const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+                               const btScalar* J_n = &m_contact->jacobianData_normal.m_jacobians[0];
+                               const btScalar* J_t1 = &m_contact->jacobianData_t1.m_jacobians[0];
+                               const btScalar* J_t2 = &m_contact->jacobianData_t2.m_jacobians[0];
+                               const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
+                               // add in the normal component of the va
+                               btScalar vel = 0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += local_dv[k] * J_n[k];
+                               }
+                               deltaVa = m_contact->m_cti.m_normal * vel;
+                               
+                               // add in the tangential components of the va
+                               vel = 0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += local_dv[k] * J_t1[k];
+                               }
+                               deltaVa += m_contact->t1 * vel;
+
+                               vel = 0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += local_dv[k] * J_t2[k];
+                               }
+                               deltaVa += m_contact->t2 * vel;
+                       }
+               }
+       }
+       return deltaVa;
+}
+
+btVector3 btReducedDeformableNodeRigidContactConstraint::getDeltaVb() const
+{      
+       // std::cout << "node: " << m_node->index << '\n';
+       return m_rsb->internalComputeNodeDeltaVelocity(m_rsb->getInterpolationWorldTransform(), m_nodeQueryIndex);
+}
+
+btVector3 btReducedDeformableNodeRigidContactConstraint::getSplitVb() const
+{
+       return m_node->m_splitv;
+}
+
+btVector3 btReducedDeformableNodeRigidContactConstraint::getDv(const btSoftBody::Node* node) const
+{
+       return m_total_normal_dv + m_total_tangent_dv;
+}
+
+void btReducedDeformableNodeRigidContactConstraint::applyImpulse(const btVector3& impulse)
+{
+  m_rsb->internalApplyFullSpaceImpulse(impulse, m_relPosB, m_nodeQueryIndex, m_dt);
+       // m_rsb->applyFullSpaceImpulse(impulse, m_relPosB, m_node->index, m_dt);
+       // m_rsb->mapToFullVelocity(m_rsb->getInterpolationWorldTransform());
+       // if (!m_collideStatic)
+       // {
+       //      // std::cout << "impulse applied: " << impulse[0] << '\t' << impulse[1] << '\t' << impulse[2] << '\n';
+       //      // std::cout << "node: " << m_node->index << " vel: " << m_node->m_v[0] << '\t' << m_node->m_v[1] << '\t' << m_node->m_v[2] << '\n';
+       //      btVector3 v_after = getDeltaVb() + m_node->m_v;
+       //      // std::cout << "vel after: " << v_after[0] << '\t' << v_after[1] << '\t' << v_after[2] << '\n';
+       // }
+       // std::cout << "node: " << m_node->index << " pos: " << m_node->m_x[0] << '\t' << m_node->m_x[1] << '\t' << m_node->m_x[2] << '\n';
+}
+
+// ================= face vs rigid constraints ===================
+btReducedDeformableFaceRigidContactConstraint::btReducedDeformableFaceRigidContactConstraint(
+  btReducedDeformableBody* rsb, 
+  const btSoftBody::DeformableFaceRigidContact& contact, 
+  const btContactSolverInfo& infoGlobal,
+       btScalar dt, 
+  bool useStrainLimiting)
+  : m_face(contact.m_face), m_useStrainLimiting(useStrainLimiting), btReducedDeformableRigidContactConstraint(rsb, contact, infoGlobal, dt)
+{}
+
+btVector3 btReducedDeformableFaceRigidContactConstraint::getVb() const
+{
+       const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+       btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
+       return vb;
+}
+
+btVector3 btReducedDeformableFaceRigidContactConstraint::getSplitVb() const
+{
+       const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+       btVector3 vb = (m_face->m_n[0]->m_splitv) * contact->m_bary[0] + (m_face->m_n[1]->m_splitv) * contact->m_bary[1] + (m_face->m_n[2]->m_splitv) * contact->m_bary[2];
+       return vb;
+}
+
+btVector3 btReducedDeformableFaceRigidContactConstraint::getDv(const btSoftBody::Node* node) const
+{
+       btVector3 face_dv = m_total_normal_dv + m_total_tangent_dv;
+       const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+       if (m_face->m_n[0] == node)
+       {
+               return face_dv * contact->m_weights[0];
+       }
+       if (m_face->m_n[1] == node)
+       {
+               return face_dv * contact->m_weights[1];
+       }
+       btAssert(node == m_face->m_n[2]);
+       return face_dv * contact->m_weights[2];
+}
+
+void btReducedDeformableFaceRigidContactConstraint::applyImpulse(const btVector3& impulse)
+{
+  //
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableContactConstraint.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/BulletReducedDeformableBody/btReducedDeformableContactConstraint.h
new file mode 100644 (file)
index 0000000..10d0938
--- /dev/null
@@ -0,0 +1,194 @@
+#include "../btDeformableContactConstraint.h"
+#include "btReducedDeformableBody.h"
+
+// ================= static constraints ===================
+class btReducedDeformableStaticConstraint : public btDeformableStaticConstraint
+{
+ public:
+  btReducedDeformableBody* m_rsb;
+  btScalar m_dt;
+  btVector3 m_ri;
+  btVector3 m_targetPos;
+  btVector3 m_impulseDirection;
+  btMatrix3x3 m_impulseFactorMatrix;
+  btScalar m_impulseFactor;
+  btScalar m_rhs;
+  btScalar m_appliedImpulse;
+  btScalar m_erp;
+
+  btReducedDeformableStaticConstraint(btReducedDeformableBody* rsb, 
+                                      btSoftBody::Node* node,
+                                      const btVector3& ri,
+                                      const btVector3& x0,
+                                      const btVector3& dir,
+                                      const btContactSolverInfo& infoGlobal,
+                                      btScalar dt);
+       // btReducedDeformableStaticConstraint(const btReducedDeformableStaticConstraint& other);
+  btReducedDeformableStaticConstraint() {}
+  virtual ~btReducedDeformableStaticConstraint() {}
+
+  virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
+  
+  // this calls reduced deformable body's applyFullSpaceImpulse
+  virtual void applyImpulse(const btVector3& impulse);
+
+  btVector3 getDeltaVa() const;
+
+  // virtual void applySplitImpulse(const btVector3& impulse) {}
+};
+
+// ================= base contact constraints ===================
+class btReducedDeformableRigidContactConstraint : public btDeformableRigidContactConstraint
+{
+ public:
+  bool m_collideStatic;     // flag for collision with static object
+  bool m_collideMultibody;  // flag for collision with multibody
+
+  int m_nodeQueryIndex;
+  int m_solverBodyId;       // for debugging
+
+  btReducedDeformableBody* m_rsb;
+  btSolverBody* m_solverBody;
+  btScalar m_dt;
+
+  btScalar m_appliedNormalImpulse;
+  btScalar m_appliedTangentImpulse;
+  btScalar m_appliedTangentImpulse2;
+  btScalar m_normalImpulseFactor;
+  btScalar m_tangentImpulseFactor;
+  btScalar m_tangentImpulseFactor2;
+  btScalar m_tangentImpulseFactorInv;
+  btScalar m_tangentImpulseFactorInv2;
+  btScalar m_rhs;
+  btScalar m_rhs_tangent;
+  btScalar m_rhs_tangent2;
+  
+  btScalar m_cfm;
+  btScalar m_cfm_friction;
+  btScalar m_erp;
+  btScalar m_erp_friction;
+  btScalar m_friction;
+
+  btVector3 m_contactNormalA;     // surface normal for rigid body (opposite direction as impulse)
+  btVector3 m_contactNormalB;     // surface normal for reduced deformable body (opposite direction as impulse)
+  btVector3 m_contactTangent;     // tangential direction of the relative velocity
+  btVector3 m_contactTangent2;    // 2nd tangential direction of the relative velocity
+  btVector3 m_relPosA;            // relative position of the contact point for A (rigid)
+  btVector3 m_relPosB;            // relative position of the contact point for B
+  btMatrix3x3 m_impulseFactor;    // total impulse matrix
+
+  btVector3 m_bufferVelocityA;    // velocity at the beginning of the iteration
+  btVector3 m_bufferVelocityB;
+  btVector3 m_linearComponentNormal;    // linear components for the solver body
+  btVector3 m_angularComponentNormal;   // angular components for the solver body
+  // since 2nd contact direction only applies to multibody, these components will never be used
+  btVector3 m_linearComponentTangent;
+  btVector3 m_angularComponentTangent;
+
+  btReducedDeformableRigidContactConstraint(btReducedDeformableBody* rsb, 
+                                            const btSoftBody::DeformableRigidContact& c, 
+                                            const btContactSolverInfo& infoGlobal,
+                                            btScalar dt);
+       // btReducedDeformableRigidContactConstraint(const btReducedDeformableRigidContactConstraint& other);
+  btReducedDeformableRigidContactConstraint() {}
+  virtual ~btReducedDeformableRigidContactConstraint() {}
+
+  void setSolverBody(const int bodyId, btSolverBody& solver_body);
+
+  virtual void warmStarting() {}
+
+  virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
+
+  void calculateTangentialImpulse(btScalar& deltaImpulse_tangent, 
+                                  btScalar& appliedImpulse, 
+                                  const btScalar rhs_tangent,
+                                  const btScalar tangentImpulseFactorInv,
+                                  const btVector3& tangent,
+                                  const btScalar lower_limit,
+                                  const btScalar upper_limit,
+                                  const btVector3& deltaV_rel);
+
+  virtual void applyImpulse(const btVector3& impulse) {}
+
+  virtual void applySplitImpulse(const btVector3& impulse) {} // TODO: may need later
+
+  virtual btVector3 getVa() const;
+  virtual btVector3 getDeltaVa() const = 0;
+  virtual btVector3 getDeltaVb() const = 0;
+};
+
+// ================= node vs rigid constraints ===================
+class btReducedDeformableNodeRigidContactConstraint : public btReducedDeformableRigidContactConstraint
+{
+ public:
+  btSoftBody::Node* m_node;
+
+  btReducedDeformableNodeRigidContactConstraint(btReducedDeformableBody* rsb, 
+                                                const btSoftBody::DeformableNodeRigidContact& contact, 
+                                                const btContactSolverInfo& infoGlobal,
+                                                btScalar dt);
+       // btReducedDeformableNodeRigidContactConstraint(const btReducedDeformableNodeRigidContactConstraint& other);
+  btReducedDeformableNodeRigidContactConstraint() {}
+  virtual ~btReducedDeformableNodeRigidContactConstraint() {}
+
+  virtual void warmStarting();
+
+  // get the velocity of the deformable node in contact
+       virtual btVector3 getVb() const;
+
+  // get the velocity change of the rigid body
+  virtual btVector3 getDeltaVa() const;
+
+  // get velocity change of the node in contat
+  virtual btVector3 getDeltaVb() const;
+
+       // get the split impulse velocity of the deformable face at the contact point
+       virtual btVector3 getSplitVb() const;
+
+       // get the velocity change of the input soft body node in the constraint
+       virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+       // cast the contact to the desired type
+       const btSoftBody::DeformableNodeRigidContact* getContact() const
+       {
+               return static_cast<const btSoftBody::DeformableNodeRigidContact*>(m_contact);
+       }
+  
+  // this calls reduced deformable body's applyFullSpaceImpulse
+  virtual void applyImpulse(const btVector3& impulse);
+};
+
+// ================= face vs rigid constraints ===================
+class btReducedDeformableFaceRigidContactConstraint : public btReducedDeformableRigidContactConstraint
+{
+ public:
+  btSoftBody::Face* m_face;
+       bool m_useStrainLimiting;
+
+  btReducedDeformableFaceRigidContactConstraint(btReducedDeformableBody* rsb, 
+                                                const btSoftBody::DeformableFaceRigidContact& contact, 
+                                                const btContactSolverInfo& infoGlobal,
+                                                btScalar dt, 
+                                                bool useStrainLimiting);
+       // btReducedDeformableFaceRigidContactConstraint(const btReducedDeformableFaceRigidContactConstraint& other);
+  btReducedDeformableFaceRigidContactConstraint() {}
+  virtual ~btReducedDeformableFaceRigidContactConstraint() {}
+
+  // get the velocity of the deformable face at the contact point
+       virtual btVector3 getVb() const;
+
+       // get the split impulse velocity of the deformable face at the contact point
+       virtual btVector3 getSplitVb() const;
+
+       // get the velocity change of the input soft body node in the constraint
+       virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+       // cast the contact to the desired type
+       const btSoftBody::DeformableFaceRigidContact* getContact() const
+       {
+               return static_cast<const btSoftBody::DeformableFaceRigidContact*>(m_contact);
+       }
+
+  // this calls reduced deformable body's applyFullSpaceImpulse
+  virtual void applyImpulse(const btVector3& impulse);
+};
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/CMakeLists.txt b/dali-physics/third-party/bullet3/src/BulletSoftBody/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c12eef5
--- /dev/null
@@ -0,0 +1,107 @@
+
+INCLUDE_DIRECTORIES(
+${BULLET_PHYSICS_SOURCE_DIR}/src
+
+)
+
+#SUBDIRS( Solvers )
+
+SET(BulletSoftBody_SRCS
+       btSoftBody.cpp
+       btSoftBodyConcaveCollisionAlgorithm.cpp
+       btSoftBodyHelpers.cpp
+       btSoftBodyRigidBodyCollisionConfiguration.cpp
+       btSoftRigidCollisionAlgorithm.cpp
+       btSoftRigidDynamicsWorld.cpp
+       btSoftMultiBodyDynamicsWorld.cpp
+       btSoftSoftCollisionAlgorithm.cpp
+       btDefaultSoftBodySolver.cpp
+
+       btDeformableBackwardEulerObjective.cpp
+       btDeformableBodySolver.cpp
+       btDeformableMultiBodyConstraintSolver.cpp
+       btDeformableContactProjection.cpp
+       btDeformableMultiBodyDynamicsWorld.cpp
+       btDeformableContactConstraint.cpp
+       poly34.cpp
+
+       BulletReducedDeformableBody/btReducedDeformableBody.cpp
+       BulletReducedDeformableBody/btReducedDeformableBodyHelpers.cpp
+       BulletReducedDeformableBody/btReducedDeformableBodySolver.cpp
+       BulletReducedDeformableBody/btReducedDeformableContactConstraint.cpp
+)
+
+
+SET(BulletSoftBody_HDRS
+       btSoftBody.h
+       btSoftBodyData.h
+       btSoftBodyConcaveCollisionAlgorithm.h
+       btSoftBodyHelpers.h
+       btSoftBodyRigidBodyCollisionConfiguration.h
+       btSoftRigidCollisionAlgorithm.h
+       btSoftRigidDynamicsWorld.h
+       btSoftMultiBodyDynamicsWorld.h
+       btSoftSoftCollisionAlgorithm.h
+       btSparseSDF.h
+
+       btSoftBodySolvers.h
+       btDefaultSoftBodySolver.h
+       
+       btCGProjection.h
+       btConjugateGradient.h
+       btConjugateResidual.h
+       btDeformableGravityForce.h
+       btDeformableMassSpringForce.h
+       btDeformableCorotatedForce.h
+       btDeformableNeoHookeanForce.h
+       btDeformableLinearElasticityForce.h
+       btDeformableLagrangianForce.h
+       btPreconditioner.h
+
+       btDeformableBackwardEulerObjective.h
+       btDeformableBodySolver.h
+       btDeformableMultiBodyConstraintSolver.h
+       btDeformableContactProjection.h
+       btDeformableMultiBodyDynamicsWorld.h
+       btDeformableContactConstraint.h
+       btKrylovSolver.h
+       poly34.h
+
+       btSoftBodySolverVertexBuffer.h
+
+       BulletReducedDeformableBody/btReducedDeformableBody.h
+       BulletReducedDeformableBody/btReducedDeformableBodyHelpers.h
+       BulletReducedDeformableBody/btReducedDeformableBodySolver.h
+       BulletReducedDeformableBody/btReducedDeformableContactConstraint.h
+)
+
+
+
+ADD_LIBRARY(BulletSoftBody  ${BulletSoftBody_SRCS} ${BulletSoftBody_HDRS})
+SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES SOVERSION ${BULLET_VERSION})
+IF (BUILD_SHARED_LIBS)
+       TARGET_LINK_LIBRARIES(BulletSoftBody BulletDynamics)
+ENDIF (BUILD_SHARED_LIBS)
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS BulletSoftBody DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       INSTALL(TARGETS BulletSoftBody RUNTIME DESTINATION bin
+                                                       LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                                       ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h"  PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES FRAMEWORK true)
+                       SET_TARGET_PROPERTIES(BulletSoftBody PROPERTIES PUBLIC_HEADER "${BulletSoftBody_HDRS}")
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h
new file mode 100644 (file)
index 0000000..01c7e93
--- /dev/null
@@ -0,0 +1,45 @@
+//
+//  DeformableBodyInplaceSolverIslandCallback.h
+//  BulletSoftBody
+//
+//  Created by Xuchen Han on 12/16/19.
+//
+
+#ifndef DeformableBodyInplaceSolverIslandCallback_h
+#define DeformableBodyInplaceSolverIslandCallback_h
+
+struct DeformableBodyInplaceSolverIslandCallback : public MultiBodyInplaceSolverIslandCallback
+{
+       btDeformableMultiBodyConstraintSolver* m_deformableSolver;
+
+       DeformableBodyInplaceSolverIslandCallback(btDeformableMultiBodyConstraintSolver* solver,
+                                                                                         btDispatcher* dispatcher)
+               : MultiBodyInplaceSolverIslandCallback(solver, dispatcher), m_deformableSolver(solver)
+       {
+       }
+
+       virtual void processConstraints(int islandId = -1)
+       {
+               btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
+               btCollisionObject** softBodies = m_softBodies.size() ? &m_softBodies[0] : 0;
+               btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
+               btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
+               btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
+
+               //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
+
+               m_deformableSolver->solveDeformableBodyGroup(bodies, m_bodies.size(), softBodies, m_softBodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
+               if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics & 1))
+               {
+                       m_deformableSolver->m_analyticsData.m_islandId = islandId;
+                       m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
+               }
+               m_bodies.resize(0);
+               m_softBodies.resize(0);
+               m_manifolds.resize(0);
+               m_constraints.resize(0);
+               m_multiBodyConstraints.resize(0);
+       }
+};
+
+#endif /* DeformableBodyInplaceSolverIslandCallback_h */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btCGProjection.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btCGProjection.h
new file mode 100644 (file)
index 0000000..e059706
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_CG_PROJECTION_H
+#define BT_CG_PROJECTION_H
+
+#include "btSoftBody.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+
+struct DeformableContactConstraint
+{
+       const btSoftBody::Node* m_node;
+       btAlignedObjectArray<const btSoftBody::RContact*> m_contact;
+       btAlignedObjectArray<btVector3> m_total_normal_dv;
+       btAlignedObjectArray<btVector3> m_total_tangent_dv;
+       btAlignedObjectArray<bool> m_static;
+       btAlignedObjectArray<bool> m_can_be_dynamic;
+
+       DeformableContactConstraint(const btSoftBody::RContact& rcontact) : m_node(rcontact.m_node)
+       {
+               append(rcontact);
+       }
+
+       DeformableContactConstraint() : m_node(NULL)
+       {
+               m_contact.push_back(NULL);
+       }
+
+       void append(const btSoftBody::RContact& rcontact)
+       {
+               m_contact.push_back(&rcontact);
+               m_total_normal_dv.push_back(btVector3(0, 0, 0));
+               m_total_tangent_dv.push_back(btVector3(0, 0, 0));
+               m_static.push_back(false);
+               m_can_be_dynamic.push_back(true);
+       }
+
+       void replace(const btSoftBody::RContact& rcontact)
+       {
+               m_contact.clear();
+               m_total_normal_dv.clear();
+               m_total_tangent_dv.clear();
+               m_static.clear();
+               m_can_be_dynamic.clear();
+               append(rcontact);
+       }
+
+       ~DeformableContactConstraint()
+       {
+       }
+};
+
+class btCGProjection
+{
+public:
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       typedef btAlignedObjectArray<btAlignedObjectArray<btVector3> > TVArrayStack;
+       typedef btAlignedObjectArray<btAlignedObjectArray<btScalar> > TArrayStack;
+       btAlignedObjectArray<btSoftBody*>& m_softBodies;
+       const btScalar& m_dt;
+       // map from node indices to node pointers
+       const btAlignedObjectArray<btSoftBody::Node*>* m_nodes;
+
+       btCGProjection(btAlignedObjectArray<btSoftBody*>& softBodies, const btScalar& dt)
+               : m_softBodies(softBodies), m_dt(dt)
+       {
+       }
+
+       virtual ~btCGProjection()
+       {
+       }
+
+       // apply the constraints
+       virtual void project(TVStack& x) = 0;
+
+       virtual void setConstraints() = 0;
+
+       // update the constraints
+       virtual btScalar update() = 0;
+
+       virtual void reinitialize(bool nodeUpdated)
+       {
+       }
+
+       virtual void setIndices(const btAlignedObjectArray<btSoftBody::Node*>* nodes)
+       {
+               m_nodes = nodes;
+       }
+};
+
+#endif /* btCGProjection_h */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btConjugateGradient.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btConjugateGradient.h
new file mode 100644 (file)
index 0000000..bcd5e6b
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_CONJUGATE_GRADIENT_H
+#define BT_CONJUGATE_GRADIENT_H
+#include "btKrylovSolver.h"
+template <class MatrixX>
+class btConjugateGradient : public btKrylovSolver<MatrixX>
+{
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       typedef btKrylovSolver<MatrixX> Base;
+       TVStack r, p, z, temp;
+
+public:
+       btConjugateGradient(const int max_it_in)
+               : btKrylovSolver<MatrixX>(max_it_in, SIMD_EPSILON)
+       {
+       }
+
+       virtual ~btConjugateGradient() {}
+
+       // return the number of iterations taken
+       int solve(MatrixX& A, TVStack& x, const TVStack& b, bool verbose = false)
+       {
+               BT_PROFILE("CGSolve");
+               btAssert(x.size() == b.size());
+               reinitialize(b);
+               temp = b;
+               A.project(temp);
+               p = temp;
+               A.precondition(p, z);
+               btScalar d0 = this->dot(z, temp);
+               d0 = btMin(btScalar(1), d0);
+               // r = b - A * x --with assigned dof zeroed out
+               A.multiply(x, temp);
+               r = this->sub(b, temp);
+               A.project(r);
+               // z = M^(-1) * r
+               A.precondition(r, z);
+               A.project(z);
+               btScalar r_dot_z = this->dot(z, r);
+               if (r_dot_z <= Base::m_tolerance * d0)
+               {
+                       if (verbose)
+                       {
+                               std::cout << "Iteration = 0" << std::endl;
+                               std::cout << "Two norm of the residual = " << r_dot_z << std::endl;
+                       }
+                       return 0;
+               }
+               p = z;
+               btScalar r_dot_z_new = r_dot_z;
+               for (int k = 1; k <= Base::m_maxIterations; k++)
+               {
+                       // temp = A*p
+                       A.multiply(p, temp);
+                       A.project(temp);
+                       if (this->dot(p, temp) < 0)
+                       {
+                               if (verbose)
+                                       std::cout << "Encountered negative direction in CG!" << std::endl;
+                               if (k == 1)
+                               {
+                                       x = b;
+                               }
+                               return k;
+                       }
+                       // alpha = r^T * z / (p^T * A * p)
+                       btScalar alpha = r_dot_z_new / this->dot(p, temp);
+                       //  x += alpha * p;
+                       this->multAndAddTo(alpha, p, x);
+                       //  r -= alpha * temp;
+                       this->multAndAddTo(-alpha, temp, r);
+                       // z = M^(-1) * r
+                       A.precondition(r, z);
+                       r_dot_z = r_dot_z_new;
+                       r_dot_z_new = this->dot(r, z);
+                       if (r_dot_z_new < Base::m_tolerance * d0)
+                       {
+                               if (verbose)
+                               {
+                                       std::cout << "ConjugateGradient iterations " << k << " residual = " << r_dot_z_new << std::endl;
+                               }
+                               return k;
+                       }
+
+                       btScalar beta = r_dot_z_new / r_dot_z;
+                       p = this->multAndAdd(beta, p, z);
+               }
+               if (verbose)
+               {
+                       std::cout << "ConjugateGradient max iterations reached " << Base::m_maxIterations << " error = " << r_dot_z_new << std::endl;
+               }
+               return Base::m_maxIterations;
+       }
+
+       void reinitialize(const TVStack& b)
+       {
+               r.resize(b.size());
+               p.resize(b.size());
+               z.resize(b.size());
+               temp.resize(b.size());
+       }
+};
+#endif /* btConjugateGradient_h */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btConjugateResidual.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btConjugateResidual.h
new file mode 100644 (file)
index 0000000..6146120
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_CONJUGATE_RESIDUAL_H
+#define BT_CONJUGATE_RESIDUAL_H
+#include "btKrylovSolver.h"
+
+template <class MatrixX>
+class btConjugateResidual : public btKrylovSolver<MatrixX>
+{
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       typedef btKrylovSolver<MatrixX> Base;
+       TVStack r, p, z, temp_p, temp_r, best_x;
+       // temp_r = A*r
+       // temp_p = A*p
+       // z = M^(-1) * temp_p = M^(-1) * A * p
+       btScalar best_r;
+
+public:
+       btConjugateResidual(const int max_it_in)
+               : Base(max_it_in, 1e-8)
+       {
+       }
+
+       virtual ~btConjugateResidual() {}
+
+       // return the number of iterations taken
+       int solve(MatrixX& A, TVStack& x, const TVStack& b, bool verbose = false)
+       {
+               BT_PROFILE("CRSolve");
+               btAssert(x.size() == b.size());
+               reinitialize(b);
+               // r = b - A * x --with assigned dof zeroed out
+               A.multiply(x, temp_r);  // borrow temp_r here to store A*x
+               r = this->sub(b, temp_r);
+               // z = M^(-1) * r
+               A.precondition(r, z);  // borrow z to store preconditioned r
+               r = z;
+               btScalar residual_norm = this->norm(r);
+               if (residual_norm <= Base::m_tolerance)
+               {
+                       return 0;
+               }
+               p = r;
+               btScalar r_dot_Ar, r_dot_Ar_new;
+               // temp_p = A*p
+               A.multiply(p, temp_p);
+               // temp_r = A*r
+               temp_r = temp_p;
+               r_dot_Ar = this->dot(r, temp_r);
+               for (int k = 1; k <= Base::m_maxIterations; k++)
+               {
+                       // z = M^(-1) * Ap
+                       A.precondition(temp_p, z);
+                       // alpha = r^T * A * r / (Ap)^T * M^-1 * Ap)
+                       btScalar alpha = r_dot_Ar / this->dot(temp_p, z);
+                       //  x += alpha * p;
+                       this->multAndAddTo(alpha, p, x);
+                       //  r -= alpha * z;
+                       this->multAndAddTo(-alpha, z, r);
+                       btScalar norm_r = this->norm(r);
+                       if (norm_r < best_r)
+                       {
+                               best_x = x;
+                               best_r = norm_r;
+                               if (norm_r < Base::m_tolerance)
+                               {
+                                       return k;
+                               }
+                       }
+                       // temp_r = A * r;
+                       A.multiply(r, temp_r);
+                       r_dot_Ar_new = this->dot(r, temp_r);
+                       btScalar beta = r_dot_Ar_new / r_dot_Ar;
+                       r_dot_Ar = r_dot_Ar_new;
+                       // p = beta*p + r;
+                       p = this->multAndAdd(beta, p, r);
+                       // temp_p = beta*temp_p + temp_r;
+                       temp_p = this->multAndAdd(beta, temp_p, temp_r);
+               }
+               if (verbose)
+               {
+                       std::cout << "ConjugateResidual max iterations reached, residual = " << best_r << std::endl;
+               }
+               x = best_x;
+               return Base::m_maxIterations;
+       }
+
+       void reinitialize(const TVStack& b)
+       {
+               r.resize(b.size());
+               p.resize(b.size());
+               z.resize(b.size());
+               temp_p.resize(b.size());
+               temp_r.resize(b.size());
+               best_x.resize(b.size());
+               best_r = SIMD_INFINITY;
+       }
+};
+#endif /* btConjugateResidual_h */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDefaultSoftBodySolver.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDefaultSoftBodySolver.cpp
new file mode 100644 (file)
index 0000000..acbf515
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+
+#include "btDefaultSoftBodySolver.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletSoftBody/btSoftBody.h"
+
+btDefaultSoftBodySolver::btDefaultSoftBodySolver()
+{
+       // Initial we will clearly need to update solver constants
+       // For now this is global for the cloths linked with this solver - we should probably make this body specific
+       // for performance in future once we understand more clearly when constants need to be updated
+       m_updateSolverConstants = true;
+}
+
+btDefaultSoftBodySolver::~btDefaultSoftBodySolver()
+{
+}
+
+// In this case the data is already in the soft bodies so there is no need for us to do anything
+void btDefaultSoftBodySolver::copyBackToSoftBodies(bool bMove)
+{
+}
+
+void btDefaultSoftBodySolver::optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate)
+{
+       m_softBodySet.copyFromArray(softBodies);
+}
+
+void btDefaultSoftBodySolver::updateSoftBodies()
+{
+       for (int i = 0; i < m_softBodySet.size(); i++)
+       {
+               btSoftBody *psb = (btSoftBody *)m_softBodySet[i];
+               if (psb->isActive())
+               {
+                       psb->integrateMotion();
+               }
+       }
+}  // updateSoftBodies
+
+bool btDefaultSoftBodySolver::checkInitialized()
+{
+       return true;
+}
+
+void btDefaultSoftBodySolver::solveConstraints(btScalar solverdt)
+{
+       // Solve constraints for non-solver softbodies
+       for (int i = 0; i < m_softBodySet.size(); ++i)
+       {
+               btSoftBody *psb = static_cast<btSoftBody *>(m_softBodySet[i]);
+               if (psb->isActive())
+               {
+                       psb->solveConstraints();
+               }
+       }
+}  // btDefaultSoftBodySolver::solveConstraints
+
+void btDefaultSoftBodySolver::copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer)
+{
+       // Currently only support CPU output buffers
+       // TODO: check for DX11 buffers. Take all offsets into the same DX11 buffer
+       // and use them together on a single kernel call if possible by setting up a
+       // per-cloth target buffer array for the copy kernel.
+
+       if (vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER)
+       {
+               const btAlignedObjectArray<btSoftBody::Node> &clothVertices(softBody->m_nodes);
+               int numVertices = clothVertices.size();
+
+               const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast<btCPUVertexBufferDescriptor *>(vertexBuffer);
+               float *basePointer = cpuVertexBuffer->getBasePointer();
+
+               if (vertexBuffer->hasVertexPositions())
+               {
+                       const int vertexOffset = cpuVertexBuffer->getVertexOffset();
+                       const int vertexStride = cpuVertexBuffer->getVertexStride();
+                       float *vertexPointer = basePointer + vertexOffset;
+
+                       for (int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
+                       {
+                               btVector3 position = clothVertices[vertexIndex].m_x;
+                               *(vertexPointer + 0) = (float)position.getX();
+                               *(vertexPointer + 1) = (float)position.getY();
+                               *(vertexPointer + 2) = (float)position.getZ();
+                               vertexPointer += vertexStride;
+                       }
+               }
+               if (vertexBuffer->hasNormals())
+               {
+                       const int normalOffset = cpuVertexBuffer->getNormalOffset();
+                       const int normalStride = cpuVertexBuffer->getNormalStride();
+                       float *normalPointer = basePointer + normalOffset;
+
+                       for (int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
+                       {
+                               btVector3 normal = clothVertices[vertexIndex].m_n;
+                               *(normalPointer + 0) = (float)normal.getX();
+                               *(normalPointer + 1) = (float)normal.getY();
+                               *(normalPointer + 2) = (float)normal.getZ();
+                               normalPointer += normalStride;
+                       }
+               }
+       }
+}  // btDefaultSoftBodySolver::copySoftBodyToVertexBuffer
+
+void btDefaultSoftBodySolver::processCollision(btSoftBody *softBody, btSoftBody *otherSoftBody)
+{
+       softBody->defaultCollisionHandler(otherSoftBody);
+}
+
+// For the default solver just leave the soft body to do its collision processing
+void btDefaultSoftBodySolver::processCollision(btSoftBody *softBody, const btCollisionObjectWrapper *collisionObjectWrap)
+{
+       softBody->defaultCollisionHandler(collisionObjectWrap);
+}  // btDefaultSoftBodySolver::processCollision
+
+void btDefaultSoftBodySolver::predictMotion(btScalar timeStep)
+{
+       for (int i = 0; i < m_softBodySet.size(); ++i)
+       {
+               btSoftBody *psb = m_softBodySet[i];
+
+               if (psb->isActive())
+               {
+                       psb->predictMotion(timeStep);
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDefaultSoftBodySolver.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDefaultSoftBodySolver.h
new file mode 100644 (file)
index 0000000..d54edca
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SOFT_BODY_DEFAULT_SOLVER_H
+#define BT_SOFT_BODY_DEFAULT_SOLVER_H
+
+#include "BulletSoftBody/btSoftBodySolvers.h"
+#include "btSoftBodySolverVertexBuffer.h"
+struct btCollisionObjectWrapper;
+
+class btDefaultSoftBodySolver : public btSoftBodySolver
+{
+protected:
+       /** Variable to define whether we need to update solver constants on the next iteration */
+       bool m_updateSolverConstants;
+
+       btAlignedObjectArray<btSoftBody *> m_softBodySet;
+
+public:
+       btDefaultSoftBodySolver();
+
+       virtual ~btDefaultSoftBodySolver();
+
+       virtual SolverTypes getSolverType() const
+       {
+               return DEFAULT_SOLVER;
+       }
+
+       virtual bool checkInitialized();
+
+       virtual void updateSoftBodies();
+
+       virtual void optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate = false);
+
+       virtual void copyBackToSoftBodies(bool bMove = true);
+
+       virtual void solveConstraints(btScalar solverdt);
+
+       virtual void predictMotion(btScalar solverdt);
+
+       virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer);
+
+       virtual void processCollision(btSoftBody *, const btCollisionObjectWrapper *);
+
+       virtual void processCollision(btSoftBody *, btSoftBody *);
+};
+
+#endif  // #ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBackwardEulerObjective.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBackwardEulerObjective.cpp
new file mode 100644 (file)
index 0000000..2455ed2
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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 "btDeformableBackwardEulerObjective.h"
+#include "btPreconditioner.h"
+#include "LinearMath/btQuickprof.h"
+
+btDeformableBackwardEulerObjective::btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody*>& softBodies, const TVStack& backup_v)
+       : m_softBodies(softBodies), m_projection(softBodies), m_backupVelocity(backup_v), m_implicit(false)
+{
+       m_massPreconditioner = new MassPreconditioner(m_softBodies);
+       m_KKTPreconditioner = new KKTPreconditioner(m_softBodies, m_projection, m_lf, m_dt, m_implicit);
+       m_preconditioner = m_KKTPreconditioner;
+}
+
+btDeformableBackwardEulerObjective::~btDeformableBackwardEulerObjective()
+{
+       delete m_KKTPreconditioner;
+       delete m_massPreconditioner;
+}
+
+void btDeformableBackwardEulerObjective::reinitialize(bool nodeUpdated, btScalar dt)
+{
+       BT_PROFILE("reinitialize");
+       if (dt > 0)
+       {
+               setDt(dt);
+       }
+       if (nodeUpdated)
+       {
+               updateId();
+       }
+       for (int i = 0; i < m_lf.size(); ++i)
+       {
+               m_lf[i]->reinitialize(nodeUpdated);
+       }
+       btMatrix3x3 I;
+       I.setIdentity();
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       if (psb->m_nodes[j].m_im > 0)
+                               psb->m_nodes[j].m_effectiveMass = I * (1.0 / psb->m_nodes[j].m_im);
+               }
+       }
+       m_projection.reinitialize(nodeUpdated);
+       //    m_preconditioner->reinitialize(nodeUpdated);
+}
+
+void btDeformableBackwardEulerObjective::setDt(btScalar dt)
+{
+       m_dt = dt;
+}
+
+void btDeformableBackwardEulerObjective::multiply(const TVStack& x, TVStack& b) const
+{
+       BT_PROFILE("multiply");
+       // add in the mass term
+       size_t counter = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       const btSoftBody::Node& node = psb->m_nodes[j];
+                       b[counter] = (node.m_im == 0) ? btVector3(0, 0, 0) : x[counter] / node.m_im;
+                       ++counter;
+               }
+       }
+
+       for (int i = 0; i < m_lf.size(); ++i)
+       {
+               // add damping matrix
+               m_lf[i]->addScaledDampingForceDifferential(-m_dt, x, b);
+        // Always integrate picking force implicitly for stability.
+        if (m_implicit || m_lf[i]->getForceType() == BT_MOUSE_PICKING_FORCE)
+               {
+                       m_lf[i]->addScaledElasticForceDifferential(-m_dt * m_dt, x, b);
+               }
+       }
+       int offset = m_nodes.size();
+       for (int i = offset; i < b.size(); ++i)
+       {
+               b[i].setZero();
+       }
+       // add in the lagrange multiplier terms
+
+       for (int c = 0; c < m_projection.m_lagrangeMultipliers.size(); ++c)
+       {
+               // C^T * lambda
+               const LagrangeMultiplier& lm = m_projection.m_lagrangeMultipliers[c];
+               for (int i = 0; i < lm.m_num_nodes; ++i)
+               {
+                       for (int j = 0; j < lm.m_num_constraints; ++j)
+                       {
+                               b[lm.m_indices[i]] += x[offset + c][j] * lm.m_weights[i] * lm.m_dirs[j];
+                       }
+               }
+               // C * x
+               for (int d = 0; d < lm.m_num_constraints; ++d)
+               {
+                       for (int i = 0; i < lm.m_num_nodes; ++i)
+                       {
+                               b[offset + c][d] += lm.m_weights[i] * x[lm.m_indices[i]].dot(lm.m_dirs[d]);
+                       }
+               }
+       }
+}
+
+void btDeformableBackwardEulerObjective::updateVelocity(const TVStack& dv)
+{
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       btSoftBody::Node& node = psb->m_nodes[j];
+                       node.m_v = m_backupVelocity[node.index] + dv[node.index];
+               }
+       }
+}
+
+void btDeformableBackwardEulerObjective::applyForce(TVStack& force, bool setZero)
+{
+       size_t counter = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (!psb->isActive())
+               {
+                       counter += psb->m_nodes.size();
+                       continue;
+               }
+               if (m_implicit)
+               {
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               if (psb->m_nodes[j].m_im != 0)
+                               {
+                                       psb->m_nodes[j].m_v += psb->m_nodes[j].m_effectiveMass_inv * force[counter++];
+                               }
+                       }
+               }
+               else
+               {
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               btScalar one_over_mass = (psb->m_nodes[j].m_im == 0) ? 0 : psb->m_nodes[j].m_im;
+                               psb->m_nodes[j].m_v += one_over_mass * force[counter++];
+                       }
+               }
+       }
+       if (setZero)
+       {
+               for (int i = 0; i < force.size(); ++i)
+                       force[i].setZero();
+       }
+}
+
+void btDeformableBackwardEulerObjective::computeResidual(btScalar dt, TVStack& residual)
+{
+       BT_PROFILE("computeResidual");
+       // add implicit force
+       for (int i = 0; i < m_lf.size(); ++i)
+       {
+        // Always integrate picking force implicitly for stability.
+               if (m_implicit || m_lf[i]->getForceType() == BT_MOUSE_PICKING_FORCE)
+               {
+                       m_lf[i]->addScaledForces(dt, residual);
+               }
+               else
+               {
+                       m_lf[i]->addScaledDampingForce(dt, residual);
+               }
+       }
+       //    m_projection.project(residual);
+}
+
+btScalar btDeformableBackwardEulerObjective::computeNorm(const TVStack& residual) const
+{
+       btScalar mag = 0;
+       for (int i = 0; i < residual.size(); ++i)
+       {
+               mag += residual[i].length2();
+       }
+       return std::sqrt(mag);
+}
+
+btScalar btDeformableBackwardEulerObjective::totalEnergy(btScalar dt)
+{
+       btScalar e = 0;
+       for (int i = 0; i < m_lf.size(); ++i)
+       {
+               e += m_lf[i]->totalEnergy(dt);
+       }
+       return e;
+}
+
+void btDeformableBackwardEulerObjective::applyExplicitForce(TVStack& force)
+{
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               m_softBodies[i]->advanceDeformation();
+       }
+       if (m_implicit)
+       {
+               // apply forces except gravity force
+               btVector3 gravity;
+               for (int i = 0; i < m_lf.size(); ++i)
+               {
+                       if (m_lf[i]->getForceType() == BT_GRAVITY_FORCE)
+                       {
+                               gravity = static_cast<btDeformableGravityForce*>(m_lf[i])->m_gravity;
+                       }
+                       else
+                       {
+                               m_lf[i]->addScaledForces(m_dt, force);
+                       }
+               }
+               for (int i = 0; i < m_lf.size(); ++i)
+               {
+                       m_lf[i]->addScaledHessian(m_dt);
+               }
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (psb->isActive())
+                       {
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                               {
+                                       // add gravity explicitly
+                                       psb->m_nodes[j].m_v += m_dt * psb->m_gravityFactor * gravity;
+                               }
+                       }
+               }
+       }
+       else
+       {
+               for (int i = 0; i < m_lf.size(); ++i)
+               {
+                       m_lf[i]->addScaledExplicitForce(m_dt, force);
+               }
+       }
+       // calculate inverse mass matrix for all nodes
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (psb->isActive())
+               {
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               if (psb->m_nodes[j].m_im > 0)
+                               {
+                                       psb->m_nodes[j].m_effectiveMass_inv = psb->m_nodes[j].m_effectiveMass.inverse();
+                               }
+                       }
+               }
+       }
+       applyForce(force, true);
+}
+
+void btDeformableBackwardEulerObjective::initialGuess(TVStack& dv, const TVStack& residual)
+{
+       size_t counter = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       dv[counter] = psb->m_nodes[j].m_im * residual[counter];
+                       ++counter;
+               }
+       }
+}
+
+//set constraints as projections
+void btDeformableBackwardEulerObjective::setConstraints(const btContactSolverInfo& infoGlobal)
+{
+       m_projection.setConstraints(infoGlobal);
+}
+
+void btDeformableBackwardEulerObjective::applyDynamicFriction(TVStack& r)
+{
+       m_projection.applyDynamicFriction(r);
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBackwardEulerObjective.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBackwardEulerObjective.h
new file mode 100644 (file)
index 0000000..60b6fe3
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_BACKWARD_EULER_OBJECTIVE_H
+#define BT_BACKWARD_EULER_OBJECTIVE_H
+//#include "btConjugateGradient.h"
+#include "btDeformableLagrangianForce.h"
+#include "btDeformableMassSpringForce.h"
+#include "btDeformableGravityForce.h"
+#include "btDeformableCorotatedForce.h"
+#include "btDeformableMousePickingForce.h"
+#include "btDeformableLinearElasticityForce.h"
+#include "btDeformableNeoHookeanForce.h"
+#include "btDeformableContactProjection.h"
+#include "btPreconditioner.h"
+// #include "btDeformableMultiBodyDynamicsWorld.h"
+#include "LinearMath/btQuickprof.h"
+
+class btDeformableBackwardEulerObjective
+{
+public:
+       enum _
+       {
+               Mass_preconditioner,
+               KKT_preconditioner
+       };
+
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       btScalar m_dt;
+       btAlignedObjectArray<btDeformableLagrangianForce*> m_lf;
+       btAlignedObjectArray<btSoftBody*>& m_softBodies;
+       Preconditioner* m_preconditioner;
+       btDeformableContactProjection m_projection;
+       const TVStack& m_backupVelocity;
+       btAlignedObjectArray<btSoftBody::Node*> m_nodes;
+       bool m_implicit;
+       MassPreconditioner* m_massPreconditioner;
+       KKTPreconditioner* m_KKTPreconditioner;
+
+       btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody*>& softBodies, const TVStack& backup_v);
+
+       virtual ~btDeformableBackwardEulerObjective();
+
+       void initialize() {}
+
+       // compute the rhs for CG solve, i.e, add the dt scaled implicit force to residual
+       void computeResidual(btScalar dt, TVStack& residual);
+
+       // add explicit force to the velocity
+       void applyExplicitForce(TVStack& force);
+
+       // apply force to velocity and optionally reset the force to zero
+       void applyForce(TVStack& force, bool setZero);
+
+       // compute the norm of the residual
+       btScalar computeNorm(const TVStack& residual) const;
+
+       // compute one step of the solve (there is only one solve if the system is linear)
+       void computeStep(TVStack& dv, const TVStack& residual, const btScalar& dt);
+
+       // perform A*x = b
+       void multiply(const TVStack& x, TVStack& b) const;
+
+       // set initial guess for CG solve
+       void initialGuess(TVStack& dv, const TVStack& residual);
+
+       // reset data structure and reset dt
+       void reinitialize(bool nodeUpdated, btScalar dt);
+
+       void setDt(btScalar dt);
+
+       // add friction force to residual
+       void applyDynamicFriction(TVStack& r);
+
+       // add dv to velocity
+       void updateVelocity(const TVStack& dv);
+
+       //set constraints as projections
+       void setConstraints(const btContactSolverInfo& infoGlobal);
+
+       // update the projections and project the residual
+       void project(TVStack& r)
+       {
+               BT_PROFILE("project");
+               m_projection.project(r);
+       }
+
+       // perform precondition M^(-1) x = b
+       void precondition(const TVStack& x, TVStack& b)
+       {
+               m_preconditioner->operator()(x, b);
+       }
+
+       // reindex all the vertices
+       virtual void updateId()
+       {
+               size_t node_id = 0;
+               size_t face_id = 0;
+               m_nodes.clear();
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               psb->m_nodes[j].index = node_id;
+                               m_nodes.push_back(&psb->m_nodes[j]);
+                               ++node_id;
+                       }
+                       for (int j = 0; j < psb->m_faces.size(); ++j)
+                       {
+                               psb->m_faces[j].m_index = face_id;
+                               ++face_id;
+                       }
+               }
+       }
+
+       const btAlignedObjectArray<btSoftBody::Node*>* getIndices() const
+       {
+               return &m_nodes;
+       }
+
+       void setImplicit(bool implicit)
+       {
+               m_implicit = implicit;
+       }
+
+       // Calculate the total potential energy in the system
+       btScalar totalEnergy(btScalar dt);
+
+       void addLagrangeMultiplier(const TVStack& vec, TVStack& extended_vec)
+       {
+               extended_vec.resize(vec.size() + m_projection.m_lagrangeMultipliers.size());
+               for (int i = 0; i < vec.size(); ++i)
+               {
+                       extended_vec[i] = vec[i];
+               }
+               int offset = vec.size();
+               for (int i = 0; i < m_projection.m_lagrangeMultipliers.size(); ++i)
+               {
+                       extended_vec[offset + i].setZero();
+               }
+       }
+
+       void addLagrangeMultiplierRHS(const TVStack& residual, const TVStack& m_dv, TVStack& extended_residual)
+       {
+               extended_residual.resize(residual.size() + m_projection.m_lagrangeMultipliers.size());
+               for (int i = 0; i < residual.size(); ++i)
+               {
+                       extended_residual[i] = residual[i];
+               }
+               int offset = residual.size();
+               for (int i = 0; i < m_projection.m_lagrangeMultipliers.size(); ++i)
+               {
+                       const LagrangeMultiplier& lm = m_projection.m_lagrangeMultipliers[i];
+                       extended_residual[offset + i].setZero();
+                       for (int d = 0; d < lm.m_num_constraints; ++d)
+                       {
+                               for (int n = 0; n < lm.m_num_nodes; ++n)
+                               {
+                                       extended_residual[offset + i][d] += lm.m_weights[n] * m_dv[lm.m_indices[n]].dot(lm.m_dirs[d]);
+                               }
+                       }
+               }
+       }
+
+       void calculateContactForce(const TVStack& dv, const TVStack& rhs, TVStack& f)
+       {
+               size_t counter = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               const btSoftBody::Node& node = psb->m_nodes[j];
+                               f[counter] = (node.m_im == 0) ? btVector3(0, 0, 0) : dv[counter] / node.m_im;
+                               ++counter;
+                       }
+               }
+               for (int i = 0; i < m_lf.size(); ++i)
+               {
+                       // add damping matrix
+                       m_lf[i]->addScaledDampingForceDifferential(-m_dt, dv, f);
+               }
+               counter = 0;
+               for (; counter < f.size(); ++counter)
+               {
+                       f[counter] = rhs[counter] - f[counter];
+               }
+       }
+};
+
+#endif /* btBackwardEulerObjective_h */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBodySolver.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBodySolver.cpp
new file mode 100644 (file)
index 0000000..4e9df5f
--- /dev/null
@@ -0,0 +1,593 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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 <stdio.h>
+#include <limits>
+#include "btDeformableBodySolver.h"
+#include "btSoftBodyInternals.h"
+#include "LinearMath/btQuickprof.h"
+static const int kMaxConjugateGradientIterations = 300;
+btDeformableBodySolver::btDeformableBodySolver()
+       : m_numNodes(0), m_cg(kMaxConjugateGradientIterations), m_cr(kMaxConjugateGradientIterations), m_maxNewtonIterations(1), m_newtonTolerance(1e-4), m_lineSearch(false), m_useProjection(false)
+{
+       m_objective = new btDeformableBackwardEulerObjective(m_softBodies, m_backupVelocity);
+       m_reducedSolver = false;
+}
+
+btDeformableBodySolver::~btDeformableBodySolver()
+{
+       delete m_objective;
+}
+
+void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
+{
+       BT_PROFILE("solveDeformableConstraints");
+       if (!m_implicit)
+       {
+               m_objective->computeResidual(solverdt, m_residual);
+               m_objective->applyDynamicFriction(m_residual);
+               if (m_useProjection)
+               {
+                       computeStep(m_dv, m_residual);
+               }
+               else
+               {
+                       TVStack rhs, x;
+                       m_objective->addLagrangeMultiplierRHS(m_residual, m_dv, rhs);
+                       m_objective->addLagrangeMultiplier(m_dv, x);
+                       m_objective->m_preconditioner->reinitialize(true);
+                       computeStep(x, rhs);
+                       for (int i = 0; i < m_dv.size(); ++i)
+                       {
+                               m_dv[i] = x[i];
+                       }
+               }
+               updateVelocity();
+       }
+       else
+       {
+               for (int i = 0; i < m_maxNewtonIterations; ++i)
+               {
+                       updateState();
+                       // add the inertia term in the residual
+                       int counter = 0;
+                       for (int k = 0; k < m_softBodies.size(); ++k)
+                       {
+                               btSoftBody* psb = m_softBodies[k];
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                               {
+                                       if (psb->m_nodes[j].m_im > 0)
+                                       {
+                                               m_residual[counter] = (-1. / psb->m_nodes[j].m_im) * m_dv[counter];
+                                       }
+                                       ++counter;
+                               }
+                       }
+
+                       m_objective->computeResidual(solverdt, m_residual);
+                       if (m_objective->computeNorm(m_residual) < m_newtonTolerance && i > 0)
+                       {
+                               break;
+                       }
+                       // todo xuchenhan@: this really only needs to be calculated once
+                       m_objective->applyDynamicFriction(m_residual);
+                       if (m_lineSearch)
+                       {
+                               btScalar inner_product = computeDescentStep(m_ddv, m_residual);
+                               btScalar alpha = 0.01, beta = 0.5;  // Boyd & Vandenberghe suggested alpha between 0.01 and 0.3, beta between 0.1 to 0.8
+                               btScalar scale = 2;
+                               btScalar f0 = m_objective->totalEnergy(solverdt) + kineticEnergy(), f1, f2;
+                               backupDv();
+                               do
+                               {
+                                       scale *= beta;
+                                       if (scale < 1e-8)
+                                       {
+                                               return;
+                                       }
+                                       updateEnergy(scale);
+                                       f1 = m_objective->totalEnergy(solverdt) + kineticEnergy();
+                                       f2 = f0 - alpha * scale * inner_product;
+                               } while (!(f1 < f2 + SIMD_EPSILON));  // if anything here is nan then the search continues
+                               revertDv();
+                               updateDv(scale);
+                       }
+                       else
+                       {
+                               computeStep(m_ddv, m_residual);
+                               updateDv();
+                       }
+                       for (int j = 0; j < m_numNodes; ++j)
+                       {
+                               m_ddv[j].setZero();
+                               m_residual[j].setZero();
+                       }
+               }
+               updateVelocity();
+       }
+}
+
+btScalar btDeformableBodySolver::kineticEnergy()
+{
+       btScalar ke = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       btSoftBody::Node& node = psb->m_nodes[j];
+                       if (node.m_im > 0)
+                       {
+                               ke += m_dv[node.index].length2() * 0.5 / node.m_im;
+                       }
+               }
+       }
+       return ke;
+}
+
+void btDeformableBodySolver::backupDv()
+{
+       m_backup_dv.resize(m_dv.size());
+       for (int i = 0; i < m_backup_dv.size(); ++i)
+       {
+               m_backup_dv[i] = m_dv[i];
+       }
+}
+
+void btDeformableBodySolver::revertDv()
+{
+       for (int i = 0; i < m_backup_dv.size(); ++i)
+       {
+               m_dv[i] = m_backup_dv[i];
+       }
+}
+
+void btDeformableBodySolver::updateEnergy(btScalar scale)
+{
+       for (int i = 0; i < m_dv.size(); ++i)
+       {
+               m_dv[i] = m_backup_dv[i] + scale * m_ddv[i];
+       }
+       updateState();
+}
+
+btScalar btDeformableBodySolver::computeDescentStep(TVStack& ddv, const TVStack& residual, bool verbose)
+{
+       m_cg.solve(*m_objective, ddv, residual, false);
+       btScalar inner_product = m_cg.dot(residual, m_ddv);
+       btScalar res_norm = m_objective->computeNorm(residual);
+       btScalar tol = 1e-5 * res_norm * m_objective->computeNorm(m_ddv);
+       if (inner_product < -tol)
+       {
+               if (verbose)
+               {
+                       std::cout << "Looking backwards!" << std::endl;
+               }
+               for (int i = 0; i < m_ddv.size(); ++i)
+               {
+                       m_ddv[i] = -m_ddv[i];
+               }
+               inner_product = -inner_product;
+       }
+       else if (std::abs(inner_product) < tol)
+       {
+               if (verbose)
+               {
+                       std::cout << "Gradient Descent!" << std::endl;
+               }
+               btScalar scale = m_objective->computeNorm(m_ddv) / res_norm;
+               for (int i = 0; i < m_ddv.size(); ++i)
+               {
+                       m_ddv[i] = scale * residual[i];
+               }
+               inner_product = scale * res_norm * res_norm;
+       }
+       return inner_product;
+}
+
+void btDeformableBodySolver::updateState()
+{
+       updateVelocity();
+       updateTempPosition();
+}
+
+void btDeformableBodySolver::updateDv(btScalar scale)
+{
+       for (int i = 0; i < m_numNodes; ++i)
+       {
+               m_dv[i] += scale * m_ddv[i];
+       }
+}
+
+void btDeformableBodySolver::computeStep(TVStack& ddv, const TVStack& residual)
+{
+       if (m_useProjection)
+               m_cg.solve(*m_objective, ddv, residual, false);
+       else
+               m_cr.solve(*m_objective, ddv, residual, false);
+}
+
+void btDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody*>& softBodies, btScalar dt)
+{
+       m_softBodies.copyFromArray(softBodies);
+       bool nodeUpdated = updateNodes();
+
+       if (nodeUpdated)
+       {
+               m_dv.resize(m_numNodes, btVector3(0, 0, 0));
+               m_ddv.resize(m_numNodes, btVector3(0, 0, 0));
+               m_residual.resize(m_numNodes, btVector3(0, 0, 0));
+               m_backupVelocity.resize(m_numNodes, btVector3(0, 0, 0));
+       }
+
+       // need to setZero here as resize only set value for newly allocated items
+       for (int i = 0; i < m_numNodes; ++i)
+       {
+               m_dv[i].setZero();
+               m_ddv[i].setZero();
+               m_residual[i].setZero();
+       }
+
+       if (dt > 0)
+       {
+               m_dt = dt;
+       }
+       m_objective->reinitialize(nodeUpdated, dt);
+       updateSoftBodies();
+}
+
+void btDeformableBodySolver::setConstraints(const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("setConstraint");
+       m_objective->setConstraints(infoGlobal);
+}
+
+btScalar btDeformableBodySolver::solveContactConstraints(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("solveContactConstraints");
+       btScalar maxSquaredResidual = m_objective->m_projection.update(deformableBodies, numDeformableBodies, infoGlobal);
+       return maxSquaredResidual;
+}
+
+void btDeformableBodySolver::updateVelocity()
+{
+       int counter = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               psb->m_maxSpeedSquared = 0;
+               if (!psb->isActive())
+               {
+                       counter += psb->m_nodes.size();
+                       continue;
+               }
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       // set NaN to zero;
+                       if (m_dv[counter] != m_dv[counter])
+                       {
+                               m_dv[counter].setZero();
+                       }
+                       if (m_implicit)
+                       {
+                               psb->m_nodes[j].m_v = m_backupVelocity[counter] + m_dv[counter];
+                       }
+                       else
+                       {
+                               psb->m_nodes[j].m_v = m_backupVelocity[counter] + m_dv[counter] - psb->m_nodes[j].m_splitv;
+                       }
+                       psb->m_maxSpeedSquared = btMax(psb->m_maxSpeedSquared, psb->m_nodes[j].m_v.length2());
+                       ++counter;
+               }
+       }
+}
+
+void btDeformableBodySolver::updateTempPosition()
+{
+       int counter = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (!psb->isActive())
+               {
+                       counter += psb->m_nodes.size();
+                       continue;
+               }
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + m_dt * (psb->m_nodes[j].m_v + psb->m_nodes[j].m_splitv);
+                       ++counter;
+               }
+               psb->updateDeformation();
+       }
+}
+
+void btDeformableBodySolver::backupVelocity()
+{
+       int counter = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       m_backupVelocity[counter++] = psb->m_nodes[j].m_v;
+               }
+       }
+}
+
+void btDeformableBodySolver::setupDeformableSolve(bool implicit)
+{
+       int counter = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (!psb->isActive())
+               {
+                       counter += psb->m_nodes.size();
+                       continue;
+               }
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       if (implicit)
+                       {
+                               // setting the initial guess for newton, need m_dv = v_{n+1} - v_n for dofs that are in constraint.
+                               if (psb->m_nodes[j].m_v == m_backupVelocity[counter])
+                                       m_dv[counter].setZero();
+                               else
+                                       m_dv[counter] = psb->m_nodes[j].m_v - psb->m_nodes[j].m_vn;
+                               m_backupVelocity[counter] = psb->m_nodes[j].m_vn;
+                       }
+                       else
+                       {
+                               m_dv[counter] = psb->m_nodes[j].m_v + psb->m_nodes[j].m_splitv - m_backupVelocity[counter];
+                       }
+                       psb->m_nodes[j].m_v = m_backupVelocity[counter];
+                       ++counter;
+               }
+       }
+}
+
+void btDeformableBodySolver::revertVelocity()
+{
+       int counter = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       psb->m_nodes[j].m_v = m_backupVelocity[counter++];
+               }
+       }
+}
+
+bool btDeformableBodySolver::updateNodes()
+{
+       int numNodes = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+               numNodes += m_softBodies[i]->m_nodes.size();
+       if (numNodes != m_numNodes)
+       {
+               m_numNodes = numNodes;
+               return true;
+       }
+       return false;
+}
+
+void btDeformableBodySolver::predictMotion(btScalar solverdt)
+{
+       // apply explicit forces to velocity
+       if (m_implicit)
+       {
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (psb->isActive())
+                       {
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                               {
+                                       psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + psb->m_nodes[j].m_v * solverdt;
+                               }
+                       }
+               }
+       }
+       applyExplicitForce();
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (psb->isActive())
+               {
+                       /* Clear contacts when softbody is active*/
+                       psb->m_nodeRigidContacts.resize(0);
+                       psb->m_faceRigidContacts.resize(0);
+                       psb->m_faceNodeContacts.resize(0);
+                       psb->m_faceNodeContactsCCD.resize(0);
+                       // predict motion for collision detection
+                       predictDeformableMotion(psb, solverdt);
+               }
+       }
+}
+
+void btDeformableBodySolver::predictDeformableMotion(btSoftBody* psb, btScalar dt)
+{
+       BT_PROFILE("btDeformableBodySolver::predictDeformableMotion");
+       int i, ni;
+
+       /* Update                */
+       if (psb->m_bUpdateRtCst)
+       {
+               psb->m_bUpdateRtCst = false;
+               psb->updateConstants();
+               psb->m_fdbvt.clear();
+               if (psb->m_cfg.collisions & btSoftBody::fCollision::SDF_RD)
+               {
+                       psb->initializeFaceTree();
+               }
+       }
+
+       /* Prepare                */
+       psb->m_sst.sdt = dt * psb->m_cfg.timescale;
+       psb->m_sst.isdt = 1 / psb->m_sst.sdt;
+       psb->m_sst.velmrg = psb->m_sst.sdt * 3;
+       psb->m_sst.radmrg = psb->getCollisionShape()->getMargin();
+       psb->m_sst.updmrg = psb->m_sst.radmrg * (btScalar)0.25;
+       /* Bounds                */
+       psb->updateBounds();
+
+       /* Integrate            */
+       // do not allow particles to move more than the bounding box size
+       btScalar max_v = (psb->m_bounds[1] - psb->m_bounds[0]).norm() / dt;
+       for (i = 0, ni = psb->m_nodes.size(); i < ni; ++i)
+       {
+               btSoftBody::Node& n = psb->m_nodes[i];
+               // apply drag
+               n.m_v *= (1 - psb->m_cfg.drag);
+               // scale velocity back
+               if (m_implicit)
+               {
+                       n.m_q = n.m_x;
+               }
+               else
+               {
+                       if (n.m_v.norm() > max_v)
+                       {
+                               n.m_v.safeNormalize();
+                               n.m_v *= max_v;
+                       }
+                       n.m_q = n.m_x + n.m_v * dt;
+               }
+               n.m_splitv.setZero();
+               n.m_constrained = false;
+       }
+
+       /* Nodes                */
+       psb->updateNodeTree(true, true);
+       if (!psb->m_fdbvt.empty())
+       {
+               psb->updateFaceTree(true, true);
+       }
+       /* Optimize dbvt's        */
+       //    psb->m_ndbvt.optimizeIncremental(1);
+       //    psb->m_fdbvt.optimizeIncremental(1);
+}
+
+void btDeformableBodySolver::updateSoftBodies()
+{
+       BT_PROFILE("updateSoftBodies");
+       for (int i = 0; i < m_softBodies.size(); i++)
+       {
+               btSoftBody* psb = (btSoftBody*)m_softBodies[i];
+               if (psb->isActive())
+               {
+                       psb->updateNormals();
+               }
+       }
+}
+
+void btDeformableBodySolver::setImplicit(bool implicit)
+{
+       m_implicit = implicit;
+       m_objective->setImplicit(implicit);
+}
+
+void btDeformableBodySolver::setLineSearch(bool lineSearch)
+{
+       m_lineSearch = lineSearch;
+}
+
+void btDeformableBodySolver::applyExplicitForce()
+{
+       m_objective->applyExplicitForce(m_residual);
+}
+
+void btDeformableBodySolver::applyTransforms(btScalar timeStep)
+{
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       btSoftBody::Node& node = psb->m_nodes[j];
+                       btScalar maxDisplacement = psb->getWorldInfo()->m_maxDisplacement;
+                       btScalar clampDeltaV = maxDisplacement / timeStep;
+                       for (int c = 0; c < 3; c++)
+                       {
+                               if (node.m_v[c] > clampDeltaV)
+                               {
+                                       node.m_v[c] = clampDeltaV;
+                               }
+                               if (node.m_v[c] < -clampDeltaV)
+                               {
+                                       node.m_v[c] = -clampDeltaV;
+                               }
+                       }
+                       node.m_x = node.m_x + timeStep * (node.m_v + node.m_splitv);
+                       node.m_q = node.m_x;
+                       node.m_vn = node.m_v;
+               }
+               // enforce anchor constraints
+               for (int j = 0; j < psb->m_deformableAnchors.size(); ++j)
+               {
+                       btSoftBody::DeformableNodeRigidAnchor& a = psb->m_deformableAnchors[j];
+                       btSoftBody::Node* n = a.m_node;
+                       n->m_x = a.m_cti.m_colObj->getWorldTransform() * a.m_local;
+
+                       // update multibody anchor info
+                       if (a.m_cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+                       {
+                               btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(a.m_cti.m_colObj);
+                               if (multibodyLinkCol)
+                               {
+                                       btVector3 nrm;
+                                       const btCollisionShape* shp = multibodyLinkCol->getCollisionShape();
+                                       const btTransform& wtr = multibodyLinkCol->getWorldTransform();
+                                       psb->m_worldInfo->m_sparsesdf.Evaluate(
+                                               wtr.invXform(n->m_x),
+                                               shp,
+                                               nrm,
+                                               0);
+                                       a.m_cti.m_normal = wtr.getBasis() * nrm;
+                                       btVector3 normal = a.m_cti.m_normal;
+                                       btVector3 t1 = generateUnitOrthogonalVector(normal);
+                                       btVector3 t2 = btCross(normal, t1);
+                                       btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+                                       findJacobian(multibodyLinkCol, jacobianData_normal, a.m_node->m_x, normal);
+                                       findJacobian(multibodyLinkCol, jacobianData_t1, a.m_node->m_x, t1);
+                                       findJacobian(multibodyLinkCol, jacobianData_t2, a.m_node->m_x, t2);
+
+                                       btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+                                       btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+                                       btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+                                       btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+                                       btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+                                       btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+                                       btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+                                                                       t1.getX(), t1.getY(), t1.getZ(),
+                                                                       t2.getX(), t2.getY(), t2.getZ());  // world frame to local frame
+                                       const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+                                       btMatrix3x3 local_impulse_matrix = (Diagonal(n->m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+                                       a.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+                                       a.jacobianData_normal = jacobianData_normal;
+                                       a.jacobianData_t1 = jacobianData_t1;
+                                       a.jacobianData_t2 = jacobianData_t2;
+                                       a.t1 = t1;
+                                       a.t2 = t2;
+                               }
+                       }
+               }
+               psb->interpolateRenderMesh();
+       }
+}
\ No newline at end of file
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBodySolver.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableBodySolver.h
new file mode 100644 (file)
index 0000000..68354f1
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_DEFORMABLE_BODY_SOLVERS_H
+#define BT_DEFORMABLE_BODY_SOLVERS_H
+
+#include "btSoftBodySolvers.h"
+#include "btDeformableBackwardEulerObjective.h"
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+#include "btConjugateResidual.h"
+#include "btConjugateGradient.h"
+struct btCollisionObjectWrapper;
+// class btDeformableBackwardEulerObjective;
+// class btDeformableMultiBodyDynamicsWorld;
+
+class btDeformableBodySolver : public btSoftBodySolver
+{
+       typedef btAlignedObjectArray<btVector3> TVStack;
+
+protected:
+       int m_numNodes;                                                // total number of deformable body nodes
+       TVStack m_dv;                                                  // v_{n+1} - v_n
+       TVStack m_backup_dv;                                           // backed up dv
+       TVStack m_ddv;                                                 // incremental dv
+       TVStack m_residual;                                            // rhs of the linear solve
+       btAlignedObjectArray<btSoftBody*> m_softBodies;                // all deformable bodies
+       TVStack m_backupVelocity;                                      // backed up v, equals v_n for implicit, equals v_{n+1}^* for explicit
+       btScalar m_dt;                                                 // dt
+       btConjugateGradient<btDeformableBackwardEulerObjective> m_cg;  // CG solver
+       btConjugateResidual<btDeformableBackwardEulerObjective> m_cr;  // CR solver
+       bool m_implicit;                                               // use implicit scheme if true, explicit scheme if false
+       int m_maxNewtonIterations;                                     // max number of newton iterations
+       btScalar m_newtonTolerance;                                    // stop newton iterations if f(x) < m_newtonTolerance
+       bool m_lineSearch;                                             // If true, use newton's method with line search under implicit scheme
+       bool m_reducedSolver;                                                                                                                                                                    // flag for reduced soft body solver
+public:
+       // handles data related to objective function
+       btDeformableBackwardEulerObjective* m_objective;
+       bool m_useProjection;
+
+       btDeformableBodySolver();
+
+       virtual ~btDeformableBodySolver();
+
+       virtual SolverTypes getSolverType() const
+       {
+               return DEFORMABLE_SOLVER;
+       }
+
+       // update soft body normals
+       virtual void updateSoftBodies();
+
+       virtual btScalar solveContactConstraints(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal);
+
+       // solve the momentum equation
+       virtual void solveDeformableConstraints(btScalar solverdt);
+
+       // set gravity (get from deformable world)
+       virtual void setGravity(const btVector3& gravity)
+       {
+               // for full deformable object, we don't store gravity in the solver
+               // this function is overriden in the reduced deformable object
+       }
+
+       // resize/clear data structures
+       virtual void reinitialize(const btAlignedObjectArray<btSoftBody*>& softBodies, btScalar dt);
+
+       // set up contact constraints
+       virtual void setConstraints(const btContactSolverInfo& infoGlobal);
+
+       // add in elastic forces and gravity to obtain v_{n+1}^* and calls predictDeformableMotion
+       virtual void predictMotion(btScalar solverdt);
+
+       // move to temporary position x_{n+1}^* = x_n + dt * v_{n+1}^*
+       // x_{n+1}^* is stored in m_q
+       void predictDeformableMotion(btSoftBody* psb, btScalar dt);
+
+       // save the current velocity to m_backupVelocity
+       void backupVelocity();
+
+       // set m_dv and m_backupVelocity to desired value to prepare for momentum solve
+       virtual void setupDeformableSolve(bool implicit);
+
+       // set the current velocity to that backed up in m_backupVelocity
+       void revertVelocity();
+
+       // set velocity to m_dv + m_backupVelocity
+       void updateVelocity();
+
+       // update the node count
+       bool updateNodes();
+
+       // calculate the change in dv resulting from the momentum solve
+       void computeStep(TVStack& ddv, const TVStack& residual);
+
+       // calculate the change in dv resulting from the momentum solve when line search is turned on
+       btScalar computeDescentStep(TVStack& ddv, const TVStack& residual, bool verbose = false);
+
+       virtual void copySoftBodyToVertexBuffer(const btSoftBody* const softBody, btVertexBufferDescriptor* vertexBuffer) {}
+
+       // process collision between deformable and rigid
+       virtual void processCollision(btSoftBody* softBody, const btCollisionObjectWrapper* collisionObjectWrap)
+       {
+               softBody->defaultCollisionHandler(collisionObjectWrap);
+       }
+
+       // process collision between deformable and deformable
+       virtual void processCollision(btSoftBody* softBody, btSoftBody* otherSoftBody)
+       {
+               softBody->defaultCollisionHandler(otherSoftBody);
+       }
+
+       // If true, implicit time stepping scheme is used.
+       // Otherwise, explicit time stepping scheme is used
+       void setImplicit(bool implicit);
+
+       // If true, newton's method with line search is used when implicit time stepping scheme is turned on
+       void setLineSearch(bool lineSearch);
+
+       // set temporary position x^* = x_n + dt * v
+       // update the deformation gradient at position x^*
+       void updateState();
+
+       // set dv = dv + scale * ddv
+       void updateDv(btScalar scale = 1);
+
+       // set temporary position x^* = x_n + dt * v^*
+       void updateTempPosition();
+
+       // save the current dv to m_backup_dv;
+       void backupDv();
+
+       // set dv to the backed-up value
+       void revertDv();
+
+       // set dv = dv + scale * ddv
+       // set v^* = v_n + dv
+       // set temporary position x^* = x_n + dt * v^*
+       // update the deformation gradient at position x^*
+       void updateEnergy(btScalar scale);
+
+       // calculates the appropriately scaled kinetic energy in the system, which is
+       // 1/2 * dv^T * M * dv
+       // used in line search
+       btScalar kineticEnergy();
+
+       // add explicit force to the velocity in the objective class
+       virtual void applyExplicitForce();
+
+       // execute position/velocity update and apply anchor constraints in the integrateTransforms from the Dynamics world
+       virtual void applyTransforms(btScalar timeStep);
+
+       virtual void setStrainLimiting(bool opt)
+       {
+               m_objective->m_projection.m_useStrainLimiting = opt;
+       }
+
+       virtual void setPreconditioner(int opt)
+       {
+               switch (opt)
+               {
+                       case btDeformableBackwardEulerObjective::Mass_preconditioner:
+                               m_objective->m_preconditioner = m_objective->m_massPreconditioner;
+                               break;
+
+                       case btDeformableBackwardEulerObjective::KKT_preconditioner:
+                               m_objective->m_preconditioner = m_objective->m_KKTPreconditioner;
+                               break;
+                       
+                       default:
+                               btAssert(false);
+                               break;
+               }
+       }
+
+       virtual btAlignedObjectArray<btDeformableLagrangianForce*>* getLagrangianForceArray()
+       {
+               return &(m_objective->m_lf);
+       }
+
+       virtual const btAlignedObjectArray<btSoftBody::Node*>* getIndices()
+       {
+               return m_objective->getIndices();
+       }
+
+       virtual void setProjection()
+       {
+               m_objective->m_projection.setProjection();
+       }
+
+       virtual void setLagrangeMultiplier()
+       {
+               m_objective->m_projection.setLagrangeMultiplier();
+       }
+
+       virtual bool isReducedSolver()
+       {
+               return m_reducedSolver;
+       }
+       
+       virtual void deformableBodyInternalWriteBack() {}
+
+       // unused functions
+       virtual void optimize(btAlignedObjectArray<btSoftBody*>& softBodies, bool forceUpdate = false) {}
+       virtual void solveConstraints(btScalar dt) {}
+       virtual bool checkInitialized() { return true; }
+       virtual void copyBackToSoftBodies(bool bMove = true) {}
+};
+
+#endif /* btDeformableBodySolver_h */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactConstraint.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactConstraint.cpp
new file mode 100644 (file)
index 0000000..09398d7
--- /dev/null
@@ -0,0 +1,720 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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 "btDeformableContactConstraint.h"
+/* ================   Deformable Node Anchor   =================== */
+btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& a, const btContactSolverInfo& infoGlobal)
+       : m_anchor(&a), btDeformableContactConstraint(a.m_cti.m_normal, infoGlobal)
+{
+}
+
+btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other)
+       : m_anchor(other.m_anchor), btDeformableContactConstraint(other)
+{
+}
+
+btVector3 btDeformableNodeAnchorConstraint::getVa() const
+{
+       const btSoftBody::sCti& cti = m_anchor->m_cti;
+       btVector3 va(0, 0, 0);
+       if (cti.m_colObj->hasContactResponse())
+       {
+               btRigidBody* rigidCol = 0;
+               btMultiBodyLinkCollider* multibodyLinkCol = 0;
+
+               // grab the velocity of the rigid body
+               if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+               {
+                       rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+                       va = rigidCol ? (rigidCol->getVelocityInLocalPoint(m_anchor->m_c1)) : btVector3(0, 0, 0);
+               }
+               else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+               {
+                       multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+                       if (multibodyLinkCol)
+                       {
+                               const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+                               const btScalar* J_n = &m_anchor->jacobianData_normal.m_jacobians[0];
+                               const btScalar* J_t1 = &m_anchor->jacobianData_t1.m_jacobians[0];
+                               const btScalar* J_t2 = &m_anchor->jacobianData_t2.m_jacobians[0];
+                               const btScalar* local_v = multibodyLinkCol->m_multiBody->getVelocityVector();
+                               const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
+                               // add in the normal component of the va
+                               btScalar vel = 0.0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += (local_v[k] + local_dv[k]) * J_n[k];
+                               }
+                               va = cti.m_normal * vel;
+                               // add in the tangential components of the va
+                               vel = 0.0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += (local_v[k] + local_dv[k]) * J_t1[k];
+                               }
+                               va += m_anchor->t1 * vel;
+                               vel = 0.0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += (local_v[k] + local_dv[k]) * J_t2[k];
+                               }
+                               va += m_anchor->t2 * vel;
+                       }
+               }
+       }
+       return va;
+}
+
+btScalar btDeformableNodeAnchorConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
+{
+       const btSoftBody::sCti& cti = m_anchor->m_cti;
+       btVector3 va = getVa();
+       btVector3 vb = getVb();
+       btVector3 vr = (vb - va);
+       // + (m_anchor->m_node->m_x - cti.m_colObj->getWorldTransform() * m_anchor->m_local) * 10.0
+       const btScalar dn = btDot(vr, vr);
+       // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
+       btScalar residualSquare = dn * dn;
+       btVector3 impulse = m_anchor->m_c0 * vr;
+       // apply impulse to deformable nodes involved and change their velocities
+       applyImpulse(impulse);
+
+       // apply impulse to the rigid/multibodies involved and change their velocities
+       if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+       {
+               btRigidBody* rigidCol = 0;
+               rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+               if (rigidCol)
+               {
+                       rigidCol->applyImpulse(impulse, m_anchor->m_c1);
+               }
+       }
+       else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+       {
+               btMultiBodyLinkCollider* multibodyLinkCol = 0;
+               multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+               if (multibodyLinkCol)
+               {
+                       const btScalar* deltaV_normal = &m_anchor->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+                       // apply normal component of the impulse
+                       multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, impulse.dot(cti.m_normal));
+                       // apply tangential component of the impulse
+                       const btScalar* deltaV_t1 = &m_anchor->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+                       multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, impulse.dot(m_anchor->t1));
+                       const btScalar* deltaV_t2 = &m_anchor->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+                       multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, impulse.dot(m_anchor->t2));
+               }
+       }
+       return residualSquare;
+}
+
+btVector3 btDeformableNodeAnchorConstraint::getVb() const
+{
+       return m_anchor->m_node->m_v;
+}
+
+void btDeformableNodeAnchorConstraint::applyImpulse(const btVector3& impulse)
+{
+       btVector3 dv = impulse * m_anchor->m_c2;
+       m_anchor->m_node->m_v -= dv;
+}
+
+/* ================   Deformable vs. Rigid   =================== */
+btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c, const btContactSolverInfo& infoGlobal)
+       : m_contact(&c), btDeformableContactConstraint(c.m_cti.m_normal, infoGlobal)
+{
+       m_total_normal_dv.setZero();
+       m_total_tangent_dv.setZero();
+       // The magnitude of penetration is the depth of penetration.
+       m_penetration = c.m_cti.m_offset;
+       m_total_split_impulse = 0;
+       m_binding = false;
+}
+
+btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other)
+       : m_contact(other.m_contact), btDeformableContactConstraint(other), m_penetration(other.m_penetration), m_total_split_impulse(other.m_total_split_impulse), m_binding(other.m_binding)
+{
+       m_total_normal_dv = other.m_total_normal_dv;
+       m_total_tangent_dv = other.m_total_tangent_dv;
+}
+
+btVector3 btDeformableRigidContactConstraint::getVa() const
+{
+       const btSoftBody::sCti& cti = m_contact->m_cti;
+       btVector3 va(0, 0, 0);
+       if (cti.m_colObj->hasContactResponse())
+       {
+               btRigidBody* rigidCol = 0;
+               btMultiBodyLinkCollider* multibodyLinkCol = 0;
+
+               // grab the velocity of the rigid body
+               if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+               {
+                       rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+                       va = rigidCol ? (rigidCol->getVelocityInLocalPoint(m_contact->m_c1)) : btVector3(0, 0, 0);
+               }
+               else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+               {
+                       multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+                       if (multibodyLinkCol)
+                       {
+                               const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+                               const btScalar* J_n = &m_contact->jacobianData_normal.m_jacobians[0];
+                               const btScalar* J_t1 = &m_contact->jacobianData_t1.m_jacobians[0];
+                               const btScalar* J_t2 = &m_contact->jacobianData_t2.m_jacobians[0];
+                               const btScalar* local_v = multibodyLinkCol->m_multiBody->getVelocityVector();
+                               const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
+                               // add in the normal component of the va
+                               btScalar vel = 0.0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += (local_v[k] + local_dv[k]) * J_n[k];
+                               }
+                               va = cti.m_normal * vel;
+                               // add in the tangential components of the va
+                               vel = 0.0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += (local_v[k] + local_dv[k]) * J_t1[k];
+                               }
+                               va += m_contact->t1 * vel;
+                               vel = 0.0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += (local_v[k] + local_dv[k]) * J_t2[k];
+                               }
+                               va += m_contact->t2 * vel;
+                       }
+               }
+       }
+       return va;
+}
+
+btVector3 btDeformableRigidContactConstraint::getSplitVa() const
+{
+       const btSoftBody::sCti& cti = m_contact->m_cti;
+       btVector3 va(0, 0, 0);
+       if (cti.m_colObj->hasContactResponse())
+       {
+               btRigidBody* rigidCol = 0;
+               btMultiBodyLinkCollider* multibodyLinkCol = 0;
+
+               // grab the velocity of the rigid body
+               if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+               {
+                       rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+                       va = rigidCol ? (rigidCol->getPushVelocityInLocalPoint(m_contact->m_c1)) : btVector3(0, 0, 0);
+               }
+               else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+               {
+                       multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+                       if (multibodyLinkCol)
+                       {
+                               const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+                               const btScalar* J_n = &m_contact->jacobianData_normal.m_jacobians[0];
+                               const btScalar* J_t1 = &m_contact->jacobianData_t1.m_jacobians[0];
+                               const btScalar* J_t2 = &m_contact->jacobianData_t2.m_jacobians[0];
+                               const btScalar* local_split_v = multibodyLinkCol->m_multiBody->getSplitVelocityVector();
+                               // add in the normal component of the va
+                               btScalar vel = 0.0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += local_split_v[k] * J_n[k];
+                               }
+                               va = cti.m_normal * vel;
+                               // add in the tangential components of the va
+                               vel = 0.0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += local_split_v[k] * J_t1[k];
+                               }
+                               va += m_contact->t1 * vel;
+                               vel = 0.0;
+                               for (int k = 0; k < ndof; ++k)
+                               {
+                                       vel += local_split_v[k] * J_t2[k];
+                               }
+                               va += m_contact->t2 * vel;
+                       }
+               }
+       }
+       return va;
+}
+
+btScalar btDeformableRigidContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
+{
+       const btSoftBody::sCti& cti = m_contact->m_cti;
+       btVector3 va = getVa();
+       btVector3 vb = getVb();
+       btVector3 vr = vb - va;
+       btScalar dn = btDot(vr, cti.m_normal) + m_total_normal_dv.dot(cti.m_normal) * infoGlobal.m_deformable_cfm;
+       if (m_penetration > 0)
+       {
+               dn += m_penetration / infoGlobal.m_timeStep;
+       }
+       if (!infoGlobal.m_splitImpulse)
+       {
+               dn += m_penetration * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep;
+       }
+       // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
+       btVector3 impulse = m_contact->m_c0 * (vr + m_total_normal_dv * infoGlobal.m_deformable_cfm + ((m_penetration > 0) ? m_penetration / infoGlobal.m_timeStep * cti.m_normal : btVector3(0, 0, 0)));
+       if (!infoGlobal.m_splitImpulse)
+       {
+               impulse += m_contact->m_c0 * (m_penetration * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep * cti.m_normal);
+       }
+       btVector3 impulse_normal = m_contact->m_c0 * (cti.m_normal * dn);
+       btVector3 impulse_tangent = impulse - impulse_normal;
+       if (dn > 0)
+       {
+               return 0;
+       }
+       m_binding = true;
+       btScalar residualSquare = dn * dn;
+       btVector3 old_total_tangent_dv = m_total_tangent_dv;
+       // m_c5 is the inverse mass of the deformable node/face
+       m_total_normal_dv -= m_contact->m_c5 * impulse_normal;
+       m_total_tangent_dv -= m_contact->m_c5 * impulse_tangent;
+
+       if (m_total_normal_dv.dot(cti.m_normal) < 0)
+       {
+               // separating in the normal direction
+               m_binding = false;
+               m_static = false;
+               impulse_tangent.setZero();
+       }
+       else
+       {
+               if (m_total_normal_dv.norm() * m_contact->m_c3 < m_total_tangent_dv.norm())
+               {
+                       // dynamic friction
+                       // with dynamic friction, the impulse are still applied to the two objects colliding, however, it does not pose a constraint in the cg solve, hence the change to dv merely serves to update velocity in the contact iterations.
+                       m_static = false;
+                       if (m_total_tangent_dv.safeNorm() < SIMD_EPSILON)
+                       {
+                               m_total_tangent_dv = btVector3(0, 0, 0);
+                       }
+                       else
+                       {
+                               m_total_tangent_dv = m_total_tangent_dv.normalized() * m_total_normal_dv.safeNorm() * m_contact->m_c3;
+                       }
+                       //            impulse_tangent = -btScalar(1)/m_contact->m_c2 * (m_total_tangent_dv - old_total_tangent_dv);
+                       impulse_tangent = m_contact->m_c5.inverse() * (old_total_tangent_dv - m_total_tangent_dv);
+               }
+               else
+               {
+                       // static friction
+                       m_static = true;
+               }
+       }
+       impulse = impulse_normal + impulse_tangent;
+       // apply impulse to deformable nodes involved and change their velocities
+       applyImpulse(impulse);
+       // apply impulse to the rigid/multibodies involved and change their velocities
+       if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+       {
+               btRigidBody* rigidCol = 0;
+               rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+               if (rigidCol)
+               {
+                       rigidCol->applyImpulse(impulse, m_contact->m_c1);
+               }
+       }
+       else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+       {
+               btMultiBodyLinkCollider* multibodyLinkCol = 0;
+               multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+               if (multibodyLinkCol)
+               {
+                       const btScalar* deltaV_normal = &m_contact->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+                       // apply normal component of the impulse
+                       multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, impulse.dot(cti.m_normal));
+                       if (impulse_tangent.norm() > SIMD_EPSILON)
+                       {
+                               // apply tangential component of the impulse
+                               const btScalar* deltaV_t1 = &m_contact->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+                               multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, impulse.dot(m_contact->t1));
+                               const btScalar* deltaV_t2 = &m_contact->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+                               multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, impulse.dot(m_contact->t2));
+                       }
+               }
+       }
+       return residualSquare;
+}
+
+btScalar btDeformableRigidContactConstraint::solveSplitImpulse(const btContactSolverInfo& infoGlobal)
+{
+       btScalar MAX_PENETRATION_CORRECTION = infoGlobal.m_deformable_maxErrorReduction;
+       const btSoftBody::sCti& cti = m_contact->m_cti;
+       btVector3 vb = getSplitVb();
+       btVector3 va = getSplitVa();
+       btScalar p = m_penetration;
+       if (p > 0)
+       {
+               return 0;
+       }
+       btVector3 vr = vb - va;
+       btScalar dn = btDot(vr, cti.m_normal) + p * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep;
+       if (dn > 0)
+       {
+               return 0;
+       }
+       if (m_total_split_impulse + dn > MAX_PENETRATION_CORRECTION)
+       {
+               dn = MAX_PENETRATION_CORRECTION - m_total_split_impulse;
+       }
+       if (m_total_split_impulse + dn < -MAX_PENETRATION_CORRECTION)
+       {
+               dn = -MAX_PENETRATION_CORRECTION - m_total_split_impulse;
+       }
+       m_total_split_impulse += dn;
+
+       btScalar residualSquare = dn * dn;
+       const btVector3 impulse = m_contact->m_c0 * (cti.m_normal * dn);
+       applySplitImpulse(impulse);
+
+       // apply split impulse to the rigid/multibodies involved and change their velocities
+       if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+       {
+               btRigidBody* rigidCol = 0;
+               rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+               if (rigidCol)
+               {
+                       rigidCol->applyPushImpulse(impulse, m_contact->m_c1);
+               }
+       }
+       else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+       {
+               btMultiBodyLinkCollider* multibodyLinkCol = 0;
+               multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+               if (multibodyLinkCol)
+               {
+                       const btScalar* deltaV_normal = &m_contact->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+                       // apply normal component of the impulse
+                       multibodyLinkCol->m_multiBody->applyDeltaSplitVeeMultiDof(deltaV_normal, impulse.dot(cti.m_normal));
+               }
+       }
+       return residualSquare;
+}
+/* ================   Node vs. Rigid   =================== */
+btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact, const btContactSolverInfo& infoGlobal)
+       : m_node(contact.m_node), btDeformableRigidContactConstraint(contact, infoGlobal)
+{
+}
+
+btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other)
+       : m_node(other.m_node), btDeformableRigidContactConstraint(other)
+{
+}
+
+btVector3 btDeformableNodeRigidContactConstraint::getVb() const
+{
+       return m_node->m_v;
+}
+
+btVector3 btDeformableNodeRigidContactConstraint::getSplitVb() const
+{
+       return m_node->m_splitv;
+}
+
+btVector3 btDeformableNodeRigidContactConstraint::getDv(const btSoftBody::Node* node) const
+{
+       return m_total_normal_dv + m_total_tangent_dv;
+}
+
+void btDeformableNodeRigidContactConstraint::applyImpulse(const btVector3& impulse)
+{
+       const btSoftBody::DeformableNodeRigidContact* contact = getContact();
+       btVector3 dv = contact->m_c5 * impulse;
+       contact->m_node->m_v -= dv;
+}
+
+void btDeformableNodeRigidContactConstraint::applySplitImpulse(const btVector3& impulse)
+{
+       const btSoftBody::DeformableNodeRigidContact* contact = getContact();
+       btVector3 dv = contact->m_c5 * impulse;
+       contact->m_node->m_splitv -= dv;
+}
+
+/* ================   Face vs. Rigid   =================== */
+btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact, const btContactSolverInfo& infoGlobal, bool useStrainLimiting)
+       : m_face(contact.m_face), m_useStrainLimiting(useStrainLimiting), btDeformableRigidContactConstraint(contact, infoGlobal)
+{
+}
+
+btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other)
+       : m_face(other.m_face), m_useStrainLimiting(other.m_useStrainLimiting), btDeformableRigidContactConstraint(other)
+{
+}
+
+btVector3 btDeformableFaceRigidContactConstraint::getVb() const
+{
+       const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+       btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
+       return vb;
+}
+
+btVector3 btDeformableFaceRigidContactConstraint::getDv(const btSoftBody::Node* node) const
+{
+       btVector3 face_dv = m_total_normal_dv + m_total_tangent_dv;
+       const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+       if (m_face->m_n[0] == node)
+       {
+               return face_dv * contact->m_weights[0];
+       }
+       if (m_face->m_n[1] == node)
+       {
+               return face_dv * contact->m_weights[1];
+       }
+       btAssert(node == m_face->m_n[2]);
+       return face_dv * contact->m_weights[2];
+}
+
+void btDeformableFaceRigidContactConstraint::applyImpulse(const btVector3& impulse)
+{
+       const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+       btVector3 dv = impulse * contact->m_c2;
+       btSoftBody::Face* face = contact->m_face;
+
+       btVector3& v0 = face->m_n[0]->m_v;
+       btVector3& v1 = face->m_n[1]->m_v;
+       btVector3& v2 = face->m_n[2]->m_v;
+       const btScalar& im0 = face->m_n[0]->m_im;
+       const btScalar& im1 = face->m_n[1]->m_im;
+       const btScalar& im2 = face->m_n[2]->m_im;
+       if (im0 > 0)
+               v0 -= dv * contact->m_weights[0];
+       if (im1 > 0)
+               v1 -= dv * contact->m_weights[1];
+       if (im2 > 0)
+               v2 -= dv * contact->m_weights[2];
+       if (m_useStrainLimiting)
+       {
+               btScalar relaxation = 1. / btScalar(m_infoGlobal->m_numIterations);
+               btScalar m01 = (relaxation / (im0 + im1));
+               btScalar m02 = (relaxation / (im0 + im2));
+               btScalar m12 = (relaxation / (im1 + im2));
+#ifdef USE_STRAIN_RATE_LIMITING
+               // apply strain limiting to prevent the new velocity to change the current length of the edge by more than 1%.
+               btScalar p = 0.01;
+               btVector3& x0 = face->m_n[0]->m_x;
+               btVector3& x1 = face->m_n[1]->m_x;
+               btVector3& x2 = face->m_n[2]->m_x;
+               const btVector3 x_diff[3] = {x1 - x0, x2 - x0, x2 - x1};
+               const btVector3 v_diff[3] = {v1 - v0, v2 - v0, v2 - v1};
+               btVector3 u[3];
+               btScalar x_diff_dot_u, dn[3];
+               btScalar dt = m_infoGlobal->m_timeStep;
+               for (int i = 0; i < 3; ++i)
+               {
+                       btScalar x_diff_norm = x_diff[i].safeNorm();
+                       btScalar x_diff_norm_new = (x_diff[i] + v_diff[i] * dt).safeNorm();
+                       btScalar strainRate = x_diff_norm_new / x_diff_norm;
+                       u[i] = v_diff[i];
+                       u[i].safeNormalize();
+                       if (x_diff_norm == 0 || (1 - p <= strainRate && strainRate <= 1 + p))
+                       {
+                               dn[i] = 0;
+                               continue;
+                       }
+                       x_diff_dot_u = btDot(x_diff[i], u[i]);
+                       btScalar s;
+                       if (1 - p > strainRate)
+                       {
+                               s = 1 / dt * (-x_diff_dot_u - btSqrt(x_diff_dot_u * x_diff_dot_u + (p * p - 2 * p) * x_diff_norm * x_diff_norm));
+                       }
+                       else
+                       {
+                               s = 1 / dt * (-x_diff_dot_u + btSqrt(x_diff_dot_u * x_diff_dot_u + (p * p + 2 * p) * x_diff_norm * x_diff_norm));
+                       }
+                       //              x_diff_norm_new = (x_diff[i] + s * u[i] * dt).safeNorm();
+                       //              strainRate = x_diff_norm_new/x_diff_norm;
+                       dn[i] = s - v_diff[i].safeNorm();
+               }
+               btVector3 dv0 = im0 * (m01 * u[0] * (-dn[0]) + m02 * u[1] * -(dn[1]));
+               btVector3 dv1 = im1 * (m01 * u[0] * (dn[0]) + m12 * u[2] * (-dn[2]));
+               btVector3 dv2 = im2 * (m12 * u[2] * (dn[2]) + m02 * u[1] * (dn[1]));
+#else
+               // apply strain limiting to prevent undamped modes
+               btVector3 dv0 = im0 * (m01 * (v1 - v0) + m02 * (v2 - v0));
+               btVector3 dv1 = im1 * (m01 * (v0 - v1) + m12 * (v2 - v1));
+               btVector3 dv2 = im2 * (m12 * (v1 - v2) + m02 * (v0 - v2));
+#endif
+               v0 += dv0;
+               v1 += dv1;
+               v2 += dv2;
+       }
+}
+
+btVector3 btDeformableFaceRigidContactConstraint::getSplitVb() const
+{
+       const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+       btVector3 vb = (m_face->m_n[0]->m_splitv) * contact->m_bary[0] + (m_face->m_n[1]->m_splitv) * contact->m_bary[1] + (m_face->m_n[2]->m_splitv) * contact->m_bary[2];
+       return vb;
+}
+
+void btDeformableFaceRigidContactConstraint::applySplitImpulse(const btVector3& impulse)
+{
+       const btSoftBody::DeformableFaceRigidContact* contact = getContact();
+       btVector3 dv = impulse * contact->m_c2;
+       btSoftBody::Face* face = contact->m_face;
+       btVector3& v0 = face->m_n[0]->m_splitv;
+       btVector3& v1 = face->m_n[1]->m_splitv;
+       btVector3& v2 = face->m_n[2]->m_splitv;
+       const btScalar& im0 = face->m_n[0]->m_im;
+       const btScalar& im1 = face->m_n[1]->m_im;
+       const btScalar& im2 = face->m_n[2]->m_im;
+       if (im0 > 0)
+       {
+               v0 -= dv * contact->m_weights[0];
+       }
+       if (im1 > 0)
+       {
+               v1 -= dv * contact->m_weights[1];
+       }
+       if (im2 > 0)
+       {
+               v2 -= dv * contact->m_weights[2];
+       }
+}
+
+/* ================   Face vs. Node   =================== */
+btDeformableFaceNodeContactConstraint::btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact, const btContactSolverInfo& infoGlobal)
+       : m_node(contact.m_node), m_face(contact.m_face), m_contact(&contact), btDeformableContactConstraint(contact.m_normal, infoGlobal)
+{
+       m_total_normal_dv.setZero();
+       m_total_tangent_dv.setZero();
+}
+
+btVector3 btDeformableFaceNodeContactConstraint::getVa() const
+{
+       return m_node->m_v;
+}
+
+btVector3 btDeformableFaceNodeContactConstraint::getVb() const
+{
+       const btSoftBody::DeformableFaceNodeContact* contact = getContact();
+       btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
+       return vb;
+}
+
+btVector3 btDeformableFaceNodeContactConstraint::getDv(const btSoftBody::Node* n) const
+{
+       btVector3 dv = m_total_normal_dv + m_total_tangent_dv;
+       if (n == m_node)
+               return dv;
+       const btSoftBody::DeformableFaceNodeContact* contact = getContact();
+       if (m_face->m_n[0] == n)
+       {
+               return dv * contact->m_weights[0];
+       }
+       if (m_face->m_n[1] == n)
+       {
+               return dv * contact->m_weights[1];
+       }
+       btAssert(n == m_face->m_n[2]);
+       return dv * contact->m_weights[2];
+}
+
+btScalar btDeformableFaceNodeContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
+{
+       btVector3 va = getVa();
+       btVector3 vb = getVb();
+       btVector3 vr = vb - va;
+       const btScalar dn = btDot(vr, m_contact->m_normal);
+       // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
+       btScalar residualSquare = dn * dn;
+       btVector3 impulse = m_contact->m_c0 * vr;
+       const btVector3 impulse_normal = m_contact->m_c0 * (m_contact->m_normal * dn);
+       btVector3 impulse_tangent = impulse - impulse_normal;
+
+       btVector3 old_total_tangent_dv = m_total_tangent_dv;
+       // m_c2 is the inverse mass of the deformable node/face
+       if (m_node->m_im > 0)
+       {
+               m_total_normal_dv -= impulse_normal * m_node->m_im;
+               m_total_tangent_dv -= impulse_tangent * m_node->m_im;
+       }
+       else
+       {
+               m_total_normal_dv -= impulse_normal * m_contact->m_imf;
+               m_total_tangent_dv -= impulse_tangent * m_contact->m_imf;
+       }
+
+       if (m_total_normal_dv.dot(m_contact->m_normal) > 0)
+       {
+               // separating in the normal direction
+               m_static = false;
+               m_total_tangent_dv = btVector3(0, 0, 0);
+               impulse_tangent.setZero();
+       }
+       else
+       {
+               if (m_total_normal_dv.norm() * m_contact->m_friction < m_total_tangent_dv.norm())
+               {
+                       // dynamic friction
+                       // with dynamic friction, the impulse are still applied to the two objects colliding, however, it does not pose a constraint in the cg solve, hence the change to dv merely serves to update velocity in the contact iterations.
+                       m_static = false;
+                       if (m_total_tangent_dv.safeNorm() < SIMD_EPSILON)
+                       {
+                               m_total_tangent_dv = btVector3(0, 0, 0);
+                       }
+                       else
+                       {
+                               m_total_tangent_dv = m_total_tangent_dv.normalized() * m_total_normal_dv.safeNorm() * m_contact->m_friction;
+                       }
+                       impulse_tangent = -btScalar(1) / m_node->m_im * (m_total_tangent_dv - old_total_tangent_dv);
+               }
+               else
+               {
+                       // static friction
+                       m_static = true;
+               }
+       }
+       impulse = impulse_normal + impulse_tangent;
+       // apply impulse to deformable nodes involved and change their velocities
+       applyImpulse(impulse);
+       return residualSquare;
+}
+
+void btDeformableFaceNodeContactConstraint::applyImpulse(const btVector3& impulse)
+{
+       const btSoftBody::DeformableFaceNodeContact* contact = getContact();
+       btVector3 dva = impulse * contact->m_node->m_im;
+       btVector3 dvb = impulse * contact->m_imf;
+       if (contact->m_node->m_im > 0)
+       {
+               contact->m_node->m_v += dva;
+       }
+
+       btSoftBody::Face* face = contact->m_face;
+       btVector3& v0 = face->m_n[0]->m_v;
+       btVector3& v1 = face->m_n[1]->m_v;
+       btVector3& v2 = face->m_n[2]->m_v;
+       const btScalar& im0 = face->m_n[0]->m_im;
+       const btScalar& im1 = face->m_n[1]->m_im;
+       const btScalar& im2 = face->m_n[2]->m_im;
+       if (im0 > 0)
+       {
+               v0 -= dvb * contact->m_weights[0];
+       }
+       if (im1 > 0)
+       {
+               v1 -= dvb * contact->m_weights[1];
+       }
+       if (im2 > 0)
+       {
+               v2 -= dvb * contact->m_weights[2];
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactConstraint.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactConstraint.h
new file mode 100644 (file)
index 0000000..ddecb40
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_DEFORMABLE_CONTACT_CONSTRAINT_H
+#define BT_DEFORMABLE_CONTACT_CONSTRAINT_H
+#include "btSoftBody.h"
+
+// btDeformableContactConstraint is an abstract class specifying the method that each type of contact constraint needs to implement
+class btDeformableContactConstraint
+{
+public:
+       // True if the friction is static
+       // False if the friction is dynamic
+       bool m_static;
+       const btContactSolverInfo* m_infoGlobal;
+
+       // normal of the contact
+       btVector3 m_normal;
+
+       btDeformableContactConstraint(const btVector3& normal, const btContactSolverInfo& infoGlobal) : m_static(false), m_normal(normal), m_infoGlobal(&infoGlobal)
+       {
+       }
+
+       btDeformableContactConstraint(bool isStatic, const btVector3& normal, const btContactSolverInfo& infoGlobal) : m_static(isStatic), m_normal(normal), m_infoGlobal(&infoGlobal)
+       {
+       }
+
+       btDeformableContactConstraint() : m_static(false) {}
+
+       btDeformableContactConstraint(const btDeformableContactConstraint& other)
+               : m_static(other.m_static), m_normal(other.m_normal), m_infoGlobal(other.m_infoGlobal)
+       {
+       }
+
+       virtual ~btDeformableContactConstraint() {}
+
+       // solve the constraint with inelastic impulse and return the error, which is the square of normal component of velocity diffrerence
+       // the constraint is solved by calculating the impulse between object A and B in the contact and apply the impulse to both objects involved in the contact
+       virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal) = 0;
+
+       // get the velocity of the object A in the contact
+       virtual btVector3 getVa() const = 0;
+
+       // get the velocity of the object B in the contact
+       virtual btVector3 getVb() const = 0;
+
+       // get the velocity change of the soft body node in the constraint
+       virtual btVector3 getDv(const btSoftBody::Node*) const = 0;
+
+       // apply impulse to the soft body node and/or face involved
+       virtual void applyImpulse(const btVector3& impulse) = 0;
+
+       // scale the penetration depth by erp
+       virtual void setPenetrationScale(btScalar scale) = 0;
+};
+
+//
+// Constraint that a certain node in the deformable objects cannot move
+class btDeformableStaticConstraint : public btDeformableContactConstraint
+{
+public:
+       btSoftBody::Node* m_node;
+
+       btDeformableStaticConstraint(btSoftBody::Node* node, const btContactSolverInfo& infoGlobal) : m_node(node), btDeformableContactConstraint(false, btVector3(0, 0, 0), infoGlobal)
+       {
+       }
+       btDeformableStaticConstraint() {}
+       btDeformableStaticConstraint(const btDeformableStaticConstraint& other)
+               : m_node(other.m_node), btDeformableContactConstraint(other)
+       {
+       }
+
+       virtual ~btDeformableStaticConstraint() {}
+
+       virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal)
+       {
+               return 0;
+       }
+
+       virtual btVector3 getVa() const
+       {
+               return btVector3(0, 0, 0);
+       }
+
+       virtual btVector3 getVb() const
+       {
+               return btVector3(0, 0, 0);
+       }
+
+       virtual btVector3 getDv(const btSoftBody::Node* n) const
+       {
+               return btVector3(0, 0, 0);
+       }
+
+       virtual void applyImpulse(const btVector3& impulse) {}
+       virtual void setPenetrationScale(btScalar scale) {}
+};
+
+//
+// Anchor Constraint between rigid and deformable node
+class btDeformableNodeAnchorConstraint : public btDeformableContactConstraint
+{
+public:
+       const btSoftBody::DeformableNodeRigidAnchor* m_anchor;
+
+       btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& c, const btContactSolverInfo& infoGlobal);
+       btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other);
+       btDeformableNodeAnchorConstraint() {}
+       virtual ~btDeformableNodeAnchorConstraint()
+       {
+       }
+       virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
+
+       // object A is the rigid/multi body, and object B is the deformable node/face
+       virtual btVector3 getVa() const;
+       // get the velocity of the deformable node in contact
+       virtual btVector3 getVb() const;
+       virtual btVector3 getDv(const btSoftBody::Node* n) const
+       {
+               return btVector3(0, 0, 0);
+       }
+       virtual void applyImpulse(const btVector3& impulse);
+
+       virtual void setPenetrationScale(btScalar scale) {}
+};
+
+//
+// Constraint between rigid/multi body and deformable objects
+class btDeformableRigidContactConstraint : public btDeformableContactConstraint
+{
+public:
+       btVector3 m_total_normal_dv;
+       btVector3 m_total_tangent_dv;
+       btScalar m_penetration;
+       btScalar m_total_split_impulse;
+       bool m_binding;
+       const btSoftBody::DeformableRigidContact* m_contact;
+
+       btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c, const btContactSolverInfo& infoGlobal);
+       btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other);
+       btDeformableRigidContactConstraint() : m_binding(false) {}
+       virtual ~btDeformableRigidContactConstraint()
+       {
+       }
+
+       // object A is the rigid/multi body, and object B is the deformable node/face
+       virtual btVector3 getVa() const;
+
+       // get the split impulse velocity of the deformable face at the contact point
+       virtual btVector3 getSplitVb() const = 0;
+
+       // get the split impulse velocity of the rigid/multibdoy at the contaft
+       virtual btVector3 getSplitVa() const;
+
+       virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
+
+       virtual void setPenetrationScale(btScalar scale)
+       {
+               m_penetration *= scale;
+       }
+
+       btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal);
+
+       virtual void applySplitImpulse(const btVector3& impulse) = 0;
+};
+
+//
+// Constraint between rigid/multi body and deformable objects nodes
+class btDeformableNodeRigidContactConstraint : public btDeformableRigidContactConstraint
+{
+public:
+       // the deformable node in contact
+       btSoftBody::Node* m_node;
+
+       btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact, const btContactSolverInfo& infoGlobal);
+       btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other);
+       btDeformableNodeRigidContactConstraint() {}
+       virtual ~btDeformableNodeRigidContactConstraint()
+       {
+       }
+
+       // get the velocity of the deformable node in contact
+       virtual btVector3 getVb() const;
+
+       // get the split impulse velocity of the deformable face at the contact point
+       virtual btVector3 getSplitVb() const;
+
+       // get the velocity change of the input soft body node in the constraint
+       virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+       // cast the contact to the desired type
+       const btSoftBody::DeformableNodeRigidContact* getContact() const
+       {
+               return static_cast<const btSoftBody::DeformableNodeRigidContact*>(m_contact);
+       }
+
+       virtual void applyImpulse(const btVector3& impulse);
+
+       virtual void applySplitImpulse(const btVector3& impulse);
+};
+
+//
+// Constraint between rigid/multi body and deformable objects faces
+class btDeformableFaceRigidContactConstraint : public btDeformableRigidContactConstraint
+{
+public:
+       btSoftBody::Face* m_face;
+       bool m_useStrainLimiting;
+       btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact, const btContactSolverInfo& infoGlobal, bool useStrainLimiting);
+       btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other);
+       btDeformableFaceRigidContactConstraint() : m_useStrainLimiting(false) {}
+       virtual ~btDeformableFaceRigidContactConstraint()
+       {
+       }
+
+       // get the velocity of the deformable face at the contact point
+       virtual btVector3 getVb() const;
+
+       // get the split impulse velocity of the deformable face at the contact point
+       virtual btVector3 getSplitVb() const;
+
+       // get the velocity change of the input soft body node in the constraint
+       virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+       // cast the contact to the desired type
+       const btSoftBody::DeformableFaceRigidContact* getContact() const
+       {
+               return static_cast<const btSoftBody::DeformableFaceRigidContact*>(m_contact);
+       }
+
+       virtual void applyImpulse(const btVector3& impulse);
+
+       virtual void applySplitImpulse(const btVector3& impulse);
+};
+
+//
+// Constraint between  deformable objects faces and deformable objects nodes
+class btDeformableFaceNodeContactConstraint : public btDeformableContactConstraint
+{
+public:
+       btSoftBody::Node* m_node;
+       btSoftBody::Face* m_face;
+       const btSoftBody::DeformableFaceNodeContact* m_contact;
+       btVector3 m_total_normal_dv;
+       btVector3 m_total_tangent_dv;
+
+       btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact, const btContactSolverInfo& infoGlobal);
+       btDeformableFaceNodeContactConstraint() {}
+       virtual ~btDeformableFaceNodeContactConstraint() {}
+
+       virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
+
+       // get the velocity of the object A in the contact
+       virtual btVector3 getVa() const;
+
+       // get the velocity of the object B in the contact
+       virtual btVector3 getVb() const;
+
+       // get the velocity change of the input soft body node in the constraint
+       virtual btVector3 getDv(const btSoftBody::Node*) const;
+
+       // cast the contact to the desired type
+       const btSoftBody::DeformableFaceNodeContact* getContact() const
+       {
+               return static_cast<const btSoftBody::DeformableFaceNodeContact*>(m_contact);
+       }
+
+       virtual void applyImpulse(const btVector3& impulse);
+
+       virtual void setPenetrationScale(btScalar scale) {}
+};
+#endif /* BT_DEFORMABLE_CONTACT_CONSTRAINT_H */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactProjection.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactProjection.cpp
new file mode 100644 (file)
index 0000000..7f67260
--- /dev/null
@@ -0,0 +1,639 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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 "btDeformableContactProjection.h"
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include <algorithm>
+#include <cmath>
+btScalar btDeformableContactProjection::update(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
+{
+       btScalar residualSquare = 0;
+       for (int i = 0; i < numDeformableBodies; ++i)
+       {
+               for (int j = 0; j < m_softBodies.size(); ++j)
+               {
+                       btCollisionObject* psb = m_softBodies[j];
+                       if (psb != deformableBodies[i])
+                       {
+                               continue;
+                       }
+                       for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
+                       {
+                               btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k];
+                               btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+                               residualSquare = btMax(residualSquare, localResidualSquare);
+                       }
+                       for (int k = 0; k < m_nodeAnchorConstraints[j].size(); ++k)
+                       {
+                               btDeformableNodeAnchorConstraint& constraint = m_nodeAnchorConstraints[j][k];
+                               btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+                               residualSquare = btMax(residualSquare, localResidualSquare);
+                       }
+                       for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
+                       {
+                               btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k];
+                               btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+                               residualSquare = btMax(residualSquare, localResidualSquare);
+                       }
+                       for (int k = 0; k < m_deformableConstraints[j].size(); ++k)
+                       {
+                               btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[j][k];
+                               btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
+                               residualSquare = btMax(residualSquare, localResidualSquare);
+                       }
+               }
+       }
+       return residualSquare;
+}
+
+btScalar btDeformableContactProjection::solveSplitImpulse(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
+{
+       btScalar residualSquare = 0;
+       for (int i = 0; i < numDeformableBodies; ++i)
+       {
+               for (int j = 0; j < m_softBodies.size(); ++j)
+               {
+                       btCollisionObject* psb = m_softBodies[j];
+                       if (psb != deformableBodies[i])
+                       {
+                               continue;
+                       }
+                       for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
+                       {
+                               btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k];
+                               btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
+                               residualSquare = btMax(residualSquare, localResidualSquare);
+                       }
+                       for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
+                       {
+                               btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k];
+                               btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
+                               residualSquare = btMax(residualSquare, localResidualSquare);
+                       }
+               }
+       }
+       return residualSquare;
+}
+
+void btDeformableContactProjection::setConstraints(const btContactSolverInfo& infoGlobal)
+{
+       BT_PROFILE("setConstraints");
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (!psb->isActive())
+               {
+                       continue;
+               }
+
+               // set Dirichlet constraint
+               for (int j = 0; j < psb->m_nodes.size(); ++j)
+               {
+                       if (psb->m_nodes[j].m_im == 0)
+                       {
+                               btDeformableStaticConstraint static_constraint(&psb->m_nodes[j], infoGlobal);
+                               m_staticConstraints[i].push_back(static_constraint);
+                       }
+               }
+
+               // set up deformable anchors
+               for (int j = 0; j < psb->m_deformableAnchors.size(); ++j)
+               {
+                       btSoftBody::DeformableNodeRigidAnchor& anchor = psb->m_deformableAnchors[j];
+                       // skip fixed points
+                       if (anchor.m_node->m_im == 0)
+                       {
+                               continue;
+                       }
+                       anchor.m_c1 = anchor.m_cti.m_colObj->getWorldTransform().getBasis() * anchor.m_local;
+                       btDeformableNodeAnchorConstraint constraint(anchor, infoGlobal);
+                       m_nodeAnchorConstraints[i].push_back(constraint);
+               }
+
+               // set Deformable Node vs. Rigid constraint
+               for (int j = 0; j < psb->m_nodeRigidContacts.size(); ++j)
+               {
+                       const btSoftBody::DeformableNodeRigidContact& contact = psb->m_nodeRigidContacts[j];
+                       // skip fixed points
+                       if (contact.m_node->m_im == 0)
+                       {
+                               continue;
+                       }
+                       btDeformableNodeRigidContactConstraint constraint(contact, infoGlobal);
+                       m_nodeRigidConstraints[i].push_back(constraint);
+               }
+
+               // set Deformable Face vs. Rigid constraint
+               for (int j = 0; j < psb->m_faceRigidContacts.size(); ++j)
+               {
+                       const btSoftBody::DeformableFaceRigidContact& contact = psb->m_faceRigidContacts[j];
+                       // skip fixed faces
+                       if (contact.m_c2 == 0)
+                       {
+                               continue;
+                       }
+                       btDeformableFaceRigidContactConstraint constraint(contact, infoGlobal, m_useStrainLimiting);
+                       m_faceRigidConstraints[i].push_back(constraint);
+               }
+       }
+}
+
+void btDeformableContactProjection::project(TVStack& x)
+{
+#ifndef USE_MGS
+       const int dim = 3;
+       for (int index = 0; index < m_projectionsDict.size(); ++index)
+       {
+               btAlignedObjectArray<btVector3>& projectionDirs = *m_projectionsDict.getAtIndex(index);
+               size_t i = m_projectionsDict.getKeyAtIndex(index).getUid1();
+               if (projectionDirs.size() >= dim)
+               {
+                       // static node
+                       x[i].setZero();
+                       continue;
+               }
+               else if (projectionDirs.size() == 2)
+               {
+                       btVector3 dir0 = projectionDirs[0];
+                       btVector3 dir1 = projectionDirs[1];
+                       btVector3 free_dir = btCross(dir0, dir1);
+                       if (free_dir.safeNorm() < SIMD_EPSILON)
+                       {
+                               x[i] -= x[i].dot(dir0) * dir0;
+                       }
+                       else
+                       {
+                               free_dir.normalize();
+                               x[i] = x[i].dot(free_dir) * free_dir;
+                       }
+               }
+               else
+               {
+                       btAssert(projectionDirs.size() == 1);
+                       btVector3 dir0 = projectionDirs[0];
+                       x[i] -= x[i].dot(dir0) * dir0;
+               }
+       }
+#else
+       btReducedVector p(x.size());
+       for (int i = 0; i < m_projections.size(); ++i)
+       {
+               p += (m_projections[i].dot(x) * m_projections[i]);
+       }
+       for (int i = 0; i < p.m_indices.size(); ++i)
+       {
+               x[p.m_indices[i]] -= p.m_vecs[i];
+       }
+#endif
+}
+
+void btDeformableContactProjection::setProjection()
+{
+#ifndef USE_MGS
+       BT_PROFILE("btDeformableContactProjection::setProjection");
+       btAlignedObjectArray<btVector3> units;
+       units.push_back(btVector3(1, 0, 0));
+       units.push_back(btVector3(0, 1, 0));
+       units.push_back(btVector3(0, 0, 1));
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (!psb->isActive())
+               {
+                       continue;
+               }
+               for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+               {
+                       int index = m_staticConstraints[i][j].m_node->index;
+                       m_staticConstraints[i][j].m_node->m_constrained = true;
+                       if (m_projectionsDict.find(index) == NULL)
+                       {
+                               m_projectionsDict.insert(index, units);
+                       }
+                       else
+                       {
+                               btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                               for (int k = 0; k < 3; ++k)
+                               {
+                                       projections.push_back(units[k]);
+                               }
+                       }
+               }
+               for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+               {
+                       int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
+                       m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_constrained = true;
+                       if (m_projectionsDict.find(index) == NULL)
+                       {
+                               m_projectionsDict.insert(index, units);
+                       }
+                       else
+                       {
+                               btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                               for (int k = 0; k < 3; ++k)
+                               {
+                                       projections.push_back(units[k]);
+                               }
+                       }
+               }
+               for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+               {
+                       int index = m_nodeRigidConstraints[i][j].m_node->index;
+                       m_nodeRigidConstraints[i][j].m_node->m_constrained = true;
+                       if (m_nodeRigidConstraints[i][j].m_binding)
+                       {
+                               if (m_nodeRigidConstraints[i][j].m_static)
+                               {
+                                       if (m_projectionsDict.find(index) == NULL)
+                                       {
+                                               m_projectionsDict.insert(index, units);
+                                       }
+                                       else
+                                       {
+                                               btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                                               for (int k = 0; k < 3; ++k)
+                                               {
+                                                       projections.push_back(units[k]);
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       if (m_projectionsDict.find(index) == NULL)
+                                       {
+                                               btAlignedObjectArray<btVector3> projections;
+                                               projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
+                                               m_projectionsDict.insert(index, projections);
+                                       }
+                                       else
+                                       {
+                                               btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                                               projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
+                                       }
+                               }
+                       }
+               }
+               for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+               {
+                       const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
+                       if (m_faceRigidConstraints[i][j].m_binding)
+                       {
+                               for (int k = 0; k < 3; ++k)
+                               {
+                                       face->m_n[k]->m_constrained = true;
+                               }
+                       }
+                       for (int k = 0; k < 3; ++k)
+                       {
+                               btSoftBody::Node* node = face->m_n[k];
+                               int index = node->index;
+                               if (m_faceRigidConstraints[i][j].m_static)
+                               {
+                                       if (m_projectionsDict.find(index) == NULL)
+                                       {
+                                               m_projectionsDict.insert(index, units);
+                                       }
+                                       else
+                                       {
+                                               btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                                               for (int l = 0; l < 3; ++l)
+                                               {
+                                                       projections.push_back(units[l]);
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       if (m_projectionsDict.find(index) == NULL)
+                                       {
+                                               btAlignedObjectArray<btVector3> projections;
+                                               projections.push_back(m_faceRigidConstraints[i][j].m_normal);
+                                               m_projectionsDict.insert(index, projections);
+                                       }
+                                       else
+                                       {
+                                               btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
+                                               projections.push_back(m_faceRigidConstraints[i][j].m_normal);
+                                       }
+                               }
+                       }
+               }
+       }
+#else
+       int dof = 0;
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               dof += m_softBodies[i]->m_nodes.size();
+       }
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (!psb->isActive())
+               {
+                       continue;
+               }
+               for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+               {
+                       int index = m_staticConstraints[i][j].m_node->index;
+                       m_staticConstraints[i][j].m_node->m_penetration = SIMD_INFINITY;
+                       btAlignedObjectArray<int> indices;
+                       btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
+                       indices.push_back(index);
+                       vecs1.push_back(btVector3(1, 0, 0));
+                       vecs2.push_back(btVector3(0, 1, 0));
+                       vecs3.push_back(btVector3(0, 0, 1));
+                       m_projections.push_back(btReducedVector(dof, indices, vecs1));
+                       m_projections.push_back(btReducedVector(dof, indices, vecs2));
+                       m_projections.push_back(btReducedVector(dof, indices, vecs3));
+               }
+
+               for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+               {
+                       int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
+                       m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_penetration = SIMD_INFINITY;
+                       btAlignedObjectArray<int> indices;
+                       btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
+                       indices.push_back(index);
+                       vecs1.push_back(btVector3(1, 0, 0));
+                       vecs2.push_back(btVector3(0, 1, 0));
+                       vecs3.push_back(btVector3(0, 0, 1));
+                       m_projections.push_back(btReducedVector(dof, indices, vecs1));
+                       m_projections.push_back(btReducedVector(dof, indices, vecs2));
+                       m_projections.push_back(btReducedVector(dof, indices, vecs3));
+               }
+               for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+               {
+                       int index = m_nodeRigidConstraints[i][j].m_node->index;
+                       m_nodeRigidConstraints[i][j].m_node->m_penetration = -m_nodeRigidConstraints[i][j].getContact()->m_cti.m_offset;
+                       btAlignedObjectArray<int> indices;
+                       indices.push_back(index);
+                       btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
+                       if (m_nodeRigidConstraints[i][j].m_static)
+                       {
+                               vecs1.push_back(btVector3(1, 0, 0));
+                               vecs2.push_back(btVector3(0, 1, 0));
+                               vecs3.push_back(btVector3(0, 0, 1));
+                               m_projections.push_back(btReducedVector(dof, indices, vecs1));
+                               m_projections.push_back(btReducedVector(dof, indices, vecs2));
+                               m_projections.push_back(btReducedVector(dof, indices, vecs3));
+                       }
+                       else
+                       {
+                               vecs1.push_back(m_nodeRigidConstraints[i][j].m_normal);
+                               m_projections.push_back(btReducedVector(dof, indices, vecs1));
+                       }
+               }
+               for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+               {
+                       const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
+                       btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
+                       btScalar penetration = -m_faceRigidConstraints[i][j].getContact()->m_cti.m_offset;
+                       for (int k = 0; k < 3; ++k)
+                       {
+                               face->m_n[k]->m_penetration = btMax(face->m_n[k]->m_penetration, penetration);
+                       }
+                       if (m_faceRigidConstraints[i][j].m_static)
+                       {
+                               for (int l = 0; l < 3; ++l)
+                               {
+                                       btReducedVector rv(dof);
+                                       for (int k = 0; k < 3; ++k)
+                                       {
+                                               rv.m_indices.push_back(face->m_n[k]->index);
+                                               btVector3 v(0, 0, 0);
+                                               v[l] = bary[k];
+                                               rv.m_vecs.push_back(v);
+                                               rv.sort();
+                                       }
+                                       m_projections.push_back(rv);
+                               }
+                       }
+                       else
+                       {
+                               btReducedVector rv(dof);
+                               for (int k = 0; k < 3; ++k)
+                               {
+                                       rv.m_indices.push_back(face->m_n[k]->index);
+                                       rv.m_vecs.push_back(bary[k] * m_faceRigidConstraints[i][j].m_normal);
+                                       rv.sort();
+                               }
+                               m_projections.push_back(rv);
+                       }
+               }
+       }
+       btModifiedGramSchmidt<btReducedVector> mgs(m_projections);
+       mgs.solve();
+       m_projections = mgs.m_out;
+#endif
+}
+
+void btDeformableContactProjection::checkConstraints(const TVStack& x)
+{
+       for (int i = 0; i < m_lagrangeMultipliers.size(); ++i)
+       {
+               btVector3 d(0, 0, 0);
+               const LagrangeMultiplier& lm = m_lagrangeMultipliers[i];
+               for (int j = 0; j < lm.m_num_constraints; ++j)
+               {
+                       for (int k = 0; k < lm.m_num_nodes; ++k)
+                       {
+                               d[j] += lm.m_weights[k] * x[lm.m_indices[k]].dot(lm.m_dirs[j]);
+                       }
+               }
+               //              printf("d = %f, %f, %f\n", d[0], d[1], d[2]);
+               //        printf("val = %f, %f, %f\n", lm.m_vals[0], lm.m_vals[1], lm.m_vals[2]);
+       }
+}
+
+void btDeformableContactProjection::setLagrangeMultiplier()
+{
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (!psb->isActive())
+               {
+                       continue;
+               }
+               for (int j = 0; j < m_staticConstraints[i].size(); ++j)
+               {
+                       int index = m_staticConstraints[i][j].m_node->index;
+                       m_staticConstraints[i][j].m_node->m_constrained = true;
+                       LagrangeMultiplier lm;
+                       lm.m_num_nodes = 1;
+                       lm.m_indices[0] = index;
+                       lm.m_weights[0] = 1.0;
+                       lm.m_num_constraints = 3;
+                       lm.m_dirs[0] = btVector3(1, 0, 0);
+                       lm.m_dirs[1] = btVector3(0, 1, 0);
+                       lm.m_dirs[2] = btVector3(0, 0, 1);
+                       m_lagrangeMultipliers.push_back(lm);
+               }
+               for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
+               {
+                       int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
+                       m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_constrained = true;
+                       LagrangeMultiplier lm;
+                       lm.m_num_nodes = 1;
+                       lm.m_indices[0] = index;
+                       lm.m_weights[0] = 1.0;
+                       lm.m_num_constraints = 3;
+                       lm.m_dirs[0] = btVector3(1, 0, 0);
+                       lm.m_dirs[1] = btVector3(0, 1, 0);
+                       lm.m_dirs[2] = btVector3(0, 0, 1);
+                       m_lagrangeMultipliers.push_back(lm);
+               }
+
+               for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+               {
+                       if (!m_nodeRigidConstraints[i][j].m_binding)
+                       {
+                               continue;
+                       }
+                       int index = m_nodeRigidConstraints[i][j].m_node->index;
+                       m_nodeRigidConstraints[i][j].m_node->m_constrained = true;
+                       LagrangeMultiplier lm;
+                       lm.m_num_nodes = 1;
+                       lm.m_indices[0] = index;
+                       lm.m_weights[0] = 1.0;
+                       if (m_nodeRigidConstraints[i][j].m_static)
+                       {
+                               lm.m_num_constraints = 3;
+                               lm.m_dirs[0] = btVector3(1, 0, 0);
+                               lm.m_dirs[1] = btVector3(0, 1, 0);
+                               lm.m_dirs[2] = btVector3(0, 0, 1);
+                       }
+                       else
+                       {
+                               lm.m_num_constraints = 1;
+                               lm.m_dirs[0] = m_nodeRigidConstraints[i][j].m_normal;
+                       }
+                       m_lagrangeMultipliers.push_back(lm);
+               }
+
+               for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+               {
+                       if (!m_faceRigidConstraints[i][j].m_binding)
+                       {
+                               continue;
+                       }
+                       btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
+
+                       btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
+                       LagrangeMultiplier lm;
+                       lm.m_num_nodes = 3;
+
+                       for (int k = 0; k < 3; ++k)
+                       {
+                               face->m_n[k]->m_constrained = true;
+                               lm.m_indices[k] = face->m_n[k]->index;
+                               lm.m_weights[k] = bary[k];
+                       }
+                       if (m_faceRigidConstraints[i][j].m_static)
+                       {
+                               face->m_pcontact[3] = 1;
+                               lm.m_num_constraints = 3;
+                               lm.m_dirs[0] = btVector3(1, 0, 0);
+                               lm.m_dirs[1] = btVector3(0, 1, 0);
+                               lm.m_dirs[2] = btVector3(0, 0, 1);
+                       }
+                       else
+                       {
+                               face->m_pcontact[3] = 0;
+                               lm.m_num_constraints = 1;
+                               lm.m_dirs[0] = m_faceRigidConstraints[i][j].m_normal;
+                       }
+                       m_lagrangeMultipliers.push_back(lm);
+               }
+       }
+}
+
+//
+void btDeformableContactProjection::applyDynamicFriction(TVStack& f)
+{
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
+               {
+                       const btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[i][j];
+                       const btSoftBody::Node* node = constraint.m_node;
+                       if (node->m_im != 0)
+                       {
+                               int index = node->index;
+                               f[index] += constraint.getDv(node) * (1. / node->m_im);
+                       }
+               }
+               for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
+               {
+                       const btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[i][j];
+                       const btSoftBody::Face* face = constraint.getContact()->m_face;
+                       for (int k = 0; k < 3; ++k)
+                       {
+                               const btSoftBody::Node* node = face->m_n[k];
+                               if (node->m_im != 0)
+                               {
+                                       int index = node->index;
+                                       f[index] += constraint.getDv(node) * (1. / node->m_im);
+                               }
+                       }
+               }
+               for (int j = 0; j < m_deformableConstraints[i].size(); ++j)
+               {
+                       const btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[i][j];
+                       const btSoftBody::Face* face = constraint.getContact()->m_face;
+                       const btSoftBody::Node* node = constraint.getContact()->m_node;
+                       if (node->m_im != 0)
+                       {
+                               int index = node->index;
+                               f[index] += constraint.getDv(node) * (1. / node->m_im);
+                       }
+                       for (int k = 0; k < 3; ++k)
+                       {
+                               const btSoftBody::Node* node = face->m_n[k];
+                               if (node->m_im != 0)
+                               {
+                                       int index = node->index;
+                                       f[index] += constraint.getDv(node) * (1. / node->m_im);
+                               }
+                       }
+               }
+       }
+}
+
+void btDeformableContactProjection::reinitialize(bool nodeUpdated)
+{
+       int N = m_softBodies.size();
+       if (nodeUpdated)
+       {
+               m_staticConstraints.resize(N);
+               m_nodeAnchorConstraints.resize(N);
+               m_nodeRigidConstraints.resize(N);
+               m_faceRigidConstraints.resize(N);
+               m_deformableConstraints.resize(N);
+       }
+       for (int i = 0; i < N; ++i)
+       {
+               m_staticConstraints[i].clear();
+               m_nodeAnchorConstraints[i].clear();
+               m_nodeRigidConstraints[i].clear();
+               m_faceRigidConstraints[i].clear();
+               m_deformableConstraints[i].clear();
+       }
+#ifndef USE_MGS
+       m_projectionsDict.clear();
+#else
+       m_projections.clear();
+#endif
+       m_lagrangeMultipliers.clear();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactProjection.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableContactProjection.h
new file mode 100644 (file)
index 0000000..4964eaf
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_CONTACT_PROJECTION_H
+#define BT_CONTACT_PROJECTION_H
+#include "btCGProjection.h"
+#include "btSoftBody.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+#include "btDeformableContactConstraint.h"
+#include "LinearMath/btHashMap.h"
+#include "LinearMath/btReducedVector.h"
+#include "LinearMath/btModifiedGramSchmidt.h"
+#include <vector>
+
+struct LagrangeMultiplier
+{
+       int m_num_constraints;  // Number of constraints
+       int m_num_nodes;        // Number of nodes in these constraints
+       btScalar m_weights[3];  // weights of the nodes involved, same size as m_num_nodes
+       btVector3 m_dirs[3];    // Constraint directions, same size of m_num_constraints;
+       int m_indices[3];       // indices of the nodes involved, same size as m_num_nodes;
+};
+
+class btDeformableContactProjection
+{
+public:
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       btAlignedObjectArray<btSoftBody*>& m_softBodies;
+
+       // all constraints involving face
+       btAlignedObjectArray<btDeformableContactConstraint*> m_allFaceConstraints;
+#ifndef USE_MGS
+       // map from node index to projection directions
+       btHashMap<btHashInt, btAlignedObjectArray<btVector3> > m_projectionsDict;
+#else
+       btAlignedObjectArray<btReducedVector> m_projections;
+#endif
+
+       btAlignedObjectArray<LagrangeMultiplier> m_lagrangeMultipliers;
+
+       // map from node index to static constraint
+       btAlignedObjectArray<btAlignedObjectArray<btDeformableStaticConstraint> > m_staticConstraints;
+       // map from node index to node rigid constraint
+       btAlignedObjectArray<btAlignedObjectArray<btDeformableNodeRigidContactConstraint> > m_nodeRigidConstraints;
+       // map from node index to face rigid constraint
+       btAlignedObjectArray<btAlignedObjectArray<btDeformableFaceRigidContactConstraint> > m_faceRigidConstraints;
+       // map from node index to deformable constraint
+       btAlignedObjectArray<btAlignedObjectArray<btDeformableFaceNodeContactConstraint> > m_deformableConstraints;
+       // map from node index to node anchor constraint
+       btAlignedObjectArray<btAlignedObjectArray<btDeformableNodeAnchorConstraint> > m_nodeAnchorConstraints;
+
+       bool m_useStrainLimiting;
+
+       btDeformableContactProjection(btAlignedObjectArray<btSoftBody*>& softBodies)
+               : m_softBodies(softBodies)
+       {
+       }
+
+       virtual ~btDeformableContactProjection()
+       {
+       }
+
+       // apply the constraints to the rhs of the linear solve
+       virtual void project(TVStack& x);
+
+       // add friction force to the rhs of the linear solve
+       virtual void applyDynamicFriction(TVStack& f);
+
+       // update and solve the constraints
+       virtual btScalar update(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal);
+
+       // Add constraints to m_constraints. In addition, the constraints that each vertex own are recorded in m_constraintsDict.
+       virtual void setConstraints(const btContactSolverInfo& infoGlobal);
+
+       // Set up projections for each vertex by adding the projection direction to
+       virtual void setProjection();
+
+       virtual void reinitialize(bool nodeUpdated);
+
+       btScalar solveSplitImpulse(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal);
+
+       virtual void setLagrangeMultiplier();
+
+       void checkConstraints(const TVStack& x);
+};
+#endif /* btDeformableContactProjection_h */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableCorotatedForce.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableCorotatedForce.h
new file mode 100644 (file)
index 0000000..dfd8552
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_COROTATED_H
+#define BT_COROTATED_H
+
+#include "btDeformableLagrangianForce.h"
+#include "LinearMath/btPolarDecomposition.h"
+
+static inline int PolarDecomposition(const btMatrix3x3& m, btMatrix3x3& q, btMatrix3x3& s)
+{
+       static const btPolarDecomposition polar;
+       return polar.decompose(m, q, s);
+}
+
+class btDeformableCorotatedForce : public btDeformableLagrangianForce
+{
+public:
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       btScalar m_mu, m_lambda;
+       btDeformableCorotatedForce() : m_mu(1), m_lambda(1)
+       {
+       }
+
+       btDeformableCorotatedForce(btScalar mu, btScalar lambda) : m_mu(mu), m_lambda(lambda)
+       {
+       }
+
+       virtual void addScaledForces(btScalar scale, TVStack& force)
+       {
+               addScaledElasticForce(scale, force);
+       }
+
+       virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+       {
+               addScaledElasticForce(scale, force);
+       }
+
+       virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+       {
+       }
+
+       virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+       {
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= force.size());
+               btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_tetras.size(); ++j)
+                       {
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btMatrix3x3 P;
+                               firstPiola(tetra.m_F, P);
+                               btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose() * grad_N_hat_1st_col);
+                               btMatrix3x3 force_on_node123 = P * tetra.m_Dm_inverse.transpose();
+
+                               btSoftBody::Node* node0 = tetra.m_n[0];
+                               btSoftBody::Node* node1 = tetra.m_n[1];
+                               btSoftBody::Node* node2 = tetra.m_n[2];
+                               btSoftBody::Node* node3 = tetra.m_n[3];
+                               size_t id0 = node0->index;
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               size_t id3 = node3->index;
+
+                               // elastic force
+                               // explicit elastic force
+                               btScalar scale1 = scale * tetra.m_element_measure;
+                               force[id0] -= scale1 * force_on_node0;
+                               force[id1] -= scale1 * force_on_node123.getColumn(0);
+                               force[id2] -= scale1 * force_on_node123.getColumn(1);
+                               force[id3] -= scale1 * force_on_node123.getColumn(2);
+                       }
+               }
+       }
+
+       void firstPiola(const btMatrix3x3& F, btMatrix3x3& P)
+       {
+               // btMatrix3x3 JFinvT = F.adjoint();
+               btScalar J = F.determinant();
+               P = F.adjoint().transpose() * (m_lambda * (J - 1));
+               if (m_mu > SIMD_EPSILON)
+               {
+                       btMatrix3x3 R, S;
+                       if (J < 1024 * SIMD_EPSILON)
+                               R.setIdentity();
+                       else
+                               PolarDecomposition(F, R, S);  // this QR is not robust, consider using implicit shift svd
+                       /*https://fuchuyuan.github.io/research/svd/paper.pdf*/
+                       P += (F - R) * 2 * m_mu;
+               }
+       }
+
+       virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+       {
+       }
+
+       virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+       {
+       }
+
+       virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) {}
+
+       virtual btDeformableLagrangianForceType getForceType()
+       {
+               return BT_COROTATED_FORCE;
+       }
+};
+
+#endif /* btCorotated_h */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableGravityForce.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableGravityForce.h
new file mode 100644 (file)
index 0000000..d91867f
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_DEFORMABLE_GRAVITY_FORCE_H
+#define BT_DEFORMABLE_GRAVITY_FORCE_H
+
+#include "btDeformableLagrangianForce.h"
+
+class btDeformableGravityForce : public btDeformableLagrangianForce
+{
+public:
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       btVector3 m_gravity;
+
+       btDeformableGravityForce(const btVector3& g) : m_gravity(g)
+       {
+       }
+
+       virtual void addScaledForces(btScalar scale, TVStack& force)
+       {
+               addScaledGravityForce(scale, force);
+       }
+
+       virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+       {
+               addScaledGravityForce(scale, force);
+       }
+
+       virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+       {
+       }
+
+       virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+       {
+       }
+
+       virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+       {
+       }
+
+       virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) {}
+
+       virtual void addScaledGravityForce(btScalar scale, TVStack& force)
+       {
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= force.size());
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               btSoftBody::Node& n = psb->m_nodes[j];
+                               size_t id = n.index;
+                               btScalar mass = (n.m_im == 0) ? 0 : 1. / n.m_im;
+                               btVector3 scaled_force = scale * m_gravity * mass * m_softBodies[i]->m_gravityFactor;
+                               force[id] += scaled_force;
+                       }
+               }
+       }
+
+       virtual btDeformableLagrangianForceType getForceType()
+       {
+               return BT_GRAVITY_FORCE;
+       }
+
+       // the gravitational potential energy
+       virtual double totalEnergy(btScalar dt)
+       {
+               double e = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               const btSoftBody::Node& node = psb->m_nodes[j];
+                               if (node.m_im > 0)
+                               {
+                                       e -= m_gravity.dot(node.m_q) / node.m_im;
+                               }
+                       }
+               }
+               return e;
+       }
+};
+#endif /* BT_DEFORMABLE_GRAVITY_FORCE_H */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableLagrangianForce.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableLagrangianForce.h
new file mode 100644 (file)
index 0000000..d58d825
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_DEFORMABLE_LAGRANGIAN_FORCE_H
+#define BT_DEFORMABLE_LAGRANGIAN_FORCE_H
+
+#include "btSoftBody.h"
+#include <LinearMath/btHashMap.h>
+#include <iostream>
+
+enum btDeformableLagrangianForceType
+{
+       BT_GRAVITY_FORCE = 1,
+       BT_MASSSPRING_FORCE = 2,
+       BT_COROTATED_FORCE = 3,
+       BT_NEOHOOKEAN_FORCE = 4,
+       BT_LINEAR_ELASTICITY_FORCE = 5,
+       BT_MOUSE_PICKING_FORCE = 6
+};
+
+static inline double randomDouble(double low, double high)
+{
+       return low + static_cast<double>(rand()) / RAND_MAX * (high - low);
+}
+
+class btDeformableLagrangianForce
+{
+public:
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       btAlignedObjectArray<btSoftBody*> m_softBodies;
+       const btAlignedObjectArray<btSoftBody::Node*>* m_nodes;
+
+       btDeformableLagrangianForce()
+       {
+       }
+
+       virtual ~btDeformableLagrangianForce() {}
+
+       // add all forces
+       virtual void addScaledForces(btScalar scale, TVStack& force) = 0;
+
+       // add damping df
+       virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df) = 0;
+
+       // build diagonal of A matrix
+       virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) = 0;
+
+       // add elastic df
+       virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df) = 0;
+
+       // add all forces that are explicit in explicit solve
+       virtual void addScaledExplicitForce(btScalar scale, TVStack& force) = 0;
+
+       // add all damping forces
+       virtual void addScaledDampingForce(btScalar scale, TVStack& force) = 0;
+
+       virtual void addScaledHessian(btScalar scale) {}
+
+       virtual btDeformableLagrangianForceType getForceType() = 0;
+
+       virtual void reinitialize(bool nodeUpdated)
+       {
+       }
+
+       // get number of nodes that have the force
+       virtual int getNumNodes()
+       {
+               int numNodes = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       numNodes += m_softBodies[i]->m_nodes.size();
+               }
+               return numNodes;
+       }
+
+       // add a soft body to be affected by the particular lagrangian force
+       virtual void addSoftBody(btSoftBody* psb)
+       {
+               m_softBodies.push_back(psb);
+       }
+
+       virtual void removeSoftBody(btSoftBody* psb)
+       {
+               m_softBodies.remove(psb);
+       }
+
+       virtual void setIndices(const btAlignedObjectArray<btSoftBody::Node*>* nodes)
+       {
+               m_nodes = nodes;
+       }
+
+       // Calculate the incremental deformable generated from the input dx
+       virtual btMatrix3x3 Ds(int id0, int id1, int id2, int id3, const TVStack& dx)
+       {
+               btVector3 c1 = dx[id1] - dx[id0];
+               btVector3 c2 = dx[id2] - dx[id0];
+               btVector3 c3 = dx[id3] - dx[id0];
+               return btMatrix3x3(c1, c2, c3).transpose();
+       }
+
+       // Calculate the incremental deformable generated from the current velocity
+       virtual btMatrix3x3 DsFromVelocity(const btSoftBody::Node* n0, const btSoftBody::Node* n1, const btSoftBody::Node* n2, const btSoftBody::Node* n3)
+       {
+               btVector3 c1 = n1->m_v - n0->m_v;
+               btVector3 c2 = n2->m_v - n0->m_v;
+               btVector3 c3 = n3->m_v - n0->m_v;
+               return btMatrix3x3(c1, c2, c3).transpose();
+       }
+
+       // test for addScaledElasticForce function
+       virtual void testDerivative()
+       {
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               psb->m_nodes[j].m_q += btVector3(randomDouble(-.1, .1), randomDouble(-.1, .1), randomDouble(-.1, .1));
+                       }
+                       psb->updateDeformation();
+               }
+
+               TVStack dx;
+               dx.resize(getNumNodes());
+               TVStack dphi_dx;
+               dphi_dx.resize(dx.size());
+               for (int i = 0; i < dphi_dx.size(); ++i)
+               {
+                       dphi_dx[i].setZero();
+               }
+               addScaledForces(-1, dphi_dx);
+
+               // write down the current position
+               TVStack x;
+               x.resize(dx.size());
+               int counter = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               x[counter] = psb->m_nodes[j].m_q;
+                               counter++;
+                       }
+               }
+               counter = 0;
+
+               // populate dx with random vectors
+               for (int i = 0; i < dx.size(); ++i)
+               {
+                       dx[i].setX(randomDouble(-1, 1));
+                       dx[i].setY(randomDouble(-1, 1));
+                       dx[i].setZ(randomDouble(-1, 1));
+               }
+
+               btAlignedObjectArray<double> errors;
+               for (int it = 0; it < 10; ++it)
+               {
+                       for (int i = 0; i < dx.size(); ++i)
+                       {
+                               dx[i] *= 0.5;
+                       }
+
+                       // get dphi/dx * dx
+                       double dphi = 0;
+                       for (int i = 0; i < dx.size(); ++i)
+                       {
+                               dphi += dphi_dx[i].dot(dx[i]);
+                       }
+
+                       for (int i = 0; i < m_softBodies.size(); ++i)
+                       {
+                               btSoftBody* psb = m_softBodies[i];
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                               {
+                                       psb->m_nodes[j].m_q = x[counter] + dx[counter];
+                                       counter++;
+                               }
+                               psb->updateDeformation();
+                       }
+                       counter = 0;
+                       double f1 = totalElasticEnergy(0);
+
+                       for (int i = 0; i < m_softBodies.size(); ++i)
+                       {
+                               btSoftBody* psb = m_softBodies[i];
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                               {
+                                       psb->m_nodes[j].m_q = x[counter] - dx[counter];
+                                       counter++;
+                               }
+                               psb->updateDeformation();
+                       }
+                       counter = 0;
+
+                       double f2 = totalElasticEnergy(0);
+
+                       //restore m_q
+                       for (int i = 0; i < m_softBodies.size(); ++i)
+                       {
+                               btSoftBody* psb = m_softBodies[i];
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                               {
+                                       psb->m_nodes[j].m_q = x[counter];
+                                       counter++;
+                               }
+                               psb->updateDeformation();
+                       }
+                       counter = 0;
+                       double error = f1 - f2 - 2 * dphi;
+                       errors.push_back(error);
+                       std::cout << "Iteration = " << it << ", f1 = " << f1 << ", f2 = " << f2 << ", error = " << error << std::endl;
+               }
+               for (int i = 1; i < errors.size(); ++i)
+               {
+                       std::cout << "Iteration = " << i << ", ratio = " << errors[i - 1] / errors[i] << std::endl;
+               }
+       }
+
+       // test for addScaledElasticForce function
+       virtual void testHessian()
+       {
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               psb->m_nodes[j].m_q += btVector3(randomDouble(-.1, .1), randomDouble(-.1, .1), randomDouble(-.1, .1));
+                       }
+                       psb->updateDeformation();
+               }
+
+               TVStack dx;
+               dx.resize(getNumNodes());
+               TVStack df;
+               df.resize(dx.size());
+               TVStack f1;
+               f1.resize(dx.size());
+               TVStack f2;
+               f2.resize(dx.size());
+
+               // write down the current position
+               TVStack x;
+               x.resize(dx.size());
+               int counter = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               x[counter] = psb->m_nodes[j].m_q;
+                               counter++;
+                       }
+               }
+               counter = 0;
+
+               // populate dx with random vectors
+               for (int i = 0; i < dx.size(); ++i)
+               {
+                       dx[i].setX(randomDouble(-1, 1));
+                       dx[i].setY(randomDouble(-1, 1));
+                       dx[i].setZ(randomDouble(-1, 1));
+               }
+
+               btAlignedObjectArray<double> errors;
+               for (int it = 0; it < 10; ++it)
+               {
+                       for (int i = 0; i < dx.size(); ++i)
+                       {
+                               dx[i] *= 0.5;
+                       }
+
+                       // get df
+                       for (int i = 0; i < df.size(); ++i)
+                       {
+                               df[i].setZero();
+                               f1[i].setZero();
+                               f2[i].setZero();
+                       }
+
+                       //set df
+                       addScaledElasticForceDifferential(-1, dx, df);
+
+                       for (int i = 0; i < m_softBodies.size(); ++i)
+                       {
+                               btSoftBody* psb = m_softBodies[i];
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                               {
+                                       psb->m_nodes[j].m_q = x[counter] + dx[counter];
+                                       counter++;
+                               }
+                               psb->updateDeformation();
+                       }
+                       counter = 0;
+
+                       //set f1
+                       addScaledForces(-1, f1);
+
+                       for (int i = 0; i < m_softBodies.size(); ++i)
+                       {
+                               btSoftBody* psb = m_softBodies[i];
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                               {
+                                       psb->m_nodes[j].m_q = x[counter] - dx[counter];
+                                       counter++;
+                               }
+                               psb->updateDeformation();
+                       }
+                       counter = 0;
+
+                       //set f2
+                       addScaledForces(-1, f2);
+
+                       //restore m_q
+                       for (int i = 0; i < m_softBodies.size(); ++i)
+                       {
+                               btSoftBody* psb = m_softBodies[i];
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                               {
+                                       psb->m_nodes[j].m_q = x[counter];
+                                       counter++;
+                               }
+                               psb->updateDeformation();
+                       }
+                       counter = 0;
+                       double error = 0;
+                       for (int i = 0; i < df.size(); ++i)
+                       {
+                               btVector3 error_vector = f1[i] - f2[i] - 2 * df[i];
+                               error += error_vector.length2();
+                       }
+                       error = btSqrt(error);
+                       errors.push_back(error);
+                       std::cout << "Iteration = " << it << ", error = " << error << std::endl;
+               }
+               for (int i = 1; i < errors.size(); ++i)
+               {
+                       std::cout << "Iteration = " << i << ", ratio = " << errors[i - 1] / errors[i] << std::endl;
+               }
+       }
+
+       //
+       virtual double totalElasticEnergy(btScalar dt)
+       {
+               return 0;
+       }
+
+       //
+       virtual double totalDampingEnergy(btScalar dt)
+       {
+               return 0;
+       }
+
+       // total Energy takes dt as input because certain energies depend on dt
+       virtual double totalEnergy(btScalar dt)
+       {
+               return totalElasticEnergy(dt) + totalDampingEnergy(dt);
+       }
+};
+#endif /* BT_DEFORMABLE_LAGRANGIAN_FORCE */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableLinearElasticityForce.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableLinearElasticityForce.h
new file mode 100644 (file)
index 0000000..9711920
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_LINEAR_ELASTICITY_H
+#define BT_LINEAR_ELASTICITY_H
+
+#include "btDeformableLagrangianForce.h"
+#include "LinearMath/btQuickprof.h"
+#include "btSoftBodyInternals.h"
+#define TETRA_FLAT_THRESHOLD 0.01
+class btDeformableLinearElasticityForce : public btDeformableLagrangianForce
+{
+public:
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       btScalar m_mu, m_lambda;
+       btScalar m_E, m_nu;  // Young's modulus and Poisson ratio
+       btScalar m_damping_alpha, m_damping_beta;
+       btDeformableLinearElasticityForce() : m_mu(1), m_lambda(1), m_damping_alpha(0.01), m_damping_beta(0.01)
+       {
+               updateYoungsModulusAndPoissonRatio();
+       }
+
+       btDeformableLinearElasticityForce(btScalar mu, btScalar lambda, btScalar damping_alpha = 0.01, btScalar damping_beta = 0.01) : m_mu(mu), m_lambda(lambda), m_damping_alpha(damping_alpha), m_damping_beta(damping_beta)
+       {
+               updateYoungsModulusAndPoissonRatio();
+       }
+
+       void updateYoungsModulusAndPoissonRatio()
+       {
+               // conversion from Lame Parameters to Young's modulus and Poisson ratio
+               // https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
+               m_E = m_mu * (3 * m_lambda + 2 * m_mu) / (m_lambda + m_mu);
+               m_nu = m_lambda * 0.5 / (m_mu + m_lambda);
+       }
+
+       void updateLameParameters()
+       {
+               // conversion from Young's modulus and Poisson ratio to Lame Parameters
+               // https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
+               m_mu = m_E * 0.5 / (1 + m_nu);
+               m_lambda = m_E * m_nu / ((1 + m_nu) * (1 - 2 * m_nu));
+       }
+
+       void setYoungsModulus(btScalar E)
+       {
+               m_E = E;
+               updateLameParameters();
+       }
+
+       void setPoissonRatio(btScalar nu)
+       {
+               m_nu = nu;
+               updateLameParameters();
+       }
+
+       void setDamping(btScalar damping_alpha, btScalar damping_beta)
+       {
+               m_damping_alpha = damping_alpha;
+               m_damping_beta = damping_beta;
+       }
+
+       void setLameParameters(btScalar mu, btScalar lambda)
+       {
+               m_mu = mu;
+               m_lambda = lambda;
+               updateYoungsModulusAndPoissonRatio();
+       }
+
+       virtual void addScaledForces(btScalar scale, TVStack& force)
+       {
+               addScaledDampingForce(scale, force);
+               addScaledElasticForce(scale, force);
+       }
+
+       virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+       {
+               addScaledElasticForce(scale, force);
+       }
+
+       // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+       virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+       {
+               if (m_damping_alpha == 0 && m_damping_beta == 0)
+                       return;
+               btScalar mu_damp = m_damping_beta * m_mu;
+               btScalar lambda_damp = m_damping_beta * m_lambda;
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= force.size());
+               btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_tetras.size(); ++j)
+                       {
+                               bool close_to_flat = (psb->m_tetraScratches[j].m_J < TETRA_FLAT_THRESHOLD);
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btSoftBody::Node* node0 = tetra.m_n[0];
+                               btSoftBody::Node* node1 = tetra.m_n[1];
+                               btSoftBody::Node* node2 = tetra.m_n[2];
+                               btSoftBody::Node* node3 = tetra.m_n[3];
+                               size_t id0 = node0->index;
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               size_t id3 = node3->index;
+                               btMatrix3x3 dF = DsFromVelocity(node0, node1, node2, node3) * tetra.m_Dm_inverse;
+                               if (!close_to_flat)
+                               {
+                                       dF = psb->m_tetraScratches[j].m_corotation.transpose() * dF;
+                               }
+                               btMatrix3x3 I;
+                               I.setIdentity();
+                               btMatrix3x3 dP = (dF + dF.transpose()) * mu_damp + I * ((dF[0][0] + dF[1][1] + dF[2][2]) * lambda_damp);
+                               btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+                               if (!close_to_flat)
+                               {
+                                       df_on_node123 = psb->m_tetraScratches[j].m_corotation * df_on_node123;
+                               }
+                               btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+                               // damping force differential
+                               btScalar scale1 = scale * tetra.m_element_measure;
+                               force[id0] -= scale1 * df_on_node0;
+                               force[id1] -= scale1 * df_on_node123.getColumn(0);
+                               force[id2] -= scale1 * df_on_node123.getColumn(1);
+                               force[id3] -= scale1 * df_on_node123.getColumn(2);
+                       }
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               const btSoftBody::Node& node = psb->m_nodes[j];
+                               size_t id = node.index;
+                               if (node.m_im > 0)
+                               {
+                                       force[id] -= scale * node.m_v / node.m_im * m_damping_alpha;
+                               }
+                       }
+               }
+       }
+
+       virtual double totalElasticEnergy(btScalar dt)
+       {
+               double energy = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_tetraScratches.size(); ++j)
+                       {
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btSoftBody::TetraScratch& s = psb->m_tetraScratches[j];
+                               energy += tetra.m_element_measure * elasticEnergyDensity(s);
+                       }
+               }
+               return energy;
+       }
+
+       // The damping energy is formulated as in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+       virtual double totalDampingEnergy(btScalar dt)
+       {
+               double energy = 0;
+               int sz = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               sz = btMax(sz, psb->m_nodes[j].index);
+                       }
+               }
+               TVStack dampingForce;
+               dampingForce.resize(sz + 1);
+               for (int i = 0; i < dampingForce.size(); ++i)
+                       dampingForce[i].setZero();
+               addScaledDampingForce(0.5, dampingForce);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               const btSoftBody::Node& node = psb->m_nodes[j];
+                               energy -= dampingForce[node.index].dot(node.m_v) / dt;
+                       }
+               }
+               return energy;
+       }
+
+       double elasticEnergyDensity(const btSoftBody::TetraScratch& s)
+       {
+               double density = 0;
+               btMatrix3x3 epsilon = (s.m_F + s.m_F.transpose()) * 0.5 - btMatrix3x3::getIdentity();
+               btScalar trace = epsilon[0][0] + epsilon[1][1] + epsilon[2][2];
+               density += m_mu * (epsilon[0].length2() + epsilon[1].length2() + epsilon[2].length2());
+               density += m_lambda * trace * trace * 0.5;
+               return density;
+       }
+
+       virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+       {
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= force.size());
+               btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       btScalar max_p = psb->m_cfg.m_maxStress;
+                       for (int j = 0; j < psb->m_tetras.size(); ++j)
+                       {
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btMatrix3x3 P;
+                               firstPiola(psb->m_tetraScratches[j], P);
+#if USE_SVD
+                               if (max_p > 0)
+                               {
+                                       // since we want to clamp the principal stress to max_p, we only need to
+                                       // calculate SVD when sigma_0^2 + sigma_1^2 + sigma_2^2 > max_p * max_p
+                                       btScalar trPTP = (P[0].length2() + P[1].length2() + P[2].length2());
+                                       if (trPTP > max_p * max_p)
+                                       {
+                                               btMatrix3x3 U, V;
+                                               btVector3 sigma;
+                                               singularValueDecomposition(P, U, sigma, V);
+                                               sigma[0] = btMin(sigma[0], max_p);
+                                               sigma[1] = btMin(sigma[1], max_p);
+                                               sigma[2] = btMin(sigma[2], max_p);
+                                               sigma[0] = btMax(sigma[0], -max_p);
+                                               sigma[1] = btMax(sigma[1], -max_p);
+                                               sigma[2] = btMax(sigma[2], -max_p);
+                                               btMatrix3x3 Sigma;
+                                               Sigma.setIdentity();
+                                               Sigma[0][0] = sigma[0];
+                                               Sigma[1][1] = sigma[1];
+                                               Sigma[2][2] = sigma[2];
+                                               P = U * Sigma * V.transpose();
+                                       }
+                               }
+#endif
+                               //                btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+                               btMatrix3x3 force_on_node123 = psb->m_tetraScratches[j].m_corotation * P * tetra.m_Dm_inverse.transpose();
+                               btVector3 force_on_node0 = force_on_node123 * grad_N_hat_1st_col;
+
+                               btSoftBody::Node* node0 = tetra.m_n[0];
+                               btSoftBody::Node* node1 = tetra.m_n[1];
+                               btSoftBody::Node* node2 = tetra.m_n[2];
+                               btSoftBody::Node* node3 = tetra.m_n[3];
+                               size_t id0 = node0->index;
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               size_t id3 = node3->index;
+
+                               // elastic force
+                               btScalar scale1 = scale * tetra.m_element_measure;
+                               force[id0] -= scale1 * force_on_node0;
+                               force[id1] -= scale1 * force_on_node123.getColumn(0);
+                               force[id2] -= scale1 * force_on_node123.getColumn(1);
+                               force[id3] -= scale1 * force_on_node123.getColumn(2);
+                       }
+               }
+       }
+
+       virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) {}
+
+       // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+       virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+       {
+               if (m_damping_alpha == 0 && m_damping_beta == 0)
+                       return;
+               btScalar mu_damp = m_damping_beta * m_mu;
+               btScalar lambda_damp = m_damping_beta * m_lambda;
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= df.size());
+               btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_tetras.size(); ++j)
+                       {
+                               bool close_to_flat = (psb->m_tetraScratches[j].m_J < TETRA_FLAT_THRESHOLD);
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btSoftBody::Node* node0 = tetra.m_n[0];
+                               btSoftBody::Node* node1 = tetra.m_n[1];
+                               btSoftBody::Node* node2 = tetra.m_n[2];
+                               btSoftBody::Node* node3 = tetra.m_n[3];
+                               size_t id0 = node0->index;
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               size_t id3 = node3->index;
+                               btMatrix3x3 dF = Ds(id0, id1, id2, id3, dv) * tetra.m_Dm_inverse;
+                               if (!close_to_flat)
+                               {
+                                       dF = psb->m_tetraScratches[j].m_corotation.transpose() * dF;
+                               }
+                               btMatrix3x3 I;
+                               I.setIdentity();
+                               btMatrix3x3 dP = (dF + dF.transpose()) * mu_damp + I * ((dF[0][0] + dF[1][1] + dF[2][2]) * lambda_damp);
+                               btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+                               if (!close_to_flat)
+                               {
+                                       df_on_node123 = psb->m_tetraScratches[j].m_corotation * df_on_node123;
+                               }
+                               btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+                               // damping force differential
+                               btScalar scale1 = scale * tetra.m_element_measure;
+                               df[id0] -= scale1 * df_on_node0;
+                               df[id1] -= scale1 * df_on_node123.getColumn(0);
+                               df[id2] -= scale1 * df_on_node123.getColumn(1);
+                               df[id3] -= scale1 * df_on_node123.getColumn(2);
+                       }
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               const btSoftBody::Node& node = psb->m_nodes[j];
+                               size_t id = node.index;
+                               if (node.m_im > 0)
+                               {
+                                       df[id] -= scale * dv[id] / node.m_im * m_damping_alpha;
+                               }
+                       }
+               }
+       }
+
+       virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+       {
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= df.size());
+               btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_tetras.size(); ++j)
+                       {
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btSoftBody::Node* node0 = tetra.m_n[0];
+                               btSoftBody::Node* node1 = tetra.m_n[1];
+                               btSoftBody::Node* node2 = tetra.m_n[2];
+                               btSoftBody::Node* node3 = tetra.m_n[3];
+                               size_t id0 = node0->index;
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               size_t id3 = node3->index;
+                               btMatrix3x3 dF = psb->m_tetraScratches[j].m_corotation.transpose() * Ds(id0, id1, id2, id3, dx) * tetra.m_Dm_inverse;
+                               btMatrix3x3 dP;
+                               firstPiolaDifferential(psb->m_tetraScratches[j], dF, dP);
+                               //                btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+                               btMatrix3x3 df_on_node123 = psb->m_tetraScratches[j].m_corotation * dP * tetra.m_Dm_inverse.transpose();
+                               btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+                               // elastic force differential
+                               btScalar scale1 = scale * tetra.m_element_measure;
+                               df[id0] -= scale1 * df_on_node0;
+                               df[id1] -= scale1 * df_on_node123.getColumn(0);
+                               df[id2] -= scale1 * df_on_node123.getColumn(1);
+                               df[id3] -= scale1 * df_on_node123.getColumn(2);
+                       }
+               }
+       }
+
+       void firstPiola(const btSoftBody::TetraScratch& s, btMatrix3x3& P)
+       {
+               btMatrix3x3 corotated_F = s.m_corotation.transpose() * s.m_F;
+
+               btMatrix3x3 epsilon = (corotated_F + corotated_F.transpose()) * 0.5 - btMatrix3x3::getIdentity();
+               btScalar trace = epsilon[0][0] + epsilon[1][1] + epsilon[2][2];
+               P = epsilon * btScalar(2) * m_mu + btMatrix3x3::getIdentity() * m_lambda * trace;
+       }
+
+       // Let P be the first piola stress.
+       // This function calculates the dP = dP/dF * dF
+       void firstPiolaDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+       {
+               btScalar trace = (dF[0][0] + dF[1][1] + dF[2][2]);
+               dP = (dF + dF.transpose()) * m_mu + btMatrix3x3::getIdentity() * m_lambda * trace;
+       }
+
+       // Let Q be the damping stress.
+       // This function calculates the dP = dQ/dF * dF
+       void firstPiolaDampingDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+       {
+               btScalar mu_damp = m_damping_beta * m_mu;
+               btScalar lambda_damp = m_damping_beta * m_lambda;
+               btScalar trace = (dF[0][0] + dF[1][1] + dF[2][2]);
+               dP = (dF + dF.transpose()) * mu_damp + btMatrix3x3::getIdentity() * lambda_damp * trace;
+       }
+
+       virtual void addScaledHessian(btScalar scale)
+       {
+               btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_tetras.size(); ++j)
+                       {
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btMatrix3x3 P;
+                               firstPiola(psb->m_tetraScratches[j], P);  // make sure scratch is evaluated at x_n + dt * vn
+                               btMatrix3x3 force_on_node123 = psb->m_tetraScratches[j].m_corotation * P * tetra.m_Dm_inverse.transpose();
+                               btVector3 force_on_node0 = force_on_node123 * grad_N_hat_1st_col;
+                               btSoftBody::Node* node0 = tetra.m_n[0];
+                               btSoftBody::Node* node1 = tetra.m_n[1];
+                               btSoftBody::Node* node2 = tetra.m_n[2];
+                               btSoftBody::Node* node3 = tetra.m_n[3];
+                               btScalar scale1 = scale * (scale + m_damping_beta) * tetra.m_element_measure;  // stiff and stiffness-damping terms;
+                               node0->m_effectiveMass += OuterProduct(force_on_node0, force_on_node0) * scale1;
+                               node1->m_effectiveMass += OuterProduct(force_on_node123.getColumn(0), force_on_node123.getColumn(0)) * scale1;
+                               node2->m_effectiveMass += OuterProduct(force_on_node123.getColumn(1), force_on_node123.getColumn(1)) * scale1;
+                               node3->m_effectiveMass += OuterProduct(force_on_node123.getColumn(2), force_on_node123.getColumn(2)) * scale1;
+                       }
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               btSoftBody::Node& node = psb->m_nodes[j];
+                               if (node.m_im > 0)
+                               {
+                                       btMatrix3x3 I;
+                                       I.setIdentity();
+                                       node.m_effectiveMass += I * (scale * (1.0 / node.m_im) * m_damping_alpha);
+                               }
+                       }
+               }
+       }
+
+       virtual btDeformableLagrangianForceType getForceType()
+       {
+               return BT_LINEAR_ELASTICITY_FORCE;
+       }
+};
+#endif /* BT_LINEAR_ELASTICITY_H */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMassSpringForce.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMassSpringForce.h
new file mode 100644 (file)
index 0000000..8c97bd1
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_MASS_SPRING_H
+#define BT_MASS_SPRING_H
+
+#include "btDeformableLagrangianForce.h"
+
+class btDeformableMassSpringForce : public btDeformableLagrangianForce
+{
+       // If true, the damping force will be in the direction of the spring
+       // If false, the damping force will be in the direction of the velocity
+       bool m_momentum_conserving;
+       btScalar m_elasticStiffness, m_dampingStiffness, m_bendingStiffness;
+
+public:
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       btDeformableMassSpringForce() : m_momentum_conserving(false), m_elasticStiffness(1), m_dampingStiffness(0.05)
+       {
+       }
+       btDeformableMassSpringForce(btScalar k, btScalar d, bool conserve_angular = true, double bending_k = -1) : m_momentum_conserving(conserve_angular), m_elasticStiffness(k), m_dampingStiffness(d), m_bendingStiffness(bending_k)
+       {
+               if (m_bendingStiffness < btScalar(0))
+               {
+                       m_bendingStiffness = m_elasticStiffness;
+               }
+       }
+
+       virtual void addScaledForces(btScalar scale, TVStack& force)
+       {
+               addScaledDampingForce(scale, force);
+               addScaledElasticForce(scale, force);
+       }
+
+       virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+       {
+               addScaledElasticForce(scale, force);
+       }
+
+       virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+       {
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= force.size());
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       const btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_links.size(); ++j)
+                       {
+                               const btSoftBody::Link& link = psb->m_links[j];
+                               btSoftBody::Node* node1 = link.m_n[0];
+                               btSoftBody::Node* node2 = link.m_n[1];
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+
+                               // damping force
+                               btVector3 v_diff = (node2->m_v - node1->m_v);
+                               btVector3 scaled_force = scale * m_dampingStiffness * v_diff;
+                               if (m_momentum_conserving)
+                               {
+                                       if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
+                                       {
+                                               btVector3 dir = (node2->m_x - node1->m_x).normalized();
+                                               scaled_force = scale * m_dampingStiffness * v_diff.dot(dir) * dir;
+                                       }
+                               }
+                               force[id1] += scaled_force;
+                               force[id2] -= scaled_force;
+                       }
+               }
+       }
+
+       virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+       {
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= force.size());
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       const btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_links.size(); ++j)
+                       {
+                               const btSoftBody::Link& link = psb->m_links[j];
+                               btSoftBody::Node* node1 = link.m_n[0];
+                               btSoftBody::Node* node2 = link.m_n[1];
+                               btScalar r = link.m_rl;
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+
+                               // elastic force
+                               btVector3 dir = (node2->m_q - node1->m_q);
+                               btVector3 dir_normalized = (dir.norm() > SIMD_EPSILON) ? dir.normalized() : btVector3(0, 0, 0);
+                               btScalar scaled_stiffness = scale * (link.m_bbending ? m_bendingStiffness : m_elasticStiffness);
+                               btVector3 scaled_force = scaled_stiffness * (dir - dir_normalized * r);
+                               force[id1] += scaled_force;
+                               force[id2] -= scaled_force;
+                       }
+               }
+       }
+
+       virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+       {
+               // implicit damping force differential
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       btScalar scaled_k_damp = m_dampingStiffness * scale;
+                       for (int j = 0; j < psb->m_links.size(); ++j)
+                       {
+                               const btSoftBody::Link& link = psb->m_links[j];
+                               btSoftBody::Node* node1 = link.m_n[0];
+                               btSoftBody::Node* node2 = link.m_n[1];
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+
+                               btVector3 local_scaled_df = scaled_k_damp * (dv[id2] - dv[id1]);
+                               if (m_momentum_conserving)
+                               {
+                                       if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
+                                       {
+                                               btVector3 dir = (node2->m_x - node1->m_x).normalized();
+                                               local_scaled_df = scaled_k_damp * (dv[id2] - dv[id1]).dot(dir) * dir;
+                                       }
+                               }
+                               df[id1] += local_scaled_df;
+                               df[id2] -= local_scaled_df;
+                       }
+               }
+       }
+
+       virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA)
+       {
+               // implicit damping force differential
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       btScalar scaled_k_damp = m_dampingStiffness * scale;
+                       for (int j = 0; j < psb->m_links.size(); ++j)
+                       {
+                               const btSoftBody::Link& link = psb->m_links[j];
+                               btSoftBody::Node* node1 = link.m_n[0];
+                               btSoftBody::Node* node2 = link.m_n[1];
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               if (m_momentum_conserving)
+                               {
+                                       if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
+                                       {
+                                               btVector3 dir = (node2->m_x - node1->m_x).normalized();
+                                               for (int d = 0; d < 3; ++d)
+                                               {
+                                                       if (node1->m_im > 0)
+                                                               diagA[id1][d] -= scaled_k_damp * dir[d] * dir[d];
+                                                       if (node2->m_im > 0)
+                                                               diagA[id2][d] -= scaled_k_damp * dir[d] * dir[d];
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       for (int d = 0; d < 3; ++d)
+                                       {
+                                               if (node1->m_im > 0)
+                                                       diagA[id1][d] -= scaled_k_damp;
+                                               if (node2->m_im > 0)
+                                                       diagA[id2][d] -= scaled_k_damp;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       virtual double totalElasticEnergy(btScalar dt)
+       {
+               double energy = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       const btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_links.size(); ++j)
+                       {
+                               const btSoftBody::Link& link = psb->m_links[j];
+                               btSoftBody::Node* node1 = link.m_n[0];
+                               btSoftBody::Node* node2 = link.m_n[1];
+                               btScalar r = link.m_rl;
+
+                               // elastic force
+                               btVector3 dir = (node2->m_q - node1->m_q);
+                               energy += 0.5 * m_elasticStiffness * (dir.norm() - r) * (dir.norm() - r);
+                       }
+               }
+               return energy;
+       }
+
+       virtual double totalDampingEnergy(btScalar dt)
+       {
+               double energy = 0;
+               int sz = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               sz = btMax(sz, psb->m_nodes[j].index);
+                       }
+               }
+               TVStack dampingForce;
+               dampingForce.resize(sz + 1);
+               for (int i = 0; i < dampingForce.size(); ++i)
+                       dampingForce[i].setZero();
+               addScaledDampingForce(0.5, dampingForce);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               const btSoftBody::Node& node = psb->m_nodes[j];
+                               energy -= dampingForce[node.index].dot(node.m_v) / dt;
+                       }
+               }
+               return energy;
+       }
+
+       virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+       {
+               // implicit damping force differential
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       const btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_links.size(); ++j)
+                       {
+                               const btSoftBody::Link& link = psb->m_links[j];
+                               btSoftBody::Node* node1 = link.m_n[0];
+                               btSoftBody::Node* node2 = link.m_n[1];
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               btScalar r = link.m_rl;
+
+                               btVector3 dir = (node1->m_q - node2->m_q);
+                               btScalar dir_norm = dir.norm();
+                               btVector3 dir_normalized = (dir_norm > SIMD_EPSILON) ? dir.normalized() : btVector3(0, 0, 0);
+                               btVector3 dx_diff = dx[id1] - dx[id2];
+                               btVector3 scaled_df = btVector3(0, 0, 0);
+                               btScalar scaled_k = scale * (link.m_bbending ? m_bendingStiffness : m_elasticStiffness);
+                               if (dir_norm > SIMD_EPSILON)
+                               {
+                                       scaled_df -= scaled_k * dir_normalized.dot(dx_diff) * dir_normalized;
+                                       scaled_df += scaled_k * dir_normalized.dot(dx_diff) * ((dir_norm - r) / dir_norm) * dir_normalized;
+                                       scaled_df -= scaled_k * ((dir_norm - r) / dir_norm) * dx_diff;
+                               }
+
+                               df[id1] += scaled_df;
+                               df[id2] -= scaled_df;
+                       }
+               }
+       }
+
+       virtual btDeformableLagrangianForceType getForceType()
+       {
+               return BT_MASSSPRING_FORCE;
+       }
+};
+
+#endif /* btMassSpring_h */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMousePickingForce.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMousePickingForce.h
new file mode 100644 (file)
index 0000000..6974083
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_MOUSE_PICKING_FORCE_H
+#define BT_MOUSE_PICKING_FORCE_H
+
+#include "btDeformableLagrangianForce.h"
+
+class btDeformableMousePickingForce : public btDeformableLagrangianForce
+{
+       // If true, the damping force will be in the direction of the spring
+       // If false, the damping force will be in the direction of the velocity
+       btScalar m_elasticStiffness, m_dampingStiffness;
+       const btSoftBody::Face& m_face;
+       btVector3 m_mouse_pos;
+       btScalar m_maxForce;
+
+public:
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       btDeformableMousePickingForce(btScalar k, btScalar d, const btSoftBody::Face& face, const btVector3& mouse_pos, btScalar maxForce = 0.3) : m_elasticStiffness(k), m_dampingStiffness(d), m_face(face), m_mouse_pos(mouse_pos), m_maxForce(maxForce)
+       {
+       }
+
+       virtual void addScaledForces(btScalar scale, TVStack& force)
+       {
+               addScaledDampingForce(scale, force);
+               addScaledElasticForce(scale, force);
+       }
+
+       virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+       {
+               addScaledElasticForce(scale, force);
+       }
+
+       virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+       {
+               for (int i = 0; i < 3; ++i)
+               {
+                       btVector3 v_diff = m_face.m_n[i]->m_v;
+                       btVector3 scaled_force = scale * m_dampingStiffness * v_diff;
+                       if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
+                       {
+                               btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
+                               scaled_force = scale * m_dampingStiffness * v_diff.dot(dir) * dir;
+                       }
+                       force[m_face.m_n[i]->index] -= scaled_force;
+               }
+       }
+
+       virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+       {
+               btScalar scaled_stiffness = scale * m_elasticStiffness;
+               for (int i = 0; i < 3; ++i)
+               {
+                       btVector3 dir = (m_face.m_n[i]->m_q - m_mouse_pos);
+                       btVector3 scaled_force = scaled_stiffness * dir;
+                       if (scaled_force.safeNorm() > m_maxForce)
+                       {
+                               scaled_force.safeNormalize();
+                               scaled_force *= m_maxForce;
+                       }
+                       force[m_face.m_n[i]->index] -= scaled_force;
+               }
+       }
+
+       virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+       {
+               btScalar scaled_k_damp = m_dampingStiffness * scale;
+               for (int i = 0; i < 3; ++i)
+               {
+                       btVector3 local_scaled_df = scaled_k_damp * dv[m_face.m_n[i]->index];
+                       if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
+                       {
+                               btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
+                               local_scaled_df = scaled_k_damp * dv[m_face.m_n[i]->index].dot(dir) * dir;
+                       }
+                       df[m_face.m_n[i]->index] -= local_scaled_df;
+               }
+       }
+
+       virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) {}
+
+       virtual double totalElasticEnergy(btScalar dt)
+       {
+               double energy = 0;
+               for (int i = 0; i < 3; ++i)
+               {
+                       btVector3 dir = (m_face.m_n[i]->m_q - m_mouse_pos);
+                       btVector3 scaled_force = m_elasticStiffness * dir;
+                       if (scaled_force.safeNorm() > m_maxForce)
+                       {
+                               scaled_force.safeNormalize();
+                               scaled_force *= m_maxForce;
+                       }
+                       energy += 0.5 * scaled_force.dot(dir);
+               }
+               return energy;
+       }
+
+       virtual double totalDampingEnergy(btScalar dt)
+       {
+               double energy = 0;
+               for (int i = 0; i < 3; ++i)
+               {
+                       btVector3 v_diff = m_face.m_n[i]->m_v;
+                       btVector3 scaled_force = m_dampingStiffness * v_diff;
+                       if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
+                       {
+                               btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
+                               scaled_force = m_dampingStiffness * v_diff.dot(dir) * dir;
+                       }
+                       energy -= scaled_force.dot(m_face.m_n[i]->m_v) / dt;
+               }
+               return energy;
+       }
+
+       virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+       {
+               btScalar scaled_stiffness = scale * m_elasticStiffness;
+               for (int i = 0; i < 3; ++i)
+               {
+                       btVector3 dir = (m_face.m_n[i]->m_q - m_mouse_pos);
+                       btScalar dir_norm = dir.norm();
+                       btVector3 dir_normalized = (dir_norm > SIMD_EPSILON) ? dir.normalized() : btVector3(0, 0, 0);
+                       int id = m_face.m_n[i]->index;
+                       btVector3 dx_diff = dx[id];
+                       btScalar r = 0;  // rest length is 0 for picking spring
+                       btVector3 scaled_df = btVector3(0, 0, 0);
+                       if (dir_norm > SIMD_EPSILON)
+                       {
+                               scaled_df -= scaled_stiffness * dir_normalized.dot(dx_diff) * dir_normalized;
+                               scaled_df += scaled_stiffness * dir_normalized.dot(dx_diff) * ((dir_norm - r) / dir_norm) * dir_normalized;
+                               scaled_df -= scaled_stiffness * ((dir_norm - r) / dir_norm) * dx_diff;
+                       }
+                       df[id] += scaled_df;
+               }
+       }
+
+       void setMousePos(const btVector3& p)
+       {
+               m_mouse_pos = p;
+       }
+
+       virtual btDeformableLagrangianForceType getForceType()
+       {
+               return BT_MOUSE_PICKING_FORCE;
+       }
+};
+
+#endif /* btMassSpring_h */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp
new file mode 100644 (file)
index 0000000..0f30054
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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 "btDeformableMultiBodyConstraintSolver.h"
+#include "BulletReducedDeformableBody/btReducedDeformableBodySolver.h"
+#include <iostream>
+
+// override the iterations method to include deformable/multibody contact
+btScalar btDeformableMultiBodyConstraintSolver::solveDeformableGroupIterations(btCollisionObject** bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       {
+               // pair deformable body with solver body
+               pairDeformableAndSolverBody(bodies, numBodies, numDeformableBodies, infoGlobal);
+
+               ///this is a special step to resolve penetrations (just for contacts)
+               solveGroupCacheFriendlySplitImpulseIterations(bodies, numBodies, deformableBodies, numDeformableBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+
+               int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
+               for (int iteration = 0; iteration < maxIterations; iteration++)
+               {
+                       // rigid bodies are solved using solver body velocity, but rigid/deformable contact directly uses the velocity of the actual rigid body. So we have to do the following: Solve one iteration of the rigid/rigid contact, get the updated velocity in the solver body and update the velocity of the underlying rigid body. Then solve the rigid/deformable contact. Finally, grab the (once again) updated rigid velocity and update the velocity of the wrapping solver body
+
+                       // solve rigid/rigid in solver body
+                       m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
+                       // solver body velocity -> rigid body velocity
+                       solverBodyWriteBack(infoGlobal);
+                       btScalar deformableResidual = m_deformableSolver->solveContactConstraints(deformableBodies, numDeformableBodies, infoGlobal);
+                       // update rigid body velocity in rigid/deformable contact
+                       m_leastSquaresResidual = btMax(m_leastSquaresResidual, deformableResidual);
+                       // solver body velocity <- rigid body velocity
+                       writeToSolverBody(bodies, numBodies, infoGlobal);
+
+
+                       // std::cout << "------------Iteration " << iteration << "------------\n";
+                       // std::cout << "m_leastSquaresResidual: " << m_leastSquaresResidual << "\n";
+
+                       if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1)))
+                       {
+#ifdef VERBOSE_RESIDUAL_PRINTF
+                               if (iteration >= (maxIterations - 1))
+                                       printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
+#endif
+                               m_analyticsData.m_numSolverCalls++;
+                               m_analyticsData.m_numIterationsUsed = iteration + 1;
+                               m_analyticsData.m_islandId = -2;
+                               if (numBodies > 0)
+                                       m_analyticsData.m_islandId = bodies[0]->getCompanionId();
+                               m_analyticsData.m_numBodies = numBodies;
+                               m_analyticsData.m_numContactManifolds = numManifolds;
+                               m_analyticsData.m_remainingLeastSquaresResidual = m_leastSquaresResidual;
+                               
+                               m_deformableSolver->deformableBodyInternalWriteBack();
+                               // std::cout << "[===================Next Step===================]\n";
+                               break;
+                       }
+               }
+       }
+       return 0.f;
+}
+
+void btDeformableMultiBodyConstraintSolver::solveDeformableBodyGroup(btCollisionObject** bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
+{
+       m_tmpMultiBodyConstraints = multiBodyConstraints;
+       m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
+
+       // inherited from MultiBodyConstraintSolver
+       solveGroupCacheFriendlySetup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer);
+
+       // overriden
+       solveDeformableGroupIterations(bodies, numBodies, deformableBodies, numDeformableBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer);
+
+       // inherited from MultiBodyConstraintSolver
+       solveGroupCacheFriendlyFinish(bodies, numBodies, info);
+
+       m_tmpMultiBodyConstraints = 0;
+       m_tmpNumMultiBodyConstraints = 0;
+}
+
+void btDeformableMultiBodyConstraintSolver::writeToSolverBody(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
+{
+       // reduced soft body solver directly modifies the solver body
+       if (m_deformableSolver->isReducedSolver())
+       {
+               return;
+       }
+
+       for (int i = 0; i < numBodies; i++)
+       {
+               int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
+
+               btRigidBody* body = btRigidBody::upcast(bodies[i]);
+               if (body && body->getInvMass())
+               {
+                       btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
+                       solverBody.m_linearVelocity = body->getLinearVelocity() - solverBody.m_deltaLinearVelocity;
+                       solverBody.m_angularVelocity = body->getAngularVelocity() - solverBody.m_deltaAngularVelocity;
+               }
+       }
+}
+
+void btDeformableMultiBodyConstraintSolver::solverBodyWriteBack(const btContactSolverInfo& infoGlobal)
+{
+       // reduced soft body solver directly modifies the solver body
+       if (m_deformableSolver->isReducedSolver())
+       {
+               return;
+       }
+
+       for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
+       {
+               btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
+               if (body)
+               {
+                       m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(m_tmpSolverBodyPool[i].m_linearVelocity + m_tmpSolverBodyPool[i].m_deltaLinearVelocity);
+                       m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(m_tmpSolverBodyPool[i].m_angularVelocity + m_tmpSolverBodyPool[i].m_deltaAngularVelocity);
+               }
+       }
+}
+
+
+void btDeformableMultiBodyConstraintSolver::pairDeformableAndSolverBody(btCollisionObject** bodies, int numBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
+{
+       if (!m_deformableSolver->isReducedSolver())
+       {
+               return;
+       }
+
+       btReducedDeformableBodySolver* solver = static_cast<btReducedDeformableBodySolver*>(m_deformableSolver);
+       
+       for (int i = 0; i < numDeformableBodies; ++i)
+       {
+               for (int k = 0; k < solver->m_nodeRigidConstraints[i].size(); ++k)
+    {
+      btReducedDeformableNodeRigidContactConstraint& constraint = solver->m_nodeRigidConstraints[i][k];
+
+                       if (!constraint.m_contact->m_cti.m_colObj->isStaticObject())
+                       {
+                               btCollisionObject& col_obj = const_cast<btCollisionObject&>(*constraint.m_contact->m_cti.m_colObj);
+
+                               // object index in the solver body pool
+                               int bodyId = getOrInitSolverBody(col_obj, infoGlobal.m_timeStep);
+                               
+                               const btRigidBody* body = btRigidBody::upcast(bodies[bodyId]);
+                               if (body && body->getInvMass())
+                               {
+                                               // std::cout << "Node: " << constraint.m_node->index << ", body: " << bodyId << "\n";
+                                       btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
+                                       constraint.setSolverBody(bodyId, solverBody);
+                               }
+                       }
+    }
+
+               // for (int j = 0; j < numBodies; j++)
+               // {
+               //      int bodyId = getOrInitSolverBody(*bodies[j], infoGlobal.m_timeStep);
+
+               //      btRigidBody* body = btRigidBody::upcast(bodies[j]);
+               //      if (body && body->getInvMass())
+               //      {
+               //              btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
+               //              m_deformableSolver->pairConstraintWithSolverBody(i, bodyId, solverBody);
+               //      }
+               // }    
+       }
+}
+
+void btDeformableMultiBodyConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
+{
+       BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
+       int iteration;
+       if (infoGlobal.m_splitImpulse)
+       {
+               {
+                       for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
+                       {
+                               btScalar leastSquaresResidual = 0.f;
+                               {
+                                       int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+                                       int j;
+                                       for (j = 0; j < numPoolConstraints; j++)
+                                       {
+                                               const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+
+                                               btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
+                                               leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+                                       }
+                                       // solve the position correction between deformable and rigid/multibody
+                                       //                    btScalar residual = m_deformableSolver->solveSplitImpulse(infoGlobal);
+                                       btScalar residual = m_deformableSolver->m_objective->m_projection.solveSplitImpulse(deformableBodies, numDeformableBodies, infoGlobal);
+                                       leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
+                               }
+                               if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
+                               {
+#ifdef VERBOSE_RESIDUAL_PRINTF
+                                       if (iteration >= (infoGlobal.m_numIterations - 1))
+                                               printf("split impulse residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
+#endif
+                                       break;
+                               }
+                       }
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h
new file mode 100644 (file)
index 0000000..28733fa
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H
+#define BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H
+
+#include "btDeformableBodySolver.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
+
+class btDeformableBodySolver;
+
+// btDeformableMultiBodyConstraintSolver extendsn btMultiBodyConstraintSolver to solve for the contact among rigid/multibody and deformable bodies. Notice that the following constraints
+// 1. rigid/multibody against rigid/multibody
+// 2. rigid/multibody against deforamble
+// 3. deformable against deformable
+// 4. deformable self collision
+// 5. joint constraints
+// are all coupled in this solve.
+ATTRIBUTE_ALIGNED16(class)
+btDeformableMultiBodyConstraintSolver : public btMultiBodyConstraintSolver
+{
+       btDeformableBodySolver* m_deformableSolver;
+
+protected:
+       // override the iterations method to include deformable/multibody contact
+       //    virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
+
+       // write the velocity of the the solver body to the underlying rigid body
+       void solverBodyWriteBack(const btContactSolverInfo& infoGlobal);
+
+       // write the velocity of the underlying rigid body to the the the solver body
+       void writeToSolverBody(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
+
+       // let each deformable body knows which solver body is in constact
+       void pairDeformableAndSolverBody(btCollisionObject** bodies, int numBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal);
+
+       virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject * *bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+
+       virtual btScalar solveDeformableGroupIterations(btCollisionObject * *bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       void setDeformableSolver(btDeformableBodySolver * deformableSolver)
+       {
+               m_deformableSolver = deformableSolver;
+       }
+
+       virtual void solveDeformableBodyGroup(btCollisionObject * *bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
+};
+
+#endif /* BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp
new file mode 100644 (file)
index 0000000..030cbaf
--- /dev/null
@@ -0,0 +1,745 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+/* ====== Overview of the Deformable Algorithm ====== */
+
+/*
+A single step of the deformable body simulation contains the following main components:
+Call internalStepSimulation multiple times, to achieve 240Hz (4 steps of 60Hz).
+1. Deformable maintaintenance of rest lengths and volume preservation. Forces only depend on position: Update velocity to a temporary state v_{n+1}^* = v_n + explicit_force * dt / mass, where explicit forces include gravity and elastic forces.
+2. Detect discrete collisions between rigid and deformable bodies at position x_{n+1}^* = x_n + dt * v_{n+1}^*.
+
+3a. Solve all constraints, including LCP. Contact, position correction due to numerical drift, friction, and anchors for deformable.
+
+3b. 5 Newton steps (multiple step). Conjugent Gradient solves linear system. Deformable Damping: Then velocities of deformable bodies v_{n+1} are solved in
+        M(v_{n+1} - v_{n+1}^*) = damping_force * dt / mass,
+   by a conjugate gradient solver, where the damping force is implicit and depends on v_{n+1}.
+   Make sure contact constraints are not violated in step b by performing velocity projections as in the paper by Baraff and Witkin https://www.cs.cmu.edu/~baraff/papers/sig98.pdf. Dynamic frictions are treated as a force and added to the rhs of the CG solve, whereas static frictions are treated as constraints similar to contact.
+4. Position is updated via x_{n+1} = x_n + dt * v_{n+1}.
+
+
+The algorithm also closely resembles the one in http://physbam.stanford.edu/~fedkiw/papers/stanford2008-03.pdf
+ */
+
+#include <stdio.h>
+#include "btDeformableMultiBodyDynamicsWorld.h"
+#include "DeformableBodyInplaceSolverIslandCallback.h"
+#include "btDeformableBodySolver.h"
+#include "LinearMath/btQuickprof.h"
+#include "btSoftBodyInternals.h"
+btDeformableMultiBodyDynamicsWorld::btDeformableMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btDeformableMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btDeformableBodySolver* deformableBodySolver)
+       : btMultiBodyDynamicsWorld(dispatcher, pairCache, (btMultiBodyConstraintSolver*)constraintSolver, collisionConfiguration),
+         m_deformableBodySolver(deformableBodySolver),
+         m_solverCallback(0)
+{
+       m_drawFlags = fDrawFlags::Std;
+       m_drawNodeTree = true;
+       m_drawFaceTree = false;
+       m_drawClusterTree = false;
+       m_sbi.m_broadphase = pairCache;
+       m_sbi.m_dispatcher = dispatcher;
+       m_sbi.m_sparsesdf.Initialize();
+       m_sbi.m_sparsesdf.setDefaultVoxelsz(0.005);
+       m_sbi.m_sparsesdf.Reset();
+
+       m_sbi.air_density = (btScalar)1.2;
+       m_sbi.water_density = 0;
+       m_sbi.water_offset = 0;
+       m_sbi.water_normal = btVector3(0, 0, 0);
+       m_sbi.m_gravity.setValue(0, -9.8, 0);
+       m_internalTime = 0.0;
+       m_implicit = false;
+       m_lineSearch = false;
+       m_useProjection = false;
+       m_ccdIterations = 5;
+       m_solverDeformableBodyIslandCallback = new DeformableBodyInplaceSolverIslandCallback(constraintSolver, dispatcher);
+}
+
+btDeformableMultiBodyDynamicsWorld::~btDeformableMultiBodyDynamicsWorld()
+{
+       delete m_solverDeformableBodyIslandCallback;
+}
+
+void btDeformableMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
+{
+       BT_PROFILE("internalSingleStepSimulation");
+       if (0 != m_internalPreTickCallback)
+       {
+               (*m_internalPreTickCallback)(this, timeStep);
+       }
+       reinitialize(timeStep);
+
+       // add gravity to velocity of rigid and multi bodys
+       applyRigidBodyGravity(timeStep);
+
+       ///apply gravity and explicit force to velocity, predict motion
+       predictUnconstraintMotion(timeStep);
+
+       ///perform collision detection that involves rigid/multi bodies
+       btMultiBodyDynamicsWorld::performDiscreteCollisionDetection();
+
+       btMultiBodyDynamicsWorld::calculateSimulationIslands();
+
+       beforeSolverCallbacks(timeStep);
+
+       // ///solve contact constraints and then deformable bodies momemtum equation
+       solveConstraints(timeStep);
+
+       afterSolverCallbacks(timeStep);
+
+       performDeformableCollisionDetection();
+
+       applyRepulsionForce(timeStep);
+
+       performGeometricCollisions(timeStep);
+
+       integrateTransforms(timeStep);
+
+       ///update vehicle simulation
+       btMultiBodyDynamicsWorld::updateActions(timeStep);
+
+       updateActivationState(timeStep);
+       // End solver-wise simulation step
+       // ///////////////////////////////
+}
+
+void btDeformableMultiBodyDynamicsWorld::performDeformableCollisionDetection()
+{
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               m_softBodies[i]->m_softSoftCollision = true;
+       }
+
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               for (int j = i; j < m_softBodies.size(); ++j)
+               {
+                       m_softBodies[i]->defaultCollisionHandler(m_softBodies[j]);
+               }
+       }
+
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               m_softBodies[i]->m_softSoftCollision = false;
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
+{
+       for (int i = 0; i < m_softBodies.size(); i++)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               psb->updateDeactivation(timeStep);
+               if (psb->wantsSleeping())
+               {
+                       if (psb->getActivationState() == ACTIVE_TAG)
+                               psb->setActivationState(WANTS_DEACTIVATION);
+                       if (psb->getActivationState() == ISLAND_SLEEPING)
+                       {
+                               psb->setZeroVelocity();
+                       }
+               }
+               else
+               {
+                       if (psb->getActivationState() != DISABLE_DEACTIVATION)
+                               psb->setActivationState(ACTIVE_TAG);
+               }
+       }
+       btMultiBodyDynamicsWorld::updateActivationState(timeStep);
+}
+
+void btDeformableMultiBodyDynamicsWorld::applyRepulsionForce(btScalar timeStep)
+{
+       BT_PROFILE("btDeformableMultiBodyDynamicsWorld::applyRepulsionForce");
+       for (int i = 0; i < m_softBodies.size(); i++)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (psb->isActive())
+               {
+                       psb->applyRepulsionForce(timeStep, true);
+               }
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::performGeometricCollisions(btScalar timeStep)
+{
+       BT_PROFILE("btDeformableMultiBodyDynamicsWorld::performGeometricCollisions");
+       // refit the BVH tree for CCD
+       for (int i = 0; i < m_softBodies.size(); ++i)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (psb->isActive())
+               {
+                       m_softBodies[i]->updateFaceTree(true, false);
+                       m_softBodies[i]->updateNodeTree(true, false);
+                       for (int j = 0; j < m_softBodies[i]->m_faces.size(); ++j)
+                       {
+                               btSoftBody::Face& f = m_softBodies[i]->m_faces[j];
+                               f.m_n0 = (f.m_n[1]->m_x - f.m_n[0]->m_x).cross(f.m_n[2]->m_x - f.m_n[0]->m_x);
+                       }
+               }
+       }
+
+       // clear contact points & update DBVT
+       for (int r = 0; r < m_ccdIterations; ++r)
+       {
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (psb->isActive())
+                       {
+                               // clear contact points in the previous iteration
+                               psb->m_faceNodeContactsCCD.clear();
+
+                               // update m_q and normals for CCD calculation
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                               {
+                                       psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + timeStep * psb->m_nodes[j].m_v;
+                               }
+                               for (int j = 0; j < psb->m_faces.size(); ++j)
+                               {
+                                       btSoftBody::Face& f = psb->m_faces[j];
+                                       f.m_n1 = (f.m_n[1]->m_q - f.m_n[0]->m_q).cross(f.m_n[2]->m_q - f.m_n[0]->m_q);
+                                       f.m_vn = (f.m_n[1]->m_v - f.m_n[0]->m_v).cross(f.m_n[2]->m_v - f.m_n[0]->m_v) * timeStep * timeStep;
+                               }
+                       }
+               }
+
+               // apply CCD to register new contact points
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       for (int j = i; j < m_softBodies.size(); ++j)
+                       {
+                               btSoftBody* psb1 = m_softBodies[i];
+                               btSoftBody* psb2 = m_softBodies[j];
+                               if (psb1->isActive() && psb2->isActive())
+                               {
+                                       m_softBodies[i]->geometricCollisionHandler(m_softBodies[j]);
+                               }
+                       }
+               }
+
+               int penetration_count = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (psb->isActive())
+                       {
+                               penetration_count += psb->m_faceNodeContactsCCD.size();
+                               ;
+                       }
+               }
+               if (penetration_count == 0)
+               {
+                       break;
+               }
+
+               // apply inelastic impulse
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (psb->isActive())
+                       {
+                               psb->applyRepulsionForce(timeStep, false);
+                       }
+               }
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::softBodySelfCollision()
+{
+       BT_PROFILE("btDeformableMultiBodyDynamicsWorld::softBodySelfCollision");
+       for (int i = 0; i < m_softBodies.size(); i++)
+       {
+               btSoftBody* psb = m_softBodies[i];
+               if (psb->isActive())
+               {
+                       psb->defaultCollisionHandler(psb);
+               }
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::positionCorrection(btScalar timeStep)
+{
+       // correct the position of rigid bodies with temporary velocity generated from split impulse
+       btContactSolverInfo infoGlobal;
+       btVector3 zero(0, 0, 0);
+       for (int i = 0; i < m_nonStaticRigidBodies.size(); ++i)
+       {
+               btRigidBody* rb = m_nonStaticRigidBodies[i];
+               //correct the position/orientation based on push/turn recovery
+               btTransform newTransform;
+               btVector3 pushVelocity = rb->getPushVelocity();
+               btVector3 turnVelocity = rb->getTurnVelocity();
+               if (pushVelocity[0] != 0.f || pushVelocity[1] != 0 || pushVelocity[2] != 0 || turnVelocity[0] != 0.f || turnVelocity[1] != 0 || turnVelocity[2] != 0)
+               {
+                       btTransformUtil::integrateTransform(rb->getWorldTransform(), pushVelocity, turnVelocity * infoGlobal.m_splitImpulseTurnErp, timeStep, newTransform);
+                       rb->setWorldTransform(newTransform);
+                       rb->setPushVelocity(zero);
+                       rb->setTurnVelocity(zero);
+               }
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+       BT_PROFILE("integrateTransforms");
+       positionCorrection(timeStep);
+       btMultiBodyDynamicsWorld::integrateTransforms(timeStep);
+       m_deformableBodySolver->applyTransforms(timeStep);
+}
+
+void btDeformableMultiBodyDynamicsWorld::solveConstraints(btScalar timeStep)
+{
+       BT_PROFILE("btDeformableMultiBodyDynamicsWorld::solveConstraints");
+       // save v_{n+1}^* velocity after explicit forces
+       m_deformableBodySolver->backupVelocity();
+
+       // set up constraints among multibodies and between multibodies and deformable bodies
+       setupConstraints();
+
+       // solve contact constraints
+       solveContactConstraints();
+
+       // set up the directions in which the velocity does not change in the momentum solve
+       if (m_useProjection)
+               m_deformableBodySolver->setProjection();
+       else
+               m_deformableBodySolver->setLagrangeMultiplier();
+
+       // for explicit scheme, m_backupVelocity = v_{n+1}^*
+       // for implicit scheme, m_backupVelocity = v_n
+       // Here, set dv = v_{n+1} - v_n for nodes in contact
+       m_deformableBodySolver->setupDeformableSolve(m_implicit);
+
+       // At this point, dv should be golden for nodes in contact
+       // proceed to solve deformable momentum equation
+       m_deformableBodySolver->solveDeformableConstraints(timeStep);
+}
+
+void btDeformableMultiBodyDynamicsWorld::setupConstraints()
+{
+       // set up constraints between multibody and deformable bodies
+       m_deformableBodySolver->setConstraints(m_solverInfo);
+
+       // set up constraints among multibodies
+       {
+               sortConstraints();
+               // setup the solver callback
+               btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
+               btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
+               m_solverDeformableBodyIslandCallback->setup(&m_solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
+
+               // build islands
+               m_islandManager->buildIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld());
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::sortConstraints()
+{
+       m_sortedConstraints.resize(m_constraints.size());
+       int i;
+       for (i = 0; i < getNumConstraints(); i++)
+       {
+               m_sortedConstraints[i] = m_constraints[i];
+       }
+       m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
+
+       m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
+       for (i = 0; i < m_multiBodyConstraints.size(); i++)
+       {
+               m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
+       }
+       m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
+}
+
+void btDeformableMultiBodyDynamicsWorld::solveContactConstraints()
+{
+       // process constraints on each island
+       m_islandManager->processIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverDeformableBodyIslandCallback);
+
+       // process deferred
+       m_solverDeformableBodyIslandCallback->processConstraints();
+       m_constraintSolver->allSolved(m_solverInfo, m_debugDrawer);
+
+       // write joint feedback
+       {
+               for (int i = 0; i < this->m_multiBodies.size(); i++)
+               {
+                       btMultiBody* bod = m_multiBodies[i];
+
+                       bool isSleeping = false;
+
+                       if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+                       {
+                               isSleeping = true;
+                       }
+                       for (int b = 0; b < bod->getNumLinks(); b++)
+                       {
+                               if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+                                       isSleeping = true;
+                       }
+
+                       if (!isSleeping)
+                       {
+                               //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
+                               m_scratch_r.resize(bod->getNumLinks() + 1);  //multidof? ("Y"s use it and it is used to store qdd)
+                               m_scratch_v.resize(bod->getNumLinks() + 1);
+                               m_scratch_m.resize(bod->getNumLinks() + 1);
+
+                               if (bod->internalNeedsJointFeedback())
+                               {
+                                       if (!bod->isUsingRK4Integration())
+                                       {
+                                               if (bod->internalNeedsJointFeedback())
+                                               {
+                                                       bool isConstraintPass = true;
+                                                       bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(m_solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
+                                                                                                                                                                         getSolverInfo().m_jointFeedbackInWorldSpace,
+                                                                                                                                                                         getSolverInfo().m_jointFeedbackInJointFrame);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       for (int i = 0; i < this->m_multiBodies.size(); i++)
+       {
+               btMultiBody* bod = m_multiBodies[i];
+               bod->processDeltaVeeMultiDof2();
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
+{
+       m_softBodies.push_back(body);
+
+       // Set the soft body solver that will deal with this body
+       // to be the world's solver
+       body->setSoftBodySolver(m_deformableBodySolver);
+
+       btCollisionWorld::addCollisionObject(body,
+                                                                                collisionFilterGroup,
+                                                                                collisionFilterMask);
+}
+
+void btDeformableMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+       BT_PROFILE("predictUnconstraintMotion");
+       btMultiBodyDynamicsWorld::predictUnconstraintMotion(timeStep);
+       m_deformableBodySolver->predictMotion(timeStep);
+}
+
+void btDeformableMultiBodyDynamicsWorld::setGravity(const btVector3& gravity)
+{
+       btDiscreteDynamicsWorld::setGravity(gravity);
+       m_deformableBodySolver->setGravity(gravity);
+}
+
+void btDeformableMultiBodyDynamicsWorld::reinitialize(btScalar timeStep)
+{
+       m_internalTime += timeStep;
+       m_deformableBodySolver->setImplicit(m_implicit);
+       m_deformableBodySolver->setLineSearch(m_lineSearch);
+       m_deformableBodySolver->reinitialize(m_softBodies, timeStep);
+       btDispatcherInfo& dispatchInfo = btMultiBodyDynamicsWorld::getDispatchInfo();
+       dispatchInfo.m_timeStep = timeStep;
+       dispatchInfo.m_stepCount = 0;
+       dispatchInfo.m_debugDraw = btMultiBodyDynamicsWorld::getDebugDrawer();
+       btMultiBodyDynamicsWorld::getSolverInfo().m_timeStep = timeStep;
+       if (m_useProjection)
+       {
+               m_deformableBodySolver->m_useProjection = true;
+               m_deformableBodySolver->setStrainLimiting(true);
+               m_deformableBodySolver->setPreconditioner(btDeformableBackwardEulerObjective::Mass_preconditioner);
+       }
+       else
+       {
+               m_deformableBodySolver->m_useProjection = false;
+               m_deformableBodySolver->setStrainLimiting(false);
+               m_deformableBodySolver->setPreconditioner(btDeformableBackwardEulerObjective::KKT_preconditioner);
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::debugDrawWorld()
+{
+       btMultiBodyDynamicsWorld::debugDrawWorld();
+
+       for (int i = 0; i < getSoftBodyArray().size(); i++)
+       {
+               btSoftBody* psb = (btSoftBody*)getSoftBodyArray()[i];
+               {
+                       btSoftBodyHelpers::DrawFrame(psb, getDebugDrawer());
+                       btSoftBodyHelpers::Draw(psb, getDebugDrawer(), getDrawFlags());
+               }
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::applyRigidBodyGravity(btScalar timeStep)
+{
+       // Gravity is applied in stepSimulation and then cleared here and then applied here and then cleared here again
+       // so that 1) gravity is applied to velocity before constraint solve and 2) gravity is applied in each substep
+       // when there are multiple substeps
+       btMultiBodyDynamicsWorld::applyGravity();
+       // integrate rigid body gravity
+       for (int i = 0; i < m_nonStaticRigidBodies.size(); ++i)
+       {
+               btRigidBody* rb = m_nonStaticRigidBodies[i];
+               rb->integrateVelocities(timeStep);
+       }
+
+       // integrate multibody gravity
+       {
+               forwardKinematics();
+               clearMultiBodyConstraintForces();
+               {
+                       for (int i = 0; i < this->m_multiBodies.size(); i++)
+                       {
+                               btMultiBody* bod = m_multiBodies[i];
+
+                               bool isSleeping = false;
+
+                               if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+                               {
+                                       isSleeping = true;
+                               }
+                               for (int b = 0; b < bod->getNumLinks(); b++)
+                               {
+                                       if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+                                               isSleeping = true;
+                               }
+
+                               if (!isSleeping)
+                               {
+                                       m_scratch_r.resize(bod->getNumLinks() + 1);
+                                       m_scratch_v.resize(bod->getNumLinks() + 1);
+                                       m_scratch_m.resize(bod->getNumLinks() + 1);
+                                       bool isConstraintPass = false;
+                                       {
+                                               if (!bod->isUsingRK4Integration())
+                                               {
+                                                       bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(m_solverInfo.m_timeStep,
+                                                                                                                                                                         m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
+                                                                                                                                                                         getSolverInfo().m_jointFeedbackInWorldSpace,
+                                                                                                                                                                         getSolverInfo().m_jointFeedbackInJointFrame);
+                                               }
+                                               else
+                                               {
+                                                       btAssert(" RK4Integration is not supported");
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       clearGravity();
+}
+
+void btDeformableMultiBodyDynamicsWorld::clearGravity()
+{
+       BT_PROFILE("btMultiBody clearGravity");
+       // clear rigid body gravity
+       for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
+       {
+               btRigidBody* body = m_nonStaticRigidBodies[i];
+               if (body->isActive())
+               {
+                       body->clearGravity();
+               }
+       }
+       // clear multibody gravity
+       for (int i = 0; i < this->m_multiBodies.size(); i++)
+       {
+               btMultiBody* bod = m_multiBodies[i];
+
+               bool isSleeping = false;
+
+               if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
+               {
+                       isSleeping = true;
+               }
+               for (int b = 0; b < bod->getNumLinks(); b++)
+               {
+                       if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
+                               isSleeping = true;
+               }
+
+               if (!isSleeping)
+               {
+                       bod->addBaseForce(-m_gravity * bod->getBaseMass());
+
+                       for (int j = 0; j < bod->getNumLinks(); ++j)
+                       {
+                               bod->addLinkForce(j, -m_gravity * bod->getLinkMass(j));
+                       }
+               }
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::beforeSolverCallbacks(btScalar timeStep)
+{
+       if (0 != m_internalTickCallback)
+       {
+               (*m_internalTickCallback)(this, timeStep);
+       }
+
+       if (0 != m_solverCallback)
+       {
+               (*m_solverCallback)(m_internalTime, this);
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::afterSolverCallbacks(btScalar timeStep)
+{
+       if (0 != m_solverCallback)
+       {
+               (*m_solverCallback)(m_internalTime, this);
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::addForce(btSoftBody* psb, btDeformableLagrangianForce* force)
+{
+       btAlignedObjectArray<btDeformableLagrangianForce*>& forces = *m_deformableBodySolver->getLagrangianForceArray();
+       bool added = false;
+       for (int i = 0; i < forces.size(); ++i)
+       {
+               if (forces[i]->getForceType() == force->getForceType())
+               {
+                       forces[i]->addSoftBody(psb);
+                       added = true;
+                       break;
+               }
+       }
+       if (!added)
+       {
+               force->addSoftBody(psb);
+               force->setIndices(m_deformableBodySolver->getIndices());
+               forces.push_back(force);
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::removeForce(btSoftBody* psb, btDeformableLagrangianForce* force)
+{
+       btAlignedObjectArray<btDeformableLagrangianForce*>& forces = *m_deformableBodySolver->getLagrangianForceArray();
+       int removed_index = -1;
+       for (int i = 0; i < forces.size(); ++i)
+       {
+               if (forces[i]->getForceType() == force->getForceType())
+               {
+                       forces[i]->removeSoftBody(psb);
+                       if (forces[i]->m_softBodies.size() == 0)
+                               removed_index = i;
+                       break;
+               }
+       }
+       if (removed_index >= 0)
+               forces.removeAtIndex(removed_index);
+}
+
+void btDeformableMultiBodyDynamicsWorld::removeSoftBodyForce(btSoftBody* psb)
+{
+       btAlignedObjectArray<btDeformableLagrangianForce*>& forces = *m_deformableBodySolver->getLagrangianForceArray();
+       for (int i = 0; i < forces.size(); ++i)
+       {
+               forces[i]->removeSoftBody(psb);
+       }
+}
+
+void btDeformableMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
+{
+       removeSoftBodyForce(body);
+       m_softBodies.remove(body);
+       btCollisionWorld::removeCollisionObject(body);
+       // force a reinitialize so that node indices get updated.
+       m_deformableBodySolver->reinitialize(m_softBodies, btScalar(-1));
+}
+
+void btDeformableMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+       btSoftBody* body = btSoftBody::upcast(collisionObject);
+       if (body)
+               removeSoftBody(body);
+       else
+               btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
+}
+
+int btDeformableMultiBodyDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
+{
+       startProfiling(timeStep);
+
+       int numSimulationSubSteps = 0;
+
+       if (maxSubSteps)
+       {
+               //fixed timestep with interpolation
+               m_fixedTimeStep = fixedTimeStep;
+               m_localTime += timeStep;
+               if (m_localTime >= fixedTimeStep)
+               {
+                       numSimulationSubSteps = int(m_localTime / fixedTimeStep);
+                       m_localTime -= numSimulationSubSteps * fixedTimeStep;
+               }
+       }
+       else
+       {
+               //variable timestep
+               fixedTimeStep = timeStep;
+               m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
+               m_fixedTimeStep = 0;
+               if (btFuzzyZero(timeStep))
+               {
+                       numSimulationSubSteps = 0;
+                       maxSubSteps = 0;
+               }
+               else
+               {
+                       numSimulationSubSteps = 1;
+                       maxSubSteps = 1;
+               }
+       }
+
+       //process some debugging flags
+       if (getDebugDrawer())
+       {
+               btIDebugDraw* debugDrawer = getDebugDrawer();
+               gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
+       }
+       if (numSimulationSubSteps)
+       {
+               //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
+               int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps) ? maxSubSteps : numSimulationSubSteps;
+
+               saveKinematicState(fixedTimeStep * clampedSimulationSteps);
+
+               for (int i = 0; i < clampedSimulationSteps; i++)
+               {
+                       internalSingleStepSimulation(fixedTimeStep);
+                       synchronizeMotionStates();
+               }
+       }
+       else
+       {
+               synchronizeMotionStates();
+       }
+
+       clearForces();
+
+#ifndef BT_NO_PROFILE
+       CProfileManager::Increment_Frame_Counter();
+#endif  //BT_NO_PROFILE
+
+       return numSimulationSubSteps;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h
new file mode 100644 (file)
index 0000000..5971ecd
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
+#define BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
+
+#include "btSoftMultiBodyDynamicsWorld.h"
+#include "btDeformableLagrangianForce.h"
+#include "btDeformableMassSpringForce.h"
+// #include "btDeformableBodySolver.h"
+#include "btDeformableMultiBodyConstraintSolver.h"
+#include "btSoftBodyHelpers.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include <functional>
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+
+class btDeformableBodySolver;
+class btDeformableLagrangianForce;
+struct MultiBodyInplaceSolverIslandCallback;
+struct DeformableBodyInplaceSolverIslandCallback;
+class btDeformableMultiBodyConstraintSolver;
+
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+
+class btDeformableMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld
+{
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       ///Solver classes that encapsulate multiple deformable bodies for solving
+       btDeformableBodySolver* m_deformableBodySolver;
+       btSoftBodyArray m_softBodies;
+       int m_drawFlags;
+       bool m_drawNodeTree;
+       bool m_drawFaceTree;
+       bool m_drawClusterTree;
+       btSoftBodyWorldInfo m_sbi;
+       btScalar m_internalTime;
+       int m_ccdIterations;
+       bool m_implicit;
+       bool m_lineSearch;
+       bool m_useProjection;
+       DeformableBodyInplaceSolverIslandCallback* m_solverDeformableBodyIslandCallback;
+
+       typedef void (*btSolverCallback)(btScalar time, btDeformableMultiBodyDynamicsWorld* world);
+       btSolverCallback m_solverCallback;
+
+protected:
+       virtual void internalSingleStepSimulation(btScalar timeStep);
+
+       virtual void integrateTransforms(btScalar timeStep);
+
+       void positionCorrection(btScalar timeStep);
+
+       void solveConstraints(btScalar timeStep);
+
+       void updateActivationState(btScalar timeStep);
+
+       void clearGravity();
+
+public:
+       btDeformableMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btDeformableMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btDeformableBodySolver* deformableBodySolver = 0);
+
+       virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
+
+       virtual void debugDrawWorld();
+
+       void setSolverCallback(btSolverCallback cb)
+       {
+               m_solverCallback = cb;
+       }
+
+       virtual ~btDeformableMultiBodyDynamicsWorld();
+
+       virtual btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld()
+       {
+               return (btMultiBodyDynamicsWorld*)(this);
+       }
+
+       virtual const btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld() const
+       {
+               return (const btMultiBodyDynamicsWorld*)(this);
+       }
+
+       virtual btDynamicsWorldType getWorldType() const
+       {
+               return BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD;
+       }
+
+       virtual void predictUnconstraintMotion(btScalar timeStep);
+
+       virtual void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
+
+       btSoftBodyArray& getSoftBodyArray()
+       {
+               return m_softBodies;
+       }
+
+       const btSoftBodyArray& getSoftBodyArray() const
+       {
+               return m_softBodies;
+       }
+
+       btSoftBodyWorldInfo& getWorldInfo()
+       {
+               return m_sbi;
+       }
+
+       const btSoftBodyWorldInfo& getWorldInfo() const
+       {
+               return m_sbi;
+       }
+
+       virtual void setGravity(const btVector3& gravity);
+
+       void reinitialize(btScalar timeStep);
+
+       void applyRigidBodyGravity(btScalar timeStep);
+
+       void beforeSolverCallbacks(btScalar timeStep);
+
+       void afterSolverCallbacks(btScalar timeStep);
+
+       void addForce(btSoftBody* psb, btDeformableLagrangianForce* force);
+
+       void removeForce(btSoftBody* psb, btDeformableLagrangianForce* force);
+
+       void removeSoftBodyForce(btSoftBody* psb);
+
+       void removeSoftBody(btSoftBody* body);
+
+       void removeCollisionObject(btCollisionObject* collisionObject);
+
+       int getDrawFlags() const { return (m_drawFlags); }
+       void setDrawFlags(int f) { m_drawFlags = f; }
+
+       void setupConstraints();
+
+       void performDeformableCollisionDetection();
+
+       void solveMultiBodyConstraints();
+
+       void solveContactConstraints();
+
+       void sortConstraints();
+
+       void softBodySelfCollision();
+
+       void setImplicit(bool implicit)
+       {
+               m_implicit = implicit;
+       }
+
+       void setLineSearch(bool lineSearch)
+       {
+               m_lineSearch = lineSearch;
+       }
+
+       void setUseProjection(bool useProjection)
+       {
+               m_useProjection = useProjection;
+       }
+
+       void applyRepulsionForce(btScalar timeStep);
+
+       void performGeometricCollisions(btScalar timeStep);
+
+       struct btDeformableSingleRayCallback : public btBroadphaseRayCallback
+       {
+               btVector3 m_rayFromWorld;
+               btVector3 m_rayToWorld;
+               btTransform m_rayFromTrans;
+               btTransform m_rayToTrans;
+               btVector3 m_hitNormal;
+
+               const btDeformableMultiBodyDynamicsWorld* m_world;
+               btCollisionWorld::RayResultCallback& m_resultCallback;
+
+               btDeformableSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btDeformableMultiBodyDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
+                       : m_rayFromWorld(rayFromWorld),
+                         m_rayToWorld(rayToWorld),
+                         m_world(world),
+                         m_resultCallback(resultCallback)
+               {
+                       m_rayFromTrans.setIdentity();
+                       m_rayFromTrans.setOrigin(m_rayFromWorld);
+                       m_rayToTrans.setIdentity();
+                       m_rayToTrans.setOrigin(m_rayToWorld);
+
+                       btVector3 rayDir = (rayToWorld - rayFromWorld);
+
+                       rayDir.normalize();
+                       ///what about division by zero? --> just set rayDirection[i] to INF/1e30
+                       m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
+                       m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
+                       m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
+                       m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+                       m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+                       m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+                       m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
+               }
+
+               virtual bool process(const btBroadphaseProxy* proxy)
+               {
+                       ///terminate further ray tests, once the closestHitFraction reached zero
+                       if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+                               return false;
+
+                       btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+                       //only perform raycast if filterMask matches
+                       if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+                       {
+                               //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+                               //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+                btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+                collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+                //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+                const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+                const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+                               //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+                               //culling already done by broadphase
+                               //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+                               {
+                                       m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
+                                                                                  collisionObject,
+                                                                                  collisionObject->getCollisionShape(),
+                                                                                  collisionObject->getWorldTransform(),
+                                                                                  m_resultCallback);
+                               }
+                       }
+                       return true;
+               }
+       };
+
+       void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+       {
+               BT_PROFILE("rayTest");
+               /// use the broadphase to accelerate the search for objects, based on their aabb
+               /// and for each object with ray-aabb overlap, perform an exact ray test
+               btDeformableSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+               m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
+#else
+               for (int i = 0; i < this->getNumCollisionObjects(); i++)
+               {
+                       rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+               }
+#endif  //USE_BRUTEFORCE_RAYBROADPHASE
+       }
+
+       void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+                                          btCollisionObject* collisionObject,
+                                          const btCollisionShape* collisionShape,
+                                          const btTransform& colObjWorldTransform,
+                                          RayResultCallback& resultCallback) const
+       {
+               if (collisionShape->isSoftBody())
+               {
+                       btSoftBody* softBody = btSoftBody::upcast(collisionObject);
+                       if (softBody)
+                       {
+                               btSoftBody::sRayCast softResult;
+                               if (softBody->rayFaceTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
+                               {
+                                       if (softResult.fraction <= resultCallback.m_closestHitFraction)
+                                       {
+                                               btCollisionWorld::LocalShapeInfo shapeInfo;
+                                               shapeInfo.m_shapePart = 0;
+                                               shapeInfo.m_triangleIndex = softResult.index;
+                                               // get the normal
+                                               btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
+                                               btVector3 normal = -rayDir;
+                                               normal.normalize();
+                                               {
+                                                       normal = softBody->m_faces[softResult.index].m_normal;
+                                                       if (normal.dot(rayDir) > 0)
+                                                       {
+                                                               // normal always point toward origin of the ray
+                                                               normal = -normal;
+                                                       }
+                                               }
+
+                                               btCollisionWorld::LocalRayResult rayResult(collisionObject,
+                                                                                                                                  &shapeInfo,
+                                                                                                                                  normal,
+                                                                                                                                  softResult.fraction);
+                                               bool normalInWorldSpace = true;
+                                               resultCallback.addSingleResult(rayResult, normalInWorldSpace);
+                                       }
+                               }
+                       }
+               }
+               else
+               {
+                       btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
+               }
+       }
+};
+
+#endif  //BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableNeoHookeanForce.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btDeformableNeoHookeanForce.h
new file mode 100644 (file)
index 0000000..60798c5
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2019 Google Inc. http://bulletphysics.org
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_NEOHOOKEAN_H
+#define BT_NEOHOOKEAN_H
+
+#include "btDeformableLagrangianForce.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btImplicitQRSVD.h"
+// This energy is as described in https://graphics.pixar.com/library/StableElasticity/paper.pdf
+class btDeformableNeoHookeanForce : public btDeformableLagrangianForce
+{
+public:
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       btScalar m_mu, m_lambda;  // Lame Parameters
+       btScalar m_E, m_nu;       // Young's modulus and Poisson ratio
+       btScalar m_mu_damp, m_lambda_damp;
+       btDeformableNeoHookeanForce() : m_mu(1), m_lambda(1)
+       {
+               btScalar damping = 0.05;
+               m_mu_damp = damping * m_mu;
+               m_lambda_damp = damping * m_lambda;
+               updateYoungsModulusAndPoissonRatio();
+       }
+
+       btDeformableNeoHookeanForce(btScalar mu, btScalar lambda, btScalar damping = 0.05) : m_mu(mu), m_lambda(lambda)
+       {
+               m_mu_damp = damping * m_mu;
+               m_lambda_damp = damping * m_lambda;
+               updateYoungsModulusAndPoissonRatio();
+       }
+
+       void updateYoungsModulusAndPoissonRatio()
+       {
+               // conversion from Lame Parameters to Young's modulus and Poisson ratio
+               // https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
+               m_E = m_mu * (3 * m_lambda + 2 * m_mu) / (m_lambda + m_mu);
+               m_nu = m_lambda * 0.5 / (m_mu + m_lambda);
+       }
+
+       void updateLameParameters()
+       {
+               // conversion from Young's modulus and Poisson ratio to Lame Parameters
+               // https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
+               m_mu = m_E * 0.5 / (1 + m_nu);
+               m_lambda = m_E * m_nu / ((1 + m_nu) * (1 - 2 * m_nu));
+       }
+
+       void setYoungsModulus(btScalar E)
+       {
+               m_E = E;
+               updateLameParameters();
+       }
+
+       void setPoissonRatio(btScalar nu)
+       {
+               m_nu = nu;
+               updateLameParameters();
+       }
+
+       void setDamping(btScalar damping)
+       {
+               m_mu_damp = damping * m_mu;
+               m_lambda_damp = damping * m_lambda;
+       }
+
+       void setLameParameters(btScalar mu, btScalar lambda)
+       {
+               m_mu = mu;
+               m_lambda = lambda;
+               updateYoungsModulusAndPoissonRatio();
+       }
+
+       virtual void addScaledForces(btScalar scale, TVStack& force)
+       {
+               addScaledDampingForce(scale, force);
+               addScaledElasticForce(scale, force);
+       }
+
+       virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
+       {
+               addScaledElasticForce(scale, force);
+       }
+
+       // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+       virtual void addScaledDampingForce(btScalar scale, TVStack& force)
+       {
+               if (m_mu_damp == 0 && m_lambda_damp == 0)
+                       return;
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= force.size());
+               btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_tetras.size(); ++j)
+                       {
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btSoftBody::Node* node0 = tetra.m_n[0];
+                               btSoftBody::Node* node1 = tetra.m_n[1];
+                               btSoftBody::Node* node2 = tetra.m_n[2];
+                               btSoftBody::Node* node3 = tetra.m_n[3];
+                               size_t id0 = node0->index;
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               size_t id3 = node3->index;
+                               btMatrix3x3 dF = DsFromVelocity(node0, node1, node2, node3) * tetra.m_Dm_inverse;
+                               btMatrix3x3 I;
+                               I.setIdentity();
+                               btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0] + dF[1][1] + dF[2][2]) * m_lambda_damp;
+                               //                firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
+                               btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose() * grad_N_hat_1st_col);
+                               btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+
+                               // damping force differential
+                               btScalar scale1 = scale * tetra.m_element_measure;
+                               force[id0] -= scale1 * df_on_node0;
+                               force[id1] -= scale1 * df_on_node123.getColumn(0);
+                               force[id2] -= scale1 * df_on_node123.getColumn(1);
+                               force[id3] -= scale1 * df_on_node123.getColumn(2);
+                       }
+               }
+       }
+
+       virtual double totalElasticEnergy(btScalar dt)
+       {
+               double energy = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_tetraScratches.size(); ++j)
+                       {
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btSoftBody::TetraScratch& s = psb->m_tetraScratches[j];
+                               energy += tetra.m_element_measure * elasticEnergyDensity(s);
+                       }
+               }
+               return energy;
+       }
+
+       // The damping energy is formulated as in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+       virtual double totalDampingEnergy(btScalar dt)
+       {
+               double energy = 0;
+               int sz = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               sz = btMax(sz, psb->m_nodes[j].index);
+                       }
+               }
+               TVStack dampingForce;
+               dampingForce.resize(sz + 1);
+               for (int i = 0; i < dampingForce.size(); ++i)
+                       dampingForce[i].setZero();
+               addScaledDampingForce(0.5, dampingForce);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               const btSoftBody::Node& node = psb->m_nodes[j];
+                               energy -= dampingForce[node.index].dot(node.m_v) / dt;
+                       }
+               }
+               return energy;
+       }
+
+       double elasticEnergyDensity(const btSoftBody::TetraScratch& s)
+       {
+               double density = 0;
+               density += m_mu * 0.5 * (s.m_trace - 3.);
+               density += m_lambda * 0.5 * (s.m_J - 1. - 0.75 * m_mu / m_lambda) * (s.m_J - 1. - 0.75 * m_mu / m_lambda);
+               density -= m_mu * 0.5 * log(s.m_trace + 1);
+               return density;
+       }
+
+       virtual void addScaledElasticForce(btScalar scale, TVStack& force)
+       {
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= force.size());
+               btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       btScalar max_p = psb->m_cfg.m_maxStress;
+                       for (int j = 0; j < psb->m_tetras.size(); ++j)
+                       {
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btMatrix3x3 P;
+                               firstPiola(psb->m_tetraScratches[j], P);
+#ifdef USE_SVD
+                               if (max_p > 0)
+                               {
+                                       // since we want to clamp the principal stress to max_p, we only need to
+                                       // calculate SVD when sigma_0^2 + sigma_1^2 + sigma_2^2 > max_p * max_p
+                                       btScalar trPTP = (P[0].length2() + P[1].length2() + P[2].length2());
+                                       if (trPTP > max_p * max_p)
+                                       {
+                                               btMatrix3x3 U, V;
+                                               btVector3 sigma;
+                                               singularValueDecomposition(P, U, sigma, V);
+                                               sigma[0] = btMin(sigma[0], max_p);
+                                               sigma[1] = btMin(sigma[1], max_p);
+                                               sigma[2] = btMin(sigma[2], max_p);
+                                               sigma[0] = btMax(sigma[0], -max_p);
+                                               sigma[1] = btMax(sigma[1], -max_p);
+                                               sigma[2] = btMax(sigma[2], -max_p);
+                                               btMatrix3x3 Sigma;
+                                               Sigma.setIdentity();
+                                               Sigma[0][0] = sigma[0];
+                                               Sigma[1][1] = sigma[1];
+                                               Sigma[2][2] = sigma[2];
+                                               P = U * Sigma * V.transpose();
+                                       }
+                               }
+#endif
+                               //                btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+                               btMatrix3x3 force_on_node123 = P * tetra.m_Dm_inverse.transpose();
+                               btVector3 force_on_node0 = force_on_node123 * grad_N_hat_1st_col;
+
+                               btSoftBody::Node* node0 = tetra.m_n[0];
+                               btSoftBody::Node* node1 = tetra.m_n[1];
+                               btSoftBody::Node* node2 = tetra.m_n[2];
+                               btSoftBody::Node* node3 = tetra.m_n[3];
+                               size_t id0 = node0->index;
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               size_t id3 = node3->index;
+
+                               // elastic force
+                               btScalar scale1 = scale * tetra.m_element_measure;
+                               force[id0] -= scale1 * force_on_node0;
+                               force[id1] -= scale1 * force_on_node123.getColumn(0);
+                               force[id2] -= scale1 * force_on_node123.getColumn(1);
+                               force[id3] -= scale1 * force_on_node123.getColumn(2);
+                       }
+               }
+       }
+
+       // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
+       virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
+       {
+               if (m_mu_damp == 0 && m_lambda_damp == 0)
+                       return;
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= df.size());
+               btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_tetras.size(); ++j)
+                       {
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btSoftBody::Node* node0 = tetra.m_n[0];
+                               btSoftBody::Node* node1 = tetra.m_n[1];
+                               btSoftBody::Node* node2 = tetra.m_n[2];
+                               btSoftBody::Node* node3 = tetra.m_n[3];
+                               size_t id0 = node0->index;
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               size_t id3 = node3->index;
+                               btMatrix3x3 dF = Ds(id0, id1, id2, id3, dv) * tetra.m_Dm_inverse;
+                               btMatrix3x3 I;
+                               I.setIdentity();
+                               btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0] + dF[1][1] + dF[2][2]) * m_lambda_damp;
+                               //                firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
+                               //                btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+                               btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+                               btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+                               // damping force differential
+                               btScalar scale1 = scale * tetra.m_element_measure;
+                               df[id0] -= scale1 * df_on_node0;
+                               df[id1] -= scale1 * df_on_node123.getColumn(0);
+                               df[id2] -= scale1 * df_on_node123.getColumn(1);
+                               df[id3] -= scale1 * df_on_node123.getColumn(2);
+                       }
+               }
+       }
+
+       virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) {}
+
+       virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
+       {
+               int numNodes = getNumNodes();
+               btAssert(numNodes <= df.size());
+               btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       if (!psb->isActive())
+                       {
+                               continue;
+                       }
+                       for (int j = 0; j < psb->m_tetras.size(); ++j)
+                       {
+                               btSoftBody::Tetra& tetra = psb->m_tetras[j];
+                               btSoftBody::Node* node0 = tetra.m_n[0];
+                               btSoftBody::Node* node1 = tetra.m_n[1];
+                               btSoftBody::Node* node2 = tetra.m_n[2];
+                               btSoftBody::Node* node3 = tetra.m_n[3];
+                               size_t id0 = node0->index;
+                               size_t id1 = node1->index;
+                               size_t id2 = node2->index;
+                               size_t id3 = node3->index;
+                               btMatrix3x3 dF = Ds(id0, id1, id2, id3, dx) * tetra.m_Dm_inverse;
+                               btMatrix3x3 dP;
+                               firstPiolaDifferential(psb->m_tetraScratches[j], dF, dP);
+                               //                btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
+                               btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
+                               btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
+
+                               // elastic force differential
+                               btScalar scale1 = scale * tetra.m_element_measure;
+                               df[id0] -= scale1 * df_on_node0;
+                               df[id1] -= scale1 * df_on_node123.getColumn(0);
+                               df[id2] -= scale1 * df_on_node123.getColumn(1);
+                               df[id3] -= scale1 * df_on_node123.getColumn(2);
+                       }
+               }
+       }
+
+       void firstPiola(const btSoftBody::TetraScratch& s, btMatrix3x3& P)
+       {
+               btScalar c1 = (m_mu * (1. - 1. / (s.m_trace + 1.)));
+               btScalar c2 = (m_lambda * (s.m_J - 1.) - 0.75 * m_mu);
+               P = s.m_F * c1 + s.m_cofF * c2;
+       }
+
+       // Let P be the first piola stress.
+       // This function calculates the dP = dP/dF * dF
+       void firstPiolaDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+       {
+               btScalar c1 = m_mu * (1. - 1. / (s.m_trace + 1.));
+               btScalar c2 = (2. * m_mu) * DotProduct(s.m_F, dF) * (1. / ((1. + s.m_trace) * (1. + s.m_trace)));
+               btScalar c3 = (m_lambda * DotProduct(s.m_cofF, dF));
+               dP = dF * c1 + s.m_F * c2;
+               addScaledCofactorMatrixDifferential(s.m_F, dF, m_lambda * (s.m_J - 1.) - 0.75 * m_mu, dP);
+               dP += s.m_cofF * c3;
+       }
+
+       // Let Q be the damping stress.
+       // This function calculates the dP = dQ/dF * dF
+       void firstPiolaDampingDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
+       {
+               btScalar c1 = (m_mu_damp * (1. - 1. / (s.m_trace + 1.)));
+               btScalar c2 = ((2. * m_mu_damp) * DotProduct(s.m_F, dF) * (1. / ((1. + s.m_trace) * (1. + s.m_trace))));
+               btScalar c3 = (m_lambda_damp * DotProduct(s.m_cofF, dF));
+               dP = dF * c1 + s.m_F * c2;
+               addScaledCofactorMatrixDifferential(s.m_F, dF, m_lambda_damp * (s.m_J - 1.) - 0.75 * m_mu_damp, dP);
+               dP += s.m_cofF * c3;
+       }
+
+       btScalar DotProduct(const btMatrix3x3& A, const btMatrix3x3& B)
+       {
+               btScalar ans = 0;
+               for (int i = 0; i < 3; ++i)
+               {
+                       ans += A[i].dot(B[i]);
+               }
+               return ans;
+       }
+
+       // Let C(A) be the cofactor of the matrix A
+       // Let H = the derivative of C(A) with respect to A evaluated at F = A
+       // This function calculates H*dF
+       void addScaledCofactorMatrixDifferential(const btMatrix3x3& F, const btMatrix3x3& dF, btScalar scale, btMatrix3x3& M)
+       {
+               M[0][0] += scale * (dF[1][1] * F[2][2] + F[1][1] * dF[2][2] - dF[2][1] * F[1][2] - F[2][1] * dF[1][2]);
+               M[1][0] += scale * (dF[2][1] * F[0][2] + F[2][1] * dF[0][2] - dF[0][1] * F[2][2] - F[0][1] * dF[2][2]);
+               M[2][0] += scale * (dF[0][1] * F[1][2] + F[0][1] * dF[1][2] - dF[1][1] * F[0][2] - F[1][1] * dF[0][2]);
+               M[0][1] += scale * (dF[2][0] * F[1][2] + F[2][0] * dF[1][2] - dF[1][0] * F[2][2] - F[1][0] * dF[2][2]);
+               M[1][1] += scale * (dF[0][0] * F[2][2] + F[0][0] * dF[2][2] - dF[2][0] * F[0][2] - F[2][0] * dF[0][2]);
+               M[2][1] += scale * (dF[1][0] * F[0][2] + F[1][0] * dF[0][2] - dF[0][0] * F[1][2] - F[0][0] * dF[1][2]);
+               M[0][2] += scale * (dF[1][0] * F[2][1] + F[1][0] * dF[2][1] - dF[2][0] * F[1][1] - F[2][0] * dF[1][1]);
+               M[1][2] += scale * (dF[2][0] * F[0][1] + F[2][0] * dF[0][1] - dF[0][0] * F[2][1] - F[0][0] * dF[2][1]);
+               M[2][2] += scale * (dF[0][0] * F[1][1] + F[0][0] * dF[1][1] - dF[1][0] * F[0][1] - F[1][0] * dF[0][1]);
+       }
+
+       virtual btDeformableLagrangianForceType getForceType()
+       {
+               return BT_NEOHOOKEAN_FORCE;
+       }
+};
+#endif /* BT_NEOHOOKEAN_H */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btKrylovSolver.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btKrylovSolver.h
new file mode 100644 (file)
index 0000000..59126b4
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_KRYLOV_SOLVER_H
+#define BT_KRYLOV_SOLVER_H
+#include <iostream>
+#include <cmath>
+#include <limits>
+#include <LinearMath/btAlignedObjectArray.h>
+#include <LinearMath/btVector3.h>
+#include <LinearMath/btScalar.h>
+#include "LinearMath/btQuickprof.h"
+
+template <class MatrixX>
+class btKrylovSolver
+{
+       typedef btAlignedObjectArray<btVector3> TVStack;
+
+public:
+       int m_maxIterations;
+       btScalar m_tolerance;
+       btKrylovSolver(int maxIterations, btScalar tolerance)
+               : m_maxIterations(maxIterations), m_tolerance(tolerance)
+       {
+       }
+
+       virtual ~btKrylovSolver() {}
+
+       virtual int solve(MatrixX& A, TVStack& x, const TVStack& b, bool verbose = false) = 0;
+
+       virtual void reinitialize(const TVStack& b) = 0;
+
+       virtual SIMD_FORCE_INLINE TVStack sub(const TVStack& a, const TVStack& b)
+       {
+               // c = a-b
+               btAssert(a.size() == b.size());
+               TVStack c;
+               c.resize(a.size());
+               for (int i = 0; i < a.size(); ++i)
+               {
+                       c[i] = a[i] - b[i];
+               }
+               return c;
+       }
+
+       virtual SIMD_FORCE_INLINE btScalar squaredNorm(const TVStack& a)
+       {
+               return dot(a, a);
+       }
+
+       virtual SIMD_FORCE_INLINE btScalar norm(const TVStack& a)
+       {
+               btScalar ret = 0;
+               for (int i = 0; i < a.size(); ++i)
+               {
+                       for (int d = 0; d < 3; ++d)
+                       {
+                               ret = btMax(ret, btFabs(a[i][d]));
+                       }
+               }
+               return ret;
+       }
+
+       virtual SIMD_FORCE_INLINE btScalar dot(const TVStack& a, const TVStack& b)
+       {
+               btScalar ans(0);
+               for (int i = 0; i < a.size(); ++i)
+                       ans += a[i].dot(b[i]);
+               return ans;
+       }
+
+       virtual SIMD_FORCE_INLINE void multAndAddTo(btScalar s, const TVStack& a, TVStack& result)
+       {
+               //        result += s*a
+               btAssert(a.size() == result.size());
+               for (int i = 0; i < a.size(); ++i)
+                       result[i] += s * a[i];
+       }
+
+       virtual SIMD_FORCE_INLINE TVStack multAndAdd(btScalar s, const TVStack& a, const TVStack& b)
+       {
+               // result = a*s + b
+               TVStack result;
+               result.resize(a.size());
+               for (int i = 0; i < a.size(); ++i)
+                       result[i] = s * a[i] + b[i];
+               return result;
+       }
+
+       virtual SIMD_FORCE_INLINE void setTolerance(btScalar tolerance)
+       {
+               m_tolerance = tolerance;
+       }
+};
+#endif /* BT_KRYLOV_SOLVER_H */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btPreconditioner.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btPreconditioner.h
new file mode 100644 (file)
index 0000000..21c1106
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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_PRECONDITIONER_H
+#define BT_PRECONDITIONER_H
+
+class Preconditioner
+{
+public:
+       typedef btAlignedObjectArray<btVector3> TVStack;
+       virtual void operator()(const TVStack& x, TVStack& b) = 0;
+       virtual void reinitialize(bool nodeUpdated) = 0;
+       virtual ~Preconditioner() {}
+};
+
+class DefaultPreconditioner : public Preconditioner
+{
+public:
+       virtual void operator()(const TVStack& x, TVStack& b)
+       {
+               btAssert(b.size() == x.size());
+               for (int i = 0; i < b.size(); ++i)
+                       b[i] = x[i];
+       }
+       virtual void reinitialize(bool nodeUpdated)
+       {
+       }
+
+       virtual ~DefaultPreconditioner() {}
+};
+
+class MassPreconditioner : public Preconditioner
+{
+       btAlignedObjectArray<btScalar> m_inv_mass;
+       const btAlignedObjectArray<btSoftBody*>& m_softBodies;
+
+public:
+       MassPreconditioner(const btAlignedObjectArray<btSoftBody*>& softBodies)
+               : m_softBodies(softBodies)
+       {
+       }
+
+       virtual void reinitialize(bool nodeUpdated)
+       {
+               if (nodeUpdated)
+               {
+                       m_inv_mass.clear();
+                       for (int i = 0; i < m_softBodies.size(); ++i)
+                       {
+                               btSoftBody* psb = m_softBodies[i];
+                               for (int j = 0; j < psb->m_nodes.size(); ++j)
+                                       m_inv_mass.push_back(psb->m_nodes[j].m_im);
+                       }
+               }
+       }
+
+       virtual void operator()(const TVStack& x, TVStack& b)
+       {
+               btAssert(b.size() == x.size());
+               btAssert(m_inv_mass.size() <= x.size());
+               for (int i = 0; i < m_inv_mass.size(); ++i)
+               {
+                       b[i] = x[i] * m_inv_mass[i];
+               }
+               for (int i = m_inv_mass.size(); i < b.size(); ++i)
+               {
+                       b[i] = x[i];
+               }
+       }
+};
+
+class KKTPreconditioner : public Preconditioner
+{
+       const btAlignedObjectArray<btSoftBody*>& m_softBodies;
+       const btDeformableContactProjection& m_projections;
+       const btAlignedObjectArray<btDeformableLagrangianForce*>& m_lf;
+       TVStack m_inv_A, m_inv_S;
+       const btScalar& m_dt;
+       const bool& m_implicit;
+
+public:
+       KKTPreconditioner(const btAlignedObjectArray<btSoftBody*>& softBodies, const btDeformableContactProjection& projections, const btAlignedObjectArray<btDeformableLagrangianForce*>& lf, const btScalar& dt, const bool& implicit)
+               : m_softBodies(softBodies), m_projections(projections), m_lf(lf), m_dt(dt), m_implicit(implicit)
+       {
+       }
+
+       virtual void reinitialize(bool nodeUpdated)
+       {
+               if (nodeUpdated)
+               {
+                       int num_nodes = 0;
+                       for (int i = 0; i < m_softBodies.size(); ++i)
+                       {
+                               btSoftBody* psb = m_softBodies[i];
+                               num_nodes += psb->m_nodes.size();
+                       }
+                       m_inv_A.resize(num_nodes);
+               }
+               buildDiagonalA(m_inv_A);
+               for (int i = 0; i < m_inv_A.size(); ++i)
+               {
+                       //            printf("A[%d] = %f, %f, %f \n", i, m_inv_A[i][0], m_inv_A[i][1], m_inv_A[i][2]);
+                       for (int d = 0; d < 3; ++d)
+                       {
+                               m_inv_A[i][d] = (m_inv_A[i][d] == 0) ? 0.0 : 1.0 / m_inv_A[i][d];
+                       }
+               }
+               m_inv_S.resize(m_projections.m_lagrangeMultipliers.size());
+               //        printf("S.size() = %d \n", m_inv_S.size());
+               buildDiagonalS(m_inv_A, m_inv_S);
+               for (int i = 0; i < m_inv_S.size(); ++i)
+               {
+                       //            printf("S[%d] = %f, %f, %f \n", i, m_inv_S[i][0], m_inv_S[i][1], m_inv_S[i][2]);
+                       for (int d = 0; d < 3; ++d)
+                       {
+                               m_inv_S[i][d] = (m_inv_S[i][d] == 0) ? 0.0 : 1.0 / m_inv_S[i][d];
+                       }
+               }
+       }
+
+       void buildDiagonalA(TVStack& diagA) const
+       {
+               size_t counter = 0;
+               for (int i = 0; i < m_softBodies.size(); ++i)
+               {
+                       btSoftBody* psb = m_softBodies[i];
+                       for (int j = 0; j < psb->m_nodes.size(); ++j)
+                       {
+                               const btSoftBody::Node& node = psb->m_nodes[j];
+                               diagA[counter] = (node.m_im == 0) ? btVector3(0, 0, 0) : btVector3(1.0 / node.m_im, 1.0 / node.m_im, 1.0 / node.m_im);
+                               ++counter;
+                       }
+               }
+               if (m_implicit)
+               {
+                       printf("implicit not implemented\n");
+                       btAssert(false);
+               }
+               for (int i = 0; i < m_lf.size(); ++i)
+               {
+                       // add damping matrix
+                       m_lf[i]->buildDampingForceDifferentialDiagonal(-m_dt, diagA);
+               }
+       }
+
+       void buildDiagonalS(const TVStack& inv_A, TVStack& diagS)
+       {
+               for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+               {
+                       // S[k,k] = e_k^T * C A_d^-1 C^T * e_k
+                       const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+                       btVector3& t = diagS[c];
+                       t.setZero();
+                       for (int j = 0; j < lm.m_num_constraints; ++j)
+                       {
+                               for (int i = 0; i < lm.m_num_nodes; ++i)
+                               {
+                                       for (int d = 0; d < 3; ++d)
+                                       {
+                                               t[j] += inv_A[lm.m_indices[i]][d] * lm.m_dirs[j][d] * lm.m_dirs[j][d] * lm.m_weights[i] * lm.m_weights[i];
+                                       }
+                               }
+                       }
+               }
+       }
+//#define USE_FULL_PRECONDITIONER
+#ifndef USE_FULL_PRECONDITIONER
+       virtual void operator()(const TVStack& x, TVStack& b)
+       {
+               btAssert(b.size() == x.size());
+               for (int i = 0; i < m_inv_A.size(); ++i)
+               {
+                       b[i] = x[i] * m_inv_A[i];
+               }
+               int offset = m_inv_A.size();
+               for (int i = 0; i < m_inv_S.size(); ++i)
+               {
+                       b[i + offset] = x[i + offset] * m_inv_S[i];
+               }
+       }
+#else
+       virtual void operator()(const TVStack& x, TVStack& b)
+       {
+               btAssert(b.size() == x.size());
+               int offset = m_inv_A.size();
+
+               for (int i = 0; i < m_inv_A.size(); ++i)
+               {
+                       b[i] = x[i] * m_inv_A[i];
+               }
+
+               for (int i = 0; i < m_inv_S.size(); ++i)
+               {
+                       b[i + offset].setZero();
+               }
+
+               for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+               {
+                       const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+                       // C * x
+                       for (int d = 0; d < lm.m_num_constraints; ++d)
+                       {
+                               for (int i = 0; i < lm.m_num_nodes; ++i)
+                               {
+                                       b[offset + c][d] += lm.m_weights[i] * b[lm.m_indices[i]].dot(lm.m_dirs[d]);
+                               }
+                       }
+               }
+
+               for (int i = 0; i < m_inv_S.size(); ++i)
+               {
+                       b[i + offset] = b[i + offset] * m_inv_S[i];
+               }
+
+               for (int i = 0; i < m_inv_A.size(); ++i)
+               {
+                       b[i].setZero();
+               }
+
+               for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+               {
+                       // C^T * lambda
+                       const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+                       for (int i = 0; i < lm.m_num_nodes; ++i)
+                       {
+                               for (int j = 0; j < lm.m_num_constraints; ++j)
+                               {
+                                       b[lm.m_indices[i]] += b[offset + c][j] * lm.m_weights[i] * lm.m_dirs[j];
+                               }
+                       }
+               }
+
+               for (int i = 0; i < m_inv_A.size(); ++i)
+               {
+                       b[i] = (x[i] - b[i]) * m_inv_A[i];
+               }
+
+               TVStack t;
+               t.resize(b.size());
+               for (int i = 0; i < m_inv_S.size(); ++i)
+               {
+                       t[i + offset] = x[i + offset] * m_inv_S[i];
+               }
+               for (int i = 0; i < m_inv_A.size(); ++i)
+               {
+                       t[i].setZero();
+               }
+               for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
+               {
+                       // C^T * lambda
+                       const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
+                       for (int i = 0; i < lm.m_num_nodes; ++i)
+                       {
+                               for (int j = 0; j < lm.m_num_constraints; ++j)
+                               {
+                                       t[lm.m_indices[i]] += t[offset + c][j] * lm.m_weights[i] * lm.m_dirs[j];
+                               }
+                       }
+               }
+               for (int i = 0; i < m_inv_A.size(); ++i)
+               {
+                       b[i] += t[i] * m_inv_A[i];
+               }
+
+               for (int i = 0; i < m_inv_S.size(); ++i)
+               {
+                       b[i + offset] -= x[i + offset] * m_inv_S[i];
+               }
+       }
+#endif
+};
+
+#endif /* BT_PRECONDITIONER_H */
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBody.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBody.cpp
new file mode 100644 (file)
index 0000000..c873099
--- /dev/null
@@ -0,0 +1,4757 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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"
+#include "BulletSoftBody/btSoftBodySolvers.h"
+#include "btSoftBodyData.h"
+#include "LinearMath/btSerializer.h"
+#include "LinearMath/btImplicitQRSVD.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include <iostream>
+//
+static inline btDbvtNode* buildTreeBottomUp(btAlignedObjectArray<btDbvtNode*>& leafNodes, btAlignedObjectArray<btAlignedObjectArray<int> >& adj)
+{
+       int N = leafNodes.size();
+       if (N == 0)
+       {
+               return NULL;
+       }
+       while (N > 1)
+       {
+               btAlignedObjectArray<bool> marked;
+               btAlignedObjectArray<btDbvtNode*> newLeafNodes;
+               btAlignedObjectArray<std::pair<int, int> > childIds;
+               btAlignedObjectArray<btAlignedObjectArray<int> > newAdj;
+               marked.resize(N);
+               for (int i = 0; i < N; ++i)
+                       marked[i] = false;
+
+               // pair adjacent nodes into new(parent) node
+               for (int i = 0; i < N; ++i)
+               {
+                       if (marked[i])
+                               continue;
+                       bool merged = false;
+                       for (int j = 0; j < adj[i].size(); ++j)
+                       {
+                               int n = adj[i][j];
+                               if (!marked[adj[i][j]])
+                               {
+                                       btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
+                                       node->parent = NULL;
+                                       node->childs[0] = leafNodes[i];
+                                       node->childs[1] = leafNodes[n];
+                                       leafNodes[i]->parent = node;
+                                       leafNodes[n]->parent = node;
+                                       newLeafNodes.push_back(node);
+                                       childIds.push_back(std::make_pair(i, n));
+                                       merged = true;
+                                       marked[n] = true;
+                                       break;
+                               }
+                       }
+                       if (!merged)
+                       {
+                               newLeafNodes.push_back(leafNodes[i]);
+                               childIds.push_back(std::make_pair(i, -1));
+                       }
+                       marked[i] = true;
+               }
+               // update adjacency matrix
+               newAdj.resize(newLeafNodes.size());
+               for (int i = 0; i < newLeafNodes.size(); ++i)
+               {
+                       for (int j = i + 1; j < newLeafNodes.size(); ++j)
+                       {
+                               bool neighbor = false;
+                               const btAlignedObjectArray<int>& leftChildNeighbors = adj[childIds[i].first];
+                               for (int k = 0; k < leftChildNeighbors.size(); ++k)
+                               {
+                                       if (leftChildNeighbors[k] == childIds[j].first || leftChildNeighbors[k] == childIds[j].second)
+                                       {
+                                               neighbor = true;
+                                               break;
+                                       }
+                               }
+                               if (!neighbor && childIds[i].second != -1)
+                               {
+                                       const btAlignedObjectArray<int>& rightChildNeighbors = adj[childIds[i].second];
+                                       for (int k = 0; k < rightChildNeighbors.size(); ++k)
+                                       {
+                                               if (rightChildNeighbors[k] == childIds[j].first || rightChildNeighbors[k] == childIds[j].second)
+                                               {
+                                                       neighbor = true;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if (neighbor)
+                               {
+                                       newAdj[i].push_back(j);
+                                       newAdj[j].push_back(i);
+                               }
+                       }
+               }
+               leafNodes = newLeafNodes;
+               //this assignment leaks memory, the assignment doesn't do a deep copy, for now a manual copy
+               //adj = newAdj;
+               adj.clear();
+               adj.resize(newAdj.size());
+               for (int i = 0; i < newAdj.size(); i++)
+               {
+                       for (int j = 0; j < newAdj[i].size(); j++)
+                       {
+                               adj[i].push_back(newAdj[i][j]);
+                       }
+               }
+               N = leafNodes.size();
+       }
+       return leafNodes[0];
+}
+
+//
+btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
+       : m_softBodySolver(0), m_worldInfo(worldInfo)
+{
+       /* Init         */
+       initDefaults();
+
+       /* Default material     */
+       Material* pm = appendMaterial();
+       pm->m_kLST = 1;
+       pm->m_kAST = 1;
+       pm->m_kVST = 1;
+       pm->m_flags = fMaterial::Default;
+
+       /* Nodes                        */
+       const btScalar margin = getCollisionShape()->getMargin();
+       m_nodes.resize(node_count);
+       m_X.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;
+               m_X[i] = n.m_x;
+       }
+       updateBounds();
+       setCollisionQuadrature(3);
+       m_fdbvnt = 0;
+}
+
+btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
+       : m_worldInfo(worldInfo)
+{
+       initDefaults();
+}
+
+void btSoftBody::initDefaults()
+{
+       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.drag = 0;
+       m_cfg.m_maxStress = 0;
+       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);
+
+       /* Collision shape      */
+       ///for now, create a collision shape internally
+       m_collisionShape = new btSoftBodyCollisionShape(this);
+       m_collisionShape->setMargin(0.25f);
+
+       m_worldTransform.setIdentity();
+
+       m_windVelocity = btVector3(0, 0, 0);
+       m_restLengthScale = btScalar(1.0);
+       m_dampingCoefficient = 1.0;
+       m_sleepingThreshold = .04;
+       m_useSelfCollision = false;
+       m_collisionFlags = 0;
+       m_softSoftCollision = false;
+       m_maxSpeedSquared = 0;
+       m_repulsionStiffness = 0.5;
+       m_gravityFactor = 1;
+       m_cacheBarycenter = false;
+       m_fdbvnt = 0;
+
+       // reduced flag
+       m_reducedModel = false;
+}
+
+//
+btSoftBody::~btSoftBody()
+{
+       //for now, delete the internal shape
+       delete m_collisionShape;
+       int i;
+
+       releaseClusters();
+       for (i = 0; i < m_materials.size(); ++i)
+               btAlignedFree(m_materials[i]);
+       for (i = 0; i < m_joints.size(); ++i)
+               btAlignedFree(m_joints[i]);
+       if (m_fdbvnt)
+               delete m_fdbvnt;
+}
+
+//
+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)
+{
+       if (node0 == node1)
+               return;
+       if (node1 == node2)
+               return;
+       if (node2 == node0)
+               return;
+
+       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::appendTetra(int model, Material* mat)
+{
+       Tetra t;
+       if (model >= 0)
+               t = m_tetras[model];
+       else
+       {
+               ZeroInitialize(t);
+               t.m_material = mat ? mat : m_materials[0];
+       }
+       m_tetras.push_back(t);
+}
+
+//
+void btSoftBody::appendTetra(int node0,
+                                                        int node1,
+                                                        int node2,
+                                                        int node3,
+                                                        Material* mat)
+{
+       appendTetra(-1, mat);
+       Tetra& t = m_tetras[m_tetras.size() - 1];
+       t.m_n[0] = &m_nodes[node0];
+       t.m_n[1] = &m_nodes[node1];
+       t.m_n[2] = &m_nodes[node2];
+       t.m_n[3] = &m_nodes[node3];
+       t.m_rv = VolumeOf(t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x);
+       m_bUpdateRtCst = true;
+}
+
+//
+
+void btSoftBody::appendAnchor(int node, btRigidBody* body, bool disableCollisionBetweenLinkedBodies, btScalar influence)
+{
+       btVector3 local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
+       appendAnchor(node, body, local, disableCollisionBetweenLinkedBodies, influence);
+}
+
+//
+void btSoftBody::appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies, btScalar influence)
+{
+       if (disableCollisionBetweenLinkedBodies)
+       {
+               if (m_collisionDisabledObjects.findLinearSearch(body) == m_collisionDisabledObjects.size())
+               {
+                       m_collisionDisabledObjects.push_back(body);
+               }
+       }
+
+       Anchor a;
+       a.m_node = &m_nodes[node];
+       a.m_body = body;
+       a.m_local = localPivot;
+       a.m_node->m_battach = 1;
+       a.m_influence = influence;
+       m_anchors.push_back(a);
+}
+
+//
+void btSoftBody::appendDeformableAnchor(int node, btRigidBody* body)
+{
+       DeformableNodeRigidAnchor c;
+       btSoftBody::Node& n = m_nodes[node];
+       const btScalar ima = n.m_im;
+       const btScalar imb = body->getInvMass();
+       btVector3 nrm;
+       const btCollisionShape* shp = body->getCollisionShape();
+       const btTransform& wtr = body->getWorldTransform();
+       btScalar dst =
+               m_worldInfo->m_sparsesdf.Evaluate(
+                       wtr.invXform(m_nodes[node].m_x),
+                       shp,
+                       nrm,
+                       0);
+
+       c.m_cti.m_colObj = body;
+       c.m_cti.m_normal = wtr.getBasis() * nrm;
+       c.m_cti.m_offset = dst;
+       c.m_node = &m_nodes[node];
+       const btScalar fc = m_cfg.kDF * body->getFriction();
+       c.m_c2 = ima;
+       c.m_c3 = fc;
+       c.m_c4 = body->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
+       static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+       const btMatrix3x3& iwi = body->getInvInertiaTensorWorld();
+       const btVector3 ra = n.m_x - wtr.getOrigin();
+
+       c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
+       c.m_c1 = ra;
+       c.m_local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
+       c.m_node->m_battach = 1;
+       m_deformableAnchors.push_back(c);
+}
+
+void btSoftBody::removeAnchor(int node)
+{
+       const btSoftBody::Node& n = m_nodes[node];
+       for (int i = 0; i < m_deformableAnchors.size();)
+       {
+               const DeformableNodeRigidAnchor& c = m_deformableAnchors[i];
+               if (c.m_node == &n)
+               {
+                       m_deformableAnchors.removeAtIndex(i);
+               }
+               else
+               {
+                       i++;
+               }
+       }
+}
+
+//
+void btSoftBody::appendDeformableAnchor(int node, btMultiBodyLinkCollider* link)
+{
+       DeformableNodeRigidAnchor c;
+       btSoftBody::Node& n = m_nodes[node];
+       const btScalar ima = n.m_im;
+       btVector3 nrm;
+       const btCollisionShape* shp = link->getCollisionShape();
+       const btTransform& wtr = link->getWorldTransform();
+       btScalar dst =
+               m_worldInfo->m_sparsesdf.Evaluate(
+                       wtr.invXform(m_nodes[node].m_x),
+                       shp,
+                       nrm,
+                       0);
+       c.m_cti.m_colObj = link;
+       c.m_cti.m_normal = wtr.getBasis() * nrm;
+       c.m_cti.m_offset = dst;
+       c.m_node = &m_nodes[node];
+       const btScalar fc = m_cfg.kDF * link->getFriction();
+       c.m_c2 = ima;
+       c.m_c3 = fc;
+       c.m_c4 = link->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
+       btVector3 normal = c.m_cti.m_normal;
+       btVector3 t1 = generateUnitOrthogonalVector(normal);
+       btVector3 t2 = btCross(normal, t1);
+       btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+       findJacobian(link, jacobianData_normal, c.m_node->m_x, normal);
+       findJacobian(link, jacobianData_t1, c.m_node->m_x, t1);
+       findJacobian(link, jacobianData_t2, c.m_node->m_x, t2);
+
+       btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+       btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+       btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+       btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+       btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+       btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+       btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+                                       t1.getX(), t1.getY(), t1.getZ(),
+                                       t2.getX(), t2.getY(), t2.getZ());  // world frame to local frame
+       const int ndof = link->m_multiBody->getNumDofs() + 6;
+       btMatrix3x3 local_impulse_matrix = (Diagonal(n.m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+       c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+       c.jacobianData_normal = jacobianData_normal;
+       c.jacobianData_t1 = jacobianData_t1;
+       c.jacobianData_t2 = jacobianData_t2;
+       c.t1 = t1;
+       c.t2 = t2;
+       const btVector3 ra = n.m_x - wtr.getOrigin();
+       c.m_c1 = ra;
+       c.m_local = link->getWorldTransform().inverse() * m_nodes[node].m_x;
+       c.m_node->m_battach = 1;
+       m_deformableAnchors.push_back(c);
+}
+//
+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::addAeroForceToNode(const btVector3& windVelocity, int nodeIndex)
+{
+       btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size());
+
+       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_aero = as_lift || as_drag;
+       const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
+
+       Node& n = m_nodes[nodeIndex];
+
+       if (n.m_im > 0)
+       {
+               btSoftBody::sMedium medium;
+
+               EvaluateMedium(m_worldInfo, n.m_x, medium);
+               medium.m_velocity = windVelocity;
+               medium.m_density = m_worldInfo->air_density;
+
+               /* Aerodynamics                 */
+               if (as_vaero)
+               {
+                       const btVector3 rel_v = n.m_v - medium.m_velocity;
+                       const btScalar rel_v_len = rel_v.length();
+                       const btScalar rel_v2 = rel_v.length2();
+
+                       if (rel_v2 > SIMD_EPSILON)
+                       {
+                               const btVector3 rel_v_nrm = rel_v.normalized();
+                               btVector3 nrm = n.m_n;
+
+                               if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag)
+                               {
+                                       nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
+                                       btVector3 fDrag(0, 0, 0);
+                                       btVector3 fLift(0, 0, 0);
+
+                                       btScalar n_dot_v = nrm.dot(rel_v_nrm);
+                                       btScalar tri_area = 0.5f * n.m_area;
+
+                                       fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
+
+                                       // Check angle of attack
+                                       // cos(10º) = 0.98480
+                                       if (0 < n_dot_v && n_dot_v < 0.98480f)
+                                               fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
+
+                                       // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
+                                       btVector3 del_v_by_fDrag = fDrag * n.m_im * m_sst.sdt;
+                                       btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
+                                       btScalar v_len2 = n.m_v.length2();
+
+                                       if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
+                                       {
+                                               btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
+                                               btScalar v_len = n.m_v.length();
+                                               fDrag *= btScalar(0.8) * (v_len / del_v_by_fDrag_len);
+                                       }
+
+                                       n.m_f += fDrag;
+                                       n.m_f += fLift;
+                               }
+                               else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
+                               {
+                                       if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
+                                               nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
+
+                                       const btScalar dvn = btDot(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);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void btSoftBody::addAeroForceToFace(const btVector3& windVelocity, int faceIndex)
+{
+       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_aero = as_lift || as_drag;
+       const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
+
+       if (as_faero)
+       {
+               btSoftBody::Face& f = m_faces[faceIndex];
+
+               btSoftBody::sMedium medium;
+
+               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);
+               medium.m_velocity = windVelocity;
+               medium.m_density = m_worldInfo->air_density;
+               const btVector3 rel_v = v - medium.m_velocity;
+               const btScalar rel_v_len = rel_v.length();
+               const btScalar rel_v2 = rel_v.length2();
+
+               if (rel_v2 > SIMD_EPSILON)
+               {
+                       const btVector3 rel_v_nrm = rel_v.normalized();
+                       btVector3 nrm = f.m_normal;
+
+                       if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag)
+                       {
+                               nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
+
+                               btVector3 fDrag(0, 0, 0);
+                               btVector3 fLift(0, 0, 0);
+
+                               btScalar n_dot_v = nrm.dot(rel_v_nrm);
+                               btScalar tri_area = 0.5f * f.m_ra;
+
+                               fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
+
+                               // Check angle of attack
+                               // cos(10º) = 0.98480
+                               if (0 < n_dot_v && n_dot_v < 0.98480f)
+                                       fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
+
+                               fDrag /= 3;
+                               fLift /= 3;
+
+                               for (int j = 0; j < 3; ++j)
+                               {
+                                       if (f.m_n[j]->m_im > 0)
+                                       {
+                                               // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
+                                               btVector3 del_v_by_fDrag = fDrag * f.m_n[j]->m_im * m_sst.sdt;
+                                               btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
+                                               btScalar v_len2 = f.m_n[j]->m_v.length2();
+
+                                               if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
+                                               {
+                                                       btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
+                                                       btScalar v_len = f.m_n[j]->m_v.length();
+                                                       fDrag *= btScalar(0.8) * (v_len / del_v_by_fDrag_len);
+                                               }
+
+                                               f.m_n[j]->m_f += fDrag;
+                                               f.m_n[j]->m_f += fLift;
+                                       }
+                               }
+                       }
+                       else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
+                       {
+                               if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
+                                       nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
+
+                               const btScalar dvn = btDot(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::addVelocity(const btVector3& velocity)
+{
+       for (int i = 0, ni = m_nodes.size(); i < ni; ++i) addVelocity(velocity, i);
+}
+
+/* Set velocity for the entire body                                                                            */
+void btSoftBody::setVelocity(const btVector3& velocity)
+{
+       for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
+       {
+               Node& n = m_nodes[i];
+               if (n.m_im > 0)
+               {
+                       n.m_v = velocity;
+                       n.m_vn = velocity;
+               }
+       }
+}
+
+//
+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::setVolumeMass(btScalar mass)
+{
+       btAlignedObjectArray<btScalar> ranks;
+       ranks.resize(m_nodes.size(), 0);
+       int i;
+
+       for (i = 0; i < m_nodes.size(); ++i)
+       {
+               m_nodes[i].m_im = 0;
+       }
+       for (i = 0; i < m_tetras.size(); ++i)
+       {
+               const Tetra& t = m_tetras[i];
+               for (int j = 0; j < 4; ++j)
+               {
+                       t.m_n[j]->m_im += btFabs(t.m_rv);
+                       ranks[int(t.m_n[j] - &m_nodes[0])] += 1;
+               }
+       }
+       for (i = 0; i < m_nodes.size(); ++i)
+       {
+               if (m_nodes[i].m_im > 0)
+               {
+                       m_nodes[i].m_im = ranks[i] / m_nodes[i].m_im;
+               }
+       }
+       setTotalMass(mass, false);
+}
+
+//
+void btSoftBody::setVolumeDensity(btScalar density)
+{
+       btScalar volume = 0;
+       for (int i = 0; i < m_tetras.size(); ++i)
+       {
+               const Tetra& t = m_tetras[i];
+               for (int j = 0; j < 4; ++j)
+               {
+                       volume += btFabs(t.m_rv);
+               }
+       }
+       setVolumeMass(volume * density / 6);
+}
+
+//
+btVector3 btSoftBody::getLinearVelocity()
+{
+       btVector3 total_momentum = btVector3(0, 0, 0);
+       for (int i = 0; i < m_nodes.size(); ++i)
+       {
+               btScalar mass = m_nodes[i].m_im == 0 ? 0 : 1.0 / m_nodes[i].m_im;
+               total_momentum += mass * m_nodes[i].m_v;
+       }
+       btScalar total_mass = getTotalMass();
+       return total_mass == 0 ? total_momentum : total_momentum / total_mass;
+}
+
+//
+void btSoftBody::setLinearVelocity(const btVector3& linVel)
+{
+       btVector3 old_vel = getLinearVelocity();
+       btVector3 diff = linVel - old_vel;
+       for (int i = 0; i < m_nodes.size(); ++i)
+               m_nodes[i].m_v += diff;
+}
+
+//
+void btSoftBody::setAngularVelocity(const btVector3& angVel)
+{
+       btVector3 old_vel = getLinearVelocity();
+       btVector3 com = getCenterOfMass();
+       for (int i = 0; i < m_nodes.size(); ++i)
+       {
+               m_nodes[i].m_v = angVel.cross(m_nodes[i].m_x - com) + old_vel;
+       }
+}
+
+//
+btTransform btSoftBody::getRigidTransform()
+{
+       btVector3 t = getCenterOfMass();
+       btMatrix3x3 S;
+       S.setZero();
+       // Get rotation that minimizes L2 difference: \sum_i || RX_i + t - x_i ||
+       // It's important to make sure that S has the correct signs.
+       // SVD is only unique up to the ordering of singular values.
+       // SVD will manipulate U and V to ensure the ordering of singular values. If all three singular
+       // vaues are negative, SVD will permute colums of U to make two of them positive.
+       for (int i = 0; i < m_nodes.size(); ++i)
+       {
+               S -= OuterProduct(m_X[i], t - m_nodes[i].m_x);
+       }
+       btVector3 sigma;
+       btMatrix3x3 U, V;
+       singularValueDecomposition(S, U, sigma, V);
+       btMatrix3x3 R = V * U.transpose();
+       btTransform trs;
+       trs.setIdentity();
+       trs.setOrigin(t);
+       trs.setBasis(R);
+       return trs;
+}
+
+//
+void btSoftBody::transformTo(const btTransform& trs)
+{
+       // get the current best rigid fit
+       btTransform current_transform = getRigidTransform();
+       // apply transform in material space
+       btTransform new_transform = trs * current_transform.inverse();
+       transform(new_transform);
+}
+
+//
+void btSoftBody::transform(const btTransform& trs)
+{
+       const btScalar margin = getCollisionShape()->getMargin();
+       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+       vol;
+
+       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;
+               vol = btDbvtVolume::FromCR(n.m_x, margin);
+
+               m_ndbvt.update(n.m_leaf, vol);
+       }
+       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();
+       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+       vol;
+
+       for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
+       {
+               Node& n = m_nodes[i];
+               n.m_x *= scl;
+               n.m_q *= scl;
+               vol = btDbvtVolume::FromCR(n.m_x, margin);
+               m_ndbvt.update(n.m_leaf, vol);
+       }
+       updateNormals();
+       updateBounds();
+       updateConstants();
+       initializeDmInverse();
+}
+
+//
+btScalar btSoftBody::getRestLengthScale()
+{
+       return m_restLengthScale;
+}
+
+//
+void btSoftBody::setRestLengthScale(btScalar restLengthScale)
+{
+       for (int i = 0, ni = m_links.size(); i < ni; ++i)
+       {
+               Link& l = m_links[i];
+               l.m_rl = l.m_rl / m_restLengthScale * restLengthScale;
+               l.m_c1 = l.m_rl * l.m_rl;
+       }
+       m_restLengthScale = restLengthScale;
+
+       if (getActivationState() == ISLAND_SLEEPING)
+               activate();
+}
+
+//
+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();
+}
+
+void btSoftBody::resetLinkRestLengths()
+{
+       for (int i = 0, ni = m_links.size(); i < ni; ++i)
+       {
+               Link& l = m_links[i];
+               l.m_rl = (l.m_n[0]->m_x - l.m_n[1]->m_x).length();
+               l.m_c1 = l.m_rl * l.m_rl;
+       }
+}
+
+//
+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 += btDot(f.m_n[0]->m_x - org, btCross(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 + btCross(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 * btCross(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 * btCross(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++;
+}
+
+struct NodeLinks
+{
+       btAlignedObjectArray<int> m_links;
+};
+
+//
+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;
+               }
+
+               //special optimized case for distance == 2
+               if (distance == 2)
+               {
+                       btAlignedObjectArray<NodeLinks> nodeLinks;
+
+                       /* Build node links */
+                       nodeLinks.resize(m_nodes.size());
+
+                       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]);
+                               if (nodeLinks[ia].m_links.findLinearSearch(ib) == nodeLinks[ia].m_links.size())
+                                       nodeLinks[ia].m_links.push_back(ib);
+
+                               if (nodeLinks[ib].m_links.findLinearSearch(ia) == nodeLinks[ib].m_links.size())
+                                       nodeLinks[ib].m_links.push_back(ia);
+                       }
+                       for (int ii = 0; ii < nodeLinks.size(); ii++)
+                       {
+                               int i = ii;
+
+                               for (int jj = 0; jj < nodeLinks[ii].m_links.size(); jj++)
+                               {
+                                       int k = nodeLinks[ii].m_links[jj];
+                                       for (int kk = 0; kk < nodeLinks[k].m_links.size(); kk++)
+                                       {
+                                               int j = nodeLinks[k].m_links[kk];
+                                               if (i != j)
+                                               {
+                                                       const unsigned sum = adj[IDX(i, k)] + adj[IDX(k, j)];
+                                                       btAssert(sum == 2);
+                                                       if (adj[IDX(i, j)] > sum)
+                                                       {
+                                                               adj[IDX(i, j)] = adj[IDX(j, i)] = sum;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               else
+               {
+                       ///generic Floyd's algorithm
+                       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
+}
+
+void btSoftBody::updateState(const btAlignedObjectArray<btVector3>& q, const btAlignedObjectArray<btVector3>& v)
+{
+       int node_count = m_nodes.size();
+       btAssert(node_count == q.size());
+       btAssert(node_count == v.size());
+       for (int i = 0; i < node_count; i++)
+       {
+               Node& n = m_nodes[i];
+               n.m_x = q[i];
+               n.m_q = q[i];
+               n.m_v = v[i];
+               n.m_vn = v[i];
+       }
+}
+
+//
+void btSoftBody::releaseCluster(int index)
+{
+       Cluster* c = m_clusters[index];
+       if (c->m_leaf) m_cdbvt.remove(c->m_leaf);
+       c->~Cluster();
+       btAlignedFree(c);
+       m_clusters.remove(c);
+}
+
+//
+void btSoftBody::releaseClusters()
+{
+       while (m_clusters.size() > 0) releaseCluster(0);
+}
+
+//
+int btSoftBody::generateClusters(int k, int maxiterations)
+{
+       int i;
+       releaseClusters();
+       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)
+                       {
+                               releaseCluster(i--);
+                       }
+               }
+       }
+       else
+       {
+               //create a cluster for each tetrahedron (if tetrahedra exist) or each face
+               if (m_tetras.size())
+               {
+                       m_clusters.resize(m_tetras.size());
+                       for (i = 0; i < m_clusters.size(); ++i)
+                       {
+                               m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
+                               m_clusters[i]->m_collide = true;
+                       }
+                       for (i = 0; i < m_tetras.size(); i++)
+                       {
+                               for (int j = 0; j < 4; j++)
+                               {
+                                       m_clusters[i]->m_nodes.push_back(m_tetras[i].m_n[j]);
+                               }
+                       }
+               }
+               else
+               {
+                       m_clusters.resize(m_faces.size());
+                       for (i = 0; i < m_clusters.size(); ++i)
+                       {
+                               m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
+                               m_clusters[i]->m_collide = true;
+                       }
+
+                       for (i = 0; i < m_faces.size(); ++i)
+                       {
+                               for (int j = 0; j < 3; ++j)
+                               {
+                                       m_clusters[i]->m_nodes.push_back(m_faces[i].m_n[j]);
+                               }
+                       }
+               }
+       }
+
+       if (m_clusters.size())
+       {
+               initializeClusters();
+               updateClusters();
+
+               //for self-collision
+               m_clusterConnectivity.resize(m_clusters.size() * m_clusters.size());
+               {
+                       for (int c0 = 0; c0 < m_clusters.size(); c0++)
+                       {
+                               m_clusters[c0]->m_clusterIndex = c0;
+                               for (int c1 = 0; c1 < m_clusters.size(); c1++)
+                               {
+                                       bool connected = false;
+                                       Cluster* cla = m_clusters[c0];
+                                       Cluster* clb = m_clusters[c1];
+                                       for (int i = 0; !connected && i < cla->m_nodes.size(); i++)
+                                       {
+                                               for (int j = 0; j < clb->m_nodes.size(); j++)
+                                               {
+                                                       if (cla->m_nodes[i] == clb->m_nodes[j])
+                                                       {
+                                                               connected = true;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       m_clusterConnectivity[c0 + c1 * m_clusters.size()] = connected;
+                               }
+                       }
+               }
+       }
+
+       return (m_clusters.size());
+}
+
+//
+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.5f;
+                                                       m = 1 / a.m_im;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (b.m_im > 0)
+                                               {
+                                                       b.m_im /= 0.5f;
+                                                       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.5f;
+                                       m_nodes[i].m_im /= 0.5f;
+                               }
+                               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::rayTest(const btVector3& rayFrom,
+                                                const btVector3& rayTo,
+                                                sRayCast& results)
+{
+       if (m_faces.size() && m_fdbvt.empty())
+               initializeFaceTree();
+
+       results.body = this;
+       results.fraction = 1.f;
+       results.feature = eFeature::None;
+       results.index = -1;
+
+       return (rayTest(rayFrom, rayTo, results.fraction, results.feature, results.index, false) != 0);
+}
+
+bool btSoftBody::rayFaceTest(const btVector3& rayFrom,
+                                                        const btVector3& rayTo,
+                                                        sRayCast& results)
+{
+       if (m_faces.size() == 0)
+               return false;
+       else
+       {
+               if (m_fdbvt.empty())
+                       initializeFaceTree();
+       }
+
+       results.body = this;
+       results.fraction = 1.f;
+       results.index = -1;
+
+       return (rayFaceTest(rayFrom, rayTo, results.fraction, results.index) != 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;
+               btVector3 deltaV = n.m_f * n.m_im * m_sst.sdt;
+               {
+                       btScalar maxDisplacement = m_worldInfo->m_maxDisplacement;
+                       btScalar clampDeltaV = maxDisplacement / m_sst.sdt;
+                       for (int c = 0; c < 3; c++)
+                       {
+                               if (deltaV[c] > clampDeltaV)
+                               {
+                                       deltaV[c] = clampDeltaV;
+                               }
+                               if (deltaV[c] < -clampDeltaV)
+                               {
+                                       deltaV[c] = -clampDeltaV;
+                               }
+                       }
+               }
+               n.m_v += deltaV;
+               n.m_x += n.m_v * m_sst.sdt;
+               n.m_f = btVector3(0, 0, 0);
+       }
+       /* Clusters                */
+       updateClusters();
+       /* Bounds                */
+       updateBounds();
+       /* Nodes                */
+       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+       vol;
+       for (i = 0, ni = m_nodes.size(); i < ni; ++i)
+       {
+               Node& n = m_nodes[i];
+               vol = btDbvtVolume::FromCR(n.m_x, m_sst.radmrg);
+               m_ndbvt.update(n.m_leaf,
+                                          vol,
+                                          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;
+                       vol = VolumeOf(f, m_sst.radmrg);
+                       m_fdbvt.update(f.m_leaf,
+                                                  vol,
+                                                  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::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom, const btVector3& rayTo, btScalar mxt)
+{
+       m_rayFrom = rayFrom;
+       m_rayNormalizedDirection = (rayTo - rayFrom);
+       m_rayTo = rayTo;
+       m_mint = mxt;
+       m_face = 0;
+       m_tests = 0;
+}
+
+//
+void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
+{
+       btSoftBody::Face& f = *(btSoftBody::Face*)leaf->data;
+       const btScalar t = rayFromToTriangle(m_rayFrom, m_rayTo, m_rayNormalizedDirection,
+                                                                                f.m_n[0]->m_x,
+                                                                                f.m_n[1]->m_x,
+                                                                                f.m_n[2]->m_x,
+                                                                                m_mint);
+       if ((t > 0) && (t < m_mint))
+       {
+               m_mint = t;
+               m_face = &f;
+       }
+       ++m_tests;
+}
+
+//
+btScalar btSoftBody::RayFromToCaster::rayFromToTriangle(const btVector3& rayFrom,
+                                                                                                               const btVector3& rayTo,
+                                                                                                               const btVector3& rayNormalizedDirection,
+                                                                                                               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 = btCross(b - a, c - a);
+       const btScalar d = btDot(a, n);
+       const btScalar den = btDot(rayNormalizedDirection, n);
+       if (!btFuzzyZero(den))
+       {
+               const btScalar num = btDot(rayFrom, n) - d;
+               const btScalar t = -num / den;
+               if ((t > teps) && (t < maxt))
+               {
+                       const btVector3 hit = rayFrom + rayNormalizedDirection * t;
+                       if ((btDot(n, btCross(a - hit, b - hit)) > ceps) &&
+                               (btDot(n, btCross(b - hit, c - hit)) > ceps) &&
+                               (btDot(n, btCross(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.size() ? &m_nodes[0] : 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.size() ? &m_nodes[0] : 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::rayTest(const btVector3& rayFrom, const btVector3& rayTo,
+                                               btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const
+{
+       int cnt = 0;
+       btVector3 dir = rayTo - rayFrom;
+
+       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 = RayFromToCaster::rayFromToTriangle(rayFrom, rayTo, 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   */
+               RayFromToCaster collider(rayFrom, rayTo, mint);
+
+               btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
+               if (collider.m_face)
+               {
+                       mint = collider.m_mint;
+                       feature = btSoftBody::eFeature::Face;
+                       index = (int)(collider.m_face - &m_faces[0]);
+                       cnt = 1;
+               }
+       }
+
+       for (int i = 0; i < m_tetras.size(); i++)
+       {
+               const btSoftBody::Tetra& tet = m_tetras[i];
+               int tetfaces[4][3] = {{0, 1, 2}, {0, 1, 3}, {1, 2, 3}, {0, 2, 3}};
+               for (int f = 0; f < 4; f++)
+               {
+                       int index0 = tetfaces[f][0];
+                       int index1 = tetfaces[f][1];
+                       int index2 = tetfaces[f][2];
+                       btVector3 v0 = tet.m_n[index0]->m_x;
+                       btVector3 v1 = tet.m_n[index1]->m_x;
+                       btVector3 v2 = tet.m_n[index2]->m_x;
+
+                       const btScalar t = RayFromToCaster::rayFromToTriangle(rayFrom, rayTo, dir,
+                                                                                                                                 v0, v1, v2,
+                                                                                                                                 mint);
+                       if (t > 0)
+                       {
+                               ++cnt;
+                               if (!bcountonly)
+                               {
+                                       feature = btSoftBody::eFeature::Tetra;
+                                       index = i;
+                                       mint = t;
+                               }
+                       }
+               }
+       }
+       return (cnt);
+}
+
+int btSoftBody::rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo,
+                                                       btScalar& mint, int& index) const
+{
+       int cnt = 0;
+       { /* Use dbvt   */
+               RayFromToCaster collider(rayFrom, rayTo, mint);
+
+               btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
+               if (collider.m_face)
+               {
+                       mint = collider.m_mint;
+                       index = (int)(collider.m_face - &m_faces[0]);
+                       cnt = 1;
+               }
+       }
+       return (cnt);
+}
+
+//
+static inline btDbvntNode* copyToDbvnt(const btDbvtNode* n)
+{
+       if (n == 0)
+               return 0;
+       btDbvntNode* root = new btDbvntNode(n);
+       if (n->isinternal())
+       {
+               btDbvntNode* c0 = copyToDbvnt(n->childs[0]);
+               root->childs[0] = c0;
+               btDbvntNode* c1 = copyToDbvnt(n->childs[1]);
+               root->childs[1] = c1;
+       }
+       return root;
+}
+
+static inline void calculateNormalCone(btDbvntNode* root)
+{
+       if (!root)
+               return;
+       if (root->isleaf())
+       {
+               const btSoftBody::Face* face = (btSoftBody::Face*)root->data;
+               root->normal = face->m_normal;
+               root->angle = 0;
+       }
+       else
+       {
+               btVector3 n0(0, 0, 0), n1(0, 0, 0);
+               btScalar a0 = 0, a1 = 0;
+               if (root->childs[0])
+               {
+                       calculateNormalCone(root->childs[0]);
+                       n0 = root->childs[0]->normal;
+                       a0 = root->childs[0]->angle;
+               }
+               if (root->childs[1])
+               {
+                       calculateNormalCone(root->childs[1]);
+                       n1 = root->childs[1]->normal;
+                       a1 = root->childs[1]->angle;
+               }
+               root->normal = (n0 + n1).safeNormalize();
+               root->angle = btMax(a0, a1) + btAngle(n0, n1) * 0.5;
+       }
+}
+
+void btSoftBody::initializeFaceTree()
+{
+       BT_PROFILE("btSoftBody::initializeFaceTree");
+       m_fdbvt.clear();
+       // create leaf nodes;
+       btAlignedObjectArray<btDbvtNode*> leafNodes;
+       leafNodes.resize(m_faces.size());
+       for (int i = 0; i < m_faces.size(); ++i)
+       {
+               Face& f = m_faces[i];
+               ATTRIBUTE_ALIGNED16(btDbvtVolume)
+               vol = VolumeOf(f, 0);
+               btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
+               node->parent = NULL;
+               node->data = &f;
+               node->childs[1] = 0;
+               node->volume = vol;
+               leafNodes[i] = node;
+               f.m_leaf = node;
+       }
+       btAlignedObjectArray<btAlignedObjectArray<int> > adj;
+       adj.resize(m_faces.size());
+       // construct the adjacency list for triangles
+       for (int i = 0; i < adj.size(); ++i)
+       {
+               for (int j = i + 1; j < adj.size(); ++j)
+               {
+                       int dup = 0;
+                       for (int k = 0; k < 3; ++k)
+                       {
+                               for (int l = 0; l < 3; ++l)
+                               {
+                                       if (m_faces[i].m_n[k] == m_faces[j].m_n[l])
+                                       {
+                                               ++dup;
+                                               break;
+                                       }
+                               }
+                               if (dup == 2)
+                               {
+                                       adj[i].push_back(j);
+                                       adj[j].push_back(i);
+                               }
+                       }
+               }
+       }
+       m_fdbvt.m_root = buildTreeBottomUp(leafNodes, adj);
+       if (m_fdbvnt)
+               delete m_fdbvnt;
+       m_fdbvnt = copyToDbvnt(m_fdbvt.m_root);
+       updateFaceTree(false, false);
+       rebuildNodeTree();
+}
+
+//
+void btSoftBody::rebuildNodeTree()
+{
+       m_ndbvt.clear();
+       btAlignedObjectArray<btDbvtNode*> leafNodes;
+       leafNodes.resize(m_nodes.size());
+       for (int i = 0; i < m_nodes.size(); ++i)
+       {
+               Node& n = m_nodes[i];
+               ATTRIBUTE_ALIGNED16(btDbvtVolume)
+               vol = btDbvtVolume::FromCR(n.m_x, 0);
+               btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
+               node->parent = NULL;
+               node->data = &n;
+               node->childs[1] = 0;
+               node->volume = vol;
+               leafNodes[i] = node;
+               n.m_leaf = node;
+       }
+       btAlignedObjectArray<btAlignedObjectArray<int> > adj;
+       adj.resize(m_nodes.size());
+       btAlignedObjectArray<int> old_id;
+       old_id.resize(m_nodes.size());
+       for (int i = 0; i < m_nodes.size(); ++i)
+               old_id[i] = m_nodes[i].index;
+       for (int i = 0; i < m_nodes.size(); ++i)
+               m_nodes[i].index = i;
+       for (int i = 0; i < m_links.size(); ++i)
+       {
+               Link& l = m_links[i];
+               adj[l.m_n[0]->index].push_back(l.m_n[1]->index);
+               adj[l.m_n[1]->index].push_back(l.m_n[0]->index);
+       }
+       m_ndbvt.m_root = buildTreeBottomUp(leafNodes, adj);
+       for (int i = 0; i < m_nodes.size(); ++i)
+               m_nodes[i].index = old_id[i];
+}
+
+//
+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(const btCollisionObjectWrapper* colObjWrap,
+                                                         const btVector3& x,
+                                                         btScalar margin,
+                                                         btSoftBody::sCti& cti) const
+{
+       btVector3 nrm;
+       const btCollisionShape* shp = colObjWrap->getCollisionShape();
+       //    const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
+       //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
+       const btTransform& wtr = colObjWrap->getWorldTransform();
+       //todo: check which transform is needed here
+
+       btScalar dst =
+               m_worldInfo->m_sparsesdf.Evaluate(
+                       wtr.invXform(x),
+                       shp,
+                       nrm,
+                       margin);
+       if (dst < 0)
+       {
+               cti.m_colObj = colObjWrap->getCollisionObject();
+               cti.m_normal = wtr.getBasis() * nrm;
+               cti.m_offset = -btDot(cti.m_normal, x - cti.m_normal * dst);
+               return (true);
+       }
+       return (false);
+}
+
+//
+bool btSoftBody::checkDeformableContact(const btCollisionObjectWrapper* colObjWrap,
+                                                                               const btVector3& x,
+                                                                               btScalar margin,
+                                                                               btSoftBody::sCti& cti, bool predict) const
+{
+       btVector3 nrm;
+       const btCollisionShape* shp = colObjWrap->getCollisionShape();
+       const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
+       // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
+       // but resolve contact at x_n
+       btTransform wtr = (predict) ? (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform() * (*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
+                                                               : colObjWrap->getWorldTransform();
+       btScalar dst =
+               m_worldInfo->m_sparsesdf.Evaluate(
+                       wtr.invXform(x),
+                       shp,
+                       nrm,
+                       margin);
+
+       if (!predict)
+       {
+               cti.m_colObj = colObjWrap->getCollisionObject();
+               cti.m_normal = wtr.getBasis() * nrm;
+               cti.m_offset = dst;
+       }
+       if (dst < 0)
+               return true;
+       return (false);
+}
+
+//
+// Compute barycentric coordinates (u, v, w) for
+// point p with respect to triangle (a, b, c)
+static void getBarycentric(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, btVector3& bary)
+{
+       btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
+       btScalar d00 = v0.dot(v0);
+       btScalar d01 = v0.dot(v1);
+       btScalar d11 = v1.dot(v1);
+       btScalar d20 = v2.dot(v0);
+       btScalar d21 = v2.dot(v1);
+       btScalar denom = d00 * d11 - d01 * d01;
+       // In the case of a degenerate triangle, pick a vertex.
+       if (btFabs(denom) < SIMD_EPSILON) 
+       {
+               bary.setY(btScalar(0.0));
+               bary.setZ(btScalar(0.0));
+       } 
+       else 
+       {
+               bary.setY((d11 * d20 - d01 * d21) / denom);
+               bary.setZ((d00 * d21 - d01 * d20) / denom);
+       }
+       bary.setX(btScalar(1) - bary.getY() - bary.getZ());
+}
+
+//
+bool btSoftBody::checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap,
+                                                                                       Face& f,
+                                                                                       btVector3& contact_point,
+                                                                                       btVector3& bary,
+                                                                                       btScalar margin,
+                                                                                       btSoftBody::sCti& cti, bool predict) const
+{
+       btVector3 nrm;
+       const btCollisionShape* shp = colObjWrap->getCollisionShape();
+       const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
+       // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
+       // but resolve contact at x_n
+       btTransform wtr = (predict) ? (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform() * (*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
+                                                               : colObjWrap->getWorldTransform();
+       btScalar dst;
+       btGjkEpaSolver2::sResults results;
+
+       //      #define USE_QUADRATURE 1
+
+       // use collision quadrature point
+#ifdef USE_QUADRATURE
+       {
+               dst = SIMD_INFINITY;
+               btVector3 local_nrm;
+               for (int q = 0; q < m_quads.size(); ++q)
+               {
+                       btVector3 p;
+                       if (predict)
+                               p = BaryEval(f.m_n[0]->m_q, f.m_n[1]->m_q, f.m_n[2]->m_q, m_quads[q]);
+                       else
+                               p = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, m_quads[q]);
+                       btScalar local_dst = m_worldInfo->m_sparsesdf.Evaluate(
+                               wtr.invXform(p),
+                               shp,
+                               local_nrm,
+                               margin);
+                       if (local_dst < dst)
+                       {
+                               if (local_dst < 0 && predict)
+                                       return true;
+                               dst = local_dst;
+                               contact_point = p;
+                               bary = m_quads[q];
+                               nrm = local_nrm;
+                       }
+                       if (!predict)
+                       {
+                               cti.m_colObj = colObjWrap->getCollisionObject();
+                               cti.m_normal = wtr.getBasis() * nrm;
+                               cti.m_offset = dst;
+                       }
+               }
+               return (dst < 0);
+       }
+#endif
+
+       // collision detection using x*
+       btTransform triangle_transform;
+       triangle_transform.setIdentity();
+       triangle_transform.setOrigin(f.m_n[0]->m_q);
+       btTriangleShape triangle(btVector3(0, 0, 0), f.m_n[1]->m_q - f.m_n[0]->m_q, f.m_n[2]->m_q - f.m_n[0]->m_q);
+       btVector3 guess(0, 0, 0);
+       const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
+       btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
+       dst = results.distance - 2.0 * csh->getMargin() - margin;  // margin padding so that the distance = the actual distance between face and rigid - margin of rigid - margin of deformable
+       if (dst >= 0)
+               return false;
+
+       // Use consistent barycenter to recalculate distance.
+       if (this->m_cacheBarycenter)
+       {
+               if (f.m_pcontact[3] != 0)
+               {
+                       for (int i = 0; i < 3; ++i)
+                               bary[i] = f.m_pcontact[i];
+                       contact_point = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+                       const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
+                       btGjkEpaSolver2::SignedDistance(contact_point, margin, csh, wtr, results);
+                       cti.m_colObj = colObjWrap->getCollisionObject();
+                       dst = results.distance;
+                       cti.m_normal = results.normal;
+                       cti.m_offset = dst;
+
+                       //point-convex CD
+                       wtr = colObjWrap->getWorldTransform();
+                       btTriangleShape triangle2(btVector3(0, 0, 0), f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
+                       triangle_transform.setOrigin(f.m_n[0]->m_x);
+                       btGjkEpaSolver2::SignedDistance(&triangle2, triangle_transform, csh, wtr, guess, results);
+
+                       dst = results.distance - csh->getMargin() - margin;
+                       return true;
+               }
+       }
+
+       // Use triangle-convex CD.
+       wtr = colObjWrap->getWorldTransform();
+       btTriangleShape triangle2(btVector3(0, 0, 0), f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
+       triangle_transform.setOrigin(f.m_n[0]->m_x);
+       btGjkEpaSolver2::SignedDistance(&triangle2, triangle_transform, csh, wtr, guess, results);
+       contact_point = results.witnesses[0];
+       getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
+
+       for (int i = 0; i < 3; ++i)
+               f.m_pcontact[i] = bary[i];
+
+       dst = results.distance - csh->getMargin() - margin;
+       cti.m_colObj = colObjWrap->getCollisionObject();
+       cti.m_normal = results.normal;
+       cti.m_offset = dst;
+       return true;
+}
+
+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 = btCross(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;
+               f.m_normal.safeNormalize();
+               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_acceleratedSoftBody )
+       {
+               // If we have an accelerated softbody we need to obtain the bounds correctly
+               // For now (slightly hackily) just have a very large AABB
+               // TODO: Write get bounds kernel
+               // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could
+               // probably do a test and exchange reasonably efficiently.
+
+               m_bounds[0] = btVector3(-1000, -1000, -1000);
+               m_bounds[1] = btVector3(1000, 1000, 1000);
+
+       } else {*/
+       //    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);
+       //    }
+       if (m_nodes.size())
+       {
+               btVector3 mins = m_nodes[0].m_x;
+               btVector3 maxs = m_nodes[0].m_x;
+               for (int i = 1; i < m_nodes.size(); ++i)
+               {
+                       for (int d = 0; d < 3; ++d)
+                       {
+                               if (m_nodes[i].m_x[d] > maxs[d])
+                                       maxs[d] = m_nodes[i].m_x[d];
+                               if (m_nodes[i].m_x[d] < mins[d])
+                                       mins[d] = m_nodes[i].m_x[d];
+                       }
+               }
+               const btScalar csm = getCollisionShape()->getMargin();
+               const btVector3 mrg = btVector3(csm,
+                                                                               csm,
+                                                                               csm);
+               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::updateArea(bool averageArea)
+{
+       int i, ni;
+
+       /* Face area            */
+       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);
+       }
+
+       /* Node area            */
+
+       if (averageArea)
+       {
+               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;
+               }
+       }
+       else
+       {
+               // initialize node area as zero
+               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)
+                       {
+                               f.m_n[j]->m_area += f.m_ra;
+                       }
+               }
+
+               for (i = 0, ni = m_nodes.size(); i < ni; ++i)
+               {
+                       m_nodes[i].m_area *= 0.3333333f;
+               }
+       }
+}
+
+void btSoftBody::updateLinkConstants()
+{
+       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_c0 = (l.m_n[0]->m_im + l.m_n[1]->m_im) / m.m_kLST;
+       }
+}
+
+void btSoftBody::updateConstants()
+{
+       resetLinkRestLengths();
+       updateLinkConstants();
+       updateArea();
+}
+
+//
+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)
+               {
+                       if (c.m_nodes[j]->m_im == 0)
+                       {
+                               c.m_containsAnchor = true;
+                               c.m_masses[j] = BT_LARGE_FLOAT;
+                       }
+                       else
+                       {
+                               c.m_masses[j] = btScalar(1.) / c.m_nodes[j]->m_im;
+                       }
+                       c.m_imass += c.m_masses[j];
+               }
+               c.m_imass = btScalar(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 += btCross(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);
+                               }
+                               ATTRIBUTE_ALIGNED16(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 + btCross(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 + btCross(c.m_av, c.m_nodes[j]->m_q - c.m_com);
+                                       if (vx.length2() <= n.m_v.length2())
+                                       {
+                                               n.m_v += c.m_ndamping * (vx - n.m_v);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void btSoftBody::setSpringStiffness(btScalar k)
+{
+       for (int i = 0; i < m_links.size(); ++i)
+       {
+               m_links[i].Feature::m_material->m_kLST = k;
+       }
+       m_repulsionStiffness = k;
+}
+
+void btSoftBody::setGravityFactor(btScalar gravFactor)
+{
+       m_gravityFactor = gravFactor;
+}
+
+void btSoftBody::setCacheBarycenter(bool cacheBarycenter)
+{
+       m_cacheBarycenter = cacheBarycenter;
+}
+
+void btSoftBody::initializeDmInverse()
+{
+       btScalar unit_simplex_measure = 1. / 6.;
+
+       for (int i = 0; i < m_tetras.size(); ++i)
+       {
+               Tetra& t = m_tetras[i];
+               btVector3 c1 = t.m_n[1]->m_x - t.m_n[0]->m_x;
+               btVector3 c2 = t.m_n[2]->m_x - t.m_n[0]->m_x;
+               btVector3 c3 = t.m_n[3]->m_x - t.m_n[0]->m_x;
+               btMatrix3x3 Dm(c1.getX(), c2.getX(), c3.getX(),
+                                          c1.getY(), c2.getY(), c3.getY(),
+                                          c1.getZ(), c2.getZ(), c3.getZ());
+               t.m_element_measure = Dm.determinant() * unit_simplex_measure;
+               t.m_Dm_inverse = Dm.inverse();
+
+               // calculate the first three columns of P^{-1}
+               btVector3 a = t.m_n[0]->m_x;
+               btVector3 b = t.m_n[1]->m_x;
+               btVector3 c = t.m_n[2]->m_x;
+               btVector3 d = t.m_n[3]->m_x;
+
+               btScalar det = 1 / (a[0] * b[1] * c[2] - a[0] * b[1] * d[2] - a[0] * b[2] * c[1] + a[0] * b[2] * d[1] + a[0] * c[1] * d[2] - a[0] * c[2] * d[1] + a[1] * (-b[0] * c[2] + b[0] * d[2] + b[2] * c[0] - b[2] * d[0] - c[0] * d[2] + c[2] * d[0]) + a[2] * (b[0] * c[1] - b[0] * d[1] + b[1] * (d[0] - c[0]) + c[0] * d[1] - c[1] * d[0]) - b[0] * c[1] * d[2] + b[0] * c[2] * d[1] + b[1] * c[0] * d[2] - b[1] * c[2] * d[0] - b[2] * c[0] * d[1] + b[2] * c[1] * d[0]);
+
+               btScalar P11 = -b[2] * c[1] + d[2] * c[1] + b[1] * c[2] + b[2] * d[1] - c[2] * d[1] - b[1] * d[2];
+               btScalar P12 = b[2] * c[0] - d[2] * c[0] - b[0] * c[2] - b[2] * d[0] + c[2] * d[0] + b[0] * d[2];
+               btScalar P13 = -b[1] * c[0] + d[1] * c[0] + b[0] * c[1] + b[1] * d[0] - c[1] * d[0] - b[0] * d[1];
+               btScalar P21 = a[2] * c[1] - d[2] * c[1] - a[1] * c[2] - a[2] * d[1] + c[2] * d[1] + a[1] * d[2];
+               btScalar P22 = -a[2] * c[0] + d[2] * c[0] + a[0] * c[2] + a[2] * d[0] - c[2] * d[0] - a[0] * d[2];
+               btScalar P23 = a[1] * c[0] - d[1] * c[0] - a[0] * c[1] - a[1] * d[0] + c[1] * d[0] + a[0] * d[1];
+               btScalar P31 = -a[2] * b[1] + d[2] * b[1] + a[1] * b[2] + a[2] * d[1] - b[2] * d[1] - a[1] * d[2];
+               btScalar P32 = a[2] * b[0] - d[2] * b[0] - a[0] * b[2] - a[2] * d[0] + b[2] * d[0] + a[0] * d[2];
+               btScalar P33 = -a[1] * b[0] + d[1] * b[0] + a[0] * b[1] + a[1] * d[0] - b[1] * d[0] - a[0] * d[1];
+               btScalar P41 = a[2] * b[1] - c[2] * b[1] - a[1] * b[2] - a[2] * c[1] + b[2] * c[1] + a[1] * c[2];
+               btScalar P42 = -a[2] * b[0] + c[2] * b[0] + a[0] * b[2] + a[2] * c[0] - b[2] * c[0] - a[0] * c[2];
+               btScalar P43 = a[1] * b[0] - c[1] * b[0] - a[0] * b[1] - a[1] * c[0] + b[1] * c[0] + a[0] * c[1];
+
+               btVector4 p1(P11 * det, P21 * det, P31 * det, P41 * det);
+               btVector4 p2(P12 * det, P22 * det, P32 * det, P42 * det);
+               btVector4 p3(P13 * det, P23 * det, P33 * det, P43 * det);
+
+               t.m_P_inv[0] = p1;
+               t.m_P_inv[1] = p2;
+               t.m_P_inv[2] = p3;
+       }
+}
+
+static btScalar Dot4(const btVector4& a, const btVector4& b)
+{
+       return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+}
+
+void btSoftBody::updateDeformation()
+{
+       btQuaternion q;
+       for (int i = 0; i < m_tetras.size(); ++i)
+       {
+               btSoftBody::Tetra& t = m_tetras[i];
+               btVector3 c1 = t.m_n[1]->m_q - t.m_n[0]->m_q;
+               btVector3 c2 = t.m_n[2]->m_q - t.m_n[0]->m_q;
+               btVector3 c3 = t.m_n[3]->m_q - t.m_n[0]->m_q;
+               btMatrix3x3 Ds(c1.getX(), c2.getX(), c3.getX(),
+                                          c1.getY(), c2.getY(), c3.getY(),
+                                          c1.getZ(), c2.getZ(), c3.getZ());
+               t.m_F = Ds * t.m_Dm_inverse;
+
+               btSoftBody::TetraScratch& s = m_tetraScratches[i];
+               s.m_F = t.m_F;
+               s.m_J = t.m_F.determinant();
+               btMatrix3x3 C = t.m_F.transpose() * t.m_F;
+               s.m_trace = C[0].getX() + C[1].getY() + C[2].getZ();
+               s.m_cofF = t.m_F.adjoint().transpose();
+
+               btVector3 a = t.m_n[0]->m_q;
+               btVector3 b = t.m_n[1]->m_q;
+               btVector3 c = t.m_n[2]->m_q;
+               btVector3 d = t.m_n[3]->m_q;
+               btVector4 q1(a[0], b[0], c[0], d[0]);
+               btVector4 q2(a[1], b[1], c[1], d[1]);
+               btVector4 q3(a[2], b[2], c[2], d[2]);
+               btMatrix3x3 B(Dot4(q1, t.m_P_inv[0]), Dot4(q1, t.m_P_inv[1]), Dot4(q1, t.m_P_inv[2]),
+                                         Dot4(q2, t.m_P_inv[0]), Dot4(q2, t.m_P_inv[1]), Dot4(q2, t.m_P_inv[2]),
+                                         Dot4(q3, t.m_P_inv[0]), Dot4(q3, t.m_P_inv[1]), Dot4(q3, t.m_P_inv[2]));
+               q.setRotation(btVector3(0, 0, 1), 0);
+               B.extractRotation(q, 0.01);  // precision of the rotation is not very important for visual correctness.
+               btMatrix3x3 Q(q);
+               s.m_corotation = Q;
+       }
+}
+
+void btSoftBody::advanceDeformation()
+{
+       updateDeformation();
+       for (int i = 0; i < m_tetras.size(); ++i)
+       {
+               m_tetraScratchesTn[i] = m_tetraScratches[i];
+       }
+}
+//
+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(btCross(m_axis[1], m_axis[0]));
+       m_drift *= btMin(maxdrift, btAcos(Clamp<btScalar>(btDot(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 = btDot(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 = btDot(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;
+
+       if (m_bodies[0].m_soft == m_bodies[1].m_soft)
+       {
+               if ((impulse.m_velocity.getX() == impulse.m_velocity.getX()) && (impulse.m_velocity.getY() == impulse.m_velocity.getY()) &&
+                       (impulse.m_velocity.getZ() == impulse.m_velocity.getZ()))
+               {
+                       if (impulse.m_asVelocity)
+                       {
+                               if (impulse.m_velocity.length() < m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
+                               {
+                               }
+                               else
+                               {
+                                       m_bodies[0].applyImpulse(-impulse * m_bodies[0].m_soft->m_selfCollisionImpulseFactor, m_rpos[0]);
+                                       m_bodies[1].applyImpulse(impulse * m_bodies[0].m_soft->m_selfCollisionImpulseFactor, m_rpos[1]);
+                               }
+                       }
+               }
+       }
+       else
+       {
+               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)
+                       {
+                               /* Aerodynamics                 */
+                               addAeroForceToNode(m_windVelocity, i);
+                       }
+                       /* 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];
+
+               /* Aerodynamics                 */
+               addAeroForceToFace(m_windVelocity, i);
+       }
+}
+
+//
+void btSoftBody::setMaxStress(btScalar maxStress)
+{
+       m_cfg.m_maxStress = maxStress;
+}
+
+//
+void btSoftBody::interpolateRenderMesh()
+{
+       if (m_z.size() > 0)
+       {
+               for (int i = 0; i < m_renderNodes.size(); ++i)
+               {
+                       const Node* p0 = m_renderNodesParents[i][0];
+                       const Node* p1 = m_renderNodesParents[i][1];
+                       const Node* p2 = m_renderNodesParents[i][2];
+                       btVector3 normal = btCross(p1->m_x - p0->m_x, p2->m_x - p0->m_x);
+                       btVector3 unit_normal = normal.normalized();
+                       RenderNode& n = m_renderNodes[i];
+                       n.m_x.setZero();
+                       for (int j = 0; j < 3; ++j)
+                       {
+                               n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
+                       }
+                       n.m_x += m_z[i] * unit_normal;
+               }
+       }
+       else
+       {
+               for (int i = 0; i < m_renderNodes.size(); ++i)
+               {
+                       RenderNode& n = m_renderNodes[i];
+                       n.m_x.setZero();
+                       for (int j = 0; j < 4; ++j)
+                       {
+                               if (m_renderNodesParents[i].size())
+                               {
+                                       n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
+                               }
+                       }
+               }
+       }
+}
+
+void btSoftBody::setCollisionQuadrature(int N)
+{
+       for (int i = 0; i <= N; ++i)
+       {
+               for (int j = 0; i + j <= N; ++j)
+               {
+                       m_quads.push_back(btVector3(btScalar(i) / btScalar(N), btScalar(j) / btScalar(N), btScalar(N - i - j) / btScalar(N)));
+               }
+       }
+}
+
+//
+void btSoftBody::PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti)
+{
+       BT_PROFILE("PSolve_Anchors");
+       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->getWorldTransform();
+               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 * a.m_influence;
+               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)
+{
+       BT_PROFILE("PSolve_RContacts");
+       const btScalar dt = psb->m_sst.sdt;
+       const btScalar mrg = psb->getCollisionShape()->getMargin();
+       btMultiBodyJacobianData jacobianData;
+       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;
+               if (cti.m_colObj->hasContactResponse())
+               {
+                       btVector3 va(0, 0, 0);
+                       btRigidBody* rigidCol = 0;
+                       btMultiBodyLinkCollider* multibodyLinkCol = 0;
+                       btScalar* deltaV = NULL;
+
+                       if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+                       {
+                               rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
+                               va = rigidCol ? rigidCol->getVelocityInLocalPoint(c.m_c1) * dt : btVector3(0, 0, 0);
+                       }
+                       else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+                       {
+                               multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+                               if (multibodyLinkCol)
+                               {
+                                       const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+                                       jacobianData.m_jacobians.resize(ndof);
+                                       jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
+                                       btScalar* jac = &jacobianData.m_jacobians[0];
+
+                                       multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, c.m_node->m_x, cti.m_normal, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
+                                       deltaV = &jacobianData.m_deltaVelocitiesUnitImpulse[0];
+                                       multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], deltaV, jacobianData.scratch_r, jacobianData.scratch_v);
+
+                                       btScalar vel = 0.0;
+                                       for (int j = 0; j < ndof; ++j)
+                                       {
+                                               vel += multibodyLinkCol->m_multiBody->getVelocityVector()[j] * jac[j];
+                                       }
+                                       va = cti.m_normal * vel * dt;
+                               }
+                       }
+
+                       const btVector3 vb = c.m_node->m_x - c.m_node->m_q;
+                       const btVector3 vr = vb - va;
+                       const btScalar dn = btDot(vr, cti.m_normal);
+                       if (dn <= SIMD_EPSILON)
+                       {
+                               const btScalar dp = btMin((btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg);
+                               const btVector3 fv = vr - (cti.m_normal * dn);
+                               // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
+                               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;
+
+                               if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+                               {
+                                       if (rigidCol)
+                                               rigidCol->applyImpulse(impulse, c.m_c1);
+                               }
+                               else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+                               {
+                                       if (multibodyLinkCol)
+                                       {
+                                               double multiplier = 0.5;
+                                               multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof(deltaV, -impulse.length() * multiplier);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+//
+void btSoftBody::PSolve_SContacts(btSoftBody* psb, btScalar, btScalar ti)
+{
+       BT_PROFILE("PSolve_SContacts");
+
+       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);
+               btScalar dot = btDot(vr, nr);
+               if (dot < 0)
+               {
+                       const btScalar j = c.m_margin - (btDot(nr, n.m_x) - btDot(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)
+{
+       BT_PROFILE("PSolve_Links");
+       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();
+                       if (l.m_c1 + len > SIMD_EPSILON)
+                       {
+                               const btScalar k = ((l.m_c1 - len) / (l.m_c0 * (l.m_c1 + len))) * kst;
+                               a.m_x -= del * (k * a.m_im);
+                               b.m_x += del * (k * b.m_im);
+                       }
+               }
+       }
+}
+
+//
+void btSoftBody::VSolve_Links(btSoftBody* psb, btScalar kst)
+{
+       BT_PROFILE("VSolve_Links");
+       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 = -btDot(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);
+               default:
+               {
+               }
+       }
+       return (0);
+}
+
+//
+btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
+{
+       switch (solver)
+       {
+               case eVSolver::Linear:
+                       return (&btSoftBody::VSolve_Links);
+               default:
+               {
+               }
+       }
+       return (0);
+}
+
+void btSoftBody::setSelfCollision(bool useSelfCollision)
+{
+       m_useSelfCollision = useSelfCollision;
+}
+
+bool btSoftBody::useSelfCollision()
+{
+       return m_useSelfCollision;
+}
+
+//
+void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
+{
+       switch (m_cfg.collisions & fCollision::RVSmask)
+       {
+               case fCollision::SDF_RS:
+               {
+                       btSoftColliders::CollideSDF_RS docollide;
+                       btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
+                       btTransform wtr = pcoWrap->getWorldTransform();
+
+                       const btTransform ctr = pcoWrap->getWorldTransform();
+                       const btScalar timemargin = (wtr.getOrigin() - ctr.getOrigin()).length();
+                       const btScalar basemargin = getCollisionShape()->getMargin();
+                       btVector3 mins;
+                       btVector3 maxs;
+                       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+                       volume;
+                       pcoWrap->getCollisionShape()->getAabb(pcoWrap->getWorldTransform(),
+                                                                                                 mins,
+                                                                                                 maxs);
+                       volume = btDbvtVolume::FromMM(mins, maxs);
+                       volume.Expand(btVector3(basemargin, basemargin, basemargin));
+                       docollide.psb = this;
+                       docollide.m_colObj1Wrap = pcoWrap;
+                       docollide.m_rigidBody = prb1;
+
+                       docollide.dynmargin = basemargin + timemargin;
+                       docollide.stamargin = basemargin;
+                       m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollide);
+               }
+               break;
+               case fCollision::CL_RS:
+               {
+                       btSoftColliders::CollideCL_RS collider;
+                       collider.ProcessColObj(this, pcoWrap);
+               }
+               break;
+               case fCollision::SDF_RD:
+               {
+                       btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
+                       if (this->isActive())
+                       {
+                               const btTransform wtr = pcoWrap->getWorldTransform();
+                               const btScalar timemargin = 0;
+                               const btScalar basemargin = getCollisionShape()->getMargin();
+                               btVector3 mins;
+                               btVector3 maxs;
+                               ATTRIBUTE_ALIGNED16(btDbvtVolume)
+                               volume;
+                               pcoWrap->getCollisionShape()->getAabb(wtr,
+                                                                                                         mins,
+                                                                                                         maxs);
+                               volume = btDbvtVolume::FromMM(mins, maxs);
+                               volume.Expand(btVector3(basemargin, basemargin, basemargin));
+                               if (m_cfg.collisions & fCollision::SDF_RDN)
+                               {
+                                       btSoftColliders::CollideSDF_RD docollideNode;
+                                       docollideNode.psb = this;
+                                       docollideNode.m_colObj1Wrap = pcoWrap;
+                                       docollideNode.m_rigidBody = prb1;
+                                       docollideNode.dynmargin = basemargin + timemargin;
+                                       docollideNode.stamargin = basemargin;
+                                       m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollideNode);
+                               }
+
+                               if (((pcoWrap->getCollisionObject()->getInternalType() == CO_RIGID_BODY) && (m_cfg.collisions & fCollision::SDF_RDF)) || ((pcoWrap->getCollisionObject()->getInternalType() == CO_FEATHERSTONE_LINK) && (m_cfg.collisions & fCollision::SDF_MDF)))
+                               {
+                                       btSoftColliders::CollideSDF_RDF docollideFace;
+                                       docollideFace.psb = this;
+                                       docollideFace.m_colObj1Wrap = pcoWrap;
+                                       docollideFace.m_rigidBody = prb1;
+                                       docollideFace.dynmargin = basemargin + timemargin;
+                                       docollideFace.stamargin = basemargin;
+                                       m_fdbvt.collideTV(m_fdbvt.m_root, volume, docollideFace);
+                               }
+                       }
+               }
+               break;
+       }
+}
+
+//
+void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
+{
+       BT_PROFILE("Deformable Collision");
+       const int cf = m_cfg.collisions & psb->m_cfg.collisions;
+       switch (cf & fCollision::SVSmask)
+       {
+               case fCollision::CL_SS:
+               {
+                       //support self-collision if CL_SELF flag set
+                       if (this != psb || psb->m_cfg.collisions & fCollision::CL_SELF)
+                       {
+                               btSoftColliders::CollideCL_SS docollide;
+                               docollide.ProcessSoftSoft(this, psb);
+                       }
+               }
+               break;
+               case fCollision::VF_SS:
+               {
+                       //only self-collision for Cluster, not Vertex-Face yet
+                       if (this != psb)
+                       {
+                               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;
+                               docollide.psb[0]->m_ndbvt.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;
+                               docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+                                                                                                       docollide.psb[1]->m_fdbvt.m_root,
+                                                                                                       docollide);
+                       }
+               }
+               break;
+               case fCollision::VF_DD:
+               {
+                       if (!psb->m_softSoftCollision)
+                               return;
+                       if (psb->isActive() || this->isActive())
+                       {
+                               if (this != psb)
+                               {
+                                       btSoftColliders::CollideVF_DD docollide;
+                                       /* common                    */
+                                       docollide.mrg = getCollisionShape()->getMargin() +
+                                                                       psb->getCollisionShape()->getMargin();
+                                       /* psb0 nodes vs psb1 faces    */
+                                       if (psb->m_tetras.size() > 0)
+                                               docollide.useFaceNormal = true;
+                                       else
+                                               docollide.useFaceNormal = false;
+                                       docollide.psb[0] = this;
+                                       docollide.psb[1] = psb;
+                                       docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+                                                                                                               docollide.psb[1]->m_fdbvt.m_root,
+                                                                                                               docollide);
+
+                                       /* psb1 nodes vs psb0 faces    */
+                                       if (this->m_tetras.size() > 0)
+                                               docollide.useFaceNormal = true;
+                                       else
+                                               docollide.useFaceNormal = false;
+                                       docollide.psb[0] = psb;
+                                       docollide.psb[1] = this;
+                                       docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+                                                                                                               docollide.psb[1]->m_fdbvt.m_root,
+                                                                                                               docollide);
+                               }
+                               else
+                               {
+                                       if (psb->useSelfCollision())
+                                       {
+                                               btSoftColliders::CollideFF_DD docollide;
+                                               docollide.mrg = 2 * getCollisionShape()->getMargin();
+                                               docollide.psb[0] = this;
+                                               docollide.psb[1] = psb;
+                                               if (this->m_tetras.size() > 0)
+                                                       docollide.useFaceNormal = true;
+                                               else
+                                                       docollide.useFaceNormal = false;
+                                               /* psb0 faces vs psb0 faces    */
+                                               calculateNormalCone(this->m_fdbvnt);
+                                               this->m_fdbvt.selfCollideT(m_fdbvnt, docollide);
+                                       }
+                               }
+                       }
+               }
+               break;
+               default:
+               {
+               }
+       }
+}
+
+void btSoftBody::geometricCollisionHandler(btSoftBody* psb)
+{
+       if (psb->isActive() || this->isActive())
+       {
+               if (this != psb)
+               {
+                       btSoftColliders::CollideCCD docollide;
+                       /* common                    */
+                       docollide.mrg = SAFE_EPSILON;  // for rounding error instead of actual margin
+                       docollide.dt = psb->m_sst.sdt;
+                       /* psb0 nodes vs psb1 faces    */
+                       if (psb->m_tetras.size() > 0)
+                               docollide.useFaceNormal = true;
+                       else
+                               docollide.useFaceNormal = false;
+                       docollide.psb[0] = this;
+                       docollide.psb[1] = psb;
+                       docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+                                                                                               docollide.psb[1]->m_fdbvt.m_root,
+                                                                                               docollide);
+                       /* psb1 nodes vs psb0 faces    */
+                       if (this->m_tetras.size() > 0)
+                               docollide.useFaceNormal = true;
+                       else
+                               docollide.useFaceNormal = false;
+                       docollide.psb[0] = psb;
+                       docollide.psb[1] = this;
+                       docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
+                                                                                               docollide.psb[1]->m_fdbvt.m_root,
+                                                                                               docollide);
+               }
+               else
+               {
+                       if (psb->useSelfCollision())
+                       {
+                               btSoftColliders::CollideCCD docollide;
+                               docollide.mrg = SAFE_EPSILON;
+                               docollide.psb[0] = this;
+                               docollide.psb[1] = psb;
+                               docollide.dt = psb->m_sst.sdt;
+                               if (this->m_tetras.size() > 0)
+                                       docollide.useFaceNormal = true;
+                               else
+                                       docollide.useFaceNormal = false;
+                               /* psb0 faces vs psb0 faces    */
+                               calculateNormalCone(this->m_fdbvnt);  // should compute this outside of this scope
+                               this->m_fdbvt.selfCollideT(m_fdbvnt, docollide);
+                       }
+               }
+       }
+}
+
+void btSoftBody::setWindVelocity(const btVector3& velocity)
+{
+       m_windVelocity = velocity;
+}
+
+const btVector3& btSoftBody::getWindVelocity()
+{
+       return m_windVelocity;
+}
+
+int btSoftBody::calculateSerializeBufferSize() const
+{
+       int sz = sizeof(btSoftBodyData);
+       return sz;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const
+{
+       btSoftBodyData* sbd = (btSoftBodyData*)dataBuffer;
+
+       btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer);
+
+       btHashMap<btHashPtr, int> m_nodeIndexMap;
+
+       sbd->m_numMaterials = m_materials.size();
+       sbd->m_materials = sbd->m_numMaterials ? (SoftBodyMaterialData**)serializer->getUniquePointer((void*)&m_materials) : 0;
+
+       if (sbd->m_materials)
+       {
+               int sz = sizeof(SoftBodyMaterialData*);
+               int numElem = sbd->m_numMaterials;
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               //SoftBodyMaterialData** memPtr = chunk->m_oldPtr;
+               SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       btSoftBody::Material* mat = m_materials[i];
+                       *memPtr = mat ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)mat) : 0;
+                       if (!serializer->findPointer(mat))
+                       {
+                               //serialize it here
+                               btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData), 1);
+                               SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr;
+                               memPtr->m_flags = mat->m_flags;
+                               memPtr->m_angularStiffness = mat->m_kAST;
+                               memPtr->m_linearStiffness = mat->m_kLST;
+                               memPtr->m_volumeStiffness = mat->m_kVST;
+                               serializer->finalizeChunk(chunk, "SoftBodyMaterialData", BT_SBMATERIAL_CODE, mat);
+                       }
+               }
+               serializer->finalizeChunk(chunk, "SoftBodyMaterialData", BT_ARRAY_CODE, (void*)&m_materials);
+       }
+
+       sbd->m_numNodes = m_nodes.size();
+       sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes) : 0;
+       if (sbd->m_nodes)
+       {
+               int sz = sizeof(SoftBodyNodeData);
+               int numElem = sbd->m_numNodes;
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       m_nodes[i].m_f.serializeFloat(memPtr->m_accumulatedForce);
+                       memPtr->m_area = m_nodes[i].m_area;
+                       memPtr->m_attach = m_nodes[i].m_battach;
+                       memPtr->m_inverseMass = m_nodes[i].m_im;
+                       memPtr->m_material = m_nodes[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_nodes[i].m_material) : 0;
+                       m_nodes[i].m_n.serializeFloat(memPtr->m_normal);
+                       m_nodes[i].m_x.serializeFloat(memPtr->m_position);
+                       m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition);
+                       m_nodes[i].m_v.serializeFloat(memPtr->m_velocity);
+                       m_nodeIndexMap.insert(&m_nodes[i], i);
+               }
+               serializer->finalizeChunk(chunk, "SoftBodyNodeData", BT_SBNODE_CODE, (void*)&m_nodes);
+       }
+
+       sbd->m_numLinks = m_links.size();
+       sbd->m_links = sbd->m_numLinks ? (SoftBodyLinkData*)serializer->getUniquePointer((void*)&m_links[0]) : 0;
+       if (sbd->m_links)
+       {
+               int sz = sizeof(SoftBodyLinkData);
+               int numElem = sbd->m_numLinks;
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       memPtr->m_bbending = m_links[i].m_bbending;
+                       memPtr->m_material = m_links[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_links[i].m_material) : 0;
+                       memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0] : -1;
+                       memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0] : -1;
+                       btAssert(memPtr->m_nodeIndices[0] < m_nodes.size());
+                       btAssert(memPtr->m_nodeIndices[1] < m_nodes.size());
+                       memPtr->m_restLength = m_links[i].m_rl;
+               }
+               serializer->finalizeChunk(chunk, "SoftBodyLinkData", BT_ARRAY_CODE, (void*)&m_links[0]);
+       }
+
+       sbd->m_numFaces = m_faces.size();
+       sbd->m_faces = sbd->m_numFaces ? (SoftBodyFaceData*)serializer->getUniquePointer((void*)&m_faces[0]) : 0;
+       if (sbd->m_faces)
+       {
+               int sz = sizeof(SoftBodyFaceData);
+               int numElem = sbd->m_numFaces;
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       memPtr->m_material = m_faces[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_faces[i].m_material) : 0;
+                       m_faces[i].m_normal.serializeFloat(memPtr->m_normal);
+                       for (int j = 0; j < 3; j++)
+                       {
+                               memPtr->m_nodeIndices[j] = m_faces[i].m_n[j] ? m_faces[i].m_n[j] - &m_nodes[0] : -1;
+                       }
+                       memPtr->m_restArea = m_faces[i].m_ra;
+               }
+               serializer->finalizeChunk(chunk, "SoftBodyFaceData", BT_ARRAY_CODE, (void*)&m_faces[0]);
+       }
+
+       sbd->m_numTetrahedra = m_tetras.size();
+       sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*)serializer->getUniquePointer((void*)&m_tetras[0]) : 0;
+       if (sbd->m_tetrahedra)
+       {
+               int sz = sizeof(SoftBodyTetraData);
+               int numElem = sbd->m_numTetrahedra;
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       for (int j = 0; j < 4; j++)
+                       {
+                               m_tetras[i].m_c0[j].serializeFloat(memPtr->m_c0[j]);
+                               memPtr->m_nodeIndices[j] = m_tetras[i].m_n[j] ? m_tetras[i].m_n[j] - &m_nodes[0] : -1;
+                       }
+                       memPtr->m_c1 = m_tetras[i].m_c1;
+                       memPtr->m_c2 = m_tetras[i].m_c2;
+                       memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_tetras[i].m_material) : 0;
+                       memPtr->m_restVolume = m_tetras[i].m_rv;
+               }
+               serializer->finalizeChunk(chunk, "SoftBodyTetraData", BT_ARRAY_CODE, (void*)&m_tetras[0]);
+       }
+
+       sbd->m_numAnchors = m_anchors.size();
+       sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*)serializer->getUniquePointer((void*)&m_anchors[0]) : 0;
+       if (sbd->m_anchors)
+       {
+               int sz = sizeof(SoftRigidAnchorData);
+               int numElem = sbd->m_numAnchors;
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       m_anchors[i].m_c0.serializeFloat(memPtr->m_c0);
+                       m_anchors[i].m_c1.serializeFloat(memPtr->m_c1);
+                       memPtr->m_c2 = m_anchors[i].m_c2;
+                       m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame);
+                       memPtr->m_nodeIndex = m_anchors[i].m_node ? m_anchors[i].m_node - &m_nodes[0] : -1;
+
+                       memPtr->m_rigidBody = m_anchors[i].m_body ? (btRigidBodyData*)serializer->getUniquePointer((void*)m_anchors[i].m_body) : 0;
+                       btAssert(memPtr->m_nodeIndex < m_nodes.size());
+               }
+               serializer->finalizeChunk(chunk, "SoftRigidAnchorData", BT_ARRAY_CODE, (void*)&m_anchors[0]);
+       }
+
+       sbd->m_config.m_dynamicFriction = m_cfg.kDF;
+       sbd->m_config.m_baumgarte = m_cfg.kVCF;
+       sbd->m_config.m_pressure = m_cfg.kPR;
+       sbd->m_config.m_aeroModel = this->m_cfg.aeromodel;
+       sbd->m_config.m_lift = m_cfg.kLF;
+       sbd->m_config.m_drag = m_cfg.kDG;
+       sbd->m_config.m_positionIterations = m_cfg.piterations;
+       sbd->m_config.m_driftIterations = m_cfg.diterations;
+       sbd->m_config.m_clusterIterations = m_cfg.citerations;
+       sbd->m_config.m_velocityIterations = m_cfg.viterations;
+       sbd->m_config.m_maxVolume = m_cfg.maxvolume;
+       sbd->m_config.m_damping = m_cfg.kDP;
+       sbd->m_config.m_poseMatch = m_cfg.kMT;
+       sbd->m_config.m_collisionFlags = m_cfg.collisions;
+       sbd->m_config.m_volume = m_cfg.kVC;
+       sbd->m_config.m_rigidContactHardness = m_cfg.kCHR;
+       sbd->m_config.m_kineticContactHardness = m_cfg.kKHR;
+       sbd->m_config.m_softContactHardness = m_cfg.kSHR;
+       sbd->m_config.m_anchorHardness = m_cfg.kAHR;
+       sbd->m_config.m_timeScale = m_cfg.timescale;
+       sbd->m_config.m_maxVolume = m_cfg.maxvolume;
+       sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL;
+       sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL;
+       sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL;
+       sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL;
+       sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL;
+       sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL;
+
+       //pose for shape matching
+       {
+               sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose);
+
+               int sz = sizeof(SoftBodyPoseData);
+               btChunk* chunk = serializer->allocate(sz, 1);
+               SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr;
+
+               m_pose.m_aqq.serializeFloat(memPtr->m_aqq);
+               memPtr->m_bframe = m_pose.m_bframe;
+               memPtr->m_bvolume = m_pose.m_bvolume;
+               m_pose.m_com.serializeFloat(memPtr->m_com);
+
+               memPtr->m_numPositions = m_pose.m_pos.size();
+               memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]) : 0;
+               if (memPtr->m_numPositions)
+               {
+                       int numElem = memPtr->m_numPositions;
+                       int sz = sizeof(btVector3Data);
+                       btChunk* chunk = serializer->allocate(sz, numElem);
+                       btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               m_pose.m_pos[i].serializeFloat(*memPtr);
+                       }
+                       serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)&m_pose.m_pos[0]);
+               }
+               memPtr->m_restVolume = m_pose.m_volume;
+               m_pose.m_rot.serializeFloat(memPtr->m_rot);
+               m_pose.m_scl.serializeFloat(memPtr->m_scale);
+
+               memPtr->m_numWeigts = m_pose.m_wgh.size();
+               memPtr->m_weights = memPtr->m_numWeigts ? (float*)serializer->getUniquePointer((void*)&m_pose.m_wgh[0]) : 0;
+               if (memPtr->m_numWeigts)
+               {
+                       int numElem = memPtr->m_numWeigts;
+                       int sz = sizeof(float);
+                       btChunk* chunk = serializer->allocate(sz, numElem);
+                       float* memPtr = (float*)chunk->m_oldPtr;
+                       for (int i = 0; i < numElem; i++, memPtr++)
+                       {
+                               *memPtr = m_pose.m_wgh[i];
+                       }
+                       serializer->finalizeChunk(chunk, "float", BT_ARRAY_CODE, (void*)&m_pose.m_wgh[0]);
+               }
+
+               serializer->finalizeChunk(chunk, "SoftBodyPoseData", BT_ARRAY_CODE, (void*)&m_pose);
+       }
+
+       //clusters for convex-cluster collision detection
+
+       sbd->m_numClusters = m_clusters.size();
+       sbd->m_clusters = sbd->m_numClusters ? (SoftBodyClusterData*)serializer->getUniquePointer((void*)m_clusters[0]) : 0;
+       if (sbd->m_numClusters)
+       {
+               int numElem = sbd->m_numClusters;
+               int sz = sizeof(SoftBodyClusterData);
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               SoftBodyClusterData* memPtr = (SoftBodyClusterData*)chunk->m_oldPtr;
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       memPtr->m_adamping = m_clusters[i]->m_adamping;
+                       m_clusters[i]->m_av.serializeFloat(memPtr->m_av);
+                       memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex;
+                       memPtr->m_collide = m_clusters[i]->m_collide;
+                       m_clusters[i]->m_com.serializeFloat(memPtr->m_com);
+                       memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor;
+                       m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]);
+                       m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]);
+                       m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform);
+                       memPtr->m_idmass = m_clusters[i]->m_idmass;
+                       memPtr->m_imass = m_clusters[i]->m_imass;
+                       m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi);
+                       memPtr->m_ldamping = m_clusters[i]->m_ldamping;
+                       m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii);
+                       m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv);
+                       memPtr->m_matching = m_clusters[i]->m_matching;
+                       memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse;
+                       memPtr->m_ndamping = m_clusters[i]->m_ndamping;
+                       memPtr->m_ldamping = m_clusters[i]->m_ldamping;
+                       memPtr->m_adamping = m_clusters[i]->m_adamping;
+                       memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor;
+
+                       memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size();
+                       memPtr->m_numMasses = m_clusters[i]->m_masses.size();
+                       memPtr->m_numNodes = m_clusters[i]->m_nodes.size();
+
+                       memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses;
+                       m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]);
+                       m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]);
+                       memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses;
+
+                       memPtr->m_framerefs = memPtr->m_numFrameRefs ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0;
+                       if (memPtr->m_framerefs)
+                       {
+                               int numElem = memPtr->m_numFrameRefs;
+                               int sz = sizeof(btVector3FloatData);
+                               btChunk* chunk = serializer->allocate(sz, numElem);
+                               btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
+                               for (int j = 0; j < numElem; j++, memPtr++)
+                               {
+                                       m_clusters[i]->m_framerefs[j].serializeFloat(*memPtr);
+                               }
+                               serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_framerefs[0]);
+                       }
+
+                       memPtr->m_masses = memPtr->m_numMasses ? (float*)serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]) : 0;
+                       if (memPtr->m_masses)
+                       {
+                               int numElem = memPtr->m_numMasses;
+                               int sz = sizeof(float);
+                               btChunk* chunk = serializer->allocate(sz, numElem);
+                               float* memPtr = (float*)chunk->m_oldPtr;
+                               for (int j = 0; j < numElem; j++, memPtr++)
+                               {
+                                       *memPtr = m_clusters[i]->m_masses[j];
+                               }
+                               serializer->finalizeChunk(chunk, "float", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_masses[0]);
+                       }
+
+                       memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*)serializer->getUniquePointer((void*)&m_clusters[i]->m_nodes) : 0;
+                       if (memPtr->m_nodeIndices)
+                       {
+                               int numElem = memPtr->m_numMasses;
+                               int sz = sizeof(int);
+                               btChunk* chunk = serializer->allocate(sz, numElem);
+                               int* memPtr = (int*)chunk->m_oldPtr;
+                               for (int j = 0; j < numElem; j++, memPtr++)
+                               {
+                                       int* indexPtr = m_nodeIndexMap.find(m_clusters[i]->m_nodes[j]);
+                                       btAssert(indexPtr);
+                                       *memPtr = *indexPtr;
+                               }
+                               serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_nodes);
+                       }
+               }
+               serializer->finalizeChunk(chunk, "SoftBodyClusterData", BT_ARRAY_CODE, (void*)m_clusters[0]);
+       }
+
+       sbd->m_numJoints = m_joints.size();
+       sbd->m_joints = m_joints.size() ? (btSoftBodyJointData*)serializer->getUniquePointer((void*)&m_joints[0]) : 0;
+
+       if (sbd->m_joints)
+       {
+               int sz = sizeof(btSoftBodyJointData);
+               int numElem = m_joints.size();
+               btChunk* chunk = serializer->allocate(sz, numElem);
+               btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr;
+
+               for (int i = 0; i < numElem; i++, memPtr++)
+               {
+                       memPtr->m_jointType = (int)m_joints[i]->Type();
+                       m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]);
+                       m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]);
+                       memPtr->m_cfm = m_joints[i]->m_cfm;
+                       memPtr->m_erp = float(m_joints[i]->m_erp);
+                       memPtr->m_split = float(m_joints[i]->m_split);
+                       memPtr->m_delete = m_joints[i]->m_delete;
+
+                       for (int j = 0; j < 4; j++)
+                       {
+                               memPtr->m_relPosition[0].m_floats[j] = 0.f;
+                               memPtr->m_relPosition[1].m_floats[j] = 0.f;
+                       }
+                       memPtr->m_bodyA = 0;
+                       memPtr->m_bodyB = 0;
+                       if (m_joints[i]->m_bodies[0].m_soft)
+                       {
+                               memPtr->m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER;
+                               memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft);
+                       }
+                       if (m_joints[i]->m_bodies[0].m_collisionObject)
+                       {
+                               memPtr->m_bodyAtype = BT_JOINT_COLLISION_OBJECT;
+                               memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject);
+                       }
+                       if (m_joints[i]->m_bodies[0].m_rigid)
+                       {
+                               memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY;
+                               memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid);
+                       }
+
+                       if (m_joints[i]->m_bodies[1].m_soft)
+                       {
+                               memPtr->m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER;
+                               memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft);
+                       }
+                       if (m_joints[i]->m_bodies[1].m_collisionObject)
+                       {
+                               memPtr->m_bodyBtype = BT_JOINT_COLLISION_OBJECT;
+                               memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject);
+                       }
+                       if (m_joints[i]->m_bodies[1].m_rigid)
+                       {
+                               memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY;
+                               memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid);
+                       }
+               }
+               serializer->finalizeChunk(chunk, "btSoftBodyJointData", BT_ARRAY_CODE, (void*)&m_joints[0]);
+       }
+
+       return btSoftBodyDataName;
+}
+
+void btSoftBody::updateDeactivation(btScalar timeStep)
+{
+       if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
+               return;
+
+       if (m_maxSpeedSquared < m_sleepingThreshold * m_sleepingThreshold)
+       {
+               m_deactivationTime += timeStep;
+       }
+       else
+       {
+               m_deactivationTime = btScalar(0.);
+               setActivationState(0);
+       }
+}
+
+void btSoftBody::setZeroVelocity()
+{
+       for (int i = 0; i < m_nodes.size(); ++i)
+       {
+               m_nodes[i].m_v.setZero();
+       }
+}
+
+bool btSoftBody::wantsSleeping()
+{
+       if (getActivationState() == DISABLE_DEACTIVATION)
+               return false;
+
+       //disable deactivation
+       if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
+               return false;
+
+       if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
+               return true;
+
+       if (m_deactivationTime > gDeactivationTime)
+       {
+               return true;
+       }
+       return false;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBody.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBody.h
new file mode 100644 (file)
index 0000000..f91640a
--- /dev/null
@@ -0,0 +1,1409 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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/btTransform.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btVector3.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "btSparseSDF.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+//#ifdef BT_USE_DOUBLE_PRECISION
+//#define btRigidBodyData      btRigidBodyDoubleData
+//#define btRigidBodyDataName  "btRigidBodyDoubleData"
+//#else
+#define btSoftBodyData btSoftBodyFloatData
+#define btSoftBodyDataName "btSoftBodyFloatData"
+static const btScalar OVERLAP_REDUCTION_FACTOR = 0.1;
+static unsigned long seed = 243703;
+//#endif //BT_USE_DOUBLE_PRECISION
+
+class btBroadphaseInterface;
+class btDispatcher;
+class btSoftBodySolver;
+
+/* btSoftBodyWorldInfo */
+struct btSoftBodyWorldInfo
+{
+       btScalar air_density;
+       btScalar water_density;
+       btScalar water_offset;
+       btScalar m_maxDisplacement;
+       btVector3 water_normal;
+       btBroadphaseInterface* m_broadphase;
+       btDispatcher* m_dispatcher;
+       btVector3 m_gravity;
+       btSparseSdf<3> m_sparsesdf;
+
+       btSoftBodyWorldInfo()
+               : air_density((btScalar)1.2),
+                 water_density(0),
+                 water_offset(0),
+                 m_maxDisplacement(1000.f),  //avoid soft body from 'exploding' so use some upper threshold of maximum motion that a node can travel per frame
+                 water_normal(0, 0, 0),
+                 m_broadphase(0),
+                 m_dispatcher(0),
+                 m_gravity(0, -10, 0)
+       {
+       }
+};
+
+///The btSoftBody is an class to simulate cloth and volumetric soft bodies.
+///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject.
+class btSoftBody : public btCollisionObject
+{
+public:
+       btAlignedObjectArray<const class btCollisionObject*> m_collisionDisabledObjects;
+
+       // The solver object that handles this soft body
+       btSoftBodySolver* m_softBodySolver;
+
+       //
+       // Enumerations
+       //
+
+       ///eAeroModel
+       struct eAeroModel
+       {
+               enum _
+               {
+                       V_Point,             ///Vertex normals are oriented toward velocity
+                       V_TwoSided,          ///Vertex normals are flipped to match velocity
+                       V_TwoSidedLiftDrag,  ///Vertex normals are flipped to match velocity and lift and drag forces are applied
+                       V_OneSided,          ///Vertex normals are taken as it is
+                       F_TwoSided,          ///Face normals are flipped to match velocity
+                       F_TwoSidedLiftDrag,  ///Face normals are flipped to match velocity and lift and drag forces are applied
+                       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,
+                       Tetra,
+                       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
+                       SDF_RD = 0x0004,   ///rigid vs deformable
+
+                       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
+                       CL_SELF = 0x0040,  ///Cluster soft body self collision
+                       VF_DD = 0x0080,    ///Vertex vs face soft vs soft handling
+
+                       RVDFmask = 0x0f00,  /// Rigid versus deformable face mask
+                       SDF_RDF = 0x0100,   /// GJK based Rigid vs. deformable face
+                       SDF_MDF = 0x0200,   /// GJK based Multibody vs. deformable face
+                       SDF_RDN = 0x0400,   /// SDF based Rigid vs. deformable node
+                       /* 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 fraction;    /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction)
+       };
+
+       /* ImplicitFn   */
+       struct ImplicitFn
+       {
+               virtual ~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
+       {
+               const btCollisionObject* m_colObj; /* Rigid body                        */
+               btVector3 m_normal;                /* Outward normal            */
+               btScalar m_offset;                 /* Offset from origin        */
+               btVector3 m_bary;                  /* Barycentric weights for faces */
+       };
+
+       /* 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 RenderNode
+       {
+               btVector3 m_x;
+               btVector3 m_uv1;
+               btVector3 m_normal;
+       };
+       struct Node : Feature
+       {
+               btVector3 m_x;       // Position
+               btVector3 m_q;       // Previous step position/Test position
+               btVector3 m_v;       // Velocity
+               btVector3 m_vn;      // Previous step 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_constrained;   // depth of penetration
+               int m_battach : 1;   // Attached
+               int index;
+               btVector3 m_splitv;               // velocity associated with split impulse
+               btMatrix3x3 m_effectiveMass;      // effective mass in contact
+               btMatrix3x3 m_effectiveMass_inv;  // inverse of effective mass
+       };
+       /* Link                 */
+       ATTRIBUTE_ALIGNED16(struct)
+       Link : Feature
+       {
+               btVector3 m_c3;      // gradient
+               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
+
+               BT_DECLARE_ALIGNED_ALLOCATOR();
+       };
+       struct RenderFace
+       {
+               RenderNode* m_n[3];  // Node pointers
+       };
+
+       /* Face                 */
+       struct Face : Feature
+       {
+               Node* m_n[3];          // Node pointers
+               btVector3 m_normal;    // Normal
+               btScalar m_ra;         // Rest area
+               btDbvtNode* m_leaf;    // Leaf data
+               btVector4 m_pcontact;  // barycentric weights of the persistent contact
+               btVector3 m_n0, m_n1, m_vn;
+               int m_index;
+       };
+       /* Tetra                */
+       struct Tetra : Feature
+       {
+               Node* m_n[4];              // Node pointers
+               btScalar m_rv;             // Rest volume
+               btDbvtNode* m_leaf;        // Leaf data
+               btVector3 m_c0[4];         // gradients
+               btScalar m_c1;             // (4*kVST)/(im0+im1+im2+im3)
+               btScalar m_c2;             // m_c1/sum(|g0..3|^2)
+               btMatrix3x3 m_Dm_inverse;  // rest Dm^-1
+               btMatrix3x3 m_F;
+               btScalar m_element_measure;
+               btVector4 m_P_inv[3];  // first three columns of P_inv matrix
+       };
+
+       /*  TetraScratch  */
+       struct TetraScratch
+       {
+               btMatrix3x3 m_F;           // deformation gradient F
+               btScalar m_trace;          // trace of F^T * F
+               btScalar m_J;              // det(F)
+               btMatrix3x3 m_cofF;        // cofactor of F
+               btMatrix3x3 m_corotation;  // corotatio of the tetra
+       };
+
+       /* 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
+
+               // jacobians and unit impulse responses for multibody
+               btMultiBodyJacobianData jacobianData_normal;
+               btMultiBodyJacobianData jacobianData_t1;
+               btMultiBodyJacobianData jacobianData_t2;
+               btVector3 t1;
+               btVector3 t2;
+       };
+
+       class DeformableRigidContact
+       {
+       public:
+               sCti m_cti;        // Contact infos
+               btMatrix3x3 m_c0;  // Impulse matrix
+               btVector3 m_c1;    // Relative anchor
+               btScalar m_c2;     // inverse mass of node/face
+               btScalar m_c3;     // Friction
+               btScalar m_c4;     // Hardness
+               btMatrix3x3 m_c5;  // inverse effective mass
+
+               // jacobians and unit impulse responses for multibody
+               btMultiBodyJacobianData jacobianData_normal;
+               btMultiBodyJacobianData jacobianData_t1;
+               btMultiBodyJacobianData jacobianData_t2;
+               btVector3 t1;
+               btVector3 t2;
+       };
+
+       class DeformableNodeRigidContact : public DeformableRigidContact
+       {
+       public:
+               Node* m_node;  // Owner node
+       };
+
+       class DeformableNodeRigidAnchor : public DeformableNodeRigidContact
+       {
+       public:
+               btVector3 m_local;  // Anchor position in body space
+       };
+
+       class DeformableFaceRigidContact : public DeformableRigidContact
+       {
+       public:
+               Face* m_face;              // Owner face
+               btVector3 m_contactPoint;  // Contact point
+               btVector3 m_bary;          // Barycentric weights
+               btVector3 m_weights;       // v_contactPoint * m_weights[i] = m_face->m_node[i]->m_v;
+       };
+
+       struct DeformableFaceNodeContact
+       {
+               Node* m_node;         // Node
+               Face* m_face;         // Face
+               btVector3 m_bary;     // Barycentric weights
+               btVector3 m_weights;  // v_contactPoint * m_weights[i] = m_face->m_node[i]->m_v;
+               btVector3 m_normal;   // Normal
+               btScalar m_margin;    // Margin
+               btScalar m_friction;  // Friction
+               btScalar m_imf;       // inverse mass of the face at contact point
+               btScalar m_c0;        // scale of the impulse matrix;
+               const btCollisionObject* m_colObj;  // Collision object to collide with.
+       };
+
+       /* 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
+               btScalar m_influence;
+               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
+       {
+               tScalarArray m_masses;
+               btAlignedObjectArray<Node*> m_nodes;
+               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; /* Node damping            */
+               btScalar m_ldamping; /* Linear damping  */
+               btScalar m_adamping; /* Angular damping */
+               btScalar m_matching;
+               btScalar m_maxSelfCollisionImpulse;
+               btScalar m_selfCollisionImpulseFactor;
+               bool m_containsAnchor;
+               bool m_collide;
+               int m_clusterIndex;
+               Cluster() : m_leaf(0), m_ndamping(0), m_ldamping(0), m_adamping(0), m_matching(0), m_maxSelfCollisionImpulse(100.f), m_selfCollisionImpulseFactor(0.01f), m_containsAnchor(false)
+               {
+               }
+       };
+       /* 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;
+               const btCollisionObject* m_collisionObject;
+
+               Body() : m_soft(0), m_rigid(0), m_collisionObject(0) {}
+               Body(Cluster* p) : m_soft(p), m_rigid(0), m_collisionObject(0) {}
+               Body(const btCollisionObject* colObj) : m_soft(0), m_collisionObject(colObj)
+               {
+                       m_rigid = (btRigidBody*)btRigidBody::upcast(m_collisionObject);
+               }
+
+               void activate() const
+               {
+                       if (m_rigid)
+                               m_rigid->activate();
+                       if (m_collisionObject)
+                               m_collisionObject->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_collisionObject) return (m_collisionObject->getWorldTransform());
+                       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 (btCross(m_rigid->getAngularVelocity(), rpos));
+                       if (m_soft) return (btCross(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)
+                       {
+                               //                              printf("impulse.m_velocity = %f,%f,%f\n",impulse.m_velocity.getX(),impulse.m_velocity.getY(),impulse.m_velocity.getZ());
+                               applyVImpulse(impulse.m_velocity, rpos);
+                       }
+                       if (impulse.m_asDrift)
+                       {
+                               //                              printf("impulse.m_drift = %f,%f,%f\n",impulse.m_drift.getX(),impulse.m_drift.getY(),impulse.m_drift.getZ());
+                               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 = 0,
+                               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 ~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
+               btScalar drag;              // deformable air drag
+               btScalar m_maxStress;       // Maximum principle first Piola stress
+       };
+       /* SolverState  */
+       struct SolverState
+       {
+               //if you add new variables, always initialize them!
+               SolverState()
+                       : sdt(0),
+                         isdt(0),
+                         velmrg(0),
+                         radmrg(0),
+                         updmrg(0)
+               {
+               }
+               btScalar sdt;     // dt*timescale
+               btScalar isdt;    // 1/sdt
+               btScalar velmrg;  // velocity margin
+               btScalar radmrg;  // radial margin
+               btScalar updmrg;  // Update margin
+       };
+       /// RayFromToCaster takes a ray from, ray to (instead of direction!)
+       struct RayFromToCaster : btDbvt::ICollide
+       {
+               btVector3 m_rayFrom;
+               btVector3 m_rayTo;
+               btVector3 m_rayNormalizedDirection;
+               btScalar m_mint;
+               Face* m_face;
+               int m_tests;
+               RayFromToCaster(const btVector3& rayFrom, const btVector3& rayTo, btScalar mxt);
+               void Process(const btDbvtNode* leaf);
+
+               static /*inline*/ btScalar rayFromToTriangle(const btVector3& rayFrom,
+                                                                                                        const btVector3& rayTo,
+                                                                                                        const btVector3& rayNormalizedDirection,
+                                                                                                        const btVector3& a,
+                                                                                                        const btVector3& b,
+                                                                                                        const btVector3& c,
+                                                                                                        btScalar maxt = SIMD_INFINITY);
+       };
+
+       //
+       // Typedefs
+       //
+
+       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<RenderNode> tRenderNodeArray;
+       typedef btAlignedObjectArray<btDbvtNode*> tLeafArray;
+       typedef btAlignedObjectArray<Link> tLinkArray;
+       typedef btAlignedObjectArray<Face> tFaceArray;
+       typedef btAlignedObjectArray<RenderFace> tRenderFaceArray;
+       typedef btAlignedObjectArray<Tetra> tTetraArray;
+       typedef btAlignedObjectArray<Anchor> tAnchorArray;
+       typedef btAlignedObjectArray<RContact> tRContactArray;
+       typedef btAlignedObjectArray<SContact> tSContactArray;
+       typedef btAlignedObjectArray<Material*> tMaterialArray;
+       typedef btAlignedObjectArray<Joint*> tJointArray;
+       typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
+       typedef btAlignedObjectArray<btAlignedObjectArray<btScalar> > tDenseMatrix;
+
+       //
+       // 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
+       tRenderNodeArray m_renderNodes;    // Render Nodes
+       tLinkArray m_links;                // Links
+       tFaceArray m_faces;                // Faces
+       tRenderFaceArray m_renderFaces;    // Faces
+       tTetraArray m_tetras;              // Tetras
+       btAlignedObjectArray<TetraScratch> m_tetraScratches;
+       btAlignedObjectArray<TetraScratch> m_tetraScratchesTn;
+       tAnchorArray m_anchors;  // Anchors
+       btAlignedObjectArray<DeformableNodeRigidAnchor> m_deformableAnchors;
+       tRContactArray m_rcontacts;  // Rigid contacts
+       btAlignedObjectArray<DeformableNodeRigidContact> m_nodeRigidContacts;
+       btAlignedObjectArray<DeformableFaceNodeContact> m_faceNodeContacts;
+       btAlignedObjectArray<DeformableFaceRigidContact> m_faceRigidContacts;
+       btAlignedObjectArray<DeformableFaceNodeContact> m_faceNodeContactsCCD;
+       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
+       btDbvntNode* m_fdbvnt;          // Faces tree with normals
+       btDbvt m_cdbvt;                 // Clusters tree
+       tClusterArray m_clusters;       // Clusters
+       btScalar m_dampingCoefficient;  // Damping Coefficient
+       btScalar m_sleepingThreshold;
+       btScalar m_maxSpeedSquared;
+       btAlignedObjectArray<btVector3> m_quads;  // quadrature points for collision detection
+       btScalar m_repulsionStiffness;
+       btScalar m_gravityFactor;
+       bool m_cacheBarycenter;
+       btAlignedObjectArray<btVector3> m_X;  // initial positions
+
+       btAlignedObjectArray<btVector4> m_renderNodesInterpolationWeights;
+       btAlignedObjectArray<btAlignedObjectArray<const btSoftBody::Node*> > m_renderNodesParents;
+       btAlignedObjectArray<btScalar> m_z;  // vertical distance used in extrapolation
+       bool m_useSelfCollision;
+       bool m_softSoftCollision;
+
+       btAlignedObjectArray<bool> m_clusterConnectivity;  //cluster connectivity, for self-collision
+
+       btVector3 m_windVelocity;
+
+       btScalar m_restLengthScale;
+
+       bool m_reducedModel;    // Reduced deformable model flag
+       
+       //
+       // Api
+       //
+
+       /* ctor                                                                                                                                 */
+       btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m);
+
+       /* ctor                                                                                                                                 */
+       btSoftBody(btSoftBodyWorldInfo* worldInfo);
+
+       void initDefaults();
+
+       /* dtor                                                                                                                                 */
+       virtual ~btSoftBody();
+       /* Check for existing link                                                                                              */
+
+       btAlignedObjectArray<int> m_userIndexMapping;
+
+       btSoftBodyWorldInfo* getWorldInfo()
+       {
+               return m_worldInfo;
+       }
+
+       void setDampingCoefficient(btScalar damping_coeff)
+       {
+               m_dampingCoefficient = damping_coeff;
+       }
+
+       ///@todo: avoid internal softbody shape hack and move collision code to collision library
+       virtual void setCollisionShape(btCollisionShape* collisionShape)
+       {
+       }
+
+       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);
+       void appendTetra(int model, Material* mat);
+       //
+       void appendTetra(int node0,
+                                        int node1,
+                                        int node2,
+                                        int node3,
+                                        Material* mat = 0);
+
+       /* Append anchor                                                                                                                */
+       void appendDeformableAnchor(int node, btRigidBody* body);
+       void appendDeformableAnchor(int node, btMultiBodyLinkCollider* link);
+       void appendAnchor(int node,
+                                         btRigidBody* body, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1);
+       void appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1);
+       void removeAnchor(int node);
+       /* 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 aero force to a node of the body */
+       void addAeroForceToNode(const btVector3& windVelocity, int nodeIndex);
+
+       /* Add aero force to a face of the body */
+       void addAeroForceToFace(const btVector3& windVelocity, int faceIndex);
+
+       /* Add velocity to the entire body                                                                              */
+       void addVelocity(const btVector3& velocity);
+
+       /* Set velocity for the entire body                                                                             */
+       void setVelocity(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);
+       /* Set volume mass (using tetrahedrons)                                                                 */
+       void setVolumeMass(btScalar mass);
+       /* Set volume density (using tetrahedrons)                                                              */
+       void setVolumeDensity(btScalar density);
+       /* Get the linear velocity of the center of mass                        */
+       btVector3 getLinearVelocity();
+       /* Set the linear velocity of the center of mass                        */
+       void setLinearVelocity(const btVector3& linVel);
+       /* Set the angular velocity of the center of mass                       */
+       void setAngularVelocity(const btVector3& angVel);
+       /* Get best fit rigid transform                                         */
+       btTransform getRigidTransform();
+       /* Transform to given pose                                              */
+       virtual void transformTo(const btTransform& trs);
+       /* Transform                                                                                                                    */
+       virtual void transform(const btTransform& trs);
+       /* Translate                                                                                                                    */
+       virtual void translate(const btVector3& trs);
+       /* Rotate                                                                                                                       */
+       virtual void rotate(const btQuaternion& rot);
+       /* Scale                                                                                                                                */
+       virtual void scale(const btVector3& scl);
+       /* Get link resting lengths scale                                                                               */
+       btScalar getRestLengthScale();
+       /* Scale resting length of all springs                                                                  */
+       void setRestLengthScale(btScalar restLength);
+       /* Set current state as pose                                                                                    */
+       void setPose(bool bvolume,
+                                bool bframe);
+       /* Set current link lengths as resting lengths                                                  */
+       void resetLinkRestLengths();
+       /* Return the volume                                                                                                    */
+       btScalar getVolume() const;
+       /* Cluster count                                                                                                                */
+       btVector3 getCenterOfMass() const
+       {
+               btVector3 com(0, 0, 0);
+               for (int i = 0; i < m_nodes.size(); i++)
+               {
+                       com += (m_nodes[i].m_x * this->getMass(i));
+               }
+               com /= this->getTotalMass();
+               return com;
+       }
+       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();
+
+       void updateState(const btAlignedObjectArray<btVector3>& qs, const btAlignedObjectArray<btVector3>& vs);
+
+       /* Release clusters                                                                                                             */
+       void releaseCluster(int index);
+       void releaseClusters();
+       /* Generate clusters (K-mean)                                                                                   */
+       ///generateClusters with k=0 will create a convex cluster for each tetrahedron or triangle
+       ///otherwise an approximation will be used (better performance)
+       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 using rayFrom and rayTo in worldspace, (not direction!)
+       bool rayTest(const btVector3& rayFrom,
+                                const btVector3& rayTo,
+                                sRayCast& results);
+       bool rayFaceTest(const btVector3& rayFrom,
+                                        const btVector3& rayTo,
+                                        sRayCast& results);
+       int rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo,
+                                       btScalar& mint, int& index) const;
+       /* 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(const btCollisionObjectWrapper* pcoWrap);
+       void defaultCollisionHandler(btSoftBody* psb);
+       void setSelfCollision(bool useSelfCollision);
+       bool useSelfCollision();
+       void updateDeactivation(btScalar timeStep);
+       void setZeroVelocity();
+       bool wantsSleeping();
+
+       virtual btMatrix3x3 getImpulseFactor(int n_node)
+       {
+               btMatrix3x3 tmp;
+               tmp.setIdentity();
+               return tmp;
+       }
+
+       //
+       // Functionality to deal with new accelerated solvers.
+       //
+
+       /**
+        * Set a wind velocity for interaction with the air.
+        */
+       void setWindVelocity(const btVector3& velocity);
+
+       /**
+        * Return the wind velocity for interaction with the air.
+        */
+       const btVector3& getWindVelocity();
+
+       //
+       // Set the solver that handles this soft body
+       // Should not be allowed to get out of sync with reality
+       // Currently called internally on addition to the world
+       void setSoftBodySolver(btSoftBodySolver* softBodySolver)
+       {
+               m_softBodySolver = softBodySolver;
+       }
+
+       //
+       // Return the solver that handles this soft body
+       //
+       btSoftBodySolver* getSoftBodySolver()
+       {
+               return m_softBodySolver;
+       }
+
+       //
+       // Return the solver that handles this soft body
+       //
+       btSoftBodySolver* getSoftBodySolver() const
+       {
+               return m_softBodySolver;
+       }
+
+       //
+       // 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 rayTest(const btVector3& rayFrom, const btVector3& rayTo,
+                               btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const;
+       void initializeFaceTree();
+       void rebuildNodeTree();
+       btVector3 evaluateCom() const;
+       bool checkDeformableContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
+       bool checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap, Face& f, btVector3& contact_point, btVector3& bary, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
+       bool checkContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti) const;
+       void updateNormals();
+       void updateBounds();
+       void updatePose();
+       void updateConstants();
+       void updateLinkConstants();
+       void updateArea(bool averageArea = true);
+       void initializeClusters();
+       void updateClusters();
+       void cleanupClusters();
+       void prepareClusters(int iterations);
+       void solveClusters(btScalar sor);
+       void applyClusters(bool drift);
+       void dampClusters();
+       void setSpringStiffness(btScalar k);
+       void setGravityFactor(btScalar gravFactor);
+       void setCacheBarycenter(bool cacheBarycenter);
+       void initializeDmInverse();
+       void updateDeformation();
+       void advanceDeformation();
+       void applyForces();
+       void setMaxStress(btScalar maxStress);
+       void interpolateRenderMesh();
+       void setCollisionQuadrature(int N);
+       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);
+       void geometricCollisionHandler(btSoftBody* psb);
+#define SAFE_EPSILON SIMD_EPSILON * 100.0
+       void updateNode(btDbvtNode* node, bool use_velocity, bool margin)
+       {
+               if (node->isleaf())
+               {
+                       btSoftBody::Node* n = (btSoftBody::Node*)(node->data);
+                       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+                       vol;
+                       btScalar pad = margin ? m_sst.radmrg : SAFE_EPSILON;  // use user defined margin or margin for floating point precision
+                       if (use_velocity)
+                       {
+                               btVector3 points[2] = {n->m_x, n->m_x + m_sst.sdt * n->m_v};
+                               vol = btDbvtVolume::FromPoints(points, 2);
+                               vol.Expand(btVector3(pad, pad, pad));
+                       }
+                       else
+                       {
+                               vol = btDbvtVolume::FromCR(n->m_x, pad);
+                       }
+                       node->volume = vol;
+                       return;
+               }
+               else
+               {
+                       updateNode(node->childs[0], use_velocity, margin);
+                       updateNode(node->childs[1], use_velocity, margin);
+                       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+                       vol;
+                       Merge(node->childs[0]->volume, node->childs[1]->volume, vol);
+                       node->volume = vol;
+               }
+       }
+
+       void updateNodeTree(bool use_velocity, bool margin)
+       {
+               if (m_ndbvt.m_root)
+                       updateNode(m_ndbvt.m_root, use_velocity, margin);
+       }
+
+       template <class DBVTNODE>  // btDbvtNode or btDbvntNode
+       void updateFace(DBVTNODE* node, bool use_velocity, bool margin)
+       {
+               if (node->isleaf())
+               {
+                       btSoftBody::Face* f = (btSoftBody::Face*)(node->data);
+                       btScalar pad = margin ? m_sst.radmrg : SAFE_EPSILON;  // use user defined margin or margin for floating point precision
+                       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+                       vol;
+                       if (use_velocity)
+                       {
+                               btVector3 points[6] = {f->m_n[0]->m_x, f->m_n[0]->m_x + m_sst.sdt * f->m_n[0]->m_v,
+                                                                          f->m_n[1]->m_x, f->m_n[1]->m_x + m_sst.sdt * f->m_n[1]->m_v,
+                                                                          f->m_n[2]->m_x, f->m_n[2]->m_x + m_sst.sdt * f->m_n[2]->m_v};
+                               vol = btDbvtVolume::FromPoints(points, 6);
+                       }
+                       else
+                       {
+                               btVector3 points[3] = {f->m_n[0]->m_x,
+                                                                          f->m_n[1]->m_x,
+                                                                          f->m_n[2]->m_x};
+                               vol = btDbvtVolume::FromPoints(points, 3);
+                       }
+                       vol.Expand(btVector3(pad, pad, pad));
+                       node->volume = vol;
+                       return;
+               }
+               else
+               {
+                       updateFace(node->childs[0], use_velocity, margin);
+                       updateFace(node->childs[1], use_velocity, margin);
+                       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+                       vol;
+                       Merge(node->childs[0]->volume, node->childs[1]->volume, vol);
+                       node->volume = vol;
+               }
+       }
+       void updateFaceTree(bool use_velocity, bool margin)
+       {
+               if (m_fdbvt.m_root)
+                       updateFace(m_fdbvt.m_root, use_velocity, margin);
+               if (m_fdbvnt)
+                       updateFace(m_fdbvnt, use_velocity, margin);
+       }
+
+       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());
+       }
+
+       void applyRepulsionForce(btScalar timeStep, bool applySpringForce)
+       {
+               btAlignedObjectArray<int> indices;
+               {
+                       // randomize the order of repulsive force
+                       indices.resize(m_faceNodeContacts.size());
+                       for (int i = 0; i < m_faceNodeContacts.size(); ++i)
+                               indices[i] = i;
+#define NEXTRAND (seed = (1664525L * seed + 1013904223L) & 0xffffffff)
+                       int i, ni;
+
+                       for (i = 0, ni = indices.size(); i < ni; ++i)
+                       {
+                               btSwap(indices[i], indices[NEXTRAND % ni]);
+                       }
+               }
+               for (int k = 0; k < m_faceNodeContacts.size(); ++k)
+               {
+                       int idx = indices[k];
+                       btSoftBody::DeformableFaceNodeContact& c = m_faceNodeContacts[idx];
+                       btSoftBody::Node* node = c.m_node;
+                       btSoftBody::Face* face = c.m_face;
+                       const btVector3& w = c.m_bary;
+                       const btVector3& n = c.m_normal;
+                       btVector3 l = node->m_x - BaryEval(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, w);
+                       btScalar d = c.m_margin - n.dot(l);
+                       d = btMax(btScalar(0), d);
+
+                       const btVector3& va = node->m_v;
+                       btVector3 vb = BaryEval(face->m_n[0]->m_v, face->m_n[1]->m_v, face->m_n[2]->m_v, w);
+                       btVector3 vr = va - vb;
+                       const btScalar vn = btDot(vr, n);  // dn < 0 <==> opposing
+                       if (vn > OVERLAP_REDUCTION_FACTOR * d / timeStep)
+                               continue;
+                       btVector3 vt = vr - vn * n;
+                       btScalar I = 0;
+                       btScalar mass = node->m_im == 0 ? 0 : btScalar(1) / node->m_im;
+                       if (applySpringForce)
+                               I = -btMin(m_repulsionStiffness * timeStep * d, mass * (OVERLAP_REDUCTION_FACTOR * d / timeStep - vn));
+                       if (vn < 0)
+                               I += 0.5 * mass * vn;
+                       int face_penetration = 0, node_penetration = node->m_constrained;
+                       for (int i = 0; i < 3; ++i)
+                               face_penetration |= face->m_n[i]->m_constrained;
+                       btScalar I_tilde = 2.0 * I / (1.0 + w.length2());
+
+                       //             double the impulse if node or face is constrained.
+                       if (face_penetration > 0 || node_penetration > 0)
+                       {
+                               I_tilde *= 2.0;
+                       }
+                       if (face_penetration <= 0)
+                       {
+                               for (int j = 0; j < 3; ++j)
+                                       face->m_n[j]->m_v += w[j] * n * I_tilde * node->m_im;
+                       }
+                       if (node_penetration <= 0)
+                       {
+                               node->m_v -= I_tilde * node->m_im * n;
+                       }
+
+                       // apply frictional impulse
+                       btScalar vt_norm = vt.safeNorm();
+                       if (vt_norm > SIMD_EPSILON)
+                       {
+                               btScalar delta_vn = -2 * I * node->m_im;
+                               btScalar mu = c.m_friction;
+                               btScalar vt_new = btMax(btScalar(1) - mu * delta_vn / (vt_norm + SIMD_EPSILON), btScalar(0)) * vt_norm;
+                               I = 0.5 * mass * (vt_norm - vt_new);
+                               vt.safeNormalize();
+                               I_tilde = 2.0 * I / (1.0 + w.length2());
+                               //                 double the impulse if node or face is constrained.
+                               if (face_penetration > 0 || node_penetration > 0)
+                                       I_tilde *= 2.0;
+                               if (face_penetration <= 0)
+                               {
+                                       for (int j = 0; j < 3; ++j)
+                                               face->m_n[j]->m_v += w[j] * vt * I_tilde * (face->m_n[j])->m_im;
+                               }
+                               if (node_penetration <= 0)
+                               {
+                                       node->m_v -= I_tilde * node->m_im * vt;
+                               }
+                       }
+               }
+       }
+       virtual int calculateSerializeBufferSize() const;
+
+       ///fills the dataBuffer and returns the struct name (and 0 on failure)
+       virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
+};
+
+#endif  //_BT_SOFT_BODY_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..383f528
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletSoftBody/btSoftBody.h"
+
+#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)  //make this configurable
+
+btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
+       : btCollisionAlgorithm(ci),
+         m_isSwapped(isSwapped),
+         m_btSoftBodyTriangleCallback(ci.m_dispatcher1, body0Wrap, body1Wrap, isSwapped)
+{
+}
+
+btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm()
+{
+}
+
+btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped) : m_dispatcher(dispatcher),
+                                                                                                                                                                                                                                                                                                                                                                                m_dispatchInfoPtr(0)
+{
+       m_softBody = (isSwapped ? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject());
+       m_triBody = isSwapped ? body0Wrap->getCollisionObject() : body1Wrap->getCollisionObject();
+
+       //
+       // 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()
+{
+       for (int i = 0; i < m_shapeCache.size(); i++)
+       {
+               btTriIndex* tmp = m_shapeCache.getAtIndex(i);
+               btAssert(tmp);
+               btAssert(tmp->m_childShape);
+               m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape);  //necessary?
+               delete tmp->m_childShape;
+       }
+       m_shapeCache.clear();
+}
+
+void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
+{
+       //just for debugging purposes
+       //printf("triangle %d",m_triangleCount++);
+
+       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() & btIDebugDraw::DBG_DrawWireframe))
+       {
+               btVector3 color(1, 1, 0);
+               const btTransform& tr = m_triBody->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);
+       }
+
+       btTriIndex triIndex(partId, triangleIndex, 0);
+       btHashKey<btTriIndex> triKey(triIndex.getUid());
+
+       btTriIndex* shapeIndex = m_shapeCache[triKey];
+       if (shapeIndex)
+       {
+               btCollisionShape* tm = shapeIndex->m_childShape;
+               btAssert(tm);
+
+               //copy over user pointers to temporary shape
+               tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());
+
+               btCollisionObjectWrapper softBody(0, m_softBody->getCollisionShape(), m_softBody, m_softBody->getWorldTransform(), -1, -1);
+               //btCollisionObjectWrapper triBody(0,tm, ob, btTransform::getIdentity());//ob->getWorldTransform());//??
+               btCollisionObjectWrapper triBody(0, tm, m_triBody, m_triBody->getWorldTransform(), partId, triangleIndex);
+               ebtDispatcherQueryType algoType = m_resultOut->m_closestPointDistanceThreshold > 0 ? BT_CLOSEST_POINT_ALGORITHMS : BT_CONTACT_POINT_ALGORITHMS;
+               btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody, &triBody, 0, algoType);  //m_manifoldPtr);
+
+               colAlgo->processCollision(&softBody, &triBody, *m_dispatchInfoPtr, m_resultOut);
+               colAlgo->~btCollisionAlgorithm();
+               ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+
+               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(m_triBody->getCollisionShape()->getUserPointer());
+
+               btCollisionObjectWrapper softBody(0, m_softBody->getCollisionShape(), m_softBody, m_softBody->getWorldTransform(), -1, -1);
+               btCollisionObjectWrapper triBody(0, tm, m_triBody, m_triBody->getWorldTransform(), partId, triangleIndex);  //btTransform::getIdentity());//??
+
+               ebtDispatcherQueryType algoType = m_resultOut->m_closestPointDistanceThreshold > 0 ? BT_CLOSEST_POINT_ALGORITHMS : BT_CONTACT_POINT_ALGORITHMS;
+               btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody, &triBody, 0, algoType);  //m_manifoldPtr);
+
+               colAlgo->processCollision(&softBody, &triBody, *m_dispatchInfoPtr, m_resultOut);
+               colAlgo->~btCollisionAlgorithm();
+               ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+
+               triIndex.m_childShape = tm;
+               m_shapeCache.insert(triKey, triIndex);
+       }
+}
+
+void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle, const btCollisionObjectWrapper* triBodyWrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       m_dispatchInfoPtr = &dispatchInfo;
+       m_collisionMarginTriangle = collisionMarginTriangle + btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
+       m_resultOut = resultOut;
+
+       btVector3 aabbWorldSpaceMin, aabbWorldSpaceMax;
+       m_softBody->getAabb(aabbWorldSpaceMin, aabbWorldSpaceMax);
+       btVector3 halfExtents = (aabbWorldSpaceMax - aabbWorldSpaceMin) * btScalar(0.5);
+       btVector3 softBodyCenter = (aabbWorldSpaceMax + aabbWorldSpaceMin) * btScalar(0.5);
+
+       btTransform softTransform;
+       softTransform.setIdentity();
+       softTransform.setOrigin(softBodyCenter);
+
+       btTransform convexInTriangleSpace;
+       convexInTriangleSpace = triBodyWrap->getWorldTransform().inverse() * softTransform;
+       btTransformAabb(halfExtents, m_collisionMarginTriangle, convexInTriangleSpace, m_aabbMin, m_aabbMax);
+}
+
+void btSoftBodyConcaveCollisionAlgorithm::clearCache()
+{
+       m_btSoftBodyTriangleCallback.clearCache();
+}
+
+void btSoftBodyConcaveCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       //btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
+       const btCollisionObjectWrapper* triBody = m_isSwapped ? body0Wrap : body1Wrap;
+
+       if (triBody->getCollisionShape()->isConcave())
+       {
+               const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>(triBody->getCollisionShape());
+
+               //      if (convexBody->getCollisionShape()->isConvex())
+               {
+                       btScalar collisionMarginTriangle = concaveShape->getMargin();
+
+                       //                      resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
+                       m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle, triBody, dispatchInfo, resultOut);
+
+                       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/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..0dbceeb
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
+#define BT_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;
+class btCollisionShape;
+
+#include "LinearMath/btHashMap.h"
+
+#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h"  //for definition of MAX_NUM_PARTS_IN_BITS
+
+struct btTriIndex
+{
+       int m_PartIdTriangleIndex;
+       class btCollisionShape* m_childShape;
+
+       btTriIndex(int partId, int triangleIndex, btCollisionShape* shape)
+       {
+               m_PartIdTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+               m_childShape = shape;
+       }
+
+       int getTriangleIndex() const
+       {
+               // Get only the lower bits where the triangle index is stored
+               unsigned int x = 0;
+               unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
+               return (m_PartIdTriangleIndex & ~(y));
+       }
+       int getPartId() const
+       {
+               // Get only the highest bits where the part index is stored
+               return (m_PartIdTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
+       }
+       int getUid() const
+       {
+               return m_PartIdTriangleIndex;
+       }
+};
+
+///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;
+       const btCollisionObject* m_triBody;
+
+       btVector3 m_aabbMin;
+       btVector3 m_aabbMax;
+
+       btManifoldResult* m_resultOut;
+
+       btDispatcher* m_dispatcher;
+       const btDispatcherInfo* m_dispatchInfoPtr;
+       btScalar m_collisionMarginTriangle;
+
+       btHashMap<btHashKey<btTriIndex>, btTriIndex> m_shapeCache;
+
+public:
+       int m_triangleCount;
+
+       //      btPersistentManifold*   m_manifoldPtr;
+
+       btSoftBodyTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
+
+       void setTimeStepAndCounters(btScalar collisionMarginTriangle, const btCollisionObjectWrapper* triObjWrap, 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, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
+
+       virtual ~btSoftBodyConcaveCollisionAlgorithm();
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, 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, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
+                       return new (mem) btSoftBodyConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
+               }
+       };
+
+       struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
+                       return new (mem) btSoftBodyConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
+               }
+       };
+};
+
+#endif  //BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyData.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyData.h
new file mode 100644 (file)
index 0000000..8469c3c
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_FLOAT_DATA
+#define BT_SOFTBODY_FLOAT_DATA
+
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+struct SoftBodyMaterialData
+{
+       float m_linearStiffness;
+       float m_angularStiffness;
+       float m_volumeStiffness;
+       int m_flags;
+};
+
+struct SoftBodyNodeData
+{
+       SoftBodyMaterialData *m_material;
+       btVector3FloatData m_position;
+       btVector3FloatData m_previousPosition;
+       btVector3FloatData m_velocity;
+       btVector3FloatData m_accumulatedForce;
+       btVector3FloatData m_normal;
+       float m_inverseMass;
+       float m_area;
+       int m_attach;
+       int m_pad;
+};
+
+struct SoftBodyLinkData
+{
+       SoftBodyMaterialData *m_material;
+       int m_nodeIndices[2];  // Node pointers
+       float m_restLength;    // Rest length
+       int m_bbending;        // Bending link
+};
+
+struct SoftBodyFaceData
+{
+       btVector3FloatData m_normal;  // Normal
+       SoftBodyMaterialData *m_material;
+       int m_nodeIndices[3];  // Node pointers
+       float m_restArea;      // Rest area
+};
+
+struct SoftBodyTetraData
+{
+       btVector3FloatData m_c0[4];  // gradients
+       SoftBodyMaterialData *m_material;
+       int m_nodeIndices[4];  // Node pointers
+       float m_restVolume;    // Rest volume
+       float m_c1;            // (4*kVST)/(im0+im1+im2+im3)
+       float m_c2;            // m_c1/sum(|g0..3|^2)
+       int m_pad;
+};
+
+struct SoftRigidAnchorData
+{
+       btMatrix3x3FloatData m_c0;        // Impulse matrix
+       btVector3FloatData m_c1;          // Relative anchor
+       btVector3FloatData m_localFrame;  // Anchor position in body space
+       btRigidBodyData *m_rigidBody;
+       int m_nodeIndex;  // Node pointer
+       float m_c2;       // ima*dt
+};
+
+struct SoftBodyConfigData
+{
+       int m_aeroModel;                         // Aerodynamic model (default: V_Point)
+       float m_baumgarte;                       // Velocities correction factor (Baumgarte)
+       float m_damping;                         // Damping coefficient [0,1]
+       float m_drag;                            // Drag coefficient [0,+inf]
+       float m_lift;                            // Lift coefficient [0,+inf]
+       float m_pressure;                        // Pressure coefficient [-inf,+inf]
+       float m_volume;                          // Volume conversation coefficient [0,+inf]
+       float m_dynamicFriction;                 // Dynamic friction coefficient [0,1]
+       float m_poseMatch;                       // Pose matching coefficient [0,1]
+       float m_rigidContactHardness;            // Rigid contacts hardness [0,1]
+       float m_kineticContactHardness;          // Kinetic contacts hardness [0,1]
+       float m_softContactHardness;             // Soft contacts hardness [0,1]
+       float m_anchorHardness;                  // Anchors hardness [0,1]
+       float m_softRigidClusterHardness;        // Soft vs rigid hardness [0,1] (cluster only)
+       float m_softKineticClusterHardness;      // Soft vs kinetic hardness [0,1] (cluster only)
+       float m_softSoftClusterHardness;         // Soft vs soft hardness [0,1] (cluster only)
+       float m_softRigidClusterImpulseSplit;    // Soft vs rigid impulse split [0,1] (cluster only)
+       float m_softKineticClusterImpulseSplit;  // Soft vs rigid impulse split [0,1] (cluster only)
+       float m_softSoftClusterImpulseSplit;     // Soft vs rigid impulse split [0,1] (cluster only)
+       float m_maxVolume;                       // Maximum volume ratio for pose
+       float m_timeScale;                       // Time scale
+       int m_velocityIterations;                // Velocities solver iterations
+       int m_positionIterations;                // Positions solver iterations
+       int m_driftIterations;                   // Drift solver iterations
+       int m_clusterIterations;                 // Cluster solver iterations
+       int m_collisionFlags;                    // Collisions flags
+};
+
+struct SoftBodyPoseData
+{
+       btMatrix3x3FloatData m_rot;    // Rotation
+       btMatrix3x3FloatData m_scale;  // Scale
+       btMatrix3x3FloatData m_aqq;    // Base scaling
+       btVector3FloatData m_com;      // COM
+
+       btVector3FloatData *m_positions;  // Reference positions
+       float *m_weights;                 // Weights
+       int m_numPositions;
+       int m_numWeigts;
+
+       int m_bvolume;       // Is valid
+       int m_bframe;        // Is frame
+       float m_restVolume;  // Rest volume
+       int m_pad;
+};
+
+struct SoftBodyClusterData
+{
+       btTransformFloatData m_framexform;
+       btMatrix3x3FloatData m_locii;
+       btMatrix3x3FloatData m_invwi;
+       btVector3FloatData m_com;
+       btVector3FloatData m_vimpulses[2];
+       btVector3FloatData m_dimpulses[2];
+       btVector3FloatData m_lv;
+       btVector3FloatData m_av;
+
+       btVector3FloatData *m_framerefs;
+       int *m_nodeIndices;
+       float *m_masses;
+
+       int m_numFrameRefs;
+       int m_numNodes;
+       int m_numMasses;
+
+       float m_idmass;
+       float m_imass;
+       int m_nvimpulses;
+       int m_ndimpulses;
+       float m_ndamping;
+       float m_ldamping;
+       float m_adamping;
+       float m_matching;
+       float m_maxSelfCollisionImpulse;
+       float m_selfCollisionImpulseFactor;
+       int m_containsAnchor;
+       int m_collide;
+       int m_clusterIndex;
+};
+
+enum btSoftJointBodyType
+{
+       BT_JOINT_SOFT_BODY_CLUSTER = 1,
+       BT_JOINT_RIGID_BODY,
+       BT_JOINT_COLLISION_OBJECT
+};
+
+struct btSoftBodyJointData
+{
+       void *m_bodyA;
+       void *m_bodyB;
+       btVector3FloatData m_refs[2];
+       float m_cfm;
+       float m_erp;
+       float m_split;
+       int m_delete;
+       btVector3FloatData m_relPosition[2];  //linear
+       int m_bodyAtype;
+       int m_bodyBtype;
+       int m_jointType;
+       int m_pad;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btSoftBodyFloatData
+{
+       btCollisionObjectFloatData m_collisionObjectData;
+
+       SoftBodyPoseData *m_pose;
+       SoftBodyMaterialData **m_materials;
+       SoftBodyNodeData *m_nodes;
+       SoftBodyLinkData *m_links;
+       SoftBodyFaceData *m_faces;
+       SoftBodyTetraData *m_tetrahedra;
+       SoftRigidAnchorData *m_anchors;
+       SoftBodyClusterData *m_clusters;
+       btSoftBodyJointData *m_joints;
+
+       int m_numMaterials;
+       int m_numNodes;
+       int m_numLinks;
+       int m_numFaces;
+       int m_numTetrahedra;
+       int m_numAnchors;
+       int m_numClusters;
+       int m_numJoints;
+       SoftBodyConfigData m_config;
+};
+
+#endif  //BT_SOFTBODY_FLOAT_DATA
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyHelpers.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyHelpers.cpp
new file mode 100644 (file)
index 0000000..fbb7298
--- /dev/null
@@ -0,0 +1,1695 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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>
+#include <iostream>
+#include <iomanip> 
+#include <sstream>
+#include <string.h>
+#include <algorithm>
+#include "btSoftBodyHelpers.h"
+#include "LinearMath/btConvexHull.h"
+#include "LinearMath/btConvexHullComputer.h"
+#include <map>
+#include <vector>
+
+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);
+}
+
+#if 0
+//
+ inline static 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(btDot(a,btCross(b,c)));
+}
+#endif
+
+//
+#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;
+
+       /* 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;
+                               }
+#define USE_NEW_CONVEX_HULL_COMPUTER
+#ifdef USE_NEW_CONVEX_HULL_COMPUTER
+                               btConvexHullComputer computer;
+                               int stride = sizeof(btVector3);
+                               int count = vertices.size();
+                               btScalar shrink = 0.f;
+                               btScalar shrinkClamp = 0.f;
+                               computer.compute(&vertices[0].getX(), stride, count, shrink, shrinkClamp);
+                               for (int i = 0; i < computer.faces.size(); i++)
+                               {
+                                       int face = computer.faces[i];
+                                       //printf("face=%d\n",face);
+                                       const btConvexHullComputer::Edge* firstEdge = &computer.edges[face];
+                                       const btConvexHullComputer::Edge* edge = firstEdge->getNextEdgeOfFace();
+
+                                       int v0 = firstEdge->getSourceVertex();
+                                       int v1 = firstEdge->getTargetVertex();
+                                       while (edge != firstEdge)
+                                       {
+                                               int v2 = edge->getTargetVertex();
+                                               idraw->drawTriangle(computer.vertices[v0], computer.vertices[v1], computer.vertices[v2], color, 1);
+                                               edge = edge->getNextEdgeOfFace();
+                                               v0 = v1;
+                                               v1 = v2;
+                                       };
+                               }
+#else
+
+                               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);
+#endif
+                       }
+                       /* 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+btCross(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));
+               }
+       }
+       else
+       {
+               /* 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 *
+                                                                                                               (btDot(c.m_node->m_x, c.m_cti.m_normal) + c.m_cti.m_offset);
+                               const btVector3 x = btCross(c.m_cti.m_normal, axis[c.m_cti.m_normal.minAxis()]).normalized();
+                               const btVector3 y = btCross(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));
+                       }
+               }
+               /* 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);
+                       }
+               }
+               /* Tetras       */
+               if (0 != (drawflags & fDrawFlags::Tetras))
+               {
+                       const btScalar scl = (btScalar)0.8;
+                       const btScalar alp = (btScalar)1;
+                       const btVector3 col((btScalar)0.3, (btScalar)0.3, (btScalar)0.7);
+                       for (int i = 0; i < psb->m_tetras.size(); ++i)
+                       {
+                               const btSoftBody::Tetra& t = psb->m_tetras[i];
+                               if (0 == (t.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
+                               const btVector3 x[] = {t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x};
+                               const btVector3 c = (x[0] + x[1] + x[2] + x[3]) / 4;
+                               idraw->drawTriangle((x[0] - c) * scl + c, (x[1] - c) * scl + c, (x[2] - c) * scl + c, col, alp);
+                               idraw->drawTriangle((x[0] - c) * scl + c, (x[1] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
+                               idraw->drawTriangle((x[1] - c) * scl + c, (x[2] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
+                               idraw->drawTriangle((x[2] - c) * scl + c, (x[0] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
+                       }
+               }
+       }
+       /* 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));
+                       }
+               }
+       }
+
+       /* 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));
+                                       break;
+                               }
+                               default:
+                               {
+                               }
+                       }
+               }
+       }
+}
+
+//
+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);
+}
+
+//The btSoftBody object from the BulletSDK includes an array of Nodes and Links. These links appear
+// to be first set up to connect a node to between 5 and 6 of its neighbors [480 links],
+//and then to the rest of the nodes after the execution of the Floyd-Warshall graph algorithm
+//[another 930 links].
+//The way the links are stored by default, we have a number of cases where adjacent links share a node in common
+// - this leads to the creation of a data dependency through memory.
+//The PSolve_Links() function reads and writes nodes as it iterates over each link.
+//So, we now have the possibility of a data dependency between iteration X
+//that processes link L with iteration X+1 that processes link L+1
+//because L and L+1 have one node in common, and iteration X updates the positions of that node,
+//and iteration X+1 reads in the position of that shared node.
+//
+//Such a memory dependency limits the ability of a modern CPU to speculate beyond
+//a certain point because it has to respect a possible dependency
+//- this prevents the CPU from making full use of its out-of-order resources.
+//If we re-order the links such that we minimize the cases where a link L and L+1 share a common node,
+//we create a temporal gap between when the node position is written,
+//and when it is subsequently read. This in turn allows the CPU to continue execution without
+//risking a dependency violation. Such a reordering would result in significant speedups on
+//modern CPUs with lots of execution resources.
+//In our testing, we see it have a tremendous impact not only on the A7,
+//but also on all x86 cores that ship with modern Macs.
+//The attached source file includes a single function (ReoptimizeLinkOrder) which can be called on a
+//btSoftBody object in the solveConstraints() function before the actual solver is invoked,
+//or right after generateBendingConstraints() once we have all 1410 links.
+
+//===================================================================
+//
+//
+// This function takes in a list of interdependent Links and tries
+// to maximize the distance between calculation
+// of dependent links.  This increases the amount of parallelism that can
+// be exploited by out-of-order instruction processors with large but
+// (inevitably) finite instruction windows.
+//
+//===================================================================
+
+// A small structure to track lists of dependent link calculations
+class LinkDeps_t
+{
+public:
+       int value;         // A link calculation that is dependent on this one
+                                          // Positive values = "input A" while negative values = "input B"
+       LinkDeps_t* next;  // Next dependence in the list
+};
+typedef LinkDeps_t* LinkDepsPtr_t;
+
+// Dependency list constants
+#define REOP_NOT_DEPENDENT -1
+#define REOP_NODE_COMPLETE -2  // Must be less than REOP_NOT_DEPENDENT
+
+void btSoftBodyHelpers::ReoptimizeLinkOrder(btSoftBody* psb /* This can be replaced by a btSoftBody pointer */)
+{
+       int i, nLinks = psb->m_links.size(), nNodes = psb->m_nodes.size();
+       btSoftBody::Link* lr;
+       int ar, br;
+       btSoftBody::Node* node0 = &(psb->m_nodes[0]);
+       btSoftBody::Node* node1 = &(psb->m_nodes[1]);
+       LinkDepsPtr_t linkDep;
+       int readyListHead, readyListTail, linkNum, linkDepFrees, depLink;
+
+       // Allocate temporary buffers
+       int* nodeWrittenAt = new int[nNodes + 1];  // What link calculation produced this node's current values?
+       int* linkDepA = new int[nLinks];           // Link calculation input is dependent upon prior calculation #N
+       int* linkDepB = new int[nLinks];
+       int* readyList = new int[nLinks];                              // List of ready-to-process link calculations (# of links, maximum)
+       LinkDeps_t* linkDepFreeList = new LinkDeps_t[2 * nLinks];      // Dependent-on-me list elements (2x# of links, maximum)
+       LinkDepsPtr_t* linkDepListStarts = new LinkDepsPtr_t[nLinks];  // Start nodes of dependent-on-me lists, one for each link
+
+       // Copy the original, unsorted links to a side buffer
+       btSoftBody::Link* linkBuffer = new btSoftBody::Link[nLinks];
+       memcpy(linkBuffer, &(psb->m_links[0]), sizeof(btSoftBody::Link) * nLinks);
+
+       // Clear out the node setup and ready list
+       for (i = 0; i < nNodes + 1; i++)
+       {
+               nodeWrittenAt[i] = REOP_NOT_DEPENDENT;
+       }
+       for (i = 0; i < nLinks; i++)
+       {
+               linkDepListStarts[i] = NULL;
+       }
+       readyListHead = readyListTail = linkDepFrees = 0;
+
+       // Initial link analysis to set up data structures
+       for (i = 0; i < nLinks; i++)
+       {
+               // Note which prior link calculations we are dependent upon & build up dependence lists
+               lr = &(psb->m_links[i]);
+               ar = (lr->m_n[0] - node0) / (node1 - node0);
+               br = (lr->m_n[1] - node0) / (node1 - node0);
+               if (nodeWrittenAt[ar] > REOP_NOT_DEPENDENT)
+               {
+                       linkDepA[i] = nodeWrittenAt[ar];
+                       linkDep = &linkDepFreeList[linkDepFrees++];
+                       linkDep->value = i;
+                       linkDep->next = linkDepListStarts[nodeWrittenAt[ar]];
+                       linkDepListStarts[nodeWrittenAt[ar]] = linkDep;
+               }
+               else
+               {
+                       linkDepA[i] = REOP_NOT_DEPENDENT;
+               }
+               if (nodeWrittenAt[br] > REOP_NOT_DEPENDENT)
+               {
+                       linkDepB[i] = nodeWrittenAt[br];
+                       linkDep = &linkDepFreeList[linkDepFrees++];
+                       linkDep->value = -(i + 1);
+                       linkDep->next = linkDepListStarts[nodeWrittenAt[br]];
+                       linkDepListStarts[nodeWrittenAt[br]] = linkDep;
+               }
+               else
+               {
+                       linkDepB[i] = REOP_NOT_DEPENDENT;
+               }
+
+               // Add this link to the initial ready list, if it is not dependent on any other links
+               if ((linkDepA[i] == REOP_NOT_DEPENDENT) && (linkDepB[i] == REOP_NOT_DEPENDENT))
+               {
+                       readyList[readyListTail++] = i;
+                       linkDepA[i] = linkDepB[i] = REOP_NODE_COMPLETE;  // Probably not needed now
+               }
+
+               // Update the nodes to mark which ones are calculated by this link
+               nodeWrittenAt[ar] = nodeWrittenAt[br] = i;
+       }
+
+       // Process the ready list and create the sorted list of links
+       // -- By treating the ready list as a queue, we maximize the distance between any
+       //    inter-dependent node calculations
+       // -- All other (non-related) nodes in the ready list will automatically be inserted
+       //    in between each set of inter-dependent link calculations by this loop
+       i = 0;
+       while (readyListHead != readyListTail)
+       {
+               // Use ready list to select the next link to process
+               linkNum = readyList[readyListHead++];
+               // Copy the next-to-calculate link back into the original link array
+               psb->m_links[i++] = linkBuffer[linkNum];
+
+               // Free up any link inputs that are dependent on this one
+               linkDep = linkDepListStarts[linkNum];
+               while (linkDep)
+               {
+                       depLink = linkDep->value;
+                       if (depLink >= 0)
+                       {
+                               linkDepA[depLink] = REOP_NOT_DEPENDENT;
+                       }
+                       else
+                       {
+                               depLink = -depLink - 1;
+                               linkDepB[depLink] = REOP_NOT_DEPENDENT;
+                       }
+                       // Add this dependent link calculation to the ready list if *both* inputs are clear
+                       if ((linkDepA[depLink] == REOP_NOT_DEPENDENT) && (linkDepB[depLink] == REOP_NOT_DEPENDENT))
+                       {
+                               readyList[readyListTail++] = depLink;
+                               linkDepA[depLink] = linkDepB[depLink] = REOP_NODE_COMPLETE;  // Probably not needed now
+                       }
+                       linkDep = linkDep->next;
+               }
+       }
+
+       // Delete the temporary buffers
+       delete[] nodeWrittenAt;
+       delete[] linkDepA;
+       delete[] linkDepB;
+       delete[] readyList;
+       delete[] linkDepFreeList;
+       delete[] linkDepListStarts;
+       delete[] linkBuffer;
+}
+
+//
+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,
+                                                                                  btScalar perturbation)
+{
+#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);
+                       btScalar pert = perturbation * btScalar(rand()) / RAND_MAX;
+                       btVector3 temp1 = py1;
+                       temp1.setY(py1.getY() + pert);
+                       btVector3 temp = py0;
+                       pert = perturbation * btScalar(rand()) / RAND_MAX;
+                       temp.setY(py0.getY() + pert);
+                       x[IDX(ix, iy)] = lerp(temp, temp1, 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::CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
+                                                                                        const btVector3& corner00,
+                                                                                        const btVector3& corner10,
+                                                                                        const btVector3& corner01,
+                                                                                        const btVector3& corner11,
+                                                                                        int resx,
+                                                                                        int resy,
+                                                                                        int fixeds,
+                                                                                        bool gendiags,
+                                                                                        float* tex_coords)
+{
+       /*
+       *
+       *  corners:
+       *
+       *  [0][0]     corner00 ------- corner01   [resx][0]
+       *                |                |
+       *                |                |
+       *  [0][resy]  corner10 -------- corner11  [resx][resy]
+       *
+       *
+       *
+       *
+       *
+       *
+       *   "fixedgs" map:
+       *
+       *  corner00     -->   +1
+       *  corner01     -->   +2
+       *  corner10     -->   +4
+       *  corner11     -->   +8
+       *  upper middle -->  +16
+       *  left middle  -->  +32
+       *  right middle -->  +64
+       *  lower middle --> +128
+       *  center       --> +256
+       *
+       *
+       *   tex_coords size   (resx-1)*(resy-1)*12
+       *
+       *
+       *
+       *     SINGLE QUAD INTERNALS
+       *
+       *  1) btSoftBody's nodes and links,
+       *     diagonal link is optional ("gendiags")
+       *
+       *
+       *    node00 ------ node01
+       *      | .              
+       *      |   .            
+       *      |     .          
+       *      |       .        
+       *      |         .      
+       *    node10        node11
+       *
+       *
+       *
+       *   2) Faces:
+       *      two triangles,
+       *      UV Coordinates (hier example for single quad)
+       *      
+       *     (0,1)          (0,1)  (1,1)
+       *     1 |\            3 \-----| 2
+       *       | \              \    |
+       *       |  \              \   |
+       *       |   \              \  |
+       *       |    \              \ |
+       *     2 |-----\ 3            \| 1
+       *     (0,0)    (1,0)       (1,0)
+       *
+       *
+       *
+       *
+       *
+       *
+       */
+
+#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);
+       if (fixeds & 16) psb->setMass(IDX((rx - 1) / 2, 0), 0);
+       if (fixeds & 32) psb->setMass(IDX(0, (ry - 1) / 2), 0);
+       if (fixeds & 64) psb->setMass(IDX(rx - 1, (ry - 1) / 2), 0);
+       if (fixeds & 128) psb->setMass(IDX((rx - 1) / 2, ry - 1), 0);
+       if (fixeds & 256) psb->setMass(IDX((rx - 1) / 2, (ry - 1) / 2), 0);
+       delete[] x;
+       delete[] m;
+
+       int z = 0;
+       /* Create links and faces       */
+       for (iy = 0; iy < ry; ++iy)
+       {
+               for (int ix = 0; ix < rx; ++ix)
+               {
+                       const bool mdx = (ix + 1) < rx;
+                       const bool mdy = (iy + 1) < ry;
+
+                       int node00 = IDX(ix, iy);
+                       int node01 = IDX(ix + 1, iy);
+                       int node10 = IDX(ix, iy + 1);
+                       int node11 = IDX(ix + 1, iy + 1);
+
+                       if (mdx) psb->appendLink(node00, node01);
+                       if (mdy) psb->appendLink(node00, node10);
+                       if (mdx && mdy)
+                       {
+                               psb->appendFace(node00, node10, node11);
+                               if (tex_coords)
+                               {
+                                       tex_coords[z + 0] = CalculateUV(resx, resy, ix, iy, 0);
+                                       tex_coords[z + 1] = CalculateUV(resx, resy, ix, iy, 1);
+                                       tex_coords[z + 2] = CalculateUV(resx, resy, ix, iy, 0);
+                                       tex_coords[z + 3] = CalculateUV(resx, resy, ix, iy, 2);
+                                       tex_coords[z + 4] = CalculateUV(resx, resy, ix, iy, 3);
+                                       tex_coords[z + 5] = CalculateUV(resx, resy, ix, iy, 2);
+                               }
+                               psb->appendFace(node11, node01, node00);
+                               if (tex_coords)
+                               {
+                                       tex_coords[z + 6] = CalculateUV(resx, resy, ix, iy, 3);
+                                       tex_coords[z + 7] = CalculateUV(resx, resy, ix, iy, 2);
+                                       tex_coords[z + 8] = CalculateUV(resx, resy, ix, iy, 3);
+                                       tex_coords[z + 9] = CalculateUV(resx, resy, ix, iy, 1);
+                                       tex_coords[z + 10] = CalculateUV(resx, resy, ix, iy, 0);
+                                       tex_coords[z + 11] = CalculateUV(resx, resy, ix, iy, 1);
+                               }
+                               if (gendiags) psb->appendLink(node00, node11);
+                               z += 12;
+                       }
+               }
+       }
+       /* Finished     */
+#undef IDX
+       return (psb);
+}
+
+float btSoftBodyHelpers::CalculateUV(int resx, int resy, int ix, int iy, int id)
+{
+       /*
+       *
+       *
+       *    node00 --- node01
+       *      |          |
+       *    node10 --- node11
+       *
+       *
+       *   ID map:
+       *
+       *   node00 s --> 0
+       *   node00 t --> 1
+       *
+       *   node01 s --> 3
+       *   node01 t --> 1
+       *
+       *   node10 s --> 0
+       *   node10 t --> 2
+       *
+       *   node11 s --> 3
+       *   node11 t --> 2
+       *
+       *
+       */
+
+       float tc = 0.0f;
+       if (id == 0)
+       {
+               tc = (1.0f / ((resx - 1)) * ix);
+       }
+       else if (id == 1)
+       {
+               tc = (1.0f / ((resy - 1)) * (resy - 1 - iy));
+       }
+       else if (id == 2)
+       {
+               tc = (1.0f / ((resy - 1)) * (resy - 1 - iy - 1));
+       }
+       else if (id == 3)
+       {
+               tc = (1.0f / ((resx - 1)) * (ix + 1));
+       }
+       return tc;
+}
+//
+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, bool randomizeConstraints)
+{
+       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[j])] = true;
+                               psb->appendLink(idx[j], idx[k]);
+                       }
+               }
+#undef IDX
+               psb->appendFace(idx[0], idx[1], idx[2]);
+       }
+
+       if (randomizeConstraints)
+       {
+               psb->randomizeConstraints();
+       }
+
+       return (psb);
+}
+
+//
+btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
+                                                                                                       int nvertices, bool randomizeConstraints)
+{
+       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[] = {static_cast<int>(hres.m_Indices[i * 3 + 0]),
+                                                  static_cast<int>(hres.m_Indices[i * 3 + 1]),
+                                                  static_cast<int>(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);
+       if (randomizeConstraints)
+       {
+               psb->randomizeConstraints();
+       }
+       return (psb);
+}
+
+static int nextLine(const char* buffer)
+{
+       int numBytesRead = 0;
+
+       while (*buffer != '\n')
+       {
+               buffer++;
+               numBytesRead++;
+       }
+
+       if (buffer[0] == 0x0a)
+       {
+               buffer++;
+               numBytesRead++;
+       }
+       return numBytesRead;
+}
+
+/* Create from TetGen .ele, .face, .node data                                                  */
+btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
+                                                                                                       const char* ele,
+                                                                                                       const char* face,
+                                                                                                       const char* node,
+                                                                                                       bool bfacelinks,
+                                                                                                       bool btetralinks,
+                                                                                                       bool bfacesfromtetras)
+{
+       btAlignedObjectArray<btVector3> pos;
+       int nnode = 0;
+       int ndims = 0;
+       int nattrb = 0;
+       int hasbounds = 0;
+       int result = sscanf(node, "%d %d %d %d", &nnode, &ndims, &nattrb, &hasbounds);
+       result = sscanf(node, "%d %d %d %d", &nnode, &ndims, &nattrb, &hasbounds);
+       node += nextLine(node);
+
+       pos.resize(nnode);
+       for (int i = 0; i < pos.size(); ++i)
+       {
+               int index = 0;
+               //int                   bound=0;
+               float x, y, z;
+               sscanf(node, "%d %f %f %f", &index, &x, &y, &z);
+
+               //      sn>>index;
+               //      sn>>x;sn>>y;sn>>z;
+               node += nextLine(node);
+
+               //for(int j=0;j<nattrb;++j)
+               //      sn>>a;
+
+               //if(hasbounds)
+               //      sn>>bound;
+
+               pos[index].setX(btScalar(x));
+               pos[index].setY(btScalar(y));
+               pos[index].setZ(btScalar(z));
+       }
+       btSoftBody* psb = new btSoftBody(&worldInfo, nnode, &pos[0], 0);
+#if 0
+if(face&&face[0])
+       {
+       int                                                             nface=0;
+       sf>>nface;sf>>hasbounds;
+       for(int i=0;i<nface;++i)
+               {
+               int                     index=0;
+               int                     bound=0;
+               int                     ni[3];
+               sf>>index;
+               sf>>ni[0];sf>>ni[1];sf>>ni[2];
+               sf>>bound;
+               psb->appendFace(ni[0],ni[1],ni[2]);     
+               if(btetralinks)
+                       {
+                       psb->appendLink(ni[0],ni[1],0,true);
+                       psb->appendLink(ni[1],ni[2],0,true);
+                       psb->appendLink(ni[2],ni[0],0,true);
+                       }
+               }
+       }
+#endif
+
+       if (ele && ele[0])
+       {
+               int ntetra = 0;
+               int ncorner = 0;
+               int neattrb = 0;
+               sscanf(ele, "%d %d %d", &ntetra, &ncorner, &neattrb);
+               ele += nextLine(ele);
+
+               //se>>ntetra;se>>ncorner;se>>neattrb;
+               for (int i = 0; i < ntetra; ++i)
+               {
+                       int index = 0;
+                       int ni[4];
+
+                       //se>>index;
+                       //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
+                       sscanf(ele, "%d %d %d %d %d", &index, &ni[0], &ni[1], &ni[2], &ni[3]);
+                       ele += nextLine(ele);
+                       //for(int j=0;j<neattrb;++j)
+                       //      se>>a;
+                       psb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
+                       if (btetralinks)
+                       {
+                               psb->appendLink(ni[0], ni[1], 0, true);
+                               psb->appendLink(ni[1], ni[2], 0, true);
+                               psb->appendLink(ni[2], ni[0], 0, true);
+                               psb->appendLink(ni[0], ni[3], 0, true);
+                               psb->appendLink(ni[1], ni[3], 0, true);
+                               psb->appendLink(ni[2], ni[3], 0, true);
+                       }
+               }
+       }
+       psb->initializeDmInverse();
+       psb->m_tetraScratches.resize(psb->m_tetras.size());
+       psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
+       printf("Nodes:  %u\r\n", psb->m_nodes.size());
+       printf("Links:  %u\r\n", psb->m_links.size());
+       printf("Faces:  %u\r\n", psb->m_faces.size());
+       printf("Tetras: %u\r\n", psb->m_tetras.size());
+       return (psb);
+}
+
+btSoftBody* btSoftBodyHelpers::CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file)
+{
+       std::ifstream fs;
+       fs.open(vtk_file);
+       btAssert(fs);
+
+       typedef btAlignedObjectArray<int> Index;
+       std::string line;
+       btAlignedObjectArray<btVector3> X;
+       btVector3 position;
+       btAlignedObjectArray<Index> indices;
+       bool reading_points = false;
+       bool reading_tets = false;
+       size_t n_points = 0;
+       size_t n_tets = 0;
+       size_t x_count = 0;
+       size_t indices_count = 0;
+       while (std::getline(fs, line))
+       {
+               std::stringstream ss(line);
+               if (line.size() == (size_t)(0))
+               {
+               }
+               else if (line.substr(0, 6) == "POINTS")
+               {
+                       reading_points = true;
+                       reading_tets = false;
+                       ss.ignore(128, ' ');  // ignore "POINTS"
+                       ss >> n_points;
+                       X.resize(n_points);
+               }
+               else if (line.substr(0, 5) == "CELLS")
+               {
+                       reading_points = false;
+                       reading_tets = true;
+                       ss.ignore(128, ' ');  // ignore "CELLS"
+                       ss >> n_tets;
+                       indices.resize(n_tets);
+               }
+               else if (line.substr(0, 10) == "CELL_TYPES")
+               {
+                       reading_points = false;
+                       reading_tets = false;
+               }
+               else if (reading_points)
+               {
+                       btScalar p;
+                       ss >> p;
+                       position.setX(p);
+                       ss >> p;
+                       position.setY(p);
+                       ss >> p;
+                       position.setZ(p);
+                       //printf("v %f %f %f\n", position.getX(), position.getY(), position.getZ());
+                       X[x_count++] = position;
+               }
+               else if (reading_tets)
+               {
+                       int d;
+                       ss >> d;
+                       if (d != 4)
+                       {
+                               printf("Load deformable failed: Only Tetrahedra are supported in VTK file.\n");
+                               fs.close();
+                               return 0;
+                       }
+                       ss.ignore(128, ' ');  // ignore "4"
+                       Index tet;
+                       tet.resize(4);
+                       for (size_t i = 0; i < 4; i++)
+                       {
+                               ss >> tet[i];
+                               //printf("%d ", tet[i]);
+                       }
+                       //printf("\n");
+                       indices[indices_count++] = tet;
+               }
+       }
+       btSoftBody* psb = new btSoftBody(&worldInfo, n_points, &X[0], 0);
+
+       for (int i = 0; i < n_tets; ++i)
+       {
+               const Index& ni = indices[i];
+               psb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
+               {
+                       psb->appendLink(ni[0], ni[1], 0, true);
+                       psb->appendLink(ni[1], ni[2], 0, true);
+                       psb->appendLink(ni[2], ni[0], 0, true);
+                       psb->appendLink(ni[0], ni[3], 0, true);
+                       psb->appendLink(ni[1], ni[3], 0, true);
+                       psb->appendLink(ni[2], ni[3], 0, true);
+               }
+       }
+
+       generateBoundaryFaces(psb);
+       psb->initializeDmInverse();
+       psb->m_tetraScratches.resize(psb->m_tetras.size());
+       psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
+       printf("Nodes:  %u\r\n", psb->m_nodes.size());
+       printf("Links:  %u\r\n", psb->m_links.size());
+       printf("Faces:  %u\r\n", psb->m_faces.size());
+       printf("Tetras: %u\r\n", psb->m_tetras.size());
+
+       fs.close();
+       return psb;
+}
+
+void btSoftBodyHelpers::generateBoundaryFaces(btSoftBody* psb)
+{
+       int counter = 0;
+       for (int i = 0; i < psb->m_nodes.size(); ++i)
+       {
+               psb->m_nodes[i].index = counter++;
+       }
+       typedef btAlignedObjectArray<int> Index;
+       btAlignedObjectArray<Index> indices;
+       indices.resize(psb->m_tetras.size());
+       for (int i = 0; i < indices.size(); ++i)
+       {
+               Index index;
+               index.push_back(psb->m_tetras[i].m_n[0]->index);
+               index.push_back(psb->m_tetras[i].m_n[1]->index);
+               index.push_back(psb->m_tetras[i].m_n[2]->index);
+               index.push_back(psb->m_tetras[i].m_n[3]->index);
+               indices[i] = index;
+       }
+
+       std::map<std::vector<int>, std::vector<int> > dict;
+       for (int i = 0; i < indices.size(); ++i)
+       {
+               for (int j = 0; j < 4; ++j)
+               {
+                       std::vector<int> f;
+                       if (j == 0)
+                       {
+                               f.push_back(indices[i][1]);
+                               f.push_back(indices[i][0]);
+                               f.push_back(indices[i][2]);
+                       }
+                       if (j == 1)
+                       {
+                               f.push_back(indices[i][3]);
+                               f.push_back(indices[i][0]);
+                               f.push_back(indices[i][1]);
+                       }
+                       if (j == 2)
+                       {
+                               f.push_back(indices[i][3]);
+                               f.push_back(indices[i][1]);
+                               f.push_back(indices[i][2]);
+                       }
+                       if (j == 3)
+                       {
+                               f.push_back(indices[i][2]);
+                               f.push_back(indices[i][0]);
+                               f.push_back(indices[i][3]);
+                       }
+                       std::vector<int> f_sorted = f;
+                       std::sort(f_sorted.begin(), f_sorted.end());
+                       if (dict.find(f_sorted) != dict.end())
+                       {
+                               dict.erase(f_sorted);
+                       }
+                       else
+                       {
+                               dict.insert(std::make_pair(f_sorted, f));
+                       }
+               }
+       }
+
+       for (std::map<std::vector<int>, std::vector<int> >::iterator it = dict.begin(); it != dict.end(); ++it)
+       {
+               std::vector<int> f = it->second;
+               psb->appendFace(f[0], f[1], f[2]);
+               //printf("f %d %d %d\n", f[0] + 1, f[1] + 1, f[2] + 1);
+       }
+}
+
+//Write the surface mesh to an obj file.
+void btSoftBodyHelpers::writeObj(const char* filename, const btSoftBody* psb)
+{
+       std::ofstream fs;
+       fs.open(filename);
+       btAssert(fs);
+
+       if (psb->m_tetras.size() > 0)
+       {
+               // For tetrahedron mesh, we need to re-index the surface mesh for it to be in obj file/
+               std::map<int, int> dict;
+               for (int i = 0; i < psb->m_faces.size(); i++)
+               {
+                       for (int d = 0; d < 3; d++)
+                       {
+                               int index = psb->m_faces[i].m_n[d]->index;
+                               if (dict.find(index) == dict.end())
+                               {
+                                       int dict_size = dict.size();
+                                       dict[index] = dict_size;
+                                       fs << "v";
+                                       for (int k = 0; k < 3; k++)
+                                       {
+                                               fs << " " << psb->m_nodes[index].m_x[k];
+                                       }
+                                       fs << "\n";
+                               }
+                       }
+               }
+               // Write surface mesh.
+               for (int i = 0; i < psb->m_faces.size(); ++i)
+               {
+                       fs << "f";
+                       for (int n = 0; n < 3; n++)
+                       {
+                               fs << " " << dict[psb->m_faces[i].m_n[n]->index] + 1;
+                       }
+                       fs << "\n";
+               }
+       }
+       else
+       {
+               // For trimesh, directly write out all the nodes and faces.xs
+               for (int i = 0; i < psb->m_nodes.size(); ++i)
+               {
+                       fs << "v";
+                       for (int d = 0; d < 3; d++)
+                       {
+                               fs << " " << psb->m_nodes[i].m_x[d];
+                       }
+                       fs << "\n";
+               }
+
+               for (int i = 0; i < psb->m_faces.size(); ++i)
+               {
+                       fs << "f";
+                       for (int n = 0; n < 3; n++)
+                       {
+                               fs << " " << psb->m_faces[i].m_n[n]->index + 1;
+                       }
+                       fs << "\n";
+               }
+       }
+       fs.close();
+}
+
+
+void btSoftBodyHelpers::writeState(const char* file, const btSoftBody* psb)
+{
+       std::ofstream fs;
+       fs.open(file);
+       btAssert(fs);
+       fs << std::scientific << std::setprecision(16);
+
+       // Only write out for trimesh, directly write out all the nodes and faces.xs
+       for (int i = 0; i < psb->m_nodes.size(); ++i)
+       {
+               fs << "q";
+               for (int d = 0; d < 3; d++)
+               {
+                       fs << " " << psb->m_nodes[i].m_q[d];
+               }
+               fs << "\n";
+       }
+
+       for (int i = 0; i < psb->m_nodes.size(); ++i)
+       {
+               fs << "v";
+               for (int d = 0; d < 3; d++)
+               {
+                       fs << " " << psb->m_nodes[i].m_v[d];
+               }
+               fs << "\n";
+       }
+       fs.close();
+}
+
+void btSoftBodyHelpers::duplicateFaces(const char* filename, const btSoftBody* psb)
+{
+       std::ifstream fs_read;
+       fs_read.open(filename);
+       std::string line;
+       btVector3 pos;
+       btAlignedObjectArray<btAlignedObjectArray<int> > additional_faces;
+       while (std::getline(fs_read, line))
+       {
+               std::stringstream ss(line);
+               if (line[0] == 'v')
+               {
+               }
+               else if (line[0] == 'f')
+               {
+                       ss.ignore();
+                       int id0, id1, id2;
+                       ss >> id0;
+                       ss >> id1;
+                       ss >> id2;
+                       btAlignedObjectArray<int> new_face;
+                       new_face.push_back(id1);
+                       new_face.push_back(id0);
+                       new_face.push_back(id2);
+                       additional_faces.push_back(new_face);
+               }
+       }
+       fs_read.close();
+
+       std::ofstream fs_write;
+       fs_write.open(filename, std::ios_base::app);
+       for (int i = 0; i < additional_faces.size(); ++i)
+       {
+               fs_write << "f";
+               for (int n = 0; n < 3; n++)
+               {
+                       fs_write << " " << additional_faces[i][n];
+               }
+               fs_write << "\n";
+       }
+       fs_write.close();
+}
+
+// Given a simplex with vertices a,b,c,d, find the barycentric weights of p in this simplex
+void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary)
+{
+       btVector3 vap = p - a;
+       btVector3 vbp = p - b;
+
+       btVector3 vab = b - a;
+       btVector3 vac = c - a;
+       btVector3 vad = d - a;
+
+       btVector3 vbc = c - b;
+       btVector3 vbd = d - b;
+       btScalar va6 = (vbp.cross(vbd)).dot(vbc);
+       btScalar vb6 = (vap.cross(vac)).dot(vad);
+       btScalar vc6 = (vap.cross(vad)).dot(vab);
+       btScalar vd6 = (vap.cross(vab)).dot(vac);
+       btScalar v6 = btScalar(1) / (vab.cross(vac).dot(vad));
+       bary = btVector4(va6 * v6, vb6 * v6, vc6 * v6, vd6 * v6);
+}
+
+// Given a simplex with vertices a,b,c, find the barycentric weights of p in this simplex. bary[3] = 0.
+void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& p, btVector4& bary)
+{
+       btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
+       btScalar d00 = btDot(v0, v0);
+       btScalar d01 = btDot(v0, v1);
+       btScalar d11 = btDot(v1, v1);
+       btScalar d20 = btDot(v2, v0);
+       btScalar d21 = btDot(v2, v1);
+       btScalar invDenom = 1.0 / (d00 * d11 - d01 * d01);
+       bary[1] = (d11 * d20 - d01 * d21) * invDenom;
+       bary[2] = (d00 * d21 - d01 * d20) * invDenom;
+       bary[0] = 1.0 - bary[1] - bary[2];
+       bary[3] = 0;
+}
+
+// Iterate through all render nodes to find the simulation tetrahedron that contains the render node and record the barycentric weights
+// If the node is not inside any tetrahedron, assign it to the tetrahedron in which the node has the least negative barycentric weight
+void btSoftBodyHelpers::interpolateBarycentricWeights(btSoftBody* psb)
+{
+       psb->m_z.resize(0);
+       psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
+       psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
+       for (int i = 0; i < psb->m_renderNodes.size(); ++i)
+       {
+               const btVector3& p = psb->m_renderNodes[i].m_x;
+               btVector4 bary;
+               btVector4 optimal_bary;
+               btScalar min_bary_weight = -1e3;
+               btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
+               for (int j = 0; j < psb->m_tetras.size(); ++j)
+               {
+                       const btSoftBody::Tetra& t = psb->m_tetras[j];
+                       getBarycentricWeights(t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x, p, bary);
+                       btScalar new_min_bary_weight = bary[0];
+                       for (int k = 1; k < 4; ++k)
+                       {
+                               new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
+                       }
+                       if (new_min_bary_weight > min_bary_weight)
+                       {
+                               btAlignedObjectArray<const btSoftBody::Node*> parents;
+                               parents.push_back(t.m_n[0]);
+                               parents.push_back(t.m_n[1]);
+                               parents.push_back(t.m_n[2]);
+                               parents.push_back(t.m_n[3]);
+                               optimal_parents = parents;
+                               optimal_bary = bary;
+                               min_bary_weight = new_min_bary_weight;
+                               // stop searching if p is inside the tetrahedron at hand
+                               if (bary[0] >= 0. && bary[1] >= 0. && bary[2] >= 0. && bary[3] >= 0.)
+                               {
+                                       break;
+                               }
+                       }
+               }
+               psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
+               psb->m_renderNodesParents[i] = optimal_parents;
+       }
+}
+
+// Iterate through all render nodes to find the simulation triangle that's closest to the node in the barycentric sense.
+void btSoftBodyHelpers::extrapolateBarycentricWeights(btSoftBody* psb)
+{
+       psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
+       psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
+       psb->m_z.resize(psb->m_renderNodes.size());
+       for (int i = 0; i < psb->m_renderNodes.size(); ++i)
+       {
+               const btVector3& p = psb->m_renderNodes[i].m_x;
+               btVector4 bary;
+               btVector4 optimal_bary;
+               btScalar min_bary_weight = -SIMD_INFINITY;
+               btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
+               btScalar dist = 0, optimal_dist = 0;
+               for (int j = 0; j < psb->m_faces.size(); ++j)
+               {
+                       const btSoftBody::Face& f = psb->m_faces[j];
+                       btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
+                       btVector3 unit_n = n.normalized();
+                       dist = (p - f.m_n[0]->m_x).dot(unit_n);
+                       btVector3 proj_p = p - dist * unit_n;
+                       getBarycentricWeights(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, proj_p, bary);
+                       btScalar new_min_bary_weight = bary[0];
+                       for (int k = 1; k < 3; ++k)
+                       {
+                               new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
+                       }
+
+                       // p is out of the current best triangle, we found a traingle that's better
+                       bool better_than_closest_outisde = (new_min_bary_weight > min_bary_weight && min_bary_weight < 0.);
+                       // p is inside of the current best triangle, we found a triangle that's better
+                       bool better_than_best_inside = (new_min_bary_weight >= 0 && min_bary_weight >= 0 && btFabs(dist) < btFabs(optimal_dist));
+
+                       if (better_than_closest_outisde || better_than_best_inside)
+                       {
+                               btAlignedObjectArray<const btSoftBody::Node*> parents;
+                               parents.push_back(f.m_n[0]);
+                               parents.push_back(f.m_n[1]);
+                               parents.push_back(f.m_n[2]);
+                               optimal_parents = parents;
+                               optimal_bary = bary;
+                               optimal_dist = dist;
+                               min_bary_weight = new_min_bary_weight;
+                       }
+               }
+               psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
+               psb->m_renderNodesParents[i] = optimal_parents;
+               psb->m_z[i] = optimal_dist;
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyHelpers.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyHelpers.h
new file mode 100644 (file)
index 0000000..e48d7b7
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SOFT_BODY_HELPERS_H
+#define BT_SOFT_BODY_HELPERS_H
+
+#include "btSoftBody.h"
+#include <fstream>
+#include <string>
+//
+// 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,
+                                                                  btScalar perturbation = 0.);
+       /* Create a patch with UV Texture Coordinates   */
+       static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
+                                                                        const btVector3& corner00,
+                                                                        const btVector3& corner10,
+                                                                        const btVector3& corner01,
+                                                                        const btVector3& corner11,
+                                                                        int resx,
+                                                                        int resy,
+                                                                        int fixeds,
+                                                                        bool gendiags,
+                                                                        float* tex_coords = 0);
+       static float CalculateUV(int resx, int resy, int ix, int iy, int id);
+       /* 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,
+                                                                                bool randomizeConstraints = true);
+       /* Create from convex-hull                                                                                              */
+       static btSoftBody* CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo,
+                                                                                       const btVector3* vertices,
+                                                                                       int nvertices,
+                                                                                       bool randomizeConstraints = true);
+
+       /* Export TetGen compatible .smesh file                                                                 */
+       //      static void                             ExportAsSMeshFile(      btSoftBody* psb,
+       //                                                                                              const char* filename);
+       /* Create from TetGen .ele, .face, .node files                                                  */
+       //      static btSoftBody*              CreateFromTetGenFile(   btSoftBodyWorldInfo& worldInfo,
+       //                                                                                                      const char* ele,
+       //                                                                                                      const char* face,
+       //                                                                                                      const char* node,
+       //                                                                                                      bool bfacelinks,
+       //                                                                                                      bool btetralinks,
+       //                                                                                                      bool bfacesfromtetras);
+       /* Create from TetGen .ele, .face, .node data                                                   */
+       static btSoftBody* CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
+                                                                                       const char* ele,
+                                                                                       const char* face,
+                                                                                       const char* node,
+                                                                                       bool bfacelinks,
+                                                                                       bool btetralinks,
+                                                                                       bool bfacesfromtetras);
+       static btSoftBody* CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file);
+
+       static void writeObj(const char* file, const btSoftBody* psb);
+
+       static void writeState(const char* file, const btSoftBody* psb);
+
+  //this code cannot be here, dependency on example code are not allowed
+       //static std::string loadDeformableState(btAlignedObjectArray<btVector3>& qs, btAlignedObjectArray<btVector3>& vs, const char* filename, CommonFileIOInterface* fileIO);
+
+       static void getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary);
+
+       static void getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& p, btVector4& bary);
+
+       static void interpolateBarycentricWeights(btSoftBody* psb);
+
+       static void extrapolateBarycentricWeights(btSoftBody* psb);
+
+       static void generateBoundaryFaces(btSoftBody* psb);
+
+       static void duplicateFaces(const char* filename, const btSoftBody* psb);
+       /// Sort the list of links to move link calculations that are dependent upon earlier
+       /// ones as far as possible away from the calculation of those values
+       /// This tends to make adjacent loop iterations not dependent upon one another,
+       /// so out-of-order processors can execute instructions from multiple iterations at once
+       static void ReoptimizeLinkOrder(btSoftBody* psb);
+};
+
+#endif  //BT_SOFT_BODY_HELPERS_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyInternals.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyInternals.h
new file mode 100644 (file)
index 0000000..1372586
--- /dev/null
@@ -0,0 +1,2146 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "LinearMath/btPolarDecomposition.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
+#include <string.h>  //for memset
+#include <cmath>
+#include "poly34.h"
+
+// Given a multibody link, a contact point and a contact direction, fill in the jacobian data needed to calculate the velocity change given an impulse in the contact direction
+static SIMD_FORCE_INLINE void findJacobian(const btMultiBodyLinkCollider* multibodyLinkCol,
+                                                                                  btMultiBodyJacobianData& jacobianData,
+                                                                                  const btVector3& contact_point,
+                                                                                  const btVector3& dir)
+{
+       const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+       jacobianData.m_jacobians.resize(ndof);
+       jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
+       btScalar* jac = &jacobianData.m_jacobians[0];
+
+       multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, contact_point, dir, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
+       multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], &jacobianData.m_deltaVelocitiesUnitImpulse[0], jacobianData.scratch_r, jacobianData.scratch_v);
+}
+static SIMD_FORCE_INLINE btVector3 generateUnitOrthogonalVector(const btVector3& u)
+{
+       btScalar ux = u.getX();
+       btScalar uy = u.getY();
+       btScalar uz = u.getZ();
+       btScalar ax = std::abs(ux);
+       btScalar ay = std::abs(uy);
+       btScalar az = std::abs(uz);
+       btVector3 v;
+       if (ax <= ay && ax <= az)
+               v = btVector3(0, -uz, uy);
+       else if (ay <= ax && ay <= az)
+               v = btVector3(-uz, 0, ux);
+       else
+               v = btVector3(-uy, ux, 0);
+       v.normalize();
+       return v;
+}
+
+static SIMD_FORCE_INLINE bool proximityTest(const btVector3& x1, const btVector3& x2, const btVector3& x3, const btVector3& x4, const btVector3& normal, const btScalar& mrg, btVector3& bary)
+{
+       btVector3 x43 = x4 - x3;
+       if (std::abs(x43.dot(normal)) > mrg)
+               return false;
+       btVector3 x13 = x1 - x3;
+       btVector3 x23 = x2 - x3;
+       btScalar a11 = x13.length2();
+       btScalar a22 = x23.length2();
+       btScalar a12 = x13.dot(x23);
+       btScalar b1 = x13.dot(x43);
+       btScalar b2 = x23.dot(x43);
+       btScalar det = a11 * a22 - a12 * a12;
+       if (det < SIMD_EPSILON)
+               return false;
+       btScalar w1 = (b1 * a22 - b2 * a12) / det;
+       btScalar w2 = (b2 * a11 - b1 * a12) / det;
+       btScalar w3 = 1 - w1 - w2;
+       btScalar delta = mrg / std::sqrt(0.5 * std::abs(x13.cross(x23).safeNorm()));
+       bary = btVector3(w1, w2, w3);
+       for (int i = 0; i < 3; ++i)
+       {
+               if (bary[i] < -delta || bary[i] > 1 + delta)
+                       return false;
+       }
+       return true;
+}
+static const int KDOP_COUNT = 13;
+static btVector3 dop[KDOP_COUNT] = {btVector3(1, 0, 0),
+                                                                       btVector3(0, 1, 0),
+                                                                       btVector3(0, 0, 1),
+                                                                       btVector3(1, 1, 0),
+                                                                       btVector3(1, 0, 1),
+                                                                       btVector3(0, 1, 1),
+                                                                       btVector3(1, -1, 0),
+                                                                       btVector3(1, 0, -1),
+                                                                       btVector3(0, 1, -1),
+                                                                       btVector3(1, 1, 1),
+                                                                       btVector3(1, -1, 1),
+                                                                       btVector3(1, 1, -1),
+                                                                       btVector3(1, -1, -1)};
+
+static inline int getSign(const btVector3& n, const btVector3& x)
+{
+       btScalar d = n.dot(x);
+       if (d > SIMD_EPSILON)
+               return 1;
+       if (d < -SIMD_EPSILON)
+               return -1;
+       return 0;
+}
+
+static SIMD_FORCE_INLINE bool hasSeparatingPlane(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+       btVector3 hex[6] = {face->m_n[0]->m_x - node->m_x,
+                                               face->m_n[1]->m_x - node->m_x,
+                                               face->m_n[2]->m_x - node->m_x,
+                                               face->m_n[0]->m_x + dt * face->m_n[0]->m_v - node->m_x,
+                                               face->m_n[1]->m_x + dt * face->m_n[1]->m_v - node->m_x,
+                                               face->m_n[2]->m_x + dt * face->m_n[2]->m_v - node->m_x};
+       btVector3 segment = dt * node->m_v;
+       for (int i = 0; i < KDOP_COUNT; ++i)
+       {
+               int s = getSign(dop[i], segment);
+               int j = 0;
+               for (; j < 6; ++j)
+               {
+                       if (getSign(dop[i], hex[j]) == s)
+                               break;
+               }
+               if (j == 6)
+                       return true;
+       }
+       return false;
+}
+
+static SIMD_FORCE_INLINE bool nearZero(const btScalar& a)
+{
+       return (a > -SAFE_EPSILON && a < SAFE_EPSILON);
+}
+static SIMD_FORCE_INLINE bool sameSign(const btScalar& a, const btScalar& b)
+{
+       return (nearZero(a) || nearZero(b) || (a > SAFE_EPSILON && b > SAFE_EPSILON) || (a < -SAFE_EPSILON && b < -SAFE_EPSILON));
+}
+static SIMD_FORCE_INLINE bool diffSign(const btScalar& a, const btScalar& b)
+{
+       return !sameSign(a, b);
+}
+inline btScalar evaluateBezier2(const btScalar& p0, const btScalar& p1, const btScalar& p2, const btScalar& t, const btScalar& s)
+{
+       btScalar s2 = s * s;
+       btScalar t2 = t * t;
+
+       return p0 * s2 + p1 * btScalar(2.0) * s * t + p2 * t2;
+}
+inline btScalar evaluateBezier(const btScalar& p0, const btScalar& p1, const btScalar& p2, const btScalar& p3, const btScalar& t, const btScalar& s)
+{
+       btScalar s2 = s * s;
+       btScalar s3 = s2 * s;
+       btScalar t2 = t * t;
+       btScalar t3 = t2 * t;
+
+       return p0 * s3 + p1 * btScalar(3.0) * s2 * t + p2 * btScalar(3.0) * s * t2 + p3 * t3;
+}
+static SIMD_FORCE_INLINE bool getSigns(bool type_c, const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& t0, const btScalar& t1, btScalar& lt0, btScalar& lt1)
+{
+       if (sameSign(t0, t1))
+       {
+               lt0 = t0;
+               lt1 = t0;
+               return true;
+       }
+
+       if (type_c || diffSign(k0, k3))
+       {
+               btScalar ft = evaluateBezier(k0, k1, k2, k3, t0, -t1);
+               if (t0 < -0)
+                       ft = -ft;
+
+               if (sameSign(ft, k0))
+               {
+                       lt0 = t1;
+                       lt1 = t1;
+               }
+               else
+               {
+                       lt0 = t0;
+                       lt1 = t0;
+               }
+               return true;
+       }
+
+       if (!type_c)
+       {
+               btScalar ft = evaluateBezier(k0, k1, k2, k3, t0, -t1);
+               if (t0 < -0)
+                       ft = -ft;
+
+               if (diffSign(ft, k0))
+               {
+                       lt0 = t0;
+                       lt1 = t1;
+                       return true;
+               }
+
+               btScalar fk = evaluateBezier2(k1 - k0, k2 - k1, k3 - k2, t0, -t1);
+
+               if (sameSign(fk, k1 - k0))
+                       lt0 = lt1 = t1;
+               else
+                       lt0 = lt1 = t0;
+
+               return true;
+       }
+       return false;
+}
+
+static SIMD_FORCE_INLINE void getBernsteinCoeff(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, btScalar& k0, btScalar& k1, btScalar& k2, btScalar& k3)
+{
+       const btVector3& n0 = face->m_n0;
+       const btVector3& n1 = face->m_n1;
+       btVector3 n_hat = n0 + n1 - face->m_vn;
+       btVector3 p0ma0 = node->m_x - face->m_n[0]->m_x;
+       btVector3 p1ma1 = node->m_q - face->m_n[0]->m_q;
+       k0 = (p0ma0).dot(n0) * 3.0;
+       k1 = (p0ma0).dot(n_hat) + (p1ma1).dot(n0);
+       k2 = (p1ma1).dot(n_hat) + (p0ma0).dot(n1);
+       k3 = (p1ma1).dot(n1) * 3.0;
+}
+
+static SIMD_FORCE_INLINE void polyDecomposition(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& j0, const btScalar& j1, const btScalar& j2, btScalar& u0, btScalar& u1, btScalar& v0, btScalar& v1)
+{
+       btScalar denom = 4.0 * (j1 - j2) * (j1 - j0) + (j2 - j0) * (j2 - j0);
+       u0 = (2.0 * (j1 - j2) * (3.0 * k1 - 2.0 * k0 - k3) - (j0 - j2) * (3.0 * k2 - 2.0 * k3 - k0)) / denom;
+       u1 = (2.0 * (j1 - j0) * (3.0 * k2 - 2.0 * k3 - k0) - (j2 - j0) * (3.0 * k1 - 2.0 * k0 - k3)) / denom;
+       v0 = k0 - u0 * j0;
+       v1 = k3 - u1 * j2;
+}
+
+static SIMD_FORCE_INLINE bool rootFindingLemma(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3)
+{
+       btScalar u0, u1, v0, v1;
+       btScalar j0 = 3.0 * (k1 - k0);
+       btScalar j1 = 3.0 * (k2 - k1);
+       btScalar j2 = 3.0 * (k3 - k2);
+       polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
+       if (sameSign(v0, v1))
+       {
+               btScalar Ypa = j0 * (1.0 - v0) * (1.0 - v0) + 2.0 * j1 * v0 * (1.0 - v0) + j2 * v0 * v0;  // Y'(v0)
+               if (sameSign(Ypa, j0))
+               {
+                       return (diffSign(k0, v1));
+               }
+       }
+       return diffSign(k0, v0);
+}
+
+static SIMD_FORCE_INLINE void getJs(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Node* a, const btSoftBody::Node* b, const btSoftBody::Node* c, const btSoftBody::Node* p, const btScalar& dt, btScalar& j0, btScalar& j1, btScalar& j2)
+{
+       const btVector3& a0 = a->m_x;
+       const btVector3& b0 = b->m_x;
+       const btVector3& c0 = c->m_x;
+       const btVector3& va = a->m_v;
+       const btVector3& vb = b->m_v;
+       const btVector3& vc = c->m_v;
+       const btVector3 a1 = a0 + dt * va;
+       const btVector3 b1 = b0 + dt * vb;
+       const btVector3 c1 = c0 + dt * vc;
+       btVector3 n0 = (b0 - a0).cross(c0 - a0);
+       btVector3 n1 = (b1 - a1).cross(c1 - a1);
+       btVector3 n_hat = n0 + n1 - dt * dt * (vb - va).cross(vc - va);
+       const btVector3& p0 = p->m_x;
+       const btVector3& vp = p->m_v;
+       btVector3 p1 = p0 + dt * vp;
+       btVector3 m0 = (b0 - p0).cross(c0 - p0);
+       btVector3 m1 = (b1 - p1).cross(c1 - p1);
+       btVector3 m_hat = m0 + m1 - dt * dt * (vb - vp).cross(vc - vp);
+       btScalar l0 = m0.dot(n0);
+       btScalar l1 = 0.25 * (m0.dot(n_hat) + m_hat.dot(n0));
+       btScalar l2 = btScalar(1) / btScalar(6) * (m0.dot(n1) + m_hat.dot(n_hat) + m1.dot(n0));
+       btScalar l3 = 0.25 * (m_hat.dot(n1) + m1.dot(n_hat));
+       btScalar l4 = m1.dot(n1);
+
+       btScalar k1p = 0.25 * k0 + 0.75 * k1;
+       btScalar k2p = 0.5 * k1 + 0.5 * k2;
+       btScalar k3p = 0.75 * k2 + 0.25 * k3;
+
+       btScalar s0 = (l1 * k0 - l0 * k1p) * 4.0;
+       btScalar s1 = (l2 * k0 - l0 * k2p) * 2.0;
+       btScalar s2 = (l3 * k0 - l0 * k3p) * btScalar(4) / btScalar(3);
+       btScalar s3 = l4 * k0 - l0 * k3;
+
+       j0 = (s1 * k0 - s0 * k1) * 3.0;
+       j1 = (s2 * k0 - s0 * k2) * 1.5;
+       j2 = (s3 * k0 - s0 * k3);
+}
+
+static SIMD_FORCE_INLINE bool signDetermination1Internal(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& u0, const btScalar& u1, const btScalar& v0, const btScalar& v1)
+{
+       btScalar Yu0 = k0 * (1.0 - u0) * (1.0 - u0) * (1.0 - u0) + 3.0 * k1 * u0 * (1.0 - u0) * (1.0 - u0) + 3.0 * k2 * u0 * u0 * (1.0 - u0) + k3 * u0 * u0 * u0;  // Y(u0)
+       btScalar Yv0 = k0 * (1.0 - v0) * (1.0 - v0) * (1.0 - v0) + 3.0 * k1 * v0 * (1.0 - v0) * (1.0 - v0) + 3.0 * k2 * v0 * v0 * (1.0 - v0) + k3 * v0 * v0 * v0;  // Y(v0)
+
+       btScalar sign_Ytp = (u0 > u1) ? Yu0 : -Yu0;
+       btScalar L = sameSign(sign_Ytp, k0) ? u1 : u0;
+       sign_Ytp = (v0 > v1) ? Yv0 : -Yv0;
+       btScalar K = (sameSign(sign_Ytp, k0)) ? v1 : v0;
+       return diffSign(L, K);
+}
+
+static SIMD_FORCE_INLINE bool signDetermination2Internal(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& j0, const btScalar& j1, const btScalar& j2, const btScalar& u0, const btScalar& u1, const btScalar& v0, const btScalar& v1)
+{
+       btScalar Yu0 = k0 * (1.0 - u0) * (1.0 - u0) * (1.0 - u0) + 3.0 * k1 * u0 * (1.0 - u0) * (1.0 - u0) + 3.0 * k2 * u0 * u0 * (1.0 - u0) + k3 * u0 * u0 * u0;  // Y(u0)
+       btScalar sign_Ytp = (u0 > u1) ? Yu0 : -Yu0, L1, L2;
+       if (diffSign(sign_Ytp, k0))
+       {
+               L1 = u0;
+               L2 = u1;
+       }
+       else
+       {
+               btScalar Yp_u0 = j0 * (1.0 - u0) * (1.0 - u0) + 2.0 * j1 * (1.0 - u0) * u0 + j2 * u0 * u0;
+               if (sameSign(Yp_u0, j0))
+               {
+                       L1 = u1;
+                       L2 = u1;
+               }
+               else
+               {
+                       L1 = u0;
+                       L2 = u0;
+               }
+       }
+       btScalar Yv0 = k0 * (1.0 - v0) * (1.0 - v0) * (1.0 - v0) + 3.0 * k1 * v0 * (1.0 - v0) * (1.0 - v0) + 3.0 * k2 * v0 * v0 * (1.0 - v0) + k3 * v0 * v0 * v0;  // Y(uv0)
+       sign_Ytp = (v0 > v1) ? Yv0 : -Yv0;
+       btScalar K1, K2;
+       if (diffSign(sign_Ytp, k0))
+       {
+               K1 = v0;
+               K2 = v1;
+       }
+       else
+       {
+               btScalar Yp_v0 = j0 * (1.0 - v0) * (1.0 - v0) + 2.0 * j1 * (1.0 - v0) * v0 + j2 * v0 * v0;
+               if (sameSign(Yp_v0, j0))
+               {
+                       K1 = v1;
+                       K2 = v1;
+               }
+               else
+               {
+                       K1 = v0;
+                       K2 = v0;
+               }
+       }
+       return (diffSign(K1, L1) || diffSign(L2, K2));
+}
+
+static SIMD_FORCE_INLINE bool signDetermination1(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+       btScalar j0, j1, j2, u0, u1, v0, v1;
+       // p1
+       getJs(k0, k1, k2, k3, face->m_n[0], face->m_n[1], face->m_n[2], node, dt, j0, j1, j2);
+       if (nearZero(j0 + j2 - j1 * 2.0))
+       {
+               btScalar lt0, lt1;
+               getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
+               if (lt0 < -SAFE_EPSILON)
+                       return false;
+       }
+       else
+       {
+               polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
+               if (!signDetermination1Internal(k0, k1, k2, k3, u0, u1, v0, v1))
+                       return false;
+       }
+       // p2
+       getJs(k0, k1, k2, k3, face->m_n[1], face->m_n[2], face->m_n[0], node, dt, j0, j1, j2);
+       if (nearZero(j0 + j2 - j1 * 2.0))
+       {
+               btScalar lt0, lt1;
+               getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
+               if (lt0 < -SAFE_EPSILON)
+                       return false;
+       }
+       else
+       {
+               polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
+               if (!signDetermination1Internal(k0, k1, k2, k3, u0, u1, v0, v1))
+                       return false;
+       }
+       // p3
+       getJs(k0, k1, k2, k3, face->m_n[2], face->m_n[0], face->m_n[1], node, dt, j0, j1, j2);
+       if (nearZero(j0 + j2 - j1 * 2.0))
+       {
+               btScalar lt0, lt1;
+               getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
+               if (lt0 < -SAFE_EPSILON)
+                       return false;
+       }
+       else
+       {
+               polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
+               if (!signDetermination1Internal(k0, k1, k2, k3, u0, u1, v0, v1))
+                       return false;
+       }
+       return true;
+}
+
+static SIMD_FORCE_INLINE bool signDetermination2(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+       btScalar j0, j1, j2, u0, u1, v0, v1;
+       // p1
+       getJs(k0, k1, k2, k3, face->m_n[0], face->m_n[1], face->m_n[2], node, dt, j0, j1, j2);
+       if (nearZero(j0 + j2 - j1 * 2.0))
+       {
+               btScalar lt0, lt1;
+               bool bt0 = true, bt1 = true;
+               getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
+               if (lt0 < -SAFE_EPSILON)
+                       bt0 = false;
+               if (lt1 < -SAFE_EPSILON)
+                       bt1 = false;
+               if (!bt0 && !bt1)
+                       return false;
+       }
+       else
+       {
+               polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
+               if (!signDetermination2Internal(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1))
+                       return false;
+       }
+       // p2
+       getJs(k0, k1, k2, k3, face->m_n[1], face->m_n[2], face->m_n[0], node, dt, j0, j1, j2);
+       if (nearZero(j0 + j2 - j1 * 2.0))
+       {
+               btScalar lt0, lt1;
+               bool bt0 = true, bt1 = true;
+               getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
+               if (lt0 < -SAFE_EPSILON)
+                       bt0 = false;
+               if (lt1 < -SAFE_EPSILON)
+                       bt1 = false;
+               if (!bt0 && !bt1)
+                       return false;
+       }
+       else
+       {
+               polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
+               if (!signDetermination2Internal(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1))
+                       return false;
+       }
+       // p3
+       getJs(k0, k1, k2, k3, face->m_n[2], face->m_n[0], face->m_n[1], node, dt, j0, j1, j2);
+       if (nearZero(j0 + j2 - j1 * 2.0))
+       {
+               btScalar lt0, lt1;
+               bool bt0 = true, bt1 = true;
+               getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
+               if (lt0 < -SAFE_EPSILON)
+                       bt0 = false;
+               if (lt1 < -SAFE_EPSILON)
+                       bt1 = false;
+               if (!bt0 && !bt1)
+                       return false;
+       }
+       else
+       {
+               polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
+               if (!signDetermination2Internal(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1))
+                       return false;
+       }
+       return true;
+}
+
+static SIMD_FORCE_INLINE bool coplanarAndInsideTest(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+       // Coplanar test
+       if (diffSign(k1 - k0, k3 - k2))
+       {
+               // Case b:
+               if (sameSign(k0, k3) && !rootFindingLemma(k0, k1, k2, k3))
+                       return false;
+               // inside test
+               return signDetermination2(k0, k1, k2, k3, face, node, dt);
+       }
+       else
+       {
+               // Case c:
+               if (sameSign(k0, k3))
+                       return false;
+               // inside test
+               return signDetermination1(k0, k1, k2, k3, face, node, dt);
+       }
+       return false;
+}
+static SIMD_FORCE_INLINE bool conservativeCulling(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& mrg)
+{
+       if (k0 > mrg && k1 > mrg && k2 > mrg && k3 > mrg)
+               return true;
+       if (k0 < -mrg && k1 < -mrg && k2 < -mrg && k3 < -mrg)
+               return true;
+       return false;
+}
+
+static SIMD_FORCE_INLINE bool bernsteinVFTest(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& mrg, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
+{
+       if (conservativeCulling(k0, k1, k2, k3, mrg))
+               return false;
+       return coplanarAndInsideTest(k0, k1, k2, k3, face, node, dt);
+}
+
+static SIMD_FORCE_INLINE void deCasteljau(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& t0, btScalar& k10, btScalar& k20, btScalar& k30, btScalar& k21, btScalar& k12)
+{
+       k10 = k0 * (1.0 - t0) + k1 * t0;
+       btScalar k11 = k1 * (1.0 - t0) + k2 * t0;
+       k12 = k2 * (1.0 - t0) + k3 * t0;
+       k20 = k10 * (1.0 - t0) + k11 * t0;
+       k21 = k11 * (1.0 - t0) + k12 * t0;
+       k30 = k20 * (1.0 - t0) + k21 * t0;
+}
+static SIMD_FORCE_INLINE bool bernsteinVFTest(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg)
+{
+       btScalar k0, k1, k2, k3;
+       getBernsteinCoeff(face, node, dt, k0, k1, k2, k3);
+       if (conservativeCulling(k0, k1, k2, k3, mrg))
+               return false;
+       return true;
+       if (diffSign(k2 - 2.0 * k1 + k0, k3 - 2.0 * k2 + k1))
+       {
+               btScalar k10, k20, k30, k21, k12;
+               btScalar t0 = (k2 - 2.0 * k1 + k0) / (k0 - 3.0 * k1 + 3.0 * k2 - k3);
+               deCasteljau(k0, k1, k2, k3, t0, k10, k20, k30, k21, k12);
+               return bernsteinVFTest(k0, k10, k20, k30, mrg, face, node, dt) || bernsteinVFTest(k30, k21, k12, k3, mrg, face, node, dt);
+       }
+       return coplanarAndInsideTest(k0, k1, k2, k3, face, node, dt);
+}
+
+static SIMD_FORCE_INLINE bool continuousCollisionDetection(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg, btVector3& bary)
+{
+       if (hasSeparatingPlane(face, node, dt))
+               return false;
+       btVector3 x21 = face->m_n[1]->m_x - face->m_n[0]->m_x;
+       btVector3 x31 = face->m_n[2]->m_x - face->m_n[0]->m_x;
+       btVector3 x41 = node->m_x - face->m_n[0]->m_x;
+       btVector3 v21 = face->m_n[1]->m_v - face->m_n[0]->m_v;
+       btVector3 v31 = face->m_n[2]->m_v - face->m_n[0]->m_v;
+       btVector3 v41 = node->m_v - face->m_n[0]->m_v;
+       btVector3 a = x21.cross(x31);
+       btVector3 b = x21.cross(v31) + v21.cross(x31);
+       btVector3 c = v21.cross(v31);
+       btVector3 d = x41;
+       btVector3 e = v41;
+       btScalar a0 = a.dot(d);
+       btScalar a1 = a.dot(e) + b.dot(d);
+       btScalar a2 = c.dot(d) + b.dot(e);
+       btScalar a3 = c.dot(e);
+       btScalar eps = SAFE_EPSILON;
+       int num_roots = 0;
+       btScalar roots[3];
+       if (std::abs(a3) < eps)
+       {
+               // cubic term is zero
+               if (std::abs(a2) < eps)
+               {
+                       if (std::abs(a1) < eps)
+                       {
+                               if (std::abs(a0) < eps)
+                               {
+                                       num_roots = 2;
+                                       roots[0] = 0;
+                                       roots[1] = dt;
+                               }
+                       }
+                       else
+                       {
+                               num_roots = 1;
+                               roots[0] = -a0 / a1;
+                       }
+               }
+               else
+               {
+                       num_roots = SolveP2(roots, a1 / a2, a0 / a2);
+               }
+       }
+       else
+       {
+               num_roots = SolveP3(roots, a2 / a3, a1 / a3, a0 / a3);
+       }
+       //    std::sort(roots, roots+num_roots);
+       if (num_roots > 1)
+       {
+               if (roots[0] > roots[1])
+                       btSwap(roots[0], roots[1]);
+       }
+       if (num_roots > 2)
+       {
+               if (roots[0] > roots[2])
+                       btSwap(roots[0], roots[2]);
+               if (roots[1] > roots[2])
+                       btSwap(roots[1], roots[2]);
+       }
+       for (int r = 0; r < num_roots; ++r)
+       {
+               double root = roots[r];
+               if (root <= 0)
+                       continue;
+               if (root > dt + SIMD_EPSILON)
+                       return false;
+               btVector3 x1 = face->m_n[0]->m_x + root * face->m_n[0]->m_v;
+               btVector3 x2 = face->m_n[1]->m_x + root * face->m_n[1]->m_v;
+               btVector3 x3 = face->m_n[2]->m_x + root * face->m_n[2]->m_v;
+               btVector3 x4 = node->m_x + root * node->m_v;
+               btVector3 normal = (x2 - x1).cross(x3 - x1);
+               normal.safeNormalize();
+               if (proximityTest(x1, x2, x3, x4, normal, mrg, bary))
+                       return true;
+       }
+       return false;
+}
+static SIMD_FORCE_INLINE bool bernsteinCCD(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg, btVector3& bary)
+{
+       if (!bernsteinVFTest(face, node, dt, mrg))
+               return false;
+       if (!continuousCollisionDetection(face, node, dt, 1e-6, bary))
+               return false;
+       return true;
+}
+
+//
+// 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_shapeType = SOFTBODY_SHAPE_PROXYTYPE;
+               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 is usually identity, except when colliding against btCompoundShape. See Issue 512 */
+               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 void setLocalScaling(const btVector3& /*scaling*/)
+       {
+               ///na
+       }
+       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 = btDot(vec, n[0]->m_x);
+               int j = 0;
+               for (int i = 1, ni = m_cluster->m_nodes.size(); i < ni; ++i)
+               {
+                       const btScalar k = btDot(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 btConvexInternalShape::getMargin();
+       }
+};
+
+//
+// Inline's
+//
+
+//
+template <typename T>
+static inline void ZeroInitialize(T& value)
+{
+       memset(&value, 0, sizeof(T));
+}
+//
+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 Diagonal(const btVector3& v)
+{
+       btMatrix3x3 m;
+       m[0] = btVector3(v.getX(), 0, 0);
+       m[1] = btVector3(0, v.getY(), 0);
+       m[2] = btVector3(0, 0, v.getZ());
+       return (m);
+}
+
+static inline btScalar Dot(const btScalar* a, const btScalar* b, int ndof)
+{
+       btScalar result = 0;
+       for (int i = 0; i < ndof; ++i)
+               result += a[i] * b[i];
+       return result;
+}
+
+static inline btMatrix3x3 OuterProduct(const btScalar* v1, const btScalar* v2, const btScalar* v3,
+                                                                          const btScalar* u1, const btScalar* u2, const btScalar* u3, int ndof)
+{
+       btMatrix3x3 m;
+       btScalar a11 = Dot(v1, u1, ndof);
+       btScalar a12 = Dot(v1, u2, ndof);
+       btScalar a13 = Dot(v1, u3, ndof);
+
+       btScalar a21 = Dot(v2, u1, ndof);
+       btScalar a22 = Dot(v2, u2, ndof);
+       btScalar a23 = Dot(v2, u3, ndof);
+
+       btScalar a31 = Dot(v3, u1, ndof);
+       btScalar a32 = Dot(v3, u2, ndof);
+       btScalar a33 = Dot(v3, u3, ndof);
+       m[0] = btVector3(a11, a12, a13);
+       m[1] = btVector3(a21, a22, a23);
+       m[2] = btVector3(a31, a32, a33);
+       return (m);
+}
+
+static inline btMatrix3x3 OuterProduct(const btVector3& v1, const btVector3& v2)
+{
+       btMatrix3x3 m;
+       btScalar a11 = v1[0] * v2[0];
+       btScalar a12 = v1[0] * v2[1];
+       btScalar a13 = v1[0] * v2[2];
+
+       btScalar a21 = v1[1] * v2[0];
+       btScalar a22 = v1[1] * v2[1];
+       btScalar a23 = v1[1] * v2[2];
+
+       btScalar a31 = v1[2] * v2[0];
+       btScalar a32 = v1[2] * v2[1];
+       btScalar a33 = v1[2] * v2[2];
+       m[0] = btVector3(a11, a12, a13);
+       m[1] = btVector3(a21, a22, a23);
+       m[2] = btVector3(a31, a32, a33);
+       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] = btCross(m[0], m[1]).normalized();
+       m[1] = btCross(m[2], m[0]).normalized();
+       m[0] = btCross(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 dt,
+                                                                               const btMatrix3x3& effective_mass_inv,
+                                                                               btScalar imb,
+                                                                               const btMatrix3x3& iwi,
+                                                                               const btVector3& r)
+{
+       return (Diagonal(1 / dt) * Add(effective_mass_inv, MassMatrix(imb, iwi, r)).inverse());
+       //    btMatrix3x3 iimb = MassMatrix(imb, iwi, r);
+       //    if (iimb.determinant() == 0)
+       //        return effective_mass_inv.inverse();
+       //    return effective_mass_inv.inverse() *  Add(effective_mass_inv.inverse(), iimb.inverse()).inverse() * iimb.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 * btDot(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>(-btDot(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 = btCross(b - a, c - a);
+       const btScalar m2 = q.length2();
+       if (m2 > SIMD_EPSILON)
+       {
+               const btVector3 n = q / btSqrt(m2);
+               const btScalar k = btDot(a, n);
+               const btScalar k2 = k * k;
+               if (k2 < sqd)
+               {
+                       const btVector3 p = n * k;
+                       if ((btDot(btCross(a - p, b - p), q) > 0) &&
+                               (btDot(btCross(b - p, c - p), q) > 0) &&
+                               (btDot(btCross(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);
+                       }
+               }
+       }
+}
+
+//
+static inline bool rayIntersectsTriangle(const btVector3& origin, const btVector3& dir, const btVector3& v0, const btVector3& v1, const btVector3& v2, btScalar& t)
+{
+       btScalar a, f, u, v;
+
+       btVector3 e1 = v1 - v0;
+       btVector3 e2 = v2 - v0;
+       btVector3 h = dir.cross(e2);
+       a = e1.dot(h);
+
+       if (a > -0.00001 && a < 0.00001)
+               return (false);
+
+       f = btScalar(1) / a;
+       btVector3 s = origin - v0;
+       u = f * s.dot(h);
+
+       if (u < 0.0 || u > 1.0)
+               return (false);
+
+       btVector3 q = s.cross(e1);
+       v = f * dir.dot(q);
+       if (v < 0.0 || u + v > 1.0)
+               return (false);
+       // at this stage we can compute t to find out where
+       // the intersection point is on the line
+       t = f * e2.dot(q);
+       if (t > 0)  // ray intersection
+               return (true);
+       else  // this means that there is a line intersection
+               // but not a ray intersection
+               return (false);
+}
+
+static inline bool lineIntersectsTriangle(const btVector3& rayStart, const btVector3& rayEnd, const btVector3& p1, const btVector3& p2, const btVector3& p3, btVector3& sect, btVector3& normal)
+{
+       btVector3 dir = rayEnd - rayStart;
+       btScalar dir_norm = dir.norm();
+       if (dir_norm < SIMD_EPSILON)
+               return false;
+       dir.normalize();
+       btScalar t;
+       bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t);
+
+       if (ret)
+       {
+               if (t <= dir_norm)
+               {
+                       sect = rayStart + dir * t;
+               }
+               else
+               {
+                       ret = false;
+               }
+       }
+
+       if (ret)
+       {
+               btVector3 n = (p3 - p1).cross(p2 - p1);
+               n.safeNormalize();
+               if (n.dot(dir) < 0)
+                       normal = n;
+               else
+                       normal = -n;
+       }
+       return ret;
+}
+
+//
+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[] = {btCross(a - p, b - p).length(),
+                                                 btCross(b - p, c - p).length(),
+                                                 btCross(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));
+}
+
+//
+inline 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);
+}
+
+inline 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 = -(btDot(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 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 = btCross(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 (btDot(a, btCross(b, c)));
+}
+
+//
+
+//
+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 btPolarDecomposition polar;
+       return polar.decompose(m, q, s);
+}
+
+//
+// btSoftColliders
+//
+struct btSoftColliders
+{
+       //
+       // ClusterBase
+       //
+       struct ClusterBase : btDbvt::ICollide
+       {
+               btScalar erp;
+               btScalar idt;
+               btScalar m_margin;
+               btScalar friction;
+               btScalar threshold;
+               ClusterBase()
+               {
+                       erp = (btScalar)1;
+                       idt = 0;
+                       m_margin = 0;
+                       friction = 0;
+                       threshold = (btScalar)0;
+               }
+               bool SolveContact(const btGjkEpaSolver2::sResults& res,
+                                                 btSoftBody::Body ba, const btSoftBody::Body bb,
+                                                 btSoftBody::CJoint& joint)
+               {
+                       if (res.distance < m_margin)
+                       {
+                               btVector3 norm = res.normal;
+                               norm.normalize();  //is it necessary?
+
+                               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 = btDot(vrel, norm);
+                               btScalar depth = res.distance - m_margin;
+
+                               //                              printf("depth=%f\n",depth);
+                               const btVector3 iv = norm * 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 * norm;
+
+                               joint.m_normal = norm;
+                               //                              printf("normal=%f,%f,%f\n",res.normal.getX(),res.normal.getY(),res.normal.getZ());
+                               joint.m_delete = false;
+                               joint.m_friction = fv.length2() < (rvac * friction * 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;
+               const btCollisionObjectWrapper* m_colObjWrap;
+
+               void Process(const btDbvtNode* leaf)
+               {
+                       btSoftBody::Cluster* cluster = (btSoftBody::Cluster*)leaf->data;
+                       btSoftClusterCollisionShape cshape(cluster);
+
+                       const btConvexShape* rshape = (const btConvexShape*)m_colObjWrap->getCollisionShape();
+
+                       ///don't collide an anchored cluster with a static/kinematic object
+                       if (m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject() && cluster->m_containsAnchor)
+                               return;
+
+                       btGjkEpaSolver2::sResults res;
+                       if (btGjkEpaSolver2::SignedDistance(&cshape, btTransform::getIdentity(),
+                                                                                               rshape, m_colObjWrap->getWorldTransform(),
+                                                                                               btVector3(1, 0, 0), res))
+                       {
+                               btSoftBody::CJoint joint;
+                               if (SolveContact(res, cluster, m_colObjWrap->getCollisionObject(), joint))  //prb,joint))
+                               {
+                                       btSoftBody::CJoint* pj = new (btAlignedAlloc(sizeof(btSoftBody::CJoint), 16)) btSoftBody::CJoint();
+                                       *pj = joint;
+                                       psb->m_joints.push_back(pj);
+                                       if (m_colObjWrap->getCollisionObject()->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 ProcessColObj(btSoftBody* ps, const btCollisionObjectWrapper* colObWrap)
+               {
+                       psb = ps;
+                       m_colObjWrap = colObWrap;
+                       idt = ps->m_sst.isdt;
+                       m_margin = m_colObjWrap->getCollisionShape()->getMargin() + psb->getCollisionShape()->getMargin();
+                       ///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful.
+                       friction = btMin(psb->m_cfg.kDF, m_colObjWrap->getCollisionObject()->getFriction());
+                       btVector3 mins;
+                       btVector3 maxs;
+
+                       ATTRIBUTE_ALIGNED16(btDbvtVolume)
+                       volume;
+                       colObWrap->getCollisionShape()->getAabb(colObWrap->getWorldTransform(), mins, maxs);
+                       volume = btDbvtVolume::FromMM(mins, maxs);
+                       volume.Expand(btVector3(1, 1, 1) * m_margin);
+                       ps->m_cdbvt.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;
+
+                       bool connected = false;
+                       if ((bodies[0] == bodies[1]) && (bodies[0]->m_clusterConnectivity.size()))
+                       {
+                               connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex + bodies[0]->m_clusters.size() * clb->m_clusterIndex];
+                       }
+
+                       if (!connected)
+                       {
+                               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;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               static int count = 0;
+                               count++;
+                               //printf("count=%d\n",count);
+                       }
+               }
+               void ProcessSoftSoft(btSoftBody* psa, btSoftBody* psb)
+               {
+                       idt = psa->m_sst.isdt;
+                       //m_margin              =       (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2;
+                       m_margin = (psa->getCollisionShape()->getMargin() + psb->getCollisionShape()->getMargin());
+                       friction = btMin(psa->m_cfg.kDF, psb->m_cfg.kDF);
+                       bodies[0] = psa;
+                       bodies[1] = psb;
+                       psa->m_cdbvt.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(m_colObj1Wrap, n.m_x, m, c.m_cti))
+                       {
+                               const btScalar ima = n.m_im;
+                               const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
+                               const btScalar ms = ima + imb;
+                               if (ms > 0)
+                               {
+                                       const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
+                                       static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+                                       const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
+                                       const btVector3 ra = n.m_x - wtr.getOrigin();
+                                       const btVector3 va = m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra) * psb->m_sst.sdt : btVector3(0, 0, 0);
+                                       const btVector3 vb = n.m_x - n.m_q;
+                                       const btVector3 vr = vb - va;
+                                       const btScalar dn = btDot(vr, c.m_cti.m_normal);
+                                       const btVector3 fv = vr - c.m_cti.m_normal * dn;
+                                       const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->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() < (dn * fc * dn * fc) ? 0 : 1 - fc;
+                                       c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
+                                       psb->m_rcontacts.push_back(c);
+                                       if (m_rigidBody)
+                                               m_rigidBody->activate();
+                               }
+                       }
+               }
+               btSoftBody* psb;
+               const btCollisionObjectWrapper* m_colObj1Wrap;
+               btRigidBody* m_rigidBody;
+               btScalar dynmargin;
+               btScalar stamargin;
+       };
+
+       //
+       // CollideSDF_RD
+       //
+       struct CollideSDF_RD : 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::DeformableNodeRigidContact c;
+
+                       if (!n.m_battach)
+                       {
+                               // check for collision at x_{n+1}^*
+                               if (psb->checkDeformableContact(m_colObj1Wrap, n.m_q, m, c.m_cti, /*predict = */ true))
+                               {
+                                       const btScalar ima = n.m_im;
+                                       // todo: collision between multibody and fixed deformable node will be missed.
+                                       const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
+                                       const btScalar ms = ima + imb;
+                                       if (ms > 0)
+                                       {
+                                               // resolve contact at x_n
+                                               psb->checkDeformableContact(m_colObj1Wrap, n.m_x, m, c.m_cti, /*predict = */ false);
+                                               btSoftBody::sCti& cti = c.m_cti;
+                                               c.m_node = &n;
+                                               const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
+                                               c.m_c2 = ima;
+                                               c.m_c3 = fc;
+                                               c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
+                                               c.m_c5 = n.m_effectiveMass_inv;
+
+                                               if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+                                               {
+                                                       const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
+                                                       const btVector3 ra = n.m_x - wtr.getOrigin();
+
+                                                       static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+                                                       const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
+                                                       if (psb->m_reducedModel)
+                                                       {
+                                                               c.m_c0 = MassMatrix(imb, iwi, ra); //impulse factor K of the rigid body only (not the inverse)
+                                                       }
+                                                       else
+                                                       {
+                                                               c.m_c0 = ImpulseMatrix(1, n.m_effectiveMass_inv, imb, iwi, ra);
+                                                               //                            c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
+                                                       }
+                                                       c.m_c1 = ra;
+                                               }
+                                               else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+                                               {
+                                                       btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+                                                       if (multibodyLinkCol)
+                                                       {
+                                                               btVector3 normal = cti.m_normal;
+                                                               btVector3 t1 = generateUnitOrthogonalVector(normal);
+                                                               btVector3 t2 = btCross(normal, t1);
+                                                               btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+                                                               findJacobian(multibodyLinkCol, jacobianData_normal, c.m_node->m_x, normal);
+                                                               findJacobian(multibodyLinkCol, jacobianData_t1, c.m_node->m_x, t1);
+                                                               findJacobian(multibodyLinkCol, jacobianData_t2, c.m_node->m_x, t2);
+
+                                                               btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+                                                               btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+                                                               btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+                                                               btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+                                                               btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+                                                               btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+                                                               btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+                                                                                               t1.getX(), t1.getY(), t1.getZ(),
+                                                                                               t2.getX(), t2.getY(), t2.getZ());  // world frame to local frame
+                                                               const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+                                                               
+                                                               btMatrix3x3 local_impulse_matrix;
+                                                               if (psb->m_reducedModel)
+                                                               {
+                                                                       local_impulse_matrix = OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof);
+                                                               }
+                                                               else
+                                                               {
+                                                                       local_impulse_matrix = (n.m_effectiveMass_inv + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+                                                               }
+                                                               c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+                                                               c.jacobianData_normal = jacobianData_normal;
+                                                               c.jacobianData_t1 = jacobianData_t1;
+                                                               c.jacobianData_t2 = jacobianData_t2;
+                                                               c.t1 = t1;
+                                                               c.t2 = t2;
+                                                       }
+                                               }
+                                               psb->m_nodeRigidContacts.push_back(c);
+                                       }
+                               }
+                       }
+               }
+               btSoftBody* psb;
+               const btCollisionObjectWrapper* m_colObj1Wrap;
+               btRigidBody* m_rigidBody;
+               btScalar dynmargin;
+               btScalar stamargin;
+       };
+
+       //
+       // CollideSDF_RDF
+       //
+       struct CollideSDF_RDF : btDbvt::ICollide
+       {
+               void Process(const btDbvtNode* leaf)
+               {
+                       btSoftBody::Face* face = (btSoftBody::Face*)leaf->data;
+                       DoNode(*face);
+               }
+               void DoNode(btSoftBody::Face& f) const
+               {
+                       btSoftBody::Node* n0 = f.m_n[0];
+                       btSoftBody::Node* n1 = f.m_n[1];
+                       btSoftBody::Node* n2 = f.m_n[2];
+                       const btScalar m = (n0->m_im > 0 && n1->m_im > 0 && n2->m_im > 0) ? dynmargin : stamargin;
+                       btSoftBody::DeformableFaceRigidContact c;
+                       btVector3 contact_point;
+                       btVector3 bary;
+                       if (psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, true))
+                       {
+                               btScalar ima = n0->m_im + n1->m_im + n2->m_im;
+                               const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
+                               // todo: collision between multibody and fixed deformable face will be missed.
+                               const btScalar ms = ima + imb;
+                               if (ms > 0)
+                               {
+                                       // resolve contact at x_n
+                                       //                    psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, /*predict = */ false);
+                                       btSoftBody::sCti& cti = c.m_cti;
+                                       c.m_contactPoint = contact_point;
+                                       c.m_bary = bary;
+                                       // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
+                                       c.m_weights = btScalar(2) / (btScalar(1) + bary.length2()) * bary;
+                                       c.m_face = &f;
+                                       // friction is handled by the nodes to prevent sticking
+                                       //                    const btScalar fc = 0;
+                                       const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
+
+                                       // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
+                                       ima = bary.getX() * c.m_weights.getX() * n0->m_im + bary.getY() * c.m_weights.getY() * n1->m_im + bary.getZ() * c.m_weights.getZ() * n2->m_im;
+                                       c.m_c2 = ima;
+                                       c.m_c3 = fc;
+                                       c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
+                                       c.m_c5 = Diagonal(ima);
+                                       if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+                                       {
+                                               const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
+                                               static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
+                                               const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
+                                               const btVector3 ra = contact_point - wtr.getOrigin();
+
+                                               // we do not scale the impulse matrix by dt
+                                               c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
+                                               c.m_c1 = ra;
+                                       }
+                                       else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
+                                       {
+                                               btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
+                                               if (multibodyLinkCol)
+                                               {
+                                                       btVector3 normal = cti.m_normal;
+                                                       btVector3 t1 = generateUnitOrthogonalVector(normal);
+                                                       btVector3 t2 = btCross(normal, t1);
+                                                       btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
+                                                       findJacobian(multibodyLinkCol, jacobianData_normal, contact_point, normal);
+                                                       findJacobian(multibodyLinkCol, jacobianData_t1, contact_point, t1);
+                                                       findJacobian(multibodyLinkCol, jacobianData_t2, contact_point, t2);
+
+                                                       btScalar* J_n = &jacobianData_normal.m_jacobians[0];
+                                                       btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
+                                                       btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
+
+                                                       btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
+                                                       btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
+                                                       btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
+
+                                                       btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
+                                                                                       t1.getX(), t1.getY(), t1.getZ(),
+                                                                                       t2.getX(), t2.getY(), t2.getZ());  // world frame to local frame
+                                                       const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
+                                                       btMatrix3x3 local_impulse_matrix = (Diagonal(ima) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
+                                                       c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
+                                                       c.jacobianData_normal = jacobianData_normal;
+                                                       c.jacobianData_t1 = jacobianData_t1;
+                                                       c.jacobianData_t2 = jacobianData_t2;
+                                                       c.t1 = t1;
+                                                       c.t2 = t2;
+                                               }
+                                       }
+                                       psb->m_faceRigidContacts.push_back(c);
+                               }
+                       }
+                       // Set caching barycenters to be false after collision detection.
+                       // Only turn on when contact is static.
+                       f.m_pcontact[3] = 0;
+               }
+               btSoftBody* psb;
+               const btCollisionObjectWrapper* m_colObj1Wrap;
+               btRigidBody* m_rigidBody;
+               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;
+                       for (int i = 0; i < 3; ++i)
+                       {
+                               if (face->m_n[i] == node)
+                                       continue;
+                       }
+
+                       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;
+       };
+
+       //
+       // CollideVF_DD
+       //
+       struct CollideVF_DD : 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 bary;
+                       if (proximityTest(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, node->m_x, face->m_normal, mrg, bary))
+                       {
+                               const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
+                               const btVector3 w = bary;
+                               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::DeformableFaceNodeContact c;
+                                       c.m_normal = face->m_normal;
+                                       if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+                                               c.m_normal = -face->m_normal;
+                                       c.m_margin = mrg;
+                                       c.m_node = node;
+                                       c.m_face = face;
+                                       c.m_bary = w;
+                                       c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+                                       // Initialize unused fields.
+                                       c.m_weights = btVector3(0, 0, 0);
+                                       c.m_imf = 0;
+                                       c.m_c0 = 0;
+                                       c.m_colObj = psb[1];
+                                       psb[0]->m_faceNodeContacts.push_back(c);
+                               }
+                       }
+               }
+               btSoftBody* psb[2];
+               btScalar mrg;
+               bool useFaceNormal;
+       };
+
+       //
+       // CollideFF_DD
+       //
+       struct CollideFF_DD : btDbvt::ICollide
+       {
+               void Process(const btDbvntNode* lface1,
+                                        const btDbvntNode* lface2)
+               {
+                       btSoftBody::Face* f1 = (btSoftBody::Face*)lface1->data;
+                       btSoftBody::Face* f2 = (btSoftBody::Face*)lface2->data;
+                       if (f1 != f2)
+                       {
+                               Repel(f1, f2);
+                               Repel(f2, f1);
+                       }
+               }
+               void Repel(btSoftBody::Face* f1, btSoftBody::Face* f2)
+               {
+                       //#define REPEL_NEIGHBOR 1
+#ifndef REPEL_NEIGHBOR
+                       for (int node_id = 0; node_id < 3; ++node_id)
+                       {
+                               btSoftBody::Node* node = f1->m_n[node_id];
+                               for (int i = 0; i < 3; ++i)
+                               {
+                                       if (f2->m_n[i] == node)
+                                               return;
+                               }
+                       }
+#endif
+                       bool skip = false;
+                       for (int node_id = 0; node_id < 3; ++node_id)
+                       {
+                               btSoftBody::Node* node = f1->m_n[node_id];
+#ifdef REPEL_NEIGHBOR
+                               for (int i = 0; i < 3; ++i)
+                               {
+                                       if (f2->m_n[i] == node)
+                                       {
+                                               skip = true;
+                                               break;
+                                       }
+                               }
+                               if (skip)
+                               {
+                                       skip = false;
+                                       continue;
+                               }
+#endif
+                               btSoftBody::Face* face = f2;
+                               btVector3 bary;
+                               if (!proximityTest(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, node->m_x, face->m_normal, mrg, bary))
+                                       continue;
+                               btSoftBody::DeformableFaceNodeContact c;
+                               c.m_normal = face->m_normal;
+                               if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+                                       c.m_normal = -face->m_normal;
+                               c.m_margin = mrg;
+                               c.m_node = node;
+                               c.m_face = face;
+                               c.m_bary = bary;
+                               c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+                               // Initialize unused fields.
+                               c.m_weights = btVector3(0, 0, 0);
+                               c.m_imf = 0;
+                               c.m_c0 = 0;
+                               c.m_colObj = psb[1];
+                               psb[0]->m_faceNodeContacts.push_back(c);
+                       }
+               }
+               btSoftBody* psb[2];
+               btScalar mrg;
+               bool useFaceNormal;
+       };
+
+       struct CollideCCD : 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 bary;
+                       if (bernsteinCCD(face, node, dt, SAFE_EPSILON, bary))
+                       {
+                               btSoftBody::DeformableFaceNodeContact c;
+                               c.m_normal = face->m_normal;
+                               if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+                                       c.m_normal = -face->m_normal;
+                               c.m_node = node;
+                               c.m_face = face;
+                               c.m_bary = bary;
+                               c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+                               // Initialize unused fields.
+                               c.m_weights = btVector3(0, 0, 0);
+                               c.m_margin = mrg;
+                               c.m_imf = 0;
+                               c.m_c0 = 0;
+                               c.m_colObj = psb[1];
+                               psb[0]->m_faceNodeContactsCCD.push_back(c);
+                       }
+               }
+               void Process(const btDbvntNode* lface1,
+                                        const btDbvntNode* lface2)
+               {
+                       btSoftBody::Face* f1 = (btSoftBody::Face*)lface1->data;
+                       btSoftBody::Face* f2 = (btSoftBody::Face*)lface2->data;
+                       if (f1 != f2)
+                       {
+                               Repel(f1, f2);
+                               Repel(f2, f1);
+                       }
+               }
+               void Repel(btSoftBody::Face* f1, btSoftBody::Face* f2)
+               {
+                       //#define REPEL_NEIGHBOR 1
+#ifndef REPEL_NEIGHBOR
+                       for (int node_id = 0; node_id < 3; ++node_id)
+                       {
+                               btSoftBody::Node* node = f1->m_n[node_id];
+                               for (int i = 0; i < 3; ++i)
+                               {
+                                       if (f2->m_n[i] == node)
+                                               return;
+                               }
+                       }
+#endif
+                       bool skip = false;
+                       for (int node_id = 0; node_id < 3; ++node_id)
+                       {
+                               btSoftBody::Node* node = f1->m_n[node_id];
+#ifdef REPEL_NEIGHBOR
+                               for (int i = 0; i < 3; ++i)
+                               {
+                                       if (f2->m_n[i] == node)
+                                       {
+                                               skip = true;
+                                               break;
+                                       }
+                               }
+                               if (skip)
+                               {
+                                       skip = false;
+                                       continue;
+                               }
+#endif
+                               btSoftBody::Face* face = f2;
+                               btVector3 bary;
+                               if (bernsteinCCD(face, node, dt, SAFE_EPSILON, bary))
+                               {
+                                       btSoftBody::DeformableFaceNodeContact c;
+                                       c.m_normal = face->m_normal;
+                                       if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
+                                               c.m_normal = -face->m_normal;
+                                       c.m_node = node;
+                                       c.m_face = face;
+                                       c.m_bary = bary;
+                                       c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
+                                       // Initialize unused fields.
+                                       c.m_weights = btVector3(0, 0, 0);
+                                       c.m_margin = mrg;
+                                       c.m_imf = 0;
+                                       c.m_c0 = 0;
+                                       c.m_colObj = psb[1];
+                                       psb[0]->m_faceNodeContactsCCD.push_back(c);
+                               }
+                       }
+               }
+               btSoftBody* psb[2];
+               btScalar dt, mrg;
+               bool useFaceNormal;
+       };
+};
+#endif  //_BT_SOFT_BODY_INTERNALS_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp
new file mode 100644 (file)
index 0000000..af728c0
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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"
+
+#include "LinearMath/btPoolAllocator.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
+
+       //replace pool by a new one, with potential larger size
+
+       if (m_ownsCollisionAlgorithmPool && m_collisionAlgorithmPool)
+       {
+               int curElemSize = m_collisionAlgorithmPool->getElementSize();
+               ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
+
+               int maxSize0 = sizeof(btSoftSoftCollisionAlgorithm);
+               int maxSize1 = sizeof(btSoftRigidCollisionAlgorithm);
+               int maxSize2 = sizeof(btSoftBodyConcaveCollisionAlgorithm);
+
+               int collisionAlgorithmMaxElementSize = btMax(maxSize0, maxSize1);
+               collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize2);
+
+               if (collisionAlgorithmMaxElementSize > curElemSize)
+               {
+                       m_collisionAlgorithmPool->~btPoolAllocator();
+                       btAlignedFree(m_collisionAlgorithmPool);
+                       void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
+                       m_collisionAlgorithmPool = new (mem) btPoolAllocator(collisionAlgorithmMaxElementSize, constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
+               }
+       }
+}
+
+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/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h
new file mode 100644 (file)
index 0000000..0feb84f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodySolverVertexBuffer.h
new file mode 100644 (file)
index 0000000..c41ebf7
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
+#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
+
+class btVertexBufferDescriptor
+{
+public:
+       enum BufferTypes
+       {
+               CPU_BUFFER,
+               DX11_BUFFER,
+               OPENGL_BUFFER
+       };
+
+protected:
+       bool m_hasVertexPositions;
+       bool m_hasNormals;
+
+       int m_vertexOffset;
+       int m_vertexStride;
+
+       int m_normalOffset;
+       int m_normalStride;
+
+public:
+       btVertexBufferDescriptor()
+       {
+               m_hasVertexPositions = false;
+               m_hasNormals = false;
+               m_vertexOffset = 0;
+               m_vertexStride = 0;
+               m_normalOffset = 0;
+               m_normalStride = 0;
+       }
+
+       virtual ~btVertexBufferDescriptor()
+       {
+       }
+
+       virtual bool hasVertexPositions() const
+       {
+               return m_hasVertexPositions;
+       }
+
+       virtual bool hasNormals() const
+       {
+               return m_hasNormals;
+       }
+
+       /**
+        * Return the type of the vertex buffer descriptor.
+        */
+       virtual BufferTypes getBufferType() const = 0;
+
+       /**
+        * Return the vertex offset in floats from the base pointer.
+        */
+       virtual int getVertexOffset() const
+       {
+               return m_vertexOffset;
+       }
+
+       /**
+        * Return the vertex stride in number of floats between vertices.
+        */
+       virtual int getVertexStride() const
+       {
+               return m_vertexStride;
+       }
+
+       /**
+        * Return the vertex offset in floats from the base pointer.
+        */
+       virtual int getNormalOffset() const
+       {
+               return m_normalOffset;
+       }
+
+       /**
+        * Return the vertex stride in number of floats between vertices.
+        */
+       virtual int getNormalStride() const
+       {
+               return m_normalStride;
+       }
+};
+
+class btCPUVertexBufferDescriptor : public btVertexBufferDescriptor
+{
+protected:
+       float *m_basePointer;
+
+public:
+       /**
+        * vertexBasePointer is pointer to beginning of the buffer.
+        * vertexOffset is the offset in floats to the first vertex.
+        * vertexStride is the stride in floats between vertices.
+        */
+       btCPUVertexBufferDescriptor(float *basePointer, int vertexOffset, int vertexStride)
+       {
+               m_basePointer = basePointer;
+               m_vertexOffset = vertexOffset;
+               m_vertexStride = vertexStride;
+               m_hasVertexPositions = true;
+       }
+
+       /**
+        * vertexBasePointer is pointer to beginning of the buffer.
+        * vertexOffset is the offset in floats to the first vertex.
+        * vertexStride is the stride in floats between vertices.
+        */
+       btCPUVertexBufferDescriptor(float *basePointer, int vertexOffset, int vertexStride, int normalOffset, int normalStride)
+       {
+               m_basePointer = basePointer;
+
+               m_vertexOffset = vertexOffset;
+               m_vertexStride = vertexStride;
+               m_hasVertexPositions = true;
+
+               m_normalOffset = normalOffset;
+               m_normalStride = normalStride;
+               m_hasNormals = true;
+       }
+
+       virtual ~btCPUVertexBufferDescriptor()
+       {
+       }
+
+       /**
+        * Return the type of the vertex buffer descriptor.
+        */
+       virtual BufferTypes getBufferType() const
+       {
+               return CPU_BUFFER;
+       }
+
+       /**
+        * Return the base pointer in memory to the first vertex.
+        */
+       virtual float *getBasePointer() const
+       {
+               return m_basePointer;
+       }
+};
+
+#endif  // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodySolvers.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftBodySolvers.h
new file mode 100644 (file)
index 0000000..7eafc6c
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SOFT_BODY_SOLVERS_H
+#define BT_SOFT_BODY_SOLVERS_H
+
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+
+class btSoftBodyTriangleData;
+class btSoftBodyLinkData;
+class btSoftBodyVertexData;
+class btVertexBufferDescriptor;
+class btCollisionObject;
+class btSoftBody;
+
+class btSoftBodySolver
+{
+public:
+       enum SolverTypes
+       {
+               DEFAULT_SOLVER,
+               CPU_SOLVER,
+               CL_SOLVER,
+               CL_SIMD_SOLVER,
+               DX_SOLVER,
+               DX_SIMD_SOLVER,
+               DEFORMABLE_SOLVER,
+               REDUCED_DEFORMABLE_SOLVER
+       };
+
+protected:
+       int m_numberOfPositionIterations;
+       int m_numberOfVelocityIterations;
+       // Simulation timescale
+       float m_timeScale;
+
+public:
+       btSoftBodySolver() : m_numberOfPositionIterations(10),
+                                                m_timeScale(1)
+       {
+               m_numberOfVelocityIterations = 0;
+               m_numberOfPositionIterations = 5;
+       }
+
+       virtual ~btSoftBodySolver()
+       {
+       }
+
+       /**
+        * Return the type of the solver.
+        */
+       virtual SolverTypes getSolverType() const = 0;
+
+       /** Ensure that this solver is initialized. */
+       virtual bool checkInitialized() = 0;
+
+       /** Optimize soft bodies in this solver. */
+       virtual void optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate = false) = 0;
+
+       /** Copy necessary data back to the original soft body source objects. */
+       virtual void copyBackToSoftBodies(bool bMove = true) = 0;
+
+       /** Predict motion of soft bodies into next timestep */
+       virtual void predictMotion(btScalar solverdt) = 0;
+
+       /** Solve constraints for a set of soft bodies */
+       virtual void solveConstraints(btScalar solverdt) = 0;
+
+       /** Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes */
+       virtual void updateSoftBodies() = 0;
+
+       /** Process a collision between one of the world's soft bodies and another collision object */
+       virtual void processCollision(btSoftBody *, const struct btCollisionObjectWrapper *) = 0;
+
+       /** Process a collision between two soft bodies */
+       virtual void processCollision(btSoftBody *, btSoftBody *) = 0;
+
+       /** Set the number of velocity constraint solver iterations this solver uses. */
+       virtual void setNumberOfPositionIterations(int iterations)
+       {
+               m_numberOfPositionIterations = iterations;
+       }
+
+       /** Get the number of velocity constraint solver iterations this solver uses. */
+       virtual int getNumberOfPositionIterations()
+       {
+               return m_numberOfPositionIterations;
+       }
+
+       /** Set the number of velocity constraint solver iterations this solver uses. */
+       virtual void setNumberOfVelocityIterations(int iterations)
+       {
+               m_numberOfVelocityIterations = iterations;
+       }
+
+       /** Get the number of velocity constraint solver iterations this solver uses. */
+       virtual int getNumberOfVelocityIterations()
+       {
+               return m_numberOfVelocityIterations;
+       }
+
+       /** Return the timescale that the simulation is using */
+       float getTimeScale()
+       {
+               return m_timeScale;
+       }
+
+#if 0
+       /**
+        * Add a collision object to be used by the indicated softbody.
+        */
+       virtual void addCollisionObjectForSoftBody( int clothIdentifier, btCollisionObject *collisionObject ) = 0;
+#endif
+};
+
+/** 
+ * Class to manage movement of data from a solver to a given target.
+ * This version is abstract. Subclasses will have custom pairings for different combinations.
+ */
+class btSoftBodySolverOutput
+{
+protected:
+public:
+       btSoftBodySolverOutput()
+       {
+       }
+
+       virtual ~btSoftBodySolverOutput()
+       {
+       }
+
+       /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */
+       virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer) = 0;
+};
+
+#endif  // #ifndef BT_SOFT_BODY_SOLVERS_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp
new file mode 100644 (file)
index 0000000..dcdd932
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btSoftMultiBodyDynamicsWorld.h"
+#include "LinearMath/btQuickprof.h"
+
+//softbody & helpers
+#include "BulletSoftBody/btSoftBody.h"
+#include "BulletSoftBody/btSoftBodyHelpers.h"
+#include "BulletSoftBody/btSoftBodySolvers.h"
+#include "BulletSoftBody/btDefaultSoftBodySolver.h"
+#include "LinearMath/btSerializer.h"
+
+btSoftMultiBodyDynamicsWorld::btSoftMultiBodyDynamicsWorld(
+       btDispatcher* dispatcher,
+       btBroadphaseInterface* pairCache,
+       btMultiBodyConstraintSolver* constraintSolver,
+       btCollisionConfiguration* collisionConfiguration,
+       btSoftBodySolver* softBodySolver) : btMultiBodyDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
+                                                                               m_softBodySolver(softBodySolver),
+                                                                               m_ownsSolver(false)
+{
+       if (!m_softBodySolver)
+       {
+               void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver), 16);
+               m_softBodySolver = new (ptr) btDefaultSoftBodySolver();
+               m_ownsSolver = true;
+       }
+
+       m_drawFlags = fDrawFlags::Std;
+       m_drawNodeTree = true;
+       m_drawFaceTree = false;
+       m_drawClusterTree = false;
+       m_sbi.m_broadphase = pairCache;
+       m_sbi.m_dispatcher = dispatcher;
+       m_sbi.m_sparsesdf.Initialize();
+       m_sbi.m_sparsesdf.Reset();
+
+       m_sbi.air_density = (btScalar)1.2;
+       m_sbi.water_density = 0;
+       m_sbi.water_offset = 0;
+       m_sbi.water_normal = btVector3(0, 0, 0);
+       m_sbi.m_gravity.setValue(0, -10, 0);
+
+       m_sbi.m_sparsesdf.Initialize();
+}
+
+btSoftMultiBodyDynamicsWorld::~btSoftMultiBodyDynamicsWorld()
+{
+       if (m_ownsSolver)
+       {
+               m_softBodySolver->~btSoftBodySolver();
+               btAlignedFree(m_softBodySolver);
+       }
+}
+
+void btSoftMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+       btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
+       {
+               BT_PROFILE("predictUnconstraintMotionSoftBody");
+               m_softBodySolver->predictMotion(float(timeStep));
+       }
+}
+
+void btSoftMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
+{
+       // Let the solver grab the soft bodies and if necessary optimize for it
+       m_softBodySolver->optimize(getSoftBodyArray());
+
+       if (!m_softBodySolver->checkInitialized())
+       {
+               btAssert("Solver initialization failed\n");
+       }
+
+       btDiscreteDynamicsWorld::internalSingleStepSimulation(timeStep);
+
+       ///solve soft bodies constraints
+       solveSoftBodiesConstraints(timeStep);
+
+       //self collisions
+       for (int i = 0; i < m_softBodies.size(); i++)
+       {
+               btSoftBody* psb = (btSoftBody*)m_softBodies[i];
+               psb->defaultCollisionHandler(psb);
+       }
+
+       ///update soft bodies
+       m_softBodySolver->updateSoftBodies();
+
+       for (int i = 0; i < m_softBodies.size(); i++)
+       {
+               btSoftBody* psb = (btSoftBody*)m_softBodies[i];
+               psb->interpolateRenderMesh();
+       }
+       // End solver-wise simulation step
+       // ///////////////////////////////
+}
+
+void btSoftMultiBodyDynamicsWorld::solveSoftBodiesConstraints(btScalar timeStep)
+{
+       BT_PROFILE("solveSoftConstraints");
+
+       if (m_softBodies.size())
+       {
+               btSoftBody::solveClusters(m_softBodies);
+       }
+
+       // Solve constraints solver-wise
+       m_softBodySolver->solveConstraints(timeStep * m_softBodySolver->getTimeScale());
+}
+
+void btSoftMultiBodyDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
+{
+       m_softBodies.push_back(body);
+
+       // Set the soft body solver that will deal with this body
+       // to be the world's solver
+       body->setSoftBodySolver(m_softBodySolver);
+
+       btCollisionWorld::addCollisionObject(body,
+                                                                                collisionFilterGroup,
+                                                                                collisionFilterMask);
+}
+
+void btSoftMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
+{
+       m_softBodies.remove(body);
+
+       btCollisionWorld::removeCollisionObject(body);
+}
+
+void btSoftMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+       btSoftBody* body = btSoftBody::upcast(collisionObject);
+       if (body)
+               removeSoftBody(body);
+       else
+               btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
+}
+
+void btSoftMultiBodyDynamicsWorld::debugDrawWorld()
+{
+       btMultiBodyDynamicsWorld::debugDrawWorld();
+
+       if (getDebugDrawer())
+       {
+               int i;
+               for (i = 0; i < this->m_softBodies.size(); i++)
+               {
+                       btSoftBody* psb = (btSoftBody*)this->m_softBodies[i];
+                       if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
+                       {
+                               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);
+                       }
+               }
+       }
+}
+
+struct btSoftSingleRayCallback : public btBroadphaseRayCallback
+{
+       btVector3 m_rayFromWorld;
+       btVector3 m_rayToWorld;
+       btTransform m_rayFromTrans;
+       btTransform m_rayToTrans;
+       btVector3 m_hitNormal;
+
+       const btSoftMultiBodyDynamicsWorld* m_world;
+       btCollisionWorld::RayResultCallback& m_resultCallback;
+
+       btSoftSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btSoftMultiBodyDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
+               : m_rayFromWorld(rayFromWorld),
+                 m_rayToWorld(rayToWorld),
+                 m_world(world),
+                 m_resultCallback(resultCallback)
+       {
+               m_rayFromTrans.setIdentity();
+               m_rayFromTrans.setOrigin(m_rayFromWorld);
+               m_rayToTrans.setIdentity();
+               m_rayToTrans.setOrigin(m_rayToWorld);
+
+               btVector3 rayDir = (rayToWorld - rayFromWorld);
+
+               rayDir.normalize();
+               ///what about division by zero? --> just set rayDirection[i] to INF/1e30
+               m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
+               m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
+               m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
+               m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+               m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+               m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+               m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
+       }
+
+       virtual bool process(const btBroadphaseProxy* proxy)
+       {
+               ///terminate further ray tests, once the closestHitFraction reached zero
+               if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+                       return false;
+
+               btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+               //only perform raycast if filterMask matches
+               if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+               {
+                       //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+                       //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+                       btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+                       collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+                       //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+                       const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+                       const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+                       //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+                       //culling already done by broadphase
+                       //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+                       {
+                               m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
+                                                                          collisionObject,
+                                                                          collisionObject->getCollisionShape(),
+                                                                          collisionObject->getWorldTransform(),
+                                                                          m_resultCallback);
+                       }
+               }
+               return true;
+       }
+};
+
+void btSoftMultiBodyDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+{
+       BT_PROFILE("rayTest");
+       /// use the broadphase to accelerate the search for objects, based on their aabb
+       /// and for each object with ray-aabb overlap, perform an exact ray test
+       btSoftSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+       m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
+#else
+       for (int i = 0; i < this->getNumCollisionObjects(); i++)
+       {
+               rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+       }
+#endif  //USE_BRUTEFORCE_RAYBROADPHASE
+}
+
+void btSoftMultiBodyDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+                                                                                                btCollisionObject* collisionObject,
+                                                                                                const btCollisionShape* collisionShape,
+                                                                                                const btTransform& colObjWorldTransform,
+                                                                                                RayResultCallback& resultCallback)
+{
+       if (collisionShape->isSoftBody())
+       {
+               btSoftBody* softBody = btSoftBody::upcast(collisionObject);
+               if (softBody)
+               {
+                       btSoftBody::sRayCast softResult;
+                       if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
+                       {
+                               if (softResult.fraction <= resultCallback.m_closestHitFraction)
+                               {
+                                       btCollisionWorld::LocalShapeInfo shapeInfo;
+                                       shapeInfo.m_shapePart = 0;
+                                       shapeInfo.m_triangleIndex = softResult.index;
+                                       // get the normal
+                                       btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
+                                       btVector3 normal = -rayDir;
+                                       normal.normalize();
+
+                                       if (softResult.feature == btSoftBody::eFeature::Face)
+                                       {
+                                               normal = softBody->m_faces[softResult.index].m_normal;
+                                               if (normal.dot(rayDir) > 0)
+                                               {
+                                                       // normal always point toward origin of the ray
+                                                       normal = -normal;
+                                               }
+                                       }
+
+                                       btCollisionWorld::LocalRayResult rayResult(collisionObject,
+                                                                                                                          &shapeInfo,
+                                                                                                                          normal,
+                                                                                                                          softResult.fraction);
+                                       bool normalInWorldSpace = true;
+                                       resultCallback.addSingleResult(rayResult, normalInWorldSpace);
+                               }
+                       }
+               }
+       }
+       else
+       {
+               btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
+       }
+}
+
+void btSoftMultiBodyDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
+{
+       int i;
+       //serialize all collision objects
+       for (i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               if (colObj->getInternalType() & btCollisionObject::CO_SOFT_BODY)
+               {
+                       int len = colObj->calculateSerializeBufferSize();
+                       btChunk* chunk = serializer->allocate(len, 1);
+                       const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
+                       serializer->finalizeChunk(chunk, structType, BT_SOFTBODY_CODE, colObj);
+               }
+       }
+}
+
+void btSoftMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
+{
+       serializer->startSerialization();
+
+       serializeDynamicsWorldInfo(serializer);
+
+       serializeSoftBodies(serializer);
+
+       serializeMultiBodies(serializer);
+
+       serializeRigidBodies(serializer);
+
+       serializeCollisionObjects(serializer);
+
+       serializeContactManifolds(serializer);
+
+       serializer->finishSerialization();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h
new file mode 100644 (file)
index 0000000..40cb1ec
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SOFT_MULTIBODY_DYNAMICS_WORLD_H
+#define BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H
+
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
+#include "BulletSoftBody/btSoftBody.h"
+
+#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+#endif
+
+class btSoftBodySolver;
+
+class btSoftMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld
+{
+       btSoftBodyArray m_softBodies;
+       int m_drawFlags;
+       bool m_drawNodeTree;
+       bool m_drawFaceTree;
+       bool m_drawClusterTree;
+       btSoftBodyWorldInfo m_sbi;
+       ///Solver classes that encapsulate multiple soft bodies for solving
+       btSoftBodySolver* m_softBodySolver;
+       bool m_ownsSolver;
+
+protected:
+       virtual void predictUnconstraintMotion(btScalar timeStep);
+
+       virtual void internalSingleStepSimulation(btScalar timeStep);
+
+       void solveSoftBodiesConstraints(btScalar timeStep);
+
+       void serializeSoftBodies(btSerializer* serializer);
+
+public:
+       btSoftMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver* softBodySolver = 0);
+
+       virtual ~btSoftMultiBodyDynamicsWorld();
+
+       virtual void debugDrawWorld();
+
+       void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
+
+       void removeSoftBody(btSoftBody* body);
+
+       ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject
+       virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+       int getDrawFlags() const { return (m_drawFlags); }
+       void setDrawFlags(int f) { m_drawFlags = f; }
+
+       btSoftBodyWorldInfo& getWorldInfo()
+       {
+               return m_sbi;
+       }
+       const btSoftBodyWorldInfo& getWorldInfo() const
+       {
+               return m_sbi;
+       }
+
+       virtual btDynamicsWorldType getWorldType() const
+       {
+               return BT_SOFT_MULTIBODY_DYNAMICS_WORLD;
+       }
+
+       btSoftBodyArray& getSoftBodyArray()
+       {
+               return m_softBodies;
+       }
+
+       const btSoftBodyArray& getSoftBodyArray() const
+       {
+               return m_softBodies;
+       }
+
+       virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& 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.
+       /// This allows more customization.
+       static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+                                                         btCollisionObject* collisionObject,
+                                                         const btCollisionShape* collisionShape,
+                                                         const btTransform& colObjWorldTransform,
+                                                         RayResultCallback& resultCallback);
+
+       virtual void serialize(btSerializer* serializer);
+};
+
+#endif  //BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..656b009
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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"
+#include "BulletSoftBody/btSoftBodySolvers.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.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, const btCollisionObjectWrapper*, const btCollisionObjectWrapper*, 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>
+#include "LinearMath/btQuickprof.h"
+void btSoftRigidCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
+{
+       BT_PROFILE("btSoftRigidCollisionAlgorithm::processCollision");
+       (void)dispatchInfo;
+       (void)resultOut;
+       //printf("btSoftRigidCollisionAlgorithm\n");
+       //      const btCollisionObjectWrapper* softWrap = m_isSwapped?body1Wrap:body0Wrap;
+       //      const btCollisionObjectWrapper* rigidWrap = m_isSwapped?body0Wrap:body1Wrap;
+       btSoftBody* softBody = m_isSwapped ? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject();
+       const btCollisionObjectWrapper* rigidCollisionObjectWrap = m_isSwapped ? body0Wrap : body1Wrap;
+
+       if (softBody->m_collisionDisabledObjects.findLinearSearch(rigidCollisionObjectWrap->getCollisionObject()) == softBody->m_collisionDisabledObjects.size())
+       {
+               softBody->getSoftBodySolver()->processCollision(softBody, rigidCollisionObjectWrap);
+       }
+}
+
+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/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..7b24545
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SOFT_RIGID_COLLISION_ALGORITHM_H
+#define BT_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, const btCollisionObjectWrapper* col0, const btCollisionObjectWrapper* col1Wrap, bool isSwapped);
+
+       virtual ~btSoftRigidCollisionAlgorithm();
+
+       virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, 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, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm));
+                       if (!m_swapped)
+                       {
+                               return new (mem) btSoftRigidCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false);
+                       }
+                       else
+                       {
+                               return new (mem) btSoftRigidCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true);
+                       }
+               }
+       };
+};
+
+#endif  //BT_SOFT_RIGID_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
new file mode 100644 (file)
index 0000000..dc9b004
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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"
+#include "btSoftBodySolvers.h"
+#include "btDefaultSoftBodySolver.h"
+#include "LinearMath/btSerializer.h"
+
+btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(
+       btDispatcher* dispatcher,
+       btBroadphaseInterface* pairCache,
+       btConstraintSolver* constraintSolver,
+       btCollisionConfiguration* collisionConfiguration,
+       btSoftBodySolver* softBodySolver) : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
+                                                                               m_softBodySolver(softBodySolver),
+                                                                               m_ownsSolver(false)
+{
+       if (!m_softBodySolver)
+       {
+               void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver), 16);
+               m_softBodySolver = new (ptr) btDefaultSoftBodySolver();
+               m_ownsSolver = true;
+       }
+
+       m_drawFlags = fDrawFlags::Std;
+       m_drawNodeTree = true;
+       m_drawFaceTree = false;
+       m_drawClusterTree = false;
+       m_sbi.m_broadphase = pairCache;
+       m_sbi.m_dispatcher = dispatcher;
+       m_sbi.m_sparsesdf.Initialize();
+       m_sbi.m_sparsesdf.Reset();
+
+       m_sbi.air_density = (btScalar)1.2;
+       m_sbi.water_density = 0;
+       m_sbi.water_offset = 0;
+       m_sbi.water_normal = btVector3(0, 0, 0);
+       m_sbi.m_gravity.setValue(0, -10, 0);
+
+       m_sbi.m_sparsesdf.Initialize();
+}
+
+btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()
+{
+       if (m_ownsSolver)
+       {
+               m_softBodySolver->~btSoftBodySolver();
+               btAlignedFree(m_softBodySolver);
+       }
+}
+
+void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+       btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
+       {
+               BT_PROFILE("predictUnconstraintMotionSoftBody");
+               m_softBodySolver->predictMotion(float(timeStep));
+       }
+}
+
+void btSoftRigidDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
+{
+       // Let the solver grab the soft bodies and if necessary optimize for it
+       m_softBodySolver->optimize(getSoftBodyArray());
+
+       if (!m_softBodySolver->checkInitialized())
+       {
+               btAssert("Solver initialization failed\n");
+       }
+
+       btDiscreteDynamicsWorld::internalSingleStepSimulation(timeStep);
+
+       ///solve soft bodies constraints
+       solveSoftBodiesConstraints(timeStep);
+
+       //self collisions
+       for (int i = 0; i < m_softBodies.size(); i++)
+       {
+               btSoftBody* psb = (btSoftBody*)m_softBodies[i];
+               psb->defaultCollisionHandler(psb);
+       }
+
+       ///update soft bodies
+       m_softBodySolver->updateSoftBodies();
+
+       // End solver-wise simulation step
+       // ///////////////////////////////
+}
+
+void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints(btScalar timeStep)
+{
+       BT_PROFILE("solveSoftConstraints");
+
+       if (m_softBodies.size())
+       {
+               btSoftBody::solveClusters(m_softBodies);
+       }
+
+       // Solve constraints solver-wise
+       m_softBodySolver->solveConstraints(timeStep * m_softBodySolver->getTimeScale());
+}
+
+void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
+{
+       m_softBodies.push_back(body);
+
+       // Set the soft body solver that will deal with this body
+       // to be the world's solver
+       body->setSoftBodySolver(m_softBodySolver);
+
+       btCollisionWorld::addCollisionObject(body,
+                                                                                collisionFilterGroup,
+                                                                                collisionFilterMask);
+}
+
+void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body)
+{
+       m_softBodies.remove(body);
+
+       btCollisionWorld::removeCollisionObject(body);
+}
+
+void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+       btSoftBody* body = btSoftBody::upcast(collisionObject);
+       if (body)
+               removeSoftBody(body);
+       else
+               btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
+}
+
+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];
+                       if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
+                       {
+                               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);
+                       }
+               }
+       }
+}
+
+struct btSoftSingleRayCallback : public btBroadphaseRayCallback
+{
+       btVector3 m_rayFromWorld;
+       btVector3 m_rayToWorld;
+       btTransform m_rayFromTrans;
+       btTransform m_rayToTrans;
+       btVector3 m_hitNormal;
+
+       const btSoftRigidDynamicsWorld* m_world;
+       btCollisionWorld::RayResultCallback& m_resultCallback;
+
+       btSoftSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btSoftRigidDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
+               : m_rayFromWorld(rayFromWorld),
+                 m_rayToWorld(rayToWorld),
+                 m_world(world),
+                 m_resultCallback(resultCallback)
+       {
+               m_rayFromTrans.setIdentity();
+               m_rayFromTrans.setOrigin(m_rayFromWorld);
+               m_rayToTrans.setIdentity();
+               m_rayToTrans.setOrigin(m_rayToWorld);
+
+               btVector3 rayDir = (rayToWorld - rayFromWorld);
+
+               rayDir.normalize();
+               ///what about division by zero? --> just set rayDirection[i] to INF/1e30
+               m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
+               m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
+               m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
+               m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+               m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+               m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+               m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
+       }
+
+       virtual bool process(const btBroadphaseProxy* proxy)
+       {
+               ///terminate further ray tests, once the closestHitFraction reached zero
+               if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+                       return false;
+
+               btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+               //only perform raycast if filterMask matches
+               if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
+               {
+                       //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+                       //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+                       btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+                       collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+                       //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+                       const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+                       const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+                       //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+                       //culling already done by broadphase
+                       //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+                       {
+                               m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
+                                                                          collisionObject,
+                                                                          collisionObject->getCollisionShape(),
+                                                                          collisionObject->getWorldTransform(),
+                                                                          m_resultCallback);
+                       }
+               }
+               return true;
+       }
+};
+
+void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+{
+       BT_PROFILE("rayTest");
+       /// use the broadphase to accelerate the search for objects, based on their aabb
+       /// and for each object with ray-aabb overlap, perform an exact ray test
+       btSoftSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+       m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
+#else
+       for (int i = 0; i < this->getNumCollisionObjects(); i++)
+       {
+               rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+       }
+#endif  //USE_BRUTEFORCE_RAYBROADPHASE
+}
+
+void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+                                                                                        btCollisionObject* collisionObject,
+                                                                                        const btCollisionShape* collisionShape,
+                                                                                        const btTransform& colObjWorldTransform,
+                                                                                        RayResultCallback& resultCallback)
+{
+       if (collisionShape->isSoftBody())
+       {
+               btSoftBody* softBody = btSoftBody::upcast(collisionObject);
+               if (softBody)
+               {
+                       btSoftBody::sRayCast softResult;
+                       if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
+                       {
+                               if (softResult.fraction <= resultCallback.m_closestHitFraction)
+                               {
+                                       btCollisionWorld::LocalShapeInfo shapeInfo;
+                                       shapeInfo.m_shapePart = 0;
+                                       shapeInfo.m_triangleIndex = softResult.index;
+                                       // get the normal
+                                       btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
+                                       btVector3 normal = -rayDir;
+                                       normal.normalize();
+
+                                       if (softResult.feature == btSoftBody::eFeature::Face)
+                                       {
+                                               normal = softBody->m_faces[softResult.index].m_normal;
+                                               if (normal.dot(rayDir) > 0)
+                                               {
+                                                       // normal always point toward origin of the ray
+                                                       normal = -normal;
+                                               }
+                                       }
+
+                                       btCollisionWorld::LocalRayResult rayResult(collisionObject,
+                                                                                                                          &shapeInfo,
+                                                                                                                          normal,
+                                                                                                                          softResult.fraction);
+                                       bool normalInWorldSpace = true;
+                                       resultCallback.addSingleResult(rayResult, normalInWorldSpace);
+                               }
+                       }
+               }
+       }
+       else
+       {
+               btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
+       }
+}
+
+void btSoftRigidDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
+{
+       int i;
+       //serialize all collision objects
+       for (i = 0; i < m_collisionObjects.size(); i++)
+       {
+               btCollisionObject* colObj = m_collisionObjects[i];
+               if (colObj->getInternalType() & btCollisionObject::CO_SOFT_BODY)
+               {
+                       int len = colObj->calculateSerializeBufferSize();
+                       btChunk* chunk = serializer->allocate(len, 1);
+                       const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
+                       serializer->finalizeChunk(chunk, structType, BT_SOFTBODY_CODE, colObj);
+               }
+       }
+}
+
+void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer)
+{
+       serializer->startSerialization();
+
+       serializeDynamicsWorldInfo(serializer);
+
+       serializeSoftBodies(serializer);
+
+       serializeRigidBodies(serializer);
+
+       serializeCollisionObjects(serializer);
+
+       serializer->finishSerialization();
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftRigidDynamicsWorld.h
new file mode 100644 (file)
index 0000000..0ecc7a0
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SOFT_RIGID_DYNAMICS_WORLD_H
+#define BT_SOFT_RIGID_DYNAMICS_WORLD_H
+
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+#include "btSoftBody.h"
+
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+
+class btSoftBodySolver;
+
+class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld
+{
+       btSoftBodyArray m_softBodies;
+       int m_drawFlags;
+       bool m_drawNodeTree;
+       bool m_drawFaceTree;
+       bool m_drawClusterTree;
+       btSoftBodyWorldInfo m_sbi;
+       ///Solver classes that encapsulate multiple soft bodies for solving
+       btSoftBodySolver* m_softBodySolver;
+       bool m_ownsSolver;
+
+protected:
+       virtual void predictUnconstraintMotion(btScalar timeStep);
+
+       virtual void internalSingleStepSimulation(btScalar timeStep);
+
+       void solveSoftBodiesConstraints(btScalar timeStep);
+
+       void serializeSoftBodies(btSerializer* serializer);
+
+public:
+       btSoftRigidDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver* softBodySolver = 0);
+
+       virtual ~btSoftRigidDynamicsWorld();
+
+       virtual void debugDrawWorld();
+
+       void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
+
+       void removeSoftBody(btSoftBody* body);
+
+       ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject
+       virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+       int getDrawFlags() const { return (m_drawFlags); }
+       void setDrawFlags(int f) { m_drawFlags = f; }
+
+       btSoftBodyWorldInfo& getWorldInfo()
+       {
+               return m_sbi;
+       }
+       const btSoftBodyWorldInfo& getWorldInfo() const
+       {
+               return m_sbi;
+       }
+
+       virtual btDynamicsWorldType getWorldType() const
+       {
+               return BT_SOFT_RIGID_DYNAMICS_WORLD;
+       }
+
+       btSoftBodyArray& getSoftBodyArray()
+       {
+               return m_softBodies;
+       }
+
+       const btSoftBodyArray& getSoftBodyArray() const
+       {
+               return m_softBodies;
+       }
+
+       virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& 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.
+       /// This allows more customization.
+       static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
+                                                         btCollisionObject* collisionObject,
+                                                         const btCollisionShape* collisionShape,
+                                                         const btTransform& colObjWorldTransform,
+                                                         RayResultCallback& resultCallback);
+
+       virtual void serialize(btSerializer* serializer);
+};
+
+#endif  //BT_SOFT_RIGID_DYNAMICS_WORLD_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
new file mode 100644 (file)
index 0000000..4e890ba
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "BulletSoftBody/btSoftBodySolvers.h"
+#include "btSoftBody.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* /*obj0*/, const btCollisionObjectWrapper* /*obj1*/)
+       : btCollisionAlgorithm(ci)
+//m_ownManifold(false),
+//m_manifoldPtr(mf)
+{
+}
+
+btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm()
+{
+}
+
+void btSoftSoftCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
+{
+       btSoftBody* soft0 = (btSoftBody*)body0Wrap->getCollisionObject();
+       btSoftBody* soft1 = (btSoftBody*)body1Wrap->getCollisionObject();
+       soft0->getSoftBodySolver()->processCollision(soft0, soft1);
+}
+
+btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
+{
+       //not yet
+       return 1.f;
+}
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
new file mode 100644 (file)
index 0000000..30923be
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SOFT_SOFT_COLLISION_ALGORITHM_H
+#define BT_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(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, 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, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
+
+       virtual ~btSoftSoftCollisionAlgorithm();
+
+       struct CreateFunc : public btCollisionAlgorithmCreateFunc
+       {
+               virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
+               {
+                       int bbsize = sizeof(btSoftSoftCollisionAlgorithm);
+                       void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+                       return new (ptr) btSoftSoftCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
+               }
+       };
+};
+
+#endif  //BT_SOFT_SOFT_COLLISION_ALGORITHM_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/btSparseSDF.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/btSparseSDF.h
new file mode 100644 (file)
index 0000000..243b80f
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 BT_SPARSE_SDF_H
+#define BT_SPARSE_SDF_H
+
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+
+// Fast Hash
+
+#if !defined(get16bits)
+#define get16bits(d) ((((unsigned int)(((const unsigned char*)(d))[1])) << 8) + (unsigned int)(((const unsigned char*)(d))[0]))
+#endif
+//
+// super hash function by Paul Hsieh
+//
+inline unsigned int HsiehHash(const char* data, int len)
+{
+       unsigned int hash = len, tmp;
+       len >>= 2;
+
+       /* Main loop */
+       for (; len > 0; len--)
+       {
+               hash += get16bits(data);
+               tmp = (get16bits(data + 2) << 11) ^ hash;
+               hash = (hash << 16) ^ tmp;
+               data += 2 * sizeof(unsigned short);
+               hash += hash >> 11;
+       }
+
+       /* Force "avalanching" of final 127 bits */
+       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;
+               const btCollisionShape* pclient;
+               Cell* next;
+       };
+       //
+       // Fields
+       //
+
+       btAlignedObjectArray<Cell*> cells;
+       btScalar voxelsz;
+       btScalar m_defaultVoxelsz;
+       int puid;
+       int ncells;
+       int m_clampCells;
+       int nprobes;
+       int nqueries;
+
+       ~btSparseSdf()
+       {
+               Reset();
+       }
+       //
+       // Methods
+       //
+
+       //
+       void Initialize(int hashsize = 2383, int clampCells = 256 * 1024)
+       {
+               //avoid a crash due to running out of memory, so clamp the maximum number of cells allocated
+               //if this limit is reached, the SDF is reset (at the cost of some performance during the reset)
+               m_clampCells = clampCells;
+               cells.resize(hashsize, 0);
+               m_defaultVoxelsz = 0.25;
+               Reset();
+       }
+       //
+
+       void setDefaultVoxelsz(btScalar sz)
+       {
+               m_defaultVoxelsz = sz;
+       }
+
+       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 = m_defaultVoxelsz;
+               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,
+                                         const 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
+                       {
+                               // printf("c->hash/c[0][1][2]=%d,%d,%d,%d\n", c->hash, c->c[0], c->c[1],c->c[2]);
+                               //printf("h,ixb,iyb,izb=%d,%d,%d,%d\n", h,ix.b, iy.b, iz.b);
+
+                               c = c->next;
+                       }
+               }
+               if (!c)
+               {
+                       ++nprobes;
+                       ++ncells;
+                       //int sz = sizeof(Cell);
+                       if (ncells > m_clampCells)
+                       {
+                               //static int numResets = 0;
+                               //numResets++;
+                               //printf("numResets=%d\n",numResets);
+                               Reset();
+                       }
+
+                       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.safeNormalize();
+#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,
+                                                                                  const btCollisionShape* shape)
+       {
+               btTransform unit;
+               unit.setIdentity();
+               if (shape->isConvex())
+               {
+                       btGjkEpaSolver2::sResults res;
+                       const btConvexShape* csh = static_cast<const 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, const btCollisionShape* shape)
+       {
+               struct btS
+               {
+                       int x, y, z, w;
+                       void* p;
+               };
+
+               btS myset;
+               //memset may be needed in case of additional (uninitialized) padding!
+               //memset(&myset, 0, sizeof(btS));
+
+               myset.x = x;
+               myset.y = y;
+               myset.z = z;
+               myset.w = 0;
+               myset.p = (void*)shape;
+               const char* ptr = (const char*)&myset;
+
+               unsigned int result = HsiehHash(ptr, sizeof(btS));
+
+               return result;
+       }
+};
+
+#endif  //BT_SPARSE_SDF_H
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/poly34.cpp b/dali-physics/third-party/bullet3/src/BulletSoftBody/poly34.cpp
new file mode 100644 (file)
index 0000000..ec7549c
--- /dev/null
@@ -0,0 +1,447 @@
+// poly34.cpp : solution of cubic and quartic equation
+// (c) Khashin S.I. http://math.ivanovo.ac.ru/dalgebra/Khashin/index.html
+// khash2 (at) gmail.com
+// Thanks to Alexandr Rakhmanin <rakhmanin (at) gmail.com>
+// public domain
+//
+#include <math.h>
+
+#include "poly34.h"  // solution of cubic and quartic equation
+#define TwoPi 6.28318530717958648
+const btScalar eps = SIMD_EPSILON;
+
+//=============================================================================
+// _root3, root3 from http://prografix.narod.ru
+//=============================================================================
+static SIMD_FORCE_INLINE btScalar _root3(btScalar x)
+{
+       btScalar s = 1.;
+       while (x < 1.)
+       {
+               x *= 8.;
+               s *= 0.5;
+       }
+       while (x > 8.)
+       {
+               x *= 0.125;
+               s *= 2.;
+       }
+       btScalar r = 1.5;
+       r -= 1. / 3. * (r - x / (r * r));
+       r -= 1. / 3. * (r - x / (r * r));
+       r -= 1. / 3. * (r - x / (r * r));
+       r -= 1. / 3. * (r - x / (r * r));
+       r -= 1. / 3. * (r - x / (r * r));
+       r -= 1. / 3. * (r - x / (r * r));
+       return r * s;
+}
+
+btScalar SIMD_FORCE_INLINE root3(btScalar x)
+{
+       if (x > 0)
+               return _root3(x);
+       else if (x < 0)
+               return -_root3(-x);
+       else
+               return 0.;
+}
+
+// x - array of size 2
+// return 2: 2 real roots x[0], x[1]
+// return 0: pair of complex roots: x[0]i*x[1]
+int SolveP2(btScalar* x, btScalar a, btScalar b)
+{  // solve equation x^2 + a*x + b = 0
+       btScalar D = 0.25 * a * a - b;
+       if (D >= 0)
+       {
+               D = sqrt(D);
+               x[0] = -0.5 * a + D;
+               x[1] = -0.5 * a - D;
+               return 2;
+       }
+       x[0] = -0.5 * a;
+       x[1] = sqrt(-D);
+       return 0;
+}
+//---------------------------------------------------------------------------
+// x - array of size 3
+// In case 3 real roots: => x[0], x[1], x[2], return 3
+//         2 real roots: x[0], x[1],          return 2
+//         1 real root : x[0], x[1]  i*x[2], return 1
+int SolveP3(btScalar* x, btScalar a, btScalar b, btScalar c)
+{  // solve cubic equation x^3 + a*x^2 + b*x + c = 0
+       btScalar a2 = a * a;
+       btScalar q = (a2 - 3 * b) / 9;
+       if (q < 0)
+               q = eps;
+       btScalar r = (a * (2 * a2 - 9 * b) + 27 * c) / 54;
+       // equation x^3 + q*x + r = 0
+       btScalar r2 = r * r;
+       btScalar q3 = q * q * q;
+       btScalar A, B;
+       if (r2 <= (q3 + eps))
+       {  //<<-- FIXED!
+               btScalar t = r / sqrt(q3);
+               if (t < -1)
+                       t = -1;
+               if (t > 1)
+                       t = 1;
+               t = acos(t);
+               a /= 3;
+               q = -2 * sqrt(q);
+               x[0] = q * cos(t / 3) - a;
+               x[1] = q * cos((t + TwoPi) / 3) - a;
+               x[2] = q * cos((t - TwoPi) / 3) - a;
+               return (3);
+       }
+       else
+       {
+               //A =-pow(fabs(r)+sqrt(r2-q3),1./3);
+               A = -root3(fabs(r) + sqrt(r2 - q3));
+               if (r < 0)
+                       A = -A;
+               B = (A == 0 ? 0 : q / A);
+
+               a /= 3;
+               x[0] = (A + B) - a;
+               x[1] = -0.5 * (A + B) - a;
+               x[2] = 0.5 * sqrt(3.) * (A - B);
+               if (fabs(x[2]) < eps)
+               {
+                       x[2] = x[1];
+                       return (2);
+               }
+               return (1);
+       }
+}  // SolveP3(btScalar *x,btScalar a,btScalar b,btScalar c) {
+//---------------------------------------------------------------------------
+// a>=0!
+void CSqrt(btScalar x, btScalar y, btScalar& a, btScalar& b)  // returns:  a+i*s = sqrt(x+i*y)
+{
+       btScalar r = sqrt(x * x + y * y);
+       if (y == 0)
+       {
+               r = sqrt(r);
+               if (x >= 0)
+               {
+                       a = r;
+                       b = 0;
+               }
+               else
+               {
+                       a = 0;
+                       b = r;
+               }
+       }
+       else
+       {  // y != 0
+               a = sqrt(0.5 * (x + r));
+               b = 0.5 * y / a;
+       }
+}
+//---------------------------------------------------------------------------
+int SolveP4Bi(btScalar* x, btScalar b, btScalar d)  // solve equation x^4 + b*x^2 + d = 0
+{
+       btScalar D = b * b - 4 * d;
+       if (D >= 0)
+       {
+               btScalar sD = sqrt(D);
+               btScalar x1 = (-b + sD) / 2;
+               btScalar x2 = (-b - sD) / 2;  // x2 <= x1
+               if (x2 >= 0)                  // 0 <= x2 <= x1, 4 real roots
+               {
+                       btScalar sx1 = sqrt(x1);
+                       btScalar sx2 = sqrt(x2);
+                       x[0] = -sx1;
+                       x[1] = sx1;
+                       x[2] = -sx2;
+                       x[3] = sx2;
+                       return 4;
+               }
+               if (x1 < 0)  // x2 <= x1 < 0, two pair of imaginary roots
+               {
+                       btScalar sx1 = sqrt(-x1);
+                       btScalar sx2 = sqrt(-x2);
+                       x[0] = 0;
+                       x[1] = sx1;
+                       x[2] = 0;
+                       x[3] = sx2;
+                       return 0;
+               }
+               // now x2 < 0 <= x1 , two real roots and one pair of imginary root
+               btScalar sx1 = sqrt(x1);
+               btScalar sx2 = sqrt(-x2);
+               x[0] = -sx1;
+               x[1] = sx1;
+               x[2] = 0;
+               x[3] = sx2;
+               return 2;
+       }
+       else
+       {  // if( D < 0 ), two pair of compex roots
+               btScalar sD2 = 0.5 * sqrt(-D);
+               CSqrt(-0.5 * b, sD2, x[0], x[1]);
+               CSqrt(-0.5 * b, -sD2, x[2], x[3]);
+               return 0;
+       }  // if( D>=0 )
+}  // SolveP4Bi(btScalar *x, btScalar b, btScalar d)    // solve equation x^4 + b*x^2 d
+//---------------------------------------------------------------------------
+#define SWAP(a, b) \
+       {              \
+               t = b;     \
+               b = a;     \
+               a = t;     \
+       }
+static void dblSort3(btScalar& a, btScalar& b, btScalar& c)  // make: a <= b <= c
+{
+       btScalar t;
+       if (a > b)
+               SWAP(a, b);  // now a<=b
+       if (c < b)
+       {
+               SWAP(b, c);  // now a<=b, b<=c
+               if (a > b)
+                       SWAP(a, b);  // now a<=b
+       }
+}
+//---------------------------------------------------------------------------
+int SolveP4De(btScalar* x, btScalar b, btScalar c, btScalar d)  // solve equation x^4 + b*x^2 + c*x + d
+{
+       //if( c==0 ) return SolveP4Bi(x,b,d); // After that, c!=0
+       if (fabs(c) < 1e-14 * (fabs(b) + fabs(d)))
+               return SolveP4Bi(x, b, d);  // After that, c!=0
+
+       int res3 = SolveP3(x, 2 * b, b * b - 4 * d, -c * c);  // solve resolvent
+       // by Viet theorem:  x1*x2*x3=-c*c not equals to 0, so x1!=0, x2!=0, x3!=0
+       if (res3 > 1)  // 3 real roots,
+       {
+               dblSort3(x[0], x[1], x[2]);  // sort roots to x[0] <= x[1] <= x[2]
+               // Note: x[0]*x[1]*x[2]= c*c > 0
+               if (x[0] > 0)  // all roots are positive
+               {
+                       btScalar sz1 = sqrt(x[0]);
+                       btScalar sz2 = sqrt(x[1]);
+                       btScalar sz3 = sqrt(x[2]);
+                       // Note: sz1*sz2*sz3= -c (and not equal to 0)
+                       if (c > 0)
+                       {
+                               x[0] = (-sz1 - sz2 - sz3) / 2;
+                               x[1] = (-sz1 + sz2 + sz3) / 2;
+                               x[2] = (+sz1 - sz2 + sz3) / 2;
+                               x[3] = (+sz1 + sz2 - sz3) / 2;
+                               return 4;
+                       }
+                       // now: c<0
+                       x[0] = (-sz1 - sz2 + sz3) / 2;
+                       x[1] = (-sz1 + sz2 - sz3) / 2;
+                       x[2] = (+sz1 - sz2 - sz3) / 2;
+                       x[3] = (+sz1 + sz2 + sz3) / 2;
+                       return 4;
+               }  // if( x[0] > 0) // all roots are positive
+               // now x[0] <= x[1] < 0, x[2] > 0
+               // two pair of comlex roots
+               btScalar sz1 = sqrt(-x[0]);
+               btScalar sz2 = sqrt(-x[1]);
+               btScalar sz3 = sqrt(x[2]);
+
+               if (c > 0)  // sign = -1
+               {
+                       x[0] = -sz3 / 2;
+                       x[1] = (sz1 - sz2) / 2;  // x[0]i*x[1]
+                       x[2] = sz3 / 2;
+                       x[3] = (-sz1 - sz2) / 2;  // x[2]i*x[3]
+                       return 0;
+               }
+               // now: c<0 , sign = +1
+               x[0] = sz3 / 2;
+               x[1] = (-sz1 + sz2) / 2;
+               x[2] = -sz3 / 2;
+               x[3] = (sz1 + sz2) / 2;
+               return 0;
+       }  // if( res3>1 )    // 3 real roots,
+       // now resoventa have 1 real and pair of compex roots
+       // x[0] - real root, and x[0]>0,
+       // x[1]i*x[2] - complex roots,
+       // x[0] must be >=0. But one times x[0]=~ 1e-17, so:
+       if (x[0] < 0)
+               x[0] = 0;
+       btScalar sz1 = sqrt(x[0]);
+       btScalar szr, szi;
+       CSqrt(x[1], x[2], szr, szi);  // (szr+i*szi)^2 = x[1]+i*x[2]
+       if (c > 0)                    // sign = -1
+       {
+               x[0] = -sz1 / 2 - szr;  // 1st real root
+               x[1] = -sz1 / 2 + szr;  // 2nd real root
+               x[2] = sz1 / 2;
+               x[3] = szi;
+               return 2;
+       }
+       // now: c<0 , sign = +1
+       x[0] = sz1 / 2 - szr;  // 1st real root
+       x[1] = sz1 / 2 + szr;  // 2nd real root
+       x[2] = -sz1 / 2;
+       x[3] = szi;
+       return 2;
+}  // SolveP4De(btScalar *x, btScalar b, btScalar c, btScalar d)    // solve equation x^4 + b*x^2 + c*x + d
+//-----------------------------------------------------------------------------
+btScalar N4Step(btScalar x, btScalar a, btScalar b, btScalar c, btScalar d)  // one Newton step for x^4 + a*x^3 + b*x^2 + c*x + d
+{
+       btScalar fxs = ((4 * x + 3 * a) * x + 2 * b) * x + c;  // f'(x)
+       if (fxs == 0)
+               return x;                                       //return 1e99; <<-- FIXED!
+       btScalar fx = (((x + a) * x + b) * x + c) * x + d;  // f(x)
+       return x - fx / fxs;
+}
+//-----------------------------------------------------------------------------
+// x - array of size 4
+// return 4: 4 real roots x[0], x[1], x[2], x[3], possible multiple roots
+// return 2: 2 real roots x[0], x[1] and complex x[2]i*x[3],
+// return 0: two pair of complex roots: x[0]i*x[1],  x[2]i*x[3],
+int SolveP4(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d)
+{  // solve equation x^4 + a*x^3 + b*x^2 + c*x + d by Dekart-Euler method
+       // move to a=0:
+       btScalar d1 = d + 0.25 * a * (0.25 * b * a - 3. / 64 * a * a * a - c);
+       btScalar c1 = c + 0.5 * a * (0.25 * a * a - b);
+       btScalar b1 = b - 0.375 * a * a;
+       int res = SolveP4De(x, b1, c1, d1);
+       if (res == 4)
+       {
+               x[0] -= a / 4;
+               x[1] -= a / 4;
+               x[2] -= a / 4;
+               x[3] -= a / 4;
+       }
+       else if (res == 2)
+       {
+               x[0] -= a / 4;
+               x[1] -= a / 4;
+               x[2] -= a / 4;
+       }
+       else
+       {
+               x[0] -= a / 4;
+               x[2] -= a / 4;
+       }
+       // one Newton step for each real root:
+       if (res > 0)
+       {
+               x[0] = N4Step(x[0], a, b, c, d);
+               x[1] = N4Step(x[1], a, b, c, d);
+       }
+       if (res > 2)
+       {
+               x[2] = N4Step(x[2], a, b, c, d);
+               x[3] = N4Step(x[3], a, b, c, d);
+       }
+       return res;
+}
+//-----------------------------------------------------------------------------
+#define F5(t) (((((t + a) * t + b) * t + c) * t + d) * t + e)
+//-----------------------------------------------------------------------------
+btScalar SolveP5_1(btScalar a, btScalar b, btScalar c, btScalar d, btScalar e)  // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+{
+       int cnt;
+       if (fabs(e) < eps)
+               return 0;
+
+       btScalar brd = fabs(a);  // brd - border of real roots
+       if (fabs(b) > brd)
+               brd = fabs(b);
+       if (fabs(c) > brd)
+               brd = fabs(c);
+       if (fabs(d) > brd)
+               brd = fabs(d);
+       if (fabs(e) > brd)
+               brd = fabs(e);
+       brd++;  // brd - border of real roots
+
+       btScalar x0, f0;       // less than root
+       btScalar x1, f1;       // greater than root
+       btScalar x2, f2, f2s;  // next values, f(x2), f'(x2)
+       btScalar dx = 0;
+
+       if (e < 0)
+       {
+               x0 = 0;
+               x1 = brd;
+               f0 = e;
+               f1 = F5(x1);
+               x2 = 0.01 * brd;
+       }  // positive root
+       else
+       {
+               x0 = -brd;
+               x1 = 0;
+               f0 = F5(x0);
+               f1 = e;
+               x2 = -0.01 * brd;
+       }  // negative root
+
+       if (fabs(f0) < eps)
+               return x0;
+       if (fabs(f1) < eps)
+               return x1;
+
+       // now x0<x1, f(x0)<0, f(x1)>0
+       // Firstly 10 bisections
+       for (cnt = 0; cnt < 10; cnt++)
+       {
+               x2 = (x0 + x1) / 2;  // next point
+               //x2 = x0 - f0*(x1 - x0) / (f1 - f0);        // next point
+               f2 = F5(x2);  // f(x2)
+               if (fabs(f2) < eps)
+                       return x2;
+               if (f2 > 0)
+               {
+                       x1 = x2;
+                       f1 = f2;
+               }
+               else
+               {
+                       x0 = x2;
+                       f0 = f2;
+               }
+       }
+
+       // At each step:
+       // x0<x1, f(x0)<0, f(x1)>0.
+       // x2 - next value
+       // we hope that x0 < x2 < x1, but not necessarily
+       do
+       {
+               if (cnt++ > 50)
+                       break;
+               if (x2 <= x0 || x2 >= x1)
+                       x2 = (x0 + x1) / 2;  // now  x0 < x2 < x1
+               f2 = F5(x2);             // f(x2)
+               if (fabs(f2) < eps)
+                       return x2;
+               if (f2 > 0)
+               {
+                       x1 = x2;
+                       f1 = f2;
+               }
+               else
+               {
+                       x0 = x2;
+                       f0 = f2;
+               }
+               f2s = (((5 * x2 + 4 * a) * x2 + 3 * b) * x2 + 2 * c) * x2 + d;  // f'(x2)
+               if (fabs(f2s) < eps)
+               {
+                       x2 = 1e99;
+                       continue;
+               }
+               dx = f2 / f2s;
+               x2 -= dx;
+       } while (fabs(dx) > eps);
+       return x2;
+}  // SolveP5_1(btScalar a,btScalar b,btScalar c,btScalar d,btScalar e)    // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+//-----------------------------------------------------------------------------
+int SolveP5(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d, btScalar e)  // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+{
+       btScalar r = x[0] = SolveP5_1(a, b, c, d, e);
+       btScalar a1 = a + r, b1 = b + r * a1, c1 = c + r * b1, d1 = d + r * c1;
+       return 1 + SolveP4(x + 1, a1, b1, c1, d1);
+}  // SolveP5(btScalar *x,btScalar a,btScalar b,btScalar c,btScalar d,btScalar e)    // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+//-----------------------------------------------------------------------------
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/poly34.h b/dali-physics/third-party/bullet3/src/BulletSoftBody/poly34.h
new file mode 100644 (file)
index 0000000..35a52c5
--- /dev/null
@@ -0,0 +1,38 @@
+// poly34.h : solution of cubic and quartic equation
+// (c) Khashin S.I. http://math.ivanovo.ac.ru/dalgebra/Khashin/index.html
+// khash2 (at) gmail.com
+
+#ifndef POLY_34
+#define POLY_34
+#include "LinearMath/btScalar.h"
+// x - array of size 2
+// return 2: 2 real roots x[0], x[1]
+// return 0: pair of complex roots: x[0]i*x[1]
+int SolveP2(btScalar* x, btScalar a, btScalar b);  // solve equation x^2 + a*x + b = 0
+
+// x - array of size 3
+// return 3: 3 real roots x[0], x[1], x[2]
+// return 1: 1 real root x[0] and pair of complex roots: x[1]i*x[2]
+int SolveP3(btScalar* x, btScalar a, btScalar b, btScalar c);  // solve cubic equation x^3 + a*x^2 + b*x + c = 0
+
+// x - array of size 4
+// return 4: 4 real roots x[0], x[1], x[2], x[3], possible multiple roots
+// return 2: 2 real roots x[0], x[1] and complex x[2]i*x[3],
+// return 0: two pair of complex roots: x[0]i*x[1],  x[2]i*x[3],
+int SolveP4(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d);  // solve equation x^4 + a*x^3 + b*x^2 + c*x + d = 0 by Dekart-Euler method
+
+// x - array of size 5
+// return 5: 5 real roots x[0], x[1], x[2], x[3], x[4], possible multiple roots
+// return 3: 3 real roots x[0], x[1], x[2] and complex x[3]i*x[4],
+// return 1: 1 real root x[0] and two pair of complex roots: x[1]i*x[2],  x[3]i*x[4],
+int SolveP5(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d, btScalar e);  // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+
+//-----------------------------------------------------------------------------
+// And some additional functions for internal use.
+// Your may remove this definitions from here
+int SolveP4Bi(btScalar* x, btScalar b, btScalar d);                              // solve equation x^4 + b*x^2 + d = 0
+int SolveP4De(btScalar* x, btScalar b, btScalar c, btScalar d);                  // solve equation x^4 + b*x^2 + c*x + d = 0
+void CSqrt(btScalar x, btScalar y, btScalar& a, btScalar& b);                    // returns as a+i*s,  sqrt(x+i*y)
+btScalar N4Step(btScalar x, btScalar a, btScalar b, btScalar c, btScalar d);     // one Newton step for x^4 + a*x^3 + b*x^2 + c*x + d
+btScalar SolveP5_1(btScalar a, btScalar b, btScalar c, btScalar d, btScalar e);  // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
+#endif
diff --git a/dali-physics/third-party/bullet3/src/BulletSoftBody/premake4.lua b/dali-physics/third-party/bullet3/src/BulletSoftBody/premake4.lua
new file mode 100644 (file)
index 0000000..370bd98
--- /dev/null
@@ -0,0 +1,15 @@
+       project "BulletSoftBody"
+               
+       kind "StaticLib"
+       
+       includedirs {
+               "..",
+       }
+    if os.is("Linux") then
+        buildoptions{"-fPIC"}
+    end
+       files {
+               "**.cpp",
+                "BulletReducedDeformableBody/**.cpp",
+               "**.h"
+       }
diff --git a/dali-physics/third-party/bullet3/src/CMakeLists.txt b/dali-physics/third-party/bullet3/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c30125c
--- /dev/null
@@ -0,0 +1,19 @@
+
+IF(BUILD_BULLET3)
+       SUBDIRS(  Bullet3OpenCL Bullet3Serialize/Bullet2FileLoader Bullet3Dynamics Bullet3Collision Bullet3Geometry )
+ENDIF(BUILD_BULLET3)
+
+
+SUBDIRS(   BulletInverseDynamics BulletSoftBody BulletCollision BulletDynamics LinearMath Bullet3Common)
+
+
+IF(INSTALL_LIBS)
+       #INSTALL of other files requires CMake 2.6
+       IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       # Don't actually need to install any common files, the frameworks include everything
+               ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       INSTALL(FILES btBulletCollisionCommon.h btBulletDynamicsCommon.h  DESTINATION ${INCLUDE_INSTALL_DIR})
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+ENDIF(INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/CMakeLists.txt b/dali-physics/third-party/bullet3/src/LinearMath/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a0532c7
--- /dev/null
@@ -0,0 +1,83 @@
+
+INCLUDE_DIRECTORIES(
+       ${BULLET_PHYSICS_SOURCE_DIR}/src
+)
+
+SET(LinearMath_SRCS
+       btAlignedAllocator.cpp
+       btConvexHull.cpp
+       btConvexHullComputer.cpp
+       btGeometryUtil.cpp
+       btPolarDecomposition.cpp
+       btQuickprof.cpp
+       btReducedVector.cpp
+       btSerializer.cpp
+       btSerializer64.cpp
+       btThreads.cpp
+       btVector3.cpp
+       TaskScheduler/btTaskScheduler.cpp
+       TaskScheduler/btThreadSupportPosix.cpp
+       TaskScheduler/btThreadSupportWin32.cpp
+)
+
+SET(LinearMath_HDRS
+       btAabbUtil2.h
+       btAlignedAllocator.h
+       btAlignedObjectArray.h
+       btConvexHull.h
+       btConvexHullComputer.h
+       btDefaultMotionState.h
+       btGeometryUtil.h
+       btGrahamScan2dConvexHull.h
+       btHashMap.h
+       btIDebugDraw.h
+       btList.h
+       btMatrix3x3.h
+       btImplicitQRSVD.h
+       btMinMax.h
+       btModifiedGramSchmidt.h
+       btMotionState.h
+       btPolarDecomposition.h
+       btPoolAllocator.h
+       btQuadWord.h
+       btQuaternion.h
+       btQuickprof.h
+       btReducedVector.h
+       btRandom.h
+       btScalar.h
+       btSerializer.h
+       btStackAlloc.h
+       btThreads.h
+       btTransform.h
+       btTransformUtil.h
+       btVector3.h
+       TaskScheduler/btThreadSupportInterface.h
+)
+
+ADD_LIBRARY(LinearMath ${LinearMath_SRCS} ${LinearMath_HDRS})
+SET_TARGET_PROPERTIES(LinearMath PROPERTIES VERSION ${BULLET_VERSION})
+SET_TARGET_PROPERTIES(LinearMath PROPERTIES SOVERSION ${BULLET_VERSION})
+
+IF (INSTALL_LIBS)
+       IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+               #FILES_MATCHING requires CMake 2.6
+               IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+                       IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS LinearMath DESTINATION .)
+                       ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                               INSTALL(TARGETS LinearMath
+                                       RUNTIME DESTINATION bin
+                                       LIBRARY DESTINATION lib${LIB_SUFFIX}
+                                       ARCHIVE DESTINATION lib${LIB_SUFFIX})
+                               INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h"  PATTERN
+".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
+                       ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+               ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
+
+               IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+                       SET_TARGET_PROPERTIES(LinearMath PROPERTIES FRAMEWORK true)
+                       SET_TARGET_PROPERTIES(LinearMath PROPERTIES PUBLIC_HEADER "${LinearMath_HDRS}")
+               ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
+       ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
+ENDIF (INSTALL_LIBS)
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btTaskScheduler.cpp b/dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btTaskScheduler.cpp
new file mode 100644 (file)
index 0000000..5f1115c
--- /dev/null
@@ -0,0 +1,792 @@
+
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btThreads.h"
+#include "LinearMath/btQuickprof.h"
+#include <stdio.h>
+#include <algorithm>
+
+#if BT_THREADSAFE
+
+#include "btThreadSupportInterface.h"
+
+#if defined(_WIN32)
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+
+#endif
+
+typedef unsigned long long btU64;
+static const int kCacheLineSize = 64;
+
+void btSpinPause()
+{
+#if defined(_WIN32)
+       YieldProcessor();
+#endif
+}
+
+struct WorkerThreadStatus
+{
+       enum Type
+       {
+               kInvalid,
+               kWaitingForWork,
+               kWorking,
+               kSleeping,
+       };
+};
+
+ATTRIBUTE_ALIGNED64(class)
+WorkerThreadDirectives
+{
+       static const int kMaxThreadCount = BT_MAX_THREAD_COUNT;
+       // directives for all worker threads packed into a single cacheline
+       char m_threadDirs[kMaxThreadCount];
+
+public:
+       enum Type
+       {
+               kInvalid,
+               kGoToSleep,         // go to sleep
+               kStayAwakeButIdle,  // wait for not checking job queue
+               kScanForJobs,       // actively scan job queue for jobs
+       };
+       WorkerThreadDirectives()
+       {
+               for (int i = 0; i < kMaxThreadCount; ++i)
+               {
+                       m_threadDirs[i] = 0;
+               }
+       }
+
+       Type getDirective(int threadId)
+       {
+               btAssert(threadId < kMaxThreadCount);
+               return static_cast<Type>(m_threadDirs[threadId]);
+       }
+
+       void setDirectiveByRange(int threadBegin, int threadEnd, Type dir)
+       {
+               btAssert(threadBegin < threadEnd);
+               btAssert(threadEnd <= kMaxThreadCount);
+               char dirChar = static_cast<char>(dir);
+               for (int i = threadBegin; i < threadEnd; ++i)
+               {
+                       m_threadDirs[i] = dirChar;
+               }
+       }
+};
+
+class JobQueue;
+
+ATTRIBUTE_ALIGNED64(struct)
+ThreadLocalStorage
+{
+       int m_threadId;
+       WorkerThreadStatus::Type m_status;
+       int m_numJobsFinished;
+       btSpinMutex m_mutex;
+       btScalar m_sumResult;
+       WorkerThreadDirectives* m_directive;
+       JobQueue* m_queue;
+       btClock* m_clock;
+       unsigned int m_cooldownTime;
+};
+
+struct IJob
+{
+       virtual void executeJob(int threadId) = 0;
+};
+
+class ParallelForJob : public IJob
+{
+       const btIParallelForBody* m_body;
+       int m_begin;
+       int m_end;
+
+public:
+       ParallelForJob(int iBegin, int iEnd, const btIParallelForBody& body)
+       {
+               m_body = &body;
+               m_begin = iBegin;
+               m_end = iEnd;
+       }
+       virtual void executeJob(int threadId) BT_OVERRIDE
+       {
+               BT_PROFILE("executeJob");
+
+               // call the functor body to do the work
+               m_body->forLoop(m_begin, m_end);
+       }
+};
+
+class ParallelSumJob : public IJob
+{
+       const btIParallelSumBody* m_body;
+       ThreadLocalStorage* m_threadLocalStoreArray;
+       int m_begin;
+       int m_end;
+
+public:
+       ParallelSumJob(int iBegin, int iEnd, const btIParallelSumBody& body, ThreadLocalStorage* tls)
+       {
+               m_body = &body;
+               m_threadLocalStoreArray = tls;
+               m_begin = iBegin;
+               m_end = iEnd;
+       }
+       virtual void executeJob(int threadId) BT_OVERRIDE
+       {
+               BT_PROFILE("executeJob");
+
+               // call the functor body to do the work
+               btScalar val = m_body->sumLoop(m_begin, m_end);
+#if BT_PARALLEL_SUM_DETERMINISTISM
+               // by truncating bits of the result, we can make the parallelSum deterministic (at the expense of precision)
+               const float TRUNC_SCALE = float(1 << 19);
+               val = floor(val * TRUNC_SCALE + 0.5f) / TRUNC_SCALE;  // truncate some bits
+#endif
+               m_threadLocalStoreArray[threadId].m_sumResult += val;
+       }
+};
+
+ATTRIBUTE_ALIGNED64(class)
+JobQueue
+{
+       btThreadSupportInterface* m_threadSupport;
+       btCriticalSection* m_queueLock;
+       btSpinMutex m_mutex;
+
+       btAlignedObjectArray<IJob*> m_jobQueue;
+       char* m_jobMem;
+       int m_jobMemSize;
+       bool m_queueIsEmpty;
+       int m_tailIndex;
+       int m_headIndex;
+       int m_allocSize;
+       bool m_useSpinMutex;
+       btAlignedObjectArray<JobQueue*> m_neighborContexts;
+       char m_cachePadding[kCacheLineSize];  // prevent false sharing
+
+       void freeJobMem()
+       {
+               if (m_jobMem)
+               {
+                       // free old
+                       btAlignedFree(m_jobMem);
+                       m_jobMem = NULL;
+               }
+       }
+       void resizeJobMem(int newSize)
+       {
+               if (newSize > m_jobMemSize)
+               {
+                       freeJobMem();
+                       m_jobMem = static_cast<char*>(btAlignedAlloc(newSize, kCacheLineSize));
+                       m_jobMemSize = newSize;
+               }
+       }
+
+public:
+       JobQueue()
+       {
+               m_jobMem = NULL;
+               m_jobMemSize = 0;
+               m_threadSupport = NULL;
+               m_queueLock = NULL;
+               m_headIndex = 0;
+               m_tailIndex = 0;
+               m_useSpinMutex = false;
+       }
+       ~JobQueue()
+       {
+               exit();
+       }
+       void exit()
+       {
+               freeJobMem();
+               if (m_queueLock && m_threadSupport)
+               {
+                       m_threadSupport->deleteCriticalSection(m_queueLock);
+                       m_queueLock = NULL;
+                       m_threadSupport = 0;
+               }
+       }
+
+       void init(btThreadSupportInterface * threadSup, btAlignedObjectArray<JobQueue> * contextArray)
+       {
+               m_threadSupport = threadSup;
+               if (threadSup)
+               {
+                       m_queueLock = m_threadSupport->createCriticalSection();
+               }
+               setupJobStealing(contextArray, contextArray->size());
+       }
+       void setupJobStealing(btAlignedObjectArray<JobQueue> * contextArray, int numActiveContexts)
+       {
+               btAlignedObjectArray<JobQueue>& contexts = *contextArray;
+               int selfIndex = 0;
+               for (int i = 0; i < contexts.size(); ++i)
+               {
+                       if (this == &contexts[i])
+                       {
+                               selfIndex = i;
+                               break;
+                       }
+               }
+               int numNeighbors = btMin(2, contexts.size() - 1);
+               int neighborOffsets[] = {-1, 1, -2, 2, -3, 3};
+               int numOffsets = sizeof(neighborOffsets) / sizeof(neighborOffsets[0]);
+               m_neighborContexts.reserve(numNeighbors);
+               m_neighborContexts.resizeNoInitialize(0);
+               for (int i = 0; i < numOffsets && m_neighborContexts.size() < numNeighbors; i++)
+               {
+                       int neighborIndex = selfIndex + neighborOffsets[i];
+                       if (neighborIndex >= 0 && neighborIndex < numActiveContexts)
+                       {
+                               m_neighborContexts.push_back(&contexts[neighborIndex]);
+                       }
+               }
+       }
+
+       bool isQueueEmpty() const { return m_queueIsEmpty; }
+       void lockQueue()
+       {
+               if (m_useSpinMutex)
+               {
+                       m_mutex.lock();
+               }
+               else
+               {
+                       m_queueLock->lock();
+               }
+       }
+       void unlockQueue()
+       {
+               if (m_useSpinMutex)
+               {
+                       m_mutex.unlock();
+               }
+               else
+               {
+                       m_queueLock->unlock();
+               }
+       }
+       void clearQueue(int jobCount, int jobSize)
+       {
+               lockQueue();
+               m_headIndex = 0;
+               m_tailIndex = 0;
+               m_allocSize = 0;
+               m_queueIsEmpty = true;
+               int jobBufSize = jobSize * jobCount;
+               // make sure we have enough memory allocated to store jobs
+               if (jobBufSize > m_jobMemSize)
+               {
+                       resizeJobMem(jobBufSize);
+               }
+               // make sure job queue is big enough
+               if (jobCount > m_jobQueue.capacity())
+               {
+                       m_jobQueue.reserve(jobCount);
+               }
+               unlockQueue();
+               m_jobQueue.resizeNoInitialize(0);
+       }
+       void* allocJobMem(int jobSize)
+       {
+               btAssert(m_jobMemSize >= (m_allocSize + jobSize));
+               void* jobMem = &m_jobMem[m_allocSize];
+               m_allocSize += jobSize;
+               return jobMem;
+       }
+       void submitJob(IJob * job)
+       {
+               btAssert(reinterpret_cast<char*>(job) >= &m_jobMem[0] && reinterpret_cast<char*>(job) < &m_jobMem[0] + m_allocSize);
+               m_jobQueue.push_back(job);
+               lockQueue();
+               m_tailIndex++;
+               m_queueIsEmpty = false;
+               unlockQueue();
+       }
+       IJob* consumeJobFromOwnQueue()
+       {
+               if (m_queueIsEmpty)
+               {
+                       // lock free path. even if this is taken erroneously it isn't harmful
+                       return NULL;
+               }
+               IJob* job = NULL;
+               lockQueue();
+               if (!m_queueIsEmpty)
+               {
+                       job = m_jobQueue[m_headIndex++];
+                       btAssert(reinterpret_cast<char*>(job) >= &m_jobMem[0] && reinterpret_cast<char*>(job) < &m_jobMem[0] + m_allocSize);
+                       if (m_headIndex == m_tailIndex)
+                       {
+                               m_queueIsEmpty = true;
+                       }
+               }
+               unlockQueue();
+               return job;
+       }
+       IJob* consumeJob()
+       {
+               if (IJob* job = consumeJobFromOwnQueue())
+               {
+                       return job;
+               }
+               // own queue is empty, try to steal from neighbor
+               for (int i = 0; i < m_neighborContexts.size(); ++i)
+               {
+                       JobQueue* otherContext = m_neighborContexts[i];
+                       if (IJob* job = otherContext->consumeJobFromOwnQueue())
+                       {
+                               return job;
+                       }
+               }
+               return NULL;
+       }
+};
+
+static void WorkerThreadFunc(void* userPtr)
+{
+       BT_PROFILE("WorkerThreadFunc");
+       ThreadLocalStorage* localStorage = (ThreadLocalStorage*)userPtr;
+       JobQueue* jobQueue = localStorage->m_queue;
+
+       bool shouldSleep = false;
+       int threadId = localStorage->m_threadId;
+       while (!shouldSleep)
+       {
+               // do work
+               localStorage->m_mutex.lock();
+               while (IJob* job = jobQueue->consumeJob())
+               {
+                       localStorage->m_status = WorkerThreadStatus::kWorking;
+                       job->executeJob(threadId);
+                       localStorage->m_numJobsFinished++;
+               }
+               localStorage->m_status = WorkerThreadStatus::kWaitingForWork;
+               localStorage->m_mutex.unlock();
+               btU64 clockStart = localStorage->m_clock->getTimeMicroseconds();
+               // while queue is empty,
+               while (jobQueue->isQueueEmpty())
+               {
+                       // todo: spin wait a bit to avoid hammering the empty queue
+                       btSpinPause();
+                       if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kGoToSleep)
+                       {
+                               shouldSleep = true;
+                               break;
+                       }
+                       // if jobs are incoming,
+                       if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kScanForJobs)
+                       {
+                               clockStart = localStorage->m_clock->getTimeMicroseconds();  // reset clock
+                       }
+                       else
+                       {
+                               for (int i = 0; i < 50; ++i)
+                               {
+                                       btSpinPause();
+                                       btSpinPause();
+                                       btSpinPause();
+                                       btSpinPause();
+                                       if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kScanForJobs || !jobQueue->isQueueEmpty())
+                                       {
+                                               break;
+                                       }
+                               }
+                               // if no jobs incoming and queue has been empty for the cooldown time, sleep
+                               btU64 timeElapsed = localStorage->m_clock->getTimeMicroseconds() - clockStart;
+                               if (timeElapsed > localStorage->m_cooldownTime)
+                               {
+                                       shouldSleep = true;
+                                       break;
+                               }
+                       }
+               }
+       }
+       {
+               BT_PROFILE("sleep");
+               // go sleep
+               localStorage->m_mutex.lock();
+               localStorage->m_status = WorkerThreadStatus::kSleeping;
+               localStorage->m_mutex.unlock();
+       }
+}
+
+class btTaskSchedulerDefault : public btITaskScheduler
+{
+       btThreadSupportInterface* m_threadSupport;
+       WorkerThreadDirectives* m_workerDirective;
+       btAlignedObjectArray<JobQueue> m_jobQueues;
+       btAlignedObjectArray<JobQueue*> m_perThreadJobQueues;
+       btAlignedObjectArray<ThreadLocalStorage> m_threadLocalStorage;
+       btSpinMutex m_antiNestingLock;  // prevent nested parallel-for
+       btClock m_clock;
+       int m_numThreads;
+       int m_numWorkerThreads;
+       int m_numActiveJobQueues;
+       int m_maxNumThreads;
+       int m_numJobs;
+       static const int kFirstWorkerThreadId = 1;
+
+public:
+       btTaskSchedulerDefault() : btITaskScheduler("ThreadSupport")
+       {
+               m_threadSupport = NULL;
+               m_workerDirective = NULL;
+       }
+
+       virtual ~btTaskSchedulerDefault()
+       {
+               waitForWorkersToSleep();
+
+               for (int i = 0; i < m_jobQueues.size(); ++i)
+               {
+                       m_jobQueues[i].exit();
+               }
+
+               if (m_threadSupport)
+               {
+                       delete m_threadSupport;
+                       m_threadSupport = NULL;
+               }
+               if (m_workerDirective)
+               {
+                       btAlignedFree(m_workerDirective);
+                       m_workerDirective = NULL;
+               }
+       }
+
+       void init()
+       {
+               btThreadSupportInterface::ConstructionInfo constructionInfo("TaskScheduler", WorkerThreadFunc);
+               m_threadSupport = btThreadSupportInterface::create(constructionInfo);
+               m_workerDirective = static_cast<WorkerThreadDirectives*>(btAlignedAlloc(sizeof(*m_workerDirective), 64));
+
+               m_numWorkerThreads = m_threadSupport->getNumWorkerThreads();
+               m_maxNumThreads = m_threadSupport->getNumWorkerThreads() + 1;
+               m_numThreads = m_maxNumThreads;
+               // ideal to have one job queue for each physical processor (except for the main thread which needs no queue)
+               int numThreadsPerQueue = m_threadSupport->getLogicalToPhysicalCoreRatio();
+               int numJobQueues = (numThreadsPerQueue == 1) ? (m_maxNumThreads - 1) : (m_maxNumThreads / numThreadsPerQueue);
+               m_jobQueues.resize(numJobQueues);
+               m_numActiveJobQueues = numJobQueues;
+               for (int i = 0; i < m_jobQueues.size(); ++i)
+               {
+                       m_jobQueues[i].init(m_threadSupport, &m_jobQueues);
+               }
+               m_perThreadJobQueues.resize(m_numThreads);
+               for (int i = 0; i < m_numThreads; i++)
+               {
+                       JobQueue* jq = NULL;
+                       // only worker threads get a job queue
+                       if (i > 0)
+                       {
+                               if (numThreadsPerQueue == 1)
+                               {
+                                       // one queue per worker thread
+                                       jq = &m_jobQueues[i - kFirstWorkerThreadId];
+                               }
+                               else
+                               {
+                                       // 2 threads share each queue
+                                       jq = &m_jobQueues[i / numThreadsPerQueue];
+                               }
+                       }
+                       m_perThreadJobQueues[i] = jq;
+               }
+               m_threadLocalStorage.resize(m_numThreads);
+               for (int i = 0; i < m_numThreads; i++)
+               {
+                       ThreadLocalStorage& storage = m_threadLocalStorage[i];
+                       storage.m_threadId = i;
+                       storage.m_directive = m_workerDirective;
+                       storage.m_status = WorkerThreadStatus::kSleeping;
+                       storage.m_cooldownTime = 100;  // 100 microseconds, threads go to sleep after this long if they have nothing to do
+                       storage.m_clock = &m_clock;
+                       storage.m_queue = m_perThreadJobQueues[i];
+               }
+               setWorkerDirectives(WorkerThreadDirectives::kGoToSleep);  // no work for them yet
+               setNumThreads(m_threadSupport->getCacheFriendlyNumThreads());
+       }
+
+       void setWorkerDirectives(WorkerThreadDirectives::Type dir)
+       {
+               m_workerDirective->setDirectiveByRange(kFirstWorkerThreadId, m_numThreads, dir);
+       }
+
+       virtual int getMaxNumThreads() const BT_OVERRIDE
+       {
+               return m_maxNumThreads;
+       }
+
+       virtual int getNumThreads() const BT_OVERRIDE
+       {
+               return m_numThreads;
+       }
+
+       virtual void setNumThreads(int numThreads) BT_OVERRIDE
+       {
+               m_numThreads = btMax(btMin(numThreads, int(m_maxNumThreads)), 1);
+               m_numWorkerThreads = m_numThreads - 1;
+               m_numActiveJobQueues = 0;
+               // if there is at least 1 worker,
+               if (m_numWorkerThreads > 0)
+               {
+                       // re-setup job stealing between queues to avoid attempting to steal from an inactive job queue
+                       JobQueue* lastActiveContext = m_perThreadJobQueues[m_numThreads - 1];
+                       int iLastActiveContext = lastActiveContext - &m_jobQueues[0];
+                       m_numActiveJobQueues = iLastActiveContext + 1;
+                       for (int i = 0; i < m_jobQueues.size(); ++i)
+                       {
+                               m_jobQueues[i].setupJobStealing(&m_jobQueues, m_numActiveJobQueues);
+                       }
+               }
+               m_workerDirective->setDirectiveByRange(m_numThreads, BT_MAX_THREAD_COUNT, WorkerThreadDirectives::kGoToSleep);
+       }
+
+       void waitJobs()
+       {
+               BT_PROFILE("waitJobs");
+               // have the main thread work until the job queues are empty
+               int numMainThreadJobsFinished = 0;
+               for (int i = 0; i < m_numActiveJobQueues; ++i)
+               {
+                       while (IJob* job = m_jobQueues[i].consumeJob())
+                       {
+                               job->executeJob(0);
+                               numMainThreadJobsFinished++;
+                       }
+               }
+
+               // done with jobs for now, tell workers to rest (but not sleep)
+               setWorkerDirectives(WorkerThreadDirectives::kStayAwakeButIdle);
+
+               btU64 clockStart = m_clock.getTimeMicroseconds();
+               // wait for workers to finish any jobs in progress
+               while (true)
+               {
+                       int numWorkerJobsFinished = 0;
+                       for (int iThread = kFirstWorkerThreadId; iThread < m_numThreads; ++iThread)
+                       {
+                               ThreadLocalStorage* storage = &m_threadLocalStorage[iThread];
+                               storage->m_mutex.lock();
+                               numWorkerJobsFinished += storage->m_numJobsFinished;
+                               storage->m_mutex.unlock();
+                       }
+                       if (numWorkerJobsFinished + numMainThreadJobsFinished == m_numJobs)
+                       {
+                               break;
+                       }
+                       btU64 timeElapsed = m_clock.getTimeMicroseconds() - clockStart;
+                       btAssert(timeElapsed < 1000);
+                       if (timeElapsed > 100000)
+                       {
+                               break;
+                       }
+                       btSpinPause();
+               }
+       }
+
+       void wakeWorkers(int numWorkersToWake)
+       {
+               BT_PROFILE("wakeWorkers");
+               btAssert(m_workerDirective->getDirective(1) == WorkerThreadDirectives::kScanForJobs);
+               int numDesiredWorkers = btMin(numWorkersToWake, m_numWorkerThreads);
+               int numActiveWorkers = 0;
+               for (int iWorker = 0; iWorker < m_numWorkerThreads; ++iWorker)
+               {
+                       // note this count of active workers is not necessarily totally reliable, because a worker thread could be
+                       // just about to put itself to sleep. So we may on occasion fail to wake up all the workers. It should be rare.
+                       ThreadLocalStorage& storage = m_threadLocalStorage[kFirstWorkerThreadId + iWorker];
+                       if (storage.m_status != WorkerThreadStatus::kSleeping)
+                       {
+                               numActiveWorkers++;
+                       }
+               }
+               for (int iWorker = 0; iWorker < m_numWorkerThreads && numActiveWorkers < numDesiredWorkers; ++iWorker)
+               {
+                       ThreadLocalStorage& storage = m_threadLocalStorage[kFirstWorkerThreadId + iWorker];
+                       if (storage.m_status == WorkerThreadStatus::kSleeping)
+                       {
+                               m_threadSupport->runTask(iWorker, &storage);
+                               numActiveWorkers++;
+                       }
+               }
+       }
+
+       void waitForWorkersToSleep()
+       {
+               BT_PROFILE("waitForWorkersToSleep");
+               setWorkerDirectives(WorkerThreadDirectives::kGoToSleep);
+               m_threadSupport->waitForAllTasks();
+               for (int i = kFirstWorkerThreadId; i < m_numThreads; i++)
+               {
+                       ThreadLocalStorage& storage = m_threadLocalStorage[i];
+                       btAssert(storage.m_status == WorkerThreadStatus::kSleeping);
+               }
+       }
+
+       virtual void sleepWorkerThreadsHint() BT_OVERRIDE
+       {
+               BT_PROFILE("sleepWorkerThreadsHint");
+               // hint the task scheduler that we may not be using these threads for a little while
+               setWorkerDirectives(WorkerThreadDirectives::kGoToSleep);
+       }
+
+       void prepareWorkerThreads()
+       {
+               for (int i = kFirstWorkerThreadId; i < m_numThreads; ++i)
+               {
+                       ThreadLocalStorage& storage = m_threadLocalStorage[i];
+                       storage.m_mutex.lock();
+                       storage.m_numJobsFinished = 0;
+                       storage.m_mutex.unlock();
+               }
+               setWorkerDirectives(WorkerThreadDirectives::kScanForJobs);
+       }
+
+       virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
+       {
+               BT_PROFILE("parallelFor_ThreadSupport");
+               btAssert(iEnd >= iBegin);
+               btAssert(grainSize >= 1);
+               int iterationCount = iEnd - iBegin;
+               if (iterationCount > grainSize && m_numWorkerThreads > 0 && m_antiNestingLock.tryLock())
+               {
+                       typedef ParallelForJob JobType;
+                       int jobCount = (iterationCount + grainSize - 1) / grainSize;
+                       m_numJobs = jobCount;
+                       btAssert(jobCount >= 2);  // need more than one job for multithreading
+                       int jobSize = sizeof(JobType);
+
+                       for (int i = 0; i < m_numActiveJobQueues; ++i)
+                       {
+                               m_jobQueues[i].clearQueue(jobCount, jobSize);
+                       }
+                       // prepare worker threads for incoming work
+                       prepareWorkerThreads();
+                       // submit all of the jobs
+                       int iJob = 0;
+                       int iThread = kFirstWorkerThreadId;  // first worker thread
+                       for (int i = iBegin; i < iEnd; i += grainSize)
+                       {
+                               btAssert(iJob < jobCount);
+                               int iE = btMin(i + grainSize, iEnd);
+                               JobQueue* jq = m_perThreadJobQueues[iThread];
+                               btAssert(jq);
+                               btAssert((jq - &m_jobQueues[0]) < m_numActiveJobQueues);
+                               void* jobMem = jq->allocJobMem(jobSize);
+                               JobType* job = new (jobMem) ParallelForJob(i, iE, body);  // placement new
+                               jq->submitJob(job);
+                               iJob++;
+                               iThread++;
+                               if (iThread >= m_numThreads)
+                               {
+                                       iThread = kFirstWorkerThreadId;  // first worker thread
+                               }
+                       }
+                       wakeWorkers(jobCount - 1);
+
+                       // put the main thread to work on emptying the job queue and then wait for all workers to finish
+                       waitJobs();
+                       m_antiNestingLock.unlock();
+               }
+               else
+               {
+                       BT_PROFILE("parallelFor_mainThread");
+                       // just run on main thread
+                       body.forLoop(iBegin, iEnd);
+               }
+       }
+       virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
+       {
+               BT_PROFILE("parallelSum_ThreadSupport");
+               btAssert(iEnd >= iBegin);
+               btAssert(grainSize >= 1);
+               int iterationCount = iEnd - iBegin;
+               if (iterationCount > grainSize && m_numWorkerThreads > 0 && m_antiNestingLock.tryLock())
+               {
+                       typedef ParallelSumJob JobType;
+                       int jobCount = (iterationCount + grainSize - 1) / grainSize;
+                       m_numJobs = jobCount;
+                       btAssert(jobCount >= 2);  // need more than one job for multithreading
+                       int jobSize = sizeof(JobType);
+                       for (int i = 0; i < m_numActiveJobQueues; ++i)
+                       {
+                               m_jobQueues[i].clearQueue(jobCount, jobSize);
+                       }
+
+                       // initialize summation
+                       for (int iThread = 0; iThread < m_numThreads; ++iThread)
+                       {
+                               m_threadLocalStorage[iThread].m_sumResult = btScalar(0);
+                       }
+
+                       // prepare worker threads for incoming work
+                       prepareWorkerThreads();
+                       // submit all of the jobs
+                       int iJob = 0;
+                       int iThread = kFirstWorkerThreadId;  // first worker thread
+                       for (int i = iBegin; i < iEnd; i += grainSize)
+                       {
+                               btAssert(iJob < jobCount);
+                               int iE = btMin(i + grainSize, iEnd);
+                               JobQueue* jq = m_perThreadJobQueues[iThread];
+                               btAssert(jq);
+                               btAssert((jq - &m_jobQueues[0]) < m_numActiveJobQueues);
+                               void* jobMem = jq->allocJobMem(jobSize);
+                               JobType* job = new (jobMem) ParallelSumJob(i, iE, body, &m_threadLocalStorage[0]);  // placement new
+                               jq->submitJob(job);
+                               iJob++;
+                               iThread++;
+                               if (iThread >= m_numThreads)
+                               {
+                                       iThread = kFirstWorkerThreadId;  // first worker thread
+                               }
+                       }
+                       wakeWorkers(jobCount - 1);
+
+                       // put the main thread to work on emptying the job queue and then wait for all workers to finish
+                       waitJobs();
+
+                       // add up all the thread sums
+                       btScalar sum = btScalar(0);
+                       for (int iThread = 0; iThread < m_numThreads; ++iThread)
+                       {
+                               sum += m_threadLocalStorage[iThread].m_sumResult;
+                       }
+                       m_antiNestingLock.unlock();
+                       return sum;
+               }
+               else
+               {
+                       BT_PROFILE("parallelSum_mainThread");
+                       // just run on main thread
+                       return body.sumLoop(iBegin, iEnd);
+               }
+       }
+};
+
+btITaskScheduler* btCreateDefaultTaskScheduler()
+{
+       btTaskSchedulerDefault* ts = new btTaskSchedulerDefault();
+       ts->init();
+       return ts;
+}
+
+#else  // #if BT_THREADSAFE
+
+btITaskScheduler* btCreateDefaultTaskScheduler()
+{
+       return NULL;
+}
+
+#endif  // #else // #if BT_THREADSAFE
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btThreadSupportInterface.h b/dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btThreadSupportInterface.h
new file mode 100644 (file)
index 0000000..1fe4933
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2018 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.
+*/
+
+#ifndef BT_THREAD_SUPPORT_INTERFACE_H
+#define BT_THREAD_SUPPORT_INTERFACE_H
+
+class btCriticalSection
+{
+public:
+       btCriticalSection() {}
+       virtual ~btCriticalSection() {}
+
+       virtual void lock() = 0;
+       virtual void unlock() = 0;
+};
+
+class btThreadSupportInterface
+{
+public:
+       virtual ~btThreadSupportInterface() {}
+
+       virtual int getNumWorkerThreads() const = 0;            // number of worker threads (total number of logical processors - 1)
+       virtual int getCacheFriendlyNumThreads() const = 0;     // the number of logical processors sharing a single L3 cache
+       virtual int getLogicalToPhysicalCoreRatio() const = 0;  // the number of logical processors per physical processor (usually 1 or 2)
+       virtual void runTask(int threadIndex, void* userData) = 0;
+       virtual void waitForAllTasks() = 0;
+
+       virtual btCriticalSection* createCriticalSection() = 0;
+       virtual void deleteCriticalSection(btCriticalSection* criticalSection) = 0;
+
+       typedef void (*ThreadFunc)(void* userPtr);
+
+       struct ConstructionInfo
+       {
+               ConstructionInfo(const char* uniqueName,
+                                                ThreadFunc userThreadFunc,
+                                                int threadStackSize = 65535)
+                       : m_uniqueName(uniqueName),
+                         m_userThreadFunc(userThreadFunc),
+                         m_threadStackSize(threadStackSize)
+               {
+               }
+
+               const char* m_uniqueName;
+               ThreadFunc m_userThreadFunc;
+               int m_threadStackSize;
+       };
+
+       static btThreadSupportInterface* create(const ConstructionInfo& info);
+};
+
+#endif  //BT_THREAD_SUPPORT_INTERFACE_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btThreadSupportPosix.cpp b/dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btThreadSupportPosix.cpp
new file mode 100644 (file)
index 0000000..a03f6dc
--- /dev/null
@@ -0,0 +1,353 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2018 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.
+*/
+
+#if BT_THREADSAFE && !defined(_WIN32)
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btThreads.h"
+#include "LinearMath/btMinMax.h"
+#include "btThreadSupportInterface.h"
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 600  //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html
+#endif                     //_XOPEN_SOURCE
+#include <pthread.h>
+#include <semaphore.h>
+#include <unistd.h>  //for sysconf
+
+///
+/// getNumHardwareThreads()
+///
+///
+/// https://stackoverflow.com/questions/150355/programmatically-find-the-number-of-cores-on-a-machine
+///
+#if __cplusplus >= 201103L
+
+#include <thread>
+
+int btGetNumHardwareThreads()
+{
+       return btMax(1u, btMin(BT_MAX_THREAD_COUNT, std::thread::hardware_concurrency()));
+}
+
+#else
+
+int btGetNumHardwareThreads()
+{
+       return btMax(1, btMin<int>(BT_MAX_THREAD_COUNT, sysconf(_SC_NPROCESSORS_ONLN)));
+}
+
+#endif
+
+// btThreadSupportPosix helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
+class btThreadSupportPosix : public btThreadSupportInterface
+{
+public:
+       struct btThreadStatus
+       {
+               int m_taskId;
+               int m_commandId;
+               int m_status;
+
+               ThreadFunc m_userThreadFunc;
+               void* m_userPtr;  //for taskDesc etc
+
+               pthread_t thread;
+               //each tread will wait until this signal to start its work
+               sem_t* startSemaphore;
+               btCriticalSection* m_cs;
+               // this is a copy of m_mainSemaphore,
+               //each tread will signal once it is finished with its work
+               sem_t* m_mainSemaphore;
+               unsigned long threadUsed;
+       };
+
+private:
+       typedef unsigned long long UINT64;
+
+       btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
+       // m_mainSemaphoresemaphore will signal, if and how many threads are finished with their work
+       sem_t* m_mainSemaphore;
+       int m_numThreads;
+       UINT64 m_startedThreadsMask;
+       void startThreads(const ConstructionInfo& threadInfo);
+       void stopThreads();
+       int waitForResponse();
+       btCriticalSection* m_cs;
+public:
+       btThreadSupportPosix(const ConstructionInfo& threadConstructionInfo);
+       virtual ~btThreadSupportPosix();
+
+       virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
+       // TODO: return the number of logical processors sharing the first L3 cache
+       virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return m_numThreads + 1; }
+       // TODO: detect if CPU has hyperthreading enabled
+       virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return 1; }
+
+       virtual void runTask(int threadIndex, void* userData) BT_OVERRIDE;
+       virtual void waitForAllTasks() BT_OVERRIDE;
+
+       virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
+       virtual void deleteCriticalSection(btCriticalSection* criticalSection) BT_OVERRIDE;
+};
+
+#define checkPThreadFunction(returnValue)                                                                 \
+       if (0 != returnValue)                                                                                 \
+       {                                                                                                     \
+               printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \
+       }
+
+// The number of threads should be equal to the number of available cores
+// Todo: each worker should be linked to a single core, using SetThreadIdealProcessor.
+
+btThreadSupportPosix::btThreadSupportPosix(const ConstructionInfo& threadConstructionInfo)
+{
+       m_cs = createCriticalSection();
+       startThreads(threadConstructionInfo);
+}
+
+// cleanup/shutdown Libspe2
+btThreadSupportPosix::~btThreadSupportPosix()
+{
+       stopThreads();
+       deleteCriticalSection(m_cs);
+       m_cs=0;
+}
+
+#if (defined(__APPLE__))
+#define NAMED_SEMAPHORES
+#endif
+
+static sem_t* createSem(const char* baseName)
+{
+       static int semCount = 0;
+#ifdef NAMED_SEMAPHORES
+       /// Named semaphore begin
+       char name[32];
+       snprintf(name, 32, "/%8.s-%4.d-%4.4d", baseName, getpid(), semCount++);
+       sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0);
+
+       if (tempSem != reinterpret_cast<sem_t*>(SEM_FAILED))
+       {
+               //        printf("Created \"%s\" Semaphore %p\n", name, tempSem);
+       }
+       else
+       {
+               //printf("Error creating Semaphore %d\n", errno);
+               exit(-1);
+       }
+       /// Named semaphore end
+#else
+       sem_t* tempSem = new sem_t;
+       checkPThreadFunction(sem_init(tempSem, 0, 0));
+#endif
+       return tempSem;
+}
+
+static void destroySem(sem_t* semaphore)
+{
+#ifdef NAMED_SEMAPHORES
+       checkPThreadFunction(sem_close(semaphore));
+#else
+       checkPThreadFunction(sem_destroy(semaphore));
+       delete semaphore;
+#endif
+}
+
+static void* threadFunction(void* argument)
+{
+       btThreadSupportPosix::btThreadStatus* status = (btThreadSupportPosix::btThreadStatus*)argument;
+
+       while (1)
+       {
+               checkPThreadFunction(sem_wait(status->startSemaphore));
+               void* userPtr = status->m_userPtr;
+
+               if (userPtr)
+               {
+                       btAssert(status->m_status);
+                       status->m_userThreadFunc(userPtr);
+                       status->m_cs->lock();
+                       status->m_status = 2;
+                       status->m_cs->unlock();
+                       checkPThreadFunction(sem_post(status->m_mainSemaphore));
+                       status->threadUsed++;
+               }
+               else
+               {
+                       //exit Thread
+                       status->m_cs->lock();
+                       status->m_status = 3;
+                       status->m_cs->unlock();
+                       checkPThreadFunction(sem_post(status->m_mainSemaphore));
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+///send messages to SPUs
+void btThreadSupportPosix::runTask(int threadIndex, void* userData)
+{
+       ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished
+       btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
+       btAssert(threadIndex >= 0);
+       btAssert(threadIndex < m_activeThreadStatus.size());
+       threadStatus.m_cs = m_cs;
+       threadStatus.m_commandId = 1;
+       threadStatus.m_status = 1;
+       threadStatus.m_userPtr = userData;
+       m_startedThreadsMask |= UINT64(1) << threadIndex;
+
+       // fire event to start new task
+       checkPThreadFunction(sem_post(threadStatus.startSemaphore));
+}
+
+///check for messages from SPUs
+int btThreadSupportPosix::waitForResponse()
+{
+       ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response
+       ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback'
+
+       btAssert(m_activeThreadStatus.size());
+
+       // wait for any of the threads to finish
+       checkPThreadFunction(sem_wait(m_mainSemaphore));
+       // get at least one thread which has finished
+       size_t last = -1;
+
+       for (size_t t = 0; t < size_t(m_activeThreadStatus.size()); ++t)
+       {
+               m_cs->lock();
+               bool hasFinished = (2 == m_activeThreadStatus[t].m_status);
+               m_cs->unlock(); 
+               if (hasFinished)
+               {
+                       last = t;
+                       break;
+               }
+       }
+
+       btThreadStatus& threadStatus = m_activeThreadStatus[last];
+
+       btAssert(threadStatus.m_status > 1);
+       threadStatus.m_status = 0;
+
+       // need to find an active spu
+       btAssert(last >= 0);
+       m_startedThreadsMask &= ~(UINT64(1) << last);
+
+       return last;
+}
+
+void btThreadSupportPosix::waitForAllTasks()
+{
+       while (m_startedThreadsMask)
+       {
+               waitForResponse();
+       }
+}
+
+void btThreadSupportPosix::startThreads(const ConstructionInfo& threadConstructionInfo)
+{
+       m_numThreads = btGetNumHardwareThreads() - 1;  // main thread exists already
+       m_activeThreadStatus.resize(m_numThreads);
+       m_startedThreadsMask = 0;
+
+       m_mainSemaphore = createSem("main");
+       //checkPThreadFunction(sem_wait(mainSemaphore));
+
+       for (int i = 0; i < m_numThreads; i++)
+       {
+               btThreadStatus& threadStatus = m_activeThreadStatus[i];
+               threadStatus.startSemaphore = createSem("threadLocal");
+               threadStatus.m_userPtr = 0;
+               threadStatus.m_cs = m_cs;
+               threadStatus.m_taskId = i;
+               threadStatus.m_commandId = 0;
+               threadStatus.m_status = 0;
+               threadStatus.m_mainSemaphore = m_mainSemaphore;
+               threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
+               threadStatus.threadUsed = 0;
+               checkPThreadFunction(pthread_create(&threadStatus.thread, NULL, &threadFunction, (void*)&threadStatus));
+
+       }
+}
+
+///tell the task scheduler we are done with the SPU tasks
+void btThreadSupportPosix::stopThreads()
+{
+       for (size_t t = 0; t < size_t(m_activeThreadStatus.size()); ++t)
+       {
+               btThreadStatus& threadStatus = m_activeThreadStatus[t];
+
+               threadStatus.m_userPtr = 0;
+               checkPThreadFunction(sem_post(threadStatus.startSemaphore));
+               checkPThreadFunction(sem_wait(m_mainSemaphore));
+
+               checkPThreadFunction(pthread_join(threadStatus.thread, 0));
+               destroySem(threadStatus.startSemaphore);
+       }
+       destroySem(m_mainSemaphore);
+       m_activeThreadStatus.clear();
+}
+
+class btCriticalSectionPosix : public btCriticalSection
+{
+       pthread_mutex_t m_mutex;
+
+public:
+       btCriticalSectionPosix()
+       {
+               pthread_mutex_init(&m_mutex, NULL);
+       }
+       virtual ~btCriticalSectionPosix()
+       {
+               pthread_mutex_destroy(&m_mutex);
+       }
+
+       virtual void lock()
+       {
+               pthread_mutex_lock(&m_mutex);
+       }
+       virtual void unlock()
+       {
+               pthread_mutex_unlock(&m_mutex);
+       }
+};
+
+btCriticalSection* btThreadSupportPosix::createCriticalSection()
+{
+       return new btCriticalSectionPosix();
+}
+
+void btThreadSupportPosix::deleteCriticalSection(btCriticalSection* cs)
+{
+       delete cs;
+}
+
+btThreadSupportInterface* btThreadSupportInterface::create(const ConstructionInfo& info)
+{
+       return new btThreadSupportPosix(info);
+}
+
+#endif  // BT_THREADSAFE && !defined( _WIN32 )
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btThreadSupportWin32.cpp b/dali-physics/third-party/bullet3/src/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
new file mode 100644 (file)
index 0000000..5010cca
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2018 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.
+*/
+
+#if defined(_WIN32) && BT_THREADSAFE
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btThreads.h"
+#include "btThreadSupportInterface.h"
+#include <windows.h>
+#include <stdio.h>
+
+struct btProcessorInfo
+{
+       int numLogicalProcessors;
+       int numCores;
+       int numNumaNodes;
+       int numL1Cache;
+       int numL2Cache;
+       int numL3Cache;
+       int numPhysicalPackages;
+       static const int maxNumTeamMasks = 32;
+       int numTeamMasks;
+       UINT64 processorTeamMasks[maxNumTeamMasks];
+};
+
+UINT64 getProcessorTeamMask(const btProcessorInfo& procInfo, int procId)
+{
+       UINT64 procMask = UINT64(1) << procId;
+       for (int i = 0; i < procInfo.numTeamMasks; ++i)
+       {
+               if (procMask & procInfo.processorTeamMasks[i])
+               {
+                       return procInfo.processorTeamMasks[i];
+               }
+       }
+       return 0;
+}
+
+int getProcessorTeamIndex(const btProcessorInfo& procInfo, int procId)
+{
+       UINT64 procMask = UINT64(1) << procId;
+       for (int i = 0; i < procInfo.numTeamMasks; ++i)
+       {
+               if (procMask & procInfo.processorTeamMasks[i])
+               {
+                       return i;
+               }
+       }
+       return -1;
+}
+
+int countSetBits(ULONG64 bits)
+{
+       int count = 0;
+       while (bits)
+       {
+               if (bits & 1)
+               {
+                       count++;
+               }
+               bits >>= 1;
+       }
+       return count;
+}
+
+typedef BOOL(WINAPI* Pfn_GetLogicalProcessorInformation)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
+
+void getProcessorInformation(btProcessorInfo* procInfo)
+{
+       memset(procInfo, 0, sizeof(*procInfo));
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+       // Can't dlopen libraries on UWP.
+       return;
+#else
+       Pfn_GetLogicalProcessorInformation getLogicalProcInfo =
+               (Pfn_GetLogicalProcessorInformation)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");
+       if (getLogicalProcInfo == NULL)
+       {
+               // no info
+               return;
+       }
+       PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buf = NULL;
+       DWORD bufSize = 0;
+       while (true)
+       {
+               if (getLogicalProcInfo(buf, &bufSize))
+               {
+                       break;
+               }
+               else
+               {
+                       if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+                       {
+                               if (buf)
+                               {
+                                       free(buf);
+                               }
+                               buf = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(bufSize);
+                       }
+               }
+       }
+
+       int len = bufSize / sizeof(*buf);
+       for (int i = 0; i < len; ++i)
+       {
+               PSYSTEM_LOGICAL_PROCESSOR_INFORMATION info = buf + i;
+               switch (info->Relationship)
+               {
+                       case RelationNumaNode:
+                               procInfo->numNumaNodes++;
+                               break;
+
+                       case RelationProcessorCore:
+                               procInfo->numCores++;
+                               procInfo->numLogicalProcessors += countSetBits(info->ProcessorMask);
+                               break;
+
+                       case RelationCache:
+                               if (info->Cache.Level == 1)
+                               {
+                                       procInfo->numL1Cache++;
+                               }
+                               else if (info->Cache.Level == 2)
+                               {
+                                       procInfo->numL2Cache++;
+                               }
+                               else if (info->Cache.Level == 3)
+                               {
+                                       procInfo->numL3Cache++;
+                                       // processors that share L3 cache are considered to be on the same team
+                                       // because they can more easily work together on the same data.
+                                       // Large performance penalties will occur if 2 or more threads from different
+                                       // teams attempt to frequently read and modify the same cache lines.
+                                       //
+                                       // On the AMD Ryzen 7 CPU for example, the 8 cores on the CPU are split into
+                                       // 2 CCX units of 4 cores each. Each CCX has a separate L3 cache, so if both
+                                       // CCXs are operating on the same data, many cycles will be spent keeping the
+                                       // two caches coherent.
+                                       if (procInfo->numTeamMasks < btProcessorInfo::maxNumTeamMasks)
+                                       {
+                                               procInfo->processorTeamMasks[procInfo->numTeamMasks] = info->ProcessorMask;
+                                               procInfo->numTeamMasks++;
+                                       }
+                               }
+                               break;
+
+                       case RelationProcessorPackage:
+                               procInfo->numPhysicalPackages++;
+                               break;
+               }
+       }
+       free(buf);
+#endif
+}
+
+///btThreadSupportWin32 helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
+class btThreadSupportWin32 : public btThreadSupportInterface
+{
+public:
+       struct btThreadStatus
+       {
+               int m_taskId;
+               int m_commandId;
+               int m_status;
+
+               ThreadFunc m_userThreadFunc;
+               void* m_userPtr;  //for taskDesc etc
+
+               void* m_threadHandle;  //this one is calling 'Win32ThreadFunc'
+
+               void* m_eventStartHandle;
+               char m_eventStartHandleName[32];
+
+               void* m_eventCompleteHandle;
+               char m_eventCompleteHandleName[32];
+       };
+
+private:
+       btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
+       btAlignedObjectArray<void*> m_completeHandles;
+       int m_numThreads;
+       DWORD_PTR m_startedThreadMask;
+       btProcessorInfo m_processorInfo;
+
+       void startThreads(const ConstructionInfo& threadInfo);
+       void stopThreads();
+       int waitForResponse();
+
+public:
+       btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo);
+       virtual ~btThreadSupportWin32();
+
+       virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
+       virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return countSetBits(m_processorInfo.processorTeamMasks[0]); }
+       virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return m_processorInfo.numLogicalProcessors / m_processorInfo.numCores; }
+
+       virtual void runTask(int threadIndex, void* userData) BT_OVERRIDE;
+       virtual void waitForAllTasks() BT_OVERRIDE;
+
+       virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
+       virtual void deleteCriticalSection(btCriticalSection* criticalSection) BT_OVERRIDE;
+};
+
+btThreadSupportWin32::btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo)
+{
+       startThreads(threadConstructionInfo);
+}
+
+btThreadSupportWin32::~btThreadSupportWin32()
+{
+       stopThreads();
+}
+
+DWORD WINAPI win32threadStartFunc(LPVOID lpParam)
+{
+       btThreadSupportWin32::btThreadStatus* status = (btThreadSupportWin32::btThreadStatus*)lpParam;
+
+       while (1)
+       {
+               WaitForSingleObject(status->m_eventStartHandle, INFINITE);
+               void* userPtr = status->m_userPtr;
+
+               if (userPtr)
+               {
+                       btAssert(status->m_status);
+                       status->m_userThreadFunc(userPtr);
+                       status->m_status = 2;
+                       SetEvent(status->m_eventCompleteHandle);
+               }
+               else
+               {
+                       //exit Thread
+                       status->m_status = 3;
+                       printf("Thread with taskId %i with handle %p exiting\n", status->m_taskId, status->m_threadHandle);
+                       SetEvent(status->m_eventCompleteHandle);
+                       break;
+               }
+       }
+       printf("Thread TERMINATED\n");
+       return 0;
+}
+
+void btThreadSupportWin32::runTask(int threadIndex, void* userData)
+{
+       btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
+       btAssert(threadIndex >= 0);
+       btAssert(int(threadIndex) < m_activeThreadStatus.size());
+
+       threadStatus.m_commandId = 1;
+       threadStatus.m_status = 1;
+       threadStatus.m_userPtr = userData;
+       m_startedThreadMask |= DWORD_PTR(1) << threadIndex;
+
+       ///fire event to start new task
+       SetEvent(threadStatus.m_eventStartHandle);
+}
+
+int btThreadSupportWin32::waitForResponse()
+{
+       btAssert(m_activeThreadStatus.size());
+
+       int last = -1;
+       DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
+       btAssert(res != WAIT_FAILED);
+       last = res - WAIT_OBJECT_0;
+
+       btThreadStatus& threadStatus = m_activeThreadStatus[last];
+       btAssert(threadStatus.m_threadHandle);
+       btAssert(threadStatus.m_eventCompleteHandle);
+
+       //WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
+       btAssert(threadStatus.m_status > 1);
+       threadStatus.m_status = 0;
+
+       ///need to find an active spu
+       btAssert(last >= 0);
+       m_startedThreadMask &= ~(DWORD_PTR(1) << last);
+
+       return last;
+}
+
+void btThreadSupportWin32::waitForAllTasks()
+{
+       while (m_startedThreadMask)
+       {
+               waitForResponse();
+       }
+}
+
+void btThreadSupportWin32::startThreads(const ConstructionInfo& threadConstructionInfo)
+{
+       static int uniqueId = 0;
+       uniqueId++;
+       btProcessorInfo& procInfo = m_processorInfo;
+       getProcessorInformation(&procInfo);
+       DWORD_PTR dwProcessAffinityMask = 0;
+       DWORD_PTR dwSystemAffinityMask = 0;
+       if (!GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask))
+       {
+               dwProcessAffinityMask = 0;
+       }
+       ///The number of threads should be equal to the number of available cores - 1
+       m_numThreads = btMin(procInfo.numLogicalProcessors, int(BT_MAX_THREAD_COUNT)) - 1;  // cap to max thread count (-1 because main thread already exists)
+
+       m_activeThreadStatus.resize(m_numThreads);
+       m_completeHandles.resize(m_numThreads);
+       m_startedThreadMask = 0;
+
+       // set main thread affinity
+       if (DWORD_PTR mask = dwProcessAffinityMask & getProcessorTeamMask(procInfo, 0))
+       {
+               SetThreadAffinityMask(GetCurrentThread(), mask);
+               SetThreadIdealProcessor(GetCurrentThread(), 0);
+       }
+
+       for (int i = 0; i < m_numThreads; i++)
+       {
+               printf("starting thread %d\n", i);
+
+               btThreadStatus& threadStatus = m_activeThreadStatus[i];
+
+               LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
+               SIZE_T dwStackSize = threadConstructionInfo.m_threadStackSize;
+               LPTHREAD_START_ROUTINE lpStartAddress = &win32threadStartFunc;
+               LPVOID lpParameter = &threadStatus;
+               DWORD dwCreationFlags = 0;
+               LPDWORD lpThreadId = 0;
+
+               threadStatus.m_userPtr = 0;
+
+               sprintf(threadStatus.m_eventStartHandleName, "es%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i);
+               threadStatus.m_eventStartHandle = CreateEventA(0, false, false, threadStatus.m_eventStartHandleName);
+
+               sprintf(threadStatus.m_eventCompleteHandleName, "ec%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i);
+               threadStatus.m_eventCompleteHandle = CreateEventA(0, false, false, threadStatus.m_eventCompleteHandleName);
+
+               m_completeHandles[i] = threadStatus.m_eventCompleteHandle;
+
+               HANDLE handle = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
+               //SetThreadPriority( handle, THREAD_PRIORITY_HIGHEST );
+               // highest priority -- can cause erratic performance when numThreads > numCores
+               //                     we don't want worker threads to be higher priority than the main thread or the main thread could get
+               //                     totally shut out and unable to tell the workers to stop
+               //SetThreadPriority( handle, THREAD_PRIORITY_BELOW_NORMAL );
+
+               {
+                       int processorId = i + 1;  // leave processor 0 for main thread
+                       DWORD_PTR teamMask = getProcessorTeamMask(procInfo, processorId);
+                       if (teamMask)
+                       {
+                               // bind each thread to only execute on processors of it's assigned team
+                               //  - for single-socket Intel x86 CPUs this has no effect (only a single, shared L3 cache so there is only 1 team)
+                               //  - for multi-socket Intel this will keep threads from migrating from one socket to another
+                               //  - for AMD Ryzen this will keep threads from migrating from one CCX to another
+                               DWORD_PTR mask = teamMask & dwProcessAffinityMask;
+                               if (mask)
+                               {
+                                       SetThreadAffinityMask(handle, mask);
+                               }
+                       }
+                       SetThreadIdealProcessor(handle, processorId);
+               }
+
+               threadStatus.m_taskId = i;
+               threadStatus.m_commandId = 0;
+               threadStatus.m_status = 0;
+               threadStatus.m_threadHandle = handle;
+               threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
+
+               printf("started %s thread %d with threadHandle %p\n", threadConstructionInfo.m_uniqueName, i, handle);
+       }
+}
+
+///tell the task scheduler we are done with the SPU tasks
+void btThreadSupportWin32::stopThreads()
+{
+       for (int i = 0; i < m_activeThreadStatus.size(); i++)
+       {
+               btThreadStatus& threadStatus = m_activeThreadStatus[i];
+               if (threadStatus.m_status > 0)
+               {
+                       WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
+               }
+
+               threadStatus.m_userPtr = NULL;
+               SetEvent(threadStatus.m_eventStartHandle);
+               WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
+
+               CloseHandle(threadStatus.m_eventCompleteHandle);
+               CloseHandle(threadStatus.m_eventStartHandle);
+               CloseHandle(threadStatus.m_threadHandle);
+       }
+
+       m_activeThreadStatus.clear();
+       m_completeHandles.clear();
+}
+
+class btWin32CriticalSection : public btCriticalSection
+{
+private:
+       CRITICAL_SECTION mCriticalSection;
+
+public:
+       btWin32CriticalSection()
+       {
+               InitializeCriticalSection(&mCriticalSection);
+       }
+
+       ~btWin32CriticalSection()
+       {
+               DeleteCriticalSection(&mCriticalSection);
+       }
+
+       void lock()
+       {
+               EnterCriticalSection(&mCriticalSection);
+       }
+
+       void unlock()
+       {
+               LeaveCriticalSection(&mCriticalSection);
+       }
+};
+
+btCriticalSection* btThreadSupportWin32::createCriticalSection()
+{
+       unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32CriticalSection), 16);
+       btWin32CriticalSection* cs = new (mem) btWin32CriticalSection();
+       return cs;
+}
+
+void btThreadSupportWin32::deleteCriticalSection(btCriticalSection* criticalSection)
+{
+       criticalSection->~btCriticalSection();
+       btAlignedFree(criticalSection);
+}
+
+btThreadSupportInterface* btThreadSupportInterface::create(const ConstructionInfo& info)
+{
+       return new btThreadSupportWin32(info);
+}
+
+#endif  //defined(_WIN32) && BT_THREADSAFE
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btAabbUtil2.h b/dali-physics/third-party/bullet3/src/LinearMath/btAabbUtil2.h
new file mode 100644 (file)
index 0000000..67ff479
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_AABB_UTIL2
+#define BT_AABB_UTIL2
+
+#include "btTransform.h"
+#include "btVector3.h"
+#include "btMinMax.h"
+
+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
+SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3& aabbMin1, const btVector3& aabbMax1,
+                                                                                        const btVector3& point)
+{
+       bool overlap = true;
+       overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
+       overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap;
+       overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap;
+       return overlap;
+}
+
+/// conservative test for overlap between two aabbs
+SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3& aabbMin1, const btVector3& aabbMax1,
+                                                                                       const btVector3& aabbMin2, const btVector3& aabbMax2)
+{
+       bool overlap = true;
+       overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
+       overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
+       overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
+       return overlap;
+}
+
+/// conservative test for overlap between triangle and aabb
+SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3* vertices,
+                                                                                               const btVector3& aabbMin, const btVector3& aabbMax)
+{
+       const btVector3& p1 = vertices[0];
+       const btVector3& p2 = vertices[1];
+       const btVector3& p3 = vertices[2];
+
+       if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
+       if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
+
+       if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
+       if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
+
+       if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
+       if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
+       return true;
+}
+
+SIMD_FORCE_INLINE int btOutcode(const btVector3& p, const btVector3& halfExtent)
+{
+       return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
+                  (p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
+                  (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
+                  (p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
+                  (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
+                  (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
+}
+
+SIMD_FORCE_INLINE bool 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]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+       tmax = (bounds[1 - raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+       tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+       tymax = (bounds[1 - raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+
+       if ((tmin > tymax) || (tymin > tmax))
+               return false;
+
+       if (tymin > tmin)
+               tmin = tymin;
+
+       if (tymax < tmax)
+               tmax = tymax;
+
+       tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+       tzmax = (bounds[1 - raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+
+       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,
+                                                                const btVector3& aabbMax,
+                                                                btScalar& param, btVector3& normal)
+{
+       btVector3 aabbHalfExtent = (aabbMax - aabbMin) * btScalar(0.5);
+       btVector3 aabbCenter = (aabbMax + aabbMin) * btScalar(0.5);
+       btVector3 source = rayFrom - aabbCenter;
+       btVector3 target = rayTo - aabbCenter;
+       int sourceOutcode = btOutcode(source, aabbHalfExtent);
+       int targetOutcode = btOutcode(target, aabbHalfExtent);
+       if ((sourceOutcode & targetOutcode) == 0x0)
+       {
+               btScalar lambda_enter = btScalar(0.0);
+               btScalar lambda_exit = param;
+               btVector3 r = target - source;
+               int i;
+               btScalar normSign = 1;
+               btVector3 hitNormal(0, 0, 0);
+               int bit = 1;
+
+               for (int j = 0; j < 2; j++)
+               {
+                       for (i = 0; i != 3; ++i)
+                       {
+                               if (sourceOutcode & bit)
+                               {
+                                       btScalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
+                                       if (lambda_enter <= lambda)
+                                       {
+                                               lambda_enter = lambda;
+                                               hitNormal.setValue(0, 0, 0);
+                                               hitNormal[i] = normSign;
+                                       }
+                               }
+                               else if (targetOutcode & bit)
+                               {
+                                       btScalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
+                                       btSetMin(lambda_exit, lambda);
+                               }
+                               bit <<= 1;
+                       }
+                       normSign = btScalar(-1.);
+               }
+               if (lambda_enter <= lambda_exit)
+               {
+                       param = lambda_enter;
+                       normal = hitNormal;
+                       return true;
+               }
+       }
+       return false;
+}
+
+SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin, const btTransform& t, btVector3& aabbMinOut, btVector3& aabbMaxOut)
+{
+       btVector3 halfExtentsWithMargin = halfExtents + btVector3(margin, margin, margin);
+       btMatrix3x3 abs_b = t.getBasis().absolute();
+       btVector3 center = t.getOrigin();
+       btVector3 extent = halfExtentsWithMargin.dot3(abs_b[0], abs_b[1], abs_b[2]);
+       aabbMinOut = center - extent;
+       aabbMaxOut = center + extent;
+}
+
+SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin, const btVector3& localAabbMax, btScalar margin, const btTransform& trans, btVector3& aabbMinOut, btVector3& aabbMaxOut)
+{
+       btAssert(localAabbMin.getX() <= localAabbMax.getX());
+       btAssert(localAabbMin.getY() <= localAabbMax.getY());
+       btAssert(localAabbMin.getZ() <= localAabbMax.getZ());
+       btVector3 localHalfExtents = btScalar(0.5) * (localAabbMax - localAabbMin);
+       localHalfExtents += btVector3(margin, margin, margin);
+
+       btVector3 localCenter = btScalar(0.5) * (localAabbMax + localAabbMin);
+       btMatrix3x3 abs_b = trans.getBasis().absolute();
+       btVector3 center = trans(localCenter);
+       btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+       aabbMinOut = center - extent;
+       aabbMaxOut = center + extent;
+}
+
+#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(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
+{
+       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(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
+{
+       bool overlap = true;
+       overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
+       overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
+       overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
+       return overlap;
+}
+#endif  //USE_BANCHLESS
+
+#endif  //BT_AABB_UTIL2
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btAlignedAllocator.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btAlignedAllocator.cpp
new file mode 100644 (file)
index 0000000..c8f436f
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btAlignedAllocator.h"
+#include <string.h>
+
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+int gNumAlignedAllocs = 0;
+int gNumAlignedFree = 0;
+int gTotalBytesAlignedAllocs = 0;  //detect memory leaks
+#endif                             //BT_DEBUG_MEMORY_ALLOCATIONST_DEBUG_ALLOCATIONS
+
+static void *btAllocDefault(size_t size)
+{
+  char* data = (char*) malloc(size);
+  memset(data,0,size);//keep msan happy
+  return data;
+}
+
+static void btFreeDefault(void *ptr)
+{
+       free(ptr);
+}
+
+static btAllocFunc *sAllocFunc = btAllocDefault;
+static btFreeFunc *sFreeFunc = btFreeDefault;
+
+#if defined(BT_HAS_ALIGNED_ALLOCATOR)
+#include <malloc.h>
+static void *btAlignedAllocDefault(size_t size, int alignment)
+{
+       return _aligned_malloc(size, (size_t)alignment);
+}
+
+static void btAlignedFreeDefault(void *ptr)
+{
+       _aligned_free(ptr);
+}
+#elif defined(__CELLOS_LV2__)
+#include <stdlib.h>
+
+static inline void *btAlignedAllocDefault(size_t size, int alignment)
+{
+       return memalign(alignment, size);
+}
+
+static inline void btAlignedFreeDefault(void *ptr)
+{
+       free(ptr);
+}
+#else
+
+static inline void *btAlignedAllocDefault(size_t size, int alignment)
+{
+       void *ret;
+       char *real;
+       real = (char *)sAllocFunc(size + sizeof(void *) + (alignment - 1));
+       if (real)
+       {
+               ret = btAlignPointer(real + sizeof(void *), alignment);
+               *((void **)(ret)-1) = (void *)(real);
+       }
+       else
+       {
+               ret = (void *)(real);
+       }
+  //keep msan happy
+  memset((char*) ret, 0, size);
+       return (ret);
+}
+
+static inline void btAlignedFreeDefault(void *ptr)
+{
+       void *real;
+
+       if (ptr)
+       {
+               real = *((void **)(ptr)-1);
+               sFreeFunc(real);
+       }
+}
+#endif
+
+static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault;
+static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault;
+
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc)
+{
+       sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
+       sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
+}
+
+void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
+{
+       sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
+       sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
+}
+
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+
+static int allocations_id[10241024];
+static int allocations_bytes[10241024];
+static int mynumallocs = 0;
+#include <stdio.h>
+
+int btDumpMemoryLeaks()
+{
+       int totalLeak = 0;
+
+       for (int i = 0; i < mynumallocs; i++)
+       {
+               printf("Error: leaked memory of allocation #%d (%d bytes)\n", allocations_id[i], allocations_bytes[i]);
+               totalLeak += allocations_bytes[i];
+       }
+       if (totalLeak)
+       {
+               printf("Error: memory leaks: %d allocations were not freed and leaked together %d bytes\n", mynumallocs, totalLeak);
+       }
+       return totalLeak;
+}
+//this generic allocator provides the total allocated number of bytes
+#include <stdio.h>
+
+struct btDebugPtrMagic
+{
+       union {
+               void **vptrptr;
+               void *vptr;
+               int *iptr;
+               char *cptr;
+       };
+};
+
+void *btAlignedAllocInternal(size_t size, int alignment, int line, const char *filename)
+{
+       if (size == 0)
+       {
+               printf("Whaat? size==0");
+               return 0;
+       }
+       static int allocId = 0;
+
+       void *ret;
+       char *real;
+
+       // to find some particular memory leak, you could do something like this:
+       //      if (allocId==172)
+       //      {
+       //              printf("catch me!\n");
+       //      }
+       //      if (size>1024*1024)
+       //      {
+       //              printf("big alloc!%d\n", size);
+       //      }
+
+       gTotalBytesAlignedAllocs += size;
+       gNumAlignedAllocs++;
+
+       int sz4prt = 4 * sizeof(void *);
+
+       real = (char *)sAllocFunc(size + sz4prt + (alignment - 1));
+       if (real)
+       {
+               ret = (void *)btAlignPointer(real + sz4prt, alignment);
+               btDebugPtrMagic p;
+               p.vptr = ret;
+               p.cptr -= sizeof(void *);
+               *p.vptrptr = (void *)real;
+               p.cptr -= sizeof(void *);
+               *p.iptr = size;
+               p.cptr -= sizeof(void *);
+               *p.iptr = allocId;
+
+               allocations_id[mynumallocs] = allocId;
+               allocations_bytes[mynumallocs] = size;
+               mynumallocs++;
+       }
+       else
+       {
+               ret = (void *)(real);  //??
+       }
+
+       printf("allocation %d at address %x, from %s,line %d, size %d (total allocated = %d)\n", allocId, real, filename, line, size, gTotalBytesAlignedAllocs);
+       allocId++;
+
+       int *ptr = (int *)ret;
+       *ptr = 12;
+       return (ret);
+}
+
+void btAlignedFreeInternal(void *ptr, int line, const char *filename)
+{
+       void *real;
+
+       if (ptr)
+       {
+               gNumAlignedFree++;
+
+               btDebugPtrMagic p;
+               p.vptr = ptr;
+               p.cptr -= sizeof(void *);
+               real = *p.vptrptr;
+               p.cptr -= sizeof(void *);
+               int size = *p.iptr;
+               p.cptr -= sizeof(void *);
+               int allocId = *p.iptr;
+
+               bool found = false;
+
+               for (int i = 0; i < mynumallocs; i++)
+               {
+                       if (allocations_id[i] == allocId)
+                       {
+                               allocations_id[i] = allocations_id[mynumallocs - 1];
+                               allocations_bytes[i] = allocations_bytes[mynumallocs - 1];
+                               mynumallocs--;
+                               found = true;
+                               break;
+                       }
+               }
+
+               gTotalBytesAlignedAllocs -= size;
+
+               int diff = gNumAlignedAllocs - gNumAlignedFree;
+               printf("free %d at address %x, from %s,line %d, size %d (total remain = %d in %d non-freed allocations)\n", allocId, real, filename, line, size, gTotalBytesAlignedAllocs, diff);
+
+               sFreeFunc(real);
+       }
+       else
+       {
+               //printf("deleting a NULL ptr, no effect\n");
+       }
+}
+
+#else  //BT_DEBUG_MEMORY_ALLOCATIONS
+
+void *btAlignedAllocInternal(size_t size, int alignment)
+{
+       void *ptr;
+       ptr = sAlignedAllocFunc(size, alignment);
+       //      printf("btAlignedAllocInternal %d, %x\n",size,ptr);
+       return ptr;
+}
+
+void btAlignedFreeInternal(void *ptr)
+{
+       if (!ptr)
+       {
+               return;
+       }
+
+       //      printf("btAlignedFreeInternal %x\n",ptr);
+       sAlignedFreeFunc(ptr);
+}
+
+#endif  //BT_DEBUG_MEMORY_ALLOCATIONS
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btAlignedAllocator.h b/dali-physics/third-party/bullet3/src/LinearMath/btAlignedAllocator.h
new file mode 100644 (file)
index 0000000..f6bbcdb
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_ALIGNED_ALLOCATOR
+#define BT_ALIGNED_ALLOCATOR
+
+///we probably replace this with our own aligned memory allocator
+///so we replace _aligned_malloc and _aligned_free with our own
+///that is better portable and more predictable
+
+#include "btScalar.h"
+
+///BT_DEBUG_MEMORY_ALLOCATIONS preprocessor can be set in build system
+///for regression tests to detect memory leaks
+///#define BT_DEBUG_MEMORY_ALLOCATIONS 1
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+
+int btDumpMemoryLeaks();
+
+#define btAlignedAlloc(a, b) \
+       btAlignedAllocInternal(a, b, __LINE__, __FILE__)
+
+#define btAlignedFree(ptr) \
+       btAlignedFreeInternal(ptr, __LINE__, __FILE__)
+
+void* btAlignedAllocInternal(size_t size, int alignment, int line, const char* filename);
+
+void btAlignedFreeInternal(void* ptr, int line, const char* filename);
+
+#else
+void* btAlignedAllocInternal(size_t size, int alignment);
+void btAlignedFreeInternal(void* ptr);
+
+#define btAlignedAlloc(size, alignment) btAlignedAllocInternal(size, alignment)
+#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);
+
+///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom
+void btAlignedAllocSetCustom(btAllocFunc* allocFunc, btFreeFunc* freeFunc);
+///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc* allocFunc, btAlignedFreeFunc* 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
+{
+       typedef btAlignedAllocator<T, Alignment> self_type;
+
+public:
+       //just going down a list:
+       btAlignedAllocator() {}
+       /*
+       btAlignedAllocator( const self_type & ) {}
+       */
+
+       template <typename Other>
+       btAlignedAllocator(const btAlignedAllocator<Other, Alignment>&)
+       {
+       }
+
+       typedef const T* const_pointer;
+       typedef const T& const_reference;
+       typedef T* pointer;
+       typedef T& reference;
+       typedef T value_type;
+
+       pointer address(reference ref) const { return &ref; }
+       const_pointer address(const_reference ref) const { return &ref; }
+       pointer allocate(size_type n, const_pointer* hint = 0)
+       {
+               (void)hint;
+               return reinterpret_cast<pointer>(btAlignedAlloc(sizeof(value_type) * n, Alignment));
+       }
+       void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); }
+       void deallocate(pointer ptr)
+       {
+               btAlignedFree(reinterpret_cast<void*>(ptr));
+       }
+       void destroy(pointer ptr) { ptr->~value_type(); }
+
+       template <typename O>
+       struct rebind
+       {
+               typedef btAlignedAllocator<O, Alignment> other;
+       };
+       template <typename O>
+       self_type& operator=(const btAlignedAllocator<O, Alignment>&)
+       {
+               return *this;
+       }
+
+       friend bool operator==(const self_type&, const self_type&) { return true; }
+};
+
+#endif  //BT_ALIGNED_ALLOCATOR
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btAlignedObjectArray.h b/dali-physics/third-party/bullet3/src/LinearMath/btAlignedObjectArray.h
new file mode 100644 (file)
index 0000000..ac3e189
--- /dev/null
@@ -0,0 +1,504 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_OBJECT_ARRAY__
+#define BT_OBJECT_ARRAY__
+
+#include "btScalar.h"  // has definitions like SIMD_FORCE_INLINE
+#include "btAlignedAllocator.h"
+
+///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW
+///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
+///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
+///see discussion here: https://bulletphysics.orgphpBB2/viewtopic.php?t=1231 and
+///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
+
+#define BT_USE_PLACEMENT_NEW 1
+//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
+#define BT_ALLOW_ARRAY_COPY_OPERATOR  // enabling this can accidently perform deep copies of data if you are not careful
+
+#ifdef BT_USE_MEMCPY
+#include <memory.h>
+#include <string.h>
+#endif  //BT_USE_MEMCPY
+
+#ifdef BT_USE_PLACEMENT_NEW
+#include <new>  //for placement new
+#endif          //BT_USE_PLACEMENT_NEW
+
+///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
+{
+       btAlignedAllocator<T, 16> m_allocator;
+
+       int m_size;
+       int m_capacity;
+       T* m_data;
+       //PCK: added this line
+       bool m_ownsMemory;
+
+#ifdef BT_ALLOW_ARRAY_COPY_OPERATOR
+public:
+       SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other)
+       {
+               copyFromArray(other);
+               return *this;
+       }
+#else   //BT_ALLOW_ARRAY_COPY_OPERATOR
+private:
+       SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other);
+#endif  //BT_ALLOW_ARRAY_COPY_OPERATOR
+
+protected:
+       SIMD_FORCE_INLINE int allocSize(int size)
+       {
+               return (size ? size * 2 : 1);
+       }
+       SIMD_FORCE_INLINE void copy(int start, int end, T* dest) const
+       {
+               int i;
+               for (i = start; i < end; ++i)
+#ifdef BT_USE_PLACEMENT_NEW
+                       new (&dest[i]) T(m_data[i]);
+#else
+                       dest[i] = m_data[i];
+#endif  //BT_USE_PLACEMENT_NEW
+       }
+
+       SIMD_FORCE_INLINE void init()
+       {
+               //PCK: added this line
+               m_ownsMemory = true;
+               m_data = 0;
+               m_size = 0;
+               m_capacity = 0;
+       }
+       SIMD_FORCE_INLINE void destroy(int first, int last)
+       {
+               int i;
+               for (i = first; i < last; i++)
+               {
+                       m_data[i].~T();
+               }
+       }
+
+       SIMD_FORCE_INLINE void* allocate(int size)
+       {
+               if (size)
+                       return m_allocator.allocate(size);
+               return 0;
+       }
+
+       SIMD_FORCE_INLINE void deallocate()
+       {
+               if (m_data)
+               {
+                       //PCK: enclosed the deallocation in this block
+                       if (m_ownsMemory)
+                       {
+                               m_allocator.deallocate(m_data);
+                       }
+                       m_data = 0;
+               }
+       }
+
+public:
+       btAlignedObjectArray()
+       {
+               init();
+       }
+
+       ~btAlignedObjectArray()
+       {
+               clear();
+       }
+
+       ///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
+       btAlignedObjectArray(const btAlignedObjectArray& otherArray)
+       {
+               init();
+
+               int otherSize = otherArray.size();
+               resize(otherSize);
+               otherArray.copy(0, otherSize, m_data);
+       }
+
+       /// return the number of elements in the array
+       SIMD_FORCE_INLINE int size() const
+       {
+               return m_size;
+       }
+
+       SIMD_FORCE_INLINE const T& at(int n) const
+       {
+               btAssert(n >= 0);
+               btAssert(n < size());
+               return m_data[n];
+       }
+
+       SIMD_FORCE_INLINE T& at(int n)
+       {
+               btAssert(n >= 0);
+               btAssert(n < size());
+               return m_data[n];
+       }
+
+       SIMD_FORCE_INLINE const T& operator[](int n) const
+       {
+               btAssert(n >= 0);
+               btAssert(n < size());
+               return m_data[n];
+       }
+
+       SIMD_FORCE_INLINE T& operator[](int n)
+       {
+               btAssert(n >= 0);
+               btAssert(n < size());
+               return m_data[n];
+       }
+
+       ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
+       SIMD_FORCE_INLINE void clear()
+       {
+               destroy(0, size());
+
+               deallocate();
+
+               init();
+       }
+
+       SIMD_FORCE_INLINE void pop_back()
+       {
+               btAssert(m_size > 0);
+               m_size--;
+               m_data[m_size].~T();
+       }
+
+       ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
+       ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
+       SIMD_FORCE_INLINE void resizeNoInitialize(int newsize)
+       {
+               if (newsize > size())
+               {
+                       reserve(newsize);
+               }
+               m_size = newsize;
+       }
+
+       SIMD_FORCE_INLINE void resize(int newsize, const T& fillData = T())
+       {
+               const int curSize = size();
+
+               if (newsize < curSize)
+               {
+                       for (int i = newsize; i < curSize; i++)
+                       {
+                               m_data[i].~T();
+                       }
+               }
+               else
+               {
+                       if (newsize > curSize)
+                       {
+                               reserve(newsize);
+                       }
+#ifdef BT_USE_PLACEMENT_NEW
+                       for (int i = curSize; i < newsize; i++)
+                       {
+                               new (&m_data[i]) T(fillData);
+                       }
+#endif  //BT_USE_PLACEMENT_NEW
+               }
+
+               m_size = newsize;
+       }
+       SIMD_FORCE_INLINE T& expandNonInitializing()
+       {
+               const int sz = size();
+               if (sz == capacity())
+               {
+                       reserve(allocSize(size()));
+               }
+               m_size++;
+
+               return m_data[sz];
+       }
+
+       SIMD_FORCE_INLINE T& expand(const T& fillValue = T())
+       {
+               const int sz = size();
+               if (sz == capacity())
+               {
+                       reserve(allocSize(size()));
+               }
+               m_size++;
+#ifdef BT_USE_PLACEMENT_NEW
+               new (&m_data[sz]) T(fillValue);  //use the in-place new (not really allocating heap memory)
+#endif
+
+               return m_data[sz];
+       }
+
+       SIMD_FORCE_INLINE void push_back(const T& _Val)
+       {
+               const int sz = size();
+               if (sz == capacity())
+               {
+                       reserve(allocSize(size()));
+               }
+
+#ifdef BT_USE_PLACEMENT_NEW
+               new (&m_data[m_size]) T(_Val);
+#else
+               m_data[size()] = _Val;
+#endif  //BT_USE_PLACEMENT_NEW
+
+               m_size++;
+       }
+
+       /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
+       SIMD_FORCE_INLINE int capacity() const
+       {
+               return m_capacity;
+       }
+
+       SIMD_FORCE_INLINE void reserve(int _Count)
+       {  // determine new minimum length of allocated storage
+               if (capacity() < _Count)
+               {  // not enough room, reallocate
+                       T* s = (T*)allocate(_Count);
+
+                       copy(0, size(), s);
+
+                       destroy(0, size());
+
+                       deallocate();
+
+                       //PCK: added this line
+                       m_ownsMemory = true;
+
+                       m_data = s;
+
+                       m_capacity = _Count;
+               }
+       }
+
+       class less
+       {
+       public:
+               bool operator()(const T& a, const T& b) const
+               {
+                       return (a < b);
+               }
+       };
+
+       template <typename L>
+       void quickSortInternal(const 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(const 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>
+       void downHeap(T* pArr, int k, int n, const L& CompareFunc)
+       {
+               /*  PRE: a[k+1..N] is a heap */
+               /* POST:  a[k..N]  is a heap */
+
+               T temp = pArr[k - 1];
+               /* k has child(s) */
+               while (k <= n / 2)
+               {
+                       int child = 2 * k;
+
+                       if ((child < n) && CompareFunc(pArr[child - 1], pArr[child]))
+                       {
+                               child++;
+                       }
+                       /* pick larger child */
+                       if (CompareFunc(temp, pArr[child - 1]))
+                       {
+                               /* move child up */
+                               pArr[k - 1] = pArr[child - 1];
+                               k = child;
+                       }
+                       else
+                       {
+                               break;
+                       }
+               }
+               pArr[k - 1] = temp;
+       } /*downHeap*/
+
+       void swap(int index0, int index1)
+       {
+#ifdef BT_USE_MEMCPY
+               char temp[sizeof(T)];
+               memcpy(temp, &m_data[index0], sizeof(T));
+               memcpy(&m_data[index0], &m_data[index1], sizeof(T));
+               memcpy(&m_data[index1], temp, sizeof(T));
+#else
+               T temp = m_data[index0];
+               m_data[index0] = m_data[index1];
+               m_data[index1] = temp;
+#endif  //BT_USE_PLACEMENT_NEW
+       }
+
+       template <typename L>
+       void heapSort(const L& CompareFunc)
+       {
+               /* sort a[0..N-1],  N.B. 0 to N-1 */
+               int k;
+               int n = m_size;
+               for (k = n / 2; k > 0; k--)
+               {
+                       downHeap(m_data, k, n, CompareFunc);
+               }
+
+               /* a[1..N] is now a heap */
+               while (n >= 1)
+               {
+                       swap(0, n - 1); /* largest of a[0..n-1] */
+
+                       n = n - 1;
+                       /* restore a[1..i-1] heap */
+                       downHeap(m_data, 1, n, CompareFunc);
+               }
+       }
+
+       ///non-recursive binary search, assumes sorted array
+       int findBinarySearch(const T& key) const
+       {
+               int first = 0;
+               int last = size() - 1;
+
+               //assume sorted array
+               while (first <= last)
+               {
+                       int mid = (first + last) / 2;  // compute mid point.
+                       if (key > m_data[mid])
+                               first = mid + 1;  // repeat search in top half.
+                       else if (key < m_data[mid])
+                               last = mid - 1;  // repeat search in bottom half.
+                       else
+                               return mid;  // found it. return position /////
+               }
+               return size();  // failed to find key
+       }
+
+       int findLinearSearch(const T& key) const
+       {
+               int index = size();
+               int i;
+
+               for (i = 0; i < size(); i++)
+               {
+                       if (m_data[i] == key)
+                       {
+                               index = i;
+                               break;
+                       }
+               }
+               return index;
+       }
+
+       // If the key is not in the array, return -1 instead of 0,
+       // since 0 also means the first element in the array.
+       int findLinearSearch2(const T& key) const
+       {
+               int index = -1;
+               int i;
+
+               for (i = 0; i < size(); i++)
+               {
+                       if (m_data[i] == key)
+                       {
+                               index = i;
+                               break;
+                       }
+               }
+               return index;
+       }
+
+       void removeAtIndex(int index)
+       {
+               if (index < size())
+               {
+                       swap(index, size() - 1);
+                       pop_back();
+               }
+       }
+       void remove(const T& key)
+       {
+               int findIndex = findLinearSearch(key);
+               removeAtIndex(findIndex);
+       }
+
+       //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;
+       }
+
+       void copyFromArray(const btAlignedObjectArray& otherArray)
+       {
+               int otherSize = otherArray.size();
+               resize(otherSize);
+               otherArray.copy(0, otherSize, m_data);
+       }
+};
+
+#endif  //BT_OBJECT_ARRAY__
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btConvexHull.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btConvexHull.cpp
new file mode 100644 (file)
index 0000000..94b68ba
--- /dev/null
@@ -0,0 +1,1122 @@
+/*
+Stan Melax Convex Hull Computation
+Copyright (c) 2003-2006 Stan Melax http://www.melax.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 <string.h>
+
+#include "btConvexHull.h"
+#include "btAlignedObjectArray.h"
+#include "btMinMax.h"
+#include "btVector3.h"
+
+//----------------------------------
+
+class int3
+{
+public:
+       int x, y, z;
+       int3(){};
+       int3(int _x, int _y, int _z)
+       {
+               x = _x;
+               y = _y;
+               z = _z;
+       }
+       const int &operator[](int i) const { return (&x)[i]; }
+       int &operator[](int i) { return (&x)[i]; }
+};
+
+//------- btPlane ----------
+
+inline btPlane PlaneFlip(const btPlane &plane) { return btPlane(-plane.normal, -plane.dist); }
+inline int operator==(const btPlane &a, const btPlane &b) { return (a.normal == b.normal && a.dist == b.dist); }
+inline int coplanar(const btPlane &a, const btPlane &b) { return (a == b || a == PlaneFlip(b)); }
+
+//--------- Utility Functions ------
+
+btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1);
+btVector3 PlaneProject(const btPlane &plane, const btVector3 &point);
+
+btVector3 ThreePlaneIntersection(const btPlane &p0, const btPlane &p1, const btPlane &p2);
+btVector3 ThreePlaneIntersection(const btPlane &p0, const btPlane &p1, const btPlane &p2)
+{
+       btVector3 N1 = p0.normal;
+       btVector3 N2 = p1.normal;
+       btVector3 N3 = p2.normal;
+
+       btVector3 n2n3;
+       n2n3 = N2.cross(N3);
+       btVector3 n3n1;
+       n3n1 = N3.cross(N1);
+       btVector3 n1n2;
+       n1n2 = N1.cross(N2);
+
+       btScalar quotient = (N1.dot(n2n3));
+
+       btAssert(btFabs(quotient) > btScalar(0.000001));
+
+       quotient = btScalar(-1.) / quotient;
+       n2n3 *= p0.dist;
+       n3n1 *= p1.dist;
+       n1n2 *= p2.dist;
+       btVector3 potentialVertex = n2n3;
+       potentialVertex += n3n1;
+       potentialVertex += n1n2;
+       potentialVertex *= quotient;
+
+       btVector3 result(potentialVertex.getX(), potentialVertex.getY(), potentialVertex.getZ());
+       return result;
+}
+
+btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint = NULL, btVector3 *vpoint = NULL);
+btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2);
+btVector3 NormalOf(const btVector3 *vert, const int n);
+
+btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1)
+{
+       // returns the point where the line p0-p1 intersects the plane n&d
+       btVector3 dif;
+       dif = p1 - p0;
+       btScalar dn = btDot(plane.normal, dif);
+       btScalar t = -(plane.dist + btDot(plane.normal, p0)) / dn;
+       return p0 + (dif * t);
+}
+
+btVector3 PlaneProject(const btPlane &plane, const btVector3 &point)
+{
+       return point - plane.normal * (btDot(point, plane.normal) + plane.dist);
+}
+
+btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2)
+{
+       // return the normal of the triangle
+       // inscribed by v0, v1, and v2
+       btVector3 cp = btCross(v1 - v0, v2 - v1);
+       btScalar m = cp.length();
+       if (m == 0) return btVector3(1, 0, 0);
+       return cp * (btScalar(1.0) / m);
+}
+
+btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint)
+{
+       btVector3 cp;
+       cp = btCross(udir, vdir).normalized();
+
+       btScalar distu = -btDot(cp, ustart);
+       btScalar distv = -btDot(cp, vstart);
+       btScalar dist = (btScalar)fabs(distu - distv);
+       if (upoint)
+       {
+               btPlane plane;
+               plane.normal = btCross(vdir, cp).normalized();
+               plane.dist = -btDot(plane.normal, vstart);
+               *upoint = PlaneLineIntersection(plane, ustart, ustart + udir);
+       }
+       if (vpoint)
+       {
+               btPlane plane;
+               plane.normal = btCross(udir, cp).normalized();
+               plane.dist = -btDot(plane.normal, ustart);
+               *vpoint = PlaneLineIntersection(plane, vstart, vstart + vdir);
+       }
+       return dist;
+}
+
+#define COPLANAR (0)
+#define UNDER (1)
+#define OVER (2)
+#define SPLIT (OVER | UNDER)
+#define PAPERWIDTH (btScalar(0.001))
+
+btScalar planetestepsilon = PAPERWIDTH;
+
+typedef ConvexH::HalfEdge HalfEdge;
+
+ConvexH::ConvexH(int vertices_size, int edges_size, int facets_size)
+{
+       vertices.resize(vertices_size);
+       edges.resize(edges_size);
+       facets.resize(facets_size);
+}
+
+int PlaneTest(const btPlane &p, const btVector3 &v);
+int PlaneTest(const btPlane &p, const btVector3 &v)
+{
+       btScalar a = btDot(v, p.normal) + p.dist;
+       int flag = (a > planetestepsilon) ? OVER : ((a < -planetestepsilon) ? UNDER : COPLANAR);
+       return flag;
+}
+
+int SplitTest(ConvexH &convex, const btPlane &plane);
+int SplitTest(ConvexH &convex, const btPlane &plane)
+{
+       int flag = 0;
+       for (int i = 0; i < convex.vertices.size(); i++)
+       {
+               flag |= PlaneTest(plane, convex.vertices[i]);
+       }
+       return flag;
+}
+
+class VertFlag
+{
+public:
+       unsigned char planetest;
+       unsigned char junk;
+       unsigned char undermap;
+       unsigned char overmap;
+};
+class EdgeFlag
+{
+public:
+       unsigned char planetest;
+       unsigned char fixes;
+       short undermap;
+       short overmap;
+};
+class PlaneFlag
+{
+public:
+       unsigned char undermap;
+       unsigned char overmap;
+};
+class Coplanar
+{
+public:
+       unsigned short ea;
+       unsigned char v0;
+       unsigned char v1;
+};
+
+template <class T>
+int maxdirfiltered(const T *p, int count, const T &dir, btAlignedObjectArray<int> &allow)
+{
+       btAssert(count);
+       int m = -1;
+       for (int i = 0; i < count; i++)
+               if (allow[i])
+               {
+                       if (m == -1 || btDot(p[i], dir) > btDot(p[m], dir))
+                               m = i;
+               }
+       btAssert(m != -1);
+       return m;
+}
+
+btVector3 orth(const btVector3 &v);
+btVector3 orth(const btVector3 &v)
+{
+       btVector3 a = btCross(v, btVector3(0, 0, 1));
+       btVector3 b = btCross(v, btVector3(0, 1, 0));
+       if (a.length() > b.length())
+       {
+               return a.normalized();
+       }
+       else
+       {
+               return b.normalized();
+       }
+}
+
+template <class T>
+int maxdirsterid(const T *p, int count, const T &dir, btAlignedObjectArray<int> &allow)
+{
+       int m = -1;
+       while (m == -1)
+       {
+               m = maxdirfiltered(p, count, dir, allow);
+               if (allow[m] == 3) return m;
+               T u = orth(dir);
+               T v = btCross(u, dir);
+               int ma = -1;
+               for (btScalar x = btScalar(0.0); x <= btScalar(360.0); x += btScalar(45.0))
+               {
+                       btScalar s = btSin(SIMD_RADS_PER_DEG * (x));
+                       btScalar c = btCos(SIMD_RADS_PER_DEG * (x));
+                       int mb = maxdirfiltered(p, count, dir + (u * s + v * c) * btScalar(0.025), allow);
+                       if (ma == m && mb == m)
+                       {
+                               allow[m] = 3;
+                               return m;
+                       }
+                       if (ma != -1 && ma != mb)  // Yuck - this is really ugly
+                       {
+                               int mc = ma;
+                               for (btScalar xx = x - btScalar(40.0); xx <= x; xx += btScalar(5.0))
+                               {
+                                       btScalar s = btSin(SIMD_RADS_PER_DEG * (xx));
+                                       btScalar c = btCos(SIMD_RADS_PER_DEG * (xx));
+                                       int md = maxdirfiltered(p, count, dir + (u * s + v * c) * btScalar(0.025), allow);
+                                       if (mc == m && md == m)
+                                       {
+                                               allow[m] = 3;
+                                               return m;
+                                       }
+                                       mc = md;
+                               }
+                       }
+                       ma = mb;
+               }
+               allow[m] = 0;
+               m = -1;
+       }
+       btAssert(0);
+       return m;
+}
+
+int operator==(const int3 &a, const int3 &b);
+int operator==(const int3 &a, const int3 &b)
+{
+       for (int i = 0; i < 3; i++)
+       {
+               if (a[i] != b[i]) return 0;
+       }
+       return 1;
+}
+
+int above(btVector3 *vertices, const int3 &t, const btVector3 &p, btScalar epsilon);
+int above(btVector3 *vertices, const int3 &t, const btVector3 &p, btScalar epsilon)
+{
+       btVector3 n = TriNormal(vertices[t[0]], vertices[t[1]], vertices[t[2]]);
+       return (btDot(n, p - vertices[t[0]]) > epsilon);  // EPSILON???
+}
+int hasedge(const int3 &t, int a, int b);
+int hasedge(const int3 &t, int a, int b)
+{
+       for (int i = 0; i < 3; i++)
+       {
+               int i1 = (i + 1) % 3;
+               if (t[i] == a && t[i1] == b) return 1;
+       }
+       return 0;
+}
+int hasvert(const int3 &t, int v);
+int hasvert(const int3 &t, int v)
+{
+       return (t[0] == v || t[1] == v || t[2] == v);
+}
+int shareedge(const int3 &a, const int3 &b);
+int shareedge(const int3 &a, const int3 &b)
+{
+       int i;
+       for (i = 0; i < 3; i++)
+       {
+               int i1 = (i + 1) % 3;
+               if (hasedge(a, b[i1], b[i])) return 1;
+       }
+       return 0;
+}
+
+class btHullTriangle;
+
+class btHullTriangle : public int3
+{
+public:
+       int3 n;
+       int id;
+       int vmax;
+       btScalar rise;
+       btHullTriangle(int a, int b, int c) : int3(a, b, c), n(-1, -1, -1)
+       {
+               vmax = -1;
+               rise = btScalar(0.0);
+       }
+       ~btHullTriangle()
+       {
+       }
+       int &neib(int a, int b);
+};
+
+int &btHullTriangle::neib(int a, int b)
+{
+       static int er = -1;
+       int i;
+       for (i = 0; i < 3; i++)
+       {
+               int i1 = (i + 1) % 3;
+               int i2 = (i + 2) % 3;
+               if ((*this)[i] == a && (*this)[i1] == b) return n[i2];
+               if ((*this)[i] == b && (*this)[i1] == a) return n[i2];
+       }
+       btAssert(0);
+       return er;
+}
+void HullLibrary::b2bfix(btHullTriangle *s, btHullTriangle *t)
+{
+       int i;
+       for (i = 0; i < 3; i++)
+       {
+               int i1 = (i + 1) % 3;
+               int i2 = (i + 2) % 3;
+               int a = (*s)[i1];
+               int b = (*s)[i2];
+               btAssert(m_tris[s->neib(a, b)]->neib(b, a) == s->id);
+               btAssert(m_tris[t->neib(a, b)]->neib(b, a) == t->id);
+               m_tris[s->neib(a, b)]->neib(b, a) = t->neib(b, a);
+               m_tris[t->neib(b, a)]->neib(a, b) = s->neib(a, b);
+       }
+}
+
+void HullLibrary::removeb2b(btHullTriangle *s, btHullTriangle *t)
+{
+       b2bfix(s, t);
+       deAllocateTriangle(s);
+
+       deAllocateTriangle(t);
+}
+
+void HullLibrary::checkit(btHullTriangle *t)
+{
+       (void)t;
+
+       int i;
+       btAssert(m_tris[t->id] == t);
+       for (i = 0; i < 3; i++)
+       {
+               int i1 = (i + 1) % 3;
+               int i2 = (i + 2) % 3;
+               int a = (*t)[i1];
+               int b = (*t)[i2];
+
+               // release compile fix
+               (void)i1;
+               (void)i2;
+               (void)a;
+               (void)b;
+
+               btAssert(a != b);
+               btAssert(m_tris[t->n[i]]->neib(b, a) == t->id);
+       }
+}
+
+btHullTriangle *HullLibrary::allocateTriangle(int a, int b, int c)
+{
+       void *mem = btAlignedAlloc(sizeof(btHullTriangle), 16);
+       btHullTriangle *tr = new (mem) btHullTriangle(a, b, c);
+       tr->id = m_tris.size();
+       m_tris.push_back(tr);
+
+       return tr;
+}
+
+void HullLibrary::deAllocateTriangle(btHullTriangle *tri)
+{
+       btAssert(m_tris[tri->id] == tri);
+       m_tris[tri->id] = NULL;
+       tri->~btHullTriangle();
+       btAlignedFree(tri);
+}
+
+void HullLibrary::extrude(btHullTriangle *t0, int v)
+{
+       int3 t = *t0;
+       int n = m_tris.size();
+       btHullTriangle *ta = allocateTriangle(v, t[1], t[2]);
+       ta->n = int3(t0->n[0], n + 1, n + 2);
+       m_tris[t0->n[0]]->neib(t[1], t[2]) = n + 0;
+       btHullTriangle *tb = allocateTriangle(v, t[2], t[0]);
+       tb->n = int3(t0->n[1], n + 2, n + 0);
+       m_tris[t0->n[1]]->neib(t[2], t[0]) = n + 1;
+       btHullTriangle *tc = allocateTriangle(v, t[0], t[1]);
+       tc->n = int3(t0->n[2], n + 0, n + 1);
+       m_tris[t0->n[2]]->neib(t[0], t[1]) = n + 2;
+       checkit(ta);
+       checkit(tb);
+       checkit(tc);
+       if (hasvert(*m_tris[ta->n[0]], v)) removeb2b(ta, m_tris[ta->n[0]]);
+       if (hasvert(*m_tris[tb->n[0]], v)) removeb2b(tb, m_tris[tb->n[0]]);
+       if (hasvert(*m_tris[tc->n[0]], v)) removeb2b(tc, m_tris[tc->n[0]]);
+       deAllocateTriangle(t0);
+}
+
+btHullTriangle *HullLibrary::extrudable(btScalar epsilon)
+{
+       int i;
+       btHullTriangle *t = NULL;
+       for (i = 0; i < m_tris.size(); i++)
+       {
+               if (!t || (m_tris[i] && t->rise < m_tris[i]->rise))
+               {
+                       t = m_tris[i];
+               }
+       }
+       return (t->rise > epsilon) ? t : NULL;
+}
+
+int4 HullLibrary::FindSimplex(btVector3 *verts, int verts_count, btAlignedObjectArray<int> &allow)
+{
+       btVector3 basis[3];
+       basis[0] = btVector3(btScalar(0.01), btScalar(0.02), btScalar(1.0));
+       int p0 = maxdirsterid(verts, verts_count, basis[0], allow);
+       int p1 = maxdirsterid(verts, verts_count, -basis[0], allow);
+       basis[0] = verts[p0] - verts[p1];
+       if (p0 == p1 || basis[0] == btVector3(0, 0, 0))
+               return int4(-1, -1, -1, -1);
+       basis[1] = btCross(btVector3(btScalar(1), btScalar(0.02), btScalar(0)), basis[0]);
+       basis[2] = btCross(btVector3(btScalar(-0.02), btScalar(1), btScalar(0)), basis[0]);
+       if (basis[1].length() > basis[2].length())
+       {
+               basis[1].normalize();
+       }
+       else
+       {
+               basis[1] = basis[2];
+               basis[1].normalize();
+       }
+       int p2 = maxdirsterid(verts, verts_count, basis[1], allow);
+       if (p2 == p0 || p2 == p1)
+       {
+               p2 = maxdirsterid(verts, verts_count, -basis[1], allow);
+       }
+       if (p2 == p0 || p2 == p1)
+               return int4(-1, -1, -1, -1);
+       basis[1] = verts[p2] - verts[p0];
+       basis[2] = btCross(basis[1], basis[0]).normalized();
+       int p3 = maxdirsterid(verts, verts_count, basis[2], allow);
+       if (p3 == p0 || p3 == p1 || p3 == p2) p3 = maxdirsterid(verts, verts_count, -basis[2], allow);
+       if (p3 == p0 || p3 == p1 || p3 == p2)
+               return int4(-1, -1, -1, -1);
+       btAssert(!(p0 == p1 || p0 == p2 || p0 == p3 || p1 == p2 || p1 == p3 || p2 == p3));
+       if (btDot(verts[p3] - verts[p0], btCross(verts[p1] - verts[p0], verts[p2] - verts[p0])) < 0)
+       {
+               btSwap(p2, p3);
+       }
+       return int4(p0, p1, p2, p3);
+}
+
+int HullLibrary::calchullgen(btVector3 *verts, int verts_count, int vlimit)
+{
+       if (verts_count < 4) return 0;
+       if (vlimit == 0) vlimit = 1000000000;
+       int j;
+       btVector3 bmin(*verts), bmax(*verts);
+       btAlignedObjectArray<int> isextreme;
+       isextreme.reserve(verts_count);
+       btAlignedObjectArray<int> allow;
+       allow.reserve(verts_count);
+
+       for (j = 0; j < verts_count; j++)
+       {
+               allow.push_back(1);
+               isextreme.push_back(0);
+               bmin.setMin(verts[j]);
+               bmax.setMax(verts[j]);
+       }
+       btScalar epsilon = (bmax - bmin).length() * btScalar(0.001);
+       btAssert(epsilon != 0.0);
+
+       int4 p = FindSimplex(verts, verts_count, allow);
+       if (p.x == -1) return 0;  // simplex failed
+
+       btVector3 center = (verts[p[0]] + verts[p[1]] + verts[p[2]] + verts[p[3]]) / btScalar(4.0);  // a valid interior point
+       btHullTriangle *t0 = allocateTriangle(p[2], p[3], p[1]);
+       t0->n = int3(2, 3, 1);
+       btHullTriangle *t1 = allocateTriangle(p[3], p[2], p[0]);
+       t1->n = int3(3, 2, 0);
+       btHullTriangle *t2 = allocateTriangle(p[0], p[1], p[3]);
+       t2->n = int3(0, 1, 3);
+       btHullTriangle *t3 = allocateTriangle(p[1], p[0], p[2]);
+       t3->n = int3(1, 0, 2);
+       isextreme[p[0]] = isextreme[p[1]] = isextreme[p[2]] = isextreme[p[3]] = 1;
+       checkit(t0);
+       checkit(t1);
+       checkit(t2);
+       checkit(t3);
+
+       for (j = 0; j < m_tris.size(); j++)
+       {
+               btHullTriangle *t = m_tris[j];
+               btAssert(t);
+               btAssert(t->vmax < 0);
+               btVector3 n = TriNormal(verts[(*t)[0]], verts[(*t)[1]], verts[(*t)[2]]);
+               t->vmax = maxdirsterid(verts, verts_count, n, allow);
+               t->rise = btDot(n, verts[t->vmax] - verts[(*t)[0]]);
+       }
+       btHullTriangle *te;
+       vlimit -= 4;
+       while (vlimit > 0 && ((te = extrudable(epsilon)) != 0))
+       {
+               //int3 ti=*te;
+               int v = te->vmax;
+               btAssert(v != -1);
+               btAssert(!isextreme[v]);  // wtf we've already done this vertex
+               isextreme[v] = 1;
+               //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
+               j = m_tris.size();
+               while (j--)
+               {
+                       if (!m_tris[j]) continue;
+                       int3 t = *m_tris[j];
+                       if (above(verts, t, verts[v], btScalar(0.01) * epsilon))
+                       {
+                               extrude(m_tris[j], v);
+                       }
+               }
+               // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
+               j = m_tris.size();
+               while (j--)
+               {
+                       if (!m_tris[j]) continue;
+                       if (!hasvert(*m_tris[j], v)) break;
+                       int3 nt = *m_tris[j];
+                       if (above(verts, nt, center, btScalar(0.01) * epsilon) || btCross(verts[nt[1]] - verts[nt[0]], verts[nt[2]] - verts[nt[1]]).length() < epsilon * epsilon * btScalar(0.1))
+                       {
+                               btHullTriangle *nb = m_tris[m_tris[j]->n[0]];
+                               btAssert(nb);
+                               btAssert(!hasvert(*nb, v));
+                               btAssert(nb->id < j);
+                               extrude(nb, v);
+                               j = m_tris.size();
+                       }
+               }
+               j = m_tris.size();
+               while (j--)
+               {
+                       btHullTriangle *t = m_tris[j];
+                       if (!t) continue;
+                       if (t->vmax >= 0) break;
+                       btVector3 n = TriNormal(verts[(*t)[0]], verts[(*t)[1]], verts[(*t)[2]]);
+                       t->vmax = maxdirsterid(verts, verts_count, n, allow);
+                       if (isextreme[t->vmax])
+                       {
+                               t->vmax = -1;  // already done that vertex - algorithm needs to be able to terminate.
+                       }
+                       else
+                       {
+                               t->rise = btDot(n, verts[t->vmax] - verts[(*t)[0]]);
+                       }
+               }
+               vlimit--;
+       }
+       return 1;
+}
+
+int HullLibrary::calchull(btVector3 *verts, int verts_count, TUIntArray &tris_out, int &tris_count, int vlimit)
+{
+       int rc = calchullgen(verts, verts_count, vlimit);
+       if (!rc) return 0;
+       btAlignedObjectArray<int> ts;
+       int i;
+
+       for (i = 0; i < m_tris.size(); i++)
+       {
+               if (m_tris[i])
+               {
+                       for (int j = 0; j < 3; j++)
+                               ts.push_back((*m_tris[i])[j]);
+                       deAllocateTriangle(m_tris[i]);
+               }
+       }
+       tris_count = ts.size() / 3;
+       tris_out.resize(ts.size());
+
+       for (i = 0; i < ts.size(); i++)
+       {
+               tris_out[i] = static_cast<unsigned int>(ts[i]);
+       }
+       m_tris.resize(0);
+
+       return 1;
+}
+
+bool HullLibrary::ComputeHull(unsigned int vcount, const btVector3 *vertices, PHullResult &result, unsigned int vlimit)
+{
+       int tris_count;
+       int ret = calchull((btVector3 *)vertices, (int)vcount, result.m_Indices, tris_count, static_cast<int>(vlimit));
+       if (!ret) return false;
+       result.mIndexCount = (unsigned int)(tris_count * 3);
+       result.mFaceCount = (unsigned int)tris_count;
+       result.mVertices = (btVector3 *)vertices;
+       result.mVcount = (unsigned int)vcount;
+       return true;
+}
+
+void ReleaseHull(PHullResult &result);
+void ReleaseHull(PHullResult &result)
+{
+       if (result.m_Indices.size())
+       {
+               result.m_Indices.clear();
+       }
+
+       result.mVcount = 0;
+       result.mIndexCount = 0;
+       result.mVertices = 0;
+}
+
+//*********************************************************************
+//*********************************************************************
+//********  HullLib header
+//*********************************************************************
+//*********************************************************************
+
+//*********************************************************************
+//*********************************************************************
+//********  HullLib implementation
+//*********************************************************************
+//*********************************************************************
+
+HullError HullLibrary::CreateConvexHull(const HullDesc &desc,  // describes the input request
+                                                                               HullResult &result)    // contains the resulst
+{
+       HullError ret = QE_FAIL;
+
+       PHullResult hr;
+
+       unsigned int vcount = desc.mVcount;
+       if (vcount < 8) vcount = 8;
+
+       btAlignedObjectArray<btVector3> vertexSource;
+       btVector3 zero;
+       zero.setZero();
+       vertexSource.resize(static_cast<int>(vcount), zero);
+
+       btVector3 scale;
+
+       unsigned int ovcount;
+
+       bool ok = CleanupVertices(desc.mVcount, desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale);  // normalize point cloud, remove duplicates!
+
+       if (ok)
+       {
+               //              if ( 1 ) // scale vertices back to their original size.
+               {
+                       for (unsigned int i = 0; i < ovcount; i++)
+                       {
+                               btVector3 &v = vertexSource[static_cast<int>(i)];
+                               v[0] *= scale[0];
+                               v[1] *= scale[1];
+                               v[2] *= scale[2];
+                       }
+               }
+
+               ok = ComputeHull(ovcount, &vertexSource[0], hr, desc.mMaxVertices);
+
+               if (ok)
+               {
+                       // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table.
+                       btAlignedObjectArray<btVector3> vertexScratch;
+                       vertexScratch.resize(static_cast<int>(hr.mVcount));
+
+                       BringOutYourDead(hr.mVertices, hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount);
+
+                       ret = QE_OK;
+
+                       if (desc.HasHullFlag(QF_TRIANGLES))  // if he wants the results as triangle!
+                       {
+                               result.mPolygons = false;
+                               result.mNumOutputVertices = ovcount;
+                               result.m_OutputVertices.resize(static_cast<int>(ovcount));
+                               result.mNumFaces = hr.mFaceCount;
+                               result.mNumIndices = hr.mIndexCount;
+
+                               result.m_Indices.resize(static_cast<int>(hr.mIndexCount));
+
+                               memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3) * ovcount);
+
+                               if (desc.HasHullFlag(QF_REVERSE_ORDER))
+                               {
+                                       const unsigned int *source = &hr.m_Indices[0];
+                                       unsigned int *dest = &result.m_Indices[0];
+
+                                       for (unsigned int i = 0; i < hr.mFaceCount; i++)
+                                       {
+                                               dest[0] = source[2];
+                                               dest[1] = source[1];
+                                               dest[2] = source[0];
+                                               dest += 3;
+                                               source += 3;
+                                       }
+                               }
+                               else
+                               {
+                                       memcpy(&result.m_Indices[0], &hr.m_Indices[0], sizeof(unsigned int) * hr.mIndexCount);
+                               }
+                       }
+                       else
+                       {
+                               result.mPolygons = true;
+                               result.mNumOutputVertices = ovcount;
+                               result.m_OutputVertices.resize(static_cast<int>(ovcount));
+                               result.mNumFaces = hr.mFaceCount;
+                               result.mNumIndices = hr.mIndexCount + hr.mFaceCount;
+                               result.m_Indices.resize(static_cast<int>(result.mNumIndices));
+                               memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3) * ovcount);
+
+                               //                              if ( 1 )
+                               {
+                                       const unsigned int *source = &hr.m_Indices[0];
+                                       unsigned int *dest = &result.m_Indices[0];
+                                       for (unsigned int i = 0; i < hr.mFaceCount; i++)
+                                       {
+                                               dest[0] = 3;
+                                               if (desc.HasHullFlag(QF_REVERSE_ORDER))
+                                               {
+                                                       dest[1] = source[2];
+                                                       dest[2] = source[1];
+                                                       dest[3] = source[0];
+                                               }
+                                               else
+                                               {
+                                                       dest[1] = source[0];
+                                                       dest[2] = source[1];
+                                                       dest[3] = source[2];
+                                               }
+
+                                               dest += 4;
+                                               source += 3;
+                                       }
+                               }
+                       }
+                       ReleaseHull(hr);
+               }
+       }
+
+       return ret;
+}
+
+HullError HullLibrary::ReleaseResult(HullResult &result)  // release memory allocated for this result, we are done with it.
+{
+       if (result.m_OutputVertices.size())
+       {
+               result.mNumOutputVertices = 0;
+               result.m_OutputVertices.clear();
+       }
+       if (result.m_Indices.size())
+       {
+               result.mNumIndices = 0;
+               result.m_Indices.clear();
+       }
+       return QE_OK;
+}
+
+static void addPoint(unsigned int &vcount, btVector3 *p, btScalar x, btScalar y, btScalar z)
+{
+       // XXX, might be broken
+       btVector3 &dest = p[vcount];
+       dest[0] = x;
+       dest[1] = y;
+       dest[2] = z;
+       vcount++;
+}
+
+btScalar GetDist(btScalar px, btScalar py, btScalar pz, const btScalar *p2);
+btScalar GetDist(btScalar px, btScalar py, btScalar pz, const btScalar *p2)
+{
+       btScalar dx = px - p2[0];
+       btScalar dy = py - p2[1];
+       btScalar dz = pz - p2[2];
+
+       return dx * dx + dy * dy + dz * dz;
+}
+
+bool HullLibrary::CleanupVertices(unsigned int svcount,
+                                                                 const btVector3 *svertices,
+                                                                 unsigned int stride,
+                                                                 unsigned int &vcount,  // output number of vertices
+                                                                 btVector3 *vertices,   // location to store the results.
+                                                                 btScalar normalepsilon,
+                                                                 btVector3 &scale)
+{
+       if (svcount == 0) return false;
+
+       m_vertexIndexMapping.resize(0);
+
+#define EPSILON btScalar(0.000001) /* close enough to consider two btScalaring point numbers to be 'the same'. */
+
+       vcount = 0;
+
+       btScalar recip[3] = {0.f, 0.f, 0.f};
+
+       if (scale)
+       {
+               scale[0] = 1;
+               scale[1] = 1;
+               scale[2] = 1;
+       }
+
+       btScalar bmin[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
+       btScalar bmax[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
+
+       const char *vtx = (const char *)svertices;
+
+       //      if ( 1 )
+       {
+               for (unsigned int i = 0; i < svcount; i++)
+               {
+                       const btScalar *p = (const btScalar *)vtx;
+
+                       vtx += stride;
+
+                       for (int j = 0; j < 3; j++)
+                       {
+                               if (p[j] < bmin[j]) bmin[j] = p[j];
+                               if (p[j] > bmax[j]) bmax[j] = p[j];
+                       }
+               }
+       }
+
+       btScalar dx = bmax[0] - bmin[0];
+       btScalar dy = bmax[1] - bmin[1];
+       btScalar dz = bmax[2] - bmin[2];
+
+       btVector3 center;
+
+       center[0] = dx * btScalar(0.5) + bmin[0];
+       center[1] = dy * btScalar(0.5) + bmin[1];
+       center[2] = dz * btScalar(0.5) + bmin[2];
+
+       if (dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3)
+       {
+               btScalar len = FLT_MAX;
+
+               if (dx > EPSILON && dx < len) len = dx;
+               if (dy > EPSILON && dy < len) len = dy;
+               if (dz > EPSILON && dz < len) len = dz;
+
+               if (len == FLT_MAX)
+               {
+                       dx = dy = dz = btScalar(0.01);  // one centimeter
+               }
+               else
+               {
+                       if (dx < EPSILON) dx = len * btScalar(0.05);  // 1/5th the shortest non-zero edge.
+                       if (dy < EPSILON) dy = len * btScalar(0.05);
+                       if (dz < EPSILON) dz = len * btScalar(0.05);
+               }
+
+               btScalar x1 = center[0] - dx;
+               btScalar x2 = center[0] + dx;
+
+               btScalar y1 = center[1] - dy;
+               btScalar y2 = center[1] + dy;
+
+               btScalar z1 = center[2] - dz;
+               btScalar z2 = center[2] + dz;
+
+               addPoint(vcount, vertices, x1, y1, z1);
+               addPoint(vcount, vertices, x2, y1, z1);
+               addPoint(vcount, vertices, x2, y2, z1);
+               addPoint(vcount, vertices, x1, y2, z1);
+               addPoint(vcount, vertices, x1, y1, z2);
+               addPoint(vcount, vertices, x2, y1, z2);
+               addPoint(vcount, vertices, x2, y2, z2);
+               addPoint(vcount, vertices, x1, y2, z2);
+
+               return true;  // return cube
+       }
+       else
+       {
+               if (scale)
+               {
+                       scale[0] = dx;
+                       scale[1] = dy;
+                       scale[2] = dz;
+
+                       recip[0] = 1 / dx;
+                       recip[1] = 1 / dy;
+                       recip[2] = 1 / dz;
+
+                       center[0] *= recip[0];
+                       center[1] *= recip[1];
+                       center[2] *= recip[2];
+               }
+       }
+
+       vtx = (const char *)svertices;
+
+       for (unsigned int i = 0; i < svcount; i++)
+       {
+               const btVector3 *p = (const btVector3 *)vtx;
+               vtx += stride;
+
+               btScalar px = p->getX();
+               btScalar py = p->getY();
+               btScalar pz = p->getZ();
+
+               if (scale)
+               {
+                       px = px * recip[0];  // normalize
+                       py = py * recip[1];  // normalize
+                       pz = pz * recip[2];  // normalize
+               }
+
+               //              if ( 1 )
+               {
+                       unsigned int j;
+
+                       for (j = 0; j < vcount; j++)
+                       {
+                               /// XXX might be broken
+                               btVector3 &v = vertices[j];
+
+                               btScalar x = v[0];
+                               btScalar y = v[1];
+                               btScalar z = v[2];
+
+                               btScalar dx = btFabs(x - px);
+                               btScalar dy = btFabs(y - py);
+                               btScalar dz = btFabs(z - pz);
+
+                               if (dx < normalepsilon && dy < normalepsilon && dz < normalepsilon)
+                               {
+                                       // ok, it is close enough to the old one
+                                       // now let us see if it is further from the center of the point cloud than the one we already recorded.
+                                       // in which case we keep this one instead.
+
+                                       btScalar dist1 = GetDist(px, py, pz, center);
+                                       btScalar dist2 = GetDist(v[0], v[1], v[2], center);
+
+                                       if (dist1 > dist2)
+                                       {
+                                               v[0] = px;
+                                               v[1] = py;
+                                               v[2] = pz;
+                                       }
+
+                                       break;
+                               }
+                       }
+
+                       if (j == vcount)
+                       {
+                               btVector3 &dest = vertices[vcount];
+                               dest[0] = px;
+                               dest[1] = py;
+                               dest[2] = pz;
+                               vcount++;
+                       }
+                       m_vertexIndexMapping.push_back(j);
+               }
+       }
+
+       // ok..now make sure we didn't prune so many vertices it is now invalid.
+       //      if ( 1 )
+       {
+               btScalar bmin[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
+               btScalar bmax[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
+
+               for (unsigned int i = 0; i < vcount; i++)
+               {
+                       const btVector3 &p = vertices[i];
+                       for (int j = 0; j < 3; j++)
+                       {
+                               if (p[j] < bmin[j]) bmin[j] = p[j];
+                               if (p[j] > bmax[j]) bmax[j] = p[j];
+                       }
+               }
+
+               btScalar dx = bmax[0] - bmin[0];
+               btScalar dy = bmax[1] - bmin[1];
+               btScalar dz = bmax[2] - bmin[2];
+
+               if (dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
+               {
+                       btScalar cx = dx * btScalar(0.5) + bmin[0];
+                       btScalar cy = dy * btScalar(0.5) + bmin[1];
+                       btScalar cz = dz * btScalar(0.5) + bmin[2];
+
+                       btScalar len = FLT_MAX;
+
+                       if (dx >= EPSILON && dx < len) len = dx;
+                       if (dy >= EPSILON && dy < len) len = dy;
+                       if (dz >= EPSILON && dz < len) len = dz;
+
+                       if (len == FLT_MAX)
+                       {
+                               dx = dy = dz = btScalar(0.01);  // one centimeter
+                       }
+                       else
+                       {
+                               if (dx < EPSILON) dx = len * btScalar(0.05);  // 1/5th the shortest non-zero edge.
+                               if (dy < EPSILON) dy = len * btScalar(0.05);
+                               if (dz < EPSILON) dz = len * btScalar(0.05);
+                       }
+
+                       btScalar x1 = cx - dx;
+                       btScalar x2 = cx + dx;
+
+                       btScalar y1 = cy - dy;
+                       btScalar y2 = cy + dy;
+
+                       btScalar z1 = cz - dz;
+                       btScalar z2 = cz + dz;
+
+                       vcount = 0;  // add box
+
+                       addPoint(vcount, vertices, x1, y1, z1);
+                       addPoint(vcount, vertices, x2, y1, z1);
+                       addPoint(vcount, vertices, x2, y2, z1);
+                       addPoint(vcount, vertices, x1, y2, z1);
+                       addPoint(vcount, vertices, x1, y1, z2);
+                       addPoint(vcount, vertices, x2, y1, z2);
+                       addPoint(vcount, vertices, x2, y2, z2);
+                       addPoint(vcount, vertices, x1, y2, z2);
+
+                       return true;
+               }
+       }
+
+       return true;
+}
+
+void HullLibrary::BringOutYourDead(const btVector3 *verts, unsigned int vcount, btVector3 *overts, unsigned int &ocount, unsigned int *indices, unsigned indexcount)
+{
+       btAlignedObjectArray<int> tmpIndices;
+       tmpIndices.resize(m_vertexIndexMapping.size());
+       int i;
+
+       for (i = 0; i < m_vertexIndexMapping.size(); i++)
+       {
+               tmpIndices[i] = m_vertexIndexMapping[i];
+       }
+
+       TUIntArray usedIndices;
+       usedIndices.resize(static_cast<int>(vcount));
+       memset(&usedIndices[0], 0, sizeof(unsigned int) * vcount);
+
+       ocount = 0;
+
+       for (i = 0; i < int(indexcount); i++)
+       {
+               unsigned int v = indices[i];  // original array index
+
+               btAssert(v >= 0 && v < vcount);
+
+               if (usedIndices[static_cast<int>(v)])  // if already remapped
+               {
+                       indices[i] = usedIndices[static_cast<int>(v)] - 1;  // index to new array
+               }
+               else
+               {
+                       indices[i] = ocount;  // new index mapping
+
+                       overts[ocount][0] = verts[v][0];  // copy old vert to new vert array
+                       overts[ocount][1] = verts[v][1];
+                       overts[ocount][2] = verts[v][2];
+
+                       for (int k = 0; k < m_vertexIndexMapping.size(); k++)
+                       {
+                               if (tmpIndices[k] == int(v))
+                                       m_vertexIndexMapping[k] = ocount;
+                       }
+
+                       ocount++;  // increment output vert count
+
+                       btAssert(ocount >= 0 && ocount <= vcount);
+
+                       usedIndices[static_cast<int>(v)] = ocount;  // assign new index remapping
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btConvexHull.h b/dali-physics/third-party/bullet3/src/LinearMath/btConvexHull.h
new file mode 100644 (file)
index 0000000..f890d75
--- /dev/null
@@ -0,0 +1,233 @@
+
+/*
+Stan Melax Convex Hull Computation
+Copyright (c) 2008 Stan Melax http://www.melax.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.
+*/
+
+///includes modifications/improvements by John Ratcliff, see BringOutYourDead below.
+
+#ifndef BT_CD_HULL_H
+#define BT_CD_HULL_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+typedef btAlignedObjectArray<unsigned int> TUIntArray;
+
+class HullResult
+{
+public:
+       HullResult(void)
+       {
+               mPolygons = true;
+               mNumOutputVertices = 0;
+               mNumFaces = 0;
+               mNumIndices = 0;
+       }
+       bool mPolygons;                                    // true if indices represents polygons, false indices are triangles
+       unsigned int mNumOutputVertices;                   // number of vertices in the output hull
+       btAlignedObjectArray<btVector3> m_OutputVertices;  // array of vertices
+       unsigned int mNumFaces;                            // the number of faces produced
+       unsigned int mNumIndices;                          // the total number of indices
+       btAlignedObjectArray<unsigned int> m_Indices;      // pointer to indices.
+
+       // If triangles, then indices are array indexes into the vertex list.
+       // If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
+};
+
+enum HullFlag
+{
+       QF_TRIANGLES = (1 << 0),      // report results as triangles, not polygons.
+       QF_REVERSE_ORDER = (1 << 1),  // reverse order of the triangle indices.
+       QF_DEFAULT = QF_TRIANGLES
+};
+
+class HullDesc
+{
+public:
+       HullDesc(void)
+       {
+               mFlags = QF_DEFAULT;
+               mVcount = 0;
+               mVertices = 0;
+               mVertexStride = sizeof(btVector3);
+               mNormalEpsilon = 0.001f;
+               mMaxVertices = 4096;  // maximum number of points to be considered for a convex hull.
+               mMaxFaces = 4096;
+       };
+
+       HullDesc(HullFlag flag,
+                        unsigned int vcount,
+                        const btVector3* vertices,
+                        unsigned int stride = sizeof(btVector3))
+       {
+               mFlags = flag;
+               mVcount = vcount;
+               mVertices = vertices;
+               mVertexStride = stride;
+               mNormalEpsilon = btScalar(0.001);
+               mMaxVertices = 4096;
+       }
+
+       bool HasHullFlag(HullFlag flag) const
+       {
+               if (mFlags & flag) return true;
+               return false;
+       }
+
+       void SetHullFlag(HullFlag flag)
+       {
+               mFlags |= flag;
+       }
+
+       void ClearHullFlag(HullFlag flag)
+       {
+               mFlags &= ~flag;
+       }
+
+       unsigned int mFlags;         // flags to use when generating the convex hull.
+       unsigned int mVcount;        // number of vertices in the input point cloud
+       const btVector3* mVertices;  // the array of vertices.
+       unsigned int mVertexStride;  // the stride of each vertex, in bytes.
+       btScalar mNormalEpsilon;     // the epsilon for removing duplicates.  This is a normalized value, if normalized bit is on.
+       unsigned int mMaxVertices;   // maximum number of vertices to be considered for the hull!
+       unsigned int mMaxFaces;
+};
+
+enum HullError
+{
+       QE_OK,   // success!
+       QE_FAIL  // failed.
+};
+
+class btPlane
+{
+public:
+       btVector3 normal;
+       btScalar dist;  // distance below origin - the D from plane equasion Ax+By+Cz+D=0
+       btPlane(const btVector3& n, btScalar d) : normal(n), dist(d) {}
+       btPlane() : normal(), dist(0) {}
+};
+
+class ConvexH
+{
+public:
+       class HalfEdge
+       {
+       public:
+               short ea;         // the other half of the edge (index into edges list)
+               unsigned char v;  // the vertex at the start of this edge (index into vertices list)
+               unsigned char p;  // the facet on which this edge lies (index into facets list)
+               HalfEdge() {}
+               HalfEdge(short _ea, unsigned char _v, unsigned char _p) : ea(_ea), v(_v), p(_p) {}
+       };
+       ConvexH()
+       {
+       }
+       ~ConvexH()
+       {
+       }
+       btAlignedObjectArray<btVector3> vertices;
+       btAlignedObjectArray<HalfEdge> edges;
+       btAlignedObjectArray<btPlane> facets;
+       ConvexH(int vertices_size, int edges_size, int facets_size);
+};
+
+class int4
+{
+public:
+       int x, y, z, w;
+       int4(){};
+       int4(int _x, int _y, int _z, int _w)
+       {
+               x = _x;
+               y = _y;
+               z = _z;
+               w = _w;
+       }
+       const int& operator[](int i) const { return (&x)[i]; }
+       int& operator[](int i) { return (&x)[i]; }
+};
+
+class PHullResult
+{
+public:
+       PHullResult(void)
+       {
+               mVcount = 0;
+               mIndexCount = 0;
+               mFaceCount = 0;
+               mVertices = 0;
+       }
+
+       unsigned int mVcount;
+       unsigned int mIndexCount;
+       unsigned int mFaceCount;
+       btVector3* mVertices;
+       TUIntArray m_Indices;
+};
+
+///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method.
+///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape.
+class HullLibrary
+{
+       btAlignedObjectArray<class btHullTriangle*> m_tris;
+
+public:
+       btAlignedObjectArray<int> m_vertexIndexMapping;
+
+       HullError CreateConvexHull(const HullDesc& desc,  // describes the input request
+                                                          HullResult& result);   // contains the resulst
+       HullError ReleaseResult(HullResult& result);      // release memory allocated for this result, we are done with it.
+
+private:
+       bool ComputeHull(unsigned int vcount, const btVector3* vertices, PHullResult& result, unsigned int vlimit);
+
+       class btHullTriangle* allocateTriangle(int a, int b, int c);
+       void deAllocateTriangle(btHullTriangle*);
+       void b2bfix(btHullTriangle* s, btHullTriangle* t);
+
+       void removeb2b(btHullTriangle* s, btHullTriangle* t);
+
+       void checkit(btHullTriangle* t);
+
+       btHullTriangle* extrudable(btScalar epsilon);
+
+       int calchull(btVector3* verts, int verts_count, TUIntArray& tris_out, int& tris_count, int vlimit);
+
+       int calchullgen(btVector3* verts, int verts_count, int vlimit);
+
+       int4 FindSimplex(btVector3* verts, int verts_count, btAlignedObjectArray<int>& allow);
+
+       class ConvexH* ConvexHCrop(ConvexH& convex, const btPlane& slice);
+
+       void extrude(class btHullTriangle* t0, int v);
+
+       ConvexH* test_cube();
+
+       //BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
+       //After the hull is generated it give you back a set of polygon faces which index the *original* point cloud.
+       //The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull.
+       //The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation.
+       void BringOutYourDead(const btVector3* verts, unsigned int vcount, btVector3* overts, unsigned int& ocount, unsigned int* indices, unsigned indexcount);
+
+       bool CleanupVertices(unsigned int svcount,
+                                                const btVector3* svertices,
+                                                unsigned int stride,
+                                                unsigned int& vcount,  // output number of vertices
+                                                btVector3* vertices,   // location to store the results.
+                                                btScalar normalepsilon,
+                                                btVector3& scale);
+};
+
+#endif  //BT_CD_HULL_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btConvexHullComputer.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btConvexHullComputer.cpp
new file mode 100644 (file)
index 0000000..12125fd
--- /dev/null
@@ -0,0 +1,2760 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 <string.h>
+
+#include "btConvexHullComputer.h"
+#include "btAlignedObjectArray.h"
+#include "btMinMax.h"
+#include "btVector3.h"
+
+#ifdef __GNUC__
+#include <stdint.h>
+#elif defined(_MSC_VER)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#else
+typedef int int32_t;
+typedef long long int int64_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long int uint64_t;
+#endif
+
+//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
+//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL))  // || (defined(__ICL) && defined(_M_X64))   bug in Intel compiler, disable inline assembly
+//     #define USE_X86_64_ASM
+//#endif
+
+//#define DEBUG_CONVEX_HULL
+//#define SHOW_ITERATIONS
+
+#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
+#include <stdio.h>
+#endif
+
+// Convex hull implementation based on Preparata and Hong
+// Ole Kniemeyer, MAXON Computer GmbH
+class btConvexHullInternal
+{
+public:
+       class Point64
+       {
+       public:
+               int64_t x;
+               int64_t y;
+               int64_t z;
+
+               Point64(int64_t x, int64_t y, int64_t z) : x(x), y(y), z(z)
+               {
+               }
+
+               bool isZero()
+               {
+                       return (x == 0) && (y == 0) && (z == 0);
+               }
+
+               int64_t dot(const Point64& b) const
+               {
+                       return x * b.x + y * b.y + z * b.z;
+               }
+       };
+
+       class Point32
+       {
+       public:
+               int32_t x;
+               int32_t y;
+               int32_t z;
+               int index;
+
+               Point32()
+               {
+               }
+
+               Point32(int32_t x, int32_t y, int32_t z) : x(x), y(y), z(z), index(-1)
+               {
+               }
+
+               bool operator==(const Point32& b) const
+               {
+                       return (x == b.x) && (y == b.y) && (z == b.z);
+               }
+
+               bool operator!=(const Point32& b) const
+               {
+                       return (x != b.x) || (y != b.y) || (z != b.z);
+               }
+
+               bool isZero()
+               {
+                       return (x == 0) && (y == 0) && (z == 0);
+               }
+
+               Point64 cross(const Point32& b) const
+               {
+                       return Point64(((int64_t)y) * b.z - ((int64_t)z) * b.y, ((int64_t)z) * b.x - ((int64_t)x) * b.z, ((int64_t)x) * b.y - ((int64_t)y) * b.x);
+               }
+
+               Point64 cross(const Point64& b) const
+               {
+                       return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+               }
+
+               int64_t dot(const Point32& b) const
+               {
+                       return ((int64_t)x) * b.x + ((int64_t)y) * b.y + ((int64_t)z) * b.z;
+               }
+
+               int64_t dot(const Point64& b) const
+               {
+                       return x * b.x + y * b.y + z * b.z;
+               }
+
+               Point32 operator+(const Point32& b) const
+               {
+                       return Point32(x + b.x, y + b.y, z + b.z);
+               }
+
+               Point32 operator-(const Point32& b) const
+               {
+                       return Point32(x - b.x, y - b.y, z - b.z);
+               }
+       };
+
+       class Int128
+       {
+       public:
+               uint64_t low;
+               uint64_t high;
+
+               Int128()
+               {
+               }
+
+               Int128(uint64_t low, uint64_t high) : low(low), high(high)
+               {
+               }
+
+               Int128(uint64_t low) : low(low), high(0)
+               {
+               }
+
+               Int128(int64_t value) : low(value), high((value >= 0) ? 0 : (uint64_t)-1LL)
+               {
+               }
+
+               static Int128 mul(int64_t a, int64_t b);
+
+               static Int128 mul(uint64_t a, uint64_t b);
+
+               Int128 operator-() const
+               {
+                       return Int128((uint64_t) - (int64_t)low, ~high + (low == 0));
+               }
+
+               Int128 operator+(const Int128& b) const
+               {
+#ifdef USE_X86_64_ASM
+                       Int128 result;
+                       __asm__(
+                               "addq %[bl], %[rl]\n\t"
+                               "adcq %[bh], %[rh]\n\t"
+                               : [rl] "=r"(result.low), [rh] "=r"(result.high)
+                               : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+                               : "cc");
+                       return result;
+#else
+                       uint64_t lo = low + b.low;
+                       return Int128(lo, high + b.high + (lo < low));
+#endif
+               }
+
+               Int128 operator-(const Int128& b) const
+               {
+#ifdef USE_X86_64_ASM
+                       Int128 result;
+                       __asm__(
+                               "subq %[bl], %[rl]\n\t"
+                               "sbbq %[bh], %[rh]\n\t"
+                               : [rl] "=r"(result.low), [rh] "=r"(result.high)
+                               : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+                               : "cc");
+                       return result;
+#else
+                       return *this + -b;
+#endif
+               }
+
+               Int128& operator+=(const Int128& b)
+               {
+#ifdef USE_X86_64_ASM
+                       __asm__(
+                               "addq %[bl], %[rl]\n\t"
+                               "adcq %[bh], %[rh]\n\t"
+                               : [rl] "=r"(low), [rh] "=r"(high)
+                               : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+                               : "cc");
+#else
+                       uint64_t lo = low + b.low;
+                       if (lo < low)
+                       {
+                               ++high;
+                       }
+                       low = lo;
+                       high += b.high;
+#endif
+                       return *this;
+               }
+
+               Int128& operator++()
+               {
+                       if (++low == 0)
+                       {
+                               ++high;
+                       }
+                       return *this;
+               }
+
+               Int128 operator*(int64_t b) const;
+
+               btScalar toScalar() const
+               {
+                       return ((int64_t)high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low)
+                                                                               : -(-*this).toScalar();
+               }
+
+               int getSign() const
+               {
+                       return ((int64_t)high < 0) ? -1 : (high || low) ? 1 : 0;
+               }
+
+               bool operator<(const Int128& b) const
+               {
+                       return (high < b.high) || ((high == b.high) && (low < b.low));
+               }
+
+               int ucmp(const Int128& b) const
+               {
+                       if (high < b.high)
+                       {
+                               return -1;
+                       }
+                       if (high > b.high)
+                       {
+                               return 1;
+                       }
+                       if (low < b.low)
+                       {
+                               return -1;
+                       }
+                       if (low > b.low)
+                       {
+                               return 1;
+                       }
+                       return 0;
+               }
+       };
+
+       class Rational64
+       {
+       private:
+               uint64_t m_numerator;
+               uint64_t m_denominator;
+               int sign;
+
+       public:
+               Rational64(int64_t numerator, int64_t denominator)
+               {
+                       if (numerator > 0)
+                       {
+                               sign = 1;
+                               m_numerator = (uint64_t)numerator;
+                       }
+                       else if (numerator < 0)
+                       {
+                               sign = -1;
+                               m_numerator = (uint64_t)-numerator;
+                       }
+                       else
+                       {
+                               sign = 0;
+                               m_numerator = 0;
+                       }
+                       if (denominator > 0)
+                       {
+                               m_denominator = (uint64_t)denominator;
+                       }
+                       else if (denominator < 0)
+                       {
+                               sign = -sign;
+                               m_denominator = (uint64_t)-denominator;
+                       }
+                       else
+                       {
+                               m_denominator = 0;
+                       }
+               }
+
+               bool isNegativeInfinity() const
+               {
+                       return (sign < 0) && (m_denominator == 0);
+               }
+
+               bool isNaN() const
+               {
+                       return (sign == 0) && (m_denominator == 0);
+               }
+
+               int compare(const Rational64& b) const;
+
+               btScalar toScalar() const
+               {
+                       return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar)m_numerator / m_denominator);
+               }
+       };
+
+       class Rational128
+       {
+       private:
+               Int128 numerator;
+               Int128 denominator;
+               int sign;
+               bool isInt64;
+
+       public:
+               Rational128(int64_t value)
+               {
+                       if (value > 0)
+                       {
+                               sign = 1;
+                               this->numerator = value;
+                       }
+                       else if (value < 0)
+                       {
+                               sign = -1;
+                               this->numerator = -value;
+                       }
+                       else
+                       {
+                               sign = 0;
+                               this->numerator = (uint64_t)0;
+                       }
+                       this->denominator = (uint64_t)1;
+                       isInt64 = true;
+               }
+
+               Rational128(const Int128& numerator, const Int128& denominator)
+               {
+                       sign = numerator.getSign();
+                       if (sign >= 0)
+                       {
+                               this->numerator = numerator;
+                       }
+                       else
+                       {
+                               this->numerator = -numerator;
+                       }
+                       int dsign = denominator.getSign();
+                       if (dsign >= 0)
+                       {
+                               this->denominator = denominator;
+                       }
+                       else
+                       {
+                               sign = -sign;
+                               this->denominator = -denominator;
+                       }
+                       isInt64 = false;
+               }
+
+               int compare(const Rational128& b) const;
+
+               int compare(int64_t b) const;
+
+               btScalar toScalar() const
+               {
+                       return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar());
+               }
+       };
+
+       class PointR128
+       {
+       public:
+               Int128 x;
+               Int128 y;
+               Int128 z;
+               Int128 denominator;
+
+               PointR128()
+               {
+               }
+
+               PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator) : x(x), y(y), z(z), denominator(denominator)
+               {
+               }
+
+               btScalar xvalue() const
+               {
+                       return x.toScalar() / denominator.toScalar();
+               }
+
+               btScalar yvalue() const
+               {
+                       return y.toScalar() / denominator.toScalar();
+               }
+
+               btScalar zvalue() const
+               {
+                       return z.toScalar() / denominator.toScalar();
+               }
+       };
+
+       class Edge;
+       class Face;
+
+       class Vertex
+       {
+       public:
+               Vertex* next;
+               Vertex* prev;
+               Edge* edges;
+               Face* firstNearbyFace;
+               Face* lastNearbyFace;
+               PointR128 point128;
+               Point32 point;
+               int copy;
+
+               Vertex() : next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
+               {
+               }
+
+#ifdef DEBUG_CONVEX_HULL
+               void print()
+               {
+                       printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
+               }
+
+               void printGraph();
+#endif
+
+               Point32 operator-(const Vertex& b) const
+               {
+                       return point - b.point;
+               }
+
+               Rational128 dot(const Point64& b) const
+               {
+                       return (point.index >= 0) ? Rational128(point.dot(b))
+                                                                         : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
+               }
+
+               btScalar xvalue() const
+               {
+                       return (point.index >= 0) ? btScalar(point.x) : point128.xvalue();
+               }
+
+               btScalar yvalue() const
+               {
+                       return (point.index >= 0) ? btScalar(point.y) : point128.yvalue();
+               }
+
+               btScalar zvalue() const
+               {
+                       return (point.index >= 0) ? btScalar(point.z) : point128.zvalue();
+               }
+
+               void receiveNearbyFaces(Vertex* src)
+               {
+                       if (lastNearbyFace)
+                       {
+                               lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
+                       }
+                       else
+                       {
+                               firstNearbyFace = src->firstNearbyFace;
+                       }
+                       if (src->lastNearbyFace)
+                       {
+                               lastNearbyFace = src->lastNearbyFace;
+                       }
+                       for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
+                       {
+                               btAssert(f->nearbyVertex == src);
+                               f->nearbyVertex = this;
+                       }
+                       src->firstNearbyFace = NULL;
+                       src->lastNearbyFace = NULL;
+               }
+       };
+
+       class Edge
+       {
+       public:
+               Edge* next;
+               Edge* prev;
+               Edge* reverse;
+               Vertex* target;
+               Face* face;
+               int copy;
+
+               ~Edge()
+               {
+                       next = NULL;
+                       prev = NULL;
+                       reverse = NULL;
+                       target = NULL;
+                       face = NULL;
+               }
+
+               void link(Edge* n)
+               {
+                       btAssert(reverse->target == n->reverse->target);
+                       next = n;
+                       n->prev = this;
+               }
+
+#ifdef DEBUG_CONVEX_HULL
+               void print()
+               {
+                       printf("E%p : %d -> %d,  n=%p p=%p   (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
+                                  reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
+               }
+#endif
+       };
+
+       class Face
+       {
+       public:
+               Face* next;
+               Vertex* nearbyVertex;
+               Face* nextWithSameNearbyVertex;
+               Point32 origin;
+               Point32 dir0;
+               Point32 dir1;
+
+               Face() : next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
+               {
+               }
+
+               void init(Vertex* a, Vertex* b, Vertex* c)
+               {
+                       nearbyVertex = a;
+                       origin = a->point;
+                       dir0 = *b - *a;
+                       dir1 = *c - *a;
+                       if (a->lastNearbyFace)
+                       {
+                               a->lastNearbyFace->nextWithSameNearbyVertex = this;
+                       }
+                       else
+                       {
+                               a->firstNearbyFace = this;
+                       }
+                       a->lastNearbyFace = this;
+               }
+
+               Point64 getNormal()
+               {
+                       return dir0.cross(dir1);
+               }
+       };
+
+       template <typename UWord, typename UHWord>
+       class DMul
+       {
+       private:
+               static uint32_t high(uint64_t value)
+               {
+                       return (uint32_t)(value >> 32);
+               }
+
+               static uint32_t low(uint64_t value)
+               {
+                       return (uint32_t)value;
+               }
+
+               static uint64_t mul(uint32_t a, uint32_t b)
+               {
+                       return (uint64_t)a * (uint64_t)b;
+               }
+
+               static void shlHalf(uint64_t& value)
+               {
+                       value <<= 32;
+               }
+
+               static uint64_t high(Int128 value)
+               {
+                       return value.high;
+               }
+
+               static uint64_t low(Int128 value)
+               {
+                       return value.low;
+               }
+
+               static Int128 mul(uint64_t a, uint64_t b)
+               {
+                       return Int128::mul(a, b);
+               }
+
+               static void shlHalf(Int128& value)
+               {
+                       value.high = value.low;
+                       value.low = 0;
+               }
+
+       public:
+               static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
+               {
+                       UWord p00 = mul(low(a), low(b));
+                       UWord p01 = mul(low(a), high(b));
+                       UWord p10 = mul(high(a), low(b));
+                       UWord p11 = mul(high(a), high(b));
+                       UWord p0110 = UWord(low(p01)) + UWord(low(p10));
+                       p11 += high(p01);
+                       p11 += high(p10);
+                       p11 += high(p0110);
+                       shlHalf(p0110);
+                       p00 += p0110;
+                       if (p00 < p0110)
+                       {
+                               ++p11;
+                       }
+                       resLow = p00;
+                       resHigh = p11;
+               }
+       };
+
+private:
+       class IntermediateHull
+       {
+       public:
+               Vertex* minXy;
+               Vertex* maxXy;
+               Vertex* minYx;
+               Vertex* maxYx;
+
+               IntermediateHull() : minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
+               {
+               }
+
+               void print();
+       };
+
+       enum Orientation
+       {
+               NONE,
+               CLOCKWISE,
+               COUNTER_CLOCKWISE
+       };
+
+       template <typename T>
+       class PoolArray
+       {
+       private:
+               T* array;
+               int size;
+
+       public:
+               PoolArray<T>* next;
+
+               PoolArray(int size) : size(size), next(NULL)
+               {
+                       array = (T*)btAlignedAlloc(sizeof(T) * size, 16);
+               }
+
+               ~PoolArray()
+               {
+                       btAlignedFree(array);
+               }
+
+               T* init()
+               {
+                       T* o = array;
+                       for (int i = 0; i < size; i++, o++)
+                       {
+                               o->next = (i + 1 < size) ? o + 1 : NULL;
+                       }
+                       return array;
+               }
+       };
+
+       template <typename T>
+       class Pool
+       {
+       private:
+               PoolArray<T>* arrays;
+               PoolArray<T>* nextArray;
+               T* freeObjects;
+               int arraySize;
+
+       public:
+               Pool() : arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
+               {
+               }
+
+               ~Pool()
+               {
+                       while (arrays)
+                       {
+                               PoolArray<T>* p = arrays;
+                               arrays = p->next;
+                               p->~PoolArray<T>();
+                               btAlignedFree(p);
+                       }
+               }
+
+               void reset()
+               {
+                       nextArray = arrays;
+                       freeObjects = NULL;
+               }
+
+               void setArraySize(int arraySize)
+               {
+                       this->arraySize = arraySize;
+               }
+
+               T* newObject()
+               {
+                       T* o = freeObjects;
+                       if (!o)
+                       {
+                               PoolArray<T>* p = nextArray;
+                               if (p)
+                               {
+                                       nextArray = p->next;
+                               }
+                               else
+                               {
+                                       p = new (btAlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
+                                       p->next = arrays;
+                                       arrays = p;
+                               }
+                               o = p->init();
+                       }
+                       freeObjects = o->next;
+                       return new (o) T();
+               };
+
+               void freeObject(T* object)
+               {
+                       object->~T();
+                       object->next = freeObjects;
+                       freeObjects = object;
+               }
+       };
+
+       btVector3 scaling;
+       btVector3 center;
+       Pool<Vertex> vertexPool;
+       Pool<Edge> edgePool;
+       Pool<Face> facePool;
+       btAlignedObjectArray<Vertex*> originalVertices;
+       int mergeStamp;
+       int minAxis;
+       int medAxis;
+       int maxAxis;
+       int usedEdgePairs;
+       int maxUsedEdgePairs;
+
+       static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
+       Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
+       void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
+
+       Edge* newEdgePair(Vertex* from, Vertex* to);
+
+       void removeEdgePair(Edge* edge)
+       {
+               Edge* n = edge->next;
+               Edge* r = edge->reverse;
+
+               btAssert(edge->target && r->target);
+
+               if (n != edge)
+               {
+                       n->prev = edge->prev;
+                       edge->prev->next = n;
+                       r->target->edges = n;
+               }
+               else
+               {
+                       r->target->edges = NULL;
+               }
+
+               n = r->next;
+
+               if (n != r)
+               {
+                       n->prev = r->prev;
+                       r->prev->next = n;
+                       edge->target->edges = n;
+               }
+               else
+               {
+                       edge->target->edges = NULL;
+               }
+
+               edgePool.freeObject(edge);
+               edgePool.freeObject(r);
+               usedEdgePairs--;
+       }
+
+       void computeInternal(int start, int end, IntermediateHull& result);
+
+       bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
+
+       void merge(IntermediateHull& h0, IntermediateHull& h1);
+
+       btVector3 toBtVector(const Point32& v);
+
+       btVector3 getBtNormal(Face* face);
+
+       bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack);
+
+public:
+       Vertex* vertexList;
+
+       void compute(const void* coords, bool doubleCoords, int stride, int count);
+
+       btVector3 getCoordinates(const Vertex* v);
+
+       btScalar shrink(btScalar amount, btScalar clampAmount);
+};
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const
+{
+       bool negative = (int64_t)high < 0;
+       Int128 a = negative ? -*this : *this;
+       if (b < 0)
+       {
+               negative = !negative;
+               b = -b;
+       }
+       Int128 result = mul(a.low, (uint64_t)b);
+       result.high += a.high * (uint64_t)b;
+       return negative ? -result : result;
+}
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b)
+{
+       Int128 result;
+
+#ifdef USE_X86_64_ASM
+       __asm__("imulq %[b]"
+                       : "=a"(result.low), "=d"(result.high)
+                       : "0"(a), [b] "r"(b)
+                       : "cc");
+       return result;
+
+#else
+       bool negative = a < 0;
+       if (negative)
+       {
+               a = -a;
+       }
+       if (b < 0)
+       {
+               negative = !negative;
+               b = -b;
+       }
+       DMul<uint64_t, uint32_t>::mul((uint64_t)a, (uint64_t)b, result.low, result.high);
+       return negative ? -result : result;
+#endif
+}
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint64_t b)
+{
+       Int128 result;
+
+#ifdef USE_X86_64_ASM
+       __asm__("mulq %[b]"
+                       : "=a"(result.low), "=d"(result.high)
+                       : "0"(a), [b] "r"(b)
+                       : "cc");
+
+#else
+       DMul<uint64_t, uint32_t>::mul(a, b, result.low, result.high);
+#endif
+
+       return result;
+}
+
+int btConvexHullInternal::Rational64::compare(const Rational64& b) const
+{
+       if (sign != b.sign)
+       {
+               return sign - b.sign;
+       }
+       else if (sign == 0)
+       {
+               return 0;
+       }
+
+       //      return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
+
+#ifdef USE_X86_64_ASM
+
+       int result;
+       int64_t tmp;
+       int64_t dummy;
+       __asm__(
+               "mulq %[bn]\n\t"
+               "movq %%rax, %[tmp]\n\t"
+               "movq %%rdx, %%rbx\n\t"
+               "movq %[tn], %%rax\n\t"
+               "mulq %[bd]\n\t"
+               "subq %[tmp], %%rax\n\t"
+               "sbbq %%rbx, %%rdx\n\t"  // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
+               "setnsb %%bh\n\t"        // bh=1 if difference is non-negative, bh=0 otherwise
+               "orq %%rdx, %%rax\n\t"
+               "setnzb %%bl\n\t"      // bl=1 if difference if non-zero, bl=0 if it is zero
+               "decb %%bh\n\t"        // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
+               "shll $16, %%ebx\n\t"  // ebx has same sign as difference
+               : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
+               : "a"(m_denominator), [bn] "g"(b.m_numerator), [tn] "g"(m_numerator), [bd] "g"(b.m_denominator)
+               : "%rdx", "cc");
+       return result ? result ^ sign  // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
+                                                                  // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
+                                 : 0;
+
+#else
+
+       return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator));
+
+#endif
+}
+
+int btConvexHullInternal::Rational128::compare(const Rational128& b) const
+{
+       if (sign != b.sign)
+       {
+               return sign - b.sign;
+       }
+       else if (sign == 0)
+       {
+               return 0;
+       }
+       if (isInt64)
+       {
+               return -b.compare(sign * (int64_t)numerator.low);
+       }
+
+       Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
+       DMul<Int128, uint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh);
+       DMul<Int128, uint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh);
+
+       int cmp = nbdHigh.ucmp(dbnHigh);
+       if (cmp)
+       {
+               return cmp * sign;
+       }
+       return nbdLow.ucmp(dbnLow) * sign;
+}
+
+int btConvexHullInternal::Rational128::compare(int64_t b) const
+{
+       if (isInt64)
+       {
+               int64_t a = sign * (int64_t)numerator.low;
+               return (a > b) ? 1 : (a < b) ? -1 : 0;
+       }
+       if (b > 0)
+       {
+               if (sign <= 0)
+               {
+                       return -1;
+               }
+       }
+       else if (b < 0)
+       {
+               if (sign >= 0)
+               {
+                       return 1;
+               }
+               b = -b;
+       }
+       else
+       {
+               return sign;
+       }
+
+       return numerator.ucmp(denominator * b) * sign;
+}
+
+btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
+{
+       btAssert(from && to);
+       Edge* e = edgePool.newObject();
+       Edge* r = edgePool.newObject();
+       e->reverse = r;
+       r->reverse = e;
+       e->copy = mergeStamp;
+       r->copy = mergeStamp;
+       e->target = to;
+       r->target = from;
+       e->face = NULL;
+       r->face = NULL;
+       usedEdgePairs++;
+       if (usedEdgePairs > maxUsedEdgePairs)
+       {
+               maxUsedEdgePairs = usedEdgePairs;
+       }
+       return e;
+}
+
+bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1)
+{
+       Vertex* v0 = h0.maxYx;
+       Vertex* v1 = h1.minYx;
+       if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y))
+       {
+               btAssert(v0->point.z < v1->point.z);
+               Vertex* v1p = v1->prev;
+               if (v1p == v1)
+               {
+                       c0 = v0;
+                       if (v1->edges)
+                       {
+                               btAssert(v1->edges->next == v1->edges);
+                               v1 = v1->edges->target;
+                               btAssert(v1->edges->next == v1->edges);
+                       }
+                       c1 = v1;
+                       return false;
+               }
+               Vertex* v1n = v1->next;
+               v1p->next = v1n;
+               v1n->prev = v1p;
+               if (v1 == h1.minXy)
+               {
+                       if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y)))
+                       {
+                               h1.minXy = v1n;
+                       }
+                       else
+                       {
+                               h1.minXy = v1p;
+                       }
+               }
+               if (v1 == h1.maxXy)
+               {
+                       if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y)))
+                       {
+                               h1.maxXy = v1n;
+                       }
+                       else
+                       {
+                               h1.maxXy = v1p;
+                       }
+               }
+       }
+
+       v0 = h0.maxXy;
+       v1 = h1.maxXy;
+       Vertex* v00 = NULL;
+       Vertex* v10 = NULL;
+       int32_t sign = 1;
+
+       for (int side = 0; side <= 1; side++)
+       {
+               int32_t dx = (v1->point.x - v0->point.x) * sign;
+               if (dx > 0)
+               {
+                       while (true)
+                       {
+                               int32_t dy = v1->point.y - v0->point.y;
+
+                               Vertex* w0 = side ? v0->next : v0->prev;
+                               if (w0 != v0)
+                               {
+                                       int32_t dx0 = (w0->point.x - v0->point.x) * sign;
+                                       int32_t dy0 = w0->point.y - v0->point.y;
+                                       if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0))))
+                                       {
+                                               v0 = w0;
+                                               dx = (v1->point.x - v0->point.x) * sign;
+                                               continue;
+                                       }
+                               }
+
+                               Vertex* w1 = side ? v1->next : v1->prev;
+                               if (w1 != v1)
+                               {
+                                       int32_t dx1 = (w1->point.x - v1->point.x) * sign;
+                                       int32_t dy1 = w1->point.y - v1->point.y;
+                                       int32_t dxn = (w1->point.x - v0->point.x) * sign;
+                                       if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1))))
+                                       {
+                                               v1 = w1;
+                                               dx = dxn;
+                                               continue;
+                                       }
+                               }
+
+                               break;
+                       }
+               }
+               else if (dx < 0)
+               {
+                       while (true)
+                       {
+                               int32_t dy = v1->point.y - v0->point.y;
+
+                               Vertex* w1 = side ? v1->prev : v1->next;
+                               if (w1 != v1)
+                               {
+                                       int32_t dx1 = (w1->point.x - v1->point.x) * sign;
+                                       int32_t dy1 = w1->point.y - v1->point.y;
+                                       if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1))))
+                                       {
+                                               v1 = w1;
+                                               dx = (v1->point.x - v0->point.x) * sign;
+                                               continue;
+                                       }
+                               }
+
+                               Vertex* w0 = side ? v0->prev : v0->next;
+                               if (w0 != v0)
+                               {
+                                       int32_t dx0 = (w0->point.x - v0->point.x) * sign;
+                                       int32_t dy0 = w0->point.y - v0->point.y;
+                                       int32_t dxn = (v1->point.x - w0->point.x) * sign;
+                                       if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0))))
+                                       {
+                                               v0 = w0;
+                                               dx = dxn;
+                                               continue;
+                                       }
+                               }
+
+                               break;
+                       }
+               }
+               else
+               {
+                       int32_t x = v0->point.x;
+                       int32_t y0 = v0->point.y;
+                       Vertex* w0 = v0;
+                       Vertex* t;
+                       while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0))
+                       {
+                               w0 = t;
+                               y0 = t->point.y;
+                       }
+                       v0 = w0;
+
+                       int32_t y1 = v1->point.y;
+                       Vertex* w1 = v1;
+                       while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1))
+                       {
+                               w1 = t;
+                               y1 = t->point.y;
+                       }
+                       v1 = w1;
+               }
+
+               if (side == 0)
+               {
+                       v00 = v0;
+                       v10 = v1;
+
+                       v0 = h0.minXy;
+                       v1 = h1.minXy;
+                       sign = -1;
+               }
+       }
+
+       v0->prev = v1;
+       v1->next = v0;
+
+       v00->next = v10;
+       v10->prev = v00;
+
+       if (h1.minXy->point.x < h0.minXy->point.x)
+       {
+               h0.minXy = h1.minXy;
+       }
+       if (h1.maxXy->point.x >= h0.maxXy->point.x)
+       {
+               h0.maxXy = h1.maxXy;
+       }
+
+       h0.maxYx = h1.maxYx;
+
+       c0 = v00;
+       c1 = v10;
+
+       return true;
+}
+
+void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result)
+{
+       int n = end - start;
+       switch (n)
+       {
+               case 0:
+                       result.minXy = NULL;
+                       result.maxXy = NULL;
+                       result.minYx = NULL;
+                       result.maxYx = NULL;
+                       return;
+               case 2:
+               {
+                       Vertex* v = originalVertices[start];
+                       Vertex* w = v + 1;
+                       if (v->point != w->point)
+                       {
+                               int32_t dx = v->point.x - w->point.x;
+                               int32_t dy = v->point.y - w->point.y;
+
+                               if ((dx == 0) && (dy == 0))
+                               {
+                                       if (v->point.z > w->point.z)
+                                       {
+                                               Vertex* t = w;
+                                               w = v;
+                                               v = t;
+                                       }
+                                       btAssert(v->point.z < w->point.z);
+                                       v->next = v;
+                                       v->prev = v;
+                                       result.minXy = v;
+                                       result.maxXy = v;
+                                       result.minYx = v;
+                                       result.maxYx = v;
+                               }
+                               else
+                               {
+                                       v->next = w;
+                                       v->prev = w;
+                                       w->next = v;
+                                       w->prev = v;
+
+                                       if ((dx < 0) || ((dx == 0) && (dy < 0)))
+                                       {
+                                               result.minXy = v;
+                                               result.maxXy = w;
+                                       }
+                                       else
+                                       {
+                                               result.minXy = w;
+                                               result.maxXy = v;
+                                       }
+
+                                       if ((dy < 0) || ((dy == 0) && (dx < 0)))
+                                       {
+                                               result.minYx = v;
+                                               result.maxYx = w;
+                                       }
+                                       else
+                                       {
+                                               result.minYx = w;
+                                               result.maxYx = v;
+                                       }
+                               }
+
+                               Edge* e = newEdgePair(v, w);
+                               e->link(e);
+                               v->edges = e;
+
+                               e = e->reverse;
+                               e->link(e);
+                               w->edges = e;
+
+                               return;
+                       }
+                       {
+                               Vertex* v = originalVertices[start];
+                               v->edges = NULL;
+                               v->next = v;
+                               v->prev = v;
+
+                               result.minXy = v;
+                               result.maxXy = v;
+                               result.minYx = v;
+                               result.maxYx = v;
+                       }
+
+                       return;
+               }
+
+               case 1:
+               {
+                       Vertex* v = originalVertices[start];
+                       v->edges = NULL;
+                       v->next = v;
+                       v->prev = v;
+
+                       result.minXy = v;
+                       result.maxXy = v;
+                       result.minYx = v;
+                       result.maxYx = v;
+
+                       return;
+               }
+       }
+
+       int split0 = start + n / 2;
+       Point32 p = originalVertices[split0 - 1]->point;
+       int split1 = split0;
+       while ((split1 < end) && (originalVertices[split1]->point == p))
+       {
+               split1++;
+       }
+       computeInternal(start, split0, result);
+       IntermediateHull hull1;
+       computeInternal(split1, end, hull1);
+#ifdef DEBUG_CONVEX_HULL
+       printf("\n\nMerge\n");
+       result.print();
+       hull1.print();
+#endif
+       merge(result, hull1);
+#ifdef DEBUG_CONVEX_HULL
+       printf("\n  Result\n");
+       result.print();
+#endif
+}
+
+#ifdef DEBUG_CONVEX_HULL
+void btConvexHullInternal::IntermediateHull::print()
+{
+       printf("    Hull\n");
+       for (Vertex* v = minXy; v;)
+       {
+               printf("      ");
+               v->print();
+               if (v == maxXy)
+               {
+                       printf(" maxXy");
+               }
+               if (v == minYx)
+               {
+                       printf(" minYx");
+               }
+               if (v == maxYx)
+               {
+                       printf(" maxYx");
+               }
+               if (v->next->prev != v)
+               {
+                       printf(" Inconsistency");
+               }
+               printf("\n");
+               v = v->next;
+               if (v == minXy)
+               {
+                       break;
+               }
+       }
+       if (minXy)
+       {
+               minXy->copy = (minXy->copy == -1) ? -2 : -1;
+               minXy->printGraph();
+       }
+}
+
+void btConvexHullInternal::Vertex::printGraph()
+{
+       print();
+       printf("\nEdges\n");
+       Edge* e = edges;
+       if (e)
+       {
+               do
+               {
+                       e->print();
+                       printf("\n");
+                       e = e->next;
+               } while (e != edges);
+               do
+               {
+                       Vertex* v = e->target;
+                       if (v->copy != copy)
+                       {
+                               v->copy = copy;
+                               v->printGraph();
+                       }
+                       e = e->next;
+               } while (e != edges);
+       }
+}
+#endif
+
+btConvexHullInternal::Orientation btConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t)
+{
+       btAssert(prev->reverse->target == next->reverse->target);
+       if (prev->next == next)
+       {
+               if (prev->prev == next)
+               {
+                       Point64 n = t.cross(s);
+                       Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target);
+                       btAssert(!m.isZero());
+                       int64_t dot = n.dot(m);
+                       btAssert(dot != 0);
+                       return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
+               }
+               return COUNTER_CLOCKWISE;
+       }
+       else if (prev->prev == next)
+       {
+               return CLOCKWISE;
+       }
+       else
+       {
+               return NONE;
+       }
+}
+
+btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot)
+{
+       Edge* minEdge = NULL;
+
+#ifdef DEBUG_CONVEX_HULL
+       printf("find max edge for %d\n", start->point.index);
+#endif
+       Edge* e = start->edges;
+       if (e)
+       {
+               do
+               {
+                       if (e->copy > mergeStamp)
+                       {
+                               Point32 t = *e->target - *start;
+                               Rational64 cot(t.dot(sxrxs), t.dot(rxs));
+#ifdef DEBUG_CONVEX_HULL
+                               printf("      Angle is %f (%d) for ", (float)btAtan(cot.toScalar()), (int)cot.isNaN());
+                               e->print();
+#endif
+                               if (cot.isNaN())
+                               {
+                                       btAssert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0));
+                               }
+                               else
+                               {
+                                       int cmp;
+                                       if (minEdge == NULL)
+                                       {
+                                               minCot = cot;
+                                               minEdge = e;
+                                       }
+                                       else if ((cmp = cot.compare(minCot)) < 0)
+                                       {
+                                               minCot = cot;
+                                               minEdge = e;
+                                       }
+                                       else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE)))
+                                       {
+                                               minEdge = e;
+                                       }
+                               }
+#ifdef DEBUG_CONVEX_HULL
+                               printf("\n");
+#endif
+                       }
+                       e = e->next;
+               } while (e != start->edges);
+       }
+       return minEdge;
+}
+
+void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1)
+{
+       Edge* start0 = e0;
+       Edge* start1 = e1;
+       Point32 et0 = start0 ? start0->target->point : c0->point;
+       Point32 et1 = start1 ? start1->target->point : c1->point;
+       Point32 s = c1->point - c0->point;
+       Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s);
+       int64_t dist = c0->point.dot(normal);
+       btAssert(!start1 || (start1->target->point.dot(normal) == dist));
+       Point64 perp = s.cross(normal);
+       btAssert(!perp.isZero());
+
+#ifdef DEBUG_CONVEX_HULL
+       printf("   Advancing %d %d  (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
+#endif
+
+       int64_t maxDot0 = et0.dot(perp);
+       if (e0)
+       {
+               while (e0->target != stop0)
+               {
+                       Edge* e = e0->reverse->prev;
+                       if (e->target->point.dot(normal) < dist)
+                       {
+                               break;
+                       }
+                       btAssert(e->target->point.dot(normal) == dist);
+                       if (e->copy == mergeStamp)
+                       {
+                               break;
+                       }
+                       int64_t dot = e->target->point.dot(perp);
+                       if (dot <= maxDot0)
+                       {
+                               break;
+                       }
+                       maxDot0 = dot;
+                       e0 = e;
+                       et0 = e->target->point;
+               }
+       }
+
+       int64_t maxDot1 = et1.dot(perp);
+       if (e1)
+       {
+               while (e1->target != stop1)
+               {
+                       Edge* e = e1->reverse->next;
+                       if (e->target->point.dot(normal) < dist)
+                       {
+                               break;
+                       }
+                       btAssert(e->target->point.dot(normal) == dist);
+                       if (e->copy == mergeStamp)
+                       {
+                               break;
+                       }
+                       int64_t dot = e->target->point.dot(perp);
+                       if (dot <= maxDot1)
+                       {
+                               break;
+                       }
+                       maxDot1 = dot;
+                       e1 = e;
+                       et1 = e->target->point;
+               }
+       }
+
+#ifdef DEBUG_CONVEX_HULL
+       printf("   Starting at %d %d\n", et0.index, et1.index);
+#endif
+
+       int64_t dx = maxDot1 - maxDot0;
+       if (dx > 0)
+       {
+               while (true)
+               {
+                       int64_t dy = (et1 - et0).dot(s);
+
+                       if (e0 && (e0->target != stop0))
+                       {
+                               Edge* f0 = e0->next->reverse;
+                               if (f0->copy > mergeStamp)
+                               {
+                                       int64_t dx0 = (f0->target->point - et0).dot(perp);
+                                       int64_t dy0 = (f0->target->point - et0).dot(s);
+                                       if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0)))
+                                       {
+                                               et0 = f0->target->point;
+                                               dx = (et1 - et0).dot(perp);
+                                               e0 = (e0 == start0) ? NULL : f0;
+                                               continue;
+                                       }
+                               }
+                       }
+
+                       if (e1 && (e1->target != stop1))
+                       {
+                               Edge* f1 = e1->reverse->next;
+                               if (f1->copy > mergeStamp)
+                               {
+                                       Point32 d1 = f1->target->point - et1;
+                                       if (d1.dot(normal) == 0)
+                                       {
+                                               int64_t dx1 = d1.dot(perp);
+                                               int64_t dy1 = d1.dot(s);
+                                               int64_t dxn = (f1->target->point - et0).dot(perp);
+                                               if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0))))
+                                               {
+                                                       e1 = f1;
+                                                       et1 = e1->target->point;
+                                                       dx = dxn;
+                                                       continue;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               btAssert((e1 == start1) && (d1.dot(normal) < 0));
+                                       }
+                               }
+                       }
+
+                       break;
+               }
+       }
+       else if (dx < 0)
+       {
+               while (true)
+               {
+                       int64_t dy = (et1 - et0).dot(s);
+
+                       if (e1 && (e1->target != stop1))
+                       {
+                               Edge* f1 = e1->prev->reverse;
+                               if (f1->copy > mergeStamp)
+                               {
+                                       int64_t dx1 = (f1->target->point - et1).dot(perp);
+                                       int64_t dy1 = (f1->target->point - et1).dot(s);
+                                       if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0)))
+                                       {
+                                               et1 = f1->target->point;
+                                               dx = (et1 - et0).dot(perp);
+                                               e1 = (e1 == start1) ? NULL : f1;
+                                               continue;
+                                       }
+                               }
+                       }
+
+                       if (e0 && (e0->target != stop0))
+                       {
+                               Edge* f0 = e0->reverse->prev;
+                               if (f0->copy > mergeStamp)
+                               {
+                                       Point32 d0 = f0->target->point - et0;
+                                       if (d0.dot(normal) == 0)
+                                       {
+                                               int64_t dx0 = d0.dot(perp);
+                                               int64_t dy0 = d0.dot(s);
+                                               int64_t dxn = (et1 - f0->target->point).dot(perp);
+                                               if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0))))
+                                               {
+                                                       e0 = f0;
+                                                       et0 = e0->target->point;
+                                                       dx = dxn;
+                                                       continue;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               btAssert((e0 == start0) && (d0.dot(normal) < 0));
+                                       }
+                               }
+                       }
+
+                       break;
+               }
+       }
+#ifdef DEBUG_CONVEX_HULL
+       printf("   Advanced edges to %d %d\n", et0.index, et1.index);
+#endif
+}
+
+void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
+{
+       if (!h1.maxXy)
+       {
+               return;
+       }
+       if (!h0.maxXy)
+       {
+               h0 = h1;
+               return;
+       }
+
+       mergeStamp--;
+
+       Vertex* c0 = NULL;
+       Edge* toPrev0 = NULL;
+       Edge* firstNew0 = NULL;
+       Edge* pendingHead0 = NULL;
+       Edge* pendingTail0 = NULL;
+       Vertex* c1 = NULL;
+       Edge* toPrev1 = NULL;
+       Edge* firstNew1 = NULL;
+       Edge* pendingHead1 = NULL;
+       Edge* pendingTail1 = NULL;
+       Point32 prevPoint;
+
+       if (mergeProjection(h0, h1, c0, c1))
+       {
+               Point32 s = *c1 - *c0;
+               Point64 normal = Point32(0, 0, -1).cross(s);
+               Point64 t = s.cross(normal);
+               btAssert(!t.isZero());
+
+               Edge* e = c0->edges;
+               Edge* start0 = NULL;
+               if (e)
+               {
+                       do
+                       {
+                               int64_t dot = (*e->target - *c0).dot(normal);
+                               btAssert(dot <= 0);
+                               if ((dot == 0) && ((*e->target - *c0).dot(t) > 0))
+                               {
+                                       if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE))
+                                       {
+                                               start0 = e;
+                                       }
+                               }
+                               e = e->next;
+                       } while (e != c0->edges);
+               }
+
+               e = c1->edges;
+               Edge* start1 = NULL;
+               if (e)
+               {
+                       do
+                       {
+                               int64_t dot = (*e->target - *c1).dot(normal);
+                               btAssert(dot <= 0);
+                               if ((dot == 0) && ((*e->target - *c1).dot(t) > 0))
+                               {
+                                       if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE))
+                                       {
+                                               start1 = e;
+                                       }
+                               }
+                               e = e->next;
+                       } while (e != c1->edges);
+               }
+
+               if (start0 || start1)
+               {
+                       findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL);
+                       if (start0)
+                       {
+                               c0 = start0->target;
+                       }
+                       if (start1)
+                       {
+                               c1 = start1->target;
+                       }
+               }
+
+               prevPoint = c1->point;
+               prevPoint.z++;
+       }
+       else
+       {
+               prevPoint = c1->point;
+               prevPoint.x++;
+       }
+
+       Vertex* first0 = c0;
+       Vertex* first1 = c1;
+       bool firstRun = true;
+
+       while (true)
+       {
+               Point32 s = *c1 - *c0;
+               Point32 r = prevPoint - c0->point;
+               Point64 rxs = r.cross(s);
+               Point64 sxrxs = s.cross(rxs);
+
+#ifdef DEBUG_CONVEX_HULL
+               printf("\n  Checking %d %d\n", c0->point.index, c1->point.index);
+#endif
+               Rational64 minCot0(0, 0);
+               Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0);
+               Rational64 minCot1(0, 0);
+               Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1);
+               if (!min0 && !min1)
+               {
+                       Edge* e = newEdgePair(c0, c1);
+                       e->link(e);
+                       c0->edges = e;
+
+                       e = e->reverse;
+                       e->link(e);
+                       c1->edges = e;
+                       return;
+               }
+               else
+               {
+                       int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1);
+#ifdef DEBUG_CONVEX_HULL
+                       printf("    -> Result %d\n", cmp);
+#endif
+                       if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity()))
+                       {
+                               Edge* e = newEdgePair(c0, c1);
+                               if (pendingTail0)
+                               {
+                                       pendingTail0->prev = e;
+                               }
+                               else
+                               {
+                                       pendingHead0 = e;
+                               }
+                               e->next = pendingTail0;
+                               pendingTail0 = e;
+
+                               e = e->reverse;
+                               if (pendingTail1)
+                               {
+                                       pendingTail1->next = e;
+                               }
+                               else
+                               {
+                                       pendingHead1 = e;
+                               }
+                               e->prev = pendingTail1;
+                               pendingTail1 = e;
+                       }
+
+                       Edge* e0 = min0;
+                       Edge* e1 = min1;
+
+#ifdef DEBUG_CONVEX_HULL
+                       printf("   Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
+#endif
+
+                       if (cmp == 0)
+                       {
+                               findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL);
+                       }
+
+                       if ((cmp >= 0) && e1)
+                       {
+                               if (toPrev1)
+                               {
+                                       for (Edge *e = toPrev1->next, *n = NULL; e != min1; e = n)
+                                       {
+                                               n = e->next;
+                                               removeEdgePair(e);
+                                       }
+                               }
+
+                               if (pendingTail1)
+                               {
+                                       if (toPrev1)
+                                       {
+                                               toPrev1->link(pendingHead1);
+                                       }
+                                       else
+                                       {
+                                               min1->prev->link(pendingHead1);
+                                               firstNew1 = pendingHead1;
+                                       }
+                                       pendingTail1->link(min1);
+                                       pendingHead1 = NULL;
+                                       pendingTail1 = NULL;
+                               }
+                               else if (!toPrev1)
+                               {
+                                       firstNew1 = min1;
+                               }
+
+                               prevPoint = c1->point;
+                               c1 = e1->target;
+                               toPrev1 = e1->reverse;
+                       }
+
+                       if ((cmp <= 0) && e0)
+                       {
+                               if (toPrev0)
+                               {
+                                       for (Edge *e = toPrev0->prev, *n = NULL; e != min0; e = n)
+                                       {
+                                               n = e->prev;
+                                               removeEdgePair(e);
+                                       }
+                               }
+
+                               if (pendingTail0)
+                               {
+                                       if (toPrev0)
+                                       {
+                                               pendingHead0->link(toPrev0);
+                                       }
+                                       else
+                                       {
+                                               pendingHead0->link(min0->next);
+                                               firstNew0 = pendingHead0;
+                                       }
+                                       min0->link(pendingTail0);
+                                       pendingHead0 = NULL;
+                                       pendingTail0 = NULL;
+                               }
+                               else if (!toPrev0)
+                               {
+                                       firstNew0 = min0;
+                               }
+
+                               prevPoint = c0->point;
+                               c0 = e0->target;
+                               toPrev0 = e0->reverse;
+                       }
+               }
+
+               if ((c0 == first0) && (c1 == first1))
+               {
+                       if (toPrev0 == NULL)
+                       {
+                               pendingHead0->link(pendingTail0);
+                               c0->edges = pendingTail0;
+                       }
+                       else
+                       {
+                               for (Edge *e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
+                               {
+                                       n = e->prev;
+                                       removeEdgePair(e);
+                               }
+                               if (pendingTail0)
+                               {
+                                       pendingHead0->link(toPrev0);
+                                       firstNew0->link(pendingTail0);
+                               }
+                       }
+
+                       if (toPrev1 == NULL)
+                       {
+                               pendingTail1->link(pendingHead1);
+                               c1->edges = pendingTail1;
+                       }
+                       else
+                       {
+                               for (Edge *e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
+                               {
+                                       n = e->next;
+                                       removeEdgePair(e);
+                               }
+                               if (pendingTail1)
+                               {
+                                       toPrev1->link(pendingHead1);
+                                       pendingTail1->link(firstNew1);
+                               }
+                       }
+
+                       return;
+               }
+
+               firstRun = false;
+       }
+}
+
+class pointCmp
+{
+public:
+       bool operator()(const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q) const
+       {
+               return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
+       }
+};
+
+void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
+{
+       btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30));
+       const char* ptr = (const char*)coords;
+       if (doubleCoords)
+       {
+               for (int i = 0; i < count; i++)
+               {
+                       const double* v = (const double*)ptr;
+                       btVector3 p((btScalar)v[0], (btScalar)v[1], (btScalar)v[2]);
+                       ptr += stride;
+                       min.setMin(p);
+                       max.setMax(p);
+               }
+       }
+       else
+       {
+               for (int i = 0; i < count; i++)
+               {
+                       const float* v = (const float*)ptr;
+                       btVector3 p(v[0], v[1], v[2]);
+                       ptr += stride;
+                       min.setMin(p);
+                       max.setMax(p);
+               }
+       }
+
+       btVector3 s = max - min;
+       maxAxis = s.maxAxis();
+       minAxis = s.minAxis();
+       if (minAxis == maxAxis)
+       {
+               minAxis = (maxAxis + 1) % 3;
+       }
+       medAxis = 3 - maxAxis - minAxis;
+
+       s /= btScalar(10216);
+       if (((medAxis + 1) % 3) != maxAxis)
+       {
+               s *= -1;
+       }
+       scaling = s;
+
+       if (s[0] != 0)
+       {
+               s[0] = btScalar(1) / s[0];
+       }
+       if (s[1] != 0)
+       {
+               s[1] = btScalar(1) / s[1];
+       }
+       if (s[2] != 0)
+       {
+               s[2] = btScalar(1) / s[2];
+       }
+
+       center = (min + max) * btScalar(0.5);
+
+       btAlignedObjectArray<Point32> points;
+       points.resize(count);
+       ptr = (const char*)coords;
+       if (doubleCoords)
+       {
+               for (int i = 0; i < count; i++)
+               {
+                       const double* v = (const double*)ptr;
+                       btVector3 p((btScalar)v[0], (btScalar)v[1], (btScalar)v[2]);
+                       ptr += stride;
+                       p = (p - center) * s;
+                       points[i].x = (int32_t)p[medAxis];
+                       points[i].y = (int32_t)p[maxAxis];
+                       points[i].z = (int32_t)p[minAxis];
+                       points[i].index = i;
+               }
+       }
+       else
+       {
+               for (int i = 0; i < count; i++)
+               {
+                       const float* v = (const float*)ptr;
+                       btVector3 p(v[0], v[1], v[2]);
+                       ptr += stride;
+                       p = (p - center) * s;
+                       points[i].x = (int32_t)p[medAxis];
+                       points[i].y = (int32_t)p[maxAxis];
+                       points[i].z = (int32_t)p[minAxis];
+                       points[i].index = i;
+               }
+       }
+       points.quickSort(pointCmp());
+
+       vertexPool.reset();
+       vertexPool.setArraySize(count);
+       originalVertices.resize(count);
+       for (int i = 0; i < count; i++)
+       {
+               Vertex* v = vertexPool.newObject();
+               v->edges = NULL;
+               v->point = points[i];
+               v->copy = -1;
+               originalVertices[i] = v;
+       }
+
+       points.clear();
+
+       edgePool.reset();
+       edgePool.setArraySize(6 * count);
+
+       usedEdgePairs = 0;
+       maxUsedEdgePairs = 0;
+
+       mergeStamp = -3;
+
+       IntermediateHull hull;
+       computeInternal(0, count, hull);
+       vertexList = hull.minXy;
+#ifdef DEBUG_CONVEX_HULL
+       printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count);
+#endif
+}
+
+btVector3 btConvexHullInternal::toBtVector(const Point32& v)
+{
+       btVector3 p;
+       p[medAxis] = btScalar(v.x);
+       p[maxAxis] = btScalar(v.y);
+       p[minAxis] = btScalar(v.z);
+       return p * scaling;
+}
+
+btVector3 btConvexHullInternal::getBtNormal(Face* face)
+{
+       return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized();
+}
+
+btVector3 btConvexHullInternal::getCoordinates(const Vertex* v)
+{
+       btVector3 p;
+       p[medAxis] = v->xvalue();
+       p[maxAxis] = v->yvalue();
+       p[minAxis] = v->zvalue();
+       return p * scaling + center;
+}
+
+btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount)
+{
+       if (!vertexList)
+       {
+               return 0;
+       }
+       int stamp = --mergeStamp;
+       btAlignedObjectArray<Vertex*> stack;
+       vertexList->copy = stamp;
+       stack.push_back(vertexList);
+       btAlignedObjectArray<Face*> faces;
+
+       Point32 ref = vertexList->point;
+       Int128 hullCenterX(0, 0);
+       Int128 hullCenterY(0, 0);
+       Int128 hullCenterZ(0, 0);
+       Int128 volume(0, 0);
+
+       while (stack.size() > 0)
+       {
+               Vertex* v = stack[stack.size() - 1];
+               stack.pop_back();
+               Edge* e = v->edges;
+               if (e)
+               {
+                       do
+                       {
+                               if (e->target->copy != stamp)
+                               {
+                                       e->target->copy = stamp;
+                                       stack.push_back(e->target);
+                               }
+                               if (e->copy != stamp)
+                               {
+                                       Face* face = facePool.newObject();
+                                       face->init(e->target, e->reverse->prev->target, v);
+                                       faces.push_back(face);
+                                       Edge* f = e;
+
+                                       Vertex* a = NULL;
+                                       Vertex* b = NULL;
+                                       do
+                                       {
+                                               if (a && b)
+                                               {
+                                                       int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
+                                                       btAssert(vol >= 0);
+                                                       Point32 c = v->point + a->point + b->point + ref;
+                                                       hullCenterX += vol * c.x;
+                                                       hullCenterY += vol * c.y;
+                                                       hullCenterZ += vol * c.z;
+                                                       volume += vol;
+                                               }
+
+                                               btAssert(f->copy != stamp);
+                                               f->copy = stamp;
+                                               f->face = face;
+
+                                               a = b;
+                                               b = f->target;
+
+                                               f = f->reverse->prev;
+                                       } while (f != e);
+                               }
+                               e = e->next;
+                       } while (e != v->edges);
+               }
+       }
+
+       if (volume.getSign() <= 0)
+       {
+               return 0;
+       }
+
+       btVector3 hullCenter;
+       hullCenter[medAxis] = hullCenterX.toScalar();
+       hullCenter[maxAxis] = hullCenterY.toScalar();
+       hullCenter[minAxis] = hullCenterZ.toScalar();
+       hullCenter /= 4 * volume.toScalar();
+       hullCenter *= scaling;
+
+       int faceCount = faces.size();
+
+       if (clampAmount > 0)
+       {
+               btScalar minDist = SIMD_INFINITY;
+               for (int i = 0; i < faceCount; i++)
+               {
+                       btVector3 normal = getBtNormal(faces[i]);
+                       btScalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter);
+                       if (dist < minDist)
+                       {
+                               minDist = dist;
+                       }
+               }
+
+               if (minDist <= 0)
+               {
+                       return 0;
+               }
+
+               amount = btMin(amount, minDist * clampAmount);
+       }
+
+       unsigned int seed = 243703;
+       for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223)
+       {
+               btSwap(faces[i], faces[seed % faceCount]);
+       }
+
+       for (int i = 0; i < faceCount; i++)
+       {
+               if (!shiftFace(faces[i], amount, stack))
+               {
+                       return -amount;
+               }
+       }
+
+       return amount;
+}
+
+bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack)
+{
+       btVector3 origShift = getBtNormal(face) * -amount;
+       if (scaling[0] != 0)
+       {
+               origShift[0] /= scaling[0];
+       }
+       if (scaling[1] != 0)
+       {
+               origShift[1] /= scaling[1];
+       }
+       if (scaling[2] != 0)
+       {
+               origShift[2] /= scaling[2];
+       }
+       Point32 shift((int32_t)origShift[medAxis], (int32_t)origShift[maxAxis], (int32_t)origShift[minAxis]);
+       if (shift.isZero())
+       {
+               return true;
+       }
+       Point64 normal = face->getNormal();
+#ifdef DEBUG_CONVEX_HULL
+       printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
+                  face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
+#endif
+       int64_t origDot = face->origin.dot(normal);
+       Point32 shiftedOrigin = face->origin + shift;
+       int64_t shiftedDot = shiftedOrigin.dot(normal);
+       btAssert(shiftedDot <= origDot);
+       if (shiftedDot >= origDot)
+       {
+               return false;
+       }
+
+       Edge* intersection = NULL;
+
+       Edge* startEdge = face->nearbyVertex->edges;
+#ifdef DEBUG_CONVEX_HULL
+       printf("Start edge is ");
+       startEdge->print();
+       printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot);
+#endif
+       Rational128 optDot = face->nearbyVertex->dot(normal);
+       int cmp = optDot.compare(shiftedDot);
+#ifdef SHOW_ITERATIONS
+       int n = 0;
+#endif
+       if (cmp >= 0)
+       {
+               Edge* e = startEdge;
+               do
+               {
+#ifdef SHOW_ITERATIONS
+                       n++;
+#endif
+                       Rational128 dot = e->target->dot(normal);
+                       btAssert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+                       printf("Moving downwards, edge is ");
+                       e->print();
+                       printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
+#endif
+                       if (dot.compare(optDot) < 0)
+                       {
+                               int c = dot.compare(shiftedDot);
+                               optDot = dot;
+                               e = e->reverse;
+                               startEdge = e;
+                               if (c < 0)
+                               {
+                                       intersection = e;
+                                       break;
+                               }
+                               cmp = c;
+                       }
+                       e = e->prev;
+               } while (e != startEdge);
+
+               if (!intersection)
+               {
+                       return false;
+               }
+       }
+       else
+       {
+               Edge* e = startEdge;
+               do
+               {
+#ifdef SHOW_ITERATIONS
+                       n++;
+#endif
+                       Rational128 dot = e->target->dot(normal);
+                       btAssert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+                       printf("Moving upwards, edge is ");
+                       e->print();
+                       printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
+#endif
+                       if (dot.compare(optDot) > 0)
+                       {
+                               cmp = dot.compare(shiftedDot);
+                               if (cmp >= 0)
+                               {
+                                       intersection = e;
+                                       break;
+                               }
+                               optDot = dot;
+                               e = e->reverse;
+                               startEdge = e;
+                       }
+                       e = e->prev;
+               } while (e != startEdge);
+
+               if (!intersection)
+               {
+                       return true;
+               }
+       }
+
+#ifdef SHOW_ITERATIONS
+       printf("Needed %d iterations to find initial intersection\n", n);
+#endif
+
+       if (cmp == 0)
+       {
+               Edge* e = intersection->reverse->next;
+#ifdef SHOW_ITERATIONS
+               n = 0;
+#endif
+               while (e->target->dot(normal).compare(shiftedDot) <= 0)
+               {
+#ifdef SHOW_ITERATIONS
+                       n++;
+#endif
+                       e = e->next;
+                       if (e == intersection->reverse)
+                       {
+                               return true;
+                       }
+#ifdef DEBUG_CONVEX_HULL
+                       printf("Checking for outwards edge, current edge is ");
+                       e->print();
+                       printf("\n");
+#endif
+               }
+#ifdef SHOW_ITERATIONS
+               printf("Needed %d iterations to check for complete containment\n", n);
+#endif
+       }
+
+       Edge* firstIntersection = NULL;
+       Edge* faceEdge = NULL;
+       Edge* firstFaceEdge = NULL;
+
+#ifdef SHOW_ITERATIONS
+       int m = 0;
+#endif
+       while (true)
+       {
+#ifdef SHOW_ITERATIONS
+               m++;
+#endif
+#ifdef DEBUG_CONVEX_HULL
+               printf("Intersecting edge is ");
+               intersection->print();
+               printf("\n");
+#endif
+               if (cmp == 0)
+               {
+                       Edge* e = intersection->reverse->next;
+                       startEdge = e;
+#ifdef SHOW_ITERATIONS
+                       n = 0;
+#endif
+                       while (true)
+                       {
+#ifdef SHOW_ITERATIONS
+                               n++;
+#endif
+                               if (e->target->dot(normal).compare(shiftedDot) >= 0)
+                               {
+                                       break;
+                               }
+                               intersection = e->reverse;
+                               e = e->next;
+                               if (e == startEdge)
+                               {
+                                       return true;
+                               }
+                       }
+#ifdef SHOW_ITERATIONS
+                       printf("Needed %d iterations to advance intersection\n", n);
+#endif
+               }
+
+#ifdef DEBUG_CONVEX_HULL
+               printf("Advanced intersecting edge to ");
+               intersection->print();
+               printf(", cmp = %d\n", cmp);
+#endif
+
+               if (!firstIntersection)
+               {
+                       firstIntersection = intersection;
+               }
+               else if (intersection == firstIntersection)
+               {
+                       break;
+               }
+
+               int prevCmp = cmp;
+               Edge* prevIntersection = intersection;
+               Edge* prevFaceEdge = faceEdge;
+
+               Edge* e = intersection->reverse;
+#ifdef SHOW_ITERATIONS
+               n = 0;
+#endif
+               while (true)
+               {
+#ifdef SHOW_ITERATIONS
+                       n++;
+#endif
+                       e = e->reverse->prev;
+                       btAssert(e != intersection->reverse);
+                       cmp = e->target->dot(normal).compare(shiftedDot);
+#ifdef DEBUG_CONVEX_HULL
+                       printf("Testing edge ");
+                       e->print();
+                       printf(" -> cmp = %d\n", cmp);
+#endif
+                       if (cmp >= 0)
+                       {
+                               intersection = e;
+                               break;
+                       }
+               }
+#ifdef SHOW_ITERATIONS
+               printf("Needed %d iterations to find other intersection of face\n", n);
+#endif
+
+               if (cmp > 0)
+               {
+                       Vertex* removed = intersection->target;
+                       e = intersection->reverse;
+                       if (e->prev == e)
+                       {
+                               removed->edges = NULL;
+                       }
+                       else
+                       {
+                               removed->edges = e->prev;
+                               e->prev->link(e->next);
+                               e->link(e);
+                       }
+#ifdef DEBUG_CONVEX_HULL
+                       printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+
+                       Point64 n0 = intersection->face->getNormal();
+                       Point64 n1 = intersection->reverse->face->getNormal();
+                       int64_t m00 = face->dir0.dot(n0);
+                       int64_t m01 = face->dir1.dot(n0);
+                       int64_t m10 = face->dir0.dot(n1);
+                       int64_t m11 = face->dir1.dot(n1);
+                       int64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0);
+                       int64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1);
+                       Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
+                       btAssert(det.getSign() != 0);
+                       Vertex* v = vertexPool.newObject();
+                       v->point.index = -1;
+                       v->copy = -1;
+                       v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
+                                                                       Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
+                                                                       Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
+                                                                       det);
+                       v->point.x = (int32_t)v->point128.xvalue();
+                       v->point.y = (int32_t)v->point128.yvalue();
+                       v->point.z = (int32_t)v->point128.zvalue();
+                       intersection->target = v;
+                       v->edges = e;
+
+                       stack.push_back(v);
+                       stack.push_back(removed);
+                       stack.push_back(NULL);
+               }
+
+               if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target))
+               {
+                       faceEdge = newEdgePair(prevIntersection->target, intersection->target);
+                       if (prevCmp == 0)
+                       {
+                               faceEdge->link(prevIntersection->reverse->next);
+                       }
+                       if ((prevCmp == 0) || prevFaceEdge)
+                       {
+                               prevIntersection->reverse->link(faceEdge);
+                       }
+                       if (cmp == 0)
+                       {
+                               intersection->reverse->prev->link(faceEdge->reverse);
+                       }
+                       faceEdge->reverse->link(intersection->reverse);
+               }
+               else
+               {
+                       faceEdge = prevIntersection->reverse->next;
+               }
+
+               if (prevFaceEdge)
+               {
+                       if (prevCmp > 0)
+                       {
+                               faceEdge->link(prevFaceEdge->reverse);
+                       }
+                       else if (faceEdge != prevFaceEdge->reverse)
+                       {
+                               stack.push_back(prevFaceEdge->target);
+                               while (faceEdge->next != prevFaceEdge->reverse)
+                               {
+                                       Vertex* removed = faceEdge->next->target;
+                                       removeEdgePair(faceEdge->next);
+                                       stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+                                       printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+                               }
+                               stack.push_back(NULL);
+                       }
+               }
+               faceEdge->face = face;
+               faceEdge->reverse->face = intersection->face;
+
+               if (!firstFaceEdge)
+               {
+                       firstFaceEdge = faceEdge;
+               }
+       }
+#ifdef SHOW_ITERATIONS
+       printf("Needed %d iterations to process all intersections\n", m);
+#endif
+
+       if (cmp > 0)
+       {
+               firstFaceEdge->reverse->target = faceEdge->target;
+               firstIntersection->reverse->link(firstFaceEdge);
+               firstFaceEdge->link(faceEdge->reverse);
+       }
+       else if (firstFaceEdge != faceEdge->reverse)
+       {
+               stack.push_back(faceEdge->target);
+               while (firstFaceEdge->next != faceEdge->reverse)
+               {
+                       Vertex* removed = firstFaceEdge->next->target;
+                       removeEdgePair(firstFaceEdge->next);
+                       stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+                       printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+               }
+               stack.push_back(NULL);
+       }
+
+       btAssert(stack.size() > 0);
+       vertexList = stack[0];
+
+#ifdef DEBUG_CONVEX_HULL
+       printf("Removing part\n");
+#endif
+#ifdef SHOW_ITERATIONS
+       n = 0;
+#endif
+       int pos = 0;
+       while (pos < stack.size())
+       {
+               int end = stack.size();
+               while (pos < end)
+               {
+                       Vertex* kept = stack[pos++];
+#ifdef DEBUG_CONVEX_HULL
+                       kept->print();
+#endif
+                       bool deeper = false;
+                       Vertex* removed;
+                       while ((removed = stack[pos++]) != NULL)
+                       {
+#ifdef SHOW_ITERATIONS
+                               n++;
+#endif
+                               kept->receiveNearbyFaces(removed);
+                               while (removed->edges)
+                               {
+                                       if (!deeper)
+                                       {
+                                               deeper = true;
+                                               stack.push_back(kept);
+                                       }
+                                       stack.push_back(removed->edges->target);
+                                       removeEdgePair(removed->edges);
+                               }
+                       }
+                       if (deeper)
+                       {
+                               stack.push_back(NULL);
+                       }
+               }
+       }
+#ifdef SHOW_ITERATIONS
+       printf("Needed %d iterations to remove part\n", n);
+#endif
+
+       stack.resize(0);
+       face->origin = shiftedOrigin;
+
+       return true;
+}
+
+static int getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray<btConvexHullInternal::Vertex*>& vertices)
+{
+       int index = vertex->copy;
+       if (index < 0)
+       {
+               index = vertices.size();
+               vertex->copy = index;
+               vertices.push_back(vertex);
+#ifdef DEBUG_CONVEX_HULL
+               printf("Vertex %d gets index *%d\n", vertex->point.index, index);
+#endif
+       }
+       return index;
+}
+
+btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+{
+       if (count <= 0)
+       {
+               vertices.clear();
+               edges.clear();
+               faces.clear();
+               return 0;
+       }
+
+       btConvexHullInternal hull;
+       hull.compute(coords, doubleCoords, stride, count);
+
+       btScalar shift = 0;
+       if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0))
+       {
+               vertices.clear();
+               edges.clear();
+               faces.clear();
+               return shift;
+       }
+
+       vertices.resize(0);
+       original_vertex_index.resize(0);
+       edges.resize(0);
+       faces.resize(0);
+
+       btAlignedObjectArray<btConvexHullInternal::Vertex*> oldVertices;
+       getVertexCopy(hull.vertexList, oldVertices);
+       int copied = 0;
+       while (copied < oldVertices.size())
+       {
+               btConvexHullInternal::Vertex* v = oldVertices[copied];
+               vertices.push_back(hull.getCoordinates(v));
+               original_vertex_index.push_back(v->point.index);
+               btConvexHullInternal::Edge* firstEdge = v->edges;
+               if (firstEdge)
+               {
+                       int firstCopy = -1;
+                       int prevCopy = -1;
+                       btConvexHullInternal::Edge* e = firstEdge;
+                       do
+                       {
+                               if (e->copy < 0)
+                               {
+                                       int s = edges.size();
+                                       edges.push_back(Edge());
+                                       edges.push_back(Edge());
+                                       Edge* c = &edges[s];
+                                       Edge* r = &edges[s + 1];
+                                       e->copy = s;
+                                       e->reverse->copy = s + 1;
+                                       c->reverse = 1;
+                                       r->reverse = -1;
+                                       c->targetVertex = getVertexCopy(e->target, oldVertices);
+                                       r->targetVertex = copied;
+#ifdef DEBUG_CONVEX_HULL
+                                       printf("      CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex());
+#endif
+                               }
+                               if (prevCopy >= 0)
+                               {
+                                       edges[e->copy].next = prevCopy - e->copy;
+                               }
+                               else
+                               {
+                                       firstCopy = e->copy;
+                               }
+                               prevCopy = e->copy;
+                               e = e->next;
+                       } while (e != firstEdge);
+                       edges[firstCopy].next = prevCopy - firstCopy;
+               }
+               copied++;
+       }
+
+       for (int i = 0; i < copied; i++)
+       {
+               btConvexHullInternal::Vertex* v = oldVertices[i];
+               btConvexHullInternal::Edge* firstEdge = v->edges;
+               if (firstEdge)
+               {
+                       btConvexHullInternal::Edge* e = firstEdge;
+                       do
+                       {
+                               if (e->copy >= 0)
+                               {
+#ifdef DEBUG_CONVEX_HULL
+                                       printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex());
+#endif
+                                       faces.push_back(e->copy);
+                                       btConvexHullInternal::Edge* f = e;
+                                       do
+                                       {
+#ifdef DEBUG_CONVEX_HULL
+                                               printf("   Face *%d\n", edges[f->copy].getTargetVertex());
+#endif
+                                               f->copy = -1;
+                                               f = f->reverse->prev;
+                                       } while (f != e);
+                               }
+                               e = e->next;
+                       } while (e != firstEdge);
+               }
+       }
+
+       return shift;
+}
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btConvexHullComputer.h b/dali-physics/third-party/bullet3/src/LinearMath/btConvexHullComputer.h
new file mode 100644 (file)
index 0000000..18b26ee
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_CONVEX_HULL_COMPUTER_H
+#define BT_CONVEX_HULL_COMPUTER_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+/// Convex hull implementation based on Preparata and Hong
+/// See http://code.google.com/p/bullet/issues/detail?id=275
+/// Ole Kniemeyer, MAXON Computer GmbH
+class btConvexHullComputer
+{
+private:
+       btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp);
+
+public:
+       class Edge
+       {
+       private:
+               int next;
+               int reverse;
+               int targetVertex;
+
+               friend class btConvexHullComputer;
+
+       public:
+               int getSourceVertex() const
+               {
+                       return (this + reverse)->targetVertex;
+               }
+
+               int getTargetVertex() const
+               {
+                       return targetVertex;
+               }
+
+               const Edge* getNextEdgeOfVertex() const  // clockwise list of all edges of a vertex
+               {
+                       return this + next;
+               }
+
+               const Edge* getNextEdgeOfFace() const  // counter-clockwise list of all edges of a face
+               {
+                       return (this + reverse)->getNextEdgeOfVertex();
+               }
+
+               const Edge* getReverseEdge() const
+               {
+                       return this + reverse;
+               }
+       };
+
+       // Vertices of the output hull
+       btAlignedObjectArray<btVector3> vertices;
+
+       // The original vertex index in the input coords array
+       btAlignedObjectArray<int> original_vertex_index;
+
+       // Edges of the output hull
+       btAlignedObjectArray<Edge> edges;
+
+       // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
+       btAlignedObjectArray<int> faces;
+
+       /*
+               Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
+               between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
+               by that amount (each face is moved by "shrink" length units towards the center along its normal).
+               If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius"
+               is the minimum distance of a face to the center of the convex hull.
+
+               The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large
+               that the resulting convex hull is empty.
+
+               The output convex hull can be found in the member variables "vertices", "edges", "faces".
+               */
+       btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+       {
+               return compute(coords, false, stride, count, shrink, shrinkClamp);
+       }
+
+       // same as above, but double precision
+       btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+       {
+               return compute(coords, true, stride, count, shrink, shrinkClamp);
+       }
+};
+
+#endif  //BT_CONVEX_HULL_COMPUTER_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btCpuFeatureUtility.h b/dali-physics/third-party/bullet3/src/LinearMath/btCpuFeatureUtility.h
new file mode 100644 (file)
index 0000000..5e4b9a3
--- /dev/null
@@ -0,0 +1,88 @@
+
+#ifndef BT_CPU_UTILITY_H
+#define BT_CPU_UTILITY_H
+
+#include "LinearMath/btScalar.h"
+
+#include <string.h>  //memset
+#ifdef USE_SIMD
+#include <emmintrin.h>
+#ifdef BT_ALLOW_SSE4
+#include <intrin.h>
+#endif  //BT_ALLOW_SSE4
+#endif  //USE_SIMD
+
+#if defined BT_USE_NEON
+#define ARM_NEON_GCC_COMPATIBILITY 1
+#include <arm_neon.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>  //for sysctlbyname
+#endif                   //BT_USE_NEON
+
+///Rudimentary btCpuFeatureUtility for CPU features: only report the features that Bullet actually uses (SSE4/FMA3, NEON_HPFP)
+///We assume SSE2 in case BT_USE_SSE2 is defined in LinearMath/btScalar.h
+class btCpuFeatureUtility
+{
+public:
+       enum btCpuFeature
+       {
+               CPU_FEATURE_FMA3 = 1,
+               CPU_FEATURE_SSE4_1 = 2,
+               CPU_FEATURE_NEON_HPFP = 4
+       };
+
+       static int getCpuFeatures()
+       {
+               static int capabilities = 0;
+               static bool testedCapabilities = false;
+               if (0 != testedCapabilities)
+               {
+                       return capabilities;
+               }
+
+#ifdef BT_USE_NEON
+               {
+                       uint32_t hasFeature = 0;
+                       size_t featureSize = sizeof(hasFeature);
+                       int err = sysctlbyname("hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0);
+                       if (0 == err && hasFeature)
+                               capabilities |= CPU_FEATURE_NEON_HPFP;
+               }
+#endif  //BT_USE_NEON
+
+#ifdef BT_ALLOW_SSE4
+               {
+                       int cpuInfo[4];
+                       memset(cpuInfo, 0, sizeof(cpuInfo));
+                       unsigned long long sseExt = 0;
+                       __cpuid(cpuInfo, 1);
+
+                       bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false;
+                       bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false;
+
+                       if (osUsesXSAVE_XRSTORE && cpuAVXSuport)
+                       {
+                               sseExt = _xgetbv(0);
+                       }
+                       const int OSXSAVEFlag = (1UL << 27);
+                       const int AVXFlag = ((1UL << 28) | OSXSAVEFlag);
+                       const int FMAFlag = ((1UL << 12) | AVXFlag | OSXSAVEFlag);
+                       if ((cpuInfo[2] & FMAFlag) == FMAFlag && (sseExt & 6) == 6)
+                       {
+                               capabilities |= btCpuFeatureUtility::CPU_FEATURE_FMA3;
+                       }
+
+                       const int SSE41Flag = (1 << 19);
+                       if (cpuInfo[2] & SSE41Flag)
+                       {
+                               capabilities |= btCpuFeatureUtility::CPU_FEATURE_SSE4_1;
+                       }
+               }
+#endif  //BT_ALLOW_SSE4
+
+               testedCapabilities = true;
+               return capabilities;
+       }
+};
+
+#endif  //BT_CPU_UTILITY_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btDefaultMotionState.h b/dali-physics/third-party/bullet3/src/LinearMath/btDefaultMotionState.h
new file mode 100644 (file)
index 0000000..14c40d3
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef BT_DEFAULT_MOTION_STATE_H
+#define BT_DEFAULT_MOTION_STATE_H
+
+#include "btMotionState.h"
+
+///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets.
+ATTRIBUTE_ALIGNED16(struct)
+btDefaultMotionState : public btMotionState
+{
+       btTransform m_graphicsWorldTrans;
+       btTransform m_centerOfMassOffset;
+       btTransform m_startWorldTrans;
+       void* m_userPointer;
+
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+       btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(), const btTransform& centerOfMassOffset = btTransform::getIdentity())
+               : m_graphicsWorldTrans(startTrans),
+                 m_centerOfMassOffset(centerOfMassOffset),
+                 m_startWorldTrans(startTrans),
+                 m_userPointer(0)
+
+       {
+       }
+
+       ///synchronizes world transform from user to physics
+       virtual void getWorldTransform(btTransform & centerOfMassWorldTrans) const
+       {
+               centerOfMassWorldTrans = m_graphicsWorldTrans * m_centerOfMassOffset.inverse();
+       }
+
+       ///synchronizes world transform from physics to user
+       ///Bullet only calls the update of worldtransform for active objects
+       virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans)
+       {
+               m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset;
+       }
+};
+
+#endif  //BT_DEFAULT_MOTION_STATE_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btGeometryUtil.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btGeometryUtil.cpp
new file mode 100644 (file)
index 0000000..62bbef2
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btGeometryUtil.h"
+
+/*
+  Make sure this dummy function never changes so that it
+  can be used by probes that are checking whether the
+  library is actually installed.
+*/
+extern "C"
+{
+       void btBulletMathProbe();
+
+       void btBulletMathProbe() {}
+}
+
+bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin)
+{
+       int numbrushes = planeEquations.size();
+       for (int i = 0; i < numbrushes; i++)
+       {
+               const btVector3& N1 = planeEquations[i];
+               btScalar dist = btScalar(N1.dot(point)) + btScalar(N1[3]) - margin;
+               if (dist > btScalar(0.))
+               {
+                       return false;
+               }
+       }
+       return true;
+}
+
+bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin)
+{
+       int numvertices = vertices.size();
+       for (int i = 0; i < numvertices; i++)
+       {
+               const btVector3& N1 = vertices[i];
+               btScalar dist = btScalar(planeNormal.dot(N1)) + btScalar(planeNormal[3]) - margin;
+               if (dist > btScalar(0.))
+               {
+                       return false;
+               }
+       }
+       return true;
+}
+
+bool notExist(const btVector3& planeEquation, const btAlignedObjectArray<btVector3>& planeEquations);
+
+bool notExist(const btVector3& planeEquation, const btAlignedObjectArray<btVector3>& planeEquations)
+{
+       int numbrushes = planeEquations.size();
+       for (int i = 0; i < numbrushes; i++)
+       {
+               const btVector3& N1 = planeEquations[i];
+               if (planeEquation.dot(N1) > btScalar(0.999))
+               {
+                       return false;
+               }
+       }
+       return true;
+}
+
+void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut)
+{
+       const int numvertices = vertices.size();
+       // brute force:
+       for (int i = 0; i < numvertices; i++)
+       {
+               const btVector3& N1 = vertices[i];
+
+               for (int j = i + 1; j < numvertices; j++)
+               {
+                       const btVector3& N2 = vertices[j];
+
+                       for (int k = j + 1; k < numvertices; k++)
+                       {
+                               const btVector3& N3 = vertices[k];
+
+                               btVector3 planeEquation, edge0, edge1;
+                               edge0 = N2 - N1;
+                               edge1 = N3 - N1;
+                               btScalar normalSign = btScalar(1.);
+                               for (int ww = 0; ww < 2; ww++)
+                               {
+                                       planeEquation = normalSign * edge0.cross(edge1);
+                                       if (planeEquation.length2() > btScalar(0.0001))
+                                       {
+                                               planeEquation.normalize();
+                                               if (notExist(planeEquation, planeEquationsOut))
+                                               {
+                                                       planeEquation[3] = -planeEquation.dot(N1);
+
+                                                       //check if inside, and replace supportingVertexOut if needed
+                                                       if (areVerticesBehindPlane(planeEquation, vertices, btScalar(0.01)))
+                                                       {
+                                                               planeEquationsOut.push_back(planeEquation);
+                                                       }
+                                               }
+                                       }
+                                       normalSign = btScalar(-1.);
+                               }
+                       }
+               }
+       }
+}
+
+void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations, btAlignedObjectArray<btVector3>& verticesOut)
+{
+       const int numbrushes = planeEquations.size();
+       // brute force:
+       for (int i = 0; i < numbrushes; i++)
+       {
+               const btVector3& N1 = planeEquations[i];
+
+               for (int j = i + 1; j < numbrushes; j++)
+               {
+                       const btVector3& N2 = planeEquations[j];
+
+                       for (int k = j + 1; k < numbrushes; k++)
+                       {
+                               const btVector3& N3 = planeEquations[k];
+
+                               btVector3 n2n3;
+                               n2n3 = N2.cross(N3);
+                               btVector3 n3n1;
+                               n3n1 = N3.cross(N1);
+                               btVector3 n1n2;
+                               n1n2 = N1.cross(N2);
+
+                               if ((n2n3.length2() > btScalar(0.0001)) &&
+                                       (n3n1.length2() > btScalar(0.0001)) &&
+                                       (n1n2.length2() > btScalar(0.0001)))
+                               {
+                                       //point P out of 3 plane equations:
+
+                                       //      d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
+                                       //P =  -------------------------------------------------------------------------
+                                       //   N1 . ( N2 * N3 )
+
+                                       btScalar quotient = (N1.dot(n2n3));
+                                       if (btFabs(quotient) > btScalar(0.000001))
+                                       {
+                                               quotient = btScalar(-1.) / quotient;
+                                               n2n3 *= N1[3];
+                                               n3n1 *= N2[3];
+                                               n1n2 *= N3[3];
+                                               btVector3 potentialVertex = n2n3;
+                                               potentialVertex += n3n1;
+                                               potentialVertex += n1n2;
+                                               potentialVertex *= quotient;
+
+                                               //check if inside, and replace supportingVertexOut if needed
+                                               if (isPointInsidePlanes(planeEquations, potentialVertex, btScalar(0.01)))
+                                               {
+                                                       verticesOut.push_back(potentialVertex);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btGeometryUtil.h b/dali-physics/third-party/bullet3/src/LinearMath/btGeometryUtil.h
new file mode 100644 (file)
index 0000000..5ed8702
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_GEOMETRY_UTIL_H
+#define BT_GEOMETRY_UTIL_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices.
+class btGeometryUtil
+{
+public:
+       static void getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut);
+
+       static void getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations, btAlignedObjectArray<btVector3>& verticesOut);
+
+       static bool isInside(const btAlignedObjectArray<btVector3>& vertices, const btVector3& planeNormal, btScalar margin);
+
+       static bool isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin);
+
+       static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin);
+};
+
+#endif  //BT_GEOMETRY_UTIL_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btGrahamScan2dConvexHull.h b/dali-physics/third-party/bullet3/src/LinearMath/btGrahamScan2dConvexHull.h
new file mode 100644 (file)
index 0000000..0fcb285
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 GRAHAM_SCAN_2D_CONVEX_HULL_H
+#define GRAHAM_SCAN_2D_CONVEX_HULL_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+struct GrahamVector3 : public btVector3
+{
+       GrahamVector3(const btVector3& org, int orgIndex)
+               : btVector3(org),
+                 m_orgIndex(orgIndex)
+       {
+       }
+       btScalar m_angle;
+       int m_orgIndex;
+};
+
+struct btAngleCompareFunc
+{
+       btVector3 m_anchor;
+       btAngleCompareFunc(const btVector3& anchor)
+               : m_anchor(anchor)
+       {
+       }
+       bool operator()(const GrahamVector3& a, const GrahamVector3& b) const
+       {
+               if (a.m_angle != b.m_angle)
+                       return a.m_angle < b.m_angle;
+               else
+               {
+                       btScalar al = (a - m_anchor).length2();
+                       btScalar bl = (b - m_anchor).length2();
+                       if (al != bl)
+                               return al < bl;
+                       else
+                       {
+                               return a.m_orgIndex < b.m_orgIndex;
+                       }
+               }
+       }
+};
+
+inline void GrahamScanConvexHull2D(btAlignedObjectArray<GrahamVector3>& originalPoints, btAlignedObjectArray<GrahamVector3>& hull, const btVector3& normalAxis)
+{
+       btVector3 axis0, axis1;
+       btPlaneSpace1(normalAxis, axis0, axis1);
+
+       if (originalPoints.size() <= 1)
+       {
+               for (int i = 0; i < originalPoints.size(); i++)
+                       hull.push_back(originalPoints[0]);
+               return;
+       }
+       //step1 : find anchor point with smallest projection on axis0 and move it to first location
+       for (int i = 0; i < originalPoints.size(); i++)
+       {
+               //              const btVector3& left = originalPoints[i];
+               //              const btVector3& right = originalPoints[0];
+               btScalar projL = originalPoints[i].dot(axis0);
+               btScalar projR = originalPoints[0].dot(axis0);
+               if (projL < projR)
+               {
+                       originalPoints.swap(0, i);
+               }
+       }
+
+       //also precompute angles
+       originalPoints[0].m_angle = -1e30f;
+       for (int i = 1; i < originalPoints.size(); i++)
+       {
+               btVector3 ar = originalPoints[i] - originalPoints[0];
+               btScalar ar1 = axis1.dot(ar);
+               btScalar ar0 = axis0.dot(ar);
+               if (ar1 * ar1 + ar0 * ar0 < FLT_EPSILON)
+               {
+                       originalPoints[i].m_angle = 0.0f;
+               }
+               else
+               {
+                       originalPoints[i].m_angle = btAtan2Fast(ar1, ar0);
+               }
+       }
+
+       //step 2: sort all points, based on 'angle' with this anchor
+       btAngleCompareFunc comp(originalPoints[0]);
+       originalPoints.quickSortInternal(comp, 1, originalPoints.size() - 1);
+
+       int i;
+       for (i = 0; i < 2; i++)
+               hull.push_back(originalPoints[i]);
+
+       //step 3: keep all 'convex' points and discard concave points (using back tracking)
+       for (; i != originalPoints.size(); i++)
+       {
+               bool isConvex = false;
+               while (!isConvex && hull.size() > 1)
+               {
+                       btVector3& a = hull[hull.size() - 2];
+                       btVector3& b = hull[hull.size() - 1];
+                       isConvex = btCross(a - b, a - originalPoints[i]).dot(normalAxis) > 0;
+                       if (!isConvex)
+                               hull.pop_back();
+                       else
+                               hull.push_back(originalPoints[i]);
+               }
+
+               if (hull.size() == 1)
+               {
+                       hull.push_back(originalPoints[i]);
+               }
+       }
+}
+
+#endif  //GRAHAM_SCAN_2D_CONVEX_HULL_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btHashMap.h b/dali-physics/third-party/bullet3/src/LinearMath/btHashMap.h
new file mode 100644 (file)
index 0000000..1fca0fb
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_HASH_MAP_H
+#define BT_HASH_MAP_H
+
+#include <string>
+#include "btAlignedObjectArray.h"
+
+///very basic hashable string implementation, compatible with btHashMap
+struct btHashString
+{
+       std::string m_string1;
+       unsigned int m_hash;
+
+       SIMD_FORCE_INLINE unsigned int getHash() const
+       {
+               return m_hash;
+       }
+
+       btHashString()
+       {
+               m_string1 = "";
+               m_hash = 0;
+       }
+       btHashString(const char* name)
+               : m_string1(name)
+       {
+               /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
+               static const unsigned int InitialFNV = 2166136261u;
+               static const unsigned int FNVMultiple = 16777619u;
+
+               /* Fowler / Noll / Vo (FNV) Hash */
+               unsigned int hash = InitialFNV;
+
+               for (int i = 0; m_string1.c_str()[i]; i++)
+               {
+                       hash = hash ^ (m_string1.c_str()[i]); /* xor  the low 8 bits */
+                       hash = hash * FNVMultiple;            /* multiply by the magic number */
+               }
+               m_hash = hash;
+       }
+
+       bool equals(const btHashString& other) const
+       {
+               return (m_string1 == other.m_string1);
+       }
+};
+
+const int BT_HASH_NULL = 0xffffffff;
+
+class btHashInt
+{
+       int m_uid;
+
+public:
+       btHashInt()
+       {
+       }
+
+       btHashInt(int uid) : m_uid(uid)
+       {
+       }
+
+       int getUid1() const
+       {
+               return m_uid;
+       }
+
+       void setUid1(int uid)
+       {
+               m_uid = uid;
+       }
+
+       bool equals(const btHashInt& other) const
+       {
+               return getUid1() == other.getUid1();
+       }
+       //to our success
+       SIMD_FORCE_INLINE unsigned int getHash() const
+       {
+               unsigned int key = m_uid;
+               // Thomas Wang's hash
+               key += ~(key << 15);
+               key ^= (key >> 10);
+               key += (key << 3);
+               key ^= (key >> 6);
+               key += ~(key << 11);
+               key ^= (key >> 16);
+
+               return key;
+       }
+};
+
+class btHashPtr
+{
+       union {
+               const void* m_pointer;
+               unsigned int m_hashValues[2];
+       };
+
+public:
+       btHashPtr(const void* ptr)
+               : m_pointer(ptr)
+       {
+       }
+
+       const void* getPointer() const
+       {
+               return m_pointer;
+       }
+
+       bool equals(const btHashPtr& other) const
+       {
+               return getPointer() == other.getPointer();
+       }
+
+       //to our success
+       SIMD_FORCE_INLINE unsigned int getHash() const
+       {
+               const bool VOID_IS_8 = ((sizeof(void*) == 8));
+
+               unsigned int key = VOID_IS_8 ? m_hashValues[0] + m_hashValues[1] : m_hashValues[0];
+               // Thomas Wang's hash
+               key += ~(key << 15);
+               key ^= (key >> 10);
+               key += (key << 3);
+               key ^= (key >> 6);
+               key += ~(key << 11);
+               key ^= (key >> 16);
+               return key;
+       }
+};
+
+template <class Value>
+class btHashKeyPtr
+{
+       int m_uid;
+
+public:
+       btHashKeyPtr(int uid) : m_uid(uid)
+       {
+       }
+
+       int getUid1() const
+       {
+               return m_uid;
+       }
+
+       bool equals(const btHashKeyPtr<Value>& other) const
+       {
+               return getUid1() == other.getUid1();
+       }
+
+       //to our success
+       SIMD_FORCE_INLINE unsigned int getHash() const
+       {
+               unsigned int key = m_uid;
+               // Thomas Wang's hash
+               key += ~(key << 15);
+               key ^= (key >> 10);
+               key += (key << 3);
+               key ^= (key >> 6);
+               key += ~(key << 11);
+               key ^= (key >> 16);
+               return key;
+       }
+};
+
+template <class Value>
+class btHashKey
+{
+       int m_uid;
+
+public:
+       btHashKey(int uid) : m_uid(uid)
+       {
+       }
+
+       int getUid1() const
+       {
+               return m_uid;
+       }
+
+       bool equals(const btHashKey<Value>& other) const
+       {
+               return getUid1() == other.getUid1();
+       }
+       //to our success
+       SIMD_FORCE_INLINE unsigned int getHash() const
+       {
+               unsigned int key = m_uid;
+               // Thomas Wang's hash
+               key += ~(key << 15);
+               key ^= (key >> 10);
+               key += (key << 3);
+               key ^= (key >> 6);
+               key += ~(key << 11);
+               key ^= (key >> 16);
+               return key;
+       }
+};
+
+///The btHashMap template class implements a generic and lightweight hashmap.
+///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
+template <class Key, class Value>
+class btHashMap
+{
+protected:
+       btAlignedObjectArray<int> m_hashTable;
+       btAlignedObjectArray<int> m_next;
+
+       btAlignedObjectArray<Value> m_valueArray;
+       btAlignedObjectArray<Key> m_keyArray;
+
+       void growTables(const Key& /*key*/)
+       {
+               int newCapacity = m_valueArray.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_HASH_NULL;
+                       }
+                       for (i = 0; i < newCapacity; ++i)
+                       {
+                               m_next[i] = BT_HASH_NULL;
+                       }
+
+                       for (i = 0; i < curHashtableSize; i++)
+                       {
+                               //const Value& value = m_valueArray[i];
+                               //const Key& key = m_keyArray[i];
+
+                               int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity() - 1);  // New hash value with new mask
+                               m_next[i] = m_hashTable[hashValue];
+                               m_hashTable[hashValue] = i;
+                       }
+               }
+       }
+
+public:
+       void insert(const Key& key, const Value& value)
+       {
+               int hash = key.getHash() & (m_valueArray.capacity() - 1);
+
+               //replace value if the key is already there
+               int index = findIndex(key);
+               if (index != BT_HASH_NULL)
+               {
+                       m_valueArray[index] = value;
+                       return;
+               }
+
+               int count = m_valueArray.size();
+               int oldCapacity = m_valueArray.capacity();
+               m_valueArray.push_back(value);
+               m_keyArray.push_back(key);
+
+               int newCapacity = m_valueArray.capacity();
+               if (oldCapacity < newCapacity)
+               {
+                       growTables(key);
+                       //hash with new capacity
+                       hash = key.getHash() & (m_valueArray.capacity() - 1);
+               }
+               m_next[count] = m_hashTable[hash];
+               m_hashTable[hash] = count;
+       }
+
+       void remove(const Key& key)
+       {
+               int hash = key.getHash() & (m_valueArray.capacity() - 1);
+
+               int pairIndex = findIndex(key);
+
+               if (pairIndex == BT_HASH_NULL)
+               {
+                       return;
+               }
+
+               // Remove the pair from the hash table.
+               int index = m_hashTable[hash];
+               btAssert(index != BT_HASH_NULL);
+
+               int previous = BT_HASH_NULL;
+               while (index != pairIndex)
+               {
+                       previous = index;
+                       index = m_next[index];
+               }
+
+               if (previous != BT_HASH_NULL)
+               {
+                       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_valueArray.size() - 1;
+
+               // If the removed pair is the last pair, we are done.
+               if (lastPairIndex == pairIndex)
+               {
+                       m_valueArray.pop_back();
+                       m_keyArray.pop_back();
+                       return;
+               }
+
+               // Remove the last pair from the hash table.
+               int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity() - 1);
+
+               index = m_hashTable[lastHash];
+               btAssert(index != BT_HASH_NULL);
+
+               previous = BT_HASH_NULL;
+               while (index != lastPairIndex)
+               {
+                       previous = index;
+                       index = m_next[index];
+               }
+
+               if (previous != BT_HASH_NULL)
+               {
+                       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_valueArray[pairIndex] = m_valueArray[lastPairIndex];
+               m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
+
+               // Insert the last pair into the hash table
+               m_next[pairIndex] = m_hashTable[lastHash];
+               m_hashTable[lastHash] = pairIndex;
+
+               m_valueArray.pop_back();
+               m_keyArray.pop_back();
+       }
+
+       int size() const
+       {
+               return m_valueArray.size();
+       }
+
+       const Value* getAtIndex(int index) const
+       {
+               btAssert(index < m_valueArray.size());
+               btAssert(index >= 0);
+               if (index >= 0 && index < m_valueArray.size())
+               {
+                       return &m_valueArray[index];
+               }
+               return 0;
+       }
+
+       Value* getAtIndex(int index)
+       {
+               btAssert(index < m_valueArray.size());
+               btAssert(index >= 0);
+               if (index >= 0 && index < m_valueArray.size())
+               {
+                       return &m_valueArray[index];
+               }
+               return 0;
+       }
+
+       Key getKeyAtIndex(int index)
+       {
+               btAssert(index < m_keyArray.size());
+               btAssert(index >= 0);
+               return m_keyArray[index];
+       }
+
+       const Key getKeyAtIndex(int index) const
+       {
+               btAssert(index < m_keyArray.size());
+               btAssert(index >= 0);
+               return m_keyArray[index];
+       }
+
+       Value* operator[](const Key& key)
+       {
+               return find(key);
+       }
+
+       const Value* operator[](const Key& key) const
+       {
+               return find(key);
+       }
+
+       const Value* find(const Key& key) const
+       {
+               int index = findIndex(key);
+               if (index == BT_HASH_NULL)
+               {
+                       return NULL;
+               }
+               return &m_valueArray[index];
+       }
+
+       Value* find(const Key& key)
+       {
+               int index = findIndex(key);
+               if (index == BT_HASH_NULL)
+               {
+                       return NULL;
+               }
+               return &m_valueArray[index];
+       }
+
+       int findIndex(const Key& key) const
+       {
+               unsigned int hash = key.getHash() & (m_valueArray.capacity() - 1);
+
+               if (hash >= (unsigned int)m_hashTable.size())
+               {
+                       return BT_HASH_NULL;
+               }
+
+               int index = m_hashTable[hash];
+               while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
+               {
+                       index = m_next[index];
+               }
+               return index;
+       }
+
+       void clear()
+       {
+               m_hashTable.clear();
+               m_next.clear();
+               m_valueArray.clear();
+               m_keyArray.clear();
+       }
+};
+
+#endif  //BT_HASH_MAP_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btIDebugDraw.h b/dali-physics/third-party/bullet3/src/LinearMath/btIDebugDraw.h
new file mode 100644 (file)
index 0000000..df4db2f
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_IDEBUG_DRAW__H
+#define BT_IDEBUG_DRAW__H
+
+#include "btVector3.h"
+#include "btTransform.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 will need to provide non-empty implementations of the the drawLine and getDebugMode methods at a minimum.
+///For color arguments the X,Y,Z components refer to Red, Green and Blue each in the range [0..1]
+class btIDebugDraw
+{
+public:
+       ATTRIBUTE_ALIGNED16(struct)
+       DefaultColors
+       {
+               btVector3 m_activeObject;
+               btVector3 m_deactivatedObject;
+               btVector3 m_wantsDeactivationObject;
+               btVector3 m_disabledDeactivationObject;
+               btVector3 m_disabledSimulationObject;
+               btVector3 m_aabb;
+               btVector3 m_contactPoint;
+
+               DefaultColors()
+                       : m_activeObject(1, 1, 1),
+                         m_deactivatedObject(0, 1, 0),
+                         m_wantsDeactivationObject(0, 1, 1),
+                         m_disabledDeactivationObject(1, 0, 0),
+                         m_disabledSimulationObject(1, 1, 0),
+                         m_aabb(1, 0, 0),
+                         m_contactPoint(1, 1, 0)
+               {
+               }
+       };
+
+       enum DebugDrawModes
+       {
+               DBG_NoDebug = 0,
+               DBG_DrawWireframe = 1,
+               DBG_DrawAabb = 2,
+               DBG_DrawFeaturesText = 4,
+               DBG_DrawContactPoints = 8,
+               DBG_NoDeactivation = 16,
+               DBG_NoHelpText = 32,
+               DBG_DrawText = 64,
+               DBG_ProfileTimings = 128,
+               DBG_EnableSatComparison = 256,
+               DBG_DisableBulletLCP = 512,
+               DBG_EnableCCD = 1024,
+               DBG_DrawConstraints = (1 << 11),
+               DBG_DrawConstraintLimits = (1 << 12),
+               DBG_FastWireframe = (1 << 13),
+               DBG_DrawNormals = (1 << 14),
+               DBG_DrawFrames = (1 << 15),
+               DBG_MAX_DEBUG_DRAW_MODE
+       };
+
+       virtual ~btIDebugDraw(){};
+
+       virtual DefaultColors getDefaultColors() const
+       {
+               DefaultColors colors;
+               return colors;
+       }
+       ///the default implementation for setDefaultColors has no effect. A derived class can implement it and store the colors.
+       virtual void setDefaultColors(const DefaultColors& /*colors*/) {}
+
+       virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) = 0;
+
+       virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
+       {
+               (void)toColor;
+               drawLine(from, to, fromColor);
+       }
+
+       virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
+       {
+               btVector3 center = transform.getOrigin();
+               btVector3 up = transform.getBasis().getColumn(1);
+               btVector3 axis = transform.getBasis().getColumn(0);
+               btScalar minTh = -SIMD_HALF_PI;
+               btScalar maxTh = SIMD_HALF_PI;
+               btScalar minPs = -SIMD_HALF_PI;
+               btScalar maxPs = SIMD_HALF_PI;
+               btScalar stepDegrees = 30.f;
+               drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, stepDegrees, false);
+               drawSpherePatch(center, up, -axis, radius, minTh, maxTh, minPs, maxPs, color, stepDegrees, false);
+       }
+
+       virtual void drawSphere(const btVector3& p, btScalar radius, const btVector3& color)
+       {
+               btTransform tr;
+               tr.setIdentity();
+               tr.setOrigin(p);
+               drawSphere(radius, tr, color);
+       }
+
+       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;
+
+       virtual void drawAabb(const btVector3& from, const btVector3& to, const btVector3& color)
+       {
+               btVector3 halfExtents = (to - from) * 0.5f;
+               btVector3 center = (to + from) * 0.5f;
+               int i, j;
+
+               btVector3 edgecoord(1.f, 1.f, 1.f), pa, pb;
+               for (i = 0; i < 4; i++)
+               {
+                       for (j = 0; j < 3; j++)
+                       {
+                               pa = btVector3(edgecoord[0] * halfExtents[0], edgecoord[1] * halfExtents[1],
+                                                          edgecoord[2] * halfExtents[2]);
+                               pa += center;
+
+                               int othercoord = j % 3;
+                               edgecoord[othercoord] *= -1.f;
+                               pb = btVector3(edgecoord[0] * halfExtents[0], edgecoord[1] * halfExtents[1],
+                                                          edgecoord[2] * halfExtents[2]);
+                               pb += center;
+
+                               drawLine(pa, pb, color);
+                       }
+                       edgecoord = btVector3(-1.f, -1.f, -1.f);
+                       if (i < 3)
+                               edgecoord[i] *= -1.f;
+               }
+       }
+       virtual void drawTransform(const btTransform& transform, btScalar orthoLen)
+       {
+               btVector3 start = transform.getOrigin();
+               drawLine(start, start + transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(btScalar(1.), btScalar(0.3), btScalar(0.3)));
+               drawLine(start, start + transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(btScalar(0.3), btScalar(1.), btScalar(0.3)));
+               drawLine(start, start + transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(btScalar(0.3), btScalar(0.3), btScalar(1.)));
+       }
+
+       virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle,
+                                                const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f))
+       {
+               const btVector3& vx = axis;
+               btVector3 vy = normal.cross(axis);
+               btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
+               int nSteps = (int)btFabs((maxAngle - minAngle) / step);
+               if (!nSteps) nSteps = 1;
+               btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle);
+               if (drawSect)
+               {
+                       drawLine(center, prev, color);
+               }
+               for (int i = 1; i <= nSteps; i++)
+               {
+                       btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps);
+                       btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle);
+                       drawLine(prev, next, color);
+                       prev = next;
+               }
+               if (drawSect)
+               {
+                       drawLine(center, prev, color);
+               }
+       }
+       virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius,
+                                                                btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f), bool drawCenter = true)
+       {
+               btVector3 vA[74];
+               btVector3 vB[74];
+               btVector3 *pvA = vA, *pvB = vB, *pT;
+               btVector3 npole = center + up * radius;
+               btVector3 spole = center - up * radius;
+               btVector3 arcStart;
+               btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
+               const btVector3& kv = up;
+               const btVector3& iv = axis;
+               btVector3 jv = kv.cross(iv);
+               bool drawN = false;
+               bool drawS = false;
+               if (minTh <= -SIMD_HALF_PI)
+               {
+                       minTh = -SIMD_HALF_PI + step;
+                       drawN = true;
+               }
+               if (maxTh >= SIMD_HALF_PI)
+               {
+                       maxTh = SIMD_HALF_PI - step;
+                       drawS = true;
+               }
+               if (minTh > maxTh)
+               {
+                       minTh = -SIMD_HALF_PI + step;
+                       maxTh = SIMD_HALF_PI - step;
+                       drawN = drawS = true;
+               }
+               int n_hor = (int)((maxTh - minTh) / step) + 1;
+               if (n_hor < 2) n_hor = 2;
+               btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1);
+               bool isClosed = false;
+               if (minPs > maxPs)
+               {
+                       minPs = -SIMD_PI + step;
+                       maxPs = SIMD_PI;
+                       isClosed = true;
+               }
+               else if ((maxPs - minPs) >= SIMD_PI * btScalar(2.f))
+               {
+                       isClosed = true;
+               }
+               else
+               {
+                       isClosed = false;
+               }
+               int n_vert = (int)((maxPs - minPs) / step) + 1;
+               if (n_vert < 2) n_vert = 2;
+               btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1);
+               for (int i = 0; i < n_hor; i++)
+               {
+                       btScalar th = minTh + btScalar(i) * step_h;
+                       btScalar sth = radius * btSin(th);
+                       btScalar cth = radius * btCos(th);
+                       for (int j = 0; j < n_vert; j++)
+                       {
+                               btScalar psi = minPs + btScalar(j) * step_v;
+                               btScalar sps = btSin(psi);
+                               btScalar cps = btCos(psi);
+                               pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv;
+                               if (i)
+                               {
+                                       drawLine(pvA[j], pvB[j], color);
+                               }
+                               else if (drawS)
+                               {
+                                       drawLine(spole, pvB[j], color);
+                               }
+                               if (j)
+                               {
+                                       drawLine(pvB[j - 1], pvB[j], color);
+                               }
+                               else
+                               {
+                                       arcStart = pvB[j];
+                               }
+                               if ((i == (n_hor - 1)) && drawN)
+                               {
+                                       drawLine(npole, pvB[j], color);
+                               }
+
+                               if (drawCenter)
+                               {
+                                       if (isClosed)
+                                       {
+                                               if (j == (n_vert - 1))
+                                               {
+                                                       drawLine(arcStart, pvB[j], color);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (((!i) || (i == (n_hor - 1))) && ((!j) || (j == (n_vert - 1))))
+                                               {
+                                                       drawLine(center, pvB[j], color);
+                                               }
+                                       }
+                               }
+                       }
+                       pT = pvA;
+                       pvA = pvB;
+                       pvB = pT;
+               }
+       }
+
+       virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color)
+       {
+               drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
+               drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
+               drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
+               drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
+               drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+               drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+               drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+               drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+               drawLine(btVector3(bbMin[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+               drawLine(btVector3(bbMax[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+               drawLine(btVector3(bbMax[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+               drawLine(btVector3(bbMin[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+       }
+       virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color)
+       {
+               drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
+               drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
+               drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
+               drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
+               drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+               drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+               drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+               drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+               drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+               drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+               drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+               drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+       }
+
+       virtual void drawCapsule(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
+       {
+               int stepDegrees = 30;
+
+               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 = transform;
+                       childTransform.getOrigin() = transform * capStart;
+                       {
+                               btVector3 center = childTransform.getOrigin();
+                               btVector3 up = childTransform.getBasis().getColumn((upAxis + 1) % 3);
+                               btVector3 axis = -childTransform.getBasis().getColumn(upAxis);
+                               btScalar minTh = -SIMD_HALF_PI;
+                               btScalar maxTh = SIMD_HALF_PI;
+                               btScalar minPs = -SIMD_HALF_PI;
+                               btScalar maxPs = SIMD_HALF_PI;
+
+                               drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees), false);
+                       }
+               }
+
+               {
+                       btTransform childTransform = transform;
+                       childTransform.getOrigin() = transform * capEnd;
+                       {
+                               btVector3 center = childTransform.getOrigin();
+                               btVector3 up = childTransform.getBasis().getColumn((upAxis + 1) % 3);
+                               btVector3 axis = childTransform.getBasis().getColumn(upAxis);
+                               btScalar minTh = -SIMD_HALF_PI;
+                               btScalar maxTh = SIMD_HALF_PI;
+                               btScalar minPs = -SIMD_HALF_PI;
+                               btScalar maxPs = SIMD_HALF_PI;
+                               drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees), false);
+                       }
+               }
+
+               // Draw some additional lines
+               btVector3 start = transform.getOrigin();
+
+               for (int i = 0; i < 360; i += stepDegrees)
+               {
+                       capEnd[(upAxis + 1) % 3] = capStart[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+                       capEnd[(upAxis + 2) % 3] = capStart[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+                       drawLine(start + transform.getBasis() * capStart, start + transform.getBasis() * capEnd, color);
+               }
+       }
+
+       virtual void drawCylinder(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
+       {
+               btVector3 start = transform.getOrigin();
+               btVector3 offsetHeight(0, 0, 0);
+               offsetHeight[upAxis] = halfHeight;
+               int stepDegrees = 30;
+               btVector3 capStart(0.f, 0.f, 0.f);
+               capStart[upAxis] = -halfHeight;
+               btVector3 capEnd(0.f, 0.f, 0.f);
+               capEnd[upAxis] = halfHeight;
+
+               for (int i = 0; i < 360; i += stepDegrees)
+               {
+                       capEnd[(upAxis + 1) % 3] = capStart[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+                       capEnd[(upAxis + 2) % 3] = capStart[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+                       drawLine(start + transform.getBasis() * capStart, start + transform.getBasis() * capEnd, color);
+               }
+               // Drawing top and bottom caps of the cylinder
+               btVector3 yaxis(0, 0, 0);
+               yaxis[upAxis] = btScalar(1.0);
+               btVector3 xaxis(0, 0, 0);
+               xaxis[(upAxis + 1) % 3] = btScalar(1.0);
+               drawArc(start - transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, btScalar(10.0));
+               drawArc(start + transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, btScalar(10.0));
+       }
+
+       virtual void drawCone(btScalar radius, btScalar height, int upAxis, const btTransform& transform, const btVector3& color)
+       {
+               int stepDegrees = 30;
+               btVector3 start = transform.getOrigin();
+
+               btVector3 offsetHeight(0, 0, 0);
+               btScalar halfHeight = height * btScalar(0.5);
+               offsetHeight[upAxis] = halfHeight;
+               btVector3 offsetRadius(0, 0, 0);
+               offsetRadius[(upAxis + 1) % 3] = radius;
+               btVector3 offset2Radius(0, 0, 0);
+               offset2Radius[(upAxis + 2) % 3] = radius;
+
+               btVector3 capEnd(0.f, 0.f, 0.f);
+               capEnd[upAxis] = -halfHeight;
+
+               for (int i = 0; i < 360; i += stepDegrees)
+               {
+                       capEnd[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+                       capEnd[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
+                       drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * capEnd, color);
+               }
+
+               drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight + offsetRadius), color);
+               drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight - offsetRadius), color);
+               drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight + offset2Radius), color);
+               drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight - offset2Radius), color);
+
+               // Drawing the base of the cone
+               btVector3 yaxis(0, 0, 0);
+               yaxis[upAxis] = btScalar(1.0);
+               btVector3 xaxis(0, 0, 0);
+               xaxis[(upAxis + 1) % 3] = btScalar(1.0);
+               drawArc(start - transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
+       }
+
+       virtual void drawPlane(const btVector3& planeNormal, btScalar planeConst, const btTransform& transform, const btVector3& color)
+       {
+               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;
+               drawLine(transform * pt0, transform * pt1, color);
+               drawLine(transform * pt2, transform * pt3, color);
+       }
+
+       virtual void clearLines()
+       {
+       }
+
+       virtual void flushLines()
+       {
+       }
+};
+
+#endif  //BT_IDEBUG_DRAW__H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btImplicitQRSVD.h b/dali-physics/third-party/bullet3/src/LinearMath/btImplicitQRSVD.h
new file mode 100644 (file)
index 0000000..aaedc96
--- /dev/null
@@ -0,0 +1,916 @@
+/**
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 Google Inc. http://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ Copyright (c) 2016 Theodore Gast, Chuyuan Fu, Chenfanfu Jiang, Joseph Teran
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is furnished to do
+ so, subject to the following conditions:
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+ If the code is used in an article, the following paper shall be cited:
+ @techreport{qrsvd:2016,
+ title={Implicit-shifted Symmetric QR Singular Value Decomposition of 3x3 Matrices},
+ author={Gast, Theodore and Fu, Chuyuan and Jiang, Chenfanfu and Teran, Joseph},
+ year={2016},
+ institution={University of California Los Angeles}
+ }
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+**/
+
+#ifndef btImplicitQRSVD_h
+#define btImplicitQRSVD_h
+#include <limits>
+#include "btMatrix3x3.h"
+class btMatrix2x2
+{
+public:
+    btScalar m_00, m_01, m_10, m_11;
+    btMatrix2x2(): m_00(0), m_10(0), m_01(0), m_11(0)
+    {
+    }
+    btMatrix2x2(const btMatrix2x2& other): m_00(other.m_00),m_01(other.m_01),m_10(other.m_10),m_11(other.m_11)
+    {}
+    btScalar& operator()(int i, int j)
+    {
+        if (i == 0 && j == 0)
+            return m_00;
+        if (i == 1 && j == 0)
+            return m_10;
+        if (i == 0 && j == 1)
+            return m_01;
+        if (i == 1 && j == 1)
+            return m_11;
+        btAssert(false);
+        return m_00;
+    }
+    const btScalar& operator()(int i, int j) const
+    {
+        if (i == 0 && j == 0)
+            return m_00;
+        if (i == 1 && j == 0)
+            return m_10;
+        if (i == 0 && j == 1)
+            return m_01;
+        if (i == 1 && j == 1)
+            return m_11;
+        btAssert(false);
+        return m_00;
+    }
+    void setIdentity()
+    {
+        m_00 = 1;
+        m_11 = 1;
+        m_01 = 0;
+        m_10 = 0;
+    }
+};
+
+static inline btScalar copySign(btScalar x, btScalar y) {
+    if ((x < 0 && y > 0) || (x > 0 && y < 0))
+        return -x;
+    return x;
+}
+
+/**
+ Class for givens rotation.
+ Row rotation G*A corresponds to something like
+ c -s  0
+ ( s  c  0 ) A
+ 0  0  1
+ Column rotation A G' corresponds to something like
+ c -s  0
+ A ( s  c  0 )
+ 0  0  1
+ c and s are always computed so that
+ ( c -s ) ( a )  =  ( * )
+ s  c     b       ( 0 )
+ Assume rowi<rowk.
+ */
+
+class GivensRotation {
+public:
+    int rowi;
+    int rowk;
+    btScalar c;
+    btScalar s;
+    
+    inline GivensRotation(int rowi_in, int rowk_in)
+    : rowi(rowi_in)
+    , rowk(rowk_in)
+    , c(1)
+    , s(0)
+    {
+    }
+    
+    inline GivensRotation(btScalar a, btScalar b, int rowi_in, int rowk_in)
+    : rowi(rowi_in)
+    , rowk(rowk_in)
+    {
+        compute(a, b);
+    }
+    
+    ~GivensRotation() {}
+    
+    inline void transposeInPlace()
+    {
+        s = -s;
+    }
+    
+    /**
+     Compute c and s from a and b so that
+     ( c -s ) ( a )  =  ( * )
+     s  c     b       ( 0 )
+     */
+    inline void compute(const btScalar a, const btScalar b)
+    {
+        btScalar d = a * a + b * b;
+        c = 1;
+        s = 0;
+        if (d > SIMD_EPSILON) {
+            btScalar sqrtd = btSqrt(d);
+            if (sqrtd>SIMD_EPSILON)
+            {
+              btScalar t = btScalar(1.0)/sqrtd;
+              c = a * t;
+              s = -b * t;
+            }
+        }
+    }
+    
+    /**
+     This function computes c and s so that
+     ( c -s ) ( a )  =  ( 0 )
+     s  c     b       ( * )
+     */
+    inline void computeUnconventional(const btScalar a, const btScalar b)
+    {
+        btScalar d = a * a + b * b;
+        c = 0;
+        s = 1;
+        if (d > SIMD_EPSILON) {
+            btScalar t = btScalar(1.0)/btSqrt(d);
+            s = a * t;
+            c = b * t;
+        }
+    }
+    /**
+     Fill the R with the entries of this rotation
+     */
+    inline void fill(const btMatrix3x3& R) const
+    {
+        btMatrix3x3& A = const_cast<btMatrix3x3&>(R);
+        A.setIdentity();
+        A[rowi][rowi] = c;
+        A[rowk][rowi] = -s;
+        A[rowi][rowk] = s;
+        A[rowk][rowk] = c;
+    }
+    
+    inline void fill(const btMatrix2x2& R) const
+    {
+        btMatrix2x2& A = const_cast<btMatrix2x2&>(R);
+        A(rowi,rowi) = c;
+        A(rowk,rowi) = -s;
+        A(rowi,rowk) = s;
+        A(rowk,rowk) = c;
+    }
+    
+    /**
+     This function does something like
+     c -s  0
+     ( s  c  0 ) A -> A
+     0  0  1
+     It only affects row i and row k of A.
+     */
+    inline void rowRotation(btMatrix3x3& A) const
+    {
+        for (int j = 0; j < 3; j++) {
+            btScalar tau1 = A[rowi][j];
+            btScalar tau2 = A[rowk][j];
+            A[rowi][j] = c * tau1 - s * tau2;
+            A[rowk][j] = s * tau1 + c * tau2;
+        }
+    }
+    inline void rowRotation(btMatrix2x2& A) const
+    {
+        for (int j = 0; j < 2; j++) {
+            btScalar tau1 = A(rowi,j);
+            btScalar tau2 = A(rowk,j);
+            A(rowi,j) = c * tau1 - s * tau2;
+            A(rowk,j) = s * tau1 + c * tau2;
+        }
+    }
+    
+    /**
+     This function does something like
+     c  s  0
+     A ( -s  c  0 )  -> A
+     0  0  1
+     It only affects column i and column k of A.
+     */
+    inline void columnRotation(btMatrix3x3& A) const
+    {
+        for (int j = 0; j < 3; j++) {
+            btScalar tau1 = A[j][rowi];
+            btScalar tau2 = A[j][rowk];
+            A[j][rowi] = c * tau1 - s * tau2;
+            A[j][rowk] = s * tau1 + c * tau2;
+        }
+    }
+    inline void columnRotation(btMatrix2x2& A) const
+    {
+        for (int j = 0; j < 2; j++) {
+            btScalar tau1 = A(j,rowi);
+            btScalar tau2 = A(j,rowk);
+            A(j,rowi) = c * tau1 - s * tau2;
+            A(j,rowk) = s * tau1 + c * tau2;
+        }
+    }
+    
+    /**
+     Multiply givens must be for same row and column
+     **/
+    inline void operator*=(const GivensRotation& A)
+    {
+        btScalar new_c = c * A.c - s * A.s;
+        btScalar new_s = s * A.c + c * A.s;
+        c = new_c;
+        s = new_s;
+    }
+    
+    /**
+     Multiply givens must be for same row and column
+     **/
+    inline GivensRotation operator*(const GivensRotation& A) const
+    {
+        GivensRotation r(*this);
+        r *= A;
+        return r;
+    }
+};
+
+/**
+ \brief zero chasing the 3X3 matrix to bidiagonal form
+ original form of H:   x x 0
+ x x x
+ 0 0 x
+ after zero chase:
+ x x 0
+ 0 x x
+ 0 0 x
+ */
+inline void zeroChase(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
+{
+    
+    /**
+     Reduce H to of form
+     x x +
+     0 x x
+     0 0 x
+     */
+    GivensRotation r1(H[0][0], H[1][0], 0, 1);
+    /**
+     Reduce H to of form
+     x x 0
+     0 x x
+     0 + x
+     Can calculate r2 without multiplying by r1 since both entries are in first two
+     rows thus no need to divide by sqrt(a^2+b^2)
+     */
+    GivensRotation r2(1, 2);
+    if (H[1][0] != 0)
+        r2.compute(H[0][0] * H[0][1] + H[1][0] * H[1][1], H[0][0] * H[0][2] + H[1][0] * H[1][2]);
+    else
+        r2.compute(H[0][1], H[0][2]);
+    
+    r1.rowRotation(H);
+    
+    /* GivensRotation<T> r2(H(0, 1), H(0, 2), 1, 2); */
+    r2.columnRotation(H);
+    r2.columnRotation(V);
+    
+    /**
+     Reduce H to of form
+     x x 0
+     0 x x
+     0 0 x
+     */
+    GivensRotation r3(H[1][1], H[2][1], 1, 2);
+    r3.rowRotation(H);
+    
+    // Save this till end for better cache coherency
+    // r1.rowRotation(u_transpose);
+    // r3.rowRotation(u_transpose);
+    r1.columnRotation(U);
+    r3.columnRotation(U);
+}
+
+/**
+ \brief make a 3X3 matrix to upper bidiagonal form
+ original form of H:   x x x
+ x x x
+ x x x
+ after zero chase:
+ x x 0
+ 0 x x
+ 0 0 x
+ */
+inline void makeUpperBidiag(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
+{
+    U.setIdentity();
+    V.setIdentity();
+    
+    /**
+     Reduce H to of form
+     x x x
+     x x x
+     0 x x
+     */
+    
+    GivensRotation r(H[1][0], H[2][0], 1, 2);
+    r.rowRotation(H);
+    // r.rowRotation(u_transpose);
+    r.columnRotation(U);
+    // zeroChase(H, u_transpose, V);
+    zeroChase(H, U, V);
+}
+
+/**
+ \brief make a 3X3 matrix to lambda shape
+ original form of H:   x x x
+ *                     x x x
+ *                     x x x
+ after :
+ *                     x 0 0
+ *                     x x 0
+ *                     x 0 x
+ */
+inline void makeLambdaShape(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
+{
+    U.setIdentity();
+    V.setIdentity();
+    
+    /**
+     Reduce H to of form
+     *                    x x 0
+     *                    x x x
+     *                    x x x
+     */
+    
+    GivensRotation r1(H[0][1], H[0][2], 1, 2);
+    r1.columnRotation(H);
+    r1.columnRotation(V);
+    
+    /**
+     Reduce H to of form
+     *                    x x 0
+     *                    x x 0
+     *                    x x x
+     */
+    
+    r1.computeUnconventional(H[1][2], H[2][2]);
+    r1.rowRotation(H);
+    r1.columnRotation(U);
+    
+    /**
+     Reduce H to of form
+     *                    x x 0
+     *                    x x 0
+     *                    x 0 x
+     */
+    
+    GivensRotation r2(H[2][0], H[2][1], 0, 1);
+    r2.columnRotation(H);
+    r2.columnRotation(V);
+    
+    /**
+     Reduce H to of form
+     *                    x 0 0
+     *                    x x 0
+     *                    x 0 x
+     */
+    r2.computeUnconventional(H[0][1], H[1][1]);
+    r2.rowRotation(H);
+    r2.columnRotation(U);
+}
+
+/**
+ \brief 2x2 polar decomposition.
+ \param[in] A matrix.
+ \param[out] R Robustly a rotation matrix.
+ \param[out] S_Sym Symmetric. Whole matrix is stored
+ Polar guarantees negative sign is on the small magnitude singular value.
+ S is guaranteed to be the closest one to identity.
+ R is guaranteed to be the closest rotation to A.
+ */
+inline void polarDecomposition(const btMatrix2x2& A,
+                   GivensRotation& R,
+                   const btMatrix2x2& S_Sym)
+{
+    btScalar a = (A(0, 0) + A(1, 1)),  b = (A(1, 0) - A(0, 1));
+    btScalar denominator = btSqrt(a*a+b*b);
+    R.c = (btScalar)1;
+    R.s = (btScalar)0;
+    if (denominator > SIMD_EPSILON) { 
+        /*
+         No need to use a tolerance here because x(0) and x(1) always have
+         smaller magnitude then denominator, therefore overflow never happens.
+         In Bullet, we use a tolerance anyway.
+         */
+        R.c = a / denominator;
+        R.s = -b / denominator;
+    }
+    btMatrix2x2& S = const_cast<btMatrix2x2&>(S_Sym);
+    S = A;
+    R.rowRotation(S);
+}
+
+inline void polarDecomposition(const btMatrix2x2& A,
+                   const btMatrix2x2& R,
+                   const btMatrix2x2& S_Sym)
+{
+    GivensRotation r(0, 1);
+    polarDecomposition(A, r, S_Sym);
+    r.fill(R);
+}
+
+/**
+ \brief 2x2 SVD (singular value decomposition) A=USV'
+ \param[in] A Input matrix.
+ \param[out] U Robustly a rotation matrix in Givens form
+ \param[out] Sigma matrix of singular values sorted with decreasing magnitude. The second one can be negative.
+ \param[out] V Robustly a rotation matrix in Givens form
+ */
+inline void singularValueDecomposition(
+                           const btMatrix2x2& A,
+                           GivensRotation& U,
+                           const btMatrix2x2& Sigma,
+                           GivensRotation& V,
+                           const btScalar tol = 64 * std::numeric_limits<btScalar>::epsilon())
+{
+    btMatrix2x2& sigma = const_cast<btMatrix2x2&>(Sigma);
+    sigma.setIdentity();
+    btMatrix2x2 S_Sym;
+    polarDecomposition(A, U, S_Sym);
+    btScalar cosine, sine;
+    btScalar x = S_Sym(0, 0);
+    btScalar y = S_Sym(0, 1);
+    btScalar z = S_Sym(1, 1);
+    if (y == 0) {
+        // S is already diagonal
+        cosine = 1;
+        sine = 0;
+        sigma(0,0) = x;
+        sigma(1,1) = z;
+    }
+    else {
+        btScalar tau = 0.5 * (x - z);
+        btScalar val = tau * tau + y * y;
+        if (val > SIMD_EPSILON)
+        {
+        btScalar w = btSqrt(val);
+        // w > y > 0
+        btScalar t;
+        if (tau > 0) {
+            // tau + w > w > y > 0 ==> division is safe
+            t = y / (tau + w);
+        }
+        else {
+            // tau - w < -w < -y < 0 ==> division is safe
+            t = y / (tau - w);
+        }
+        cosine = btScalar(1) / btSqrt(t * t + btScalar(1));
+        sine = -t * cosine;
+        /*
+         V = [cosine -sine; sine cosine]
+         Sigma = V'SV. Only compute the diagonals for efficiency.
+         Also utilize symmetry of S and don't form V yet.
+         */
+        btScalar c2 = cosine * cosine;
+        btScalar csy = 2 * cosine * sine * y;
+        btScalar s2 = sine * sine;
+        sigma(0,0) = c2 * x - csy + s2 * z;
+        sigma(1,1) = s2 * x + csy + c2 * z;
+      } else
+       {
+               cosine = 1;
+        sine = 0;
+        sigma(0,0) = x;
+        sigma(1,1) = z;
+       }
+    }
+    
+    // Sorting
+    // Polar already guarantees negative sign is on the small magnitude singular value.
+    if (sigma(0,0) < sigma(1,1)) {
+        std::swap(sigma(0,0), sigma(1,1));
+        V.c = -sine;
+        V.s = cosine;
+    }
+    else {
+        V.c = cosine;
+        V.s = sine;
+    }
+    U *= V;
+}
+
+/**
+ \brief 2x2 SVD (singular value decomposition) A=USV'
+ \param[in] A Input matrix.
+ \param[out] U Robustly a rotation matrix.
+ \param[out] Sigma Vector of singular values sorted with decreasing magnitude. The second one can be negative.
+ \param[out] V Robustly a rotation matrix.
+ */
+inline void singularValueDecomposition(
+                           const btMatrix2x2& A,
+                           const btMatrix2x2& U,
+                           const btMatrix2x2& Sigma,
+                           const btMatrix2x2& V,
+                           const btScalar tol = 64 * std::numeric_limits<btScalar>::epsilon())
+{
+    GivensRotation gv(0, 1);
+    GivensRotation gu(0, 1);
+    singularValueDecomposition(A, gu, Sigma, gv);
+    
+    gu.fill(U);
+    gv.fill(V);
+}
+
+/**
+ \brief compute wilkinsonShift of the block
+ a1     b1
+ b1     a2
+ based on the wilkinsonShift formula
+ mu = c + d - sign (d) \ sqrt (d*d + b*b), where d = (a-c)/2
+ */
+inline btScalar wilkinsonShift(const btScalar a1, const btScalar b1, const btScalar a2)
+{
+       btScalar d = (btScalar)0.5 * (a1 - a2);
+       btScalar bs = b1 * b1;
+       btScalar val = d * d + bs;
+       if (val>SIMD_EPSILON)
+       {
+               btScalar denom = btFabs(d) + btSqrt(val);
+
+               btScalar mu = a2 - copySign(bs / (denom), d);
+               // T mu = a2 - bs / ( d + sign_d*sqrt (d*d + bs));
+               return mu;
+       }
+       return a2;
+}
+
+/**
+ \brief Helper function of 3X3 SVD for processing 2X2 SVD
+ */
+template <int t>
+inline void process(btMatrix3x3& B, btMatrix3x3& U, btVector3& sigma, btMatrix3x3& V)
+{
+    int other = (t == 1) ? 0 : 2;
+    GivensRotation u(0, 1);
+    GivensRotation v(0, 1);
+    sigma[other] = B[other][other];
+    
+    btMatrix2x2 B_sub, sigma_sub;
+    if (t == 0)
+    {
+        B_sub.m_00 = B[0][0];
+        B_sub.m_10 = B[1][0];
+        B_sub.m_01 = B[0][1];
+        B_sub.m_11 = B[1][1];
+        sigma_sub.m_00 = sigma[0];
+        sigma_sub.m_11 = sigma[1];
+//        singularValueDecomposition(B.template block<2, 2>(t, t), u, sigma.template block<2, 1>(t, 0), v);
+        singularValueDecomposition(B_sub, u, sigma_sub, v);
+        B[0][0] = B_sub.m_00;
+        B[1][0] = B_sub.m_10;
+        B[0][1] = B_sub.m_01;
+        B[1][1] = B_sub.m_11;
+        sigma[0] = sigma_sub.m_00;
+        sigma[1] = sigma_sub.m_11;
+    }
+    else
+    {
+        B_sub.m_00 = B[1][1];
+        B_sub.m_10 = B[2][1];
+        B_sub.m_01 = B[1][2];
+        B_sub.m_11 = B[2][2];
+        sigma_sub.m_00 = sigma[1];
+        sigma_sub.m_11 = sigma[2];
+        //        singularValueDecomposition(B.template block<2, 2>(t, t), u, sigma.template block<2, 1>(t, 0), v);
+        singularValueDecomposition(B_sub, u, sigma_sub, v);
+        B[1][1] = B_sub.m_00;
+        B[2][1] = B_sub.m_10;
+        B[1][2] = B_sub.m_01;
+        B[2][2] = B_sub.m_11;
+        sigma[1] = sigma_sub.m_00;
+        sigma[2] = sigma_sub.m_11;
+    }
+    u.rowi += t;
+    u.rowk += t;
+    v.rowi += t;
+    v.rowk += t;
+    u.columnRotation(U);
+    v.columnRotation(V);
+}
+
+/**
+ \brief Helper function of 3X3 SVD for flipping signs due to flipping signs of sigma
+ */
+inline void flipSign(int i, btMatrix3x3& U, btVector3& sigma)
+{
+    sigma[i] = -sigma[i];
+    U[0][i] = -U[0][i];
+    U[1][i] = -U[1][i];
+    U[2][i] = -U[2][i];
+}
+
+inline void flipSign(int i, btMatrix3x3& U)
+{
+    U[0][i] = -U[0][i];
+    U[1][i] = -U[1][i];
+    U[2][i] = -U[2][i];
+}
+
+inline void swapCol(btMatrix3x3& A, int i, int j)
+{
+    for (int d = 0; d < 3; ++d)
+        std::swap(A[d][i], A[d][j]);
+}
+/**
+ \brief Helper function of 3X3 SVD for sorting singular values
+ */
+inline void sort(btMatrix3x3& U, btVector3& sigma, btMatrix3x3& V, int t)
+{
+    if (t == 0)
+    {
+        // Case: sigma(0) > |sigma(1)| >= |sigma(2)|
+        if (btFabs(sigma[1]) >= btFabs(sigma[2])) {
+            if (sigma[1] < 0) {
+                flipSign(1, U, sigma);
+                flipSign(2, U, sigma);
+            }
+            return;
+        }
+        
+        //fix sign of sigma for both cases
+        if (sigma[2] < 0) {
+            flipSign(1, U, sigma);
+            flipSign(2, U, sigma);
+        }
+        
+        //swap sigma(1) and sigma(2) for both cases
+        std::swap(sigma[1], sigma[2]);
+        // swap the col 1 and col 2 for U,V
+        swapCol(U,1,2);
+        swapCol(V,1,2);
+        
+        // Case: |sigma(2)| >= sigma(0) > |simga(1)|
+        if (sigma[1] > sigma[0]) {
+            std::swap(sigma[0], sigma[1]);
+            swapCol(U,0,1);
+            swapCol(V,0,1);
+        }
+        
+        // Case: sigma(0) >= |sigma(2)| > |simga(1)|
+        else {
+            flipSign(2, U);
+            flipSign(2, V);
+        }
+    }
+    else if (t == 1)
+    {
+        // Case: |sigma(0)| >= sigma(1) > |sigma(2)|
+        if (btFabs(sigma[0]) >= sigma[1]) {
+            if (sigma[0] < 0) {
+                flipSign(0, U, sigma);
+                flipSign(2, U, sigma);
+            }
+            return;
+        }
+        
+        //swap sigma(0) and sigma(1) for both cases
+        std::swap(sigma[0], sigma[1]);
+        swapCol(U, 0, 1);
+        swapCol(V, 0, 1);
+        
+        // Case: sigma(1) > |sigma(2)| >= |sigma(0)|
+        if (btFabs(sigma[1]) < btFabs(sigma[2])) {
+            std::swap(sigma[1], sigma[2]);
+            swapCol(U, 1, 2);
+            swapCol(V, 1, 2);
+        }
+        
+        // Case: sigma(1) >= |sigma(0)| > |sigma(2)|
+        else {
+            flipSign(1, U);
+            flipSign(1, V);
+        }
+        
+        // fix sign for both cases
+        if (sigma[1] < 0) {
+            flipSign(1, U, sigma);
+            flipSign(2, U, sigma);
+        }
+    }
+}
+
+/**
+ \brief 3X3 SVD (singular value decomposition) A=USV'
+ \param[in] A Input matrix.
+ \param[out] U is a rotation matrix.
+ \param[out] sigma Diagonal matrix, sorted with decreasing magnitude. The third one can be negative.
+ \param[out] V is a rotation matrix.
+ */
+inline int singularValueDecomposition(const btMatrix3x3& A,
+                                     btMatrix3x3& U,
+                                     btVector3& sigma,
+                                     btMatrix3x3& V,
+                                     btScalar tol = 128*std::numeric_limits<btScalar>::epsilon())
+{
+//    using std::fabs;
+    btMatrix3x3 B = A;
+    U.setIdentity();
+    V.setIdentity();
+    
+    makeUpperBidiag(B, U, V);
+    
+    int count = 0;
+    btScalar mu = (btScalar)0;
+    GivensRotation r(0, 1);
+    
+    btScalar alpha_1 = B[0][0];
+    btScalar beta_1 = B[0][1];
+    btScalar alpha_2 = B[1][1];
+    btScalar alpha_3 = B[2][2];
+    btScalar beta_2 = B[1][2];
+    btScalar gamma_1 = alpha_1 * beta_1;
+    btScalar gamma_2 = alpha_2 * beta_2;
+    btScalar val = alpha_1 * alpha_1 + alpha_2 * alpha_2 + alpha_3 * alpha_3 + beta_1 * beta_1 + beta_2 * beta_2;
+    if (val > SIMD_EPSILON)
+    {
+           tol *= btMax((btScalar)0.5 * btSqrt(val), (btScalar)1);
+               }    
+    /**
+     Do implicit shift QR until A^T A is block diagonal
+     */
+    int max_count = 100;
+    
+    while (btFabs(beta_2) > tol && btFabs(beta_1) > tol
+           && btFabs(alpha_1) > tol && btFabs(alpha_2) > tol
+           && btFabs(alpha_3) > tol
+           && count < max_count) {
+        mu = wilkinsonShift(alpha_2 * alpha_2 + beta_1 * beta_1, gamma_2, alpha_3 * alpha_3 + beta_2 * beta_2);
+        
+        r.compute(alpha_1 * alpha_1 - mu, gamma_1);
+        r.columnRotation(B);
+        
+        r.columnRotation(V);
+        zeroChase(B, U, V);
+        
+        alpha_1 = B[0][0];
+        beta_1 = B[0][1];
+        alpha_2 = B[1][1];
+        alpha_3 = B[2][2];
+        beta_2 = B[1][2];
+        gamma_1 = alpha_1 * beta_1;
+        gamma_2 = alpha_2 * beta_2;
+        count++;
+    }
+    /**
+     Handle the cases of one of the alphas and betas being 0
+     Sorted by ease of handling and then frequency
+     of occurrence
+     
+     If B is of form
+     x x 0
+     0 x 0
+     0 0 x
+     */
+    if (btFabs(beta_2) <= tol) {
+        process<0>(B, U, sigma, V);
+        sort(U, sigma, V,0);
+    }
+    /**
+     If B is of form
+     x 0 0
+     0 x x
+     0 0 x
+     */
+    else if (btFabs(beta_1) <= tol) {
+        process<1>(B, U, sigma, V);
+        sort(U, sigma, V,1);
+    }
+    /**
+     If B is of form
+     x x 0
+     0 0 x
+     0 0 x
+     */
+    else if (btFabs(alpha_2) <= tol) {
+        /**
+         Reduce B to
+         x x 0
+         0 0 0
+         0 0 x
+         */
+        GivensRotation r1(1, 2);
+        r1.computeUnconventional(B[1][2], B[2][2]);
+        r1.rowRotation(B);
+        r1.columnRotation(U);
+        
+        process<0>(B, U, sigma, V);
+        sort(U, sigma, V, 0);
+    }
+    /**
+     If B is of form
+     x x 0
+     0 x x
+     0 0 0
+     */
+    else if (btFabs(alpha_3) <= tol) {
+        /**
+         Reduce B to
+         x x +
+         0 x 0
+         0 0 0
+         */
+        GivensRotation r1(1, 2);
+        r1.compute(B[1][1], B[1][2]);
+        r1.columnRotation(B);
+        r1.columnRotation(V);
+        /**
+         Reduce B to
+         x x 0
+         + x 0
+         0 0 0
+         */
+        GivensRotation r2(0, 2);
+        r2.compute(B[0][0], B[0][2]);
+        r2.columnRotation(B);
+        r2.columnRotation(V);
+        
+        process<0>(B, U, sigma, V);
+        sort(U, sigma, V, 0);
+    }
+    /**
+     If B is of form
+     0 x 0
+     0 x x
+     0 0 x
+     */
+    else if (btFabs(alpha_1) <= tol) {
+        /**
+         Reduce B to
+         0 0 +
+         0 x x
+         0 0 x
+         */
+        GivensRotation r1(0, 1);
+        r1.computeUnconventional(B[0][1], B[1][1]);
+        r1.rowRotation(B);
+        r1.columnRotation(U);
+        
+        /**
+         Reduce B to
+         0 0 0
+         0 x x
+         0 + x
+         */
+        GivensRotation r2(0, 2);
+        r2.computeUnconventional(B[0][2], B[2][2]);
+        r2.rowRotation(B);
+        r2.columnRotation(U);
+        
+        process<1>(B, U, sigma, V);
+        sort(U, sigma, V, 1);
+    }
+    
+    return count;
+}
+#endif /* btImplicitQRSVD_h */
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btList.h b/dali-physics/third-party/bullet3/src/LinearMath/btList.h
new file mode 100644 (file)
index 0000000..9072abc
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_GEN_LIST_H
+#define BT_GEN_LIST_H
+
+class btGEN_Link
+{
+public:
+       btGEN_Link() : m_next(0), m_prev(0) {}
+       btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {}
+
+       btGEN_Link *getNext() const { return m_next; }
+       btGEN_Link *getPrev() const { return m_prev; }
+
+       bool isHead() const { return m_prev == 0; }
+       bool isTail() const { return m_next == 0; }
+
+       void insertBefore(btGEN_Link *link)
+       {
+               m_next = link;
+               m_prev = link->m_prev;
+               m_next->m_prev = this;
+               m_prev->m_next = this;
+       }
+
+       void insertAfter(btGEN_Link *link)
+       {
+               m_next = link->m_next;
+               m_prev = link;
+               m_next->m_prev = this;
+               m_prev->m_next = this;
+       }
+
+       void remove()
+       {
+               m_next->m_prev = m_prev;
+               m_prev->m_next = m_next;
+       }
+
+private:
+       btGEN_Link *m_next;
+       btGEN_Link *m_prev;
+};
+
+class btGEN_List
+{
+public:
+       btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
+
+       btGEN_Link *getHead() const { return m_head.getNext(); }
+       btGEN_Link *getTail() const { return m_tail.getPrev(); }
+
+       void addHead(btGEN_Link *link) { link->insertAfter(&m_head); }
+       void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); }
+
+private:
+       btGEN_Link m_head;
+       btGEN_Link m_tail;
+};
+
+#endif  //BT_GEN_LIST_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btMatrix3x3.h b/dali-physics/third-party/bullet3/src/LinearMath/btMatrix3x3.h
new file mode 100644 (file)
index 0000000..4391a52
--- /dev/null
@@ -0,0 +1,1431 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_MATRIX3x3_H
+#define BT_MATRIX3x3_H
+
+#include "btVector3.h"
+#include "btQuaternion.h"
+#include <stdio.h>
+
+#ifdef BT_USE_SSE
+//const __m128 ATTRIBUTE_ALIGNED16(v2220) = {2.0f, 2.0f, 2.0f, 0.0f};
+//const __m128 ATTRIBUTE_ALIGNED16(vMPPP) = {-0.0f, +0.0f, +0.0f, +0.0f};
+#define vMPPP (_mm_set_ps(+0.0f, +0.0f, +0.0f, -0.0f))
+#endif
+
+#if defined(BT_USE_SSE)
+#define v0000 (_mm_set_ps(0.0f, 0.0f, 0.0f, 0.0f))
+#define v1000 (_mm_set_ps(0.0f, 0.0f, 0.0f, 1.0f))
+#define v0100 (_mm_set_ps(0.0f, 0.0f, 1.0f, 0.0f))
+#define v0010 (_mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f))
+#elif defined(BT_USE_NEON)
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0000) = {0.0f, 0.0f, 0.0f, 0.0f};
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
+#endif
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btMatrix3x3Data btMatrix3x3DoubleData
+#else
+#define btMatrix3x3Data btMatrix3x3FloatData
+#endif  //BT_USE_DOUBLE_PRECISION
+
+/**@brief 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. */
+ATTRIBUTE_ALIGNED16(class)
+btMatrix3x3
+{
+       ///Data storage for the matrix, each vector is a row of the matrix
+       btVector3 m_el[3];
+
+public:
+       /** @brief No initializaion constructor */
+       btMatrix3x3() {}
+
+       //              explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); }
+
+       /**@brief Constructor from Quaternion */
+       explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); }
+       /*
+       template <typename btScalar>
+       Matrix3x3(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+       { 
+       setEulerYPR(yaw, pitch, roll);
+       }
+       */
+       /** @brief Constructor with row major formatting */
+       btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz,
+                               const btScalar& yx, const btScalar& yy, const btScalar& yz,
+                               const btScalar& zx, const btScalar& zy, const btScalar& zz)
+       {
+               setValue(xx, xy, xz,
+                                yx, yy, yz,
+                                zx, zy, zz);
+       }
+
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+       SIMD_FORCE_INLINE btMatrix3x3(const btSimdFloat4 v0, const btSimdFloat4 v1, const btSimdFloat4 v2)
+       {
+               m_el[0].mVec128 = v0;
+               m_el[1].mVec128 = v1;
+               m_el[2].mVec128 = v2;
+       }
+
+       SIMD_FORCE_INLINE btMatrix3x3(const btVector3& v0, const btVector3& v1, const btVector3& v2)
+       {
+               m_el[0] = v0;
+               m_el[1] = v1;
+               m_el[2] = v2;
+       }
+
+       // Copy constructor
+       SIMD_FORCE_INLINE btMatrix3x3(const btMatrix3x3& rhs)
+       {
+               m_el[0].mVec128 = rhs.m_el[0].mVec128;
+               m_el[1].mVec128 = rhs.m_el[1].mVec128;
+               m_el[2].mVec128 = rhs.m_el[2].mVec128;
+       }
+
+       // Assignment Operator
+       SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& m)
+       {
+               m_el[0].mVec128 = m.m_el[0].mVec128;
+               m_el[1].mVec128 = m.m_el[1].mVec128;
+               m_el[2].mVec128 = m.m_el[2].mVec128;
+
+               return *this;
+       }
+
+#else
+
+       /** @brief Copy constructor */
+       SIMD_FORCE_INLINE btMatrix3x3(const btMatrix3x3& other)
+       {
+               m_el[0] = other.m_el[0];
+               m_el[1] = other.m_el[1];
+               m_el[2] = other.m_el[2];
+       }
+
+       /** @brief Assignment Operator */
+       SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other)
+       {
+               m_el[0] = other.m_el[0];
+               m_el[1] = other.m_el[1];
+               m_el[2] = other.m_el[2];
+               return *this;
+       }
+    
+    SIMD_FORCE_INLINE btMatrix3x3(const btVector3& v0, const btVector3& v1, const btVector3& v2)
+    {
+        m_el[0] = v0;
+        m_el[1] = v1;
+        m_el[2] = v2;
+    }
+
+#endif
+
+       /** @brief Get a column of the matrix as a vector 
+       *  @param i Column number 0 indexed */
+       SIMD_FORCE_INLINE btVector3 getColumn(int i) const
+       {
+               return btVector3(m_el[0][i], m_el[1][i], m_el[2][i]);
+       }
+
+       /** @brief Get a row of the matrix as a vector 
+       *  @param i Row number 0 indexed */
+       SIMD_FORCE_INLINE const btVector3& getRow(int i) const
+       {
+               btFullAssert(0 <= i && i < 3);
+               return m_el[i];
+       }
+
+       /** @brief Get a mutable reference to a row of the matrix as a vector 
+       *  @param i Row number 0 indexed */
+       SIMD_FORCE_INLINE btVector3& operator[](int i)
+       {
+               btFullAssert(0 <= i && i < 3);
+               return m_el[i];
+       }
+
+       /** @brief Get a const reference to a row of the matrix as a vector 
+       *  @param i Row number 0 indexed */
+       SIMD_FORCE_INLINE const btVector3& operator[](int i) const
+       {
+               btFullAssert(0 <= i && i < 3);
+               return m_el[i];
+       }
+
+       /** @brief Multiply by the target matrix on the right
+       *  @param m Rotation matrix to be applied 
+       * Equivilant to this = this * m */
+       btMatrix3x3& operator*=(const btMatrix3x3& m);
+
+       /** @brief Adds by the target matrix on the right
+       *  @param m matrix to be applied 
+       * Equivilant to this = this + m */
+       btMatrix3x3& operator+=(const btMatrix3x3& m);
+
+       /** @brief Substractss by the target matrix on the right
+       *  @param m matrix to be applied 
+       * Equivilant to this = this - m */
+       btMatrix3x3& operator-=(const btMatrix3x3& m);
+
+       /** @brief Set from the rotational part of a 4x4 OpenGL matrix
+       *  @param m A pointer to the beginning of the array of scalars*/
+       void setFromOpenGLSubMatrix(const btScalar* m)
+       {
+               m_el[0].setValue(m[0], m[4], m[8]);
+               m_el[1].setValue(m[1], m[5], m[9]);
+               m_el[2].setValue(m[2], m[6], m[10]);
+       }
+       /** @brief Set the values of the matrix explicitly (row major)
+       *  @param xx Top left
+       *  @param xy Top Middle
+       *  @param xz Top Right
+       *  @param yx Middle Left
+       *  @param yy Middle Middle
+       *  @param yz Middle Right
+       *  @param zx Bottom Left
+       *  @param zy Bottom Middle
+       *  @param zz Bottom Right*/
+       void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz,
+                                 const btScalar& yx, const btScalar& yy, const btScalar& yz,
+                                 const btScalar& zx, const btScalar& zy, const btScalar& zz)
+       {
+               m_el[0].setValue(xx, xy, xz);
+               m_el[1].setValue(yx, yy, yz);
+               m_el[2].setValue(zx, zy, zz);
+       }
+
+       /** @brief Set the matrix from a quaternion
+       *  @param q The Quaternion to match */
+       void setRotation(const btQuaternion& q)
+       {
+               btScalar d = q.length2();
+               btFullAssert(d != btScalar(0.0));
+               btScalar s = btScalar(2.0) / d;
+
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 vs, Q = q.get128();
+               __m128i Qi = btCastfTo128i(Q);
+               __m128 Y, Z;
+               __m128 V1, V2, V3;
+               __m128 V11, V21, V31;
+               __m128 NQ = _mm_xor_ps(Q, btvMzeroMask);
+               __m128i NQi = btCastfTo128i(NQ);
+
+               V1 = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(1, 0, 2, 3)));  // Y X Z W
+               V2 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(0, 0, 1, 3));                 // -X -X  Y  W
+               V3 = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(2, 1, 0, 3)));  // Z Y X W
+               V1 = _mm_xor_ps(V1, vMPPP);                                         //  change the sign of the first element
+
+               V11 = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(1, 1, 0, 3)));  // Y Y X W
+               V21 = _mm_unpackhi_ps(Q, Q);                                         //  Z  Z  W  W
+               V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(0, 2, 0, 3));                 //  X  Z -X -W
+
+               V2 = V2 * V1;   //
+               V1 = V1 * V11;  //
+               V3 = V3 * V31;  //
+
+               V11 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(2, 3, 1, 3));                //  -Z -W  Y  W
+               V11 = V11 * V21;                                                    //
+               V21 = _mm_xor_ps(V21, vMPPP);                                       //  change the sign of the first element
+               V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(3, 3, 1, 3));                //   W  W -Y -W
+               V31 = _mm_xor_ps(V31, vMPPP);                                       //  change the sign of the first element
+               Y = btCastiTo128f(_mm_shuffle_epi32(NQi, BT_SHUFFLE(3, 2, 0, 3)));  // -W -Z -X -W
+               Z = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(1, 0, 1, 3)));   //  Y  X  Y  W
+
+               vs = _mm_load_ss(&s);
+               V21 = V21 * Y;
+               V31 = V31 * Z;
+
+               V1 = V1 + V11;
+               V2 = V2 + V21;
+               V3 = V3 + V31;
+
+               vs = bt_splat3_ps(vs, 0);
+               //      s ready
+               V1 = V1 * vs;
+               V2 = V2 * vs;
+               V3 = V3 * vs;
+
+               V1 = V1 + v1000;
+               V2 = V2 + v0100;
+               V3 = V3 + v0010;
+
+               m_el[0] = V1;
+               m_el[1] = V2;
+               m_el[2] = V3;
+#else
+               btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s;
+               btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs;
+               btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs;
+               btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs;
+               setValue(
+                       btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
+                       xy + wz, btScalar(1.0) - (xx + zz), yz - wx,
+                       xz - wy, yz + wx, btScalar(1.0) - (xx + yy));
+#endif
+       }
+
+       /** @brief Set the matrix from euler angles using YPR around YXZ respectively
+       *  @param yaw Yaw about Y axis
+       *  @param pitch Pitch about X axis
+       *  @param roll Roll about Z axis 
+       */
+       void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+       {
+               setEulerZYX(roll, pitch, yaw);
+       }
+
+       /** @brief Set the matrix from euler angles YPR around ZYX axes
+       * @param eulerX Roll about X axis
+       * @param eulerY Pitch around Y axis
+       * @param eulerZ Yaw about Z axis
+       * 
+       * These angles are used to produce a rotation matrix. The euler
+       * angles are applied in ZYX order. I.e a vector is first rotated 
+       * about X then Y and then Z
+       **/
+       void setEulerZYX(btScalar eulerX, btScalar eulerY, btScalar eulerZ)
+       {
+               ///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
+               btScalar ci(btCos(eulerX));
+               btScalar cj(btCos(eulerY));
+               btScalar ch(btCos(eulerZ));
+               btScalar si(btSin(eulerX));
+               btScalar sj(btSin(eulerY));
+               btScalar sh(btSin(eulerZ));
+               btScalar cc = ci * ch;
+               btScalar cs = ci * sh;
+               btScalar sc = si * ch;
+               btScalar ss = si * sh;
+
+               setValue(cj * ch, sj * sc - cs, sj * cc + ss,
+                                cj * sh, sj * ss + cc, sj * cs - sc,
+                                -sj, cj * si, cj * ci);
+       }
+
+       /**@brief Set the matrix to the identity */
+       void setIdentity()
+       {
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+               m_el[0] = v1000;
+               m_el[1] = v0100;
+               m_el[2] = v0010;
+#else
+               setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0),
+                                btScalar(0.0), btScalar(1.0), btScalar(0.0),
+                                btScalar(0.0), btScalar(0.0), btScalar(1.0));
+#endif
+       }
+    
+    /**@brief Set the matrix to the identity */
+    void setZero()
+    {
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+        m_el[0] = v0000;
+        m_el[1] = v0000;
+        m_el[2] = v0000;
+#else
+        setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0),
+                 btScalar(0.0), btScalar(0.0), btScalar(0.0),
+                 btScalar(0.0), btScalar(0.0), btScalar(0.0));
+#endif
+    }
+
+       static const btMatrix3x3& getIdentity()
+       {
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+               static const btMatrix3x3
+                       identityMatrix(v1000, v0100, v0010);
+#else
+               static const btMatrix3x3
+                       identityMatrix(
+                               btScalar(1.0), btScalar(0.0), btScalar(0.0),
+                               btScalar(0.0), btScalar(1.0), btScalar(0.0),
+                               btScalar(0.0), btScalar(0.0), btScalar(1.0));
+#endif
+               return identityMatrix;
+       }
+
+       /**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective
+       * @param m The array to be filled */
+       void getOpenGLSubMatrix(btScalar * m) const
+       {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 v0 = m_el[0].mVec128;
+               __m128 v1 = m_el[1].mVec128;
+               __m128 v2 = m_el[2].mVec128;  //  x2 y2 z2 w2
+               __m128* vm = (__m128*)m;
+               __m128 vT;
+
+               v2 = _mm_and_ps(v2, btvFFF0fMask);  //  x2 y2 z2 0
+
+               vT = _mm_unpackhi_ps(v0, v1);  //       z0 z1 * *
+               v0 = _mm_unpacklo_ps(v0, v1);  //       x0 x1 y0 y1
+
+               v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3));                    // y0 y1 y2 0
+               v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3));                    // x0 x1 x2 0
+               v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT)));  // z0 z1 z2 0
+
+               vm[0] = v0;
+               vm[1] = v1;
+               vm[2] = v2;
+#elif defined(BT_USE_NEON)
+               // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+               static const uint32x2_t zMask = (const uint32x2_t){static_cast<uint32_t>(-1), 0};
+               float32x4_t* vm = (float32x4_t*)m;
+               float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128);               // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+               float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f));  // {x2  0 }, {y2 0}
+               float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
+               float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
+               float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
+               float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q);  // z0 z1 z2  0
+
+               vm[0] = v0;
+               vm[1] = v1;
+               vm[2] = v2;
+#else
+               m[0] = btScalar(m_el[0].x());
+               m[1] = btScalar(m_el[1].x());
+               m[2] = btScalar(m_el[2].x());
+               m[3] = btScalar(0.0);
+               m[4] = btScalar(m_el[0].y());
+               m[5] = btScalar(m_el[1].y());
+               m[6] = btScalar(m_el[2].y());
+               m[7] = btScalar(0.0);
+               m[8] = btScalar(m_el[0].z());
+               m[9] = btScalar(m_el[1].z());
+               m[10] = btScalar(m_el[2].z());
+               m[11] = btScalar(0.0);
+#endif
+       }
+
+       /**@brief Get the matrix represented as a quaternion 
+       * @param q The quaternion which will be set */
+       void getRotation(btQuaternion & q) const
+       {
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+               btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
+               btScalar s, x;
+
+               union {
+                       btSimdFloat4 vec;
+                       btScalar f[4];
+               } temp;
+
+               if (trace > btScalar(0.0))
+               {
+                       x = trace + btScalar(1.0);
+
+                       temp.f[0] = m_el[2].y() - m_el[1].z();
+                       temp.f[1] = m_el[0].z() - m_el[2].x();
+                       temp.f[2] = m_el[1].x() - m_el[0].y();
+                       temp.f[3] = x;
+                       //temp.f[3]= s * btScalar(0.5);
+               }
+               else
+               {
+                       int i, j, k;
+                       if (m_el[0].x() < m_el[1].y())
+                       {
+                               if (m_el[1].y() < m_el[2].z())
+                               {
+                                       i = 2;
+                                       j = 0;
+                                       k = 1;
+                               }
+                               else
+                               {
+                                       i = 1;
+                                       j = 2;
+                                       k = 0;
+                               }
+                       }
+                       else
+                       {
+                               if (m_el[0].x() < m_el[2].z())
+                               {
+                                       i = 2;
+                                       j = 0;
+                                       k = 1;
+                               }
+                               else
+                               {
+                                       i = 0;
+                                       j = 1;
+                                       k = 2;
+                               }
+                       }
+
+                       x = m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0);
+
+                       temp.f[3] = (m_el[k][j] - m_el[j][k]);
+                       temp.f[j] = (m_el[j][i] + m_el[i][j]);
+                       temp.f[k] = (m_el[k][i] + m_el[i][k]);
+                       temp.f[i] = x;
+                       //temp.f[i] = s * btScalar(0.5);
+               }
+
+               s = btSqrt(x);
+               q.set128(temp.vec);
+               s = btScalar(0.5) / s;
+
+               q *= s;
+#else
+               btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
+
+               btScalar temp[4];
+
+               if (trace > btScalar(0.0))
+               {
+                       btScalar s = btSqrt(trace + btScalar(1.0));
+                       temp[3] = (s * btScalar(0.5));
+                       s = btScalar(0.5) / s;
+
+                       temp[0] = ((m_el[2].y() - m_el[1].z()) * s);
+                       temp[1] = ((m_el[0].z() - m_el[2].x()) * s);
+                       temp[2] = ((m_el[1].x() - m_el[0].y()) * s);
+               }
+               else
+               {
+                       int i = m_el[0].x() < m_el[1].y() ? (m_el[1].y() < m_el[2].z() ? 2 : 1) : (m_el[0].x() < m_el[2].z() ? 2 : 0);
+                       int j = (i + 1) % 3;
+                       int k = (i + 2) % 3;
+
+                       btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0));
+                       temp[i] = s * btScalar(0.5);
+                       s = btScalar(0.5) / s;
+
+                       temp[3] = (m_el[k][j] - m_el[j][k]) * s;
+                       temp[j] = (m_el[j][i] + m_el[i][j]) * s;
+                       temp[k] = (m_el[k][i] + m_el[i][k]) * s;
+               }
+               q.setValue(temp[0], temp[1], temp[2], temp[3]);
+#endif
+       }
+
+       /**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
+       * @param yaw Yaw around Y axis
+       * @param pitch Pitch around X axis
+       * @param roll around Z axis */
+       void getEulerYPR(btScalar & yaw, btScalar & pitch, btScalar & roll) const
+       {
+               // first use the normal calculus
+               yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x()));
+               pitch = btScalar(btAsin(-m_el[2].x()));
+               roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z()));
+
+               // on pitch = +/-HalfPI
+               if (btFabs(pitch) == SIMD_HALF_PI)
+               {
+                       if (yaw > 0)
+                               yaw -= SIMD_PI;
+                       else
+                               yaw += SIMD_PI;
+
+                       if (roll > 0)
+                               roll -= SIMD_PI;
+                       else
+                               roll += SIMD_PI;
+               }
+       };
+
+       /**@brief Get the matrix represented as euler angles around ZYX
+       * @param yaw Yaw around Z axis
+       * @param pitch Pitch around Y axis
+       * @param roll around X axis 
+       * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
+       void getEulerZYX(btScalar & yaw, btScalar & pitch, btScalar & roll, unsigned int solution_number = 1) const
+       {
+               struct Euler
+               {
+                       btScalar yaw;
+                       btScalar pitch;
+                       btScalar roll;
+               };
+
+               Euler euler_out;
+               Euler euler_out2;  //second solution
+               //get the pointer to the raw data
+
+               // Check that pitch is not at a singularity
+               if (btFabs(m_el[2].x()) >= 1)
+               {
+                       euler_out.yaw = 0;
+                       euler_out2.yaw = 0;
+
+                       // From difference of angles formula
+                       btScalar delta = btAtan2(m_el[0].x(), m_el[0].z());
+                       if (m_el[2].x() > 0)  //gimbal locked up
+                       {
+                               euler_out.pitch = SIMD_PI / btScalar(2.0);
+                               euler_out2.pitch = SIMD_PI / btScalar(2.0);
+                               euler_out.roll = euler_out.pitch + delta;
+                               euler_out2.roll = euler_out.pitch + delta;
+                       }
+                       else  // gimbal locked down
+                       {
+                               euler_out.pitch = -SIMD_PI / btScalar(2.0);
+                               euler_out2.pitch = -SIMD_PI / btScalar(2.0);
+                               euler_out.roll = -euler_out.pitch + delta;
+                               euler_out2.roll = -euler_out.pitch + delta;
+                       }
+               }
+               else
+               {
+                       euler_out.pitch = -btAsin(m_el[2].x());
+                       euler_out2.pitch = SIMD_PI - euler_out.pitch;
+
+                       euler_out.roll = btAtan2(m_el[2].y() / btCos(euler_out.pitch),
+                                                                        m_el[2].z() / btCos(euler_out.pitch));
+                       euler_out2.roll = btAtan2(m_el[2].y() / btCos(euler_out2.pitch),
+                                                                         m_el[2].z() / btCos(euler_out2.pitch));
+
+                       euler_out.yaw = btAtan2(m_el[1].x() / btCos(euler_out.pitch),
+                                                                       m_el[0].x() / btCos(euler_out.pitch));
+                       euler_out2.yaw = btAtan2(m_el[1].x() / btCos(euler_out2.pitch),
+                                                                        m_el[0].x() / btCos(euler_out2.pitch));
+               }
+
+               if (solution_number == 1)
+               {
+                       yaw = euler_out.yaw;
+                       pitch = euler_out.pitch;
+                       roll = euler_out.roll;
+               }
+               else
+               {
+                       yaw = euler_out2.yaw;
+                       pitch = euler_out2.pitch;
+                       roll = euler_out2.roll;
+               }
+       }
+
+       /**@brief Create a scaled copy of the matrix 
+       * @param s Scaling vector The elements of the vector will scale each column */
+
+       btMatrix3x3 scaled(const btVector3& s) const
+       {
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+               return btMatrix3x3(m_el[0] * s, m_el[1] * s, m_el[2] * s);
+#else
+               return btMatrix3x3(
+                       m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
+                       m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(),
+                       m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z());
+#endif
+       }
+
+       /**@brief Return the determinant of the matrix */
+       btScalar determinant() const;
+       /**@brief Return the adjoint of the matrix */
+       btMatrix3x3 adjoint() const;
+       /**@brief Return the matrix with all values non negative */
+       btMatrix3x3 absolute() const;
+       /**@brief Return the transpose of the matrix */
+       btMatrix3x3 transpose() const;
+       /**@brief Return the inverse of the matrix */
+       btMatrix3x3 inverse() const;
+
+       /// Solve A * x = b, where b is a column vector. This is more efficient
+       /// than computing the inverse in one-shot cases.
+       ///Solve33 is from Box2d, thanks to Erin Catto,
+       btVector3 solve33(const btVector3& b) const
+       {
+               btVector3 col1 = getColumn(0);
+               btVector3 col2 = getColumn(1);
+               btVector3 col3 = getColumn(2);
+
+               btScalar det = btDot(col1, btCross(col2, col3));
+               if (btFabs(det) > SIMD_EPSILON)
+               {
+                       det = 1.0f / det;
+               }
+               btVector3 x;
+               x[0] = det * btDot(b, btCross(col2, col3));
+               x[1] = det * btDot(col1, btCross(b, col3));
+               x[2] = det * btDot(col1, btCross(col2, b));
+               return x;
+       }
+
+       btMatrix3x3 transposeTimes(const btMatrix3x3& m) const;
+       btMatrix3x3 timesTranspose(const btMatrix3x3& m) const;
+
+       SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const
+       {
+               return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z();
+       }
+       SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const
+       {
+               return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z();
+       }
+       SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const
+       {
+               return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z();
+       }
+
+       ///extractRotation is from "A robust method to extract the rotational part of deformations"
+       ///See http://dl.acm.org/citation.cfm?doid=2994258.2994269
+       ///decomposes a matrix A in a orthogonal matrix R and a
+       ///symmetric matrix S:
+       ///A = R*S.
+       ///note that R can include both rotation and scaling.
+       SIMD_FORCE_INLINE void extractRotation(btQuaternion & q, btScalar tolerance = 1.0e-9, int maxIter = 100)
+       {
+               int iter = 0;
+               btScalar w;
+               const btMatrix3x3& A = *this;
+               for (iter = 0; iter < maxIter; iter++)
+               {
+                       btMatrix3x3 R(q);
+                       btVector3 omega = (R.getColumn(0).cross(A.getColumn(0)) + R.getColumn(1).cross(A.getColumn(1)) + R.getColumn(2).cross(A.getColumn(2))) * (btScalar(1.0) / btFabs(R.getColumn(0).dot(A.getColumn(0)) + R.getColumn(1).dot(A.getColumn(1)) + R.getColumn(2).dot(A.getColumn(2))) +
+                                                                                                                                                                                                                                                                                                         tolerance);
+                       w = omega.norm();
+                       if (w < tolerance)
+                               break;
+                       q = btQuaternion(btVector3((btScalar(1.0) / w) * omega), w) *
+                               q;
+                       q.normalize();
+               }
+       }
+
+       /**@brief diagonalizes this matrix by the Jacobi method.
+       * @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
+       * coordinate system, i.e., old_this = rot * new_this * rot^T.
+       * @param threshold See iteration
+       * @param iteration The iteration stops when all off-diagonal elements are less than the threshold multiplied
+       * by the sum of the absolute values of the diagonal, or when maxSteps have been executed.
+       *
+       * Note that this matrix is assumed to be symmetric.
+       */
+       void diagonalize(btMatrix3x3 & rot, btScalar threshold, int maxSteps)
+       {
+               rot.setIdentity();
+               for (int step = maxSteps; step > 0; step--)
+               {
+                       // find off-diagonal element [p][q] with largest magnitude
+                       int p = 0;
+                       int q = 1;
+                       int r = 2;
+                       btScalar max = btFabs(m_el[0][1]);
+                       btScalar v = btFabs(m_el[0][2]);
+                       if (v > max)
+                       {
+                               q = 2;
+                               r = 1;
+                               max = v;
+                       }
+                       v = btFabs(m_el[1][2]);
+                       if (v > max)
+                       {
+                               p = 1;
+                               q = 2;
+                               r = 0;
+                               max = v;
+                       }
+
+                       btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2]));
+                       if (max <= t)
+                       {
+                               if (max <= SIMD_EPSILON * t)
+                               {
+                                       return;
+                               }
+                               step = 1;
+                       }
+
+                       // compute Jacobi rotation J which leads to a zero for element [p][q]
+                       btScalar mpq = m_el[p][q];
+                       btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
+                       btScalar theta2 = theta * theta;
+                       btScalar cos;
+                       btScalar sin;
+                       if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON))
+                       {
+                               t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2))
+                                                                : 1 / (theta - btSqrt(1 + theta2));
+                               cos = 1 / btSqrt(1 + t * t);
+                               sin = cos * t;
+                       }
+                       else
+                       {
+                               // approximation for large theta-value, i.e., a nearly diagonal matrix
+                               t = 1 / (theta * (2 + btScalar(0.5) / theta2));
+                               cos = 1 - btScalar(0.5) * t * t;
+                               sin = cos * t;
+                       }
+
+                       // apply rotation to matrix (this = J^T * this * J)
+                       m_el[p][q] = m_el[q][p] = 0;
+                       m_el[p][p] -= t * mpq;
+                       m_el[q][q] += t * mpq;
+                       btScalar mrp = m_el[r][p];
+                       btScalar mrq = m_el[r][q];
+                       m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq;
+                       m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp;
+
+                       // apply rotation to rot (rot = rot * J)
+                       for (int i = 0; i < 3; i++)
+                       {
+                               btVector3& row = rot[i];
+                               mrp = row[p];
+                               mrq = row[q];
+                               row[p] = cos * mrp - sin * mrq;
+                               row[q] = cos * mrq + sin * mrp;
+                       }
+               }
+       }
+
+       /**@brief Calculate the matrix cofactor 
+       * @param r1 The first row to use for calculating the cofactor
+       * @param c1 The first column to use for calculating the cofactor
+       * @param r1 The second row to use for calculating the cofactor
+       * @param c1 The second column to use for calculating the cofactor
+       * See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
+       */
+       btScalar cofac(int r1, int c1, int r2, int c2) const
+       {
+               return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
+       }
+
+       void serialize(struct btMatrix3x3Data & dataOut) const;
+
+       void serializeFloat(struct btMatrix3x3FloatData & dataOut) const;
+
+       void deSerialize(const struct btMatrix3x3Data& dataIn);
+
+       void deSerializeFloat(const struct btMatrix3x3FloatData& dataIn);
+
+       void deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn);
+};
+
+SIMD_FORCE_INLINE btMatrix3x3&
+btMatrix3x3::operator*=(const btMatrix3x3& m)
+{
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+       __m128 rv00, rv01, rv02;
+       __m128 rv10, rv11, rv12;
+       __m128 rv20, rv21, rv22;
+       __m128 mv0, mv1, mv2;
+
+       rv02 = m_el[0].mVec128;
+       rv12 = m_el[1].mVec128;
+       rv22 = m_el[2].mVec128;
+
+       mv0 = _mm_and_ps(m[0].mVec128, btvFFF0fMask);
+       mv1 = _mm_and_ps(m[1].mVec128, btvFFF0fMask);
+       mv2 = _mm_and_ps(m[2].mVec128, btvFFF0fMask);
+
+       // rv0
+       rv00 = bt_splat_ps(rv02, 0);
+       rv01 = bt_splat_ps(rv02, 1);
+       rv02 = bt_splat_ps(rv02, 2);
+
+       rv00 = _mm_mul_ps(rv00, mv0);
+       rv01 = _mm_mul_ps(rv01, mv1);
+       rv02 = _mm_mul_ps(rv02, mv2);
+
+       // rv1
+       rv10 = bt_splat_ps(rv12, 0);
+       rv11 = bt_splat_ps(rv12, 1);
+       rv12 = bt_splat_ps(rv12, 2);
+
+       rv10 = _mm_mul_ps(rv10, mv0);
+       rv11 = _mm_mul_ps(rv11, mv1);
+       rv12 = _mm_mul_ps(rv12, mv2);
+
+       // rv2
+       rv20 = bt_splat_ps(rv22, 0);
+       rv21 = bt_splat_ps(rv22, 1);
+       rv22 = bt_splat_ps(rv22, 2);
+
+       rv20 = _mm_mul_ps(rv20, mv0);
+       rv21 = _mm_mul_ps(rv21, mv1);
+       rv22 = _mm_mul_ps(rv22, mv2);
+
+       rv00 = _mm_add_ps(rv00, rv01);
+       rv10 = _mm_add_ps(rv10, rv11);
+       rv20 = _mm_add_ps(rv20, rv21);
+
+       m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
+       m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
+       m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
+
+#elif defined(BT_USE_NEON)
+
+       float32x4_t rv0, rv1, rv2;
+       float32x4_t v0, v1, v2;
+       float32x4_t mv0, mv1, mv2;
+
+       v0 = m_el[0].mVec128;
+       v1 = m_el[1].mVec128;
+       v2 = m_el[2].mVec128;
+
+       mv0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
+       mv1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
+       mv2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
+
+       rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+       rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+       rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+       rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+       rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+       rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+       rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+       rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+       rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+       m_el[0].mVec128 = rv0;
+       m_el[1].mVec128 = rv1;
+       m_el[2].mVec128 = rv2;
+#else
+       setValue(
+               m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
+               m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
+               m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
+#endif
+       return *this;
+}
+
+SIMD_FORCE_INLINE btMatrix3x3&
+btMatrix3x3::operator+=(const btMatrix3x3& m)
+{
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+       m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
+       m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
+       m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
+#else
+       setValue(
+               m_el[0][0] + m.m_el[0][0],
+               m_el[0][1] + m.m_el[0][1],
+               m_el[0][2] + m.m_el[0][2],
+               m_el[1][0] + m.m_el[1][0],
+               m_el[1][1] + m.m_el[1][1],
+               m_el[1][2] + m.m_el[1][2],
+               m_el[2][0] + m.m_el[2][0],
+               m_el[2][1] + m.m_el[2][1],
+               m_el[2][2] + m.m_el[2][2]);
+#endif
+       return *this;
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+operator*(const btMatrix3x3& m, const btScalar& k)
+{
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+       __m128 vk = bt_splat_ps(_mm_load_ss((float*)&k), 0x80);
+       return btMatrix3x3(
+               _mm_mul_ps(m[0].mVec128, vk),
+               _mm_mul_ps(m[1].mVec128, vk),
+               _mm_mul_ps(m[2].mVec128, vk));
+#elif defined(BT_USE_NEON)
+       return btMatrix3x3(
+               vmulq_n_f32(m[0].mVec128, k),
+               vmulq_n_f32(m[1].mVec128, k),
+               vmulq_n_f32(m[2].mVec128, k));
+#else
+       return btMatrix3x3(
+               m[0].x() * k, m[0].y() * k, m[0].z() * k,
+               m[1].x() * k, m[1].y() * k, m[1].z() * k,
+               m[2].x() * k, m[2].y() * k, m[2].z() * k);
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+operator+(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+       return btMatrix3x3(
+               m1[0].mVec128 + m2[0].mVec128,
+               m1[1].mVec128 + m2[1].mVec128,
+               m1[2].mVec128 + m2[2].mVec128);
+#else
+       return btMatrix3x3(
+               m1[0][0] + m2[0][0],
+               m1[0][1] + m2[0][1],
+               m1[0][2] + m2[0][2],
+
+               m1[1][0] + m2[1][0],
+               m1[1][1] + m2[1][1],
+               m1[1][2] + m2[1][2],
+
+               m1[2][0] + m2[2][0],
+               m1[2][1] + m2[2][1],
+               m1[2][2] + m2[2][2]);
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+operator-(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+       return btMatrix3x3(
+               m1[0].mVec128 - m2[0].mVec128,
+               m1[1].mVec128 - m2[1].mVec128,
+               m1[2].mVec128 - m2[2].mVec128);
+#else
+       return btMatrix3x3(
+               m1[0][0] - m2[0][0],
+               m1[0][1] - m2[0][1],
+               m1[0][2] - m2[0][2],
+
+               m1[1][0] - m2[1][0],
+               m1[1][1] - m2[1][1],
+               m1[1][2] - m2[1][2],
+
+               m1[2][0] - m2[2][0],
+               m1[2][1] - m2[2][1],
+               m1[2][2] - m2[2][2]);
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3&
+btMatrix3x3::operator-=(const btMatrix3x3& m)
+{
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+       m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
+       m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
+       m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
+#else
+       setValue(
+               m_el[0][0] - m.m_el[0][0],
+               m_el[0][1] - m.m_el[0][1],
+               m_el[0][2] - m.m_el[0][2],
+               m_el[1][0] - m.m_el[1][0],
+               m_el[1][1] - m.m_el[1][1],
+               m_el[1][2] - m.m_el[1][2],
+               m_el[2][0] - m.m_el[2][0],
+               m_el[2][1] - m.m_el[2][1],
+               m_el[2][2] - m.m_el[2][2]);
+#endif
+       return *this;
+}
+
+SIMD_FORCE_INLINE btScalar
+btMatrix3x3::determinant() const
+{
+       return btTriple((*this)[0], (*this)[1], (*this)[2]);
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::absolute() const
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+       return btMatrix3x3(
+               _mm_and_ps(m_el[0].mVec128, btvAbsfMask),
+               _mm_and_ps(m_el[1].mVec128, btvAbsfMask),
+               _mm_and_ps(m_el[2].mVec128, btvAbsfMask));
+#elif defined(BT_USE_NEON)
+       return btMatrix3x3(
+               (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, btv3AbsMask),
+               (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, btv3AbsMask),
+               (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, btv3AbsMask));
+#else
+       return btMatrix3x3(
+               btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
+               btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
+               btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::transpose() const
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+       __m128 v0 = m_el[0].mVec128;
+       __m128 v1 = m_el[1].mVec128;
+       __m128 v2 = m_el[2].mVec128;  //  x2 y2 z2 w2
+       __m128 vT;
+
+       v2 = _mm_and_ps(v2, btvFFF0fMask);  //  x2 y2 z2 0
+
+       vT = _mm_unpackhi_ps(v0, v1);  //       z0 z1 * *
+       v0 = _mm_unpacklo_ps(v0, v1);  //       x0 x1 y0 y1
+
+       v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3));                    // y0 y1 y2 0
+       v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3));                    // x0 x1 x2 0
+       v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT)));  // z0 z1 z2 0
+
+       return btMatrix3x3(v0, v1, v2);
+#elif defined(BT_USE_NEON)
+       // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+       static const uint32x2_t zMask = (const uint32x2_t){static_cast<uint32_t>(-1), 0};
+       float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128);               // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+       float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f));  // {x2  0 }, {y2 0}
+       float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
+       float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
+       float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
+       float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q);  // z0 z1 z2  0
+       return btMatrix3x3(v0, v1, v2);
+#else
+       return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(),
+                                          m_el[0].y(), m_el[1].y(), m_el[2].y(),
+                                          m_el[0].z(), m_el[1].z(), m_el[2].z());
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::adjoint() const
+{
+       return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
+                                          cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
+                                          cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::inverse() const
+{
+       btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
+       btScalar det = (*this)[0].dot(co);
+       //btFullAssert(det != btScalar(0.0));
+       btAssert(det != btScalar(0.0));
+       btScalar s = btScalar(1.0) / det;
+       return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
+                                          co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+                                          co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+       // zeros w
+       //    static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
+       __m128 row = m_el[0].mVec128;
+       __m128 m0 = _mm_and_ps(m.getRow(0).mVec128, btvFFF0fMask);
+       __m128 m1 = _mm_and_ps(m.getRow(1).mVec128, btvFFF0fMask);
+       __m128 m2 = _mm_and_ps(m.getRow(2).mVec128, btvFFF0fMask);
+       __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
+       __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
+       __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
+       row = m_el[1].mVec128;
+       r0 = _mm_add_ps(r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
+       r1 = _mm_add_ps(r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
+       r2 = _mm_add_ps(r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
+       row = m_el[2].mVec128;
+       r0 = _mm_add_ps(r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
+       r1 = _mm_add_ps(r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
+       r2 = _mm_add_ps(r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
+       return btMatrix3x3(r0, r1, r2);
+
+#elif defined BT_USE_NEON
+       // zeros w
+       static const uint32x4_t xyzMask = (const uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0};
+       float32x4_t m0 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(0).mVec128, xyzMask);
+       float32x4_t m1 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(1).mVec128, xyzMask);
+       float32x4_t m2 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(2).mVec128, xyzMask);
+       float32x4_t row = m_el[0].mVec128;
+       float32x4_t r0 = vmulq_lane_f32(m0, vget_low_f32(row), 0);
+       float32x4_t r1 = vmulq_lane_f32(m0, vget_low_f32(row), 1);
+       float32x4_t r2 = vmulq_lane_f32(m0, vget_high_f32(row), 0);
+       row = m_el[1].mVec128;
+       r0 = vmlaq_lane_f32(r0, m1, vget_low_f32(row), 0);
+       r1 = vmlaq_lane_f32(r1, m1, vget_low_f32(row), 1);
+       r2 = vmlaq_lane_f32(r2, m1, vget_high_f32(row), 0);
+       row = m_el[2].mVec128;
+       r0 = vmlaq_lane_f32(r0, m2, vget_low_f32(row), 0);
+       r1 = vmlaq_lane_f32(r1, m2, vget_low_f32(row), 1);
+       r2 = vmlaq_lane_f32(r2, m2, vget_high_f32(row), 0);
+       return btMatrix3x3(r0, r1, r2);
+#else
+       return btMatrix3x3(
+               m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(),
+               m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(),
+               m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(),
+               m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(),
+               m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(),
+               m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(),
+               m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(),
+               m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(),
+               m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z());
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+btMatrix3x3::timesTranspose(const btMatrix3x3& m) const
+{
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+       __m128 a0 = m_el[0].mVec128;
+       __m128 a1 = m_el[1].mVec128;
+       __m128 a2 = m_el[2].mVec128;
+
+       btMatrix3x3 mT = m.transpose();  // we rely on transpose() zeroing w channel so that we don't have to do it here
+       __m128 mx = mT[0].mVec128;
+       __m128 my = mT[1].mVec128;
+       __m128 mz = mT[2].mVec128;
+
+       __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
+       __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
+       __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
+       r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
+       r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
+       r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
+       r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
+       r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
+       r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
+       return btMatrix3x3(r0, r1, r2);
+
+#elif defined BT_USE_NEON
+       float32x4_t a0 = m_el[0].mVec128;
+       float32x4_t a1 = m_el[1].mVec128;
+       float32x4_t a2 = m_el[2].mVec128;
+
+       btMatrix3x3 mT = m.transpose();  // we rely on transpose() zeroing w channel so that we don't have to do it here
+       float32x4_t mx = mT[0].mVec128;
+       float32x4_t my = mT[1].mVec128;
+       float32x4_t mz = mT[2].mVec128;
+
+       float32x4_t r0 = vmulq_lane_f32(mx, vget_low_f32(a0), 0);
+       float32x4_t r1 = vmulq_lane_f32(mx, vget_low_f32(a1), 0);
+       float32x4_t r2 = vmulq_lane_f32(mx, vget_low_f32(a2), 0);
+       r0 = vmlaq_lane_f32(r0, my, vget_low_f32(a0), 1);
+       r1 = vmlaq_lane_f32(r1, my, vget_low_f32(a1), 1);
+       r2 = vmlaq_lane_f32(r2, my, vget_low_f32(a2), 1);
+       r0 = vmlaq_lane_f32(r0, mz, vget_high_f32(a0), 0);
+       r1 = vmlaq_lane_f32(r1, mz, vget_high_f32(a1), 0);
+       r2 = vmlaq_lane_f32(r2, mz, vget_high_f32(a2), 0);
+       return btMatrix3x3(r0, r1, r2);
+
+#else
+       return btMatrix3x3(
+               m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
+               m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
+               m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
+#endif
+}
+
+SIMD_FORCE_INLINE btVector3
+operator*(const btMatrix3x3& m, const btVector3& v)
+{
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+       return v.dot3(m[0], m[1], m[2]);
+#else
+       return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
+#endif
+}
+
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v, const btMatrix3x3& m)
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+
+       const __m128 vv = v.mVec128;
+
+       __m128 c0 = bt_splat_ps(vv, 0);
+       __m128 c1 = bt_splat_ps(vv, 1);
+       __m128 c2 = bt_splat_ps(vv, 2);
+
+       c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, btvFFF0fMask));
+       c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, btvFFF0fMask));
+       c0 = _mm_add_ps(c0, c1);
+       c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, btvFFF0fMask));
+
+       return btVector3(_mm_add_ps(c0, c2));
+#elif defined(BT_USE_NEON)
+       const float32x4_t vv = v.mVec128;
+       const float32x2_t vlo = vget_low_f32(vv);
+       const float32x2_t vhi = vget_high_f32(vv);
+
+       float32x4_t c0, c1, c2;
+
+       c0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
+       c1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
+       c2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
+
+       c0 = vmulq_lane_f32(c0, vlo, 0);
+       c1 = vmulq_lane_f32(c1, vlo, 1);
+       c2 = vmulq_lane_f32(c2, vhi, 0);
+       c0 = vaddq_f32(c0, c1);
+       c0 = vaddq_f32(c0, c2);
+
+       return btVector3(c0);
+#else
+       return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
+#endif
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+operator*(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+
+       __m128 m10 = m1[0].mVec128;
+       __m128 m11 = m1[1].mVec128;
+       __m128 m12 = m1[2].mVec128;
+
+       __m128 m2v = _mm_and_ps(m2[0].mVec128, btvFFF0fMask);
+
+       __m128 c0 = bt_splat_ps(m10, 0);
+       __m128 c1 = bt_splat_ps(m11, 0);
+       __m128 c2 = bt_splat_ps(m12, 0);
+
+       c0 = _mm_mul_ps(c0, m2v);
+       c1 = _mm_mul_ps(c1, m2v);
+       c2 = _mm_mul_ps(c2, m2v);
+
+       m2v = _mm_and_ps(m2[1].mVec128, btvFFF0fMask);
+
+       __m128 c0_1 = bt_splat_ps(m10, 1);
+       __m128 c1_1 = bt_splat_ps(m11, 1);
+       __m128 c2_1 = bt_splat_ps(m12, 1);
+
+       c0_1 = _mm_mul_ps(c0_1, m2v);
+       c1_1 = _mm_mul_ps(c1_1, m2v);
+       c2_1 = _mm_mul_ps(c2_1, m2v);
+
+       m2v = _mm_and_ps(m2[2].mVec128, btvFFF0fMask);
+
+       c0 = _mm_add_ps(c0, c0_1);
+       c1 = _mm_add_ps(c1, c1_1);
+       c2 = _mm_add_ps(c2, c2_1);
+
+       m10 = bt_splat_ps(m10, 2);
+       m11 = bt_splat_ps(m11, 2);
+       m12 = bt_splat_ps(m12, 2);
+
+       m10 = _mm_mul_ps(m10, m2v);
+       m11 = _mm_mul_ps(m11, m2v);
+       m12 = _mm_mul_ps(m12, m2v);
+
+       c0 = _mm_add_ps(c0, m10);
+       c1 = _mm_add_ps(c1, m11);
+       c2 = _mm_add_ps(c2, m12);
+
+       return btMatrix3x3(c0, c1, c2);
+
+#elif defined(BT_USE_NEON)
+
+       float32x4_t rv0, rv1, rv2;
+       float32x4_t v0, v1, v2;
+       float32x4_t mv0, mv1, mv2;
+
+       v0 = m1[0].mVec128;
+       v1 = m1[1].mVec128;
+       v2 = m1[2].mVec128;
+
+       mv0 = (float32x4_t)vandq_s32((int32x4_t)m2[0].mVec128, btvFFF0Mask);
+       mv1 = (float32x4_t)vandq_s32((int32x4_t)m2[1].mVec128, btvFFF0Mask);
+       mv2 = (float32x4_t)vandq_s32((int32x4_t)m2[2].mVec128, btvFFF0Mask);
+
+       rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+       rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+       rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+       rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+       rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+       rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+       rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+       rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+       rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+       return btMatrix3x3(rv0, rv1, rv2);
+
+#else
+       return btMatrix3x3(
+               m2.tdotx(m1[0]), m2.tdoty(m1[0]), m2.tdotz(m1[0]),
+               m2.tdotx(m1[1]), m2.tdoty(m1[1]), m2.tdotz(m1[1]),
+               m2.tdotx(m1[2]), m2.tdoty(m1[2]), m2.tdotz(m1[2]));
+#endif
+}
+
+/*
+SIMD_FORCE_INLINE btMatrix3x3 btMultTransposeLeft(const btMatrix3x3& m1, const btMatrix3x3& m2) {
+return btMatrix3x3(
+m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
+m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
+m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
+m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
+m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
+m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
+m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
+m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
+m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
+}
+*/
+
+/**@brief Equality operator between two matrices
+* It will test all elements are equal.  */
+SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+
+       __m128 c0, c1, c2;
+
+       c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
+       c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
+       c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
+
+       c0 = _mm_and_ps(c0, c1);
+       c0 = _mm_and_ps(c0, c2);
+
+       int m = _mm_movemask_ps((__m128)c0);
+       return (0x7 == (m & 0x7));
+
+#else
+       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
+}
+
+///for serialization
+struct btMatrix3x3FloatData
+{
+       btVector3FloatData m_el[3];
+};
+
+///for serialization
+struct btMatrix3x3DoubleData
+{
+       btVector3DoubleData m_el[3];
+};
+
+SIMD_FORCE_INLINE void btMatrix3x3::serialize(struct btMatrix3x3Data& dataOut) const
+{
+       for (int i = 0; i < 3; i++)
+               m_el[i].serialize(dataOut.m_el[i]);
+}
+
+SIMD_FORCE_INLINE void btMatrix3x3::serializeFloat(struct btMatrix3x3FloatData& dataOut) const
+{
+       for (int i = 0; i < 3; i++)
+               m_el[i].serializeFloat(dataOut.m_el[i]);
+}
+
+SIMD_FORCE_INLINE void btMatrix3x3::deSerialize(const struct btMatrix3x3Data& dataIn)
+{
+       for (int i = 0; i < 3; i++)
+               m_el[i].deSerialize(dataIn.m_el[i]);
+}
+
+SIMD_FORCE_INLINE void btMatrix3x3::deSerializeFloat(const struct btMatrix3x3FloatData& dataIn)
+{
+       for (int i = 0; i < 3; i++)
+               m_el[i].deSerializeFloat(dataIn.m_el[i]);
+}
+
+SIMD_FORCE_INLINE void btMatrix3x3::deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn)
+{
+       for (int i = 0; i < 3; i++)
+               m_el[i].deSerializeDouble(dataIn.m_el[i]);
+}
+
+#endif  //BT_MATRIX3x3_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btMatrixX.h b/dali-physics/third-party/bullet3/src/LinearMath/btMatrixX.h
new file mode 100644 (file)
index 0000000..bb0f0dd
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2013 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///original version written by Erwin Coumans, October 2013
+
+#ifndef BT_MATRIX_X_H
+#define BT_MATRIX_X_H
+
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include <stdio.h>
+
+//#define BT_DEBUG_OSTREAM
+#ifdef BT_DEBUG_OSTREAM
+#include <iostream>
+#include <iomanip>  // std::setw
+#endif              //BT_DEBUG_OSTREAM
+
+class btIntSortPredicate
+{
+public:
+       bool operator()(const int& a, const int& b) const
+       {
+               return a < b;
+       }
+};
+
+template <typename T>
+struct btVectorX
+{
+       btAlignedObjectArray<T> m_storage;
+
+       btVectorX()
+       {
+       }
+       btVectorX(int numRows)
+       {
+               m_storage.resize(numRows);
+       }
+
+       void resize(int rows)
+       {
+               m_storage.resize(rows);
+       }
+       int cols() const
+       {
+               return 1;
+       }
+       int rows() const
+       {
+               return m_storage.size();
+       }
+       int size() const
+       {
+               return rows();
+       }
+
+       T nrm2() const
+       {
+               T norm = T(0);
+
+               int nn = rows();
+
+               {
+                       if (nn == 1)
+                       {
+                               norm = btFabs((*this)[0]);
+                       }
+                       else
+                       {
+                               T scale = 0.0;
+                               T ssq = 1.0;
+
+                               /* The following loop is equivalent to this call to the LAPACK
+                                auxiliary routine:   CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */
+
+                               for (int ix = 0; ix < nn; ix++)
+                               {
+                                       if ((*this)[ix] != 0.0)
+                                       {
+                                               T absxi = btFabs((*this)[ix]);
+                                               if (scale < absxi)
+                                               {
+                                                       T temp;
+                                                       temp = scale / absxi;
+                                                       ssq = ssq * (temp * temp) + BT_ONE;
+                                                       scale = absxi;
+                                               }
+                                               else
+                                               {
+                                                       T temp;
+                                                       temp = absxi / scale;
+                                                       ssq += temp * temp;
+                                               }
+                                       }
+                               }
+                               norm = scale * sqrt(ssq);
+                       }
+               }
+               return norm;
+       }
+       void setZero()
+       {
+               if (m_storage.size())
+               {
+                       //      for (int i=0;i<m_storage.size();i++)
+                       //              m_storage[i]=0;
+                       //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
+                       btSetZero(&m_storage[0], m_storage.size());
+               }
+       }
+       const T& operator[](int index) const
+       {
+               return m_storage[index];
+       }
+
+       T& operator[](int index)
+       {
+               return m_storage[index];
+       }
+
+       T* getBufferPointerWritable()
+       {
+               return m_storage.size() ? &m_storage[0] : 0;
+       }
+
+       const T* getBufferPointer() const
+       {
+               return m_storage.size() ? &m_storage[0] : 0;
+       }
+};
+/*
+ template <typename T>
+ void setElem(btMatrixX<T>& mat, int row, int col, T val)
+ {
+ mat.setElem(row,col,val);
+ }
+ */
+
+template <typename T>
+struct btMatrixX
+{
+       int m_rows;
+       int m_cols;
+       int m_operations;
+       int m_resizeOperations;
+       int m_setElemOperations;
+
+       btAlignedObjectArray<T> m_storage;
+       mutable btAlignedObjectArray<btAlignedObjectArray<int> > m_rowNonZeroElements1;
+
+       T* getBufferPointerWritable()
+       {
+               return m_storage.size() ? &m_storage[0] : 0;
+       }
+
+       const T* getBufferPointer() const
+       {
+               return m_storage.size() ? &m_storage[0] : 0;
+       }
+       btMatrixX()
+               : m_rows(0),
+                 m_cols(0),
+                 m_operations(0),
+                 m_resizeOperations(0),
+                 m_setElemOperations(0)
+       {
+       }
+       btMatrixX(int rows, int cols)
+               : m_rows(rows),
+                 m_cols(cols),
+                 m_operations(0),
+                 m_resizeOperations(0),
+                 m_setElemOperations(0)
+       {
+               resize(rows, cols);
+       }
+       void resize(int rows, int cols)
+       {
+               m_resizeOperations++;
+               m_rows = rows;
+               m_cols = cols;
+               {
+                       BT_PROFILE("m_storage.resize");
+                       m_storage.resize(rows * cols);
+               }
+       }
+       int cols() const
+       {
+               return m_cols;
+       }
+       int rows() const
+       {
+               return m_rows;
+       }
+       ///we don't want this read/write operator(), because we cannot keep track of non-zero elements, use setElem instead
+       /*T& operator() (int row,int col)
+       {
+               return m_storage[col*m_rows+row];
+       }
+       */
+
+       void addElem(int row, int col, T val)
+       {
+               if (val)
+               {
+                       if (m_storage[col + row * m_cols] == 0.f)
+                       {
+                               setElem(row, col, val);
+                       }
+                       else
+                       {
+                               m_storage[row * m_cols + col] += val;
+                       }
+               }
+       }
+
+       void setElem(int row, int col, T val)
+       {
+               m_setElemOperations++;
+               m_storage[row * m_cols + col] = val;
+       }
+
+       void mulElem(int row, int col, T val)
+       {
+               m_setElemOperations++;
+               //mul doesn't change sparsity info
+
+               m_storage[row * m_cols + col] *= val;
+       }
+
+       void copyLowerToUpperTriangle()
+       {
+               int count = 0;
+               for (int row = 0; row < rows(); row++)
+               {
+                       for (int col = 0; col < row; col++)
+                       {
+                               setElem(col, row, (*this)(row, col));
+                               count++;
+                       }
+               }
+               //printf("copyLowerToUpperTriangle copied %d elements out of %dx%d=%d\n", count,rows(),cols(),cols()*rows());
+       }
+
+       const T& operator()(int row, int col) const
+       {
+               return m_storage[col + row * m_cols];
+       }
+
+       void setZero()
+       {
+               {
+                       BT_PROFILE("storage=0");
+                       if (m_storage.size())
+                       {
+                               btSetZero(&m_storage[0], m_storage.size());
+                       }
+                       //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
+                       //for (int i=0;i<m_storage.size();i++)
+                       //                      m_storage[i]=0;
+               }
+       }
+
+       void setIdentity()
+       {
+               btAssert(rows() == cols());
+
+               setZero();
+               for (int row = 0; row < rows(); row++)
+               {
+                       setElem(row, row, 1);
+               }
+       }
+
+       void printMatrix(const char* msg) const
+       {
+               printf("%s ---------------------\n", msg);
+               for (int i = 0; i < rows(); i++)
+               {
+                       printf("\n");
+                       for (int j = 0; j < cols(); j++)
+                       {
+                               printf("%2.1f\t", (*this)(i, j));
+                       }
+               }
+               printf("\n---------------------\n");
+       }
+
+       void rowComputeNonZeroElements() const
+       {
+               m_rowNonZeroElements1.resize(rows());
+               for (int i = 0; i < rows(); i++)
+               {
+                       m_rowNonZeroElements1[i].resize(0);
+                       for (int j = 0; j < cols(); j++)
+                       {
+                               if ((*this)(i, j) != 0.f)
+                               {
+                                       m_rowNonZeroElements1[i].push_back(j);
+                               }
+                       }
+               }
+       }
+       btMatrixX transpose() const
+       {
+               //transpose is optimized for sparse matrices
+               btMatrixX tr(m_cols, m_rows);
+               tr.setZero();
+               for (int i = 0; i < m_cols; i++)
+                       for (int j = 0; j < m_rows; j++)
+                       {
+                               T v = (*this)(j, i);
+                               if (v)
+                               {
+                                       tr.setElem(i, j, v);
+                               }
+                       }
+               return tr;
+       }
+
+       btMatrixX operator*(const btMatrixX& other)
+       {
+               //btMatrixX*btMatrixX implementation, brute force
+               btAssert(cols() == other.rows());
+
+               btMatrixX res(rows(), other.cols());
+               res.setZero();
+               //              BT_PROFILE("btMatrixX mul");
+               for (int i = 0; i < rows(); ++i)
+               {
+                       {
+                               for (int j = 0; j < other.cols(); ++j)
+                               {
+                                       T dotProd = 0;
+                                       {
+                                               {
+                                                       int c = cols();
+
+                                                       for (int k = 0; k < c; k++)
+                                                       {
+                                                               T w = (*this)(i, k);
+                                                               if (other(k, j) != 0.f)
+                                                               {
+                                                                       dotProd += w * other(k, j);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       if (dotProd)
+                                               res.setElem(i, j, dotProd);
+                               }
+                       }
+               }
+               return res;
+       }
+
+       // this assumes the 4th and 8th rows of B and C are zero.
+       void multiplyAdd2_p8r(const btScalar* B, const btScalar* C, int numRows, int numRowsOther, int row, int col)
+       {
+               const btScalar* bb = B;
+               for (int i = 0; i < numRows; i++)
+               {
+                       const btScalar* cc = C;
+                       for (int j = 0; j < numRowsOther; j++)
+                       {
+                               btScalar sum;
+                               sum = bb[0] * cc[0];
+                               sum += bb[1] * cc[1];
+                               sum += bb[2] * cc[2];
+                               sum += bb[4] * cc[4];
+                               sum += bb[5] * cc[5];
+                               sum += bb[6] * cc[6];
+                               addElem(row + i, col + j, sum);
+                               cc += 8;
+                       }
+                       bb += 8;
+               }
+       }
+
+       void multiply2_p8r(const btScalar* B, const btScalar* C, int numRows, int numRowsOther, int row, int col)
+       {
+               btAssert(numRows > 0 && numRowsOther > 0 && B && C);
+               const btScalar* bb = B;
+               for (int i = 0; i < numRows; i++)
+               {
+                       const btScalar* cc = C;
+                       for (int j = 0; j < numRowsOther; j++)
+                       {
+                               btScalar sum;
+                               sum = bb[0] * cc[0];
+                               sum += bb[1] * cc[1];
+                               sum += bb[2] * cc[2];
+                               sum += bb[4] * cc[4];
+                               sum += bb[5] * cc[5];
+                               sum += bb[6] * cc[6];
+                               setElem(row + i, col + j, sum);
+                               cc += 8;
+                       }
+                       bb += 8;
+               }
+       }
+
+       void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const T value)
+       {
+               int numRows = rowend + 1 - rowstart;
+               int numCols = colend + 1 - colstart;
+
+               for (int row = 0; row < numRows; row++)
+               {
+                       for (int col = 0; col < numCols; col++)
+                       {
+                               setElem(rowstart + row, colstart + col, value);
+                       }
+               }
+       }
+
+       void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const btMatrixX& block)
+       {
+               btAssert(rowend + 1 - rowstart == block.rows());
+               btAssert(colend + 1 - colstart == block.cols());
+               for (int row = 0; row < block.rows(); row++)
+               {
+                       for (int col = 0; col < block.cols(); col++)
+                       {
+                               setElem(rowstart + row, colstart + col, block(row, col));
+                       }
+               }
+       }
+       void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const btVectorX<T>& block)
+       {
+               btAssert(rowend + 1 - rowstart == block.rows());
+               btAssert(colend + 1 - colstart == block.cols());
+               for (int row = 0; row < block.rows(); row++)
+               {
+                       for (int col = 0; col < block.cols(); col++)
+                       {
+                               setElem(rowstart + row, colstart + col, block[row]);
+                       }
+               }
+       }
+
+       btMatrixX negative()
+       {
+               btMatrixX neg(rows(), cols());
+               for (int i = 0; i < rows(); i++)
+                       for (int j = 0; j < cols(); j++)
+                       {
+                               T v = (*this)(i, j);
+                               neg.setElem(i, j, -v);
+                       }
+               return neg;
+       }
+};
+
+typedef btMatrixX<float> btMatrixXf;
+typedef btVectorX<float> btVectorXf;
+
+typedef btMatrixX<double> btMatrixXd;
+typedef btVectorX<double> btVectorXd;
+
+#ifdef BT_DEBUG_OSTREAM
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const btMatrixX<T>& mat)
+{
+       os << " [";
+       //printf("%s ---------------------\n",msg);
+       for (int i = 0; i < mat.rows(); i++)
+       {
+               for (int j = 0; j < mat.cols(); j++)
+               {
+                       os << std::setw(12) << mat(i, j);
+               }
+               if (i != mat.rows() - 1)
+                       os << std::endl
+                          << "  ";
+       }
+       os << " ]";
+       //printf("\n---------------------\n");
+
+       return os;
+}
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const btVectorX<T>& mat)
+{
+       os << " [";
+       //printf("%s ---------------------\n",msg);
+       for (int i = 0; i < mat.rows(); i++)
+       {
+               os << std::setw(12) << mat[i];
+               if (i != mat.rows() - 1)
+                       os << std::endl
+                          << "  ";
+       }
+       os << " ]";
+       //printf("\n---------------------\n");
+
+       return os;
+}
+
+#endif  //BT_DEBUG_OSTREAM
+
+inline void setElem(btMatrixXd& mat, int row, int col, double val)
+{
+       mat.setElem(row, col, val);
+}
+
+inline void setElem(btMatrixXf& mat, int row, int col, float val)
+{
+       mat.setElem(row, col, val);
+}
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btVectorXu btVectorXd
+#define btMatrixXu btMatrixXd
+#else
+#define btVectorXu btVectorXf
+#define btMatrixXu btMatrixXf
+#endif  //BT_USE_DOUBLE_PRECISION
+
+#endif  //BT_MATRIX_H_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btMinMax.h b/dali-physics/third-party/bullet3/src/LinearMath/btMinMax.h
new file mode 100644 (file)
index 0000000..cdc54f3
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_GEN_MINMAX_H
+#define BT_GEN_MINMAX_H
+
+#include "btScalar.h"
+
+template <class T>
+SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b)
+{
+       return a < b ? a : b;
+}
+
+template <class T>
+SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b)
+{
+       return a > b ? a : b;
+}
+
+template <class T>
+SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub)
+{
+       return a < lb ? lb : (ub < a ? ub : a);
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btSetMin(T& a, const T& b)
+{
+       if (b < a)
+       {
+               a = b;
+       }
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btSetMax(T& a, const T& b)
+{
+       if (a < b)
+       {
+               a = b;
+       }
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub)
+{
+       if (a < lb)
+       {
+               a = lb;
+       }
+       else if (ub < a)
+       {
+               a = ub;
+       }
+}
+
+#endif  //BT_GEN_MINMAX_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btModifiedGramSchmidt.h b/dali-physics/third-party/bullet3/src/LinearMath/btModifiedGramSchmidt.h
new file mode 100644 (file)
index 0000000..33bab8d
--- /dev/null
@@ -0,0 +1,83 @@
+//
+//  btModifiedGramSchmidt.h
+//  LinearMath
+//
+//  Created by Xuchen Han on 4/4/20.
+//
+
+#ifndef btModifiedGramSchmidt_h
+#define btModifiedGramSchmidt_h
+
+#include "btReducedVector.h"
+#include "btAlignedObjectArray.h"
+#include <iostream>
+#include <cmath>
+template<class TV>
+class btModifiedGramSchmidt
+{
+public:
+    btAlignedObjectArray<TV> m_in;
+    btAlignedObjectArray<TV> m_out;
+    
+    btModifiedGramSchmidt(const btAlignedObjectArray<TV>& vecs): m_in(vecs)
+    {
+        m_out.resize(0);
+    }
+    
+    void solve()
+    {
+        m_out.resize(m_in.size());
+        for (int i = 0; i < m_in.size(); ++i)
+        {
+//            printf("========= starting %d ==========\n", i);
+            TV v(m_in[i]);
+//            v.print();
+            for (int j = 0; j < i; ++j)
+            {
+                v = v - v.proj(m_out[j]);
+//                v.print();
+            }
+            v.normalize();
+            m_out[i] = v;
+//            v.print();
+        }
+    }
+    
+    void test()
+    {
+        std::cout << SIMD_EPSILON << std::endl;
+        printf("=======inputs=========\n");
+        for (int i = 0; i < m_out.size(); ++i)
+        {
+            m_in[i].print();
+        }
+        printf("=======output=========\n");
+        for (int i = 0; i < m_out.size(); ++i)
+        {
+            m_out[i].print();
+        }
+        btScalar eps = SIMD_EPSILON;
+        for (int i = 0; i < m_out.size(); ++i)
+        {
+            for (int j = 0; j < m_out.size(); ++j)
+            {
+                if (i == j)
+                {
+                    if (std::abs(1.0-m_out[i].dot(m_out[j])) > eps)// && std::abs(m_out[i].dot(m_out[j])) > eps)
+                    {
+                        printf("vec[%d] is not unit, norm squared = %f\n", i,m_out[i].dot(m_out[j]));
+                    }
+                }
+                else
+                {
+                    if (std::abs(m_out[i].dot(m_out[j])) > eps)
+                    {
+                        printf("vec[%d] and vec[%d] is not orthogonal, dot product = %f\n", i, j, m_out[i].dot(m_out[j]));
+                    }
+                }
+            }
+        }
+    }
+};
+template class btModifiedGramSchmidt<btReducedVector>;
+#endif /* btModifiedGramSchmidt_h */
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btMotionState.h b/dali-physics/third-party/bullet3/src/LinearMath/btMotionState.h
new file mode 100644 (file)
index 0000000..87aa602
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_MOTIONSTATE_H
+#define BT_MOTIONSTATE_H
+
+#include "btTransform.h"
+
+///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
+{
+public:
+       virtual ~btMotionState()
+       {
+       }
+
+       virtual void getWorldTransform(btTransform& worldTrans) const = 0;
+
+       //Bullet only calls the update of worldtransform for active objects
+       virtual void setWorldTransform(const btTransform& worldTrans) = 0;
+};
+
+#endif  //BT_MOTIONSTATE_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btPolarDecomposition.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btPolarDecomposition.cpp
new file mode 100644 (file)
index 0000000..d9c72a8
--- /dev/null
@@ -0,0 +1,94 @@
+#include "btPolarDecomposition.h"
+#include "btMinMax.h"
+
+namespace
+{
+btScalar abs_column_sum(const btMatrix3x3& a, int i)
+{
+       return btFabs(a[0][i]) + btFabs(a[1][i]) + btFabs(a[2][i]);
+}
+
+btScalar abs_row_sum(const btMatrix3x3& a, int i)
+{
+       return btFabs(a[i][0]) + btFabs(a[i][1]) + btFabs(a[i][2]);
+}
+
+btScalar p1_norm(const btMatrix3x3& a)
+{
+       const btScalar sum0 = abs_column_sum(a, 0);
+       const btScalar sum1 = abs_column_sum(a, 1);
+       const btScalar sum2 = abs_column_sum(a, 2);
+       return btMax(btMax(sum0, sum1), sum2);
+}
+
+btScalar pinf_norm(const btMatrix3x3& a)
+{
+       const btScalar sum0 = abs_row_sum(a, 0);
+       const btScalar sum1 = abs_row_sum(a, 1);
+       const btScalar sum2 = abs_row_sum(a, 2);
+       return btMax(btMax(sum0, sum1), sum2);
+}
+}  // namespace
+
+btPolarDecomposition::btPolarDecomposition(btScalar tolerance, unsigned int maxIterations)
+       : m_tolerance(tolerance), m_maxIterations(maxIterations)
+{
+}
+
+unsigned int btPolarDecomposition::decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const
+{
+       // Use the 'u' and 'h' matrices for intermediate calculations
+       u = a;
+       h = a.inverse();
+
+       for (unsigned int i = 0; i < m_maxIterations; ++i)
+       {
+               const btScalar h_1 = p1_norm(h);
+               const btScalar h_inf = pinf_norm(h);
+               const btScalar u_1 = p1_norm(u);
+               const btScalar u_inf = pinf_norm(u);
+
+               const btScalar h_norm = h_1 * h_inf;
+               const btScalar u_norm = u_1 * u_inf;
+
+               // The matrix is effectively singular so we cannot invert it
+               if (btFuzzyZero(h_norm) || btFuzzyZero(u_norm))
+                       break;
+
+               const btScalar gamma = btPow(h_norm / u_norm, 0.25f);
+               const btScalar inv_gamma = btScalar(1.0) / gamma;
+
+               // Determine the delta to 'u'
+               const btMatrix3x3 delta = (u * (gamma - btScalar(2.0)) + h.transpose() * inv_gamma) * btScalar(0.5);
+
+               // Update the matrices
+               u += delta;
+               h = u.inverse();
+
+               // Check for convergence
+               if (p1_norm(delta) <= m_tolerance * u_1)
+               {
+                       h = u.transpose() * a;
+                       h = (h + h.transpose()) * 0.5;
+                       return i;
+               }
+       }
+
+       // The algorithm has failed to converge to the specified tolerance, but we
+       // want to make sure that the matrices returned are in the right form.
+       h = u.transpose() * a;
+       h = (h + h.transpose()) * 0.5;
+
+       return m_maxIterations;
+}
+
+unsigned int btPolarDecomposition::maxIterations() const
+{
+       return m_maxIterations;
+}
+
+unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h)
+{
+       static btPolarDecomposition polar;
+       return polar.decompose(a, u, h);
+}
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btPolarDecomposition.h b/dali-physics/third-party/bullet3/src/LinearMath/btPolarDecomposition.h
new file mode 100644 (file)
index 0000000..bf29140
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef POLARDECOMPOSITION_H
+#define POLARDECOMPOSITION_H
+
+#include "btMatrix3x3.h"
+
+/**
+ * This class is used to compute the polar decomposition of a matrix. In
+ * general, the polar decomposition factorizes a matrix, A, into two parts: a
+ * unitary matrix (U) and a positive, semi-definite Hermitian matrix (H).
+ * However, in this particular implementation the original matrix, A, is
+ * required to be a square 3x3 matrix with real elements. This means that U will
+ * be an orthogonal matrix and H with be a positive-definite, symmetric matrix.
+ */
+class btPolarDecomposition
+{
+public:
+       /**
+     * Creates an instance with optional parameters.
+     *
+     * @param tolerance     - the tolerance used to determine convergence of the
+     *                        algorithm
+     * @param maxIterations - the maximum number of iterations used to achieve
+     *                        convergence
+     */
+       btPolarDecomposition(btScalar tolerance = btScalar(0.0001),
+                                                unsigned int maxIterations = 16);
+
+       /**
+     * Decomposes a matrix into orthogonal and symmetric, positive-definite
+     * parts. If the number of iterations returned by this function is equal to
+     * the maximum number of iterations, the algorithm has failed to converge.
+     *
+     * @param a - the original matrix
+     * @param u - the resulting orthogonal matrix
+     * @param h - the resulting symmetric matrix
+     *
+     * @return the number of iterations performed by the algorithm.
+     */
+       unsigned int decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const;
+
+       /**
+     * Returns the maximum number of iterations that this algorithm will perform
+     * to achieve convergence.
+     *
+     * @return maximum number of iterations
+     */
+       unsigned int maxIterations() const;
+
+private:
+       btScalar m_tolerance;
+       unsigned int m_maxIterations;
+};
+
+/**
+ * This functions decomposes the matrix 'a' into two parts: an orthogonal matrix
+ * 'u' and a symmetric, positive-definite matrix 'h'. If the number of
+ * iterations returned by this function is equal to
+ * btPolarDecomposition::DEFAULT_MAX_ITERATIONS, the algorithm has failed to
+ * converge.
+ *
+ * @param a - the original matrix
+ * @param u - the resulting orthogonal matrix
+ * @param h - the resulting symmetric matrix
+ *
+ * @return the number of iterations performed by the algorithm.
+ */
+unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h);
+
+#endif  // POLARDECOMPOSITION_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btPoolAllocator.h b/dali-physics/third-party/bullet3/src/LinearMath/btPoolAllocator.h
new file mode 100644 (file)
index 0000000..816cd62
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _BT_POOL_ALLOCATOR_H
+#define _BT_POOL_ALLOCATOR_H
+
+#include "btScalar.h"
+#include "btAlignedAllocator.h"
+#include "btThreads.h"
+
+///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
+class btPoolAllocator
+{
+       int m_elemSize;
+       int m_maxElements;
+       int m_freeCount;
+       void* m_firstFree;
+       unsigned char* m_pool;
+       btSpinMutex m_mutex;  // only used if BT_THREADSAFE
+
+public:
+       btPoolAllocator(int elemSize, int maxElements)
+               : m_elemSize(elemSize),
+                 m_maxElements(maxElements)
+       {
+               m_pool = (unsigned char*)btAlignedAlloc(static_cast<unsigned int>(m_elemSize * m_maxElements), 16);
+
+               unsigned char* p = m_pool;
+               m_firstFree = p;
+               m_freeCount = m_maxElements;
+               int count = m_maxElements;
+               while (--count)
+               {
+                       *(void**)p = (p + m_elemSize);
+                       p += m_elemSize;
+               }
+               *(void**)p = 0;
+       }
+
+       ~btPoolAllocator()
+       {
+               btAlignedFree(m_pool);
+       }
+
+       int getFreeCount() const
+       {
+               return m_freeCount;
+       }
+
+       int getUsedCount() const
+       {
+               return m_maxElements - m_freeCount;
+       }
+
+       int getMaxCount() const
+       {
+               return m_maxElements;
+       }
+
+       void* allocate(int size)
+       {
+               // release mode fix
+               (void)size;
+               btMutexLock(&m_mutex);
+               btAssert(!size || size <= m_elemSize);
+               //btAssert(m_freeCount>0);  // should return null if all full
+               void* result = m_firstFree;
+               if (NULL != m_firstFree)
+               {
+                       m_firstFree = *(void**)m_firstFree;
+                       --m_freeCount;
+               }
+               btMutexUnlock(&m_mutex);
+               return result;
+       }
+
+       bool validPtr(void* ptr)
+       {
+               if (ptr)
+               {
+                       if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
+                       {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       void freeMemory(void* ptr)
+       {
+               if (ptr)
+               {
+                       btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
+
+                       btMutexLock(&m_mutex);
+                       *(void**)ptr = m_firstFree;
+                       m_firstFree = ptr;
+                       ++m_freeCount;
+                       btMutexUnlock(&m_mutex);
+               }
+       }
+
+       int getElementSize() const
+       {
+               return m_elemSize;
+       }
+
+       unsigned char* getPoolAddress()
+       {
+               return m_pool;
+       }
+
+       const unsigned char* getPoolAddress() const
+       {
+               return m_pool;
+       }
+};
+
+#endif  //_BT_POOL_ALLOCATOR_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btQuadWord.h b/dali-physics/third-party/bullet3/src/LinearMath/btQuadWord.h
new file mode 100644 (file)
index 0000000..851596b
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SIMD_QUADWORD_H
+#define BT_SIMD_QUADWORD_H
+
+#include "btScalar.h"
+#include "btMinMax.h"
+
+#if defined(__CELLOS_LV2) && defined(__SPU__)
+#include <altivec.h>
+#endif
+
+/**@brief The btQuadWord 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.
+ */
+#ifndef USE_LIBSPE2
+ATTRIBUTE_ALIGNED16(class)
+btQuadWord
+#else
+class btQuadWord
+#endif
+{
+protected:
+#if defined(__SPU__) && defined(__CELLOS_LV2__)
+       union {
+               vec_float4 mVec128;
+               btScalar m_floats[4];
+       };
+
+public:
+       vec_float4 get128() const
+       {
+               return mVec128;
+       }
+
+protected:
+#else  //__CELLOS_LV2__ __SPU__
+
+#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
+       union {
+               btSimdFloat4 mVec128;
+               btScalar m_floats[4];
+       };
+
+public:
+       SIMD_FORCE_INLINE btSimdFloat4 get128() const
+       {
+               return mVec128;
+       }
+       SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
+       {
+               mVec128 = v128;
+       }
+#else
+       btScalar m_floats[4];
+#endif  // BT_USE_SSE
+
+#endif  //__CELLOS_LV2__ __SPU__
+
+public:
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+
+       // Set Vector
+       SIMD_FORCE_INLINE btQuadWord(const btSimdFloat4 vec)
+       {
+               mVec128 = vec;
+       }
+
+       // Copy constructor
+       SIMD_FORCE_INLINE btQuadWord(const btQuadWord& rhs)
+       {
+               mVec128 = rhs.mVec128;
+       }
+
+       // Assignment Operator
+       SIMD_FORCE_INLINE btQuadWord&
+       operator=(const btQuadWord& v)
+       {
+               mVec128 = v.mVec128;
+
+               return *this;
+       }
+
+#endif
+
+       /**@brief Return the x value */
+       SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+       /**@brief Return the y value */
+       SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+       /**@brief Return the z value */
+       SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+       /**@brief Set the x value */
+       SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x; };
+       /**@brief Set the y value */
+       SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y; };
+       /**@brief Set the z value */
+       SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z; };
+       /**@brief Set the w value */
+       SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w; };
+       /**@brief Return the x value */
+       SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+       /**@brief Return the y value */
+       SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+       /**@brief Return the z value */
+       SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+       /**@brief Return the w value */
+       SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+       //SIMD_FORCE_INLINE btScalar&       operator[](int i)       { return (&m_floats[0])[i]; }
+       //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
+       ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+       SIMD_FORCE_INLINE operator btScalar*() { return &m_floats[0]; }
+       SIMD_FORCE_INLINE operator const btScalar*() const { return &m_floats[0]; }
+
+       SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const
+       {
+#ifdef BT_USE_SSE
+               return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+               return ((m_floats[3] == other.m_floats[3]) &&
+                               (m_floats[2] == other.m_floats[2]) &&
+                               (m_floats[1] == other.m_floats[1]) &&
+                               (m_floats[0] == other.m_floats[0]));
+#endif
+       }
+
+       SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const
+       {
+               return !(*this == other);
+       }
+
+       /**@brief Set x,y,z and zero w 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+       SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+       {
+               m_floats[0] = _x;
+               m_floats[1] = _y;
+               m_floats[2] = _z;
+               m_floats[3] = 0.f;
+       }
+
+       /*              void getValue(btScalar *m) const 
+               {
+                       m[0] = m_floats[0];
+                       m[1] = m_floats[1];
+                       m[2] = m_floats[2];
+               }
+*/
+       /**@brief Set the values 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+       SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+       {
+               m_floats[0] = _x;
+               m_floats[1] = _y;
+               m_floats[2] = _z;
+               m_floats[3] = _w;
+       }
+       /**@brief No initialization constructor */
+       SIMD_FORCE_INLINE btQuadWord()
+       //      :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.))
+       {
+       }
+
+       /**@brief Three argument constructor (zeros w)
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+       SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+       {
+               m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
+       }
+
+       /**@brief Initializing constructor
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+       SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+       {
+               m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
+       }
+
+       /**@brief Set each element to the max of the current values and the values of another btQuadWord
+   * @param other The other btQuadWord to compare with 
+   */
+       SIMD_FORCE_INLINE void setMax(const btQuadWord& other)
+       {
+#ifdef BT_USE_SSE
+               mVec128 = _mm_max_ps(mVec128, other.mVec128);
+#elif defined(BT_USE_NEON)
+               mVec128 = vmaxq_f32(mVec128, other.mVec128);
+#else
+               btSetMax(m_floats[0], other.m_floats[0]);
+               btSetMax(m_floats[1], other.m_floats[1]);
+               btSetMax(m_floats[2], other.m_floats[2]);
+               btSetMax(m_floats[3], other.m_floats[3]);
+#endif
+       }
+       /**@brief Set each element to the min of the current values and the values of another btQuadWord
+   * @param other The other btQuadWord to compare with 
+   */
+       SIMD_FORCE_INLINE void setMin(const btQuadWord& other)
+       {
+#ifdef BT_USE_SSE
+               mVec128 = _mm_min_ps(mVec128, other.mVec128);
+#elif defined(BT_USE_NEON)
+               mVec128 = vminq_f32(mVec128, other.mVec128);
+#else
+               btSetMin(m_floats[0], other.m_floats[0]);
+               btSetMin(m_floats[1], other.m_floats[1]);
+               btSetMin(m_floats[2], other.m_floats[2]);
+               btSetMin(m_floats[3], other.m_floats[3]);
+#endif
+       }
+};
+
+#endif  //BT_SIMD_QUADWORD_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btQuaternion.h b/dali-physics/third-party/bullet3/src/LinearMath/btQuaternion.h
new file mode 100644 (file)
index 0000000..40d6e14
--- /dev/null
@@ -0,0 +1,1021 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SIMD__QUATERNION_H_
+#define BT_SIMD__QUATERNION_H_
+
+#include "btVector3.h"
+#include "btQuadWord.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btQuaternionData btQuaternionDoubleData
+#define btQuaternionDataName "btQuaternionDoubleData"
+#else
+#define btQuaternionData btQuaternionFloatData
+#define btQuaternionDataName "btQuaternionFloatData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+#ifdef BT_USE_SSE
+
+//const __m128 ATTRIBUTE_ALIGNED16(vOnes) = {1.0f, 1.0f, 1.0f, 1.0f};
+#define vOnes (_mm_set_ps(1.0f, 1.0f, 1.0f, 1.0f))
+
+#endif
+
+#if defined(BT_USE_SSE)
+
+#define vQInv (_mm_set_ps(+0.0f, -0.0f, -0.0f, -0.0f))
+#define vPPPM (_mm_set_ps(-0.0f, +0.0f, +0.0f, +0.0f))
+
+#elif defined(BT_USE_NEON)
+
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(vQInv) = {-0.0f, -0.0f, -0.0f, +0.0f};
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(vPPPM) = {+0.0f, +0.0f, +0.0f, -0.0f};
+
+#endif
+
+/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */
+class btQuaternion : public btQuadWord
+{
+public:
+       /**@brief No initialization constructor */
+       btQuaternion() {}
+
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+       // Set Vector
+       SIMD_FORCE_INLINE btQuaternion(const btSimdFloat4 vec)
+       {
+               mVec128 = vec;
+       }
+
+       // Copy constructor
+       SIMD_FORCE_INLINE btQuaternion(const btQuaternion& rhs)
+       {
+               mVec128 = rhs.mVec128;
+       }
+
+       // Assignment Operator
+       SIMD_FORCE_INLINE btQuaternion&
+       operator=(const btQuaternion& v)
+       {
+               mVec128 = v.mVec128;
+
+               return *this;
+       }
+
+#endif
+
+       //              template <typename btScalar>
+       //              explicit Quaternion(const btScalar *v) : Tuple4<btScalar>(v) {}
+       /**@brief Constructor from scalars */
+       btQuaternion(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+               : btQuadWord(_x, _y, _z, _w)
+       {
+       }
+       /**@brief Axis angle Constructor
+   * @param axis The axis which the rotation is around
+   * @param angle The magnitude of the rotation around the angle (Radians) */
+       btQuaternion(const btVector3& _axis, const btScalar& _angle)
+       {
+               setRotation(_axis, _angle);
+       }
+       /**@brief Constructor from Euler angles
+   * @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z
+   * @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y
+   * @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */
+       btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+       {
+#ifndef BT_EULER_DEFAULT_ZYX
+               setEuler(yaw, pitch, roll);
+#else
+               setEulerZYX(yaw, pitch, roll);
+#endif
+       }
+       /**@brief Set the rotation using axis angle notation 
+   * @param axis The axis around which to rotate
+   * @param angle The magnitude of the rotation in Radians */
+       void setRotation(const btVector3& axis, const btScalar& _angle)
+       {
+               btScalar d = axis.length();
+               btAssert(d != btScalar(0.0));
+               btScalar s = btSin(_angle * btScalar(0.5)) / d;
+               setValue(axis.x() * s, axis.y() * s, axis.z() * s,
+                                btCos(_angle * btScalar(0.5)));
+       }
+       /**@brief Set the quaternion using Euler angles
+   * @param yaw Angle around Y
+   * @param pitch Angle around X
+   * @param roll Angle around Z */
+       void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+       {
+               btScalar halfYaw = btScalar(yaw) * btScalar(0.5);
+               btScalar halfPitch = btScalar(pitch) * btScalar(0.5);
+               btScalar halfRoll = btScalar(roll) * btScalar(0.5);
+               btScalar cosYaw = btCos(halfYaw);
+               btScalar sinYaw = btSin(halfYaw);
+               btScalar cosPitch = btCos(halfPitch);
+               btScalar sinPitch = btSin(halfPitch);
+               btScalar cosRoll = btCos(halfRoll);
+               btScalar sinRoll = btSin(halfRoll);
+               setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
+                                cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
+                                sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
+                                cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
+       }
+       /**@brief Set the quaternion using euler angles 
+   * @param yaw Angle around Z
+   * @param pitch Angle around Y
+   * @param roll Angle around X */
+       void setEulerZYX(const btScalar& yawZ, const btScalar& pitchY, const btScalar& rollX)
+       {
+               btScalar halfYaw = btScalar(yawZ) * btScalar(0.5);
+               btScalar halfPitch = btScalar(pitchY) * btScalar(0.5);
+               btScalar halfRoll = btScalar(rollX) * btScalar(0.5);
+               btScalar cosYaw = btCos(halfYaw);
+               btScalar sinYaw = btSin(halfYaw);
+               btScalar cosPitch = btCos(halfPitch);
+               btScalar sinPitch = btSin(halfPitch);
+               btScalar cosRoll = btCos(halfRoll);
+               btScalar sinRoll = btSin(halfRoll);
+               setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,   //x
+                                cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,   //y
+                                cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,   //z
+                                cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);  //formerly yzx
+       }
+
+       /**@brief Get the euler angles from this quaternion
+          * @param yaw Angle around Z
+          * @param pitch Angle around Y
+          * @param roll Angle around X */
+       void getEulerZYX(btScalar& yawZ, btScalar& pitchY, btScalar& rollX) const
+       {
+               btScalar squ;
+               btScalar sqx;
+               btScalar sqy;
+               btScalar sqz;
+               btScalar sarg;
+               sqx = m_floats[0] * m_floats[0];
+               sqy = m_floats[1] * m_floats[1];
+               sqz = m_floats[2] * m_floats[2];
+               squ = m_floats[3] * m_floats[3];
+               sarg = btScalar(-2.) * (m_floats[0] * m_floats[2] - m_floats[3] * m_floats[1]);
+
+               // If the pitch angle is PI/2 or -PI/2, we can only compute
+               // the sum roll + yaw.  However, any combination that gives
+               // the right sum will produce the correct orientation, so we
+               // set rollX = 0 and compute yawZ.
+               if (sarg <= -btScalar(0.99999))
+               {
+                       pitchY = btScalar(-0.5) * SIMD_PI;
+                       rollX = 0;
+                       yawZ = btScalar(2) * btAtan2(m_floats[0], -m_floats[1]);
+               }
+               else if (sarg >= btScalar(0.99999))
+               {
+                       pitchY = btScalar(0.5) * SIMD_PI;
+                       rollX = 0;
+                       yawZ = btScalar(2) * btAtan2(-m_floats[0], m_floats[1]);
+               }
+               else
+               {
+                       pitchY = btAsin(sarg);
+                       rollX = btAtan2(2 * (m_floats[1] * m_floats[2] + m_floats[3] * m_floats[0]), squ - sqx - sqy + sqz);
+                       yawZ = btAtan2(2 * (m_floats[0] * m_floats[1] + m_floats[3] * m_floats[2]), squ + sqx - sqy - sqz);
+               }
+       }
+
+       /**@brief Add two quaternions
+   * @param q The quaternion to add to this one */
+       SIMD_FORCE_INLINE btQuaternion& operator+=(const btQuaternion& q)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               mVec128 = _mm_add_ps(mVec128, q.mVec128);
+#elif defined(BT_USE_NEON)
+               mVec128 = vaddq_f32(mVec128, q.mVec128);
+#else
+               m_floats[0] += q.x();
+               m_floats[1] += q.y();
+               m_floats[2] += q.z();
+               m_floats[3] += q.m_floats[3];
+#endif
+               return *this;
+       }
+
+       /**@brief Subtract out a quaternion
+   * @param q The quaternion to subtract from this one */
+       btQuaternion& operator-=(const btQuaternion& q)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               mVec128 = _mm_sub_ps(mVec128, q.mVec128);
+#elif defined(BT_USE_NEON)
+               mVec128 = vsubq_f32(mVec128, q.mVec128);
+#else
+               m_floats[0] -= q.x();
+               m_floats[1] -= q.y();
+               m_floats[2] -= q.z();
+               m_floats[3] -= q.m_floats[3];
+#endif
+               return *this;
+       }
+
+       /**@brief Scale this quaternion
+   * @param s The scalar to scale by */
+       btQuaternion& operator*=(const btScalar& s)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 vs = _mm_load_ss(&s);  //        (S 0 0 0)
+               vs = bt_pshufd_ps(vs, 0);     //        (S S S S)
+               mVec128 = _mm_mul_ps(mVec128, vs);
+#elif defined(BT_USE_NEON)
+               mVec128 = vmulq_n_f32(mVec128, s);
+#else
+               m_floats[0] *= s;
+               m_floats[1] *= s;
+               m_floats[2] *= s;
+               m_floats[3] *= s;
+#endif
+               return *this;
+       }
+
+       /**@brief Multiply this quaternion by q on the right
+   * @param q The other quaternion 
+   * Equivilant to this = this * q */
+       btQuaternion& operator*=(const btQuaternion& q)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 vQ2 = q.get128();
+
+               __m128 A1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(0, 1, 2, 0));
+               __m128 B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3, 3, 3, 0));
+
+               A1 = A1 * B1;
+
+               __m128 A2 = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 1));
+               __m128 B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1));
+
+               A2 = A2 * B2;
+
+               B1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(2, 0, 1, 2));
+               B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2));
+
+               B1 = B1 * B2;  //       A3 *= B3
+
+               mVec128 = bt_splat_ps(mVec128, 3);  //  A0
+               mVec128 = mVec128 * vQ2;            //  A0 * B0
+
+               A1 = A1 + A2;                // AB12
+               mVec128 = mVec128 - B1;      // AB03 = AB0 - AB3
+               A1 = _mm_xor_ps(A1, vPPPM);  // change sign of the last element
+               mVec128 = mVec128 + A1;      // AB03 + AB12
+
+#elif defined(BT_USE_NEON)
+
+               float32x4_t vQ1 = mVec128;
+               float32x4_t vQ2 = q.get128();
+               float32x4_t A0, A1, B1, A2, B2, A3, B3;
+               float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+               {
+                       float32x2x2_t tmp;
+                       tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1));  // {z x}, {w y}
+                       vQ1zx = tmp.val[0];
+
+                       tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2));  // {z x}, {w y}
+                       vQ2zx = tmp.val[0];
+               }
+               vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+               vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+               vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+               vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+               A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx);                     // X Y  z x
+               B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx);  // W W  W X
+
+               A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+               B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+               A3 = vcombine_f32(vQ1zx, vQ1yz);  // Z X Y Z
+               B3 = vcombine_f32(vQ2yz, vQ2xz);  // Y Z x z
+
+               A1 = vmulq_f32(A1, B1);
+               A2 = vmulq_f32(A2, B2);
+               A3 = vmulq_f32(A3, B3);                           //    A3 *= B3
+               A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1);  //    A0 * B0
+
+               A1 = vaddq_f32(A1, A2);  //     AB12 = AB1 + AB2
+               A0 = vsubq_f32(A0, A3);  //     AB03 = AB0 - AB3
+
+               //      change the sign of the last element
+               A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+               A0 = vaddq_f32(A0, A1);  //     AB03 + AB12
+
+               mVec128 = A0;
+#else
+               setValue(
+                       m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
+                       m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(),
+                       m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(),
+                       m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z());
+#endif
+               return *this;
+       }
+       /**@brief Return the dot product between this quaternion and another
+   * @param q The other quaternion */
+       btScalar dot(const btQuaternion& q) const
+       {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 vd;
+
+               vd = _mm_mul_ps(mVec128, q.mVec128);
+
+               __m128 t = _mm_movehl_ps(vd, vd);
+               vd = _mm_add_ps(vd, t);
+               t = _mm_shuffle_ps(vd, vd, 0x55);
+               vd = _mm_add_ss(vd, t);
+
+               return _mm_cvtss_f32(vd);
+#elif defined(BT_USE_NEON)
+               float32x4_t vd = vmulq_f32(mVec128, q.mVec128);
+               float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
+               x = vpadd_f32(x, x);
+               return vget_lane_f32(x, 0);
+#else
+               return m_floats[0] * q.x() +
+                          m_floats[1] * q.y() +
+                          m_floats[2] * q.z() +
+                          m_floats[3] * q.m_floats[3];
+#endif
+       }
+
+       /**@brief Return the length squared of the quaternion */
+       btScalar length2() const
+       {
+               return dot(*this);
+       }
+
+       /**@brief Return the length of the quaternion */
+       btScalar length() const
+       {
+               return btSqrt(length2());
+       }
+       btQuaternion& safeNormalize()
+       {
+               btScalar l2 = length2();
+               if (l2 > SIMD_EPSILON)
+               {
+                       normalize();
+               }
+               return *this;
+       }
+       /**@brief Normalize the quaternion 
+   * Such that x^2 + y^2 + z^2 +w^2 = 1 */
+       btQuaternion& normalize()
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 vd;
+
+               vd = _mm_mul_ps(mVec128, mVec128);
+
+               __m128 t = _mm_movehl_ps(vd, vd);
+               vd = _mm_add_ps(vd, t);
+               t = _mm_shuffle_ps(vd, vd, 0x55);
+               vd = _mm_add_ss(vd, t);
+
+               vd = _mm_sqrt_ss(vd);
+               vd = _mm_div_ss(vOnes, vd);
+               vd = bt_pshufd_ps(vd, 0);  // splat
+               mVec128 = _mm_mul_ps(mVec128, vd);
+
+               return *this;
+#else
+               return *this /= length();
+#endif
+       }
+
+       /**@brief Return a scaled version of this quaternion
+   * @param s The scale factor */
+       SIMD_FORCE_INLINE btQuaternion
+       operator*(const btScalar& s) const
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 vs = _mm_load_ss(&s);  //        (S 0 0 0)
+               vs = bt_pshufd_ps(vs, 0x00);  //        (S S S S)
+
+               return btQuaternion(_mm_mul_ps(mVec128, vs));
+#elif defined(BT_USE_NEON)
+               return btQuaternion(vmulq_n_f32(mVec128, s));
+#else
+               return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s);
+#endif
+       }
+
+       /**@brief Return an inversely scaled versionof this quaternion
+   * @param s The inverse scale factor */
+       btQuaternion operator/(const btScalar& s) const
+       {
+               btAssert(s != btScalar(0.0));
+               return *this * (btScalar(1.0) / s);
+       }
+
+       /**@brief Inversely scale this quaternion
+   * @param s The scale factor */
+       btQuaternion& operator/=(const btScalar& s)
+       {
+               btAssert(s != btScalar(0.0));
+               return *this *= btScalar(1.0) / s;
+       }
+
+       /**@brief Return a normalized version of this quaternion */
+       btQuaternion normalized() const
+       {
+               return *this / length();
+       }
+       /**@brief Return the ***half*** angle between this quaternion and the other
+   * @param q The other quaternion */
+       btScalar angle(const btQuaternion& q) const
+       {
+               btScalar s = btSqrt(length2() * q.length2());
+               btAssert(s != btScalar(0.0));
+               return btAcos(dot(q) / s);
+       }
+
+       /**@brief Return the angle between this quaternion and the other along the shortest path
+       * @param q The other quaternion */
+       btScalar angleShortestPath(const btQuaternion& q) const
+       {
+               btScalar s = btSqrt(length2() * q.length2());
+               btAssert(s != btScalar(0.0));
+               if (dot(q) < 0)  // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
+                       return btAcos(dot(-q) / s) * btScalar(2.0);
+               else
+                       return btAcos(dot(q) / s) * btScalar(2.0);
+       }
+
+       /**@brief Return the angle [0, 2Pi] of rotation represented by this quaternion */
+       btScalar getAngle() const
+       {
+               btScalar s = btScalar(2.) * btAcos(m_floats[3]);
+               return s;
+       }
+
+       /**@brief Return the angle [0, Pi] of rotation represented by this quaternion along the shortest path */
+       btScalar getAngleShortestPath() const
+       {
+               btScalar s;
+               if (m_floats[3] >= 0)
+                       s = btScalar(2.) * btAcos(m_floats[3]);
+               else
+                       s = btScalar(2.) * btAcos(-m_floats[3]);
+               return s;
+       }
+
+       /**@brief Return the axis of the rotation represented by this quaternion */
+       btVector3 getAxis() const
+       {
+               btScalar s_squared = 1.f - m_floats[3] * m_floats[3];
+
+               if (s_squared < btScalar(10.) * SIMD_EPSILON)  //Check for divide by zero
+                       return btVector3(1.0, 0.0, 0.0);           // Arbitrary
+               btScalar s = 1.f / btSqrt(s_squared);
+               return btVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s);
+       }
+
+       /**@brief Return the inverse of this quaternion */
+       btQuaternion inverse() const
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               return btQuaternion(_mm_xor_ps(mVec128, vQInv));
+#elif defined(BT_USE_NEON)
+               return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)vQInv));
+#else
+               return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
+#endif
+       }
+
+       /**@brief Return the sum of this quaternion and the other 
+   * @param q2 The other quaternion */
+       SIMD_FORCE_INLINE btQuaternion
+       operator+(const btQuaternion& q2) const
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               return btQuaternion(_mm_add_ps(mVec128, q2.mVec128));
+#elif defined(BT_USE_NEON)
+               return btQuaternion(vaddq_f32(mVec128, q2.mVec128));
+#else
+               const btQuaternion& q1 = *this;
+               return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
+#endif
+       }
+
+       /**@brief Return the difference between this quaternion and the other 
+   * @param q2 The other quaternion */
+       SIMD_FORCE_INLINE btQuaternion
+       operator-(const btQuaternion& q2) const
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               return btQuaternion(_mm_sub_ps(mVec128, q2.mVec128));
+#elif defined(BT_USE_NEON)
+               return btQuaternion(vsubq_f32(mVec128, q2.mVec128));
+#else
+               const btQuaternion& q1 = *this;
+               return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
+#endif
+       }
+
+       /**@brief Return the negative of this quaternion 
+   * This simply negates each element */
+       SIMD_FORCE_INLINE btQuaternion operator-() const
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               return btQuaternion(_mm_xor_ps(mVec128, btvMzeroMask));
+#elif defined(BT_USE_NEON)
+               return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)btvMzeroMask));
+#else
+               const btQuaternion& q2 = *this;
+               return btQuaternion(-q2.x(), -q2.y(), -q2.z(), -q2.m_floats[3]);
+#endif
+       }
+       /**@todo document this and it's use */
+       SIMD_FORCE_INLINE btQuaternion farthest(const btQuaternion& qd) const
+       {
+               btQuaternion diff, sum;
+               diff = *this - qd;
+               sum = *this + qd;
+               if (diff.dot(diff) > sum.dot(sum))
+                       return qd;
+               return (-qd);
+       }
+
+       /**@todo document this and it's use */
+       SIMD_FORCE_INLINE btQuaternion nearest(const btQuaternion& qd) const
+       {
+               btQuaternion diff, sum;
+               diff = *this - qd;
+               sum = *this + qd;
+               if (diff.dot(diff) < sum.dot(sum))
+                       return qd;
+               return (-qd);
+       }
+
+       /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
+   * @param q The other quaternion to interpolate with 
+   * @param t The ratio between this and q to interpolate.  If t = 0 the result is this, if t=1 the result is q.
+   * Slerp interpolates assuming constant velocity.  */
+       btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
+       {
+               const btScalar magnitude = btSqrt(length2() * q.length2());
+               btAssert(magnitude > btScalar(0));
+
+               const btScalar product = dot(q) / magnitude;
+               const btScalar absproduct = btFabs(product);
+
+               if (absproduct < btScalar(1.0 - SIMD_EPSILON))
+               {
+                       // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
+                       const btScalar theta = btAcos(absproduct);
+                       const btScalar d = btSin(theta);
+                       btAssert(d > btScalar(0));
+
+                       const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1);
+                       const btScalar s0 = btSin((btScalar(1.0) - t) * theta) / d;
+                       const btScalar s1 = btSin(sign * t * theta) / d;
+
+                       return btQuaternion(
+                               (m_floats[0] * s0 + q.x() * s1),
+                               (m_floats[1] * s0 + q.y() * s1),
+                               (m_floats[2] * s0 + q.z() * s1),
+                               (m_floats[3] * s0 + q.w() * s1));
+               }
+               else
+               {
+                       return *this;
+               }
+       }
+
+       static const btQuaternion& getIdentity()
+       {
+               static const btQuaternion identityQuat(btScalar(0.), btScalar(0.), btScalar(0.), btScalar(1.));
+               return identityQuat;
+       }
+
+       SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
+
+       SIMD_FORCE_INLINE void serialize(struct btQuaternionData& dataOut) const;
+
+       SIMD_FORCE_INLINE void deSerialize(const struct btQuaternionFloatData& dataIn);
+
+       SIMD_FORCE_INLINE void deSerialize(const struct btQuaternionDoubleData& dataIn);
+
+       SIMD_FORCE_INLINE void serializeFloat(struct btQuaternionFloatData& dataOut) const;
+
+       SIMD_FORCE_INLINE void deSerializeFloat(const struct btQuaternionFloatData& dataIn);
+
+       SIMD_FORCE_INLINE void serializeDouble(struct btQuaternionDoubleData& dataOut) const;
+
+       SIMD_FORCE_INLINE void deSerializeDouble(const struct btQuaternionDoubleData& dataIn);
+};
+
+/**@brief Return the product of two quaternions */
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btQuaternion& q1, const btQuaternion& q2)
+{
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+       __m128 vQ1 = q1.get128();
+       __m128 vQ2 = q2.get128();
+       __m128 A0, A1, B1, A2, B2;
+
+       A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0, 1, 2, 0));  // X Y  z x     //      vtrn
+       B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3, 3, 3, 0));  // W W  W X     // vdup vext
+
+       A1 = A1 * B1;
+
+       A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1, 2, 0, 1));  // Y Z  X Y     // vext
+       B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1));  // z x  Y Y     // vtrn vdup
+
+       A2 = A2 * B2;
+
+       B1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2, 0, 1, 2));  // z x Y Z      // vtrn vext
+       B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2));  // Y Z x z      // vext vtrn
+
+       B1 = B1 * B2;  //       A3 *= B3
+
+       A0 = bt_splat_ps(vQ1, 3);  //   A0
+       A0 = A0 * vQ2;             //   A0 * B0
+
+       A1 = A1 + A2;  //       AB12
+       A0 = A0 - B1;  //       AB03 = AB0 - AB3
+
+       A1 = _mm_xor_ps(A1, vPPPM);  // change sign of the last element
+       A0 = A0 + A1;                // AB03 + AB12
+
+       return btQuaternion(A0);
+
+#elif defined(BT_USE_NEON)
+
+       float32x4_t vQ1 = q1.get128();
+       float32x4_t vQ2 = q2.get128();
+       float32x4_t A0, A1, B1, A2, B2, A3, B3;
+       float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+       {
+               float32x2x2_t tmp;
+               tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1));  // {z x}, {w y}
+               vQ1zx = tmp.val[0];
+
+               tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2));  // {z x}, {w y}
+               vQ2zx = tmp.val[0];
+       }
+       vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+       vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+       vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+       vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+       A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx);                     // X Y  z x
+       B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx);  // W W  W X
+
+       A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+       B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+       A3 = vcombine_f32(vQ1zx, vQ1yz);  // Z X Y Z
+       B3 = vcombine_f32(vQ2yz, vQ2xz);  // Y Z x z
+
+       A1 = vmulq_f32(A1, B1);
+       A2 = vmulq_f32(A2, B2);
+       A3 = vmulq_f32(A3, B3);                           //    A3 *= B3
+       A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1);  //    A0 * B0
+
+       A1 = vaddq_f32(A1, A2);  //     AB12 = AB1 + AB2
+       A0 = vsubq_f32(A0, A3);  //     AB03 = AB0 - AB3
+
+       //      change the sign of the last element
+       A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+       A0 = vaddq_f32(A0, A1);  //     AB03 + AB12
+
+       return btQuaternion(A0);
+
+#else
+       return btQuaternion(
+               q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
+               q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
+               q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
+               q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z());
+#endif
+}
+
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btQuaternion& q, const btVector3& w)
+{
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+       __m128 vQ1 = q.get128();
+       __m128 vQ2 = w.get128();
+       __m128 A1, B1, A2, B2, A3, B3;
+
+       A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(3, 3, 3, 0));
+       B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(0, 1, 2, 0));
+
+       A1 = A1 * B1;
+
+       A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1, 2, 0, 1));
+       B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1));
+
+       A2 = A2 * B2;
+
+       A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2, 0, 1, 2));
+       B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2));
+
+       A3 = A3 * B3;  //       A3 *= B3
+
+       A1 = A1 + A2;                // AB12
+       A1 = _mm_xor_ps(A1, vPPPM);  // change sign of the last element
+       A1 = A1 - A3;                // AB123 = AB12 - AB3
+
+       return btQuaternion(A1);
+
+#elif defined(BT_USE_NEON)
+
+       float32x4_t vQ1 = q.get128();
+       float32x4_t vQ2 = w.get128();
+       float32x4_t A1, B1, A2, B2, A3, B3;
+       float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
+
+       vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
+       {
+               float32x2x2_t tmp;
+
+               tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2));  // {z x}, {w y}
+               vQ2zx = tmp.val[0];
+
+               tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1));  // {z x}, {w y}
+               vQ1zx = tmp.val[0];
+       }
+
+       vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+       vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+       vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+       A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx);  // W W  W X
+       B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx);                     // X Y  z x
+
+       A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+       B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+       A3 = vcombine_f32(vQ1zx, vQ1yz);  // Z X Y Z
+       B3 = vcombine_f32(vQ2yz, vQ2xz);  // Y Z x z
+
+       A1 = vmulq_f32(A1, B1);
+       A2 = vmulq_f32(A2, B2);
+       A3 = vmulq_f32(A3, B3);  //     A3 *= B3
+
+       A1 = vaddq_f32(A1, A2);  //     AB12 = AB1 + AB2
+
+       //      change the sign of the last element
+       A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+
+       A1 = vsubq_f32(A1, A3);  //     AB123 = AB12 - AB3
+
+       return btQuaternion(A1);
+
+#else
+       return btQuaternion(
+               q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
+               q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
+               q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
+               -q.x() * w.x() - q.y() * w.y() - q.z() * w.z());
+#endif
+}
+
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btVector3& w, const btQuaternion& q)
+{
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+       __m128 vQ1 = w.get128();
+       __m128 vQ2 = q.get128();
+       __m128 A1, B1, A2, B2, A3, B3;
+
+       A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0, 1, 2, 0));  // X Y  z x
+       B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3, 3, 3, 0));  // W W  W X
+
+       A1 = A1 * B1;
+
+       A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1, 2, 0, 1));
+       B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1));
+
+       A2 = A2 * B2;
+
+       A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2, 0, 1, 2));
+       B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2));
+
+       A3 = A3 * B3;  //       A3 *= B3
+
+       A1 = A1 + A2;                // AB12
+       A1 = _mm_xor_ps(A1, vPPPM);  // change sign of the last element
+       A1 = A1 - A3;                // AB123 = AB12 - AB3
+
+       return btQuaternion(A1);
+
+#elif defined(BT_USE_NEON)
+
+       float32x4_t vQ1 = w.get128();
+       float32x4_t vQ2 = q.get128();
+       float32x4_t A1, B1, A2, B2, A3, B3;
+       float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+       {
+               float32x2x2_t tmp;
+
+               tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1));  // {z x}, {w y}
+               vQ1zx = tmp.val[0];
+
+               tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2));  // {z x}, {w y}
+               vQ2zx = tmp.val[0];
+       }
+       vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+       vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+       vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+       vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+       A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx);                     // X Y  z x
+       B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx);  // W W  W X
+
+       A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+       B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+       A3 = vcombine_f32(vQ1zx, vQ1yz);  // Z X Y Z
+       B3 = vcombine_f32(vQ2yz, vQ2xz);  // Y Z x z
+
+       A1 = vmulq_f32(A1, B1);
+       A2 = vmulq_f32(A2, B2);
+       A3 = vmulq_f32(A3, B3);  //     A3 *= B3
+
+       A1 = vaddq_f32(A1, A2);  //     AB12 = AB1 + AB2
+
+       //      change the sign of the last element
+       A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+
+       A1 = vsubq_f32(A1, A3);  //     AB123 = AB12 - AB3
+
+       return btQuaternion(A1);
+
+#else
+       return btQuaternion(
+               +w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
+               +w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
+               +w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
+               -w.x() * q.x() - w.y() * q.y() - w.z() * q.z());
+#endif
+}
+
+/**@brief Calculate the dot product between two quaternions */
+SIMD_FORCE_INLINE btScalar
+dot(const btQuaternion& q1, const btQuaternion& q2)
+{
+       return q1.dot(q2);
+}
+
+/**@brief Return the length of a quaternion */
+SIMD_FORCE_INLINE btScalar
+length(const btQuaternion& q)
+{
+       return q.length();
+}
+
+/**@brief Return the angle between two quaternions*/
+SIMD_FORCE_INLINE btScalar
+btAngle(const btQuaternion& q1, const btQuaternion& q2)
+{
+       return q1.angle(q2);
+}
+
+/**@brief Return the inverse of a quaternion*/
+SIMD_FORCE_INLINE btQuaternion
+inverse(const btQuaternion& q)
+{
+       return q.inverse();
+}
+
+/**@brief Return the result of spherical linear interpolation betwen two quaternions 
+ * @param q1 The first quaternion
+ * @param q2 The second quaternion 
+ * @param t The ration between q1 and q2.  t = 0 return q1, t=1 returns q2 
+ * Slerp assumes constant velocity between positions. */
+SIMD_FORCE_INLINE btQuaternion
+slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t)
+{
+       return q1.slerp(q2, t);
+}
+
+SIMD_FORCE_INLINE btVector3
+quatRotate(const btQuaternion& rotation, const btVector3& v)
+{
+       btQuaternion q = rotation * v;
+       q *= rotation.inverse();
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+       return btVector3(_mm_and_ps(q.get128(), btvFFF0fMask));
+#elif defined(BT_USE_NEON)
+       return btVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), btvFFF0Mask));
+#else
+       return btVector3(q.getX(), q.getY(), q.getZ());
+#endif
+}
+
+SIMD_FORCE_INLINE btQuaternion
+shortestArcQuat(const btVector3& v0, const btVector3& v1)  // Game Programming Gems 2.10. make sure v0,v1 are normalized
+{
+       btVector3 c = v0.cross(v1);
+       btScalar d = v0.dot(v1);
+
+       if (d < -1.0 + SIMD_EPSILON)
+       {
+               btVector3 n, unused;
+               btPlaneSpace1(v0, n, unused);
+               return btQuaternion(n.x(), n.y(), n.z(), 0.0f);  // just pick any vector that is orthogonal to v0
+       }
+
+       btScalar s = btSqrt((1.0f + d) * 2.0f);
+       btScalar rs = 1.0f / s;
+
+       return btQuaternion(c.getX() * rs, c.getY() * rs, c.getZ() * rs, s * 0.5f);
+}
+
+SIMD_FORCE_INLINE btQuaternion
+shortestArcQuatNormalize2(btVector3& v0, btVector3& v1)
+{
+       v0.normalize();
+       v1.normalize();
+       return shortestArcQuat(v0, v1);
+}
+
+struct btQuaternionFloatData
+{
+       float m_floats[4];
+};
+
+struct btQuaternionDoubleData
+{
+       double m_floats[4];
+};
+
+SIMD_FORCE_INLINE void btQuaternion::serializeFloat(struct btQuaternionFloatData& dataOut) const
+{
+       ///could also do a memcpy, check if it is worth it
+       for (int i = 0; i < 4; i++)
+               dataOut.m_floats[i] = float(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btQuaternion::deSerializeFloat(const struct btQuaternionFloatData& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btQuaternion::serializeDouble(struct btQuaternionDoubleData& dataOut) const
+{
+       ///could also do a memcpy, check if it is worth it
+       for (int i = 0; i < 4; i++)
+               dataOut.m_floats[i] = double(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btQuaternion::deSerializeDouble(const struct btQuaternionDoubleData& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btQuaternion::serialize(struct btQuaternionData& dataOut) const
+{
+       ///could also do a memcpy, check if it is worth it
+       for (int i = 0; i < 4; i++)
+               dataOut.m_floats[i] = m_floats[i];
+}
+
+SIMD_FORCE_INLINE void btQuaternion::deSerialize(const struct btQuaternionFloatData& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = (btScalar)dataIn.m_floats[i];
+}
+
+SIMD_FORCE_INLINE void btQuaternion::deSerialize(const struct btQuaternionDoubleData& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = (btScalar)dataIn.m_floats[i];
+}
+
+#endif  //BT_SIMD__QUATERNION_H_
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btQuickprof.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btQuickprof.cpp
new file mode 100644 (file)
index 0000000..33b51eb
--- /dev/null
@@ -0,0 +1,805 @@
+/*
+
+***************************************************************************************************
+**
+** profile.cpp
+**
+** 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).
+
+#include "btQuickprof.h"
+#include "btThreads.h"
+
+#ifdef __CELLOS_LV2__
+#include <sys/sys_time.h>
+#include <sys/time_util.h>
+#include <stdio.h>
+#endif
+
+#if defined(SUNOS) || defined(__SUNOS__)
+#include <stdio.h>
+#endif
+#ifdef __APPLE__
+#include <mach/mach_time.h>
+#include <TargetConditionals.h>
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+
+#define BT_USE_WINDOWS_TIMERS
+#define WIN32_LEAN_AND_MEAN
+#define NOWINRES
+#define NOMCX
+#define NOIME
+
+#ifdef _XBOX
+#include <Xtl.h>
+#else  //_XBOX
+#include <windows.h>
+
+#if WINVER < 0x0602
+#define GetTickCount64 GetTickCount
+#endif
+
+#endif  //_XBOX
+
+#include <time.h>
+
+#else  //_WIN32
+#include <sys/time.h>
+
+#ifdef BT_LINUX_REALTIME
+//required linking against rt (librt)
+#include <time.h>
+#endif  //BT_LINUX_REALTIME
+
+#endif  //_WIN32
+
+#define mymin(a, b) (a > b ? a : b)
+
+struct btClockData
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+       LARGE_INTEGER mClockFrequency;
+       LONGLONG mStartTick;
+       LARGE_INTEGER mStartTime;
+#else
+#ifdef __CELLOS_LV2__
+       uint64_t mStartTime;
+#else
+#ifdef __APPLE__
+       uint64_t mStartTimeNano;
+#endif
+       struct timeval mStartTime;
+#endif
+#endif  //__CELLOS_LV2__
+};
+
+///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
+btClock::btClock()
+{
+       m_data = new btClockData;
+#ifdef BT_USE_WINDOWS_TIMERS
+       QueryPerformanceFrequency(&m_data->mClockFrequency);
+#endif
+       reset();
+}
+
+btClock::~btClock()
+{
+       delete m_data;
+}
+
+btClock::btClock(const btClock& other)
+{
+       m_data = new btClockData;
+       *m_data = *other.m_data;
+}
+
+btClock& btClock::operator=(const btClock& other)
+{
+       *m_data = *other.m_data;
+       return *this;
+}
+
+/// Resets the initial reference time.
+void btClock::reset()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+       QueryPerformanceCounter(&m_data->mStartTime);
+       m_data->mStartTick = GetTickCount64();
+#else
+#ifdef __CELLOS_LV2__
+
+       typedef uint64_t ClockSize;
+       ClockSize newTime;
+       //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+       SYS_TIMEBASE_GET(newTime);
+       m_data->mStartTime = newTime;
+#else
+#ifdef __APPLE__
+       m_data->mStartTimeNano = mach_absolute_time();
+#endif
+       gettimeofday(&m_data->mStartTime, 0);
+#endif
+#endif
+}
+
+/// Returns the time in ms since the last call to reset or since
+/// the btClock was created.
+unsigned long long int btClock::getTimeMilliseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+       LARGE_INTEGER currentTime;
+       QueryPerformanceCounter(&currentTime);
+       LONGLONG elapsedTime = currentTime.QuadPart -
+                                                  m_data->mStartTime.QuadPart;
+       // Compute the number of millisecond ticks elapsed.
+       unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
+                                                                                         m_data->mClockFrequency.QuadPart);
+
+       return msecTicks;
+#else
+
+#ifdef __CELLOS_LV2__
+       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 - m_data->mStartTime)) / dFreq);
+#else
+
+       struct timeval currentTime;
+       gettimeofday(&currentTime, 0);
+       return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
+                  (currentTime.tv_usec - m_data->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 long int btClock::getTimeMicroseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+       //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
+       LARGE_INTEGER currentTime, elapsedTime;
+
+       QueryPerformanceCounter(&currentTime);
+       elapsedTime.QuadPart = currentTime.QuadPart -
+                                                  m_data->mStartTime.QuadPart;
+       elapsedTime.QuadPart *= 1000000;
+       elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
+
+       return (unsigned long long)elapsedTime.QuadPart;
+#else
+
+#ifdef __CELLOS_LV2__
+       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 - m_data->mStartTime)) / dFreq);
+#else
+
+       struct timeval currentTime;
+       gettimeofday(&currentTime, 0);
+       return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
+                  (currentTime.tv_usec - m_data->mStartTime.tv_usec);
+#endif  //__CELLOS_LV2__
+#endif
+}
+
+unsigned long long int btClock::getTimeNanoseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+       //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
+       LARGE_INTEGER currentTime, elapsedTime;
+
+       QueryPerformanceCounter(&currentTime);
+       elapsedTime.QuadPart = currentTime.QuadPart -
+                                                  m_data->mStartTime.QuadPart;
+       elapsedTime.QuadPart *= 1000000000;
+       elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
+
+       return (unsigned long long)elapsedTime.QuadPart;
+#else
+
+#ifdef __CELLOS_LV2__
+       uint64_t freq = sys_time_get_timebase_frequency();
+       double dFreq = ((double)freq) / 1e9;
+       typedef uint64_t ClockSize;
+       ClockSize newTime;
+       //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+       SYS_TIMEBASE_GET(newTime);
+
+       return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq);
+#else
+#ifdef __APPLE__
+       uint64_t ticks = mach_absolute_time() - m_data->mStartTimeNano;
+       static long double conversion = 0.0L;
+       if (0.0L == conversion)
+       {
+               // attempt to get conversion to nanoseconds
+               mach_timebase_info_data_t info;
+               int err = mach_timebase_info(&info);
+               if (err)
+               {
+                       btAssert(0);
+                       conversion = 1.;
+               }
+               conversion = info.numer / info.denom;
+       }
+       return (ticks * conversion);
+
+#else  //__APPLE__
+
+#ifdef BT_LINUX_REALTIME
+       timespec ts;
+       clock_gettime(CLOCK_REALTIME, &ts);
+       return 1000000000 * ts.tv_sec + ts.tv_nsec;
+#else
+       struct timeval currentTime;
+       gettimeofday(&currentTime, 0);
+       return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1e9 +
+                  (currentTime.tv_usec - m_data->mStartTime.tv_usec) * 1000;
+#endif  //BT_LINUX_REALTIME
+
+#endif  //__APPLE__
+#endif  //__CELLOS_LV2__
+#endif
+}
+
+/// Returns the time in s since the last call to reset or since
+/// the Clock was created.
+btScalar btClock::getTimeSeconds()
+{
+       static const btScalar microseconds_to_seconds = btScalar(0.000001);
+       return btScalar(getTimeMicroseconds()) * microseconds_to_seconds;
+}
+
+#ifndef BT_NO_PROFILE
+
+static btClock gProfileClock;
+
+inline void Profile_Get_Ticks(unsigned long int* ticks)
+{
+       *ticks = (unsigned long int)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),
+                                                                                                                                        m_userPtr(0)
+{
+       Reset();
+}
+
+void CProfileNode::CleanupMemory()
+{
+       delete (Child);
+       Child = NULL;
+       delete (Sibling);
+       Sibling = NULL;
+}
+
+CProfileNode::~CProfileNode(void)
+{
+       CleanupMemory();
+}
+
+/***********************************************************************************************
+ * 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;
+
+       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 gRoots[BT_QUICKPROF_MAX_THREAD_COUNT] = {
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
+       CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL)};
+
+CProfileNode* gCurrentNodes[BT_QUICKPROF_MAX_THREAD_COUNT] =
+       {
+               &gRoots[0],
+               &gRoots[1],
+               &gRoots[2],
+               &gRoots[3],
+               &gRoots[4],
+               &gRoots[5],
+               &gRoots[6],
+               &gRoots[7],
+               &gRoots[8],
+               &gRoots[9],
+               &gRoots[10],
+               &gRoots[11],
+               &gRoots[12],
+               &gRoots[13],
+               &gRoots[14],
+               &gRoots[15],
+               &gRoots[16],
+               &gRoots[17],
+               &gRoots[18],
+               &gRoots[19],
+               &gRoots[20],
+               &gRoots[21],
+               &gRoots[22],
+               &gRoots[23],
+               &gRoots[24],
+               &gRoots[25],
+               &gRoots[26],
+               &gRoots[27],
+               &gRoots[28],
+               &gRoots[29],
+               &gRoots[30],
+               &gRoots[31],
+               &gRoots[32],
+               &gRoots[33],
+               &gRoots[34],
+               &gRoots[35],
+               &gRoots[36],
+               &gRoots[37],
+               &gRoots[38],
+               &gRoots[39],
+               &gRoots[40],
+               &gRoots[41],
+               &gRoots[42],
+               &gRoots[43],
+               &gRoots[44],
+               &gRoots[45],
+               &gRoots[46],
+               &gRoots[47],
+               &gRoots[48],
+               &gRoots[49],
+               &gRoots[50],
+               &gRoots[51],
+               &gRoots[52],
+               &gRoots[53],
+               &gRoots[54],
+               &gRoots[55],
+               &gRoots[56],
+               &gRoots[57],
+               &gRoots[58],
+               &gRoots[59],
+               &gRoots[60],
+               &gRoots[61],
+               &gRoots[62],
+               &gRoots[63],
+};
+
+int CProfileManager::FrameCounter = 0;
+unsigned long int CProfileManager::ResetTime = 0;
+
+CProfileIterator* CProfileManager::Get_Iterator(void)
+{
+       int threadIndex = btQuickprofGetCurrentThreadIndex2();
+       if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+               return 0;
+
+       return new CProfileIterator(&gRoots[threadIndex]);
+}
+
+void CProfileManager::CleanupMemory(void)
+{
+       for (int i = 0; i < BT_QUICKPROF_MAX_THREAD_COUNT; i++)
+       {
+               gRoots[i].CleanupMemory();
+       }
+}
+
+/***********************************************************************************************
+ * 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)
+{
+       int threadIndex = btQuickprofGetCurrentThreadIndex2();
+       if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+               return;
+
+       if (name != gCurrentNodes[threadIndex]->Get_Name())
+       {
+               gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Sub_Node(name);
+       }
+
+       gCurrentNodes[threadIndex]->Call();
+}
+
+/***********************************************************************************************
+ * CProfileManager::Stop_Profile -- Stop timing and record the results.                       *
+ *=============================================================================================*/
+void CProfileManager::Stop_Profile(void)
+{
+       int threadIndex = btQuickprofGetCurrentThreadIndex2();
+       if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+               return;
+
+       // Return will indicate whether we should back up to our parent (we may
+       // be profiling a recursive function)
+       if (gCurrentNodes[threadIndex]->Return())
+       {
+               gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->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)
+{
+       gProfileClock.reset();
+       int threadIndex = btQuickprofGetCurrentThreadIndex2();
+       if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
+               return;
+       gRoots[threadIndex].Reset();
+       gRoots[threadIndex].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();
+}
+
+#include <stdio.h>
+
+void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
+{
+       profileIterator->First();
+       if (profileIterator->Is_Done())
+               return;
+
+       float accumulated_time = 0, parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
+       int i;
+       int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
+       for (i = 0; i < spacing; i++) printf(".");
+       printf("----------------------------------\n");
+       for (i = 0; i < spacing; i++) printf(".");
+       printf("Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time);
+       float totalTime = 0.f;
+
+       int numChildren = 0;
+
+       for (i = 0; !profileIterator->Is_Done(); i++, profileIterator->Next())
+       {
+               numChildren++;
+               float current_total_time = profileIterator->Get_Current_Total_Time();
+               accumulated_time += current_total_time;
+               float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
+               {
+                       int i;
+                       for (i = 0; i < spacing; i++) printf(".");
+               }
+               printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n", i, profileIterator->Get_Current_Name(), fraction, (current_total_time / (double)frames_since_reset), profileIterator->Get_Current_Total_Calls());
+               totalTime += current_total_time;
+               //recurse into children
+       }
+
+       if (parent_time < accumulated_time)
+       {
+               //printf("what's wrong\n");
+       }
+       for (i = 0; i < spacing; i++) printf(".");
+       printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:", parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
+
+       for (i = 0; i < numChildren; i++)
+       {
+               profileIterator->Enter_Child(i);
+               dumpRecursive(profileIterator, spacing + 3);
+               profileIterator->Enter_Parent();
+       }
+}
+
+void CProfileManager::dumpAll()
+{
+       CProfileIterator* profileIterator = 0;
+       profileIterator = CProfileManager::Get_Iterator();
+
+       dumpRecursive(profileIterator, 0);
+
+       CProfileManager::Release_Iterator(profileIterator);
+}
+
+
+void btEnterProfileZoneDefault(const char* name)
+{
+}
+void btLeaveProfileZoneDefault()
+{
+}
+
+#else
+void btEnterProfileZoneDefault(const char* name)
+{
+}
+void btLeaveProfileZoneDefault()
+{
+}
+#endif  //BT_NO_PROFILE
+
+
+// clang-format off
+#if defined(_WIN32) && (defined(__MINGW32__) || defined(__MINGW64__))
+  #define BT_HAVE_TLS 1
+#elif __APPLE__ && !TARGET_OS_IPHONE
+  // TODO: Modern versions of iOS support TLS now with updated version checking.
+  #define BT_HAVE_TLS 1
+#elif __linux__
+  #define BT_HAVE_TLS 1
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+  // TODO: At the moment disabling purposely OpenBSD, albeit tls support exists but not fully functioning
+  #define BT_HAVE_TLS 1
+#endif
+
+// __thread is broken on Andorid clang until r12b. See
+// https://github.com/android-ndk/ndk/issues/8
+#if defined(__ANDROID__) && defined(__clang__)
+  #if __has_include(<android/ndk-version.h>)
+    #include <android/ndk-version.h>
+  #endif  // __has_include(<android/ndk-version.h>)
+  #if defined(__NDK_MAJOR__) && \
+    ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1)))
+    #undef BT_HAVE_TLS
+  #endif
+#endif  // defined(__ANDROID__) && defined(__clang__)
+// clang-format on
+
+unsigned int btQuickprofGetCurrentThreadIndex2()
+{
+       const unsigned int kNullIndex = ~0U;
+
+#if BT_THREADSAFE
+       return btGetCurrentThreadIndex();
+#else
+#if defined(BT_HAVE_TLS)
+       static __thread unsigned int sThreadIndex = kNullIndex;
+#elif defined(_WIN32)
+       __declspec(thread) static unsigned int sThreadIndex = kNullIndex;
+#else
+       unsigned int sThreadIndex = 0;
+       return -1;
+#endif
+
+       static int gThreadCounter = 0;
+
+       if (sThreadIndex == kNullIndex)
+       {
+               sThreadIndex = gThreadCounter++;
+       }
+       return sThreadIndex;
+#endif  //BT_THREADSAFE
+}
+
+static btEnterProfileZoneFunc* bts_enterFunc = btEnterProfileZoneDefault;
+static btLeaveProfileZoneFunc* bts_leaveFunc = btLeaveProfileZoneDefault;
+
+void btEnterProfileZone(const char* name)
+{
+       (bts_enterFunc)(name);
+}
+void btLeaveProfileZone()
+{
+       (bts_leaveFunc)();
+}
+
+btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc()
+{
+       return bts_enterFunc;
+}
+btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc()
+{
+       return bts_leaveFunc;
+}
+
+void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc)
+{
+       bts_enterFunc = enterFunc;
+}
+void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc)
+{
+       bts_leaveFunc = leaveFunc;
+}
+
+CProfileSample::CProfileSample(const char* name)
+{
+       btEnterProfileZone(name);
+}
+
+CProfileSample::~CProfileSample(void)
+{
+       btLeaveProfileZone();
+}
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btQuickprof.h b/dali-physics/third-party/bullet3/src/LinearMath/btQuickprof.h
new file mode 100644 (file)
index 0000000..990d401
--- /dev/null
@@ -0,0 +1,200 @@
+
+/***************************************************************************************************
+**
+** 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).
+
+#ifndef BT_QUICK_PROF_H
+#define BT_QUICK_PROF_H
+
+#include "btScalar.h"
+#define USE_BT_CLOCK 1
+
+#ifdef USE_BT_CLOCK
+
+///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
+class btClock
+{
+public:
+       btClock();
+
+       btClock(const btClock& other);
+       btClock& operator=(const btClock& other);
+
+       ~btClock();
+
+       /// Resets the initial reference time.
+       void reset();
+
+       /// Returns the time in ms since the last call to reset or since
+       /// the btClock was created.
+       unsigned long long int getTimeMilliseconds();
+
+       /// Returns the time in us since the last call to reset or since
+       /// the Clock was created.
+       unsigned long long int getTimeMicroseconds();
+
+       unsigned long long int getTimeNanoseconds();
+
+       /// Returns the time in s since the last call to reset or since
+       /// the Clock was created.
+       btScalar getTimeSeconds();
+
+private:
+       struct btClockData* m_data;
+};
+
+#endif  //USE_BT_CLOCK
+
+typedef void(btEnterProfileZoneFunc)(const char* msg);
+typedef void(btLeaveProfileZoneFunc)();
+
+btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc();
+btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc();
+
+void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc);
+void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc);
+
+#ifndef BT_ENABLE_PROFILE
+#define BT_NO_PROFILE 1
+#endif  //BT_NO_PROFILE
+
+const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT = 64;
+
+//btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined,
+//otherwise returns thread index in range [0..maxThreads]
+unsigned int btQuickprofGetCurrentThreadIndex2();
+
+#ifndef BT_NO_PROFILE
+
+
+#include <stdio.h>  //@todo remove this, backwards compatibility
+
+#include "btAlignedAllocator.h"
+#include <new>
+
+///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);
+
+       CProfileNode* Get_Parent(void) { return Parent; }
+       CProfileNode* Get_Sibling(void) { return Sibling; }
+       CProfileNode* Get_Child(void) { return Child; }
+
+       void CleanupMemory();
+       void Reset(void);
+       void Call(void);
+       bool Return(void);
+
+       const char* Get_Name(void) { return Name; }
+       int Get_Total_Calls(void) { return TotalCalls; }
+       float Get_Total_Time(void) { return TotalTime; }
+       void* GetUserPointer() const { return m_userPtr; }
+       void SetUserPointer(void* ptr) { m_userPtr = ptr; }
+
+protected:
+       const char* Name;
+       int TotalCalls;
+       float TotalTime;
+       unsigned long int StartTime;
+       int RecursionCounter;
+
+       CProfileNode* Parent;
+       CProfileNode* Child;
+       CProfileNode* Sibling;
+       void* m_userPtr;
+};
+
+///An iterator to navigate through the tree
+class CProfileIterator
+{
+public:
+       // 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); }
+
+       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
+
+       // 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(); }
+
+       void* Get_Current_UserPointer(void) { return CurrentChild->GetUserPointer(); }
+       void Set_Current_UserPointer(void* ptr) { CurrentChild->SetUserPointer(ptr); }
+       // 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(); }
+
+protected:
+       CProfileNode* CurrentParent;
+       CProfileNode* CurrentChild;
+
+       CProfileIterator(CProfileNode* start);
+       friend class CProfileManager;
+};
+
+///The Manager for the Profile system
+class CProfileManager
+{
+public:
+       static void Start_Profile(const char* name);
+       static void Stop_Profile(void);
+
+       static void CleanupMemory(void);
+       //      {
+       //              Root.CleanupMemory();
+       //      }
+
+       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);
+
+       static CProfileIterator* Get_Iterator(void);
+       //      {
+       //
+       //              return new CProfileIterator( &Root );
+       //      }
+       static void Release_Iterator(CProfileIterator* iterator) { delete (iterator); }
+
+       static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
+
+       static void dumpAll();
+
+private:
+       static int FrameCounter;
+       static unsigned long int ResetTime;
+};
+
+#endif  //#ifndef BT_NO_PROFILE
+
+///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);
+
+       ~CProfileSample(void);
+};
+
+#define BT_PROFILE(name) CProfileSample __profile(name)
+
+#endif  //BT_QUICK_PROF_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btRandom.h b/dali-physics/third-party/bullet3/src/LinearMath/btRandom.h
new file mode 100644 (file)
index 0000000..7753130
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_GEN_RANDOM_H
+#define BT_GEN_RANDOM_H
+
+#ifdef MT19937
+
+#include <limits.h>
+#include <mt19937.h>
+
+#define GEN_RAND_MAX UINT_MAX
+
+SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); }
+SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); }
+
+#else
+
+#include <stdlib.h>
+
+#define GEN_RAND_MAX RAND_MAX
+
+SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); }
+SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); }
+
+#endif
+
+#endif  //BT_GEN_RANDOM_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btReducedVector.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btReducedVector.cpp
new file mode 100644 (file)
index 0000000..1539584
--- /dev/null
@@ -0,0 +1,170 @@
+//
+//  btReducedVector.cpp
+//  LinearMath
+//
+//  Created by Xuchen Han on 4/4/20.
+//
+#include <stdio.h>
+#include "btReducedVector.h"
+#include <cmath>
+
+// returns the projection of this onto other
+btReducedVector btReducedVector::proj(const btReducedVector& other) const
+{
+    btReducedVector ret(m_sz);
+    btScalar other_length2 = other.length2();
+    if (other_length2 < SIMD_EPSILON)
+    {
+        return ret;
+    }
+    return other*(this->dot(other))/other_length2;
+}
+
+void btReducedVector::normalize()
+{
+    if (this->length2() < SIMD_EPSILON)
+    {
+        m_indices.clear();
+        m_vecs.clear();
+        return;
+    }
+    *this /= std::sqrt(this->length2());
+}
+
+bool btReducedVector::testAdd() const
+{
+    int sz = 5;
+    btAlignedObjectArray<int> id1;
+    id1.push_back(1);
+    id1.push_back(3);
+    btAlignedObjectArray<btVector3> v1;
+    v1.push_back(btVector3(1,0,1));
+    v1.push_back(btVector3(3,1,5));
+    btAlignedObjectArray<int> id2;
+    id2.push_back(2);
+    id2.push_back(3);
+    id2.push_back(5);
+    btAlignedObjectArray<btVector3> v2;
+    v2.push_back(btVector3(2,3,1));
+    v2.push_back(btVector3(3,4,9));
+    v2.push_back(btVector3(0,4,0));
+    btAlignedObjectArray<int> id3;
+    id3.push_back(1);
+    id3.push_back(2);
+    id3.push_back(3);
+    id3.push_back(5);
+    btAlignedObjectArray<btVector3> v3;
+    v3.push_back(btVector3(1,0,1));
+    v3.push_back(btVector3(2,3,1));
+    v3.push_back(btVector3(6,5,14));
+    v3.push_back(btVector3(0,4,0));
+    btReducedVector rv1(sz, id1, v1);
+    btReducedVector rv2(sz, id2, v2);
+    btReducedVector ans(sz, id3, v3);
+    bool ret = ((ans == rv1+rv2) && (ans == rv2+rv1));
+    if (!ret)
+        printf("btReducedVector testAdd failed\n");
+    return ret;
+}
+
+bool btReducedVector::testMinus() const
+{
+    int sz = 5;
+    btAlignedObjectArray<int> id1;
+    id1.push_back(1);
+    id1.push_back(3);
+    btAlignedObjectArray<btVector3> v1;
+    v1.push_back(btVector3(1,0,1));
+    v1.push_back(btVector3(3,1,5));
+    btAlignedObjectArray<int> id2;
+    id2.push_back(2);
+    id2.push_back(3);
+    id2.push_back(5);
+    btAlignedObjectArray<btVector3> v2;
+    v2.push_back(btVector3(2,3,1));
+    v2.push_back(btVector3(3,4,9));
+    v2.push_back(btVector3(0,4,0));
+    btAlignedObjectArray<int> id3;
+    id3.push_back(1);
+    id3.push_back(2);
+    id3.push_back(3);
+    id3.push_back(5);
+    btAlignedObjectArray<btVector3> v3;
+    v3.push_back(btVector3(-1,-0,-1));
+    v3.push_back(btVector3(2,3,1));
+    v3.push_back(btVector3(0,3,4));
+    v3.push_back(btVector3(0,4,0));
+    btReducedVector rv1(sz, id1, v1);
+    btReducedVector rv2(sz, id2, v2);
+    btReducedVector ans(sz, id3, v3);
+    bool ret = (ans == rv2-rv1);
+    if (!ret)
+        printf("btReducedVector testMinus failed\n");
+    return ret;
+}
+
+bool btReducedVector::testDot() const
+{
+    int sz = 5;
+    btAlignedObjectArray<int> id1;
+    id1.push_back(1);
+    id1.push_back(3);
+    btAlignedObjectArray<btVector3> v1;
+    v1.push_back(btVector3(1,0,1));
+    v1.push_back(btVector3(3,1,5));
+    btAlignedObjectArray<int> id2;
+    id2.push_back(2);
+    id2.push_back(3);
+    id2.push_back(5);
+    btAlignedObjectArray<btVector3> v2;
+    v2.push_back(btVector3(2,3,1));
+    v2.push_back(btVector3(3,4,9));
+    v2.push_back(btVector3(0,4,0));
+    btReducedVector rv1(sz, id1, v1);
+    btReducedVector rv2(sz, id2, v2);
+    btScalar ans = 58;
+    bool ret = (ans == rv2.dot(rv1) && ans == rv1.dot(rv2));
+    ans = 14+16+9+16+81;
+    ret &= (ans==rv2.dot(rv2));
+    
+    if (!ret)
+        printf("btReducedVector testDot failed\n");
+    return ret;
+}
+
+bool btReducedVector::testMultiply() const
+{
+    int sz = 5;
+    btAlignedObjectArray<int> id1;
+    id1.push_back(1);
+    id1.push_back(3);
+    btAlignedObjectArray<btVector3> v1;
+    v1.push_back(btVector3(1,0,1));
+    v1.push_back(btVector3(3,1,5));
+    btScalar s = 2;
+    btReducedVector rv1(sz, id1, v1);
+    btAlignedObjectArray<int> id2;
+    id2.push_back(1);
+    id2.push_back(3);
+    btAlignedObjectArray<btVector3> v2;
+    v2.push_back(btVector3(2,0,2));
+    v2.push_back(btVector3(6,2,10));
+    btReducedVector ans(sz, id2, v2);
+    bool ret = (ans == rv1*s);
+    if (!ret)
+        printf("btReducedVector testMultiply failed\n");
+    return ret;
+}
+
+void btReducedVector::test() const
+{
+    bool ans = testAdd() && testMinus() && testDot() && testMultiply();
+    if (ans)
+    {
+        printf("All tests passed\n");
+    }
+    else
+    {
+        printf("Tests failed\n");
+    }
+}
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btReducedVector.h b/dali-physics/third-party/bullet3/src/LinearMath/btReducedVector.h
new file mode 100644 (file)
index 0000000..313a427
--- /dev/null
@@ -0,0 +1,320 @@
+//
+//  btReducedVectors.h
+//  BulletLinearMath
+//
+//  Created by Xuchen Han on 4/4/20.
+//
+#ifndef btReducedVectors_h
+#define btReducedVectors_h
+#include "btVector3.h"
+#include "btMatrix3x3.h"
+#include "btAlignedObjectArray.h"
+#include <stdio.h>
+#include <vector>
+#include <algorithm>
+struct TwoInts
+{
+    int a,b;
+};
+inline bool operator<(const TwoInts& A, const TwoInts& B)
+{
+    return A.b < B.b;
+}
+
+
+// A helper vector type used for CG projections
+class btReducedVector
+{
+public:
+    btAlignedObjectArray<int> m_indices;
+    btAlignedObjectArray<btVector3> m_vecs;
+    int m_sz; // all m_indices value < m_sz
+public:
+       btReducedVector():m_sz(0)
+       {
+               m_indices.resize(0);
+               m_vecs.resize(0);
+        m_indices.clear();
+        m_vecs.clear();
+       }
+       
+    btReducedVector(int sz): m_sz(sz)
+    {
+        m_indices.resize(0);
+        m_vecs.resize(0);
+        m_indices.clear();
+        m_vecs.clear();
+    }
+    
+    btReducedVector(int sz, const btAlignedObjectArray<int>& indices, const btAlignedObjectArray<btVector3>& vecs): m_sz(sz), m_indices(indices), m_vecs(vecs)
+    {
+    }
+    
+    void simplify()
+    {
+        btAlignedObjectArray<int> old_indices(m_indices);
+        btAlignedObjectArray<btVector3> old_vecs(m_vecs);
+        m_indices.resize(0);
+        m_vecs.resize(0);
+        m_indices.clear();
+        m_vecs.clear();
+        for (int i = 0; i < old_indices.size(); ++i)
+        {
+            if (old_vecs[i].length2() > SIMD_EPSILON)
+            {
+                m_indices.push_back(old_indices[i]);
+                m_vecs.push_back(old_vecs[i]);
+            }
+        }
+    }
+    
+    btReducedVector operator+(const btReducedVector& other)
+    {
+               btReducedVector ret(m_sz);
+               int i=0, j=0;
+               while (i < m_indices.size() && j < other.m_indices.size())
+               {
+                       if (m_indices[i] < other.m_indices[j])
+                       {
+                               ret.m_indices.push_back(m_indices[i]);
+                               ret.m_vecs.push_back(m_vecs[i]);
+                               ++i;
+                       }
+                       else if (m_indices[i] > other.m_indices[j])
+                       {
+                               ret.m_indices.push_back(other.m_indices[j]);
+                               ret.m_vecs.push_back(other.m_vecs[j]);
+                               ++j;
+                       }
+                       else
+                       {
+                               ret.m_indices.push_back(other.m_indices[j]);
+                               ret.m_vecs.push_back(m_vecs[i] + other.m_vecs[j]);
+                               ++i; ++j;
+                       }
+               }
+               while (i < m_indices.size())
+               {
+                       ret.m_indices.push_back(m_indices[i]);
+                       ret.m_vecs.push_back(m_vecs[i]);
+                       ++i;
+               }
+               while (j < other.m_indices.size())
+               {
+                       ret.m_indices.push_back(other.m_indices[j]);
+                       ret.m_vecs.push_back(other.m_vecs[j]);
+                       ++j;
+               }
+        ret.simplify();
+        return ret;
+    }
+
+    btReducedVector operator-()
+    {
+        btReducedVector ret(m_sz);
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            ret.m_indices.push_back(m_indices[i]);
+            ret.m_vecs.push_back(-m_vecs[i]);
+        }
+        ret.simplify();
+        return ret;
+    }
+    
+    btReducedVector operator-(const btReducedVector& other)
+    {
+               btReducedVector ret(m_sz);
+               int i=0, j=0;
+               while (i < m_indices.size() && j < other.m_indices.size())
+               {
+                       if (m_indices[i] < other.m_indices[j])
+                       {
+                               ret.m_indices.push_back(m_indices[i]);
+                               ret.m_vecs.push_back(m_vecs[i]);
+                               ++i;
+                       }
+                       else if (m_indices[i] > other.m_indices[j])
+                       {
+                               ret.m_indices.push_back(other.m_indices[j]);
+                               ret.m_vecs.push_back(-other.m_vecs[j]);
+                               ++j;
+                       }
+                       else
+                       {
+                               ret.m_indices.push_back(other.m_indices[j]);
+                               ret.m_vecs.push_back(m_vecs[i] - other.m_vecs[j]);
+                               ++i; ++j;
+                       }
+               }
+               while (i < m_indices.size())
+               {
+                       ret.m_indices.push_back(m_indices[i]);
+                       ret.m_vecs.push_back(m_vecs[i]);
+                       ++i;
+               }
+               while (j < other.m_indices.size())
+               {
+                       ret.m_indices.push_back(other.m_indices[j]);
+                       ret.m_vecs.push_back(-other.m_vecs[j]);
+                       ++j;
+               }
+        ret.simplify();
+               return ret;
+    }
+    
+    bool operator==(const btReducedVector& other) const
+    {
+        if (m_sz != other.m_sz)
+            return false;
+        if (m_indices.size() != other.m_indices.size())
+            return false;
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            if (m_indices[i] != other.m_indices[i] || m_vecs[i] != other.m_vecs[i])
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    bool operator!=(const btReducedVector& other) const
+    {
+        return !(*this == other);
+    }
+       
+       btReducedVector& operator=(const btReducedVector& other)
+       {
+               if (this == &other)
+               {
+                       return *this;
+               }
+        m_sz = other.m_sz;
+               m_indices.copyFromArray(other.m_indices);
+               m_vecs.copyFromArray(other.m_vecs);
+               return *this;
+       }
+    
+    btScalar dot(const btReducedVector& other) const
+    {
+        btScalar ret = 0;
+        int j = 0;
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            while (j < other.m_indices.size() && other.m_indices[j] < m_indices[i])
+            {
+                ++j;
+            }
+            if (j < other.m_indices.size() && other.m_indices[j] == m_indices[i])
+            {
+                ret += m_vecs[i].dot(other.m_vecs[j]);
+//                ++j;
+            }
+        }
+        return ret;
+    }
+    
+    btScalar dot(const btAlignedObjectArray<btVector3>& other) const
+    {
+        btScalar ret = 0;
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            ret += m_vecs[i].dot(other[m_indices[i]]);
+        }
+        return ret;
+    }
+    
+    btScalar length2() const
+    {
+        return this->dot(*this);
+    }
+       
+       void normalize();
+    
+    // returns the projection of this onto other
+    btReducedVector proj(const btReducedVector& other) const;
+    
+    bool testAdd() const;
+    
+    bool testMinus() const;
+    
+    bool testDot() const;
+    
+    bool testMultiply() const;
+    
+    void test() const;
+    
+    void print() const
+    {
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            printf("%d: (%f, %f, %f)/", m_indices[i], m_vecs[i][0],m_vecs[i][1],m_vecs[i][2]);
+        }
+        printf("\n");
+    }
+    
+    
+    void sort()
+    {
+        std::vector<TwoInts> tuples;
+        for (int i = 0; i < m_indices.size(); ++i)
+        {
+            TwoInts ti;
+            ti.a = i;
+            ti.b = m_indices[i];
+            tuples.push_back(ti);
+        }
+        std::sort(tuples.begin(), tuples.end());
+        btAlignedObjectArray<int> new_indices;
+        btAlignedObjectArray<btVector3> new_vecs;
+        for (size_t i = 0; i < tuples.size(); ++i)
+        {
+            new_indices.push_back(tuples[i].b);
+            new_vecs.push_back(m_vecs[tuples[i].a]);
+        }
+        m_indices = new_indices;
+        m_vecs = new_vecs;
+    }
+};
+
+SIMD_FORCE_INLINE btReducedVector operator*(const btReducedVector& v, btScalar s)
+{
+    btReducedVector ret(v.m_sz);
+    for (int i = 0; i < v.m_indices.size(); ++i)
+    {
+        ret.m_indices.push_back(v.m_indices[i]);
+        ret.m_vecs.push_back(s*v.m_vecs[i]);
+    }
+    ret.simplify();
+    return ret;
+}
+
+SIMD_FORCE_INLINE btReducedVector operator*(btScalar s, const btReducedVector& v)
+{
+    return v*s;
+}
+
+SIMD_FORCE_INLINE btReducedVector operator/(const btReducedVector& v, btScalar s)
+{
+       return v * (1.0/s);
+}
+
+SIMD_FORCE_INLINE btReducedVector& operator/=(btReducedVector& v, btScalar s)
+{
+       v = v/s;
+       return v;
+}
+
+SIMD_FORCE_INLINE btReducedVector& operator+=(btReducedVector& v1, const btReducedVector& v2)
+{
+       v1 = v1+v2;
+       return v1;
+}
+
+SIMD_FORCE_INLINE btReducedVector& operator-=(btReducedVector& v1, const btReducedVector& v2)
+{
+       v1 = v1-v2;
+       return v1;
+}
+
+#endif /* btReducedVectors_h */
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btScalar.h b/dali-physics/third-party/bullet3/src/LinearMath/btScalar.h
new file mode 100644 (file)
index 0000000..dea1b05
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+Copyright (c) 2003-2009 Erwin Coumans  http://bullet.googlecode.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.
+*/
+
+#ifndef BT_SCALAR_H
+#define BT_SCALAR_H
+
+#ifdef BT_MANAGED_CODE
+//Aligned data types not supported in managed code
+#pragma unmanaged
+#endif
+
+#include <math.h>
+#include <stdlib.h>  //size_t for MSVC 6.0
+#include <float.h>
+
+/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
+#define BT_BULLET_VERSION 325
+
+inline int btGetVersion()
+{
+       return BT_BULLET_VERSION;
+}
+
+inline int btIsDoublePrecision()
+{
+  #ifdef BT_USE_DOUBLE_PRECISION
+  return true;
+  #else
+  return false;
+  #endif
+}
+
+
+// The following macro "BT_NOT_EMPTY_FILE" can be put into a file
+// in order suppress the MS Visual C++ Linker warning 4221
+//
+// warning LNK4221: no public symbols found; archive member will be inaccessible
+//
+// This warning occurs on PC and XBOX when a file compiles out completely
+// has no externally visible symbols which may be dependant on configuration
+// #defines and options.
+//
+// see more https://stackoverflow.com/questions/1822887/what-is-the-best-way-to-eliminate-ms-visual-c-linker-warning-warning-lnk422
+
+#if defined(_MSC_VER)
+#define BT_NOT_EMPTY_FILE_CAT_II(p, res) res
+#define BT_NOT_EMPTY_FILE_CAT_I(a, b) BT_NOT_EMPTY_FILE_CAT_II(~, a##b)
+#define BT_NOT_EMPTY_FILE_CAT(a, b) BT_NOT_EMPTY_FILE_CAT_I(a, b)
+#define BT_NOT_EMPTY_FILE                                      \
+       namespace                                                  \
+       {                                                          \
+       char BT_NOT_EMPTY_FILE_CAT(NoEmptyFileDummy, __COUNTER__); \
+       }
+#else
+#define BT_NOT_EMPTY_FILE
+#endif
+
+// clang and most formatting tools don't support indentation of preprocessor guards, so turn it off
+// clang-format off
+#if defined(DEBUG) || defined (_DEBUG)
+       #define BT_DEBUG
+#endif
+
+#ifdef _WIN32
+       #if  defined(__GNUC__)  // it should handle both MINGW and CYGWIN
+               #define SIMD_FORCE_INLINE        __inline__ __attribute__((always_inline))
+               #define ATTRIBUTE_ALIGNED16(a)   a __attribute__((aligned(16)))
+               #define ATTRIBUTE_ALIGNED64(a)   a __attribute__((aligned(64)))
+               #define ATTRIBUTE_ALIGNED128(a)  a __attribute__((aligned(128)))
+       #elif ( defined(_MSC_VER) && _MSC_VER < 1300 )
+               #define SIMD_FORCE_INLINE inline
+               #define ATTRIBUTE_ALIGNED16(a) a
+               #define ATTRIBUTE_ALIGNED64(a) a
+               #define ATTRIBUTE_ALIGNED128(a) a
+       #elif defined(_M_ARM)
+               #define SIMD_FORCE_INLINE __forceinline
+               #define ATTRIBUTE_ALIGNED16(a) __declspec() a
+               #define ATTRIBUTE_ALIGNED64(a) __declspec() a
+               #define ATTRIBUTE_ALIGNED128(a) __declspec () a
+       #else//__MINGW32__
+               //#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_ALIGNED64(a) __declspec(align(64)) 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
+
+#if defined (_M_ARM) || defined (_M_ARM64)
+            //Do not turn SSE on for ARM (may want to turn on BT_USE_NEON however)
+#elif (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
+
+#ifdef __clang__
+#define __BT_DISABLE_SSE__
+#endif
+#ifndef __BT_DISABLE_SSE__
+                       #if _MSC_VER>1400
+                               #define BT_USE_SIMD_VECTOR3
+                       #endif
+                       #define BT_USE_SSE
+#endif//__BT_DISABLE_SSE__
+                       #ifdef BT_USE_SSE
+
+#if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default)
+                       #define BT_ALLOW_SSE4
+#endif //(_MSC_FULL_VER >= 160040219)
+
+                       //BT_USE_SSE_IN_API is disabled under Windows by default, because 
+                       //it makes it harder to integrate Bullet into your application under Windows 
+                       //(structured embedding Bullet structs/classes need to be 16-byte aligned)
+                       //with relatively little performance gain
+                       //If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries
+                       //you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage)
+                       //#define BT_USE_SSE_IN_API
+                       #endif //BT_USE_SSE
+                       #include <emmintrin.h>
+#endif
+
+               #endif//_XBOX
+
+       #endif //__MINGW32__
+
+       #ifdef BT_DEBUG
+               #ifdef _MSC_VER
+                       #include <stdio.h>
+                       #define btAssert(x) { if(!(x)){printf("Assert " __FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak();    }}
+               #else//_MSC_VER
+                       #include <assert.h>
+                       #define btAssert assert
+               #endif//_MSC_VER
+       #else
+               #define btAssert(x)
+       #endif
+               //btFullAssert is optional, slows down a lot
+               #define btFullAssert(x)
+
+               #define btLikely(_c)  _c
+               #define btUnlikely(_c) _c
+
+#else//_WIN32
+       
+       #if defined     (__CELLOS_LV2__)
+               #define SIMD_FORCE_INLINE inline __attribute__((always_inline))
+               #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+               #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+               #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+               #ifndef assert
+               #include <assert.h>
+               #endif
+               #ifdef BT_DEBUG
+                       #ifdef __SPU__
+                               #include <spu_printf.h>
+                               #define printf spu_printf
+                               #define btAssert(x) {if(!(x)){printf("Assert " __FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
+                       #else
+                               #define btAssert assert
+                       #endif
+       
+               #else//BT_DEBUG
+                               #define btAssert(x)
+               #endif//BT_DEBUG
+               //btFullAssert is optional, slows down a lot
+               #define btFullAssert(x)
+
+               #define btLikely(_c)  _c
+               #define btUnlikely(_c) _c
+
+       #else//defined  (__CELLOS_LV2__)
+
+               #ifdef USE_LIBSPE2
+
+                       #define SIMD_FORCE_INLINE __inline
+                       #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+                       #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+                       #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+                       #ifndef assert
+                       #include <assert.h>
+                       #endif
+       #ifdef BT_DEBUG
+                       #define btAssert assert
+       #else
+                       #define btAssert(x)
+       #endif
+                       //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//USE_LIBSPE2
+       //non-windows systems
+
+                       #if (defined (__APPLE__) && (!defined (BT_USE_DOUBLE_PRECISION)))
+                               #if defined (__i386__) || defined (__x86_64__)
+                                       #define BT_USE_SIMD_VECTOR3
+                                       #define BT_USE_SSE
+                                       //BT_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries
+                                       //if apps run into issues, we will disable the next line
+                                       #define BT_USE_SSE_IN_API
+                                       #ifdef BT_USE_SSE
+                                               // include appropriate SSE level
+                                               #if defined (__SSE4_1__)
+                                                       #include <smmintrin.h>
+                                               #elif defined (__SSSE3__)
+                                                       #include <tmmintrin.h>
+                                               #elif defined (__SSE3__)
+                                                       #include <pmmintrin.h>
+                                               #else
+                                                       #include <emmintrin.h>
+                                               #endif
+                                       #endif //BT_USE_SSE
+                               #elif defined( __ARM_NEON__ )
+                                       #ifdef __clang__
+                                               #define BT_USE_NEON 1
+                                               #define BT_USE_SIMD_VECTOR3
+               
+                                               #if defined BT_USE_NEON && defined (__clang__)
+                                                       #include <arm_neon.h>
+                                               #endif//BT_USE_NEON
+                                  #endif //__clang__
+                               #endif//__arm__
+
+                               #define SIMD_FORCE_INLINE inline __attribute__ ((always_inline))
+                       ///@todo: check out alignment methods for other platforms/compilers
+                               #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+                               #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+                               #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+                               #ifndef assert
+                               #include <assert.h>
+                               #endif
+
+                               #if defined(DEBUG) || defined (_DEBUG)
+                                #if defined (__i386__) || defined (__x86_64__)
+                               #include <stdio.h>
+                                #define btAssert(x)\
+                               {\
+                               if(!(x))\
+                               {\
+                                       printf("Assert %s in line %d, file %s\n",#x, __LINE__, __FILE__);\
+                                       asm volatile ("int3");\
+                               }\
+                               }
+                               #else//defined (__i386__) || defined (__x86_64__)
+                                       #define btAssert assert
+                               #endif//defined (__i386__) || defined (__x86_64__)
+                               #else//defined(DEBUG) || defined (_DEBUG)
+                                       #define btAssert(x)
+                               #endif//defined(DEBUG) || defined (_DEBUG)
+
+                               //btFullAssert is optional, slows down a lot
+                               #define btFullAssert(x)
+                               #define btLikely(_c)  _c
+                               #define btUnlikely(_c) _c
+
+                       #else//__APPLE__
+
+                               #define SIMD_FORCE_INLINE inline
+                               ///@todo: check out alignment methods for other platforms/compilers
+                               ///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+                               ///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+                               ///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+                               #define ATTRIBUTE_ALIGNED16(a) a
+                               #define ATTRIBUTE_ALIGNED64(a) a
+                               #define ATTRIBUTE_ALIGNED128(a) a
+                               #ifndef assert
+                               #include <assert.h>
+                               #endif
+
+                               #if defined(DEBUG) || defined (_DEBUG)
+                                       #define btAssert assert
+                               #else
+                                       #define btAssert(x)
+                               #endif
+
+                               //btFullAssert is optional, slows down a lot
+                               #define btFullAssert(x)
+                               #define btLikely(_c)  _c
+                               #define btUnlikely(_c) _c
+                       #endif //__APPLE__ 
+               #endif // LIBSPE2
+       #endif  //__CELLOS_LV2__
+#endif//_WIN32
+
+
+///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;
+       //this number could be bigger in double precision
+       #define BT_LARGE_FLOAT 1e30
+#else
+       typedef float btScalar;
+       //keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX
+       #define BT_LARGE_FLOAT 1e18f
+#endif
+
+#ifdef BT_USE_SSE
+       typedef __m128 btSimdFloat4;
+#endif  //BT_USE_SSE
+
+#if defined(BT_USE_SSE)
+       //#if defined BT_USE_SSE_IN_API && defined (BT_USE_SSE)
+       #ifdef _WIN32
+
+               #ifndef BT_NAN
+                       static int btNanMask = 0x7F800001;
+                       #define BT_NAN (*(float *)&btNanMask)
+               #endif
+
+               #ifndef BT_INFINITY
+                       static int btInfinityMask = 0x7F800000;
+                       #define BT_INFINITY (*(float *)&btInfinityMask)
+                       inline int btGetInfinityMask()  //suppress stupid compiler warning
+                       {
+                               return btInfinityMask;
+                       }
+               #endif
+
+
+
+       //use this, in case there are clashes (such as xnamath.h)
+       #ifndef BT_NO_SIMD_OPERATOR_OVERLOADS
+       inline __m128 operator+(const __m128 A, const __m128 B)
+       {
+               return _mm_add_ps(A, B);
+       }
+
+       inline __m128 operator-(const __m128 A, const __m128 B)
+       {
+               return _mm_sub_ps(A, B);
+       }
+
+       inline __m128 operator*(const __m128 A, const __m128 B)
+       {
+               return _mm_mul_ps(A, B);
+       }
+       #endif  //BT_NO_SIMD_OPERATOR_OVERLOADS
+
+       #define btCastfTo128i(a) (_mm_castps_si128(a))
+       #define btCastfTo128d(a) (_mm_castps_pd(a))
+       #define btCastiTo128f(a) (_mm_castsi128_ps(a))
+       #define btCastdTo128f(a) (_mm_castpd_ps(a))
+       #define btCastdTo128i(a) (_mm_castpd_si128(a))
+       #define btAssign128(r0, r1, r2, r3) _mm_setr_ps(r0, r1, r2, r3)
+
+       #else  //_WIN32
+
+               #define btCastfTo128i(a) ((__m128i)(a))
+               #define btCastfTo128d(a) ((__m128d)(a))
+               #define btCastiTo128f(a) ((__m128)(a))
+               #define btCastdTo128f(a) ((__m128)(a))
+               #define btCastdTo128i(a) ((__m128i)(a))
+               #define btAssign128(r0, r1, r2, r3) \
+                       (__m128) { r0, r1, r2, r3 }
+               #define BT_INFINITY INFINITY
+               #define BT_NAN NAN
+       #endif  //_WIN32
+#else//BT_USE_SSE
+
+       #ifdef BT_USE_NEON
+       #include <arm_neon.h>
+
+       typedef float32x4_t btSimdFloat4;
+       #define BT_INFINITY INFINITY
+       #define BT_NAN NAN
+       #define btAssign128(r0, r1, r2, r3) \
+               (float32x4_t) { r0, r1, r2, r3 }
+       #else  //BT_USE_NEON
+
+       #ifndef BT_INFINITY
+       struct btInfMaskConverter
+       {
+               union {
+                       float mask;
+                       int intmask;
+               };
+               btInfMaskConverter(int _mask = 0x7F800000)
+                       : intmask(_mask)
+               {
+               }
+       };
+       static btInfMaskConverter btInfinityMask = 0x7F800000;
+       #define BT_INFINITY (btInfinityMask.mask)
+       inline int btGetInfinityMask()  //suppress stupid compiler warning
+       {
+               return btInfinityMask.intmask;
+       }
+       #endif
+       #endif  //BT_USE_NEON
+
+#endif  //BT_USE_SSE
+
+#ifdef BT_USE_NEON
+       #include <arm_neon.h>
+
+       typedef float32x4_t btSimdFloat4;
+       #define BT_INFINITY INFINITY
+       #define BT_NAN NAN
+       #define btAssign128(r0, r1, r2, r3) \
+               (float32x4_t) { r0, r1, r2, r3 }
+#endif//BT_USE_NEON
+
+#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 *) {}                                              \
+       SIMD_FORCE_INLINE void *operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
+       SIMD_FORCE_INLINE void operator delete[](void *ptr) { btAlignedFree(ptr); }                            \
+       SIMD_FORCE_INLINE void *operator new[](size_t, void *ptr) { return ptr; }                              \
+       SIMD_FORCE_INLINE void operator delete[](void *, void *) {}
+
+#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
+
+       SIMD_FORCE_INLINE btScalar btSqrt(btScalar x)
+       {
+               return sqrt(x);
+       }
+       SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
+       SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
+       SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
+       SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
+       SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
+       {
+               if (x < btScalar(-1)) x = btScalar(-1);
+               if (x > btScalar(1)) x = btScalar(1);
+               return acos(x);
+       }
+       SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
+       {
+               if (x < btScalar(-1)) x = btScalar(-1);
+               if (x > btScalar(1)) x = btScalar(1);
+               return asin(x);
+       }
+       SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
+       SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
+       SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
+       SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
+       SIMD_FORCE_INLINE btScalar btPow(btScalar x, btScalar y) { return pow(x, y); }
+       SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmod(x, y); }
+
+#else//BT_USE_DOUBLE_PRECISION
+
+       SIMD_FORCE_INLINE btScalar btSqrt(btScalar y)
+       {
+       #ifdef USE_APPROXIMATION
+       #ifdef __LP64__
+               float xhalf = 0.5f * y;
+               int i = *(int *)&y;
+               i = 0x5f375a86 - (i >> 1);
+               y = *(float *)&i;
+               y = y * (1.5f - xhalf * y * y);
+               y = y * (1.5f - xhalf * y * y);
+               y = y * (1.5f - xhalf * y * y);
+               y = 1 / y;
+               return y;
+       #else
+               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);
+               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;
+       #endif
+       #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)
+       {
+               if (x < btScalar(-1))
+                       x = btScalar(-1);
+               if (x > btScalar(1))
+                       x = btScalar(1);
+               return acosf(x);
+       }
+       SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
+       {
+               if (x < btScalar(-1))
+                       x = btScalar(-1);
+               if (x > btScalar(1))
+                       x = btScalar(1);
+               return asinf(x);
+       }
+       SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); }
+       SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); }
+       SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); }
+       SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); }
+       SIMD_FORCE_INLINE btScalar btPow(btScalar x, btScalar y) { return powf(x, y); }
+       SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmodf(x, y); }
+
+#endif//BT_USE_DOUBLE_PRECISION
+
+#define SIMD_PI btScalar(3.1415926535897932384626433832795029)
+#define SIMD_2_PI (btScalar(2.0) * SIMD_PI)
+#define SIMD_HALF_PI (SIMD_PI * btScalar(0.5))
+#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
+#define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI)
+#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490)
+#define btRecipSqrt(x) ((btScalar)(btScalar(1.0) / btSqrt(btScalar(x)))) /* reciprocal square root */
+#define btRecip(x) (btScalar(1.0) / btScalar(x))
+
+#ifdef BT_USE_DOUBLE_PRECISION
+       #define SIMD_EPSILON DBL_EPSILON
+       #define SIMD_INFINITY DBL_MAX
+       #define BT_ONE 1.0
+       #define BT_ZERO 0.0
+       #define BT_TWO 2.0
+       #define BT_HALF 0.5
+#else
+       #define SIMD_EPSILON FLT_EPSILON
+       #define SIMD_INFINITY FLT_MAX
+       #define BT_ONE 1.0f
+       #define BT_ZERO 0.0f
+       #define BT_TWO 2.0f
+       #define BT_HALF 0.5f
+#endif
+
+// clang-format on
+
+SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x)
+{
+       btScalar coeff_1 = SIMD_PI / 4.0f;
+       btScalar coeff_2 = 3.0f * coeff_1;
+       btScalar abs_y = btFabs(y);
+       btScalar angle;
+       if (x >= 0.0f)
+       {
+               btScalar r = (x - abs_y) / (x + abs_y);
+               angle = coeff_1 - coeff_1 * r;
+       }
+       else
+       {
+               btScalar r = (x + abs_y) / (abs_y - x);
+               angle = coeff_2 - coeff_1 * r;
+       }
+       return (y < 0.0f) ? -angle : angle;
+}
+
+SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; }
+
+SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps)
+{
+       return (((a) <= eps) && !((a) < -eps));
+}
+SIMD_FORCE_INLINE bool btGreaterEqual(btScalar a, btScalar eps)
+{
+       return (!((a) <= eps));
+}
+
+SIMD_FORCE_INLINE int btIsNegative(btScalar x)
+{
+       return x < btScalar(0.0) ? 1 : 0;
+}
+
+SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; }
+SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; }
+
+#define BT_DECLARE_HANDLE(name) \
+       typedef struct name##__     \
+       {                           \
+               int unused;             \
+       } * name
+
+#ifndef btFsel
+SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c)
+{
+       return a >= 0 ? b : c;
+}
+#endif
+#define btFsels(a, b, c) (btScalar) btFsel(a, b, c)
+
+SIMD_FORCE_INLINE bool btMachineIsLittleEndian()
+{
+       long int i = 1;
+       const char *p = (const char *)&i;
+       if (p[0] == 1)  // Lowest address contains the least significant byte
+               return true;
+       else
+               return false;
+}
+
+///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
+///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
+SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
+{
+       // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
+       // Rely on positive value or'ed with its negative having sign bit on
+       // and zero value or'ed with its negative (which is still zero) having sign bit off
+       // Use arithmetic shift right, shifting the sign bit through all 32 bits
+       unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+       unsigned testEqz = ~testNz;
+       return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+}
+SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
+{
+       unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+       unsigned testEqz = ~testNz;
+       return 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;
+}
+
+template <typename T>
+SIMD_FORCE_INLINE void btSetZero(T *a, int n)
+{
+       T *acurr = a;
+       size_t ncurr = n;
+       while (ncurr > 0)
+       {
+               *(acurr++) = 0;
+               --ncurr;
+       }
+}
+
+SIMD_FORCE_INLINE btScalar btLargeDot(const btScalar *a, const btScalar *b, int n)
+{
+       btScalar p0, q0, m0, p1, q1, m1, sum;
+       sum = 0;
+       n -= 2;
+       while (n >= 0)
+       {
+               p0 = a[0];
+               q0 = b[0];
+               m0 = p0 * q0;
+               p1 = a[1];
+               q1 = b[1];
+               m1 = p1 * q1;
+               sum += m0;
+               sum += m1;
+               a += 2;
+               b += 2;
+               n -= 2;
+       }
+       n += 2;
+       while (n > 0)
+       {
+               sum += (*a) * (*b);
+               a++;
+               b++;
+               n--;
+       }
+       return sum;
+}
+
+// returns normalized value in range [-SIMD_PI, SIMD_PI]
+SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians)
+{
+       angleInRadians = btFmod(angleInRadians, SIMD_2_PI);
+       if (angleInRadians < -SIMD_PI)
+       {
+               return angleInRadians + SIMD_2_PI;
+       }
+       else if (angleInRadians > SIMD_PI)
+       {
+               return angleInRadians - SIMD_2_PI;
+       }
+       else
+       {
+               return angleInRadians;
+       }
+}
+
+///rudimentary class to provide type info
+struct btTypedObject
+{
+       btTypedObject(int objectType)
+               : m_objectType(objectType)
+       {
+       }
+       int m_objectType;
+       inline int getObjectType() const
+       {
+               return m_objectType;
+       }
+};
+
+///align a pointer to the provided alignment, upwards
+template <typename T>
+T *btAlignPointer(T *unalignedPtr, size_t alignment)
+{
+       struct btConvertPointerSizeT
+       {
+               union {
+                       T *ptr;
+                       size_t integer;
+               };
+       };
+       btConvertPointerSizeT converter;
+
+       const size_t bit_mask = ~(alignment - 1);
+       converter.ptr = unalignedPtr;
+       converter.integer += alignment - 1;
+       converter.integer &= bit_mask;
+       return converter.ptr;
+}
+
+#endif  //BT_SCALAR_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btSerializer.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btSerializer.cpp
new file mode 100644 (file)
index 0000000..068836f
--- /dev/null
@@ -0,0 +1,692 @@
+char sBulletDNAstr[]= {
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-74),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
+char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
+char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
+char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
+char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
+char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
+char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
+char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
+char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
+char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
+char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
+char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
+char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
+char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
+char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
+char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
+char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
+char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
+char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
+char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
+char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
+char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
+char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
+char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
+char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
+char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
+char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(112),char(97),
+char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
+char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
+char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
+char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),char(115),
+char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
+char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
+char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),
+char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
+char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
+char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
+char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
+char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
+char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
+char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
+char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
+char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
+char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
+char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
+char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),
+char(101),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
+char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
+char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),
+char(77),char(97),char(112),char(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
+char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(116),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
+char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
+char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
+char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
+char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(117),char(112),char(73),char(110),char(100),
+char(101),char(120),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),
+char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),
+char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),
+char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),
+char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),
+char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),
+char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),
+char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),
+char(116),char(101),char(120),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(68),
+char(105),char(115),char(116),char(97),char(110),char(99),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(122),
+char(101),char(114),char(111),char(65),char(114),char(101),char(97),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),
+char(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),
+char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(75),char(101),char(121),char(115),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(111),
+char(99),char(97),char(108),char(80),char(111),char(105),char(110),char(116),char(65),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(76),char(111),char(99),char(97),char(108),char(80),char(111),char(105),char(110),char(116),char(66),char(91),char(52),char(93),char(0),
+char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),
+char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(65),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(66),
+char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(78),char(111),char(114),char(109),
+char(97),char(108),char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(66),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),
+char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
+char(110),char(68),char(105),char(114),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
+char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(68),char(105),char(114),char(50),
+char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(68),char(105),char(115),char(116),
+char(97),char(110),char(99),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
+char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(91),char(52),char(93),char(0),char(109),char(95),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(114),char(101),char(118),char(82),char(72),char(83),char(91),char(52),char(93),
+char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),
+char(100),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),
+char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
+char(97),char(114),char(116),char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(80),char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
+char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),
+char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),
+char(116),char(70),char(108),char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),
+char(114),char(97),char(108),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
+char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),
+char(108),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
+char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),
+char(110),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),
+char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),
+char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),
+char(101),char(84),char(105),char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),
+char(80),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),
+char(65),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),
+char(110),char(100),char(101),char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),
+char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),
+char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),
+char(111),char(100),char(121),char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),
+char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),
+char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),
+char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),
+char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),
+char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),
+char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),
+char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),
+char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),
+char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),
+char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),
+char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
+char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),
+char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
+char(99),char(116),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),
+char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),
+char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),
+char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),
+char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),
+char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),
+char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),
+char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),
+char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
+char(116),char(101),char(114),char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(105),char(108),char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),
+char(100),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),
+char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),
+char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),
+char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),
+char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),
+char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),
+char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(114),char(116),char(105),char(99),char(117),char(108),
+char(97),char(116),char(101),char(100),char(87),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),
+char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),
+char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
+char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),
+char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),
+char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),
+char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),
+char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
+char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),
+char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),
+char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),
+char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),
+char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),
+char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
+char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),
+char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),
+char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),
+char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),
+char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),
+char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),
+char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
+char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),
+char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),
+char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),
+char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),
+char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),
+char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),
+char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),
+char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
+char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),
+char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),
+char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),
+char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),
+char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),
+char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),
+char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),
+char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),
+char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),
+char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),
+char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),
+char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),
+char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),
+char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),
+char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),
+char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),
+char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
+char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),
+char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),
+char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),
+char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),
+char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),
+char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(97),char(120),char(77),
+char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
+char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),
+char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
+char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
+char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
+char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),
+char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),
+char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),
+char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),
+char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),
+char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),char(114),
+char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),char(101),char(114),char(0),char(109),char(95),
+char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(66),char(0),char(109),char(95),
+char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),
+char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),
+char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),
+char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),
+char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),
+char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),
+char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),
+char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),
+char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),
+char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),
+char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),
+char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),
+char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),
+char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),
+char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),
+char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),
+char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),
+char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
+char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),
+char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),
+char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
+char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),
+char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),
+char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
+char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),
+char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),
+char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),
+char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),
+char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),
+char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),
+char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),
+char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),
+char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),
+char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),
+char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),
+char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),
+char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),
+char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),
+char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
+char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),
+char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),
+char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),
+char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
+char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),
+char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),
+char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
+char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),
+char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),
+char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),
+char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),
+char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),
+char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),
+char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),
+char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),
+char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),
+char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),
+char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
+char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),
+char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(109),
+char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),char(111),char(84),char(104),char(105),char(115),
+char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),char(104),char(105),char(115),char(80),char(105),
+char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),char(115),char(80),char(105),char(118),char(111),
+char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(106),
+char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),
+char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),
+char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),
+char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),
+char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),
+char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
+char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110),char(100),char(101),char(120),
+char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115),char(86),char(97),char(114),
+char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91),char(55),char(93),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
+char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),
+char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),char(109),char(101),char(0),char(42),char(109),
+char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),char(109),char(95),char(112),char(97),char(100),
+char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(80),
+char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(79),
+char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(76),char(105),char(110),
+char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),
+char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(42),
+char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(67),char(111),
+char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),char(68),char(97),char(116),char(97),char(0),
+char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(0),
+char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),
+char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),
+char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),
+char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),
+char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),
+char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
+char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),
+char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),
+char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),
+char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),
+char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),
+char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),
+char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
+char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),
+char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
+char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),
+char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),
+char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),
+char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),
+char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),
+char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),
+char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),
+char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),
+char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),
+char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),
+char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),
+char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
+char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
+char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
+char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),
+char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
+char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),
+char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
+char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),
+char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),
+char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),
+char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),
+char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),
+char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),
+char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),
+char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),
+char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),
+char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),
+char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),
+char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
+char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
+char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),
+char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
+char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),
+char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),
+char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),
+char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
+char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0),char(-124),char(0),char(12),char(0),char(52),char(0),char(52),char(0),
+char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(32),char(0),char(28),char(0),char(60),char(0),char(56),char(0),
+char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(60),char(0),char(16),char(0),char(16),char(6),char(-24),char(1),char(72),char(3),
+char(16),char(1),char(64),char(0),char(68),char(0),char(-96),char(0),char(88),char(0),char(-64),char(0),char(104),char(0),char(-8),char(1),char(-72),char(3),char(8),char(0),
+char(52),char(0),char(52),char(0),char(0),char(0),char(68),char(0),char(84),char(0),char(-124),char(0),char(116),char(0),char(92),char(1),char(-36),char(0),char(-116),char(1),
+char(124),char(1),char(-44),char(0),char(-4),char(0),char(-52),char(1),char(92),char(1),char(116),char(2),char(-124),char(2),char(-76),char(4),char(-52),char(0),char(108),char(1),
+char(92),char(0),char(-116),char(0),char(16),char(0),char(100),char(0),char(20),char(0),char(36),char(0),char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0),
+char(92),char(1),char(104),char(0),char(-68),char(1),char(112),char(3),char(-56),char(1),char(-68),char(0),char(100),char(0),char(28),char(1),char(-12),char(1),char(0),char(0),
+char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),
+char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),
+char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),
+char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),
+char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
+char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),
+char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
+char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
+char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
+char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
+char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),
+char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
+char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),
+char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
+char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
+char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),
+char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),
+char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
+char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
+char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),
+char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),
+char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),
+char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
+char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),
+char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),
+char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),
+char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),
+char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
+char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
+char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
+char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),
+char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),
+char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),
+char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),
+char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),
+char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),
+char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(39),char(0),char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),
+char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),
+char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),
+char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),
+char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),
+char(8),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(48),char(0),char(-124),char(0),char(48),char(0),char(-123),char(0),char(49),char(0),char(39),char(0),char(13),char(0),char(96),char(0),char(13),char(0),char(97),char(0),
+char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),char(13),char(0),char(102),char(0),
+char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),char(7),char(0),char(107),char(0),
+char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),char(7),char(0),char(117),char(0),
+char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),char(7),char(0),char(122),char(0),
+char(7),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(7),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(50),char(0),char(-124),char(0),char(50),char(0),char(-123),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
+char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-122),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
+char(13),char(0),char(-121),char(0),char(14),char(0),char(-120),char(0),char(4),char(0),char(-119),char(0),char(0),char(0),char(-118),char(0),char(48),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-114),char(0),
+char(20),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),char(8),char(0),char(-125),char(0),
+char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),char(8),char(0),char(-105),char(0),
+char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(50),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-114),char(0),
+char(19),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(13),char(0),char(-110),char(0),char(7),char(0),char(-125),char(0),
+char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),char(7),char(0),char(-105),char(0),
+char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(53),char(0),char(23),char(0),
+char(8),char(0),char(-90),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-88),char(0),char(8),char(0),char(-104),char(0),
+char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),
+char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),
+char(8),char(0),char(-77),char(0),char(8),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),
+char(4),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-90),char(0),
+char(7),char(0),char(-89),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-87),char(0),
+char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0),
+char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
+char(7),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(4),char(0),char(-72),char(0),
+char(4),char(0),char(-71),char(0),char(55),char(0),char(2),char(0),char(53),char(0),char(-70),char(0),char(14),char(0),char(-69),char(0),char(56),char(0),char(2),char(0),
+char(54),char(0),char(-70),char(0),char(13),char(0),char(-69),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-68),char(0),char(17),char(0),char(-67),char(0),
+char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0),char(13),char(0),char(-69),char(0),
+char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(13),char(0),char(-60),char(0),char(13),char(0),char(-59),char(0),char(7),char(0),char(-58),char(0),
+char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),
+char(7),char(0),char(-52),char(0),char(7),char(0),char(-51),char(0),char(7),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(58),char(0),char(22),char(0),
+char(48),char(0),char(-68),char(0),char(18),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),char(14),char(0),char(-64),char(0),
+char(14),char(0),char(-63),char(0),char(14),char(0),char(-69),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),char(14),char(0),char(-60),char(0),
+char(14),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-55),char(0),
+char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(8),char(0),char(-51),char(0),char(8),char(0),char(-50),char(0),
+char(4),char(0),char(-49),char(0),char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-48),char(0),char(4),char(0),char(-47),char(0),
+char(60),char(0),char(13),char(0),char(57),char(0),char(-46),char(0),char(57),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),
+char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),
+char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(61),char(0),char(13),char(0),
+char(62),char(0),char(-46),char(0),char(62),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),
+char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
+char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-46),char(0),
+char(58),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),
+char(4),char(0),char(-42),char(0),char(8),char(0),char(-41),char(0),char(8),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),
+char(8),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),
+char(13),char(0),char(-33),char(0),char(13),char(0),char(-32),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),
+char(14),char(0),char(-32),char(0),char(66),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),char(14),char(0),char(-32),char(0),
+char(67),char(0),char(13),char(0),char(61),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
+char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
+char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(68),char(0),char(13),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),
+char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),
+char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),
+char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),
+char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(0),char(0),char(-19),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),
+char(8),char(0),char(-22),char(0),char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-89),char(0),char(71),char(0),char(11),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(7),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0),
+char(7),char(0),char(-16),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-89),char(0),
+char(0),char(0),char(21),char(0),char(72),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),
+char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(73),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),
+char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(74),char(0),char(5),char(0),char(72),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),
+char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),
+char(8),char(0),char(-7),char(0),char(8),char(0),char(-6),char(0),char(8),char(0),char(-5),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-34),char(0),
+char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-4),char(0),
+char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),char(13),char(0),char(1),char(1),
+char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(13),char(0),char(5),char(1),char(13),char(0),char(6),char(1),
+char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),
+char(0),char(0),char(-19),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(13),char(0),char(12),char(1),char(13),char(0),char(13),char(1),
+char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),char(13),char(0),char(18),char(1),
+char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(13),char(0),char(21),char(1),char(13),char(0),char(22),char(1),char(0),char(0),char(23),char(1),
+char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),
+char(77),char(0),char(41),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(14),char(0),char(-15),char(0),
+char(14),char(0),char(-14),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),char(14),char(0),char(-1),char(0),
+char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),char(14),char(0),char(4),char(1),
+char(14),char(0),char(5),char(1),char(14),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),
+char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),char(0),char(0),char(-19),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),
+char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),char(14),char(0),char(16),char(1),
+char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),char(14),char(0),char(21),char(1),
+char(14),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),
+char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),
+char(19),char(0),char(-30),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),char(7),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),
+char(20),char(0),char(-30),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(8),char(0),char(-13),char(0),char(8),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-34),char(0),char(13),char(0),char(29),char(1),
+char(13),char(0),char(30),char(1),char(7),char(0),char(31),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-34),char(0),
+char(14),char(0),char(29),char(1),char(14),char(0),char(30),char(1),char(8),char(0),char(31),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(32),char(1),
+char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(35),char(1),
+char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(13),char(0),char(39),char(1),char(13),char(0),char(40),char(1),
+char(7),char(0),char(-58),char(0),char(7),char(0),char(41),char(1),char(4),char(0),char(42),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),
+char(82),char(0),char(35),char(1),char(4),char(0),char(43),char(1),char(7),char(0),char(44),char(1),char(4),char(0),char(45),char(1),char(85),char(0),char(4),char(0),
+char(13),char(0),char(40),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(46),char(1),char(7),char(0),char(47),char(1),char(86),char(0),char(7),char(0),
+char(13),char(0),char(48),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(49),char(1),char(7),char(0),char(50),char(1),char(7),char(0),char(51),char(1),
+char(7),char(0),char(52),char(1),char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(53),char(1),char(13),char(0),char(51),char(1),
+char(13),char(0),char(54),char(1),char(62),char(0),char(55),char(1),char(4),char(0),char(56),char(1),char(7),char(0),char(52),char(1),char(88),char(0),char(26),char(0),
+char(4),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(-89),char(0),char(7),char(0),char(59),char(1),char(7),char(0),char(60),char(1),
+char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1),
+char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1),
+char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),char(7),char(0),char(75),char(1),
+char(7),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(79),char(1),char(4),char(0),char(80),char(1),
+char(4),char(0),char(-99),char(0),char(89),char(0),char(12),char(0),char(17),char(0),char(81),char(1),char(17),char(0),char(82),char(1),char(17),char(0),char(83),char(1),
+char(13),char(0),char(84),char(1),char(13),char(0),char(85),char(1),char(7),char(0),char(86),char(1),char(4),char(0),char(87),char(1),char(4),char(0),char(88),char(1),
+char(4),char(0),char(89),char(1),char(4),char(0),char(90),char(1),char(7),char(0),char(50),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),
+char(19),char(0),char(91),char(1),char(17),char(0),char(92),char(1),char(17),char(0),char(93),char(1),char(13),char(0),char(84),char(1),char(13),char(0),char(94),char(1),
+char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(13),char(0),char(97),char(1),char(13),char(0),char(98),char(1),char(4),char(0),char(99),char(1),
+char(7),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(103),char(1),char(7),char(0),char(104),char(1),
+char(7),char(0),char(105),char(1),char(4),char(0),char(106),char(1),char(4),char(0),char(107),char(1),char(7),char(0),char(108),char(1),char(7),char(0),char(109),char(1),
+char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(7),char(0),char(112),char(1),char(7),char(0),char(113),char(1),char(4),char(0),char(114),char(1),
+char(4),char(0),char(115),char(1),char(4),char(0),char(116),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(117),char(1),char(9),char(0),char(118),char(1),
+char(13),char(0),char(119),char(1),char(7),char(0),char(120),char(1),char(7),char(0),char(-85),char(0),char(7),char(0),char(121),char(1),char(4),char(0),char(122),char(1),
+char(13),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(125),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(53),char(0),
+char(92),char(0),char(19),char(0),char(50),char(0),char(-68),char(0),char(89),char(0),char(127),char(1),char(82),char(0),char(-128),char(1),char(83),char(0),char(-127),char(1),
+char(84),char(0),char(-126),char(1),char(85),char(0),char(-125),char(1),char(86),char(0),char(-124),char(1),char(87),char(0),char(-123),char(1),char(90),char(0),char(-122),char(1),
+char(91),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(-119),char(1),char(4),char(0),char(-118),char(1),
+char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(4),char(0),char(-115),char(1),char(4),char(0),char(-114),char(1),char(88),char(0),char(-113),char(1),
+char(93),char(0),char(28),char(0),char(16),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),char(14),char(0),char(-109),char(1),
+char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),char(14),char(0),char(-104),char(1),
+char(14),char(0),char(-103),char(1),char(8),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(-100),char(1),
+char(4),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),char(8),char(0),char(-95),char(1),
+char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(8),char(0),char(-91),char(1),char(8),char(0),char(-90),char(1),
+char(0),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(48),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(94),char(0),char(28),char(0),
+char(15),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),char(13),char(0),char(-108),char(1),
+char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(13),char(0),char(-104),char(1),char(13),char(0),char(-103),char(1),
+char(4),char(0),char(-100),char(1),char(7),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(7),char(0),char(-98),char(1),
+char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(4),char(0),char(-99),char(1),char(7),char(0),char(-95),char(1),char(7),char(0),char(-94),char(1),
+char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(7),char(0),char(-91),char(1),char(7),char(0),char(-90),char(1),char(0),char(0),char(-89),char(1),
+char(0),char(0),char(-88),char(1),char(50),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-85),char(1),
+char(16),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(14),char(0),char(-82),char(1),char(14),char(0),char(-81),char(1),char(8),char(0),char(-80),char(1),
+char(4),char(0),char(-119),char(1),char(0),char(0),char(37),char(0),char(0),char(0),char(-79),char(1),char(93),char(0),char(-126),char(1),char(48),char(0),char(-78),char(1),
+char(96),char(0),char(10),char(0),char(13),char(0),char(-85),char(1),char(15),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),char(13),char(0),char(-82),char(1),
+char(13),char(0),char(-81),char(1),char(7),char(0),char(-80),char(1),char(4),char(0),char(-119),char(1),char(0),char(0),char(-79),char(1),char(94),char(0),char(-126),char(1),
+char(50),char(0),char(-78),char(1),char(97),char(0),char(4),char(0),char(50),char(0),char(-77),char(1),char(96),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),char(98),char(0),char(4),char(0),char(48),char(0),char(-77),char(1),char(95),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),};
+int sBulletDNAlen= sizeof(sBulletDNAstr);
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btSerializer.h b/dali-physics/third-party/bullet3/src/LinearMath/btSerializer.h
new file mode 100644 (file)
index 0000000..8670956
--- /dev/null
@@ -0,0 +1,866 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_SERIALIZER_H
+#define BT_SERIALIZER_H
+
+#include "btScalar.h"  // has definitions like SIMD_FORCE_INLINE
+#include "btHashMap.h"
+
+#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+extern char sBulletDNAstr[];
+extern int sBulletDNAlen;
+extern char sBulletDNAstr64[];
+extern int sBulletDNAlen64;
+
+SIMD_FORCE_INLINE int btStrLen(const char* str)
+{
+       if (!str)
+               return (0);
+       int len = 0;
+
+       while (*str != 0)
+       {
+               str++;
+               len++;
+       }
+
+       return len;
+}
+
+class btChunk
+{
+public:
+       int m_chunkCode;
+       int m_length;
+       void* m_oldPtr;
+       int m_dna_nr;
+       int m_number;
+};
+
+enum btSerializationFlags
+{
+       BT_SERIALIZE_NO_BVH = 1,
+       BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
+       BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4,
+       BT_SERIALIZE_CONTACT_MANIFOLDS = 8,
+};
+
+class btSerializer
+{
+public:
+       virtual ~btSerializer() {}
+
+       virtual const unsigned char* getBufferPointer() const = 0;
+
+       virtual int getCurrentBufferSize() const = 0;
+
+       virtual btChunk* allocate(size_t size, int numElements) = 0;
+
+       virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr) = 0;
+
+       virtual void* findPointer(void* oldPtr) = 0;
+
+       virtual void* getUniquePointer(void* oldPtr) = 0;
+
+       virtual void startSerialization() = 0;
+
+       virtual void finishSerialization() = 0;
+
+       virtual const char* findNameForPointer(const void* ptr) const = 0;
+
+       virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
+
+       virtual void serializeName(const char* ptr) = 0;
+
+       virtual int getSerializationFlags() const = 0;
+
+       virtual void setSerializationFlags(int flags) = 0;
+
+       virtual int getNumChunks() const = 0;
+
+       virtual const btChunk* getChunk(int chunkIndex) const = 0;
+};
+
+#define BT_HEADER_LENGTH 12
+#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
+#define BT_MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
+#else
+#define BT_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
+#endif
+
+#define BT_MULTIBODY_CODE BT_MAKE_ID('M', 'B', 'D', 'Y')
+#define BT_MB_LINKCOLLIDER_CODE BT_MAKE_ID('M', 'B', 'L', 'C')
+#define BT_SOFTBODY_CODE BT_MAKE_ID('S', 'B', 'D', 'Y')
+#define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C', 'O', 'B', 'J')
+#define BT_RIGIDBODY_CODE BT_MAKE_ID('R', 'B', 'D', 'Y')
+#define BT_CONSTRAINT_CODE BT_MAKE_ID('C', 'O', 'N', 'S')
+#define BT_BOXSHAPE_CODE BT_MAKE_ID('B', 'O', 'X', 'S')
+#define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q', 'B', 'V', 'H')
+#define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T', 'M', 'A', 'P')
+#define BT_SHAPE_CODE BT_MAKE_ID('S', 'H', 'A', 'P')
+#define BT_ARRAY_CODE BT_MAKE_ID('A', 'R', 'A', 'Y')
+#define BT_SBMATERIAL_CODE BT_MAKE_ID('S', 'B', 'M', 'T')
+#define BT_SBNODE_CODE BT_MAKE_ID('S', 'B', 'N', 'D')
+#define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D', 'W', 'L', 'D')
+#define BT_CONTACTMANIFOLD_CODE BT_MAKE_ID('C', 'O', 'N', 'T')
+#define BT_DNA_CODE BT_MAKE_ID('D', 'N', 'A', '1')
+
+struct btPointerUid
+{
+       union {
+               void* m_ptr;
+               int m_uniqueIds[2];
+       };
+};
+
+struct btBulletSerializedArrays
+{
+       btBulletSerializedArrays()
+       {
+       }
+       btAlignedObjectArray<struct btQuantizedBvhDoubleData*> m_bvhsDouble;
+       btAlignedObjectArray<struct btQuantizedBvhFloatData*> m_bvhsFloat;
+       btAlignedObjectArray<struct btCollisionShapeData*> m_colShapeData;
+       btAlignedObjectArray<struct btDynamicsWorldDoubleData*> m_dynamicWorldInfoDataDouble;
+       btAlignedObjectArray<struct btDynamicsWorldFloatData*> m_dynamicWorldInfoDataFloat;
+       btAlignedObjectArray<struct btRigidBodyDoubleData*> m_rigidBodyDataDouble;
+       btAlignedObjectArray<struct btRigidBodyFloatData*> m_rigidBodyDataFloat;
+       btAlignedObjectArray<struct btCollisionObjectDoubleData*> m_collisionObjectDataDouble;
+       btAlignedObjectArray<struct btCollisionObjectFloatData*> m_collisionObjectDataFloat;
+       btAlignedObjectArray<struct btTypedConstraintFloatData*> m_constraintDataFloat;
+       btAlignedObjectArray<struct btTypedConstraintDoubleData*> m_constraintDataDouble;
+       btAlignedObjectArray<struct btTypedConstraintData*> m_constraintData;  //for backwards compatibility
+       btAlignedObjectArray<struct btSoftBodyFloatData*> m_softBodyFloatData;
+       btAlignedObjectArray<struct btSoftBodyDoubleData*> m_softBodyDoubleData;
+};
+
+///The btDefaultSerializer is the main Bullet serialization class.
+///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
+class btDefaultSerializer : public btSerializer
+{
+protected:
+       btAlignedObjectArray<char*> mTypes;
+       btAlignedObjectArray<short*> mStructs;
+       btAlignedObjectArray<short> mTlens;
+       btHashMap<btHashInt, int> mStructReverse;
+       btHashMap<btHashString, int> mTypeLookup;
+
+       btHashMap<btHashPtr, void*> m_chunkP;
+
+       btHashMap<btHashPtr, const char*> m_nameMap;
+
+       btHashMap<btHashPtr, btPointerUid> m_uniquePointers;
+       int m_uniqueIdGenerator;
+
+       int m_totalSize;
+       unsigned char* m_buffer;
+       bool m_ownsBuffer;
+       int m_currentSize;
+       void* m_dna;
+       int m_dnaLength;
+
+       int m_serializationFlags;
+
+       btAlignedObjectArray<btChunk*> m_chunkPtrs;
+
+protected:
+       virtual void* findPointer(void* oldPtr)
+       {
+               void** ptr = m_chunkP.find(oldPtr);
+               if (ptr && *ptr)
+                       return *ptr;
+               return 0;
+       }
+
+       virtual void writeDNA()
+       {
+               btChunk* dnaChunk = allocate(m_dnaLength, 1);
+               memcpy(dnaChunk->m_oldPtr, m_dna, m_dnaLength);
+               finalizeChunk(dnaChunk, "DNA1", BT_DNA_CODE, m_dna);
+       }
+
+       int getReverseType(const char* type) const
+       {
+               btHashString key(type);
+               const int* valuePtr = mTypeLookup.find(key);
+               if (valuePtr)
+                       return *valuePtr;
+
+               return -1;
+       }
+
+       void initDNA(const char* bdnaOrg, int dnalen)
+       {
+               ///was already initialized
+               if (m_dna)
+                       return;
+
+               int littleEndian = 1;
+               littleEndian = ((char*)&littleEndian)[0];
+
+               m_dna = btAlignedAlloc(dnalen, 16);
+               memcpy(m_dna, bdnaOrg, dnalen);
+               m_dnaLength = dnalen;
+
+               int* intPtr = 0;
+               short* shtPtr = 0;
+               char* cp = 0;
+               int dataLen = 0;
+               intPtr = (int*)m_dna;
+
+               /*
+                               SDNA (4 bytes) (magic number)
+                               NAME (4 bytes)
+                               <nr> (4 bytes) amount of names (int)
+                               <string>
+                               <string>
+                       */
+
+               if (strncmp((const char*)m_dna, "SDNA", 4) == 0)
+               {
+                       // skip ++ NAME
+                       intPtr++;
+                       intPtr++;
+               }
+
+               // Parse names
+               if (!littleEndian)
+                       *intPtr = btSwapEndian(*intPtr);
+
+               dataLen = *intPtr;
+
+               intPtr++;
+
+               cp = (char*)intPtr;
+               int i;
+               for (i = 0; i < dataLen; i++)
+               {
+                       while (*cp) cp++;
+                       cp++;
+               }
+               cp = btAlignPointer(cp, 4);
+
+               /*
+                               TYPE (4 bytes)
+                               <nr> amount of types (int)
+                               <string>
+                               <string>
+                       */
+
+               intPtr = (int*)cp;
+               btAssert(strncmp(cp, "TYPE", 4) == 0);
+               intPtr++;
+
+               if (!littleEndian)
+                       *intPtr = btSwapEndian(*intPtr);
+
+               dataLen = *intPtr;
+               intPtr++;
+
+               cp = (char*)intPtr;
+               for (i = 0; i < dataLen; i++)
+               {
+                       mTypes.push_back(cp);
+                       while (*cp) cp++;
+                       cp++;
+               }
+
+               cp = btAlignPointer(cp, 4);
+
+               /*
+                               TLEN (4 bytes)
+                               <len> (short) the lengths of types
+                               <len>
+                       */
+
+               // Parse type lens
+               intPtr = (int*)cp;
+               btAssert(strncmp(cp, "TLEN", 4) == 0);
+               intPtr++;
+
+               dataLen = (int)mTypes.size();
+
+               shtPtr = (short*)intPtr;
+               for (i = 0; i < dataLen; i++, shtPtr++)
+               {
+                       if (!littleEndian)
+                               shtPtr[0] = btSwapEndian(shtPtr[0]);
+                       mTlens.push_back(shtPtr[0]);
+               }
+
+               if (dataLen & 1) shtPtr++;
+
+               /*
+                               STRC (4 bytes)
+                               <nr> amount of structs (int)
+                               <typenr>
+                               <nr_of_elems>
+                               <typenr>
+                               <namenr>
+                               <typenr>
+                               <namenr>
+                       */
+
+               intPtr = (int*)shtPtr;
+               cp = (char*)intPtr;
+               btAssert(strncmp(cp, "STRC", 4) == 0);
+               intPtr++;
+
+               if (!littleEndian)
+                       *intPtr = btSwapEndian(*intPtr);
+               dataLen = *intPtr;
+               intPtr++;
+
+               shtPtr = (short*)intPtr;
+               for (i = 0; i < dataLen; i++)
+               {
+                       mStructs.push_back(shtPtr);
+
+                       if (!littleEndian)
+                       {
+                               shtPtr[0] = btSwapEndian(shtPtr[0]);
+                               shtPtr[1] = btSwapEndian(shtPtr[1]);
+
+                               int len = shtPtr[1];
+                               shtPtr += 2;
+
+                               for (int a = 0; a < len; a++, shtPtr += 2)
+                               {
+                                       shtPtr[0] = btSwapEndian(shtPtr[0]);
+                                       shtPtr[1] = btSwapEndian(shtPtr[1]);
+                               }
+                       }
+                       else
+                       {
+                               shtPtr += (2 * shtPtr[1]) + 2;
+                       }
+               }
+
+               // build reverse lookups
+               for (i = 0; i < (int)mStructs.size(); i++)
+               {
+                       short* strc = mStructs.at(i);
+                       mStructReverse.insert(strc[0], i);
+                       mTypeLookup.insert(btHashString(mTypes[strc[0]]), i);
+               }
+       }
+
+public:
+       btHashMap<btHashPtr, void*> m_skipPointers;
+
+       btDefaultSerializer(int totalSize = 0, unsigned char* buffer = 0)
+               : m_uniqueIdGenerator(0),
+                 m_totalSize(totalSize),
+                 m_currentSize(0),
+                 m_dna(0),
+                 m_dnaLength(0),
+                 m_serializationFlags(0)
+       {
+               if (buffer == 0)
+               {
+                       m_buffer = m_totalSize ? (unsigned char*)btAlignedAlloc(totalSize, 16) : 0;
+                       m_ownsBuffer = true;
+               }
+               else
+               {
+                       m_buffer = buffer;
+                       m_ownsBuffer = false;
+               }
+
+               const bool VOID_IS_8 = ((sizeof(void*) == 8));
+
+#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+               if (VOID_IS_8)
+               {
+#if _WIN64
+                       initDNA((const char*)sBulletDNAstr64, sBulletDNAlen64);
+#else
+                       btAssert(0);
+#endif
+               }
+               else
+               {
+#ifndef _WIN64
+                       initDNA((const char*)sBulletDNAstr, sBulletDNAlen);
+#else
+                       btAssert(0);
+#endif
+               }
+
+#else   //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+               if (VOID_IS_8)
+               {
+                       initDNA((const char*)sBulletDNAstr64, sBulletDNAlen64);
+               }
+               else
+               {
+                       initDNA((const char*)sBulletDNAstr, sBulletDNAlen);
+               }
+#endif  //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+       }
+
+       virtual ~btDefaultSerializer()
+       {
+               if (m_buffer && m_ownsBuffer)
+                       btAlignedFree(m_buffer);
+               if (m_dna)
+                       btAlignedFree(m_dna);
+       }
+
+       static int getMemoryDnaSizeInBytes()
+       {
+               const bool VOID_IS_8 = ((sizeof(void*) == 8));
+
+               if (VOID_IS_8)
+               {
+                       return sBulletDNAlen64;
+               }
+               return sBulletDNAlen;
+       }
+       static const char* getMemoryDna()
+       {
+               const bool VOID_IS_8 = ((sizeof(void*) == 8));
+               if (VOID_IS_8)
+               {
+                       return (const char*)sBulletDNAstr64;
+               }
+               return (const char*)sBulletDNAstr;
+       }
+
+       void insertHeader()
+       {
+               writeHeader(m_buffer);
+               m_currentSize += BT_HEADER_LENGTH;
+       }
+
+       void writeHeader(unsigned char* buffer) const
+       {
+#ifdef BT_USE_DOUBLE_PRECISION
+               memcpy(buffer, "BULLETd", 7);
+#else
+               memcpy(buffer, "BULLETf", 7);
+#endif  //BT_USE_DOUBLE_PRECISION
+
+               int littleEndian = 1;
+               littleEndian = ((char*)&littleEndian)[0];
+
+               if (sizeof(void*) == 8)
+               {
+                       buffer[7] = '-';
+               }
+               else
+               {
+                       buffer[7] = '_';
+               }
+
+               if (littleEndian)
+               {
+                       buffer[8] = 'v';
+               }
+               else
+               {
+                       buffer[8] = 'V';
+               }
+
+               buffer[9] = '3';
+               buffer[10] = '2';
+               buffer[11] = '5';
+       }
+
+       virtual void startSerialization()
+       {
+               m_uniqueIdGenerator = 1;
+               if (m_totalSize)
+               {
+                       unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
+                       writeHeader(buffer);
+               }
+       }
+
+       virtual void finishSerialization()
+       {
+               writeDNA();
+
+               //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
+               if (!m_totalSize)
+               {
+                       if (m_buffer)
+                               btAlignedFree(m_buffer);
+
+                       m_currentSize += BT_HEADER_LENGTH;
+                       m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize, 16);
+
+                       unsigned char* currentPtr = m_buffer;
+                       writeHeader(m_buffer);
+                       currentPtr += BT_HEADER_LENGTH;
+                       for (int i = 0; i < m_chunkPtrs.size(); i++)
+                       {
+                               int curLength = (int)sizeof(btChunk) + m_chunkPtrs[i]->m_length;
+                               memcpy(currentPtr, m_chunkPtrs[i], curLength);
+                               btAlignedFree(m_chunkPtrs[i]);
+                               currentPtr += curLength;
+                       }
+               }
+
+               mTypes.clear();
+               mStructs.clear();
+               mTlens.clear();
+               mStructReverse.clear();
+               mTypeLookup.clear();
+               m_skipPointers.clear();
+               m_chunkP.clear();
+               m_nameMap.clear();
+               m_uniquePointers.clear();
+               m_chunkPtrs.clear();
+       }
+
+       virtual void* getUniquePointer(void* oldPtr)
+       {
+               btAssert(m_uniqueIdGenerator >= 0);
+               if (!oldPtr)
+                       return 0;
+
+               btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
+               if (uptr)
+               {
+                       return uptr->m_ptr;
+               }
+
+               void** ptr2 = m_skipPointers[oldPtr];
+               if (ptr2)
+               {
+                       return 0;
+               }
+
+               m_uniqueIdGenerator++;
+
+               btPointerUid uid;
+               uid.m_uniqueIds[0] = m_uniqueIdGenerator;
+               uid.m_uniqueIds[1] = m_uniqueIdGenerator;
+               m_uniquePointers.insert(oldPtr, uid);
+               return uid.m_ptr;
+       }
+
+       virtual const unsigned char* getBufferPointer() const
+       {
+               return m_buffer;
+       }
+
+       virtual int getCurrentBufferSize() const
+       {
+               return m_currentSize;
+       }
+
+       virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
+       {
+               if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
+               {
+                       btAssert(!findPointer(oldPtr));
+               }
+
+               chunk->m_dna_nr = getReverseType(structType);
+
+               chunk->m_chunkCode = chunkCode;
+
+               void* uniquePtr = getUniquePointer(oldPtr);
+
+               m_chunkP.insert(oldPtr, uniquePtr);  //chunk->m_oldPtr);
+               chunk->m_oldPtr = uniquePtr;         //oldPtr;
+       }
+
+       virtual unsigned char* internalAlloc(size_t size)
+       {
+               unsigned char* ptr = 0;
+
+               if (m_totalSize)
+               {
+                       ptr = m_buffer + m_currentSize;
+                       m_currentSize += int(size);
+                       btAssert(m_currentSize < m_totalSize);
+               }
+               else
+               {
+                       ptr = (unsigned char*)btAlignedAlloc(size, 16);
+                       m_currentSize += int(size);
+               }
+               return ptr;
+       }
+
+       virtual btChunk* allocate(size_t size, int numElements)
+       {
+               unsigned char* ptr = internalAlloc(int(size) * numElements + sizeof(btChunk));
+
+               unsigned char* data = ptr + sizeof(btChunk);
+
+               btChunk* chunk = (btChunk*)ptr;
+               chunk->m_chunkCode = 0;
+               chunk->m_oldPtr = data;
+               chunk->m_length = int(size) * numElements;
+               chunk->m_number = numElements;
+
+               m_chunkPtrs.push_back(chunk);
+
+               return chunk;
+       }
+
+       virtual const char* findNameForPointer(const void* ptr) const
+       {
+               const char* const* namePtr = m_nameMap.find(ptr);
+               if (namePtr && *namePtr)
+                       return *namePtr;
+               return 0;
+       }
+
+       virtual void registerNameForPointer(const void* ptr, const char* name)
+       {
+               m_nameMap.insert(ptr, name);
+       }
+
+       virtual void serializeName(const char* name)
+       {
+               if (name)
+               {
+                       //don't serialize name twice
+                       if (findPointer((void*)name))
+                               return;
+
+                       int len = btStrLen(name);
+                       if (len)
+                       {
+                               int newLen = len + 1;
+                               int padding = ((newLen + 3) & ~3) - newLen;
+                               newLen += padding;
+
+                               //serialize name string now
+                               btChunk* chunk = allocate(sizeof(char), newLen);
+                               char* destinationName = (char*)chunk->m_oldPtr;
+                               for (int i = 0; i < len; i++)
+                               {
+                                       destinationName[i] = name[i];
+                               }
+                               destinationName[len] = 0;
+                               finalizeChunk(chunk, "char", BT_ARRAY_CODE, (void*)name);
+                       }
+               }
+       }
+
+       virtual int getSerializationFlags() const
+       {
+               return m_serializationFlags;
+       }
+
+       virtual void setSerializationFlags(int flags)
+       {
+               m_serializationFlags = flags;
+       }
+       int getNumChunks() const
+       {
+               return m_chunkPtrs.size();
+       }
+
+       const btChunk* getChunk(int chunkIndex) const
+       {
+               return m_chunkPtrs[chunkIndex];
+       }
+};
+
+///In general it is best to use btDefaultSerializer,
+///in particular when writing the data to disk or sending it over the network.
+///The btInMemorySerializer is experimental and only suitable in a few cases.
+///The btInMemorySerializer takes a shortcut and can be useful to create a deep-copy
+///of objects. There will be a demo on how to use the btInMemorySerializer.
+#ifdef ENABLE_INMEMORY_SERIALIZER
+
+struct btInMemorySerializer : public btDefaultSerializer
+{
+       btHashMap<btHashPtr, btChunk*> m_uid2ChunkPtr;
+       btHashMap<btHashPtr, void*> m_orgPtr2UniqueDataPtr;
+       btHashMap<btHashString, const void*> m_names2Ptr;
+
+       btBulletSerializedArrays m_arrays;
+
+       btInMemorySerializer(int totalSize = 0, unsigned char* buffer = 0)
+               : btDefaultSerializer(totalSize, buffer)
+       {
+       }
+
+       virtual void startSerialization()
+       {
+               m_uid2ChunkPtr.clear();
+               //todo: m_arrays.clear();
+               btDefaultSerializer::startSerialization();
+       }
+
+       btChunk* findChunkFromUniquePointer(void* uniquePointer)
+       {
+               btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer];
+               if (chkPtr)
+               {
+                       return *chkPtr;
+               }
+               return 0;
+       }
+
+       virtual void registerNameForPointer(const void* ptr, const char* name)
+       {
+               btDefaultSerializer::registerNameForPointer(ptr, name);
+               m_names2Ptr.insert(name, ptr);
+       }
+
+       virtual void finishSerialization()
+       {
+       }
+
+       virtual void* getUniquePointer(void* oldPtr)
+       {
+               if (oldPtr == 0)
+                       return 0;
+
+               // void* uniquePtr = getUniquePointer(oldPtr);
+               btChunk* chunk = findChunkFromUniquePointer(oldPtr);
+               if (chunk)
+               {
+                       return chunk->m_oldPtr;
+               }
+               else
+               {
+                       const char* n = (const char*)oldPtr;
+                       const void** ptr = m_names2Ptr[n];
+                       if (ptr)
+                       {
+                               return oldPtr;
+                       }
+                       else
+                       {
+                               void** ptr2 = m_skipPointers[oldPtr];
+                               if (ptr2)
+                               {
+                                       return 0;
+                               }
+                               else
+                               {
+                                       //If this assert hit, serialization happened in the wrong order
+                                       // 'getUniquePointer'
+                                       btAssert(0);
+                               }
+                       }
+                       return 0;
+               }
+               return oldPtr;
+       }
+
+       virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
+       {
+               if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
+               {
+                       btAssert(!findPointer(oldPtr));
+               }
+
+               chunk->m_dna_nr = getReverseType(structType);
+               chunk->m_chunkCode = chunkCode;
+               //void* uniquePtr = getUniquePointer(oldPtr);
+               m_chunkP.insert(oldPtr, oldPtr);  //chunk->m_oldPtr);
+               // chunk->m_oldPtr = uniquePtr;//oldPtr;
+
+               void* uid = findPointer(oldPtr);
+               m_uid2ChunkPtr.insert(uid, chunk);
+
+               switch (chunk->m_chunkCode)
+               {
+                       case BT_SOFTBODY_CODE:
+                       {
+#ifdef BT_USE_DOUBLE_PRECISION
+                               m_arrays.m_softBodyDoubleData.push_back((btSoftBodyDoubleData*)chunk->m_oldPtr);
+#else
+                               m_arrays.m_softBodyFloatData.push_back((btSoftBodyFloatData*)chunk->m_oldPtr);
+#endif
+                               break;
+                       }
+                       case BT_COLLISIONOBJECT_CODE:
+                       {
+#ifdef BT_USE_DOUBLE_PRECISION
+                               m_arrays.m_collisionObjectDataDouble.push_back((btCollisionObjectDoubleData*)chunk->m_oldPtr);
+#else   //BT_USE_DOUBLE_PRECISION
+                               m_arrays.m_collisionObjectDataFloat.push_back((btCollisionObjectFloatData*)chunk->m_oldPtr);
+#endif  //BT_USE_DOUBLE_PRECISION
+                               break;
+                       }
+                       case BT_RIGIDBODY_CODE:
+                       {
+#ifdef BT_USE_DOUBLE_PRECISION
+                               m_arrays.m_rigidBodyDataDouble.push_back((btRigidBodyDoubleData*)chunk->m_oldPtr);
+#else
+                               m_arrays.m_rigidBodyDataFloat.push_back((btRigidBodyFloatData*)chunk->m_oldPtr);
+#endif  //BT_USE_DOUBLE_PRECISION
+                               break;
+                       };
+                       case BT_CONSTRAINT_CODE:
+                       {
+#ifdef BT_USE_DOUBLE_PRECISION
+                               m_arrays.m_constraintDataDouble.push_back((btTypedConstraintDoubleData*)chunk->m_oldPtr);
+#else
+                               m_arrays.m_constraintDataFloat.push_back((btTypedConstraintFloatData*)chunk->m_oldPtr);
+#endif
+                               break;
+                       }
+                       case BT_QUANTIZED_BVH_CODE:
+                       {
+#ifdef BT_USE_DOUBLE_PRECISION
+                               m_arrays.m_bvhsDouble.push_back((btQuantizedBvhDoubleData*)chunk->m_oldPtr);
+#else
+                               m_arrays.m_bvhsFloat.push_back((btQuantizedBvhFloatData*)chunk->m_oldPtr);
+#endif
+                               break;
+                       }
+
+                       case BT_SHAPE_CODE:
+                       {
+                               btCollisionShapeData* shapeData = (btCollisionShapeData*)chunk->m_oldPtr;
+                               m_arrays.m_colShapeData.push_back(shapeData);
+                               break;
+                       }
+                       case BT_TRIANLGE_INFO_MAP:
+                       case BT_ARRAY_CODE:
+                       case BT_SBMATERIAL_CODE:
+                       case BT_SBNODE_CODE:
+                       case BT_DYNAMICSWORLD_CODE:
+                       case BT_DNA_CODE:
+                       {
+                               break;
+                       }
+                       default:
+                       {
+                       }
+               };
+       }
+
+       int getNumChunks() const
+       {
+               return m_uid2ChunkPtr.size();
+       }
+
+       const btChunk* getChunk(int chunkIndex) const
+       {
+               return *m_uid2ChunkPtr.getAtIndex(chunkIndex);
+       }
+};
+#endif  //ENABLE_INMEMORY_SERIALIZER
+
+#endif  //BT_SERIALIZER_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btSerializer64.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btSerializer64.cpp
new file mode 100644 (file)
index 0000000..6c4bc70
--- /dev/null
@@ -0,0 +1,692 @@
+char sBulletDNAstr64[]= {
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-74),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
+char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
+char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
+char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
+char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
+char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
+char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
+char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
+char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
+char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
+char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
+char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
+char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
+char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
+char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
+char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
+char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
+char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
+char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
+char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
+char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
+char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
+char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
+char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
+char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
+char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
+char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(112),char(97),
+char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
+char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
+char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
+char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),char(115),
+char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
+char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
+char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),
+char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
+char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
+char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
+char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
+char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
+char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
+char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
+char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
+char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
+char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
+char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
+char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),
+char(101),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
+char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
+char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),
+char(77),char(97),char(112),char(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
+char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(116),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
+char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
+char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
+char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
+char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(117),char(112),char(73),char(110),char(100),
+char(101),char(120),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),
+char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),
+char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),
+char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),
+char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),
+char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),
+char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),
+char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),
+char(116),char(101),char(120),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(68),
+char(105),char(115),char(116),char(97),char(110),char(99),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(122),
+char(101),char(114),char(111),char(65),char(114),char(101),char(97),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),
+char(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),
+char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(75),char(101),char(121),char(115),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(111),
+char(99),char(97),char(108),char(80),char(111),char(105),char(110),char(116),char(65),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(76),char(111),char(99),char(97),char(108),char(80),char(111),char(105),char(110),char(116),char(66),char(91),char(52),char(93),char(0),
+char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),
+char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(65),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(66),
+char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(78),char(111),char(114),char(109),
+char(97),char(108),char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(66),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),
+char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
+char(110),char(68),char(105),char(114),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
+char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(68),char(105),char(114),char(50),
+char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(68),char(105),char(115),char(116),
+char(97),char(110),char(99),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
+char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(91),char(52),char(93),char(0),char(109),char(95),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(114),char(101),char(118),char(82),char(72),char(83),char(91),char(52),char(93),
+char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),
+char(100),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),
+char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
+char(97),char(114),char(116),char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(80),char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
+char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),
+char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),
+char(116),char(70),char(108),char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
+char(104),char(101),char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),
+char(114),char(97),char(108),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
+char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),
+char(108),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
+char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),
+char(110),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
+char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
+char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),
+char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),
+char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),
+char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),
+char(101),char(84),char(105),char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),
+char(80),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),
+char(65),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),
+char(110),char(100),char(101),char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),
+char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),
+char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),
+char(111),char(100),char(121),char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),
+char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),
+char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),
+char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),
+char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),
+char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),
+char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),
+char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),
+char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),
+char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),
+char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),
+char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),
+char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
+char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),
+char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
+char(99),char(116),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),
+char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),
+char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),
+char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),
+char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),
+char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),
+char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),
+char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),
+char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),
+char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
+char(116),char(101),char(114),char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(70),char(105),char(108),char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),
+char(100),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),
+char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),
+char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),
+char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),
+char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),
+char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),
+char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(114),char(116),char(105),char(99),char(117),char(108),
+char(97),char(116),char(101),char(100),char(87),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),
+char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),
+char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
+char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),
+char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),
+char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),
+char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),
+char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),
+char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
+char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),
+char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),
+char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),
+char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),
+char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),
+char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
+char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),
+char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
+char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),
+char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),
+char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),
+char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),
+char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),
+char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
+char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),
+char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),
+char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),
+char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),
+char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),
+char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),
+char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),
+char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
+char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),
+char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),
+char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),
+char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),
+char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),
+char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),
+char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),
+char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),
+char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),
+char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),
+char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),
+char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(108),
+char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),
+char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),
+char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),
+char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),
+char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),
+char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),
+char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
+char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),
+char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),
+char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),
+char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),
+char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),
+char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(97),char(120),char(77),
+char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
+char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),
+char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
+char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),
+char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
+char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
+char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
+char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),
+char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),
+char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),
+char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(97),char(120),char(77),char(111),
+char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),
+char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),
+char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),
+char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
+char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),
+char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),
+char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),char(114),
+char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
+char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
+char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
+char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),char(101),char(114),char(0),char(109),char(95),
+char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(66),char(0),char(109),char(95),
+char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),
+char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),
+char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
+char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),
+char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),
+char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),
+char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),
+char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),
+char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),
+char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),
+char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),
+char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),
+char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),
+char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),
+char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),
+char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),
+char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),
+char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),
+char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
+char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),
+char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),
+char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
+char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),
+char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),
+char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
+char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),
+char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),
+char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),
+char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),
+char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),
+char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),
+char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),
+char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),
+char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),
+char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),
+char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),
+char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),
+char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),
+char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),
+char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
+char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),
+char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),
+char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),
+char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
+char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),
+char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),
+char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
+char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),
+char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),
+char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),
+char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),
+char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),
+char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),
+char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),
+char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),
+char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),
+char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),
+char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),
+char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),
+char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
+char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),
+char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),
+char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(109),
+char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),char(111),char(84),char(104),char(105),char(115),
+char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),char(104),char(105),char(115),char(80),char(105),
+char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),char(115),char(80),char(105),char(118),char(111),
+char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(106),
+char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),
+char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),
+char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),
+char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),
+char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),
+char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
+char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(108),char(105),
+char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110),char(100),char(101),char(120),
+char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115),char(86),char(97),char(114),
+char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91),char(55),char(93),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(68),char(97),
+char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
+char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
+char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),
+char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
+char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
+char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),char(109),char(101),char(0),char(42),char(109),
+char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),char(109),char(95),char(112),char(97),char(100),
+char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(80),
+char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(79),
+char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(76),char(105),char(110),
+char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(65),char(110),
+char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),
+char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(42),
+char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(67),char(111),
+char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),char(68),char(97),char(116),char(97),char(0),
+char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(0),
+char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),
+char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),
+char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),
+char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),
+char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),
+char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
+char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),
+char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),
+char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),
+char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),
+char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),
+char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),
+char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
+char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
+char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),
+char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
+char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),
+char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),
+char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),
+char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),
+char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
+char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),
+char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),
+char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),
+char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),
+char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),
+char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),
+char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),
+char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),
+char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
+char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
+char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
+char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),
+char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
+char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),
+char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
+char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),
+char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),
+char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),
+char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),
+char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),
+char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
+char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
+char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),
+char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),
+char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),
+char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),
+char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),
+char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),
+char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),
+char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
+char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
+char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
+char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),
+char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),
+char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),
+char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
+char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),
+char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),
+char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),
+char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
+char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0),char(-112),char(0),char(16),char(0),char(56),char(0),char(56),char(0),
+char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(56),char(0),char(32),char(0),char(80),char(0),char(72),char(0),
+char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(64),char(0),char(16),char(0),char(24),char(6),char(-8),char(1),char(80),char(3),
+char(32),char(1),char(72),char(0),char(80),char(0),char(-96),char(0),char(88),char(0),char(-64),char(0),char(104),char(0),char(8),char(2),char(-56),char(3),char(8),char(0),
+char(64),char(0),char(64),char(0),char(0),char(0),char(80),char(0),char(96),char(0),char(-112),char(0),char(-128),char(0),char(104),char(1),char(-24),char(0),char(-104),char(1),
+char(-120),char(1),char(-32),char(0),char(8),char(1),char(-40),char(1),char(104),char(1),char(-128),char(2),char(-112),char(2),char(-64),char(4),char(-40),char(0),char(120),char(1),
+char(104),char(0),char(-104),char(0),char(16),char(0),char(104),char(0),char(24),char(0),char(40),char(0),char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0),
+char(104),char(1),char(112),char(0),char(-16),char(1),char(-128),char(3),char(-40),char(1),char(-56),char(0),char(112),char(0),char(48),char(1),char(8),char(2),char(0),char(0),
+char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),
+char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),
+char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),
+char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),
+char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
+char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),
+char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
+char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
+char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
+char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
+char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),
+char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
+char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),
+char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
+char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
+char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),
+char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),
+char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
+char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
+char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),
+char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),
+char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),
+char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
+char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),
+char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),
+char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),
+char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),
+char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
+char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
+char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
+char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),
+char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),
+char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),
+char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),
+char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),
+char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),
+char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(39),char(0),char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),
+char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),
+char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),
+char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),
+char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),
+char(8),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(48),char(0),char(-124),char(0),char(48),char(0),char(-123),char(0),char(49),char(0),char(39),char(0),char(13),char(0),char(96),char(0),char(13),char(0),char(97),char(0),
+char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),char(13),char(0),char(102),char(0),
+char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),char(7),char(0),char(107),char(0),
+char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
+char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),char(7),char(0),char(117),char(0),
+char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),char(7),char(0),char(122),char(0),
+char(7),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
+char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(7),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
+char(50),char(0),char(-124),char(0),char(50),char(0),char(-123),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
+char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-122),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
+char(13),char(0),char(-121),char(0),char(14),char(0),char(-120),char(0),char(4),char(0),char(-119),char(0),char(0),char(0),char(-118),char(0),char(48),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-114),char(0),
+char(20),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),char(8),char(0),char(-125),char(0),
+char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),char(8),char(0),char(-105),char(0),
+char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(50),char(0),char(29),char(0),
+char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-114),char(0),
+char(19),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(13),char(0),char(-110),char(0),char(7),char(0),char(-125),char(0),
+char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),char(7),char(0),char(-105),char(0),
+char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
+char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
+char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(53),char(0),char(23),char(0),
+char(8),char(0),char(-90),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-88),char(0),char(8),char(0),char(-104),char(0),
+char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),
+char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),
+char(8),char(0),char(-77),char(0),char(8),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),
+char(4),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-90),char(0),
+char(7),char(0),char(-89),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-87),char(0),
+char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0),
+char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
+char(7),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(4),char(0),char(-72),char(0),
+char(4),char(0),char(-71),char(0),char(55),char(0),char(2),char(0),char(53),char(0),char(-70),char(0),char(14),char(0),char(-69),char(0),char(56),char(0),char(2),char(0),
+char(54),char(0),char(-70),char(0),char(13),char(0),char(-69),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-68),char(0),char(17),char(0),char(-67),char(0),
+char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0),char(13),char(0),char(-69),char(0),
+char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(13),char(0),char(-60),char(0),char(13),char(0),char(-59),char(0),char(7),char(0),char(-58),char(0),
+char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),
+char(7),char(0),char(-52),char(0),char(7),char(0),char(-51),char(0),char(7),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(58),char(0),char(22),char(0),
+char(48),char(0),char(-68),char(0),char(18),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),char(14),char(0),char(-64),char(0),
+char(14),char(0),char(-63),char(0),char(14),char(0),char(-69),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),char(14),char(0),char(-60),char(0),
+char(14),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-55),char(0),
+char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(8),char(0),char(-51),char(0),char(8),char(0),char(-50),char(0),
+char(4),char(0),char(-49),char(0),char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-48),char(0),char(4),char(0),char(-47),char(0),
+char(60),char(0),char(13),char(0),char(57),char(0),char(-46),char(0),char(57),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),
+char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),
+char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(61),char(0),char(13),char(0),
+char(62),char(0),char(-46),char(0),char(62),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),
+char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
+char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-46),char(0),
+char(58),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),
+char(4),char(0),char(-42),char(0),char(8),char(0),char(-41),char(0),char(8),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),
+char(8),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),
+char(13),char(0),char(-33),char(0),char(13),char(0),char(-32),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),
+char(14),char(0),char(-32),char(0),char(66),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),char(14),char(0),char(-32),char(0),
+char(67),char(0),char(13),char(0),char(61),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
+char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
+char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(68),char(0),char(13),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),
+char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),
+char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),
+char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),
+char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(0),char(0),char(-19),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-34),char(0),
+char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),
+char(8),char(0),char(-22),char(0),char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-89),char(0),char(71),char(0),char(11),char(0),
+char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(7),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0),
+char(7),char(0),char(-16),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-89),char(0),
+char(0),char(0),char(21),char(0),char(72),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),
+char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(73),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),
+char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
+char(4),char(0),char(-10),char(0),char(74),char(0),char(5),char(0),char(72),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),
+char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),
+char(8),char(0),char(-7),char(0),char(8),char(0),char(-6),char(0),char(8),char(0),char(-5),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-34),char(0),
+char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-4),char(0),
+char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),char(13),char(0),char(1),char(1),
+char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(13),char(0),char(5),char(1),char(13),char(0),char(6),char(1),
+char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),
+char(0),char(0),char(-19),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(13),char(0),char(12),char(1),char(13),char(0),char(13),char(1),
+char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),char(13),char(0),char(18),char(1),
+char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(13),char(0),char(21),char(1),char(13),char(0),char(22),char(1),char(0),char(0),char(23),char(1),
+char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),
+char(77),char(0),char(41),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(14),char(0),char(-15),char(0),
+char(14),char(0),char(-14),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),char(14),char(0),char(-1),char(0),
+char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),char(14),char(0),char(4),char(1),
+char(14),char(0),char(5),char(1),char(14),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),
+char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),char(0),char(0),char(-19),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),
+char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),char(14),char(0),char(16),char(1),
+char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),char(14),char(0),char(21),char(1),
+char(14),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),
+char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),
+char(19),char(0),char(-30),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),char(7),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),
+char(20),char(0),char(-30),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(8),char(0),char(-13),char(0),char(8),char(0),char(-12),char(0),
+char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-34),char(0),char(13),char(0),char(29),char(1),
+char(13),char(0),char(30),char(1),char(7),char(0),char(31),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-34),char(0),
+char(14),char(0),char(29),char(1),char(14),char(0),char(30),char(1),char(8),char(0),char(31),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(32),char(1),
+char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(35),char(1),
+char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(13),char(0),char(39),char(1),char(13),char(0),char(40),char(1),
+char(7),char(0),char(-58),char(0),char(7),char(0),char(41),char(1),char(4),char(0),char(42),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),
+char(82),char(0),char(35),char(1),char(4),char(0),char(43),char(1),char(7),char(0),char(44),char(1),char(4),char(0),char(45),char(1),char(85),char(0),char(4),char(0),
+char(13),char(0),char(40),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(46),char(1),char(7),char(0),char(47),char(1),char(86),char(0),char(7),char(0),
+char(13),char(0),char(48),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(49),char(1),char(7),char(0),char(50),char(1),char(7),char(0),char(51),char(1),
+char(7),char(0),char(52),char(1),char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(53),char(1),char(13),char(0),char(51),char(1),
+char(13),char(0),char(54),char(1),char(62),char(0),char(55),char(1),char(4),char(0),char(56),char(1),char(7),char(0),char(52),char(1),char(88),char(0),char(26),char(0),
+char(4),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(-89),char(0),char(7),char(0),char(59),char(1),char(7),char(0),char(60),char(1),
+char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1),
+char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1),
+char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),char(7),char(0),char(75),char(1),
+char(7),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(79),char(1),char(4),char(0),char(80),char(1),
+char(4),char(0),char(-99),char(0),char(89),char(0),char(12),char(0),char(17),char(0),char(81),char(1),char(17),char(0),char(82),char(1),char(17),char(0),char(83),char(1),
+char(13),char(0),char(84),char(1),char(13),char(0),char(85),char(1),char(7),char(0),char(86),char(1),char(4),char(0),char(87),char(1),char(4),char(0),char(88),char(1),
+char(4),char(0),char(89),char(1),char(4),char(0),char(90),char(1),char(7),char(0),char(50),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),
+char(19),char(0),char(91),char(1),char(17),char(0),char(92),char(1),char(17),char(0),char(93),char(1),char(13),char(0),char(84),char(1),char(13),char(0),char(94),char(1),
+char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(13),char(0),char(97),char(1),char(13),char(0),char(98),char(1),char(4),char(0),char(99),char(1),
+char(7),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(103),char(1),char(7),char(0),char(104),char(1),
+char(7),char(0),char(105),char(1),char(4),char(0),char(106),char(1),char(4),char(0),char(107),char(1),char(7),char(0),char(108),char(1),char(7),char(0),char(109),char(1),
+char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(7),char(0),char(112),char(1),char(7),char(0),char(113),char(1),char(4),char(0),char(114),char(1),
+char(4),char(0),char(115),char(1),char(4),char(0),char(116),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(117),char(1),char(9),char(0),char(118),char(1),
+char(13),char(0),char(119),char(1),char(7),char(0),char(120),char(1),char(7),char(0),char(-85),char(0),char(7),char(0),char(121),char(1),char(4),char(0),char(122),char(1),
+char(13),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(125),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(53),char(0),
+char(92),char(0),char(19),char(0),char(50),char(0),char(-68),char(0),char(89),char(0),char(127),char(1),char(82),char(0),char(-128),char(1),char(83),char(0),char(-127),char(1),
+char(84),char(0),char(-126),char(1),char(85),char(0),char(-125),char(1),char(86),char(0),char(-124),char(1),char(87),char(0),char(-123),char(1),char(90),char(0),char(-122),char(1),
+char(91),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(-119),char(1),char(4),char(0),char(-118),char(1),
+char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(4),char(0),char(-115),char(1),char(4),char(0),char(-114),char(1),char(88),char(0),char(-113),char(1),
+char(93),char(0),char(28),char(0),char(16),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),char(14),char(0),char(-109),char(1),
+char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),char(14),char(0),char(-104),char(1),
+char(14),char(0),char(-103),char(1),char(8),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(-100),char(1),
+char(4),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),char(8),char(0),char(-95),char(1),
+char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(8),char(0),char(-91),char(1),char(8),char(0),char(-90),char(1),
+char(0),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(48),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(94),char(0),char(28),char(0),
+char(15),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),char(13),char(0),char(-108),char(1),
+char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(13),char(0),char(-104),char(1),char(13),char(0),char(-103),char(1),
+char(4),char(0),char(-100),char(1),char(7),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(7),char(0),char(-98),char(1),
+char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(4),char(0),char(-99),char(1),char(7),char(0),char(-95),char(1),char(7),char(0),char(-94),char(1),
+char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(7),char(0),char(-91),char(1),char(7),char(0),char(-90),char(1),char(0),char(0),char(-89),char(1),
+char(0),char(0),char(-88),char(1),char(50),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-85),char(1),
+char(16),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(14),char(0),char(-82),char(1),char(14),char(0),char(-81),char(1),char(8),char(0),char(-80),char(1),
+char(4),char(0),char(-119),char(1),char(0),char(0),char(37),char(0),char(0),char(0),char(-79),char(1),char(93),char(0),char(-126),char(1),char(48),char(0),char(-78),char(1),
+char(96),char(0),char(10),char(0),char(13),char(0),char(-85),char(1),char(15),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),char(13),char(0),char(-82),char(1),
+char(13),char(0),char(-81),char(1),char(7),char(0),char(-80),char(1),char(4),char(0),char(-119),char(1),char(0),char(0),char(-79),char(1),char(94),char(0),char(-126),char(1),
+char(50),char(0),char(-78),char(1),char(97),char(0),char(4),char(0),char(50),char(0),char(-77),char(1),char(96),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),char(98),char(0),char(4),char(0),char(48),char(0),char(-77),char(1),char(95),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
+char(0),char(0),char(37),char(0),};
+int sBulletDNAlen64= sizeof(sBulletDNAstr64);
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btSpatialAlgebra.h b/dali-physics/third-party/bullet3/src/LinearMath/btSpatialAlgebra.h
new file mode 100644 (file)
index 0000000..6ad67a1
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+Copyright (c) 2003-2015 Erwin Coumans, Jakub Stepien
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///These spatial algebra classes are used for btMultiBody,
+///see BulletDynamics/Featherstone
+
+#ifndef BT_SPATIAL_ALGEBRA_H
+#define BT_SPATIAL_ALGEBRA_H
+
+#include "btMatrix3x3.h"
+
+struct btSpatialForceVector
+{
+       btVector3 m_topVec, m_bottomVec;
+       //
+       btSpatialForceVector() { setZero(); }
+       btSpatialForceVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(linear), m_bottomVec(angular) {}
+       btSpatialForceVector(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
+       {
+               setValue(ax, ay, az, lx, ly, lz);
+       }
+       //
+       void setVector(const btVector3 &angular, const btVector3 &linear)
+       {
+               m_topVec = linear;
+               m_bottomVec = angular;
+       }
+       void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
+       {
+               m_bottomVec.setValue(ax, ay, az);
+               m_topVec.setValue(lx, ly, lz);
+       }
+       //
+       void addVector(const btVector3 &angular, const btVector3 &linear)
+       {
+               m_topVec += linear;
+               m_bottomVec += angular;
+       }
+       void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
+       {
+               m_bottomVec[0] += ax;
+               m_bottomVec[1] += ay;
+               m_bottomVec[2] += az;
+               m_topVec[0] += lx;
+               m_topVec[1] += ly;
+               m_topVec[2] += lz;
+       }
+       //
+       const btVector3 &getLinear() const { return m_topVec; }
+       const btVector3 &getAngular() const { return m_bottomVec; }
+       //
+       void setLinear(const btVector3 &linear) { m_topVec = linear; }
+       void setAngular(const btVector3 &angular) { m_bottomVec = angular; }
+       //
+       void addAngular(const btVector3 &angular) { m_bottomVec += angular; }
+       void addLinear(const btVector3 &linear) { m_topVec += linear; }
+       //
+       void setZero()
+       {
+               m_topVec.setZero();
+               m_bottomVec.setZero();
+       }
+       //
+       btSpatialForceVector &operator+=(const btSpatialForceVector &vec)
+       {
+               m_topVec += vec.m_topVec;
+               m_bottomVec += vec.m_bottomVec;
+               return *this;
+       }
+       btSpatialForceVector &operator-=(const btSpatialForceVector &vec)
+       {
+               m_topVec -= vec.m_topVec;
+               m_bottomVec -= vec.m_bottomVec;
+               return *this;
+       }
+       btSpatialForceVector operator-(const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec - vec.m_bottomVec, m_topVec - vec.m_topVec); }
+       btSpatialForceVector operator+(const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec + vec.m_bottomVec, m_topVec + vec.m_topVec); }
+       btSpatialForceVector operator-() const { return btSpatialForceVector(-m_bottomVec, -m_topVec); }
+       btSpatialForceVector operator*(const btScalar &s) const { return btSpatialForceVector(s * m_bottomVec, s * m_topVec); }
+       //btSpatialForceVector & operator = (const btSpatialForceVector &vec) { m_topVec = vec.m_topVec; m_bottomVec = vec.m_bottomVec; return *this; }
+};
+
+struct btSpatialMotionVector
+{
+       btVector3 m_topVec, m_bottomVec;
+       //
+       btSpatialMotionVector() { setZero(); }
+       btSpatialMotionVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(angular), m_bottomVec(linear) {}
+       //
+       void setVector(const btVector3 &angular, const btVector3 &linear)
+       {
+               m_topVec = angular;
+               m_bottomVec = linear;
+       }
+       void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
+       {
+               m_topVec.setValue(ax, ay, az);
+               m_bottomVec.setValue(lx, ly, lz);
+       }
+       //
+       void addVector(const btVector3 &angular, const btVector3 &linear)
+       {
+               m_topVec += linear;
+               m_bottomVec += angular;
+       }
+       void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
+       {
+               m_topVec[0] += ax;
+               m_topVec[1] += ay;
+               m_topVec[2] += az;
+               m_bottomVec[0] += lx;
+               m_bottomVec[1] += ly;
+               m_bottomVec[2] += lz;
+       }
+       //
+       const btVector3 &getAngular() const { return m_topVec; }
+       const btVector3 &getLinear() const { return m_bottomVec; }
+       //
+       void setAngular(const btVector3 &angular) { m_topVec = angular; }
+       void setLinear(const btVector3 &linear) { m_bottomVec = linear; }
+       //
+       void addAngular(const btVector3 &angular) { m_topVec += angular; }
+       void addLinear(const btVector3 &linear) { m_bottomVec += linear; }
+       //
+       void setZero()
+       {
+               m_topVec.setZero();
+               m_bottomVec.setZero();
+       }
+       //
+       btScalar dot(const btSpatialForceVector &b) const
+       {
+               return m_bottomVec.dot(b.m_topVec) + m_topVec.dot(b.m_bottomVec);
+       }
+       //
+       template <typename SpatialVectorType>
+       void cross(const SpatialVectorType &b, SpatialVectorType &out) const
+       {
+               out.m_topVec = m_topVec.cross(b.m_topVec);
+               out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
+       }
+       template <typename SpatialVectorType>
+       SpatialVectorType cross(const SpatialVectorType &b) const
+       {
+               SpatialVectorType out;
+               out.m_topVec = m_topVec.cross(b.m_topVec);
+               out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
+               return out;
+       }
+       //
+       btSpatialMotionVector &operator+=(const btSpatialMotionVector &vec)
+       {
+               m_topVec += vec.m_topVec;
+               m_bottomVec += vec.m_bottomVec;
+               return *this;
+       }
+       btSpatialMotionVector &operator-=(const btSpatialMotionVector &vec)
+       {
+               m_topVec -= vec.m_topVec;
+               m_bottomVec -= vec.m_bottomVec;
+               return *this;
+       }
+       btSpatialMotionVector &operator*=(const btScalar &s)
+       {
+               m_topVec *= s;
+               m_bottomVec *= s;
+               return *this;
+       }
+       btSpatialMotionVector operator-(const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec - vec.m_topVec, m_bottomVec - vec.m_bottomVec); }
+       btSpatialMotionVector operator+(const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec + vec.m_topVec, m_bottomVec + vec.m_bottomVec); }
+       btSpatialMotionVector operator-() const { return btSpatialMotionVector(-m_topVec, -m_bottomVec); }
+       btSpatialMotionVector operator*(const btScalar &s) const { return btSpatialMotionVector(s * m_topVec, s * m_bottomVec); }
+};
+
+struct btSymmetricSpatialDyad
+{
+       btMatrix3x3 m_topLeftMat, m_topRightMat, m_bottomLeftMat;
+       //
+       btSymmetricSpatialDyad() { setIdentity(); }
+       btSymmetricSpatialDyad(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat) { setMatrix(topLeftMat, topRightMat, bottomLeftMat); }
+       //
+       void setMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
+       {
+               m_topLeftMat = topLeftMat;
+               m_topRightMat = topRightMat;
+               m_bottomLeftMat = bottomLeftMat;
+       }
+       //
+       void addMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
+       {
+               m_topLeftMat += topLeftMat;
+               m_topRightMat += topRightMat;
+               m_bottomLeftMat += bottomLeftMat;
+       }
+       //
+       void setIdentity()
+       {
+               m_topLeftMat.setIdentity();
+               m_topRightMat.setIdentity();
+               m_bottomLeftMat.setIdentity();
+       }
+       //
+       btSymmetricSpatialDyad &operator-=(const btSymmetricSpatialDyad &mat)
+       {
+               m_topLeftMat -= mat.m_topLeftMat;
+               m_topRightMat -= mat.m_topRightMat;
+               m_bottomLeftMat -= mat.m_bottomLeftMat;
+               return *this;
+       }
+       //
+       btSpatialForceVector operator*(const btSpatialMotionVector &vec)
+       {
+               return btSpatialForceVector(m_bottomLeftMat * vec.m_topVec + m_topLeftMat.transpose() * vec.m_bottomVec, m_topLeftMat * vec.m_topVec + m_topRightMat * vec.m_bottomVec);
+       }
+};
+
+struct btSpatialTransformationMatrix
+{
+       btMatrix3x3 m_rotMat;  //btMatrix3x3 m_trnCrossMat;
+       btVector3 m_trnVec;
+       //
+       enum eOutputOperation
+       {
+               None = 0,
+               Add = 1,
+               Subtract = 2
+       };
+       //
+       template <typename SpatialVectorType>
+       void transform(const SpatialVectorType &inVec,
+                                  SpatialVectorType &outVec,
+                                  eOutputOperation outOp = None)
+       {
+               if (outOp == None)
+               {
+                       outVec.m_topVec = m_rotMat * inVec.m_topVec;
+                       outVec.m_bottomVec = -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
+               }
+               else if (outOp == Add)
+               {
+                       outVec.m_topVec += m_rotMat * inVec.m_topVec;
+                       outVec.m_bottomVec += -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
+               }
+               else if (outOp == Subtract)
+               {
+                       outVec.m_topVec -= m_rotMat * inVec.m_topVec;
+                       outVec.m_bottomVec -= -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
+               }
+       }
+
+       template <typename SpatialVectorType>
+       void transformRotationOnly(const SpatialVectorType &inVec,
+                                                          SpatialVectorType &outVec,
+                                                          eOutputOperation outOp = None)
+       {
+               if (outOp == None)
+               {
+                       outVec.m_topVec = m_rotMat * inVec.m_topVec;
+                       outVec.m_bottomVec = m_rotMat * inVec.m_bottomVec;
+               }
+               else if (outOp == Add)
+               {
+                       outVec.m_topVec += m_rotMat * inVec.m_topVec;
+                       outVec.m_bottomVec += m_rotMat * inVec.m_bottomVec;
+               }
+               else if (outOp == Subtract)
+               {
+                       outVec.m_topVec -= m_rotMat * inVec.m_topVec;
+                       outVec.m_bottomVec -= m_rotMat * inVec.m_bottomVec;
+               }
+       }
+
+       template <typename SpatialVectorType>
+       void transformInverse(const SpatialVectorType &inVec,
+                                                 SpatialVectorType &outVec,
+                                                 eOutputOperation outOp = None)
+       {
+               if (outOp == None)
+               {
+                       outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
+                       outVec.m_bottomVec = m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
+               }
+               else if (outOp == Add)
+               {
+                       outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
+                       outVec.m_bottomVec += m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
+               }
+               else if (outOp == Subtract)
+               {
+                       outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
+                       outVec.m_bottomVec -= m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
+               }
+       }
+
+       template <typename SpatialVectorType>
+       void transformInverseRotationOnly(const SpatialVectorType &inVec,
+                                                                         SpatialVectorType &outVec,
+                                                                         eOutputOperation outOp = None)
+       {
+               if (outOp == None)
+               {
+                       outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
+                       outVec.m_bottomVec = m_rotMat.transpose() * inVec.m_bottomVec;
+               }
+               else if (outOp == Add)
+               {
+                       outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
+                       outVec.m_bottomVec += m_rotMat.transpose() * inVec.m_bottomVec;
+               }
+               else if (outOp == Subtract)
+               {
+                       outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
+                       outVec.m_bottomVec -= m_rotMat.transpose() * inVec.m_bottomVec;
+               }
+       }
+
+       void transformInverse(const btSymmetricSpatialDyad &inMat,
+                                                 btSymmetricSpatialDyad &outMat,
+                                                 eOutputOperation outOp = None)
+       {
+               const btMatrix3x3 r_cross(0, -m_trnVec[2], m_trnVec[1],
+                                                                 m_trnVec[2], 0, -m_trnVec[0],
+                                                                 -m_trnVec[1], m_trnVec[0], 0);
+
+               if (outOp == None)
+               {
+                       outMat.m_topLeftMat = m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
+                       outMat.m_topRightMat = m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
+                       outMat.m_bottomLeftMat = m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
+               }
+               else if (outOp == Add)
+               {
+                       outMat.m_topLeftMat += m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
+                       outMat.m_topRightMat += m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
+                       outMat.m_bottomLeftMat += m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
+               }
+               else if (outOp == Subtract)
+               {
+                       outMat.m_topLeftMat -= m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
+                       outMat.m_topRightMat -= m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
+                       outMat.m_bottomLeftMat -= m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
+               }
+       }
+
+       template <typename SpatialVectorType>
+       SpatialVectorType operator*(const SpatialVectorType &vec)
+       {
+               SpatialVectorType out;
+               transform(vec, out);
+               return out;
+       }
+};
+
+template <typename SpatialVectorType>
+void symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b, btSymmetricSpatialDyad &out)
+{
+       //output op maybe?
+
+       out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
+       out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
+       out.m_topLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
+       //maybe simple a*spatTranspose(a) would be nicer?
+}
+
+template <typename SpatialVectorType>
+btSymmetricSpatialDyad symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b)
+{
+       btSymmetricSpatialDyad out;
+
+       out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
+       out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
+       out.m_bottomLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
+
+       return out;
+       //maybe simple a*spatTranspose(a) would be nicer?
+}
+
+#endif  //BT_SPATIAL_ALGEBRA_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btStackAlloc.h b/dali-physics/third-party/bullet3/src/LinearMath/btStackAlloc.h
new file mode 100644 (file)
index 0000000..761d6a4
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson
+Nov.2006
+*/
+
+#ifndef BT_STACK_ALLOC
+#define BT_STACK_ALLOC
+
+#include "btScalar.h"  //for btAssert
+#include "btAlignedAllocator.h"
+
+///The btBlock class is an internal structure for the btStackAlloc memory allocator.
+struct btBlock
+{
+       btBlock* previous;
+       unsigned char* address;
+};
+
+///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
+class btStackAlloc
+{
+public:
+       btStackAlloc(unsigned int size)
+       {
+               ctor();
+               create(size);
+       }
+       ~btStackAlloc() { destroy(); }
+
+       inline void create(unsigned int size)
+       {
+               destroy();
+               data = (unsigned char*)btAlignedAlloc(size, 16);
+               totalsize = size;
+       }
+       inline void destroy()
+       {
+               btAssert(usedsize == 0);
+               //Raise(L"StackAlloc is still in use");
+
+               if (usedsize == 0)
+               {
+                       if (!ischild && data)
+                               btAlignedFree(data);
+
+                       data = 0;
+                       usedsize = 0;
+               }
+       }
+
+       int getAvailableMemory() const
+       {
+               return static_cast<int>(totalsize - usedsize);
+       }
+
+       unsigned char* allocate(unsigned int size)
+       {
+               const unsigned int nus(usedsize + size);
+               if (nus < totalsize)
+               {
+                       usedsize = nus;
+                       return (data + (usedsize - size));
+               }
+               btAssert(0);
+               //&& (L"Not enough memory"));
+
+               return (0);
+       }
+       SIMD_FORCE_INLINE btBlock* beginBlock()
+       {
+               btBlock* pb = (btBlock*)allocate(sizeof(btBlock));
+               pb->previous = current;
+               pb->address = data + usedsize;
+               current = pb;
+               return (pb);
+       }
+       SIMD_FORCE_INLINE void endBlock(btBlock* block)
+       {
+               btAssert(block == current);
+               //Raise(L"Unmatched blocks");
+               if (block == current)
+               {
+                       current = block->previous;
+                       usedsize = (unsigned int)((block->address - data) - sizeof(btBlock));
+               }
+       }
+
+private:
+       void ctor()
+       {
+               data = 0;
+               totalsize = 0;
+               usedsize = 0;
+               current = 0;
+               ischild = false;
+       }
+       unsigned char* data;
+       unsigned int totalsize;
+       unsigned int usedsize;
+       btBlock* current;
+       bool ischild;
+};
+
+#endif  //BT_STACK_ALLOC
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btThreads.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btThreads.cpp
new file mode 100644 (file)
index 0000000..69a8679
--- /dev/null
@@ -0,0 +1,792 @@
+/*
+Copyright (c) 2003-2014 Erwin Coumans  http://bullet.googlecode.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 "btThreads.h"
+#include "btQuickprof.h"
+#include <algorithm>  // for min and max
+
+#if BT_USE_OPENMP && BT_THREADSAFE
+
+#include <omp.h>
+
+#endif  // #if BT_USE_OPENMP && BT_THREADSAFE
+
+#if BT_USE_PPL && BT_THREADSAFE
+
+// use Microsoft Parallel Patterns Library (installed with Visual Studio 2010 and later)
+#include <ppl.h>  // if you get a compile error here, check whether your version of Visual Studio includes PPL
+// Visual Studio 2010 and later should come with it
+#include <concrtrm.h>  // for GetProcessorCount()
+
+#endif  // #if BT_USE_PPL && BT_THREADSAFE
+
+#if BT_USE_TBB && BT_THREADSAFE
+
+// use Intel Threading Building Blocks for thread management
+#define __TBB_NO_IMPLICIT_LINKAGE 1
+#include <tbb/tbb.h>
+#include <tbb/task_scheduler_init.h>
+#include <tbb/parallel_for.h>
+#include <tbb/blocked_range.h>
+
+#endif  // #if BT_USE_TBB && BT_THREADSAFE
+
+#if BT_THREADSAFE
+//
+// Lightweight spin-mutex based on atomics
+// Using ordinary system-provided mutexes like Windows critical sections was noticeably slower
+// presumably because when it fails to lock at first it would sleep the thread and trigger costly
+// context switching.
+//
+
+#if __cplusplus >= 201103L
+
+// for anything claiming full C++11 compliance, use C++11 atomics
+// on GCC or Clang you need to compile with -std=c++11
+#define USE_CPP11_ATOMICS 1
+
+#elif defined(_MSC_VER)
+
+// on MSVC, use intrinsics instead
+#define USE_MSVC_INTRINSICS 1
+
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
+
+// available since GCC 4.7 and some versions of clang
+// todo: check for clang
+#define USE_GCC_BUILTIN_ATOMICS 1
+
+#elif defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
+
+// available since GCC 4.1
+#define USE_GCC_BUILTIN_ATOMICS_OLD 1
+
+#endif
+
+#if USE_CPP11_ATOMICS
+
+#include <atomic>
+#include <thread>
+
+#define THREAD_LOCAL_STATIC thread_local static
+
+bool btSpinMutex::tryLock()
+{
+       std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
+       int expected = 0;
+       return std::atomic_compare_exchange_weak_explicit(aDest, &expected, int(1), std::memory_order_acq_rel, std::memory_order_acquire);
+}
+
+void btSpinMutex::lock()
+{
+       // note: this lock does not sleep the thread.
+       while (!tryLock())
+       {
+               // spin
+       }
+}
+
+void btSpinMutex::unlock()
+{
+       std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
+       std::atomic_store_explicit(aDest, int(0), std::memory_order_release);
+}
+
+#elif USE_MSVC_INTRINSICS
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <intrin.h>
+
+#define THREAD_LOCAL_STATIC __declspec(thread) static
+
+bool btSpinMutex::tryLock()
+{
+       volatile long* aDest = reinterpret_cast<long*>(&mLock);
+       return (0 == _InterlockedCompareExchange(aDest, 1, 0));
+}
+
+void btSpinMutex::lock()
+{
+       // note: this lock does not sleep the thread
+       while (!tryLock())
+       {
+               // spin
+       }
+}
+
+void btSpinMutex::unlock()
+{
+       volatile long* aDest = reinterpret_cast<long*>(&mLock);
+       _InterlockedExchange(aDest, 0);
+}
+
+#elif USE_GCC_BUILTIN_ATOMICS
+
+#define THREAD_LOCAL_STATIC static __thread
+
+bool btSpinMutex::tryLock()
+{
+       int expected = 0;
+       bool weak = false;
+       const int memOrderSuccess = __ATOMIC_ACQ_REL;
+       const int memOrderFail = __ATOMIC_ACQUIRE;
+       return __atomic_compare_exchange_n(&mLock, &expected, int(1), weak, memOrderSuccess, memOrderFail);
+}
+
+void btSpinMutex::lock()
+{
+       // note: this lock does not sleep the thread
+       while (!tryLock())
+       {
+               // spin
+       }
+}
+
+void btSpinMutex::unlock()
+{
+       __atomic_store_n(&mLock, int(0), __ATOMIC_RELEASE);
+}
+
+#elif USE_GCC_BUILTIN_ATOMICS_OLD
+
+#define THREAD_LOCAL_STATIC static __thread
+
+bool btSpinMutex::tryLock()
+{
+       return __sync_bool_compare_and_swap(&mLock, int(0), int(1));
+}
+
+void btSpinMutex::lock()
+{
+       // note: this lock does not sleep the thread
+       while (!tryLock())
+       {
+               // spin
+       }
+}
+
+void btSpinMutex::unlock()
+{
+       // write 0
+       __sync_fetch_and_and(&mLock, int(0));
+}
+
+#else  //#elif USE_MSVC_INTRINSICS
+
+#error "no threading primitives defined -- unknown platform"
+
+#endif  //#else //#elif USE_MSVC_INTRINSICS
+
+#else  //#if BT_THREADSAFE
+
+// These should not be called ever
+void btSpinMutex::lock()
+{
+       btAssert(!"unimplemented btSpinMutex::lock() called");
+}
+
+void btSpinMutex::unlock()
+{
+       btAssert(!"unimplemented btSpinMutex::unlock() called");
+}
+
+bool btSpinMutex::tryLock()
+{
+       btAssert(!"unimplemented btSpinMutex::tryLock() called");
+       return true;
+}
+
+#define THREAD_LOCAL_STATIC static
+
+#endif  // #else //#if BT_THREADSAFE
+
+struct ThreadsafeCounter
+{
+       unsigned int mCounter;
+       btSpinMutex mMutex;
+
+       ThreadsafeCounter()
+       {
+               mCounter = 0;
+               --mCounter;  // first count should come back 0
+       }
+
+       unsigned int getNext()
+       {
+               // no need to optimize this with atomics, it is only called ONCE per thread!
+               mMutex.lock();
+               mCounter++;
+               if (mCounter >= BT_MAX_THREAD_COUNT)
+               {
+                       btAssert(!"thread counter exceeded");
+                       // wrap back to the first worker index
+                       mCounter = 1;
+               }
+               unsigned int val = mCounter;
+               mMutex.unlock();
+               return val;
+       }
+};
+
+static btITaskScheduler* gBtTaskScheduler=0;
+static int gThreadsRunningCounter = 0;  // useful for detecting if we are trying to do nested parallel-for calls
+static btSpinMutex gThreadsRunningCounterMutex;
+static ThreadsafeCounter gThreadCounter;
+
+//
+// BT_DETECT_BAD_THREAD_INDEX tries to detect when there are multiple threads assigned the same thread index.
+//
+// BT_DETECT_BAD_THREAD_INDEX is a developer option to test if
+// certain assumptions about how the task scheduler manages its threads
+// holds true.
+// The main assumption is:
+//   - when the threadpool is resized, the task scheduler either
+//      1. destroys all worker threads and creates all new ones in the correct number, OR
+//      2. never destroys a worker thread
+//
+// We make that assumption because we can't easily enumerate the worker threads of a task scheduler
+// to assign nice sequential thread-indexes. We also do not get notified if a worker thread is destroyed,
+// so we can't tell when a thread-index is no longer being used.
+// We allocate thread-indexes as needed with a sequential global thread counter.
+//
+// Our simple thread-counting scheme falls apart if the task scheduler destroys some threads but
+// continues to re-use other threads and the application repeatedly resizes the thread pool of the
+// task scheduler.
+// In order to prevent the thread-counter from exceeding the global max (BT_MAX_THREAD_COUNT), we
+// wrap the thread counter back to 1. This should only happen if the worker threads have all been
+// destroyed and re-created.
+//
+// BT_DETECT_BAD_THREAD_INDEX only works for Win32 right now,
+// but could be adapted to work with pthreads
+#define BT_DETECT_BAD_THREAD_INDEX 0
+
+#if BT_DETECT_BAD_THREAD_INDEX
+
+typedef DWORD ThreadId_t;
+const static ThreadId_t kInvalidThreadId = 0;
+ThreadId_t gDebugThreadIds[BT_MAX_THREAD_COUNT];
+
+static ThreadId_t getDebugThreadId()
+{
+       return GetCurrentThreadId();
+}
+
+#endif  // #if BT_DETECT_BAD_THREAD_INDEX
+
+// return a unique index per thread, main thread is 0, worker threads are in [1, BT_MAX_THREAD_COUNT)
+unsigned int btGetCurrentThreadIndex()
+{
+       const unsigned int kNullIndex = ~0U;
+       THREAD_LOCAL_STATIC unsigned int sThreadIndex = kNullIndex;
+       if (sThreadIndex == kNullIndex)
+       {
+               sThreadIndex = gThreadCounter.getNext();
+               btAssert(sThreadIndex < BT_MAX_THREAD_COUNT);
+       }
+#if BT_DETECT_BAD_THREAD_INDEX
+       if (gBtTaskScheduler && sThreadIndex > 0)
+       {
+               ThreadId_t tid = getDebugThreadId();
+               // if not set
+               if (gDebugThreadIds[sThreadIndex] == kInvalidThreadId)
+               {
+                       // set it
+                       gDebugThreadIds[sThreadIndex] = tid;
+               }
+               else
+               {
+                       if (gDebugThreadIds[sThreadIndex] != tid)
+                       {
+                               // this could indicate the task scheduler is breaking our assumptions about
+                               // how threads are managed when threadpool is resized
+                               btAssert(!"there are 2 or more threads with the same thread-index!");
+                               __debugbreak();
+                       }
+               }
+       }
+#endif  // #if BT_DETECT_BAD_THREAD_INDEX
+       return sThreadIndex;
+}
+
+bool btIsMainThread()
+{
+       return btGetCurrentThreadIndex() == 0;
+}
+
+void btResetThreadIndexCounter()
+{
+       // for when all current worker threads are destroyed
+       btAssert(btIsMainThread());
+       gThreadCounter.mCounter = 0;
+}
+
+btITaskScheduler::btITaskScheduler(const char* name)
+{
+       m_name = name;
+       m_savedThreadCounter = 0;
+       m_isActive = false;
+}
+
+void btITaskScheduler::activate()
+{
+       // gThreadCounter is used to assign a thread-index to each worker thread in a task scheduler.
+       // The main thread is always thread-index 0, and worker threads are numbered from 1 to 63 (BT_MAX_THREAD_COUNT-1)
+       // The thread-indexes need to be unique amongst the threads that can be running simultaneously.
+       // Since only one task scheduler can be used at a time, it is OK for a pair of threads that belong to different
+       // task schedulers to share the same thread index because they can't be running at the same time.
+       // So each task scheduler needs to keep its own thread counter value
+       if (!m_isActive)
+       {
+               gThreadCounter.mCounter = m_savedThreadCounter;  // restore saved thread counter
+               m_isActive = true;
+       }
+}
+
+void btITaskScheduler::deactivate()
+{
+       if (m_isActive)
+       {
+               m_savedThreadCounter = gThreadCounter.mCounter;  // save thread counter
+               m_isActive = false;
+       }
+}
+
+void btPushThreadsAreRunning()
+{
+       gThreadsRunningCounterMutex.lock();
+       gThreadsRunningCounter++;
+       gThreadsRunningCounterMutex.unlock();
+}
+
+void btPopThreadsAreRunning()
+{
+       gThreadsRunningCounterMutex.lock();
+       gThreadsRunningCounter--;
+       gThreadsRunningCounterMutex.unlock();
+}
+
+bool btThreadsAreRunning()
+{
+       return gThreadsRunningCounter != 0;
+}
+
+void btSetTaskScheduler(btITaskScheduler* ts)
+{
+       int threadId = btGetCurrentThreadIndex();  // make sure we call this on main thread at least once before any workers run
+       if (threadId != 0)
+       {
+               btAssert(!"btSetTaskScheduler must be called from the main thread!");
+               return;
+       }
+       if (gBtTaskScheduler)
+       {
+               // deactivate old task scheduler
+               gBtTaskScheduler->deactivate();
+       }
+       gBtTaskScheduler = ts;
+       if (ts)
+       {
+               // activate new task scheduler
+               ts->activate();
+       }
+}
+
+btITaskScheduler* btGetTaskScheduler()
+{
+       return gBtTaskScheduler;
+}
+
+void btParallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body)
+{
+#if BT_THREADSAFE
+
+#if BT_DETECT_BAD_THREAD_INDEX
+       if (!btThreadsAreRunning())
+       {
+               // clear out thread ids
+               for (int i = 0; i < BT_MAX_THREAD_COUNT; ++i)
+               {
+                       gDebugThreadIds[i] = kInvalidThreadId;
+               }
+       }
+#endif  // #if BT_DETECT_BAD_THREAD_INDEX
+
+       btAssert(gBtTaskScheduler != NULL);  // call btSetTaskScheduler() with a valid task scheduler first!
+       gBtTaskScheduler->parallelFor(iBegin, iEnd, grainSize, body);
+
+#else  // #if BT_THREADSAFE
+
+       // non-parallel version of btParallelFor
+       btAssert(!"called btParallelFor in non-threadsafe build. enable BT_THREADSAFE");
+       body.forLoop(iBegin, iEnd);
+
+#endif  // #if BT_THREADSAFE
+}
+
+btScalar btParallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body)
+{
+#if BT_THREADSAFE
+
+#if BT_DETECT_BAD_THREAD_INDEX
+       if (!btThreadsAreRunning())
+       {
+               // clear out thread ids
+               for (int i = 0; i < BT_MAX_THREAD_COUNT; ++i)
+               {
+                       gDebugThreadIds[i] = kInvalidThreadId;
+               }
+       }
+#endif  // #if BT_DETECT_BAD_THREAD_INDEX
+
+       btAssert(gBtTaskScheduler != NULL);  // call btSetTaskScheduler() with a valid task scheduler first!
+       return gBtTaskScheduler->parallelSum(iBegin, iEnd, grainSize, body);
+
+#else  // #if BT_THREADSAFE
+
+       // non-parallel version of btParallelSum
+       btAssert(!"called btParallelFor in non-threadsafe build. enable BT_THREADSAFE");
+       return body.sumLoop(iBegin, iEnd);
+
+#endif  //#else // #if BT_THREADSAFE
+}
+
+///
+/// btTaskSchedulerSequential -- non-threaded implementation of task scheduler
+///                              (really just useful for testing performance of single threaded vs multi)
+///
+class btTaskSchedulerSequential : public btITaskScheduler
+{
+public:
+       btTaskSchedulerSequential() : btITaskScheduler("Sequential") {}
+       virtual int getMaxNumThreads() const BT_OVERRIDE { return 1; }
+       virtual int getNumThreads() const BT_OVERRIDE { return 1; }
+       virtual void setNumThreads(int numThreads) BT_OVERRIDE {}
+       virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
+       {
+               BT_PROFILE("parallelFor_sequential");
+               body.forLoop(iBegin, iEnd);
+       }
+       virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
+       {
+               BT_PROFILE("parallelSum_sequential");
+               return body.sumLoop(iBegin, iEnd);
+       }
+};
+
+#if BT_USE_OPENMP && BT_THREADSAFE
+///
+/// btTaskSchedulerOpenMP -- wrapper around OpenMP task scheduler
+///
+class btTaskSchedulerOpenMP : public btITaskScheduler
+{
+       int m_numThreads;
+
+public:
+       btTaskSchedulerOpenMP() : btITaskScheduler("OpenMP")
+       {
+               m_numThreads = 0;
+       }
+       virtual int getMaxNumThreads() const BT_OVERRIDE
+       {
+               return omp_get_max_threads();
+       }
+       virtual int getNumThreads() const BT_OVERRIDE
+       {
+               return m_numThreads;
+       }
+       virtual void setNumThreads(int numThreads) BT_OVERRIDE
+       {
+               // With OpenMP, because it is a standard with various implementations, we can't
+               // know for sure if every implementation has the same behavior of destroying all
+               // previous threads when resizing the threadpool
+               m_numThreads = (std::max)(1, (std::min)(int(BT_MAX_THREAD_COUNT), numThreads));
+               omp_set_num_threads(1);  // hopefully, all previous threads get destroyed here
+               omp_set_num_threads(m_numThreads);
+               m_savedThreadCounter = 0;
+               if (m_isActive)
+               {
+                       btResetThreadIndexCounter();
+               }
+       }
+       virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
+       {
+               BT_PROFILE("parallelFor_OpenMP");
+               btPushThreadsAreRunning();
+#pragma omp parallel for schedule(static, 1)
+               for (int i = iBegin; i < iEnd; i += grainSize)
+               {
+                       BT_PROFILE("OpenMP_forJob");
+                       body.forLoop(i, (std::min)(i + grainSize, iEnd));
+               }
+               btPopThreadsAreRunning();
+       }
+       virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
+       {
+               BT_PROFILE("parallelFor_OpenMP");
+               btPushThreadsAreRunning();
+               btScalar sum = btScalar(0);
+#pragma omp parallel for schedule(static, 1) reduction(+ \
+                                                                                                          : sum)
+               for (int i = iBegin; i < iEnd; i += grainSize)
+               {
+                       BT_PROFILE("OpenMP_sumJob");
+                       sum += body.sumLoop(i, (std::min)(i + grainSize, iEnd));
+               }
+               btPopThreadsAreRunning();
+               return sum;
+       }
+};
+#endif  // #if BT_USE_OPENMP && BT_THREADSAFE
+
+#if BT_USE_TBB && BT_THREADSAFE
+///
+/// btTaskSchedulerTBB -- wrapper around Intel Threaded Building Blocks task scheduler
+///
+class btTaskSchedulerTBB : public btITaskScheduler
+{
+       int m_numThreads;
+       tbb::task_scheduler_init* m_tbbSchedulerInit;
+
+public:
+       btTaskSchedulerTBB() : btITaskScheduler("IntelTBB")
+       {
+               m_numThreads = 0;
+               m_tbbSchedulerInit = NULL;
+       }
+       ~btTaskSchedulerTBB()
+       {
+               if (m_tbbSchedulerInit)
+               {
+                       delete m_tbbSchedulerInit;
+                       m_tbbSchedulerInit = NULL;
+               }
+       }
+
+       virtual int getMaxNumThreads() const BT_OVERRIDE
+       {
+               return tbb::task_scheduler_init::default_num_threads();
+       }
+       virtual int getNumThreads() const BT_OVERRIDE
+       {
+               return m_numThreads;
+       }
+       virtual void setNumThreads(int numThreads) BT_OVERRIDE
+       {
+               m_numThreads = (std::max)(1, (std::min)(int(BT_MAX_THREAD_COUNT), numThreads));
+               if (m_tbbSchedulerInit)
+               {
+                       // destroys all previous threads
+                       delete m_tbbSchedulerInit;
+                       m_tbbSchedulerInit = NULL;
+               }
+               m_tbbSchedulerInit = new tbb::task_scheduler_init(m_numThreads);
+               m_savedThreadCounter = 0;
+               if (m_isActive)
+               {
+                       btResetThreadIndexCounter();
+               }
+       }
+       struct ForBodyAdapter
+       {
+               const btIParallelForBody* mBody;
+
+               ForBodyAdapter(const btIParallelForBody* body) : mBody(body) {}
+               void operator()(const tbb::blocked_range<int>& range) const
+               {
+                       BT_PROFILE("TBB_forJob");
+                       mBody->forLoop(range.begin(), range.end());
+               }
+       };
+       virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
+       {
+               BT_PROFILE("parallelFor_TBB");
+               ForBodyAdapter tbbBody(&body);
+               btPushThreadsAreRunning();
+               tbb::parallel_for(tbb::blocked_range<int>(iBegin, iEnd, grainSize),
+                                                 tbbBody,
+                                                 tbb::simple_partitioner());
+               btPopThreadsAreRunning();
+       }
+       struct SumBodyAdapter
+       {
+               const btIParallelSumBody* mBody;
+               btScalar mSum;
+
+               SumBodyAdapter(const btIParallelSumBody* body) : mBody(body), mSum(btScalar(0)) {}
+               SumBodyAdapter(const SumBodyAdapter& src, tbb::split) : mBody(src.mBody), mSum(btScalar(0)) {}
+               void join(const SumBodyAdapter& src) { mSum += src.mSum; }
+               void operator()(const tbb::blocked_range<int>& range)
+               {
+                       BT_PROFILE("TBB_sumJob");
+                       mSum += mBody->sumLoop(range.begin(), range.end());
+               }
+       };
+       virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
+       {
+               BT_PROFILE("parallelSum_TBB");
+               SumBodyAdapter tbbBody(&body);
+               btPushThreadsAreRunning();
+               tbb::parallel_deterministic_reduce(tbb::blocked_range<int>(iBegin, iEnd, grainSize), tbbBody);
+               btPopThreadsAreRunning();
+               return tbbBody.mSum;
+       }
+};
+#endif  // #if BT_USE_TBB && BT_THREADSAFE
+
+#if BT_USE_PPL && BT_THREADSAFE
+///
+/// btTaskSchedulerPPL -- wrapper around Microsoft Parallel Patterns Lib task scheduler
+///
+class btTaskSchedulerPPL : public btITaskScheduler
+{
+       int m_numThreads;
+       concurrency::combinable<btScalar> m_sum;  // for parallelSum
+public:
+       btTaskSchedulerPPL() : btITaskScheduler("PPL")
+       {
+               m_numThreads = 0;
+       }
+       virtual int getMaxNumThreads() const BT_OVERRIDE
+       {
+               return concurrency::GetProcessorCount();
+       }
+       virtual int getNumThreads() const BT_OVERRIDE
+       {
+               return m_numThreads;
+       }
+       virtual void setNumThreads(int numThreads) BT_OVERRIDE
+       {
+               // capping the thread count for PPL due to a thread-index issue
+               const int maxThreadCount = (std::min)(int(BT_MAX_THREAD_COUNT), 31);
+               m_numThreads = (std::max)(1, (std::min)(maxThreadCount, numThreads));
+               using namespace concurrency;
+               if (CurrentScheduler::Id() != -1)
+               {
+                       CurrentScheduler::Detach();
+               }
+               SchedulerPolicy policy;
+               {
+                       // PPL seems to destroy threads when threadpool is shrunk, but keeps reusing old threads
+                       // force it to destroy old threads
+                       policy.SetConcurrencyLimits(1, 1);
+                       CurrentScheduler::Create(policy);
+                       CurrentScheduler::Detach();
+               }
+               policy.SetConcurrencyLimits(m_numThreads, m_numThreads);
+               CurrentScheduler::Create(policy);
+               m_savedThreadCounter = 0;
+               if (m_isActive)
+               {
+                       btResetThreadIndexCounter();
+               }
+       }
+       struct ForBodyAdapter
+       {
+               const btIParallelForBody* mBody;
+               int mGrainSize;
+               int mIndexEnd;
+
+               ForBodyAdapter(const btIParallelForBody* body, int grainSize, int end) : mBody(body), mGrainSize(grainSize), mIndexEnd(end) {}
+               void operator()(int i) const
+               {
+                       BT_PROFILE("PPL_forJob");
+                       mBody->forLoop(i, (std::min)(i + mGrainSize, mIndexEnd));
+               }
+       };
+       virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
+       {
+               BT_PROFILE("parallelFor_PPL");
+               // PPL dispatch
+               ForBodyAdapter pplBody(&body, grainSize, iEnd);
+               btPushThreadsAreRunning();
+               // note: MSVC 2010 doesn't support partitioner args, so avoid them
+               concurrency::parallel_for(iBegin,
+                                                                 iEnd,
+                                                                 grainSize,
+                                                                 pplBody);
+               btPopThreadsAreRunning();
+       }
+       struct SumBodyAdapter
+       {
+               const btIParallelSumBody* mBody;
+               concurrency::combinable<btScalar>* mSum;
+               int mGrainSize;
+               int mIndexEnd;
+
+               SumBodyAdapter(const btIParallelSumBody* body, concurrency::combinable<btScalar>* sum, int grainSize, int end) : mBody(body), mSum(sum), mGrainSize(grainSize), mIndexEnd(end) {}
+               void operator()(int i) const
+               {
+                       BT_PROFILE("PPL_sumJob");
+                       mSum->local() += mBody->sumLoop(i, (std::min)(i + mGrainSize, mIndexEnd));
+               }
+       };
+       static btScalar sumFunc(btScalar a, btScalar b) { return a + b; }
+       virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
+       {
+               BT_PROFILE("parallelSum_PPL");
+               m_sum.clear();
+               SumBodyAdapter pplBody(&body, &m_sum, grainSize, iEnd);
+               btPushThreadsAreRunning();
+               // note: MSVC 2010 doesn't support partitioner args, so avoid them
+               concurrency::parallel_for(iBegin,
+                                                                 iEnd,
+                                                                 grainSize,
+                                                                 pplBody);
+               btPopThreadsAreRunning();
+               return m_sum.combine(sumFunc);
+       }
+};
+#endif  // #if BT_USE_PPL && BT_THREADSAFE
+
+// create a non-threaded task scheduler (always available)
+btITaskScheduler* btGetSequentialTaskScheduler()
+{
+       static btTaskSchedulerSequential sTaskScheduler;
+       return &sTaskScheduler;
+}
+
+// create an OpenMP task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetOpenMPTaskScheduler()
+{
+#if BT_USE_OPENMP && BT_THREADSAFE
+       static btTaskSchedulerOpenMP sTaskScheduler;
+       return &sTaskScheduler;
+#else
+       return NULL;
+#endif
+}
+
+// create an Intel TBB task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetTBBTaskScheduler()
+{
+#if BT_USE_TBB && BT_THREADSAFE
+       static btTaskSchedulerTBB sTaskScheduler;
+       return &sTaskScheduler;
+#else
+       return NULL;
+#endif
+}
+
+// create a PPL task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetPPLTaskScheduler()
+{
+#if BT_USE_PPL && BT_THREADSAFE
+       static btTaskSchedulerPPL sTaskScheduler;
+       return &sTaskScheduler;
+#else
+       return NULL;
+#endif
+}
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btThreads.h b/dali-physics/third-party/bullet3/src/LinearMath/btThreads.h
new file mode 100644 (file)
index 0000000..b2227e1
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+Copyright (c) 2003-2014 Erwin Coumans  http://bullet.googlecode.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.
+*/
+
+#ifndef BT_THREADS_H
+#define BT_THREADS_H
+
+#include "btScalar.h"  // has definitions like SIMD_FORCE_INLINE
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600
+// give us a compile error if any signatures of overriden methods is changed
+#define BT_OVERRIDE override
+#endif
+
+#ifndef BT_OVERRIDE
+#define BT_OVERRIDE
+#endif
+
+// Don't set this to larger than 64, without modifying btThreadSupportPosix
+// and btThreadSupportWin32. They use UINT64 bit-masks.
+const unsigned int BT_MAX_THREAD_COUNT = 64;  // only if BT_THREADSAFE is 1
+
+// for internal use only
+bool btIsMainThread();
+bool btThreadsAreRunning();
+unsigned int btGetCurrentThreadIndex();
+void btResetThreadIndexCounter();  // notify that all worker threads have been destroyed
+
+///
+/// btSpinMutex -- lightweight spin-mutex implemented with atomic ops, never puts
+///               a thread to sleep because it is designed to be used with a task scheduler
+///               which has one thread per core and the threads don't sleep until they
+///               run out of tasks. Not good for general purpose use.
+///
+class btSpinMutex
+{
+       int mLock;
+
+public:
+       btSpinMutex()
+       {
+               mLock = 0;
+       }
+       void lock();
+       void unlock();
+       bool tryLock();
+};
+
+//
+// NOTE: btMutex* is for internal Bullet use only
+//
+// If BT_THREADSAFE is undefined or 0, should optimize away to nothing.
+// This is good because for the single-threaded build of Bullet, any calls
+// to these functions will be optimized out.
+//
+// However, for users of the multi-threaded build of Bullet this is kind
+// of bad because if you call any of these functions from external code
+// (where BT_THREADSAFE is undefined) you will get unexpected race conditions.
+//
+SIMD_FORCE_INLINE void btMutexLock(btSpinMutex* mutex)
+{
+#if BT_THREADSAFE
+       mutex->lock();
+#else
+       (void)mutex;
+#endif  // #if BT_THREADSAFE
+}
+
+SIMD_FORCE_INLINE void btMutexUnlock(btSpinMutex* mutex)
+{
+#if BT_THREADSAFE
+       mutex->unlock();
+#else
+       (void)mutex;
+#endif  // #if BT_THREADSAFE
+}
+
+SIMD_FORCE_INLINE bool btMutexTryLock(btSpinMutex* mutex)
+{
+#if BT_THREADSAFE
+       return mutex->tryLock();
+#else
+       (void)mutex;
+       return true;
+#endif  // #if BT_THREADSAFE
+}
+
+//
+// btIParallelForBody -- subclass this to express work that can be done in parallel
+//
+class btIParallelForBody
+{
+public:
+       virtual ~btIParallelForBody() {}
+       virtual void forLoop(int iBegin, int iEnd) const = 0;
+};
+
+//
+// btIParallelSumBody -- subclass this to express work that can be done in parallel
+//                       and produces a sum over all loop elements
+//
+class btIParallelSumBody
+{
+public:
+       virtual ~btIParallelSumBody() {}
+       virtual btScalar sumLoop(int iBegin, int iEnd) const = 0;
+};
+
+//
+// btITaskScheduler -- subclass this to implement a task scheduler that can dispatch work to
+//                     worker threads
+//
+class btITaskScheduler
+{
+public:
+       btITaskScheduler(const char* name);
+       virtual ~btITaskScheduler() {}
+       const char* getName() const { return m_name; }
+
+       virtual int getMaxNumThreads() const = 0;
+       virtual int getNumThreads() const = 0;
+       virtual void setNumThreads(int numThreads) = 0;
+       virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) = 0;
+       virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) = 0;
+       virtual void sleepWorkerThreadsHint() {}  // hint the task scheduler that we may not be using these threads for a little while
+
+       // internal use only
+       virtual void activate();
+       virtual void deactivate();
+
+protected:
+       const char* m_name;
+       unsigned int m_savedThreadCounter;
+       bool m_isActive;
+};
+
+// set the task scheduler to use for all calls to btParallelFor()
+// NOTE: you must set this prior to using any of the multi-threaded "Mt" classes
+void btSetTaskScheduler(btITaskScheduler* ts);
+
+// get the current task scheduler
+btITaskScheduler* btGetTaskScheduler();
+
+// get non-threaded task scheduler (always available)
+btITaskScheduler* btGetSequentialTaskScheduler();
+
+// create a default task scheduler (Win32 or pthreads based)
+btITaskScheduler* btCreateDefaultTaskScheduler();
+
+// get OpenMP task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetOpenMPTaskScheduler();
+
+// get Intel TBB task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetTBBTaskScheduler();
+
+// get PPL task scheduler (if available, otherwise returns null)
+btITaskScheduler* btGetPPLTaskScheduler();
+
+// btParallelFor -- call this to dispatch work like a for-loop
+//                 (iterations may be done out of order, so no dependencies are allowed)
+void btParallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body);
+
+// btParallelSum -- call this to dispatch work like a for-loop, returns the sum of all iterations
+//                 (iterations may be done out of order, so no dependencies are allowed)
+btScalar btParallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body);
+
+#endif
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btTransform.h b/dali-physics/third-party/bullet3/src/LinearMath/btTransform.h
new file mode 100644 (file)
index 0000000..b60c061
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_TRANSFORM_H
+#define BT_TRANSFORM_H
+
+#include "btMatrix3x3.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btTransformData btTransformDoubleData
+#else
+#define btTransformData btTransformFloatData
+#endif
+
+/**@brief 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. */
+ATTRIBUTE_ALIGNED16(class)
+btTransform
+{
+       ///Storage for the rotation
+       btMatrix3x3 m_basis;
+       ///Storage for the translation
+       btVector3 m_origin;
+
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+       /**@brief No initialization constructor */
+       btTransform() {}
+       /**@brief Constructor from btQuaternion (optional btVector3 )
+   * @param q Rotation from quaternion 
+   * @param c Translation from Vector (default 0,0,0) */
+       explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q,
+                                                                                  const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
+               : m_basis(q),
+                 m_origin(c)
+       {
+       }
+
+       /**@brief Constructor from btMatrix3x3 (optional btVector3)
+   * @param b Rotation from Matrix 
+   * @param c Translation from Vector default (0,0,0)*/
+       explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b,
+                                                                                  const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
+               : m_basis(b),
+                 m_origin(c)
+       {
+       }
+       /**@brief Copy constructor */
+       SIMD_FORCE_INLINE btTransform(const btTransform& other)
+               : m_basis(other.m_basis),
+                 m_origin(other.m_origin)
+       {
+       }
+       /**@brief Assignment Operator */
+       SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other)
+       {
+               m_basis = other.m_basis;
+               m_origin = other.m_origin;
+               return *this;
+       }
+
+       /**@brief Set the current transform as the value of the product of two transforms
+   * @param t1 Transform 1
+   * @param t2 Transform 2
+   * This = Transform1 * Transform2 */
+       SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2)
+       {
+               m_basis = t1.m_basis * t2.m_basis;
+               m_origin = t1(t2.m_origin);
+       }
+
+       /*              void multInverseLeft(const btTransform& t1, const btTransform& t2) {
+                       btVector3 v = t2.m_origin - t1.m_origin;
+                       m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis);
+                       m_origin = v * t1.m_basis;
+               }
+               */
+
+       /**@brief Return the transform of the vector */
+       SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const
+       {
+               return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
+       }
+
+       /**@brief Return the transform of the vector */
+       SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const
+       {
+               return (*this)(x);
+       }
+
+       /**@brief Return the transform of the btQuaternion */
+       SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const
+       {
+               return getRotation() * q;
+       }
+
+       /**@brief Return the basis matrix for the rotation */
+       SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; }
+       /**@brief Return the basis matrix for the rotation */
+       SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; }
+
+       /**@brief Return the origin vector translation */
+       SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; }
+       /**@brief Return the origin vector translation */
+       SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; }
+
+       /**@brief Return a quaternion representing the rotation */
+       btQuaternion getRotation() const
+       {
+               btQuaternion q;
+               m_basis.getRotation(q);
+               return q;
+       }
+
+       /**@brief Set from an array 
+   * @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+       void setFromOpenGLMatrix(const btScalar* m)
+       {
+               m_basis.setFromOpenGLSubMatrix(m);
+               m_origin.setValue(m[12], m[13], m[14]);
+       }
+
+       /**@brief Fill an array representation
+   * @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+       void getOpenGLMatrix(btScalar * m) const
+       {
+               m_basis.getOpenGLSubMatrix(m);
+               m[12] = m_origin.x();
+               m[13] = m_origin.y();
+               m[14] = m_origin.z();
+               m[15] = btScalar(1.0);
+       }
+
+       /**@brief Set the translational element
+   * @param origin The vector to set the translation to */
+       SIMD_FORCE_INLINE void setOrigin(const btVector3& origin)
+       {
+               m_origin = origin;
+       }
+
+       SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const;
+
+       /**@brief Set the rotational element by btMatrix3x3 */
+       SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis)
+       {
+               m_basis = basis;
+       }
+
+       /**@brief Set the rotational element by btQuaternion */
+       SIMD_FORCE_INLINE void setRotation(const btQuaternion& q)
+       {
+               m_basis.setRotation(q);
+       }
+
+       /**@brief Set this transformation to the identity */
+       void setIdentity()
+       {
+               m_basis.setIdentity();
+               m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+       }
+
+       /**@brief Multiply this Transform by another(this = this * another) 
+   * @param t The other transform */
+       btTransform& operator*=(const btTransform& t)
+       {
+               m_origin += m_basis * t.m_origin;
+               m_basis *= t.m_basis;
+               return *this;
+       }
+
+       /**@brief Return the inverse of this transform */
+       btTransform inverse() const
+       {
+               btMatrix3x3 inv = m_basis.transpose();
+               return btTransform(inv, inv * -m_origin);
+       }
+
+       /**@brief Return the inverse of this transform times the other transform
+   * @param t The other transform 
+   * return this.inverse() * the other */
+       btTransform inverseTimes(const btTransform& t) const;
+
+       /**@brief Return the product of this transform and the other */
+       btTransform operator*(const btTransform& t) const;
+
+       /**@brief Return an identity transform */
+       static const btTransform& getIdentity()
+       {
+               static const btTransform identityTransform(btMatrix3x3::getIdentity());
+               return identityTransform;
+       }
+
+       void serialize(struct btTransformData & dataOut) const;
+
+       void serializeFloat(struct btTransformFloatData & dataOut) const;
+
+       void deSerialize(const struct btTransformData& dataIn);
+
+       void deSerializeDouble(const struct btTransformDoubleData& dataIn);
+
+       void deSerializeFloat(const struct btTransformFloatData& dataIn);
+};
+
+SIMD_FORCE_INLINE btVector3
+btTransform::invXform(const btVector3& inVec) const
+{
+       btVector3 v = inVec - m_origin;
+       return (m_basis.transpose() * v);
+}
+
+SIMD_FORCE_INLINE btTransform
+btTransform::inverseTimes(const btTransform& t) const
+{
+       btVector3 v = t.getOrigin() - m_origin;
+       return btTransform(m_basis.transposeTimes(t.m_basis),
+                                          v * m_basis);
+}
+
+SIMD_FORCE_INLINE btTransform
+       btTransform::operator*(const btTransform& t) const
+{
+       return btTransform(m_basis * t.m_basis,
+                                          (*this)(t.m_origin));
+}
+
+/**@brief Test if two transforms have all elements equal */
+SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2)
+{
+       return (t1.getBasis() == t2.getBasis() &&
+                       t1.getOrigin() == t2.getOrigin());
+}
+
+///for serialization
+struct btTransformFloatData
+{
+       btMatrix3x3FloatData m_basis;
+       btVector3FloatData m_origin;
+};
+
+struct btTransformDoubleData
+{
+       btMatrix3x3DoubleData m_basis;
+       btVector3DoubleData m_origin;
+};
+
+SIMD_FORCE_INLINE void btTransform::serialize(btTransformData& dataOut) const
+{
+       m_basis.serialize(dataOut.m_basis);
+       m_origin.serialize(dataOut.m_origin);
+}
+
+SIMD_FORCE_INLINE void btTransform::serializeFloat(btTransformFloatData& dataOut) const
+{
+       m_basis.serializeFloat(dataOut.m_basis);
+       m_origin.serializeFloat(dataOut.m_origin);
+}
+
+SIMD_FORCE_INLINE void btTransform::deSerialize(const btTransformData& dataIn)
+{
+       m_basis.deSerialize(dataIn.m_basis);
+       m_origin.deSerialize(dataIn.m_origin);
+}
+
+SIMD_FORCE_INLINE void btTransform::deSerializeFloat(const btTransformFloatData& dataIn)
+{
+       m_basis.deSerializeFloat(dataIn.m_basis);
+       m_origin.deSerializeFloat(dataIn.m_origin);
+}
+
+SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleData& dataIn)
+{
+       m_basis.deSerializeDouble(dataIn.m_basis);
+       m_origin.deSerializeDouble(dataIn.m_origin);
+}
+
+#endif  //BT_TRANSFORM_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btTransformUtil.h b/dali-physics/third-party/bullet3/src/LinearMath/btTransformUtil.h
new file mode 100644 (file)
index 0000000..a5aab20
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_TRANSFORM_UTIL_H
+#define BT_TRANSFORM_UTIL_H
+
+#include "btTransform.h"
+#define ANGULAR_MOTION_THRESHOLD btScalar(0.5) * SIMD_HALF_PI
+
+SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents, const btVector3& supportDir)
+{
+       return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
+                                        supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
+                                        supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
+}
+
+/// Utils related to temporal transforms
+class btTransformUtil
+{
+public:
+       static void integrateTransform(const btTransform& curTrans, const btVector3& linvel, const btVector3& angvel, btScalar timeStep, btTransform& predictedTransform)
+       {
+               predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
+               //      #define QUATERNION_DERIVATIVE
+#ifdef QUATERNION_DERIVATIVE
+               btQuaternion predictedOrn = curTrans.getRotation();
+               predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
+               predictedOrn.safeNormalize();
+#else
+               //Exponential map
+               //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
+
+               btVector3 axis;
+               btScalar fAngle2 = angvel.length2();
+               btScalar fAngle = 0;
+               if (fAngle2 > SIMD_EPSILON)
+               {
+                       fAngle = btSqrt(fAngle2);
+               }
+
+               //limit the angular motion
+               if (fAngle * timeStep > ANGULAR_MOTION_THRESHOLD)
+               {
+                       fAngle = ANGULAR_MOTION_THRESHOLD / timeStep;
+               }
+
+               if (fAngle < btScalar(0.001))
+               {
+                       // use Taylor's expansions of sync function
+                       axis = angvel * (btScalar(0.5) * timeStep - (timeStep * timeStep * timeStep) * (btScalar(0.020833333333)) * fAngle * fAngle);
+               }
+               else
+               {
+                       // sync(fAngle) = sin(c*fAngle)/t
+                       axis = angvel * (btSin(btScalar(0.5) * fAngle * timeStep) / fAngle);
+               }
+               btQuaternion dorn(axis.x(), axis.y(), axis.z(), btCos(fAngle * timeStep * btScalar(0.5)));
+               btQuaternion orn0 = curTrans.getRotation();
+
+               btQuaternion predictedOrn = dorn * orn0;
+               predictedOrn.safeNormalize();
+#endif
+               if (predictedOrn.length2() > SIMD_EPSILON)
+               {
+                       predictedTransform.setRotation(predictedOrn);
+               }
+               else
+               {
+                       predictedTransform.setBasis(curTrans.getBasis());
+               }
+       }
+
+       static void calculateVelocityQuaternion(const btVector3& pos0, const btVector3& pos1, const btQuaternion& orn0, const btQuaternion& orn1, btScalar timeStep, btVector3& linVel, btVector3& angVel)
+       {
+               linVel = (pos1 - pos0) / timeStep;
+               btVector3 axis;
+               btScalar angle;
+               if (orn0 != orn1)
+               {
+                       calculateDiffAxisAngleQuaternion(orn0, orn1, axis, angle);
+                       angVel = axis * angle / timeStep;
+               }
+               else
+               {
+                       angVel.setValue(0, 0, 0);
+               }
+       }
+
+       static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0, const btQuaternion& orn1a, btVector3& axis, btScalar& angle)
+       {
+               btQuaternion orn1 = orn0.nearest(orn1a);
+               btQuaternion dorn = orn1 * orn0.inverse();
+               angle = dorn.getAngle();
+               axis = btVector3(dorn.x(), dorn.y(), dorn.z());
+               axis[3] = btScalar(0.);
+               //check for axis length
+               btScalar len = axis.length2();
+               if (len < SIMD_EPSILON * SIMD_EPSILON)
+                       axis = btVector3(btScalar(1.), btScalar(0.), btScalar(0.));
+               else
+                       axis /= btSqrt(len);
+       }
+
+       static void calculateVelocity(const btTransform& transform0, const btTransform& transform1, btScalar timeStep, btVector3& linVel, btVector3& angVel)
+       {
+               linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
+               btVector3 axis;
+               btScalar angle;
+               calculateDiffAxisAngle(transform0, transform1, axis, angle);
+               angVel = axis * angle / timeStep;
+       }
+
+       static void calculateDiffAxisAngle(const btTransform& transform0, const btTransform& transform1, btVector3& axis, btScalar& angle)
+       {
+               btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
+               btQuaternion dorn;
+               dmat.getRotation(dorn);
+
+               ///floating point inaccuracy can lead to w component > 1..., which breaks
+               dorn.normalize();
+
+               angle = dorn.getAngle();
+               axis = btVector3(dorn.x(), dorn.y(), dorn.z());
+               axis[3] = btScalar(0.);
+               //check for axis length
+               btScalar len = axis.length2();
+               if (len < SIMD_EPSILON * SIMD_EPSILON)
+                       axis = btVector3(btScalar(1.), btScalar(0.), btScalar(0.));
+               else
+                       axis /= btSqrt(len);
+       }
+};
+
+///The btConvexSeparatingDistanceUtil can help speed up convex collision detection
+///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
+class btConvexSeparatingDistanceUtil
+{
+       btQuaternion m_ornA;
+       btQuaternion m_ornB;
+       btVector3 m_posA;
+       btVector3 m_posB;
+
+       btVector3 m_separatingNormal;
+
+       btScalar m_boundingRadiusA;
+       btScalar m_boundingRadiusB;
+       btScalar m_separatingDistance;
+
+public:
+       btConvexSeparatingDistanceUtil(btScalar boundingRadiusA, btScalar boundingRadiusB)
+               : m_boundingRadiusA(boundingRadiusA),
+                 m_boundingRadiusB(boundingRadiusB),
+                 m_separatingDistance(0.f)
+       {
+       }
+
+       btScalar getConservativeSeparatingDistance()
+       {
+               return m_separatingDistance;
+       }
+
+       void updateSeparatingDistance(const btTransform& transA, const btTransform& transB)
+       {
+               const btVector3& toPosA = transA.getOrigin();
+               const btVector3& toPosB = transB.getOrigin();
+               btQuaternion toOrnA = transA.getRotation();
+               btQuaternion toOrnB = transB.getRotation();
+
+               if (m_separatingDistance > 0.f)
+               {
+                       btVector3 linVelA, angVelA, linVelB, angVelB;
+                       btTransformUtil::calculateVelocityQuaternion(m_posA, toPosA, m_ornA, toOrnA, btScalar(1.), linVelA, angVelA);
+                       btTransformUtil::calculateVelocityQuaternion(m_posB, toPosB, m_ornB, toOrnB, btScalar(1.), linVelB, angVelB);
+                       btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
+                       btVector3 relLinVel = (linVelB - linVelA);
+                       btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
+                       if (relLinVelocLength < 0.f)
+                       {
+                               relLinVelocLength = 0.f;
+                       }
+
+                       btScalar projectedMotion = maxAngularProjectedVelocity + relLinVelocLength;
+                       m_separatingDistance -= projectedMotion;
+               }
+
+               m_posA = toPosA;
+               m_posB = toPosB;
+               m_ornA = toOrnA;
+               m_ornB = toOrnB;
+       }
+
+       void initSeparatingDistance(const btVector3& separatingVector, btScalar separatingDistance, const btTransform& transA, const btTransform& transB)
+       {
+               m_separatingDistance = separatingDistance;
+
+               if (m_separatingDistance > 0.f)
+               {
+                       m_separatingNormal = separatingVector;
+
+                       const btVector3& toPosA = transA.getOrigin();
+                       const btVector3& toPosB = transB.getOrigin();
+                       btQuaternion toOrnA = transA.getRotation();
+                       btQuaternion toOrnB = transB.getRotation();
+                       m_posA = toPosA;
+                       m_posB = toPosB;
+                       m_ornA = toOrnA;
+                       m_ornB = toOrnB;
+               }
+       }
+};
+
+#endif  //BT_TRANSFORM_UTIL_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btVector3.cpp b/dali-physics/third-party/bullet3/src/LinearMath/btVector3.cpp
new file mode 100644 (file)
index 0000000..55796c4
--- /dev/null
@@ -0,0 +1,1664 @@
+/*
+ Copyright (c) 2011 Apple Inc.
+ https://bulletphysics.org
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose, 
+ including commercial applications, and to alter it and redistribute it freely, 
+ subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as 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 source version has been altered.
+ */
+
+#if defined(_WIN32) || defined(__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+#include "btVector3.h"
+
+#if defined BT_USE_SIMD_VECTOR3
+
+#if DEBUG
+#include <string.h>  //for memset
+#endif
+
+#ifdef __APPLE__
+#include <stdint.h>
+typedef float float4 __attribute__((vector_size(16)));
+#else
+#define float4 __m128
+#endif
+//typedef  uint32_t uint4 __attribute__ ((vector_size(16)));
+
+#if defined BT_USE_SSE || defined _WIN32
+
+#define LOG2_ARRAY_SIZE 6
+#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
+
+#include <emmintrin.h>
+
+long _maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
+long _maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       const float4 *vertices = (const float4 *)vv;
+       static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
+       float4 dotMax = btAssign128(-BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY);
+       float4 vvec = _mm_loadu_ps(vec);
+       float4 vHi = btCastiTo128f(_mm_shuffle_epi32(btCastfTo128i(vvec), 0xaa));  /// zzzz
+       float4 vLo = _mm_movelh_ps(vvec, vvec);                                    /// xyxy
+
+       long maxIndex = -1L;
+
+       size_t segment = 0;
+       float4 stack_array[STACK_ARRAY_COUNT];
+
+#if DEBUG
+       //memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+#endif
+
+       size_t index;
+       float4 max;
+       // Faster loop without cleanup code for full tiles
+       for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
+       {
+               max = dotMax;
+
+               for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
+               {  // do four dot products at a time. Carefully avoid touching the w element.
+                       float4 v0 = vertices[0];
+                       float4 v1 = vertices[1];
+                       float4 v2 = vertices[2];
+                       float4 v3 = vertices[3];
+                       vertices += 4;
+
+                       float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 1] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 2] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 3] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       // It is too costly to keep the index of the max here. We will look for it again later.  We save a lot of work this way.
+               }
+
+               // If we found a new max
+               if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
+               {
+                       // copy the new max across all lanes of our max accumulator
+                       max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
+                       max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
+
+                       dotMax = max;
+
+                       // find first occurrence of that max
+                       size_t test;
+                       for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++)  // local_count must be a multiple of 4
+                       {
+                       }
+                       // record where it is.
+                       maxIndex = 4 * index + segment + indexTable[test];
+               }
+       }
+
+       // account for work we've already done
+       count -= segment;
+
+       // Deal with the last < STACK_ARRAY_COUNT vectors
+       max = dotMax;
+       index = 0;
+
+       if (btUnlikely(count > 16))
+       {
+               for (; index + 4 <= count / 4; index += 4)
+               {  // do four dot products at a time. Carefully avoid touching the w element.
+                       float4 v0 = vertices[0];
+                       float4 v1 = vertices[1];
+                       float4 v2 = vertices[2];
+                       float4 v3 = vertices[3];
+                       vertices += 4;
+
+                       float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 1] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 2] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 3] = x;
+                       max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+
+                       // It is too costly to keep the index of the max here. We will look for it again later.  We save a lot of work this way.
+               }
+       }
+
+       size_t localCount = (count & -4L) - 4 * index;
+       if (localCount)
+       {
+#ifdef __APPLE__
+               float4 t0, t1, t2, t3, t4;
+               float4 *sap = &stack_array[index + localCount / 4];
+               vertices += localCount;  // counter the offset
+               size_t byteIndex = -(localCount) * sizeof(float);
+               //AT&T Code style assembly
+               asm volatile(
+                       ".align 4                                                                   \n\
+             0: movaps  %[max], %[t2]                            // move max out of the way to avoid propagating NaNs in max \n\
+          movaps  (%[vertices], %[byteIndex], 4),    %[t0]    // vertices[0]      \n\
+          movaps  16(%[vertices], %[byteIndex], 4),  %[t1]    // vertices[1]      \n\
+          movaps  %[t0], %[max]                               // vertices[0]      \n\
+          movlhps %[t1], %[max]                               // x0y0x1y1         \n\
+         movaps  32(%[vertices], %[byteIndex], 4),  %[t3]    // vertices[2]      \n\
+         movaps  48(%[vertices], %[byteIndex], 4),  %[t4]    // vertices[3]      \n\
+          mulps   %[vLo], %[max]                              // x0y0x1y1 * vLo   \n\
+         movhlps %[t0], %[t1]                                // z0w0z1w1         \n\
+         movaps  %[t3], %[t0]                                // vertices[2]      \n\
+         movlhps %[t4], %[t0]                                // x2y2x3y3         \n\
+         mulps   %[vLo], %[t0]                               // x2y2x3y3 * vLo   \n\
+          movhlps %[t3], %[t4]                                // z2w2z3w3         \n\
+          shufps  $0x88, %[t4], %[t1]                         // z0z1z2z3         \n\
+          mulps   %[vHi], %[t1]                               // z0z1z2z3 * vHi   \n\
+         movaps  %[max], %[t3]                               // x0y0x1y1 * vLo   \n\
+         shufps  $0x88, %[t0], %[max]                        // x0x1x2x3 * vLo.x \n\
+         shufps  $0xdd, %[t0], %[t3]                         // y0y1y2y3 * vLo.y \n\
+         addps   %[t3], %[max]                               // x + y            \n\
+         addps   %[t1], %[max]                               // x + y + z        \n\
+         movaps  %[max], (%[sap], %[byteIndex])              // record result for later scrutiny \n\
+         maxps   %[t2], %[max]                               // record max, restore max   \n\
+         add     $16, %[byteIndex]                           // advance loop counter\n\
+         jnz     0b                                          \n\
+     "
+                       : [max] "+x"(max), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
+                       : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
+                       : "memory", "cc");
+               index += localCount / 4;
+#else
+               {
+                       for (unsigned int i = 0; i < localCount / 4; i++, index++)
+                       {  // do four dot products at a time. Carefully avoid touching the w element.
+                               float4 v0 = vertices[0];
+                               float4 v1 = vertices[1];
+                               float4 v2 = vertices[2];
+                               float4 v3 = vertices[3];
+                               vertices += 4;
+
+                               float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                               float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                               float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                               float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                               lo0 = lo0 * vLo;
+                               lo1 = lo1 * vLo;
+                               float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                               float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                               float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                               z = z * vHi;
+                               x = x + y;
+                               x = x + z;
+                               stack_array[index] = x;
+                               max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+                       }
+               }
+#endif  //__APPLE__
+       }
+
+       // process the last few points
+       if (count & 3)
+       {
+               float4 v0, v1, v2, x, y, z;
+               switch (count & 3)
+               {
+                       case 3:
+                       {
+                               v0 = vertices[0];
+                               v1 = vertices[1];
+                               v2 = vertices[2];
+
+                               // Calculate 3 dot products, transpose, duplicate v2
+                               float4 lo0 = _mm_movelh_ps(v0, v1);  // xyxy.lo
+                               float4 hi0 = _mm_movehl_ps(v1, v0);  // z?z?.lo
+                               lo0 = lo0 * vLo;
+                               z = _mm_shuffle_ps(hi0, v2, 0xa8);  // z0z1z2z2
+                               z = z * vHi;
+                               float4 lo1 = _mm_movelh_ps(v2, v2);  // xyxy
+                               lo1 = lo1 * vLo;
+                               x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                               y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       }
+                       break;
+                       case 2:
+                       {
+                               v0 = vertices[0];
+                               v1 = vertices[1];
+                               float4 xy = _mm_movelh_ps(v0, v1);
+                               z = _mm_movehl_ps(v1, v0);
+                               xy = xy * vLo;
+                               z = _mm_shuffle_ps(z, z, 0xa8);
+                               x = _mm_shuffle_ps(xy, xy, 0xa8);
+                               y = _mm_shuffle_ps(xy, xy, 0xfd);
+                               z = z * vHi;
+                       }
+                       break;
+                       case 1:
+                       {
+                               float4 xy = vertices[0];
+                               z = _mm_shuffle_ps(xy, xy, 0xaa);
+                               xy = xy * vLo;
+                               z = z * vHi;
+                               x = _mm_shuffle_ps(xy, xy, 0);
+                               y = _mm_shuffle_ps(xy, xy, 0x55);
+                       }
+                       break;
+               }
+               x = x + y;
+               x = x + z;
+               stack_array[index] = x;
+               max = _mm_max_ps(x, max);  // control the order here so that max is never NaN even if x is nan
+               index++;
+       }
+
+       // if we found a new max.
+       if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
+       {  // we found a new max. Search for it
+               // find max across the max vector, place in all elements of max -- big latency hit here
+               max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
+               max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
+
+               // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+               // this where it actually makes a difference is handled in the early out at the top of the function,
+               // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+               // complexity, and removed it.
+
+               dotMax = max;
+
+               // scan for the first occurence of max in the array
+               size_t test;
+               for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++)  // local_count must be a multiple of 4
+               {
+               }
+               maxIndex = 4 * index + segment + indexTable[test];
+       }
+
+       _mm_store_ss(dotResult, dotMax);
+       return maxIndex;
+}
+
+long _mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
+
+long _mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       const float4 *vertices = (const float4 *)vv;
+       static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
+       float4 dotmin = btAssign128(BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY);
+       float4 vvec = _mm_loadu_ps(vec);
+       float4 vHi = btCastiTo128f(_mm_shuffle_epi32(btCastfTo128i(vvec), 0xaa));  /// zzzz
+       float4 vLo = _mm_movelh_ps(vvec, vvec);                                    /// xyxy
+
+       long minIndex = -1L;
+
+       size_t segment = 0;
+       float4 stack_array[STACK_ARRAY_COUNT];
+
+#if DEBUG
+       //memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+#endif
+
+       size_t index;
+       float4 min;
+       // Faster loop without cleanup code for full tiles
+       for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
+       {
+               min = dotmin;
+
+               for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
+               {  // do four dot products at a time. Carefully avoid touching the w element.
+                       float4 v0 = vertices[0];
+                       float4 v1 = vertices[1];
+                       float4 v2 = vertices[2];
+                       float4 v3 = vertices[3];
+                       vertices += 4;
+
+                       float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 1] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 2] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 3] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       // It is too costly to keep the index of the min here. We will look for it again later.  We save a lot of work this way.
+               }
+
+               // If we found a new min
+               if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
+               {
+                       // copy the new min across all lanes of our min accumulator
+                       min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
+                       min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
+
+                       dotmin = min;
+
+                       // find first occurrence of that min
+                       size_t test;
+                       for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++)  // local_count must be a multiple of 4
+                       {
+                       }
+                       // record where it is.
+                       minIndex = 4 * index + segment + indexTable[test];
+               }
+       }
+
+       // account for work we've already done
+       count -= segment;
+
+       // Deal with the last < STACK_ARRAY_COUNT vectors
+       min = dotmin;
+       index = 0;
+
+       if (btUnlikely(count > 16))
+       {
+               for (; index + 4 <= count / 4; index += 4)
+               {  // do four dot products at a time. Carefully avoid touching the w element.
+                       float4 v0 = vertices[0];
+                       float4 v1 = vertices[1];
+                       float4 v2 = vertices[2];
+                       float4 v3 = vertices[3];
+                       vertices += 4;
+
+                       float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 1] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 2] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       v0 = vertices[0];
+                       v1 = vertices[1];
+                       v2 = vertices[2];
+                       v3 = vertices[3];
+                       vertices += 4;
+
+                       lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                       hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                       lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                       hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                       lo0 = lo0 * vLo;
+                       lo1 = lo1 * vLo;
+                       z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                       x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                       y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       z = z * vHi;
+                       x = x + y;
+                       x = x + z;
+                       stack_array[index + 3] = x;
+                       min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+
+                       // It is too costly to keep the index of the min here. We will look for it again later.  We save a lot of work this way.
+               }
+       }
+
+       size_t localCount = (count & -4L) - 4 * index;
+       if (localCount)
+       {
+#ifdef __APPLE__
+               vertices += localCount;  // counter the offset
+               float4 t0, t1, t2, t3, t4;
+               size_t byteIndex = -(localCount) * sizeof(float);
+               float4 *sap = &stack_array[index + localCount / 4];
+
+               asm volatile(
+                       ".align 4                                                                   \n\
+             0: movaps  %[min], %[t2]                            // move min out of the way to avoid propagating NaNs in min \n\
+             movaps  (%[vertices], %[byteIndex], 4),    %[t0]    // vertices[0]      \n\
+             movaps  16(%[vertices], %[byteIndex], 4),  %[t1]    // vertices[1]      \n\
+             movaps  %[t0], %[min]                               // vertices[0]      \n\
+             movlhps %[t1], %[min]                               // x0y0x1y1         \n\
+             movaps  32(%[vertices], %[byteIndex], 4),  %[t3]    // vertices[2]      \n\
+             movaps  48(%[vertices], %[byteIndex], 4),  %[t4]    // vertices[3]      \n\
+             mulps   %[vLo], %[min]                              // x0y0x1y1 * vLo   \n\
+             movhlps %[t0], %[t1]                                // z0w0z1w1         \n\
+             movaps  %[t3], %[t0]                                // vertices[2]      \n\
+             movlhps %[t4], %[t0]                                // x2y2x3y3         \n\
+             movhlps %[t3], %[t4]                                // z2w2z3w3         \n\
+             mulps   %[vLo], %[t0]                               // x2y2x3y3 * vLo   \n\
+             shufps  $0x88, %[t4], %[t1]                         // z0z1z2z3         \n\
+             mulps   %[vHi], %[t1]                               // z0z1z2z3 * vHi   \n\
+             movaps  %[min], %[t3]                               // x0y0x1y1 * vLo   \n\
+             shufps  $0x88, %[t0], %[min]                        // x0x1x2x3 * vLo.x \n\
+             shufps  $0xdd, %[t0], %[t3]                         // y0y1y2y3 * vLo.y \n\
+             addps   %[t3], %[min]                               // x + y            \n\
+             addps   %[t1], %[min]                               // x + y + z        \n\
+             movaps  %[min], (%[sap], %[byteIndex])              // record result for later scrutiny \n\
+             minps   %[t2], %[min]                               // record min, restore min   \n\
+             add     $16, %[byteIndex]                           // advance loop counter\n\
+             jnz     0b                                          \n\
+             "
+                       : [min] "+x"(min), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
+                       : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
+                       : "memory", "cc");
+               index += localCount / 4;
+#else
+               {
+                       for (unsigned int i = 0; i < localCount / 4; i++, index++)
+                       {  // do four dot products at a time. Carefully avoid touching the w element.
+                               float4 v0 = vertices[0];
+                               float4 v1 = vertices[1];
+                               float4 v2 = vertices[2];
+                               float4 v3 = vertices[3];
+                               vertices += 4;
+
+                               float4 lo0 = _mm_movelh_ps(v0, v1);  // x0y0x1y1
+                               float4 hi0 = _mm_movehl_ps(v1, v0);  // z0?0z1?1
+                               float4 lo1 = _mm_movelh_ps(v2, v3);  // x2y2x3y3
+                               float4 hi1 = _mm_movehl_ps(v3, v2);  // z2?2z3?3
+
+                               lo0 = lo0 * vLo;
+                               lo1 = lo1 * vLo;
+                               float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+                               float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                               float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                               z = z * vHi;
+                               x = x + y;
+                               x = x + z;
+                               stack_array[index] = x;
+                               min = _mm_min_ps(x, min);  // control the order here so that max is never NaN even if x is nan
+                       }
+               }
+
+#endif
+       }
+
+       // process the last few points
+       if (count & 3)
+       {
+               float4 v0, v1, v2, x, y, z;
+               switch (count & 3)
+               {
+                       case 3:
+                       {
+                               v0 = vertices[0];
+                               v1 = vertices[1];
+                               v2 = vertices[2];
+
+                               // Calculate 3 dot products, transpose, duplicate v2
+                               float4 lo0 = _mm_movelh_ps(v0, v1);  // xyxy.lo
+                               float4 hi0 = _mm_movehl_ps(v1, v0);  // z?z?.lo
+                               lo0 = lo0 * vLo;
+                               z = _mm_shuffle_ps(hi0, v2, 0xa8);  // z0z1z2z2
+                               z = z * vHi;
+                               float4 lo1 = _mm_movelh_ps(v2, v2);  // xyxy
+                               lo1 = lo1 * vLo;
+                               x = _mm_shuffle_ps(lo0, lo1, 0x88);
+                               y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+                       }
+                       break;
+                       case 2:
+                       {
+                               v0 = vertices[0];
+                               v1 = vertices[1];
+                               float4 xy = _mm_movelh_ps(v0, v1);
+                               z = _mm_movehl_ps(v1, v0);
+                               xy = xy * vLo;
+                               z = _mm_shuffle_ps(z, z, 0xa8);
+                               x = _mm_shuffle_ps(xy, xy, 0xa8);
+                               y = _mm_shuffle_ps(xy, xy, 0xfd);
+                               z = z * vHi;
+                       }
+                       break;
+                       case 1:
+                       {
+                               float4 xy = vertices[0];
+                               z = _mm_shuffle_ps(xy, xy, 0xaa);
+                               xy = xy * vLo;
+                               z = z * vHi;
+                               x = _mm_shuffle_ps(xy, xy, 0);
+                               y = _mm_shuffle_ps(xy, xy, 0x55);
+                       }
+                       break;
+               }
+               x = x + y;
+               x = x + z;
+               stack_array[index] = x;
+               min = _mm_min_ps(x, min);  // control the order here so that min is never NaN even if x is nan
+               index++;
+       }
+
+       // if we found a new min.
+       if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
+       {  // we found a new min. Search for it
+               // find min across the min vector, place in all elements of min -- big latency hit here
+               min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
+               min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
+
+               // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+               // this where it actually makes a difference is handled in the early out at the top of the function,
+               // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+               // complexity, and removed it.
+
+               dotmin = min;
+
+               // scan for the first occurence of min in the array
+               size_t test;
+               for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++)  // local_count must be a multiple of 4
+               {
+               }
+               minIndex = 4 * index + segment + indexTable[test];
+       }
+
+       _mm_store_ss(dotResult, dotmin);
+       return minIndex;
+}
+
+#elif defined BT_USE_NEON
+
+#define ARM_NEON_GCC_COMPATIBILITY 1
+#include <arm_neon.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>  //for sysctlbyname
+
+static long _maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long _maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long _maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long _mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long _mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
+static long _mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
+
+long (*_maxdot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = _maxdot_large_sel;
+long (*_mindot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = _mindot_large_sel;
+
+static inline uint32_t btGetCpuCapabilities(void)
+{
+       static uint32_t capabilities = 0;
+       static bool testedCapabilities = false;
+
+       if (0 == testedCapabilities)
+       {
+               uint32_t hasFeature = 0;
+               size_t featureSize = sizeof(hasFeature);
+               int err = sysctlbyname("hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0);
+
+               if (0 == err && hasFeature)
+                       capabilities |= 0x2000;
+
+               testedCapabilities = true;
+       }
+
+       return capabilities;
+}
+
+static long _maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       if (btGetCpuCapabilities() & 0x2000)
+               _maxdot_large = _maxdot_large_v1;
+       else
+               _maxdot_large = _maxdot_large_v0;
+
+       return _maxdot_large(vv, vec, count, dotResult);
+}
+
+static long _mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       if (btGetCpuCapabilities() & 0x2000)
+               _mindot_large = _mindot_large_v1;
+       else
+               _mindot_large = _mindot_large_v0;
+
+       return _mindot_large(vv, vec, count, dotResult);
+}
+
+#if defined __arm__
+#define vld1q_f32_aligned_postincrement(_ptr) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
+#else
+//support 64bit arm
+#define vld1q_f32_aligned_postincrement(_ptr) ({ float32x4_t _r = ((float32x4_t*)(_ptr))[0]; (_ptr) = (const float*) ((const char*)(_ptr) + 16L); /*return*/ _r; })
+#endif
+
+long _maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       unsigned long i = 0;
+       float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+       float32x2_t vLo = vget_low_f32(vvec);
+       float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+       float32x2_t dotMaxLo = (float32x2_t){-BT_INFINITY, -BT_INFINITY};
+       float32x2_t dotMaxHi = (float32x2_t){-BT_INFINITY, -BT_INFINITY};
+       uint32x2_t indexLo = (uint32x2_t){0, 1};
+       uint32x2_t indexHi = (uint32x2_t){2, 3};
+       uint32x2_t iLo = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+       uint32x2_t iHi = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+       const uint32x2_t four = (uint32x2_t){4, 4};
+
+       for (; i + 8 <= count; i += 8)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+               float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+               float32x2_t rLo = vpadd_f32(xy0, xy1);
+               float32x2_t rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+               uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+               dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+               dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+
+               v0 = vld1q_f32_aligned_postincrement(vv);
+               v1 = vld1q_f32_aligned_postincrement(vv);
+               v2 = vld1q_f32_aligned_postincrement(vv);
+               v3 = vld1q_f32_aligned_postincrement(vv);
+
+               xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               zLo = vmul_f32(z0.val[0], vHi);
+               zHi = vmul_f32(z1.val[0], vHi);
+
+               rLo = vpadd_f32(xy0, xy1);
+               rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               maskLo = vcgt_f32(rLo, dotMaxLo);
+               maskHi = vcgt_f32(rHi, dotMaxHi);
+               dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+               dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+       }
+
+       for (; i + 4 <= count; i += 4)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+               float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+               float32x2_t rLo = vpadd_f32(xy0, xy1);
+               float32x2_t rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+               uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+               dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+               dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+       }
+
+       switch (count & 3)
+       {
+               case 3:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+                       float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+
+                       float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+                       float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+                       float32x2_t rLo = vpadd_f32(xy0, xy1);
+                       float32x2_t rHi = vpadd_f32(xy2, xy2);
+                       rLo = vadd_f32(rLo, zLo);
+                       rHi = vadd_f32(rHi, zHi);
+
+                       uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+                       uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
+                       dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+                       dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+                       iHi = vbsl_u32(maskHi, indexHi, iHi);
+               }
+               break;
+               case 2:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+
+                       float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+
+                       float32x2_t rLo = vpadd_f32(xy0, xy1);
+                       rLo = vadd_f32(rLo, zLo);
+
+                       uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+                       dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+               }
+               break;
+               case 1:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+                       float32x2_t zLo = vmul_f32(z0, vHi);
+                       float32x2_t rLo = vpadd_f32(xy0, xy0);
+                       rLo = vadd_f32(rLo, zLo);
+                       uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
+                       dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+               }
+               break;
+
+               default:
+                       break;
+       }
+
+       // select best answer between hi and lo results
+       uint32x2_t mask = vcgt_f32(dotMaxHi, dotMaxLo);
+       dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+       iLo = vbsl_u32(mask, iHi, iLo);
+
+       // select best answer between even and odd results
+       dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
+       iHi = vdup_lane_u32(iLo, 1);
+       mask = vcgt_f32(dotMaxHi, dotMaxLo);
+       dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+       iLo = vbsl_u32(mask, iHi, iLo);
+
+       *dotResult = vget_lane_f32(dotMaxLo, 0);
+       return vget_lane_u32(iLo, 0);
+}
+
+long _maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+       float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+       float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+       const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
+       uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
+       uint32x4_t index = (uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+       float32x4_t maxDot = (float32x4_t){-BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY};
+
+       unsigned long i = 0;
+       for (; i + 8 <= count; i += 8)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               float32x4x2_t zb = vuzpq_f32(z0, z1);
+               float32x4_t z = vmulq_f32(zb.val[0], vHi);
+               float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+               float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               uint32x4_t mask = vcgtq_f32(x, maxDot);
+               maxDot = vbslq_f32(mask, x, maxDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+
+               v0 = vld1q_f32_aligned_postincrement(vv);
+               v1 = vld1q_f32_aligned_postincrement(vv);
+               v2 = vld1q_f32_aligned_postincrement(vv);
+               v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               zb = vuzpq_f32(z0, z1);
+               z = vmulq_f32(zb.val[0], vHi);
+               xy = vuzpq_f32(xy0, xy1);
+               x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               mask = vcgtq_f32(x, maxDot);
+               maxDot = vbslq_f32(mask, x, maxDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+       }
+
+       for (; i + 4 <= count; i += 4)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               float32x4x2_t zb = vuzpq_f32(z0, z1);
+               float32x4_t z = vmulq_f32(zb.val[0], vHi);
+               float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+               float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               uint32x4_t mask = vcgtq_f32(x, maxDot);
+               maxDot = vbslq_f32(mask, x, maxDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+       }
+
+       switch (count & 3)
+       {
+               case 3:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+                       float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
+
+                       xy0 = vmulq_f32(xy0, vLo);
+                       xy1 = vmulq_f32(xy1, vLo);
+
+                       float32x4x2_t zb = vuzpq_f32(z0, z1);
+                       float32x4_t z = vmulq_f32(zb.val[0], vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcgtq_f32(x, maxDot);
+                       maxDot = vbslq_f32(mask, x, maxDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               case 2:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+
+                       xy0 = vmulq_f32(xy0, vLo);
+
+                       float32x4x2_t zb = vuzpq_f32(z0, z0);
+                       float32x4_t z = vmulq_f32(zb.val[0], vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcgtq_f32(x, maxDot);
+                       maxDot = vbslq_f32(mask, x, maxDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               case 1:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+                       xy0 = vmulq_f32(xy0, vLo);
+
+                       z = vmulq_f32(z, vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcgtq_f32(x, maxDot);
+                       maxDot = vbslq_f32(mask, x, maxDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               default:
+                       break;
+       }
+
+       // select best answer between hi and lo results
+       uint32x2_t mask = vcgt_f32(vget_high_f32(maxDot), vget_low_f32(maxDot));
+       float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
+       uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+       // select best answer between even and odd results
+       float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
+       uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+       mask = vcgt_f32(maxDotO, maxDot2);
+       maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
+       index2 = vbsl_u32(mask, indexHi, index2);
+
+       *dotResult = vget_lane_f32(maxDot2, 0);
+       return vget_lane_u32(index2, 0);
+}
+
+long _mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       unsigned long i = 0;
+       float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+       float32x2_t vLo = vget_low_f32(vvec);
+       float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+       float32x2_t dotMinLo = (float32x2_t){BT_INFINITY, BT_INFINITY};
+       float32x2_t dotMinHi = (float32x2_t){BT_INFINITY, BT_INFINITY};
+       uint32x2_t indexLo = (uint32x2_t){0, 1};
+       uint32x2_t indexHi = (uint32x2_t){2, 3};
+       uint32x2_t iLo = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+       uint32x2_t iHi = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+       const uint32x2_t four = (uint32x2_t){4, 4};
+
+       for (; i + 8 <= count; i += 8)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+               float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+               float32x2_t rLo = vpadd_f32(xy0, xy1);
+               float32x2_t rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+               uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+               dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+               dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+
+               v0 = vld1q_f32_aligned_postincrement(vv);
+               v1 = vld1q_f32_aligned_postincrement(vv);
+               v2 = vld1q_f32_aligned_postincrement(vv);
+               v3 = vld1q_f32_aligned_postincrement(vv);
+
+               xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               zLo = vmul_f32(z0.val[0], vHi);
+               zHi = vmul_f32(z1.val[0], vHi);
+
+               rLo = vpadd_f32(xy0, xy1);
+               rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               maskLo = vclt_f32(rLo, dotMinLo);
+               maskHi = vclt_f32(rHi, dotMinHi);
+               dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+               dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+       }
+
+       for (; i + 4 <= count; i += 4)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+               float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+               float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+               float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
+
+               float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
+               float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+               float32x2_t zHi = vmul_f32(z1.val[0], vHi);
+
+               float32x2_t rLo = vpadd_f32(xy0, xy1);
+               float32x2_t rHi = vpadd_f32(xy2, xy3);
+               rLo = vadd_f32(rLo, zLo);
+               rHi = vadd_f32(rHi, zHi);
+
+               uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+               uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+               dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+               dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+               iLo = vbsl_u32(maskLo, indexLo, iLo);
+               iHi = vbsl_u32(maskHi, indexHi, iHi);
+               indexLo = vadd_u32(indexLo, four);
+               indexHi = vadd_u32(indexHi, four);
+       }
+       switch (count & 3)
+       {
+               case 3:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+                       float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
+
+                       float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+                       float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+                       float32x2_t rLo = vpadd_f32(xy0, xy1);
+                       float32x2_t rHi = vpadd_f32(xy2, xy2);
+                       rLo = vadd_f32(rLo, zLo);
+                       rHi = vadd_f32(rHi, zHi);
+
+                       uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+                       uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
+                       dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+                       dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+                       iHi = vbsl_u32(maskHi, indexHi, iHi);
+               }
+               break;
+               case 2:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
+
+                       float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x2_t zLo = vmul_f32(z0.val[0], vHi);
+
+                       float32x2_t rLo = vpadd_f32(xy0, xy1);
+                       rLo = vadd_f32(rLo, zLo);
+
+                       uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+                       dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+               }
+               break;
+               case 1:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
+                       float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+                       float32x2_t zLo = vmul_f32(z0, vHi);
+                       float32x2_t rLo = vpadd_f32(xy0, xy0);
+                       rLo = vadd_f32(rLo, zLo);
+                       uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
+                       dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
+                       iLo = vbsl_u32(maskLo, indexLo, iLo);
+               }
+               break;
+
+               default:
+                       break;
+       }
+
+       // select best answer between hi and lo results
+       uint32x2_t mask = vclt_f32(dotMinHi, dotMinLo);
+       dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+       iLo = vbsl_u32(mask, iHi, iLo);
+
+       // select best answer between even and odd results
+       dotMinHi = vdup_lane_f32(dotMinLo, 1);
+       iHi = vdup_lane_u32(iLo, 1);
+       mask = vclt_f32(dotMinHi, dotMinLo);
+       dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+       iLo = vbsl_u32(mask, iHi, iLo);
+
+       *dotResult = vget_lane_f32(dotMinLo, 0);
+       return vget_lane_u32(iLo, 0);
+}
+
+long _mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
+{
+       float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
+       float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+       float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+       const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
+       uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
+       uint32x4_t index = (uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
+       float32x4_t minDot = (float32x4_t){BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY};
+
+       unsigned long i = 0;
+       for (; i + 8 <= count; i += 8)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               float32x4x2_t zb = vuzpq_f32(z0, z1);
+               float32x4_t z = vmulq_f32(zb.val[0], vHi);
+               float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+               float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               uint32x4_t mask = vcltq_f32(x, minDot);
+               minDot = vbslq_f32(mask, x, minDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+
+               v0 = vld1q_f32_aligned_postincrement(vv);
+               v1 = vld1q_f32_aligned_postincrement(vv);
+               v2 = vld1q_f32_aligned_postincrement(vv);
+               v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               zb = vuzpq_f32(z0, z1);
+               z = vmulq_f32(zb.val[0], vHi);
+               xy = vuzpq_f32(xy0, xy1);
+               x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               mask = vcltq_f32(x, minDot);
+               minDot = vbslq_f32(mask, x, minDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+       }
+
+       for (; i + 4 <= count; i += 4)
+       {
+               float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+               float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
+
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+               float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
+               // the next two lines should resolve to a single vswp d, d
+               float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+               float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
+
+               xy0 = vmulq_f32(xy0, vLo);
+               xy1 = vmulq_f32(xy1, vLo);
+
+               float32x4x2_t zb = vuzpq_f32(z0, z1);
+               float32x4_t z = vmulq_f32(zb.val[0], vHi);
+               float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+               float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+               x = vaddq_f32(x, z);
+
+               uint32x4_t mask = vcltq_f32(x, minDot);
+               minDot = vbslq_f32(mask, x, minDot);
+               index = vbslq_u32(mask, local_index, index);
+               local_index = vaddq_u32(local_index, four);
+       }
+
+       switch (count & 3)
+       {
+               case 3:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+                       float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+                       float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
+
+                       xy0 = vmulq_f32(xy0, vLo);
+                       xy1 = vmulq_f32(xy1, vLo);
+
+                       float32x4x2_t zb = vuzpq_f32(z0, z1);
+                       float32x4_t z = vmulq_f32(zb.val[0], vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy1);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcltq_f32(x, minDot);
+                       minDot = vbslq_f32(mask, x, minDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               case 2:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+                       float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
+
+                       xy0 = vmulq_f32(xy0, vLo);
+
+                       float32x4x2_t zb = vuzpq_f32(z0, z0);
+                       float32x4_t z = vmulq_f32(zb.val[0], vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcltq_f32(x, minDot);
+                       minDot = vbslq_f32(mask, x, minDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               case 1:
+               {
+                       float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
+
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
+                       // the next two lines should resolve to a single vswp d, d
+                       float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+                       xy0 = vmulq_f32(xy0, vLo);
+
+                       z = vmulq_f32(z, vHi);
+                       float32x4x2_t xy = vuzpq_f32(xy0, xy0);
+                       float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+                       x = vaddq_f32(x, z);
+
+                       uint32x4_t mask = vcltq_f32(x, minDot);
+                       minDot = vbslq_f32(mask, x, minDot);
+                       index = vbslq_u32(mask, local_index, index);
+                       local_index = vaddq_u32(local_index, four);
+               }
+               break;
+
+               default:
+                       break;
+       }
+
+       // select best answer between hi and lo results
+       uint32x2_t mask = vclt_f32(vget_high_f32(minDot), vget_low_f32(minDot));
+       float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
+       uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+       // select best answer between even and odd results
+       float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
+       uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+       mask = vclt_f32(minDotO, minDot2);
+       minDot2 = vbsl_f32(mask, minDotO, minDot2);
+       index2 = vbsl_u32(mask, indexHi, index2);
+
+       *dotResult = vget_lane_f32(minDot2, 0);
+       return vget_lane_u32(index2, 0);
+}
+
+#else
+#error Unhandled __APPLE__ arch
+#endif
+
+#endif /* __APPLE__ */
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/btVector3.h b/dali-physics/third-party/bullet3/src/LinearMath/btVector3.h
new file mode 100644 (file)
index 0000000..9da1627
--- /dev/null
@@ -0,0 +1,1336 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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_VECTOR3_H
+#define BT_VECTOR3_H
+
+//#include <stdint.h>
+#include "btScalar.h"
+#include "btMinMax.h"
+#include "btAlignedAllocator.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btVector3Data btVector3DoubleData
+#define btVector3DataName "btVector3DoubleData"
+#else
+#define btVector3Data btVector3FloatData
+#define btVector3DataName "btVector3FloatData"
+#endif  //BT_USE_DOUBLE_PRECISION
+
+#if defined BT_USE_SSE
+
+//typedef  uint32_t __m128i __attribute__ ((vector_size(16)));
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4556)  // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
+#endif
+
+#define BT_SHUFFLE(x, y, z, w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
+//#define bt_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
+#define bt_pshufd_ps(_a, _mask) _mm_shuffle_ps((_a), (_a), (_mask))
+#define bt_splat3_ps(_a, _i) bt_pshufd_ps((_a), BT_SHUFFLE(_i, _i, _i, 3))
+#define bt_splat_ps(_a, _i) bt_pshufd_ps((_a), BT_SHUFFLE(_i, _i, _i, _i))
+
+#define btv3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define btvAbsMask (_mm_set_epi32(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define btvFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF))
+#define btv3AbsfMask btCastiTo128f(btv3AbsiMask)
+#define btvFFF0fMask btCastiTo128f(btvFFF0Mask)
+#define btvxyzMaskf btvFFF0fMask
+#define btvAbsfMask btCastiTo128f(btvAbsMask)
+
+//there is an issue with XCode 3.2 (LCx errors)
+#define btvMzeroMask (_mm_set_ps(-0.0f, -0.0f, -0.0f, -0.0f))
+#define v1110 (_mm_set_ps(0.0f, 1.0f, 1.0f, 1.0f))
+#define vHalf (_mm_set_ps(0.5f, 0.5f, 0.5f, 0.5f))
+#define v1_5 (_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f))
+
+//const __m128 ATTRIBUTE_ALIGNED16(btvMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f};
+//const __m128 ATTRIBUTE_ALIGNED16(v1110) = {1.0f, 1.0f, 1.0f, 0.0f};
+//const __m128 ATTRIBUTE_ALIGNED16(vHalf) = {0.5f, 0.5f, 0.5f, 0.5f};
+//const __m128 ATTRIBUTE_ALIGNED16(v1_5)  = {1.5f, 1.5f, 1.5f, 1.5f};
+
+#endif
+
+#ifdef BT_USE_NEON
+
+const float32x4_t ATTRIBUTE_ALIGNED16(btvMzeroMask) = (float32x4_t){-0.0f, -0.0f, -0.0f, -0.0f};
+const int32x4_t ATTRIBUTE_ALIGNED16(btvFFF0Mask) = (int32x4_t){static_cast<int32_t>(0xFFFFFFFF),
+                                                                                                                          static_cast<int32_t>(0xFFFFFFFF), static_cast<int32_t>(0xFFFFFFFF), 0x0};
+const int32x4_t ATTRIBUTE_ALIGNED16(btvAbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
+const int32x4_t ATTRIBUTE_ALIGNED16(btv3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0};
+
+#endif
+
+/**@brief btVector3 can be used to represent 3D points and vectors.
+ * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
+ * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
+ */
+ATTRIBUTE_ALIGNED16(class)
+btVector3
+{
+public:
+       BT_DECLARE_ALIGNED_ALLOCATOR();
+
+#if defined(__SPU__) && defined(__CELLOS_LV2__)
+       btScalar m_floats[4];
+
+public:
+       SIMD_FORCE_INLINE const vec_float4& get128() const
+       {
+               return *((const vec_float4*)&m_floats[0]);
+       }
+
+public:
+#else                                            //__CELLOS_LV2__ __SPU__
+#if defined(BT_USE_SSE) || defined(BT_USE_NEON)  // _WIN32 || ARM
+       union {
+               btSimdFloat4 mVec128;
+               btScalar m_floats[4];
+       };
+       SIMD_FORCE_INLINE btSimdFloat4 get128() const
+       {
+               return mVec128;
+       }
+       SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
+       {
+               mVec128 = v128;
+       }
+#else
+       btScalar m_floats[4];
+#endif
+#endif  //__CELLOS_LV2__ __SPU__
+
+public:
+       /**@brief No initialization constructor */
+       SIMD_FORCE_INLINE btVector3()
+       {
+       }
+
+       /**@brief Constructor from scalars 
+   * @param x X value
+   * @param y Y value 
+   * @param z Z value 
+   */
+       SIMD_FORCE_INLINE btVector3(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+       {
+               m_floats[0] = _x;
+               m_floats[1] = _y;
+               m_floats[2] = _z;
+               m_floats[3] = btScalar(0.f);
+       }
+
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+       // Set Vector
+       SIMD_FORCE_INLINE btVector3(btSimdFloat4 v)
+       {
+               mVec128 = v;
+       }
+
+       // Copy constructor
+       SIMD_FORCE_INLINE btVector3(const btVector3& rhs)
+       {
+               mVec128 = rhs.mVec128;
+       }
+
+       // Assignment Operator
+       SIMD_FORCE_INLINE btVector3&
+       operator=(const btVector3& v)
+       {
+               mVec128 = v.mVec128;
+
+               return *this;
+       }
+#endif  // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+
+       /**@brief Add a vector to this one 
+ * @param The vector to add to this one */
+       SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               mVec128 = _mm_add_ps(mVec128, v.mVec128);
+#elif defined(BT_USE_NEON)
+               mVec128 = vaddq_f32(mVec128, v.mVec128);
+#else
+               m_floats[0] += v.m_floats[0];
+               m_floats[1] += v.m_floats[1];
+               m_floats[2] += v.m_floats[2];
+#endif
+               return *this;
+       }
+
+       /**@brief Subtract a vector from this one
+   * @param The vector to subtract */
+       SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               mVec128 = _mm_sub_ps(mVec128, v.mVec128);
+#elif defined(BT_USE_NEON)
+               mVec128 = vsubq_f32(mVec128, v.mVec128);
+#else
+               m_floats[0] -= v.m_floats[0];
+               m_floats[1] -= v.m_floats[1];
+               m_floats[2] -= v.m_floats[2];
+#endif
+               return *this;
+       }
+
+       /**@brief Scale the vector
+   * @param s Scale factor */
+       SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 vs = _mm_load_ss(&s);  //        (S 0 0 0)
+               vs = bt_pshufd_ps(vs, 0x80);  //        (S S S 0.0)
+               mVec128 = _mm_mul_ps(mVec128, vs);
+#elif defined(BT_USE_NEON)
+               mVec128 = vmulq_n_f32(mVec128, s);
+#else
+               m_floats[0] *= s;
+               m_floats[1] *= s;
+               m_floats[2] *= s;
+#endif
+               return *this;
+       }
+
+       /**@brief Inversely scale the vector 
+   * @param s Scale factor to divide by */
+       SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s)
+       {
+               btFullAssert(s != btScalar(0.0));
+
+#if 0  //defined(BT_USE_SSE_IN_API)
+// this code is not faster !
+               __m128 vs = _mm_load_ss(&s);
+               vs = _mm_div_ss(v1110, vs);
+               vs = bt_pshufd_ps(vs, 0x00);    //      (S S S S)
+
+               mVec128 = _mm_mul_ps(mVec128, vs);
+               
+               return *this;
+#else
+               return *this *= btScalar(1.0) / s;
+#endif
+       }
+
+       /**@brief Return the dot product
+   * @param v The other vector in the dot product */
+       SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const
+       {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 vd = _mm_mul_ps(mVec128, v.mVec128);
+               __m128 z = _mm_movehl_ps(vd, vd);
+               __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
+               vd = _mm_add_ss(vd, y);
+               vd = _mm_add_ss(vd, z);
+               return _mm_cvtss_f32(vd);
+#elif defined(BT_USE_NEON)
+               float32x4_t vd = vmulq_f32(mVec128, v.mVec128);
+               float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd));
+               x = vadd_f32(x, vget_high_f32(vd));
+               return vget_lane_f32(x, 0);
+#else
+               return m_floats[0] * v.m_floats[0] +
+                          m_floats[1] * v.m_floats[1] +
+                          m_floats[2] * v.m_floats[2];
+#endif
+       }
+
+       /**@brief Return the length of the vector squared */
+       SIMD_FORCE_INLINE btScalar length2() const
+       {
+               return dot(*this);
+       }
+
+       /**@brief Return the length of the vector */
+       SIMD_FORCE_INLINE btScalar length() const
+       {
+               return btSqrt(length2());
+       }
+
+       /**@brief Return the norm (length) of the vector */
+       SIMD_FORCE_INLINE btScalar norm() const
+       {
+               return length();
+       }
+
+       /**@brief Return the norm (length) of the vector */
+       SIMD_FORCE_INLINE btScalar safeNorm() const
+       {
+               btScalar d = length2();
+               //workaround for some clang/gcc issue of sqrtf(tiny number) = -INF
+               if (d > SIMD_EPSILON)
+                       return btSqrt(d);
+               return btScalar(0);
+       }
+
+       /**@brief Return the distance squared between the ends of this and another vector
+   * This is symantically treating the vector like a point */
+       SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const;
+
+       /**@brief Return the distance between the ends of this and another vector
+   * This is symantically treating the vector like a point */
+       SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const;
+
+       SIMD_FORCE_INLINE btVector3& safeNormalize()
+       {
+               btScalar l2 = length2();
+               //triNormal.normalize();
+               if (l2 >= SIMD_EPSILON * SIMD_EPSILON)
+               {
+                       (*this) /= btSqrt(l2);
+               }
+               else
+               {
+                       setValue(1, 0, 0);
+               }
+               return *this;
+       }
+
+       /**@brief Normalize this vector 
+   * x^2 + y^2 + z^2 = 1 */
+       SIMD_FORCE_INLINE btVector3& normalize()
+       {
+               btAssert(!fuzzyZero());
+
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               // dot product first
+               __m128 vd = _mm_mul_ps(mVec128, mVec128);
+               __m128 z = _mm_movehl_ps(vd, vd);
+               __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
+               vd = _mm_add_ss(vd, y);
+               vd = _mm_add_ss(vd, z);
+
+#if 0
+        vd = _mm_sqrt_ss(vd);
+               vd = _mm_div_ss(v1110, vd);
+               vd = bt_splat_ps(vd, 0x80);
+               mVec128 = _mm_mul_ps(mVec128, vd);
+#else
+
+               // NR step 1/sqrt(x) - vd is x, y is output
+               y = _mm_rsqrt_ss(vd);  // estimate
+
+               //  one step NR
+               z = v1_5;
+               vd = _mm_mul_ss(vd, vHalf);  // vd * 0.5
+               //x2 = vd;
+               vd = _mm_mul_ss(vd, y);  // vd * 0.5 * y0
+               vd = _mm_mul_ss(vd, y);  // vd * 0.5 * y0 * y0
+               z = _mm_sub_ss(z, vd);   // 1.5 - vd * 0.5 * y0 * y0
+
+               y = _mm_mul_ss(y, z);  // y0 * (1.5 - vd * 0.5 * y0 * y0)
+
+               y = bt_splat_ps(y, 0x80);
+               mVec128 = _mm_mul_ps(mVec128, y);
+
+#endif
+
+               return *this;
+#else
+               return *this /= length();
+#endif
+       }
+
+       /**@brief Return a normalized version of this vector */
+       SIMD_FORCE_INLINE btVector3 normalized() const;
+
+       /**@brief Return a rotated version of this vector
+   * @param wAxis The axis to rotate about 
+   * @param angle The angle to rotate by */
+       SIMD_FORCE_INLINE btVector3 rotate(const btVector3& wAxis, const btScalar angle) const;
+
+       /**@brief Return the angle between this and another vector
+   * @param v The other vector */
+       SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const
+       {
+               btScalar s = btSqrt(length2() * v.length2());
+               btFullAssert(s != btScalar(0.0));
+               return btAcos(dot(v) / s);
+       }
+
+       /**@brief Return a vector with the absolute values of each element */
+       SIMD_FORCE_INLINE btVector3 absolute() const
+       {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               return btVector3(_mm_and_ps(mVec128, btv3AbsfMask));
+#elif defined(BT_USE_NEON)
+               return btVector3(vabsq_f32(mVec128));
+#else
+               return btVector3(
+                       btFabs(m_floats[0]),
+                       btFabs(m_floats[1]),
+                       btFabs(m_floats[2]));
+#endif
+       }
+
+       /**@brief Return the cross product between this and another vector 
+   * @param v The other vector */
+       SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 T, V;
+
+               T = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 3));    //        (Y Z X 0)
+               V = bt_pshufd_ps(v.mVec128, BT_SHUFFLE(1, 2, 0, 3));  //        (Y Z X 0)
+
+               V = _mm_mul_ps(V, mVec128);
+               T = _mm_mul_ps(T, v.mVec128);
+               V = _mm_sub_ps(V, T);
+
+               V = bt_pshufd_ps(V, BT_SHUFFLE(1, 2, 0, 3));
+               return btVector3(V);
+#elif defined(BT_USE_NEON)
+               float32x4_t T, V;
+               // form (Y, Z, X, _) of mVec128 and v.mVec128
+               float32x2_t Tlow = vget_low_f32(mVec128);
+               float32x2_t Vlow = vget_low_f32(v.mVec128);
+               T = vcombine_f32(vext_f32(Tlow, vget_high_f32(mVec128), 1), Tlow);
+               V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v.mVec128), 1), Vlow);
+
+               V = vmulq_f32(V, mVec128);
+               T = vmulq_f32(T, v.mVec128);
+               V = vsubq_f32(V, T);
+               Vlow = vget_low_f32(V);
+               // form (Y, Z, X, _);
+               V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
+               V = (float32x4_t)vandq_s32((int32x4_t)V, btvFFF0Mask);
+
+               return btVector3(V);
+#else
+               return btVector3(
+                       m_floats[1] * v.m_floats[2] - m_floats[2] * v.m_floats[1],
+                       m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
+                       m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
+#endif
+       }
+
+       SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const
+       {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               // cross:
+               __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, BT_SHUFFLE(1, 2, 0, 3));  //  (Y Z X 0)
+               __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, BT_SHUFFLE(1, 2, 0, 3));  //  (Y Z X 0)
+
+               V = _mm_mul_ps(V, v1.mVec128);
+               T = _mm_mul_ps(T, v2.mVec128);
+               V = _mm_sub_ps(V, T);
+
+               V = _mm_shuffle_ps(V, V, BT_SHUFFLE(1, 2, 0, 3));
+
+               // dot:
+               V = _mm_mul_ps(V, mVec128);
+               __m128 z = _mm_movehl_ps(V, V);
+               __m128 y = _mm_shuffle_ps(V, V, 0x55);
+               V = _mm_add_ss(V, y);
+               V = _mm_add_ss(V, z);
+               return _mm_cvtss_f32(V);
+
+#elif defined(BT_USE_NEON)
+               // cross:
+               float32x4_t T, V;
+               // form (Y, Z, X, _) of mVec128 and v.mVec128
+               float32x2_t Tlow = vget_low_f32(v1.mVec128);
+               float32x2_t Vlow = vget_low_f32(v2.mVec128);
+               T = vcombine_f32(vext_f32(Tlow, vget_high_f32(v1.mVec128), 1), Tlow);
+               V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v2.mVec128), 1), Vlow);
+
+               V = vmulq_f32(V, v1.mVec128);
+               T = vmulq_f32(T, v2.mVec128);
+               V = vsubq_f32(V, T);
+               Vlow = vget_low_f32(V);
+               // form (Y, Z, X, _);
+               V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
+
+               // dot:
+               V = vmulq_f32(mVec128, V);
+               float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V));
+               x = vadd_f32(x, vget_high_f32(V));
+               return vget_lane_f32(x, 0);
+#else
+               return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
+                          m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
+                          m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
+#endif
+       }
+
+       /**@brief Return the axis with the smallest value 
+   * Note return values are 0,1,2 for x, y, or z */
+       SIMD_FORCE_INLINE int minAxis() const
+       {
+               return m_floats[0] < m_floats[1] ? (m_floats[0] < m_floats[2] ? 0 : 2) : (m_floats[1] < m_floats[2] ? 1 : 2);
+       }
+
+       /**@brief Return the axis with the largest value 
+   * Note return values are 0,1,2 for x, y, or z */
+       SIMD_FORCE_INLINE int maxAxis() const
+       {
+               return m_floats[0] < m_floats[1] ? (m_floats[1] < m_floats[2] ? 2 : 1) : (m_floats[0] < m_floats[2] ? 2 : 0);
+       }
+
+       SIMD_FORCE_INLINE int furthestAxis() const
+       {
+               return absolute().minAxis();
+       }
+
+       SIMD_FORCE_INLINE int closestAxis() const
+       {
+               return absolute().maxAxis();
+       }
+
+       SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 vrt = _mm_load_ss(&rt);  //      (rt 0 0 0)
+               btScalar s = btScalar(1.0) - rt;
+               __m128 vs = _mm_load_ss(&s);  //        (S 0 0 0)
+               vs = bt_pshufd_ps(vs, 0x80);  //        (S S S 0.0)
+               __m128 r0 = _mm_mul_ps(v0.mVec128, vs);
+               vrt = bt_pshufd_ps(vrt, 0x80);  //      (rt rt rt 0.0)
+               __m128 r1 = _mm_mul_ps(v1.mVec128, vrt);
+               __m128 tmp3 = _mm_add_ps(r0, r1);
+               mVec128 = tmp3;
+#elif defined(BT_USE_NEON)
+               float32x4_t vl = vsubq_f32(v1.mVec128, v0.mVec128);
+               vl = vmulq_n_f32(vl, rt);
+               mVec128 = vaddq_f32(vl, v0.mVec128);
+#else
+               btScalar s = btScalar(1.0) - rt;
+               m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
+               m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
+               m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
+               //don't do the unused w component
+               //              m_co[3] = s * v0[3] + rt * v1[3];
+#endif
+       }
+
+       /**@brief Return the linear interpolation between this and another vector 
+   * @param v The other vector 
+   * @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
+       SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               __m128 vt = _mm_load_ss(&t);  //        (t 0 0 0)
+               vt = bt_pshufd_ps(vt, 0x80);  //        (rt rt rt 0.0)
+               __m128 vl = _mm_sub_ps(v.mVec128, mVec128);
+               vl = _mm_mul_ps(vl, vt);
+               vl = _mm_add_ps(vl, mVec128);
+
+               return btVector3(vl);
+#elif defined(BT_USE_NEON)
+               float32x4_t vl = vsubq_f32(v.mVec128, mVec128);
+               vl = vmulq_n_f32(vl, t);
+               vl = vaddq_f32(vl, mVec128);
+
+               return btVector3(vl);
+#else
+               return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
+                                                m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
+                                                m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
+#endif
+       }
+
+       /**@brief Elementwise multiply this vector by the other 
+   * @param v The other vector */
+       SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               mVec128 = _mm_mul_ps(mVec128, v.mVec128);
+#elif defined(BT_USE_NEON)
+               mVec128 = vmulq_f32(mVec128, v.mVec128);
+#else
+               m_floats[0] *= v.m_floats[0];
+               m_floats[1] *= v.m_floats[1];
+               m_floats[2] *= v.m_floats[2];
+#endif
+               return *this;
+       }
+
+       /**@brief Return the x value */
+       SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+       /**@brief Return the y value */
+       SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+       /**@brief Return the z value */
+       SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+       /**@brief Set the x value */
+       SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x; };
+       /**@brief Set the y value */
+       SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y; };
+       /**@brief Set the z value */
+       SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z; };
+       /**@brief Set the w value */
+       SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w; };
+       /**@brief Return the x value */
+       SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+       /**@brief Return the y value */
+       SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+       /**@brief Return the z value */
+       SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+       /**@brief Return the w value */
+       SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+       //SIMD_FORCE_INLINE btScalar&       operator[](int i)       { return (&m_floats[0])[i]; }
+       //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
+       ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+       SIMD_FORCE_INLINE operator btScalar*() { return &m_floats[0]; }
+       SIMD_FORCE_INLINE operator const btScalar*() const { return &m_floats[0]; }
+
+       SIMD_FORCE_INLINE bool operator==(const btVector3& other) const
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+               return ((m_floats[3] == other.m_floats[3]) &&
+                               (m_floats[2] == other.m_floats[2]) &&
+                               (m_floats[1] == other.m_floats[1]) &&
+                               (m_floats[0] == other.m_floats[0]));
+#endif
+       }
+
+       SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const
+       {
+               return !(*this == other);
+       }
+
+       /**@brief Set each element to the max of the current values and the values of another btVector3
+   * @param other The other btVector3 to compare with 
+   */
+       SIMD_FORCE_INLINE void setMax(const btVector3& other)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               mVec128 = _mm_max_ps(mVec128, other.mVec128);
+#elif defined(BT_USE_NEON)
+               mVec128 = vmaxq_f32(mVec128, other.mVec128);
+#else
+               btSetMax(m_floats[0], other.m_floats[0]);
+               btSetMax(m_floats[1], other.m_floats[1]);
+               btSetMax(m_floats[2], other.m_floats[2]);
+               btSetMax(m_floats[3], other.w());
+#endif
+       }
+
+       /**@brief Set each element to the min of the current values and the values of another btVector3
+   * @param other The other btVector3 to compare with 
+   */
+       SIMD_FORCE_INLINE void setMin(const btVector3& other)
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               mVec128 = _mm_min_ps(mVec128, other.mVec128);
+#elif defined(BT_USE_NEON)
+               mVec128 = vminq_f32(mVec128, other.mVec128);
+#else
+               btSetMin(m_floats[0], other.m_floats[0]);
+               btSetMin(m_floats[1], other.m_floats[1]);
+               btSetMin(m_floats[2], other.m_floats[2]);
+               btSetMin(m_floats[3], other.w());
+#endif
+       }
+
+       SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+       {
+               m_floats[0] = _x;
+               m_floats[1] = _y;
+               m_floats[2] = _z;
+               m_floats[3] = btScalar(0.f);
+       }
+
+       void getSkewSymmetricMatrix(btVector3 * v0, btVector3 * v1, btVector3 * v2) const
+       {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+
+               __m128 V = _mm_and_ps(mVec128, btvFFF0fMask);
+               __m128 V0 = _mm_xor_ps(btvMzeroMask, V);
+               __m128 V2 = _mm_movelh_ps(V0, V);
+
+               __m128 V1 = _mm_shuffle_ps(V, V0, 0xCE);
+
+               V0 = _mm_shuffle_ps(V0, V, 0xDB);
+               V2 = _mm_shuffle_ps(V2, V, 0xF9);
+
+               v0->mVec128 = V0;
+               v1->mVec128 = V1;
+               v2->mVec128 = V2;
+#else
+               v0->setValue(0., -z(), y());
+               v1->setValue(z(), 0., -x());
+               v2->setValue(-y(), x(), 0.);
+#endif
+       }
+
+       void setZero()
+       {
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128);
+#elif defined(BT_USE_NEON)
+               int32x4_t vi = vdupq_n_s32(0);
+               mVec128 = vreinterpretq_f32_s32(vi);
+#else
+               setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+#endif
+       }
+
+       SIMD_FORCE_INLINE bool isZero() const
+       {
+               return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
+       }
+
+       SIMD_FORCE_INLINE bool fuzzyZero() const
+       {
+               return length2() < SIMD_EPSILON * SIMD_EPSILON;
+       }
+
+       SIMD_FORCE_INLINE void serialize(struct btVector3Data & dataOut) const;
+
+       SIMD_FORCE_INLINE void deSerialize(const struct btVector3DoubleData& dataIn);
+
+       SIMD_FORCE_INLINE void deSerialize(const struct btVector3FloatData& dataIn);
+
+       SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData & dataOut) const;
+
+       SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn);
+
+       SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData & dataOut) const;
+
+       SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn);
+
+       /**@brief returns index of maximum dot product between this and vectors in array[]
+         * @param array The other vectors 
+         * @param array_count The number of other vectors 
+         * @param dotOut The maximum dot product */
+       SIMD_FORCE_INLINE long maxDot(const btVector3* array, long array_count, btScalar& dotOut) const;
+
+       /**@brief returns index of minimum dot product between this and vectors in array[]
+         * @param array The other vectors 
+         * @param array_count The number of other vectors 
+         * @param dotOut The minimum dot product */
+       SIMD_FORCE_INLINE long minDot(const btVector3* array, long array_count, btScalar& dotOut) const;
+
+       /* create a vector as  btVector3( this->dot( btVector3 v0 ), this->dot( btVector3 v1), this->dot( btVector3 v2 ))  */
+       SIMD_FORCE_INLINE btVector3 dot3(const btVector3& v0, const btVector3& v1, const btVector3& v2) const
+       {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+
+               __m128 a0 = _mm_mul_ps(v0.mVec128, this->mVec128);
+               __m128 a1 = _mm_mul_ps(v1.mVec128, this->mVec128);
+               __m128 a2 = _mm_mul_ps(v2.mVec128, this->mVec128);
+               __m128 b0 = _mm_unpacklo_ps(a0, a1);
+               __m128 b1 = _mm_unpackhi_ps(a0, a1);
+               __m128 b2 = _mm_unpacklo_ps(a2, _mm_setzero_ps());
+               __m128 r = _mm_movelh_ps(b0, b2);
+               r = _mm_add_ps(r, _mm_movehl_ps(b2, b0));
+               a2 = _mm_and_ps(a2, btvxyzMaskf);
+               r = _mm_add_ps(r, btCastdTo128f(_mm_move_sd(btCastfTo128d(a2), btCastfTo128d(b1))));
+               return btVector3(r);
+
+#elif defined(BT_USE_NEON)
+               static const uint32x4_t xyzMask = (const uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0};
+               float32x4_t a0 = vmulq_f32(v0.mVec128, this->mVec128);
+               float32x4_t a1 = vmulq_f32(v1.mVec128, this->mVec128);
+               float32x4_t a2 = vmulq_f32(v2.mVec128, this->mVec128);
+               float32x2x2_t zLo = vtrn_f32(vget_high_f32(a0), vget_high_f32(a1));
+               a2 = (float32x4_t)vandq_u32((uint32x4_t)a2, xyzMask);
+               float32x2_t b0 = vadd_f32(vpadd_f32(vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0]);
+               float32x2_t b1 = vpadd_f32(vpadd_f32(vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
+               return btVector3(vcombine_f32(b0, b1));
+#else
+               return btVector3(dot(v0), dot(v1), dot(v2));
+#endif
+       }
+};
+
+/**@brief Return the sum of two vectors (Point symantics)*/
+SIMD_FORCE_INLINE btVector3
+operator+(const btVector3& v1, const btVector3& v2)
+{
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+       return btVector3(_mm_add_ps(v1.mVec128, v2.mVec128));
+#elif defined(BT_USE_NEON)
+       return btVector3(vaddq_f32(v1.mVec128, v2.mVec128));
+#else
+       return btVector3(
+               v1.m_floats[0] + v2.m_floats[0],
+               v1.m_floats[1] + v2.m_floats[1],
+               v1.m_floats[2] + v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the elementwise product of two vectors */
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v1, const btVector3& v2)
+{
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+       return btVector3(_mm_mul_ps(v1.mVec128, v2.mVec128));
+#elif defined(BT_USE_NEON)
+       return btVector3(vmulq_f32(v1.mVec128, v2.mVec128));
+#else
+       return btVector3(
+               v1.m_floats[0] * v2.m_floats[0],
+               v1.m_floats[1] * v2.m_floats[1],
+               v1.m_floats[2] * v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the difference between two vectors */
+SIMD_FORCE_INLINE btVector3
+operator-(const btVector3& v1, const btVector3& v2)
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+
+       //      without _mm_and_ps this code causes slowdown in Concave moving
+       __m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128);
+       return btVector3(_mm_and_ps(r, btvFFF0fMask));
+#elif defined(BT_USE_NEON)
+       float32x4_t r = vsubq_f32(v1.mVec128, v2.mVec128);
+       return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
+#else
+       return btVector3(
+               v1.m_floats[0] - v2.m_floats[0],
+               v1.m_floats[1] - v2.m_floats[1],
+               v1.m_floats[2] - v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the negative of the vector */
+SIMD_FORCE_INLINE btVector3
+operator-(const btVector3& v)
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+       __m128 r = _mm_xor_ps(v.mVec128, btvMzeroMask);
+       return btVector3(_mm_and_ps(r, btvFFF0fMask));
+#elif defined(BT_USE_NEON)
+       return btVector3((btSimdFloat4)veorq_s32((int32x4_t)v.mVec128, (int32x4_t)btvMzeroMask));
+#else
+       return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
+#endif
+}
+
+/**@brief Return the vector scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v, const btScalar& s)
+{
+#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+       __m128 vs = _mm_load_ss(&s);  //        (S 0 0 0)
+       vs = bt_pshufd_ps(vs, 0x80);  //        (S S S 0.0)
+       return btVector3(_mm_mul_ps(v.mVec128, vs));
+#elif defined(BT_USE_NEON)
+       float32x4_t r = vmulq_n_f32(v.mVec128, s);
+       return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
+#else
+       return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
+#endif
+}
+
+/**@brief Return the vector scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator*(const btScalar& s, const btVector3& v)
+{
+       return v * s;
+}
+
+/**@brief Return the vector inversely scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator/(const btVector3& v, const btScalar& s)
+{
+       btFullAssert(s != btScalar(0.0));
+#if 0  //defined(BT_USE_SSE_IN_API)
+// this code is not faster !
+       __m128 vs = _mm_load_ss(&s);
+    vs = _mm_div_ss(v1110, vs);
+       vs = bt_pshufd_ps(vs, 0x00);    //      (S S S S)
+
+       return btVector3(_mm_mul_ps(v.mVec128, vs));
+#else
+       return v * (btScalar(1.0) / s);
+#endif
+}
+
+/**@brief Return the vector inversely scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator/(const btVector3& v1, const btVector3& v2)
+{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+       __m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128);
+       vec = _mm_and_ps(vec, btvFFF0fMask);
+       return btVector3(vec);
+#elif defined(BT_USE_NEON)
+       float32x4_t x, y, v, m;
+
+       x = v1.mVec128;
+       y = v2.mVec128;
+
+       v = vrecpeq_f32(y);     // v ~ 1/y
+       m = vrecpsq_f32(y, v);  // m = (2-v*y)
+       v = vmulq_f32(v, m);    // vv = v*m ~~ 1/y
+       m = vrecpsq_f32(y, v);  // mm = (2-vv*y)
+       v = vmulq_f32(v, x);    // x*vv
+       v = vmulq_f32(v, m);    // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
+
+       return btVector3(v);
+#else
+       return btVector3(
+               v1.m_floats[0] / v2.m_floats[0],
+               v1.m_floats[1] / v2.m_floats[1],
+               v1.m_floats[2] / v2.m_floats[2]);
+#endif
+}
+
+/**@brief Return the dot product between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDot(const btVector3& v1, const btVector3& v2)
+{
+       return v1.dot(v2);
+}
+
+/**@brief Return the distance squared between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDistance2(const btVector3& v1, const btVector3& v2)
+{
+       return v1.distance2(v2);
+}
+
+/**@brief Return the distance between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDistance(const btVector3& v1, const btVector3& v2)
+{
+       return v1.distance(v2);
+}
+
+/**@brief Return the angle between two vectors */
+SIMD_FORCE_INLINE btScalar
+btAngle(const btVector3& v1, const btVector3& v2)
+{
+       return v1.angle(v2);
+}
+
+/**@brief Return the cross product of two vectors */
+SIMD_FORCE_INLINE btVector3
+btCross(const btVector3& v1, const btVector3& v2)
+{
+       return v1.cross(v2);
+}
+
+SIMD_FORCE_INLINE btScalar
+btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3)
+{
+       return v1.triple(v2, v3);
+}
+
+/**@brief Return the linear interpolation between two vectors
+ * @param v1 One vector 
+ * @param v2 The other vector 
+ * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
+SIMD_FORCE_INLINE btVector3
+lerp(const btVector3& v1, const btVector3& v2, const btScalar& t)
+{
+       return v1.lerp(v2, t);
+}
+
+SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const
+{
+       return (v - *this).length2();
+}
+
+SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const
+{
+       return (v - *this).length();
+}
+
+SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
+{
+       btVector3 nrm = *this;
+
+       return nrm.normalize();
+}
+
+SIMD_FORCE_INLINE btVector3 btVector3::rotate(const btVector3& wAxis, const btScalar _angle) const
+{
+       // wAxis must be a unit lenght vector
+
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+
+       __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
+       btScalar ssin = btSin(_angle);
+       __m128 C = wAxis.cross(mVec128).mVec128;
+       O = _mm_and_ps(O, btvFFF0fMask);
+       btScalar scos = btCos(_angle);
+
+       __m128 vsin = _mm_load_ss(&ssin);  //   (S 0 0 0)
+       __m128 vcos = _mm_load_ss(&scos);  //   (S 0 0 0)
+
+       __m128 Y = bt_pshufd_ps(O, 0xC9);  //   (Y Z X 0)
+       __m128 Z = bt_pshufd_ps(O, 0xD2);  //   (Z X Y 0)
+       O = _mm_add_ps(O, Y);
+       vsin = bt_pshufd_ps(vsin, 0x80);  //    (S S S 0)
+       O = _mm_add_ps(O, Z);
+       vcos = bt_pshufd_ps(vcos, 0x80);  //    (S S S 0)
+
+       vsin = vsin * C;
+       O = O * wAxis.mVec128;
+       __m128 X = mVec128 - O;
+
+       O = O + vsin;
+       vcos = vcos * X;
+       O = O + vcos;
+
+       return btVector3(O);
+#else
+       btVector3 o = wAxis * wAxis.dot(*this);
+       btVector3 _x = *this - o;
+       btVector3 _y;
+
+       _y = wAxis.cross(*this);
+
+       return (o + _x * btCos(_angle) + _y * btSin(_angle));
+#endif
+}
+
+SIMD_FORCE_INLINE long btVector3::maxDot(const btVector3* array, long array_count, btScalar& dotOut) const
+{
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
+#if defined _WIN32 || defined(BT_USE_SSE)
+       const long scalar_cutoff = 10;
+       long _maxdot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#elif defined BT_USE_NEON
+       const long scalar_cutoff = 4;
+       extern long (*_maxdot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#endif
+       if (array_count < scalar_cutoff)
+#endif
+       {
+               btScalar maxDot1 = -SIMD_INFINITY;
+               int i = 0;
+               int ptIndex = -1;
+               for (i = 0; i < array_count; i++)
+               {
+                       btScalar dot = array[i].dot(*this);
+
+                       if (dot > maxDot1)
+                       {
+                               maxDot1 = dot;
+                               ptIndex = i;
+                       }
+               }
+
+               dotOut = maxDot1;
+               return ptIndex;
+       }
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
+       return _maxdot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
+#endif
+}
+
+SIMD_FORCE_INLINE long btVector3::minDot(const btVector3* array, long array_count, btScalar& dotOut) const
+{
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
+#if defined BT_USE_SSE
+       const long scalar_cutoff = 10;
+       long _mindot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#elif defined BT_USE_NEON
+       const long scalar_cutoff = 4;
+       extern long (*_mindot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
+#else
+#error unhandled arch!
+#endif
+
+       if (array_count < scalar_cutoff)
+#endif
+       {
+               btScalar minDot = SIMD_INFINITY;
+               int i = 0;
+               int ptIndex = -1;
+
+               for (i = 0; i < array_count; i++)
+               {
+                       btScalar dot = array[i].dot(*this);
+
+                       if (dot < minDot)
+                       {
+                               minDot = dot;
+                               ptIndex = i;
+                       }
+               }
+
+               dotOut = minDot;
+
+               return ptIndex;
+       }
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
+       return _mindot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
+#endif  //BT_USE_SIMD_VECTOR3
+}
+
+class btVector4 : public btVector3
+{
+public:
+       SIMD_FORCE_INLINE btVector4() {}
+
+       SIMD_FORCE_INLINE btVector4(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+               : btVector3(_x, _y, _z)
+       {
+               m_floats[3] = _w;
+       }
+
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
+       SIMD_FORCE_INLINE btVector4(const btSimdFloat4 vec)
+       {
+               mVec128 = vec;
+       }
+
+       SIMD_FORCE_INLINE btVector4(const btVector3& rhs)
+       {
+               mVec128 = rhs.mVec128;
+       }
+
+       SIMD_FORCE_INLINE btVector4&
+       operator=(const btVector4& v)
+       {
+               mVec128 = v.mVec128;
+               return *this;
+       }
+#endif  // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+
+       SIMD_FORCE_INLINE btVector4 absolute4() const
+       {
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
+               return btVector4(_mm_and_ps(mVec128, btvAbsfMask));
+#elif defined(BT_USE_NEON)
+               return btVector4(vabsq_f32(mVec128));
+#else
+               return btVector4(
+                       btFabs(m_floats[0]),
+                       btFabs(m_floats[1]),
+                       btFabs(m_floats[2]),
+                       btFabs(m_floats[3]));
+#endif
+       }
+
+       btScalar getW() const { return m_floats[3]; }
+
+       SIMD_FORCE_INLINE int maxAxis4() const
+       {
+               int maxIndex = -1;
+               btScalar maxVal = btScalar(-BT_LARGE_FLOAT);
+               if (m_floats[0] > maxVal)
+               {
+                       maxIndex = 0;
+                       maxVal = m_floats[0];
+               }
+               if (m_floats[1] > maxVal)
+               {
+                       maxIndex = 1;
+                       maxVal = m_floats[1];
+               }
+               if (m_floats[2] > maxVal)
+               {
+                       maxIndex = 2;
+                       maxVal = m_floats[2];
+               }
+               if (m_floats[3] > maxVal)
+               {
+                       maxIndex = 3;
+               }
+
+               return maxIndex;
+       }
+
+       SIMD_FORCE_INLINE int minAxis4() const
+       {
+               int minIndex = -1;
+               btScalar minVal = btScalar(BT_LARGE_FLOAT);
+               if (m_floats[0] < minVal)
+               {
+                       minIndex = 0;
+                       minVal = m_floats[0];
+               }
+               if (m_floats[1] < minVal)
+               {
+                       minIndex = 1;
+                       minVal = m_floats[1];
+               }
+               if (m_floats[2] < minVal)
+               {
+                       minIndex = 2;
+                       minVal = m_floats[2];
+               }
+               if (m_floats[3] < minVal)
+               {
+                       minIndex = 3;
+               }
+
+               return minIndex;
+       }
+
+       SIMD_FORCE_INLINE int closestAxis4() const
+       {
+               return absolute4().maxAxis4();
+       }
+
+       /**@brief Set x,y,z and zero w 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+
+       /*              void getValue(btScalar *m) const 
+               {
+                       m[0] = m_floats[0];
+                       m[1] = m_floats[1];
+                       m[2] =m_floats[2];
+               }
+*/
+       /**@brief Set the values 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+       SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+       {
+               m_floats[0] = _x;
+               m_floats[1] = _y;
+               m_floats[2] = _z;
+               m_floats[3] = _w;
+       }
+};
+
+///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;
+       const unsigned char* src = (const 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;
+       const unsigned char* src = (const 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;
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btPlaneSpace1(const T& n, T& p, T& q)
+{
+       if (btFabs(n[2]) > SIMDSQRT12)
+       {
+               // choose p in y-z plane
+               btScalar a = n[1] * n[1] + n[2] * n[2];
+               btScalar k = btRecipSqrt(a);
+               p[0] = 0;
+               p[1] = -n[2] * k;
+               p[2] = n[1] * k;
+               // set q = n x p
+               q[0] = a * k;
+               q[1] = -n[0] * p[2];
+               q[2] = n[0] * p[1];
+       }
+       else
+       {
+               // choose p in x-y plane
+               btScalar a = n[0] * n[0] + n[1] * n[1];
+               btScalar k = btRecipSqrt(a);
+               p[0] = -n[1] * k;
+               p[1] = n[0] * k;
+               p[2] = 0;
+               // set q = n x p
+               q[0] = -n[2] * p[1];
+               q[1] = n[2] * p[0];
+               q[2] = a * k;
+       }
+}
+
+struct btVector3FloatData
+{
+       float m_floats[4];
+};
+
+struct btVector3DoubleData
+{
+       double m_floats[4];
+};
+
+SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const
+{
+       ///could also do a memcpy, check if it is worth it
+       for (int i = 0; i < 4; i++)
+               dataOut.m_floats[i] = float(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const
+{
+       ///could also do a memcpy, check if it is worth it
+       for (int i = 0; i < 4; i++)
+               dataOut.m_floats[i] = double(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const
+{
+       ///could also do a memcpy, check if it is worth it
+       for (int i = 0; i < 4; i++)
+               dataOut.m_floats[i] = m_floats[i];
+}
+
+SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3FloatData& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = (btScalar)dataIn.m_floats[i];
+}
+
+SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3DoubleData& dataIn)
+{
+       for (int i = 0; i < 4; i++)
+               m_floats[i] = (btScalar)dataIn.m_floats[i];
+}
+
+#endif  //BT_VECTOR3_H
diff --git a/dali-physics/third-party/bullet3/src/LinearMath/premake4.lua b/dali-physics/third-party/bullet3/src/LinearMath/premake4.lua
new file mode 100644 (file)
index 0000000..3765811
--- /dev/null
@@ -0,0 +1,15 @@
+       project "LinearMath"
+
+       kind "StaticLib"
+       if os.is("Linux") then
+           buildoptions{"-fPIC"}
+       end
+       includedirs {
+               "..",
+       }
+       files {
+               "*.cpp",
+               "*.h",
+               "TaskScheduler/*.cpp",
+               "TaskScheduler/*.h"
+       }
diff --git a/dali-physics/third-party/bullet3/src/btBulletCollisionAll.cpp b/dali-physics/third-party/bullet3/src/btBulletCollisionAll.cpp
new file mode 100644 (file)
index 0000000..4a3ec8d
--- /dev/null
@@ -0,0 +1,97 @@
+#include "BulletCollision/BroadphaseCollision/btAxisSweep3.cpp"
+#include "BulletCollision/BroadphaseCollision/btDbvt.cpp"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp"
+#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp"
+#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.cpp"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp"
+#include "BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp"
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp"
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp"
+#include "BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.cpp"
+#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp"
+#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp"
+#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp"
+#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.cpp"
+#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp"
+#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.cpp"
+#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp"
+#include "BulletCollision/CollisionDispatch/btUnionFind.cpp"
+#include "BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp"
+#include "BulletCollision/CollisionDispatch/btGhostObject.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp"
+#include "BulletCollision/CollisionShapes/btBox2dShape.cpp"
+#include "BulletCollision/CollisionShapes/btConvexPolyhedron.cpp"
+#include "BulletCollision/CollisionShapes/btShapeHull.cpp"
+#include "BulletCollision/CollisionShapes/btBoxShape.cpp"
+#include "BulletCollision/CollisionShapes/btConvexShape.cpp"
+#include "BulletCollision/CollisionShapes/btSphereShape.cpp"
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp"
+#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.cpp"
+#include "BulletCollision/CollisionShapes/btCylinderShape.cpp"
+#include "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp"
+#include "BulletCollision/CollisionShapes/btCollisionShape.cpp"
+#include "BulletCollision/CollisionShapes/btEmptyShape.cpp"
+#include "BulletCollision/CollisionShapes/btTetrahedronShape.cpp"
+#include "BulletCollision/CollisionShapes/btCompoundShape.cpp"
+#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleBuffer.cpp"
+#include "BulletCollision/CollisionShapes/btConcaveShape.cpp"
+#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.cpp"
+#include "BulletCollision/CollisionShapes/btConeShape.cpp"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp"
+#include "BulletCollision/CollisionShapes/btConvex2dShape.cpp"
+#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp"
+#include "BulletCollision/CollisionShapes/btConvexHullShape.cpp"
+#include "BulletCollision/CollisionShapes/btOptimizedBvh.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleMesh.cpp"
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.cpp"
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp"
+#include "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp"
+#include "BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp"
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp"
+#include "BulletCollision/CollisionShapes/btSdfCollisionShape.cpp"
+#include "BulletCollision/CollisionShapes/btMiniSDF.cpp"
+#include "BulletCollision/CollisionShapes/btUniformScalingShape.cpp"
+#include "BulletCollision/Gimpact/btContactProcessing.cpp"
+#include "BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp"
+#include "BulletCollision/Gimpact/btTriangleShapeEx.cpp"
+#include "BulletCollision/Gimpact/gim_memory.cpp"
+#include "BulletCollision/Gimpact/btGImpactBvh.cpp"
+#include "BulletCollision/Gimpact/btGImpactShape.cpp"
+#include "BulletCollision/Gimpact/gim_box_set.cpp"
+#include "BulletCollision/Gimpact/gim_tri_collision.cpp"
+#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp"
+#include "BulletCollision/Gimpact/btGenericPoolAllocator.cpp"
+#include "BulletCollision/Gimpact/gim_contact.cpp"
diff --git a/dali-physics/third-party/bullet3/src/btBulletCollisionCommon.h b/dali-physics/third-party/bullet3/src/btBulletCollisionCommon.h
new file mode 100644 (file)
index 0000000..2de34ad
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BULLET_COLLISION_COMMON_H
+#define BULLET_COLLISION_COMMON_H
+
+///Common headerfile includes for Bullet Collision Detection
+
+///Bullet's btCollisionWorld and btCollisionObject definitions
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+///Collision Shapes
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btCylinderShape.h"
+#include "BulletCollision/CollisionShapes/btConeShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleMesh.h"
+#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
+#include "BulletCollision/CollisionShapes/btEmptyShape.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btUniformScalingShape.h"
+
+///Narrowphase Collision Detector
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+
+//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
+
+///Dispatching and generation of collision pairs (broadphase)
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h"
+#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
+
+///Math library & Utils
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btDefaultMotionState.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btSerializer.h"
+
+#endif  //BULLET_COLLISION_COMMON_H
diff --git a/dali-physics/third-party/bullet3/src/btBulletDynamicsAll.cpp b/dali-physics/third-party/bullet3/src/btBulletDynamicsAll.cpp
new file mode 100644 (file)
index 0000000..6e73880
--- /dev/null
@@ -0,0 +1,43 @@
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp"
+#include "BulletDynamics/Dynamics/btRigidBody.cpp"
+#include "BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp"
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp"
+#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp"
+#include "BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btContactConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btFixedConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btGearConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp"
+#include "BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp"
+#include "BulletDynamics/MLCPSolvers/btDantzigLCP.cpp"
+#include "BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp"
+#include "BulletDynamics/MLCPSolvers/btMLCPSolver.cpp"
+#include "BulletDynamics/Featherstone/btMultiBody.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraint.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp"
+#include "BulletDynamics/Featherstone/btMultiBodySphericalJointLimit.cpp"
+#include "BulletDynamics/Vehicle/btRaycastVehicle.cpp"
+#include "BulletDynamics/Vehicle/btWheelInfo.cpp"
+#include "BulletDynamics/Character/btKinematicCharacterController.cpp"
+
diff --git a/dali-physics/third-party/bullet3/src/btBulletDynamicsCommon.h b/dali-physics/third-party/bullet3/src/btBulletDynamicsCommon.h
new file mode 100644 (file)
index 0000000..fef4380
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  https://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BULLET_DYNAMICS_COMMON_H
+#define BULLET_DYNAMICS_COMMON_H
+
+///Common headerfile includes for Bullet Dynamics, including Collision Detection
+#include "btBulletCollisionCommon.h"
+
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+
+#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btUniversalConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHinge2Constraint.h"
+#include "BulletDynamics/ConstraintSolver/btGearConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btFixedConstraint.h"
+
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+
+///Vehicle simulation, with wheel contact simulated by raycasts
+#include "BulletDynamics/Vehicle/btRaycastVehicle.h"
+
+#endif  //BULLET_DYNAMICS_COMMON_H
diff --git a/dali-physics/third-party/bullet3/src/btLinearMathAll.cpp b/dali-physics/third-party/bullet3/src/btLinearMathAll.cpp
new file mode 100644 (file)
index 0000000..d05a19e
--- /dev/null
@@ -0,0 +1,15 @@
+#include "LinearMath/btAlignedAllocator.cpp"
+#include "LinearMath/btGeometryUtil.cpp"
+#include "LinearMath/btSerializer.cpp"
+#include "LinearMath/btVector3.cpp"
+#include "LinearMath/btConvexHull.cpp"
+#include "LinearMath/btPolarDecomposition.cpp"
+#include "LinearMath/btSerializer64.cpp"
+#include "LinearMath/btConvexHullComputer.cpp"
+#include "LinearMath/btQuickprof.cpp"
+#include "LinearMath/btThreads.cpp"
+#include "LinearMath/btReducedVector.cpp"
+#include "LinearMath/TaskScheduler/btTaskScheduler.cpp"
+#include "LinearMath/TaskScheduler/btThreadSupportPosix.cpp"
+#include "LinearMath/TaskScheduler/btThreadSupportWin32.cpp"
+
diff --git a/dali-physics/third-party/bullet3/src/clew/clew.c b/dali-physics/third-party/bullet3/src/clew/clew.c
new file mode 100644 (file)
index 0000000..90caced
--- /dev/null
@@ -0,0 +1,374 @@
+//////////////////////////////////////////////////////////////////////////
+//  Copyright (c) 2009 Organic Vectory B.V.
+//  Written by George van Venrooij
+//
+//  Distributed under the Boost Software License, Version 1.0.
+//  (See accompanying file license.txt)
+//////////////////////////////////////////////////////////////////////////
+
+#include "clew.h"
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#define VC_EXTRALEAN
+#include <windows.h>
+
+typedef HMODULE CLEW_DYNLIB_HANDLE;
+
+#define CLEW_DYNLIB_OPEN LoadLibraryA
+#define CLEW_DYNLIB_CLOSE FreeLibrary
+#define CLEW_DYNLIB_IMPORT GetProcAddress
+#else
+#include <dlfcn.h>
+
+typedef void* CLEW_DYNLIB_HANDLE;
+
+#define CLEW_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL)
+#define CLEW_DYNLIB_CLOSE dlclose
+#define CLEW_DYNLIB_IMPORT dlsym
+#endif
+
+#include <stdlib.h>
+
+//! \brief module handle
+static CLEW_DYNLIB_HANDLE module = NULL;
+
+//  Variables holding function entry points
+PFNCLGETPLATFORMIDS __clewGetPlatformIDs = NULL;
+PFNCLGETPLATFORMINFO __clewGetPlatformInfo = NULL;
+PFNCLGETDEVICEIDS __clewGetDeviceIDs = NULL;
+PFNCLGETDEVICEINFO __clewGetDeviceInfo = NULL;
+PFNCLCREATECONTEXT __clewCreateContext = NULL;
+PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType = NULL;
+PFNCLRETAINCONTEXT __clewRetainContext = NULL;
+PFNCLRELEASECONTEXT __clewReleaseContext = NULL;
+PFNCLGETCONTEXTINFO __clewGetContextInfo = NULL;
+PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue = NULL;
+PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue = NULL;
+PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue = NULL;
+PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo = NULL;
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty = NULL;
+#endif
+PFNCLCREATEBUFFER __clewCreateBuffer = NULL;
+PFNCLCREATESUBBUFFER __clewCreateSubBuffer = NULL;
+PFNCLCREATEIMAGE2D __clewCreateImage2D = NULL;
+PFNCLCREATEIMAGE3D __clewCreateImage3D = NULL;
+PFNCLRETAINMEMOBJECT __clewRetainMemObject = NULL;
+PFNCLRELEASEMEMOBJECT __clewReleaseMemObject = NULL;
+PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats = NULL;
+PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo = NULL;
+PFNCLGETIMAGEINFO __clewGetImageInfo = NULL;
+PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback = NULL;
+PFNCLCREATESAMPLER __clewCreateSampler = NULL;
+PFNCLRETAINSAMPLER __clewRetainSampler = NULL;
+PFNCLRELEASESAMPLER __clewReleaseSampler = NULL;
+PFNCLGETSAMPLERINFO __clewGetSamplerInfo = NULL;
+PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource = NULL;
+PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary = NULL;
+PFNCLRETAINPROGRAM __clewRetainProgram = NULL;
+PFNCLRELEASEPROGRAM __clewReleaseProgram = NULL;
+PFNCLBUILDPROGRAM __clewBuildProgram = NULL;
+PFNCLUNLOADCOMPILER __clewUnloadCompiler = NULL;
+PFNCLGETPROGRAMINFO __clewGetProgramInfo = NULL;
+PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo = NULL;
+PFNCLCREATEKERNEL __clewCreateKernel = NULL;
+PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram = NULL;
+PFNCLRETAINKERNEL __clewRetainKernel = NULL;
+PFNCLRELEASEKERNEL __clewReleaseKernel = NULL;
+PFNCLSETKERNELARG __clewSetKernelArg = NULL;
+PFNCLGETKERNELINFO __clewGetKernelInfo = NULL;
+PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo = NULL;
+PFNCLWAITFOREVENTS __clewWaitForEvents = NULL;
+PFNCLGETEVENTINFO __clewGetEventInfo = NULL;
+PFNCLCREATEUSEREVENT __clewCreateUserEvent = NULL;
+PFNCLRETAINEVENT __clewRetainEvent = NULL;
+PFNCLRELEASEEVENT __clewReleaseEvent = NULL;
+PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus = NULL;
+PFNCLSETEVENTCALLBACK __clewSetEventCallback = NULL;
+PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo = NULL;
+PFNCLFLUSH __clewFlush = NULL;
+PFNCLFINISH __clewFinish = NULL;
+PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer = NULL;
+PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect = NULL;
+PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer = NULL;
+PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect = NULL;
+PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer = NULL;
+PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage = NULL;
+PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage = NULL;
+PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage = NULL;
+PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect = NULL;
+PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer = NULL;
+PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage = NULL;
+PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer = NULL;
+PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage = NULL;
+PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject = NULL;
+PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel = NULL;
+PFNCLENQUEUETASK __clewEnqueueTask = NULL;
+PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel = NULL;
+PFNCLENQUEUEMARKER __clewEnqueueMarker = NULL;
+PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents = NULL;
+PFNCLENQUEUEBARRIER __clewEnqueueBarrier = NULL;
+PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress = NULL;
+
+void clewExit(void)
+{
+       if (module != NULL)
+       {
+               //  Ignore errors
+               CLEW_DYNLIB_CLOSE(module);
+               module = NULL;
+       }
+}
+
+int clewInit(const char* path)
+{
+       int error = 0;
+
+       //  Check if already initialized
+       if (module != NULL)
+       {
+               return CLEW_SUCCESS;
+       }
+
+       //  Load library
+       module = CLEW_DYNLIB_OPEN(path);
+
+       //  Check for errors
+       if (module == NULL)
+       {
+               return CLEW_ERROR_OPEN_FAILED;
+       }
+
+       //  Set unloading
+       error = atexit(clewExit);
+
+       if (error)
+       {
+               //  Failure queuing atexit, shutdown with error
+               CLEW_DYNLIB_CLOSE(module);
+               module = NULL;
+
+               return CLEW_ERROR_ATEXIT_FAILED;
+       }
+
+       //  Determine function entry-points
+       __clewGetPlatformIDs = (PFNCLGETPLATFORMIDS)CLEW_DYNLIB_IMPORT(module, "clGetPlatformIDs");
+       __clewGetPlatformInfo = (PFNCLGETPLATFORMINFO)CLEW_DYNLIB_IMPORT(module, "clGetPlatformInfo");
+       __clewGetDeviceIDs = (PFNCLGETDEVICEIDS)CLEW_DYNLIB_IMPORT(module, "clGetDeviceIDs");
+       __clewGetDeviceInfo = (PFNCLGETDEVICEINFO)CLEW_DYNLIB_IMPORT(module, "clGetDeviceInfo");
+       __clewCreateContext = (PFNCLCREATECONTEXT)CLEW_DYNLIB_IMPORT(module, "clCreateContext");
+       __clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE)CLEW_DYNLIB_IMPORT(module, "clCreateContextFromType");
+       __clewRetainContext = (PFNCLRETAINCONTEXT)CLEW_DYNLIB_IMPORT(module, "clRetainContext");
+       __clewReleaseContext = (PFNCLRELEASECONTEXT)CLEW_DYNLIB_IMPORT(module, "clReleaseContext");
+       __clewGetContextInfo = (PFNCLGETCONTEXTINFO)CLEW_DYNLIB_IMPORT(module, "clGetContextInfo");
+       __clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE)CLEW_DYNLIB_IMPORT(module, "clCreateCommandQueue");
+       __clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE)CLEW_DYNLIB_IMPORT(module, "clRetainCommandQueue");
+       __clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE)CLEW_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
+       __clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO)CLEW_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+       __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY)CLEW_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
+#endif
+       __clewCreateBuffer = (PFNCLCREATEBUFFER)CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
+       __clewCreateSubBuffer = (PFNCLCREATESUBBUFFER)CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
+       __clewCreateImage2D = (PFNCLCREATEIMAGE2D)CLEW_DYNLIB_IMPORT(module, "clCreateImage2D");
+       __clewCreateImage3D = (PFNCLCREATEIMAGE3D)CLEW_DYNLIB_IMPORT(module, "clCreateImage3D");
+       __clewRetainMemObject = (PFNCLRETAINMEMOBJECT)CLEW_DYNLIB_IMPORT(module, "clRetainMemObject");
+       __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT)CLEW_DYNLIB_IMPORT(module, "clReleaseMemObject");
+       __clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS)CLEW_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
+       __clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO)CLEW_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
+       __clewGetImageInfo = (PFNCLGETIMAGEINFO)CLEW_DYNLIB_IMPORT(module, "clGetImageInfo");
+       __clewSetMemObjectDestructorCallback = (PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)CLEW_DYNLIB_IMPORT(module, "clSetMemObjectDestructorCallback");
+       __clewCreateSampler = (PFNCLCREATESAMPLER)CLEW_DYNLIB_IMPORT(module, "clCreateSampler");
+       __clewRetainSampler = (PFNCLRETAINSAMPLER)CLEW_DYNLIB_IMPORT(module, "clRetainSampler");
+       __clewReleaseSampler = (PFNCLRELEASESAMPLER)CLEW_DYNLIB_IMPORT(module, "clReleaseSampler");
+       __clewGetSamplerInfo = (PFNCLGETSAMPLERINFO)CLEW_DYNLIB_IMPORT(module, "clGetSamplerInfo");
+       __clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE)CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
+       __clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY)CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
+       __clewRetainProgram = (PFNCLRETAINPROGRAM)CLEW_DYNLIB_IMPORT(module, "clRetainProgram");
+       __clewReleaseProgram = (PFNCLRELEASEPROGRAM)CLEW_DYNLIB_IMPORT(module, "clReleaseProgram");
+       __clewBuildProgram = (PFNCLBUILDPROGRAM)CLEW_DYNLIB_IMPORT(module, "clBuildProgram");
+       __clewUnloadCompiler = (PFNCLUNLOADCOMPILER)CLEW_DYNLIB_IMPORT(module, "clUnloadCompiler");
+       __clewGetProgramInfo = (PFNCLGETPROGRAMINFO)CLEW_DYNLIB_IMPORT(module, "clGetProgramInfo");
+       __clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO)CLEW_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
+       __clewCreateKernel = (PFNCLCREATEKERNEL)CLEW_DYNLIB_IMPORT(module, "clCreateKernel");
+       __clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM)CLEW_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
+       __clewRetainKernel = (PFNCLRETAINKERNEL)CLEW_DYNLIB_IMPORT(module, "clRetainKernel");
+       __clewReleaseKernel = (PFNCLRELEASEKERNEL)CLEW_DYNLIB_IMPORT(module, "clReleaseKernel");
+       __clewSetKernelArg = (PFNCLSETKERNELARG)CLEW_DYNLIB_IMPORT(module, "clSetKernelArg");
+       __clewGetKernelInfo = (PFNCLGETKERNELINFO)CLEW_DYNLIB_IMPORT(module, "clGetKernelInfo");
+       __clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO)CLEW_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
+       __clewWaitForEvents = (PFNCLWAITFOREVENTS)CLEW_DYNLIB_IMPORT(module, "clWaitForEvents");
+       __clewGetEventInfo = (PFNCLGETEVENTINFO)CLEW_DYNLIB_IMPORT(module, "clGetEventInfo");
+       __clewCreateUserEvent = (PFNCLCREATEUSEREVENT)CLEW_DYNLIB_IMPORT(module, "clCreateUserEvent");
+       __clewRetainEvent = (PFNCLRETAINEVENT)CLEW_DYNLIB_IMPORT(module, "clRetainEvent");
+       __clewReleaseEvent = (PFNCLRELEASEEVENT)CLEW_DYNLIB_IMPORT(module, "clReleaseEvent");
+       __clewSetUserEventStatus = (PFNCLSETUSEREVENTSTATUS)CLEW_DYNLIB_IMPORT(module, "clSetUserEventStatus");
+       __clewSetEventCallback = (PFNCLSETEVENTCALLBACK)CLEW_DYNLIB_IMPORT(module, "clSetEventCallback");
+       __clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO)CLEW_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
+       __clewFlush = (PFNCLFLUSH)CLEW_DYNLIB_IMPORT(module, "clFlush");
+       __clewFinish = (PFNCLFINISH)CLEW_DYNLIB_IMPORT(module, "clFinish");
+       __clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
+       __clewEnqueueReadBufferRect = (PFNCLENQUEUEREADBUFFERRECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBufferRect");
+       __clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
+       __clewEnqueueWriteBufferRect = (PFNCLENQUEUEWRITEBUFFERRECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBufferRect");
+       __clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
+       __clewEnqueueCopyBufferRect = (PFNCLENQUEUECOPYBUFFERRECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferRect");
+       __clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueReadImage");
+       __clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
+       __clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
+       __clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
+       __clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
+       __clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
+       __clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueMapImage");
+       __clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
+       __clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL)CLEW_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
+       __clewEnqueueTask = (PFNCLENQUEUETASK)CLEW_DYNLIB_IMPORT(module, "clEnqueueTask");
+       __clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL)CLEW_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
+       __clewEnqueueMarker = (PFNCLENQUEUEMARKER)CLEW_DYNLIB_IMPORT(module, "clEnqueueMarker");
+       __clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS)CLEW_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
+       __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER)CLEW_DYNLIB_IMPORT(module, "clEnqueueBarrier");
+       __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS)CLEW_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
+
+       return CLEW_SUCCESS;
+}
+
+const char* clewErrorString(cl_int error)
+{
+       static const char* strings[] =
+               {
+                       // Error Codes
+                       "CL_SUCCESS"  //   0
+                       ,
+                       "CL_DEVICE_NOT_FOUND"  //  -1
+                       ,
+                       "CL_DEVICE_NOT_AVAILABLE"  //  -2
+                       ,
+                       "CL_COMPILER_NOT_AVAILABLE"  //  -3
+                       ,
+                       "CL_MEM_OBJECT_ALLOCATION_FAILURE"  //  -4
+                       ,
+                       "CL_OUT_OF_RESOURCES"  //  -5
+                       ,
+                       "CL_OUT_OF_HOST_MEMORY"  //  -6
+                       ,
+                       "CL_PROFILING_INFO_NOT_AVAILABLE"  //  -7
+                       ,
+                       "CL_MEM_COPY_OVERLAP"  //  -8
+                       ,
+                       "CL_IMAGE_FORMAT_MISMATCH"  //  -9
+                       ,
+                       "CL_IMAGE_FORMAT_NOT_SUPPORTED"  //  -10
+                       ,
+                       "CL_BUILD_PROGRAM_FAILURE"  //  -11
+                       ,
+                       "CL_MAP_FAILURE"  //  -12
+
+                       ,
+                       ""  //  -13
+                       ,
+                       ""  //  -14
+                       ,
+                       ""  //  -15
+                       ,
+                       ""  //  -16
+                       ,
+                       ""  //  -17
+                       ,
+                       ""  //  -18
+                       ,
+                       ""  //  -19
+
+                       ,
+                       ""  //  -20
+                       ,
+                       ""  //  -21
+                       ,
+                       ""  //  -22
+                       ,
+                       ""  //  -23
+                       ,
+                       ""  //  -24
+                       ,
+                       ""  //  -25
+                       ,
+                       ""  //  -26
+                       ,
+                       ""  //  -27
+                       ,
+                       ""  //  -28
+                       ,
+                       ""  //  -29
+
+                       ,
+                       "CL_INVALID_VALUE"  //  -30
+                       ,
+                       "CL_INVALID_DEVICE_TYPE"  //  -31
+                       ,
+                       "CL_INVALID_PLATFORM"  //  -32
+                       ,
+                       "CL_INVALID_DEVICE"  //  -33
+                       ,
+                       "CL_INVALID_CONTEXT"  //  -34
+                       ,
+                       "CL_INVALID_QUEUE_PROPERTIES"  //  -35
+                       ,
+                       "CL_INVALID_COMMAND_QUEUE"  //  -36
+                       ,
+                       "CL_INVALID_HOST_PTR"  //  -37
+                       ,
+                       "CL_INVALID_MEM_OBJECT"  //  -38
+                       ,
+                       "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR"  //  -39
+                       ,
+                       "CL_INVALID_IMAGE_SIZE"  //  -40
+                       ,
+                       "CL_INVALID_SAMPLER"  //  -41
+                       ,
+                       "CL_INVALID_BINARY"  //  -42
+                       ,
+                       "CL_INVALID_BUILD_OPTIONS"  //  -43
+                       ,
+                       "CL_INVALID_PROGRAM"  //  -44
+                       ,
+                       "CL_INVALID_PROGRAM_EXECUTABLE"  //  -45
+                       ,
+                       "CL_INVALID_KERNEL_NAME"  //  -46
+                       ,
+                       "CL_INVALID_KERNEL_DEFINITION"  //  -47
+                       ,
+                       "CL_INVALID_KERNEL"  //  -48
+                       ,
+                       "CL_INVALID_ARG_INDEX"  //  -49
+                       ,
+                       "CL_INVALID_ARG_VALUE"  //  -50
+                       ,
+                       "CL_INVALID_ARG_SIZE"  //  -51
+                       ,
+                       "CL_INVALID_KERNEL_ARGS"  //  -52
+                       ,
+                       "CL_INVALID_WORK_DIMENSION"  //  -53
+                       ,
+                       "CL_INVALID_WORK_GROUP_SIZE"  //  -54
+                       ,
+                       "CL_INVALID_WORK_ITEM_SIZE"  //  -55
+                       ,
+                       "CL_INVALID_GLOBAL_OFFSET"  //  -56
+                       ,
+                       "CL_INVALID_EVENT_WAIT_LIST"  //  -57
+                       ,
+                       "CL_INVALID_EVENT"  //  -58
+                       ,
+                       "CL_INVALID_OPERATION"  //  -59
+                       ,
+                       "CL_INVALID_GL_OBJECT"  //  -60
+                       ,
+                       "CL_INVALID_BUFFER_SIZE"  //  -61
+                       ,
+                       "CL_INVALID_MIP_LEVEL"  //  -62
+                       ,
+                       "CL_INVALID_GLOBAL_WORK_SIZE"  //  -63
+               };
+
+       return strings[-error];
+}
diff --git a/dali-physics/third-party/bullet3/src/clew/clew.h b/dali-physics/third-party/bullet3/src/clew/clew.h
new file mode 100644 (file)
index 0000000..cba8585
--- /dev/null
@@ -0,0 +1,2708 @@
+#ifndef CLEW_HPP_INCLUDED
+#define CLEW_HPP_INCLUDED
+
+//////////////////////////////////////////////////////////////////////////
+//  Copyright (c) 2009-2011 Organic Vectory B.V., KindDragon
+//  Written by George van Venrooij
+//
+//  Distributed under the MIT License.
+//////////////////////////////////////////////////////////////////////////
+
+//! \file clew.h
+//! \brief OpenCL run-time loader header
+//!
+//! This file contains a copy of the contents of CL.H and CL_PLATFORM.H from the
+//! official OpenCL spec. The purpose of this code is to load the OpenCL dynamic
+//! library at run-time and thus allow the executable to function on many
+//! platforms regardless of the vendor of the OpenCL driver actually installed.
+//! Some of the techniques used here were inspired by work done in the GLEW
+//! library (http://glew.sourceforge.net/)
+
+//  Run-time dynamic linking functionality based on concepts used in GLEW
+#ifdef __OPENCL_CL_H
+#error cl.h included before clew.h
+#endif
+
+#ifdef __OPENCL_CL_PLATFORM_H
+#error cl_platform.h included before clew.h
+#endif
+
+//  Prevent cl.h inclusion
+#define __OPENCL_CL_H
+//  Prevent cl_platform.h inclusion
+#define __CL_PLATFORM_H
+
+/*******************************************************************************
+* Copyright (c) 2008-2010 The Khronos Group Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and/or associated documentation files (the
+* "Materials"), to deal in the Materials without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Materials, and to
+* permit persons to whom the Materials are furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Materials.
+*
+* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+******************************************************************************/
+#ifdef __APPLE__
+/* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */
+#include <AvailabilityMacros.h>
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if defined(_WIN32)
+#define CL_API_ENTRY
+#define CL_API_CALL __stdcall
+#define CL_CALLBACK __stdcall
+#else
+#define CL_API_ENTRY
+#define CL_API_CALL
+#define CL_CALLBACK
+#endif
+       //disabled the APPLE thing, don't know why it is there, is just causes tons of warnings
+
+#ifdef __APPLE1__
+#define CL_EXTENSION_WEAK_LINK __attribute__((weak_import))
+#define CL_API_SUFFIX__VERSION_1_0 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+#define CL_EXT_SUFFIX__VERSION_1_0 CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+#define CL_API_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
+#define CL_EXT_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
+#define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
+#else
+#define CL_EXTENSION_WEAK_LINK
+#define CL_API_SUFFIX__VERSION_1_0
+#define CL_EXT_SUFFIX__VERSION_1_0
+#define CL_API_SUFFIX__VERSION_1_1
+#define CL_EXT_SUFFIX__VERSION_1_1
+#define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED
+#endif
+
+#if (defined(_WIN32) && defined(_MSC_VER))
+
+       /* scalar types  */
+       typedef signed __int8 cl_char;
+       typedef unsigned __int8 cl_uchar;
+       typedef signed __int16 cl_short;
+       typedef unsigned __int16 cl_ushort;
+       typedef signed __int32 cl_int;
+       typedef unsigned __int32 cl_uint;
+       typedef signed __int64 cl_long;
+       typedef unsigned __int64 cl_ulong;
+
+       typedef unsigned __int16 cl_half;
+       typedef float cl_float;
+       typedef double cl_double;
+
+/* Macro names and corresponding values defined by OpenCL */
+#define CL_CHAR_BIT 8
+#define CL_SCHAR_MAX 127
+#define CL_SCHAR_MIN (-127 - 1)
+#define CL_CHAR_MAX CL_SCHAR_MAX
+#define CL_CHAR_MIN CL_SCHAR_MIN
+#define CL_UCHAR_MAX 255
+#define CL_SHRT_MAX 32767
+#define CL_SHRT_MIN (-32767 - 1)
+#define CL_USHRT_MAX 65535
+#define CL_INT_MAX 2147483647
+#define CL_INT_MIN (-2147483647 - 1)
+#define CL_UINT_MAX 0xffffffffU
+#define CL_LONG_MAX ((cl_long)0x7FFFFFFFFFFFFFFFLL)
+#define CL_LONG_MIN ((cl_long)-0x7FFFFFFFFFFFFFFFLL - 1LL)
+#define CL_ULONG_MAX ((cl_ulong)0xFFFFFFFFFFFFFFFFULL)
+
+#define CL_FLT_DIG 6
+#define CL_FLT_MANT_DIG 24
+#define CL_FLT_MAX_10_EXP +38
+#define CL_FLT_MAX_EXP +128
+#define CL_FLT_MIN_10_EXP -37
+#define CL_FLT_MIN_EXP -125
+#define CL_FLT_RADIX 2
+#define CL_FLT_MAX 340282346638528859811704183484516925440.0f
+#define CL_FLT_MIN 1.175494350822287507969e-38f
+#define CL_FLT_EPSILON 0x1.0p-23f
+
+#define CL_DBL_DIG 15
+#define CL_DBL_MANT_DIG 53
+#define CL_DBL_MAX_10_EXP +308
+#define CL_DBL_MAX_EXP +1024
+#define CL_DBL_MIN_10_EXP -307
+#define CL_DBL_MIN_EXP -1021
+#define CL_DBL_RADIX 2
+#define CL_DBL_MAX 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0
+#define CL_DBL_MIN 2.225073858507201383090e-308
+#define CL_DBL_EPSILON 2.220446049250313080847e-16
+
+#define CL_M_E 2.718281828459045090796
+#define CL_M_LOG2E 1.442695040888963387005
+#define CL_M_LOG10E 0.434294481903251816668
+#define CL_M_LN2 0.693147180559945286227
+#define CL_M_LN10 2.302585092994045901094
+#define CL_M_PI 3.141592653589793115998
+#define CL_M_PI_2 1.570796326794896557999
+#define CL_M_PI_4 0.785398163397448278999
+#define CL_M_1_PI 0.318309886183790691216
+#define CL_M_2_PI 0.636619772367581382433
+#define CL_M_2_SQRTPI 1.128379167095512558561
+#define CL_M_SQRT2 1.414213562373095145475
+#define CL_M_SQRT1_2 0.707106781186547572737
+
+#define CL_M_E_F 2.71828174591064f
+#define CL_M_LOG2E_F 1.44269502162933f
+#define CL_M_LOG10E_F 0.43429449200630f
+#define CL_M_LN2_F 0.69314718246460f
+#define CL_M_LN10_F 2.30258512496948f
+#define CL_M_PI_F 3.14159274101257f
+#define CL_M_PI_2_F 1.57079637050629f
+#define CL_M_PI_4_F 0.78539818525314f
+#define CL_M_1_PI_F 0.31830987334251f
+#define CL_M_2_PI_F 0.63661974668503f
+#define CL_M_2_SQRTPI_F 1.12837922573090f
+#define CL_M_SQRT2_F 1.41421353816986f
+#define CL_M_SQRT1_2_F 0.70710676908493f
+
+#define CL_NAN (CL_INFINITY - CL_INFINITY)
+#define CL_HUGE_VALF ((cl_float)1e50)
+#define CL_HUGE_VAL ((cl_double)1e500)
+#define CL_MAXFLOAT CL_FLT_MAX
+#define CL_INFINITY CL_HUGE_VALF
+
+#else
+
+#include <stdint.h>
+
+/* scalar types  */
+typedef int8_t cl_char;
+typedef uint8_t cl_uchar;
+typedef int16_t cl_short __attribute__((aligned(2)));
+typedef uint16_t cl_ushort __attribute__((aligned(2)));
+typedef int32_t cl_int __attribute__((aligned(4)));
+typedef uint32_t cl_uint __attribute__((aligned(4)));
+typedef int64_t cl_long __attribute__((aligned(8)));
+typedef uint64_t cl_ulong __attribute__((aligned(8)));
+
+typedef uint16_t cl_half __attribute__((aligned(2)));
+typedef float cl_float __attribute__((aligned(4)));
+typedef double cl_double __attribute__((aligned(8)));
+
+/* Macro names and corresponding values defined by OpenCL */
+#define CL_CHAR_BIT 8
+#define CL_SCHAR_MAX 127
+#define CL_SCHAR_MIN (-127 - 1)
+#define CL_CHAR_MAX CL_SCHAR_MAX
+#define CL_CHAR_MIN CL_SCHAR_MIN
+#define CL_UCHAR_MAX 255
+#define CL_SHRT_MAX 32767
+#define CL_SHRT_MIN (-32767 - 1)
+#define CL_USHRT_MAX 65535
+#define CL_INT_MAX 2147483647
+#define CL_INT_MIN (-2147483647 - 1)
+#define CL_UINT_MAX 0xffffffffU
+#define CL_LONG_MAX ((cl_long)0x7FFFFFFFFFFFFFFFLL)
+#define CL_LONG_MIN ((cl_long)-0x7FFFFFFFFFFFFFFFLL - 1LL)
+#define CL_ULONG_MAX ((cl_ulong)0xFFFFFFFFFFFFFFFFULL)
+
+#define CL_FLT_DIG 6
+#define CL_FLT_MANT_DIG 24
+#define CL_FLT_MAX_10_EXP +38
+#define CL_FLT_MAX_EXP +128
+#define CL_FLT_MIN_10_EXP -37
+#define CL_FLT_MIN_EXP -125
+#define CL_FLT_RADIX 2
+#define CL_FLT_MAX 0x1.fffffep127f
+#define CL_FLT_MIN 0x1.0p-126f
+#define CL_FLT_EPSILON 0x1.0p-23f
+
+#define CL_DBL_DIG 15
+#define CL_DBL_MANT_DIG 53
+#define CL_DBL_MAX_10_EXP +308
+#define CL_DBL_MAX_EXP +1024
+#define CL_DBL_MIN_10_EXP -307
+#define CL_DBL_MIN_EXP -1021
+#define CL_DBL_RADIX 2
+#define CL_DBL_MAX 0x1.fffffffffffffp1023
+#define CL_DBL_MIN 0x1.0p-1022
+#define CL_DBL_EPSILON 0x1.0p-52
+
+#define CL_M_E 2.718281828459045090796
+#define CL_M_LOG2E 1.442695040888963387005
+#define CL_M_LOG10E 0.434294481903251816668
+#define CL_M_LN2 0.693147180559945286227
+#define CL_M_LN10 2.302585092994045901094
+#define CL_M_PI 3.141592653589793115998
+#define CL_M_PI_2 1.570796326794896557999
+#define CL_M_PI_4 0.785398163397448278999
+#define CL_M_1_PI 0.318309886183790691216
+#define CL_M_2_PI 0.636619772367581382433
+#define CL_M_2_SQRTPI 1.128379167095512558561
+#define CL_M_SQRT2 1.414213562373095145475
+#define CL_M_SQRT1_2 0.707106781186547572737
+
+#define CL_M_E_F 2.71828174591064f
+#define CL_M_LOG2E_F 1.44269502162933f
+#define CL_M_LOG10E_F 0.43429449200630f
+#define CL_M_LN2_F 0.69314718246460f
+#define CL_M_LN10_F 2.30258512496948f
+#define CL_M_PI_F 3.14159274101257f
+#define CL_M_PI_2_F 1.57079637050629f
+#define CL_M_PI_4_F 0.78539818525314f
+#define CL_M_1_PI_F 0.31830987334251f
+#define CL_M_2_PI_F 0.63661974668503f
+#define CL_M_2_SQRTPI_F 1.12837922573090f
+#define CL_M_SQRT2_F 1.41421353816986f
+#define CL_M_SQRT1_2_F 0.70710676908493f
+
+#if defined(__GNUC__)
+#define CL_HUGE_VALF __builtin_huge_valf()
+#define CL_HUGE_VAL __builtin_huge_val()
+#define CL_NAN __builtin_nanf("")
+#else
+#define CL_HUGE_VALF ((cl_float)1e50)
+#define CL_HUGE_VAL ((cl_double)1e500)
+float nanf(const char *);
+#define CL_NAN nanf("")
+#endif
+#define CL_MAXFLOAT CL_FLT_MAX
+#define CL_INFINITY CL_HUGE_VALF
+
+#endif
+
+#include <stddef.h>
+
+       /* Mirror types to GL types. Mirror types allow us to avoid deciding which headers to load based on whether we are using GL or GLES here. */
+       typedef unsigned int cl_GLuint;
+       typedef int cl_GLint;
+       typedef unsigned int cl_GLenum;
+
+       /*
+ * Vector types 
+ *
+ *  Note:   OpenCL requires that all types be naturally aligned. 
+ *          This means that vector types must be naturally aligned.
+ *          For example, a vector of four floats must be aligned to
+ *          a 16 byte boundary (calculated as 4 * the natural 4-byte 
+ *          alignment of the float).  The alignment qualifiers here
+ *          will only function properly if your compiler supports them
+ *          and if you don't actively work to defeat them.  For example,
+ *          in order for a cl_float4 to be 16 byte aligned in a struct,
+ *          the start of the struct must itself be 16-byte aligned. 
+ *
+ *          Maintaining proper alignment is the user's responsibility.
+ */
+
+#ifdef _MSC_VER
+#if defined(_M_IX86)
+#if _M_IX86_FP >= 0
+#define __SSE__
+#endif
+#if _M_IX86_FP >= 1
+#define __SSE2__
+#endif
+#elif defined(_M_X64)
+#define __SSE__
+#define __SSE2__
+#endif
+#endif
+
+/* Define basic vector types */
+#if defined(__VEC__)
+#include <altivec.h> /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */
+       typedef vector unsigned char __cl_uchar16;
+       typedef vector signed char __cl_char16;
+       typedef vector unsigned short __cl_ushort8;
+       typedef vector signed short __cl_short8;
+       typedef vector unsigned int __cl_uint4;
+       typedef vector signed int __cl_int4;
+       typedef vector float __cl_float4;
+#define __CL_UCHAR16__ 1
+#define __CL_CHAR16__ 1
+#define __CL_USHORT8__ 1
+#define __CL_SHORT8__ 1
+#define __CL_UINT4__ 1
+#define __CL_INT4__ 1
+#define __CL_FLOAT4__ 1
+#endif
+
+#if defined(__SSE__)
+#if defined(__MINGW64__)
+#include <intrin.h>
+#else
+#include <xmmintrin.h>
+#endif
+#if defined(__GNUC__) && !defined(__ICC)
+       typedef float __cl_float4 __attribute__((vector_size(16)));
+#else
+       typedef __m128 __cl_float4;
+#endif
+#define __CL_FLOAT4__ 1
+#endif
+
+#if defined(__SSE2__)
+#if defined(__MINGW64__)
+#include <intrin.h>
+#else
+#include <emmintrin.h>
+#endif
+#if defined(__GNUC__) && !defined(__ICC)
+       typedef cl_uchar __cl_uchar16 __attribute__((vector_size(16)));
+       typedef cl_char __cl_char16 __attribute__((vector_size(16)));
+       typedef cl_ushort __cl_ushort8 __attribute__((vector_size(16)));
+       typedef cl_short __cl_short8 __attribute__((vector_size(16)));
+       typedef cl_uint __cl_uint4 __attribute__((vector_size(16)));
+       typedef cl_int __cl_int4 __attribute__((vector_size(16)));
+       typedef cl_ulong __cl_ulong2 __attribute__((vector_size(16)));
+       typedef cl_long __cl_long2 __attribute__((vector_size(16)));
+       typedef cl_double __cl_double2 __attribute__((vector_size(16)));
+#else
+       typedef __m128i __cl_uchar16;
+       typedef __m128i __cl_char16;
+       typedef __m128i __cl_ushort8;
+       typedef __m128i __cl_short8;
+       typedef __m128i __cl_uint4;
+       typedef __m128i __cl_int4;
+       typedef __m128i __cl_ulong2;
+       typedef __m128i __cl_long2;
+       typedef __m128d __cl_double2;
+#endif
+#define __CL_UCHAR16__ 1
+#define __CL_CHAR16__ 1
+#define __CL_USHORT8__ 1
+#define __CL_SHORT8__ 1
+#define __CL_INT4__ 1
+#define __CL_UINT4__ 1
+#define __CL_ULONG2__ 1
+#define __CL_LONG2__ 1
+#define __CL_DOUBLE2__ 1
+#endif
+
+#if defined(__MMX__)
+#include <mmintrin.h>
+#if defined(__GNUC__) && !defined(__ICC)
+       typedef cl_uchar __cl_uchar8 __attribute__((vector_size(8)));
+       typedef cl_char __cl_char8 __attribute__((vector_size(8)));
+       typedef cl_ushort __cl_ushort4 __attribute__((vector_size(8)));
+       typedef cl_short __cl_short4 __attribute__((vector_size(8)));
+       typedef cl_uint __cl_uint2 __attribute__((vector_size(8)));
+       typedef cl_int __cl_int2 __attribute__((vector_size(8)));
+       typedef cl_ulong __cl_ulong1 __attribute__((vector_size(8)));
+       typedef cl_long __cl_long1 __attribute__((vector_size(8)));
+       typedef cl_float __cl_float2 __attribute__((vector_size(8)));
+#else
+       typedef __m64 __cl_uchar8;
+       typedef __m64 __cl_char8;
+       typedef __m64 __cl_ushort4;
+       typedef __m64 __cl_short4;
+       typedef __m64 __cl_uint2;
+       typedef __m64 __cl_int2;
+       typedef __m64 __cl_ulong1;
+       typedef __m64 __cl_long1;
+       typedef __m64 __cl_float2;
+#endif
+#define __CL_UCHAR8__ 1
+#define __CL_CHAR8__ 1
+#define __CL_USHORT4__ 1
+#define __CL_SHORT4__ 1
+#define __CL_INT2__ 1
+#define __CL_UINT2__ 1
+#define __CL_ULONG1__ 1
+#define __CL_LONG1__ 1
+#define __CL_FLOAT2__ 1
+#endif
+
+#if defined(__AVX__)
+#if defined(__MINGW64__)
+#include <intrin.h>
+#else
+#include <immintrin.h>
+#endif
+#if defined(__GNUC__) && !defined(__ICC)
+       typedef cl_float __cl_float8 __attribute__((vector_size(32)));
+       typedef cl_double __cl_double4 __attribute__((vector_size(32)));
+#else
+       typedef __m256 __cl_float8;
+       typedef __m256d __cl_double4;
+#endif
+#define __CL_FLOAT8__ 1
+#define __CL_DOUBLE4__ 1
+#endif
+
+/* Define alignment keys */
+#if defined(__GNUC__)
+#define CL_ALIGNED(_x) __attribute__((aligned(_x)))
+#elif defined(_WIN32) && (_MSC_VER)
+/* Alignment keys neutered on windows because MSVC can't swallow function arguments with alignment requirements     */
+/* http://msdn.microsoft.com/en-us/library/373ak2y1%28VS.71%29.aspx                                                 */
+/* #include <crtdefs.h>                                                                                             */
+/* #define CL_ALIGNED(_x)          _CRT_ALIGN(_x)                                                                   */
+#define CL_ALIGNED(_x)
+#else
+#warning Need to implement some method to align data here
+#define CL_ALIGNED(_x)
+#endif
+
+/* Indicate whether .xyzw, .s0123 and .hi.lo are supported */
+#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || (defined(_MSC_VER) && !defined(__STDC__))
+/* .xyzw and .s0123...{f|F} are supported */
+#define CL_HAS_NAMED_VECTOR_FIELDS 1
+/* .hi and .lo are supported */
+#define CL_HAS_HI_LO_VECTOR_FIELDS 1
+
+#define CL_NAMED_STRUCT_SUPPORTED
+#endif
+
+#if defined(CL_NAMED_STRUCT_SUPPORTED) && defined(_MSC_VER)
+#define __extension__ __pragma(warning(suppress : 4201))
+#endif
+
+       /* Define cl_vector types */
+
+       /* ---- cl_charn ---- */
+       typedef union {
+               cl_char CL_ALIGNED(2) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_char x, y;
+               };
+               __extension__ struct
+               {
+                       cl_char s0, s1;
+               };
+               __extension__ struct
+               {
+                       cl_char lo, hi;
+               };
+#endif
+#if defined(__CL_CHAR2__)
+               __cl_char2 v2;
+#endif
+       } cl_char2;
+
+       typedef union {
+               cl_char CL_ALIGNED(4) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_char x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_char s0, s1, s2, s3;
+               };
+               __extension__ struct
+               {
+                       cl_char2 lo, hi;
+               };
+#endif
+#if defined(__CL_CHAR2__)
+               __cl_char2 v2[2];
+#endif
+#if defined(__CL_CHAR4__)
+               __cl_char4 v4;
+#endif
+       } cl_char4;
+
+       /* cl_char3 is identical in size, alignment and behavior to cl_char4. See section 6.1.5. */
+       typedef cl_char4 cl_char3;
+
+       typedef union {
+               cl_char CL_ALIGNED(8) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_char x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_char s0, s1, s2, s3, s4, s5, s6, s7;
+               };
+               __extension__ struct
+               {
+                       cl_char4 lo, hi;
+               };
+#endif
+#if defined(__CL_CHAR2__)
+               __cl_char2 v2[4];
+#endif
+#if defined(__CL_CHAR4__)
+               __cl_char4 v4[2];
+#endif
+#if defined(__CL_CHAR8__)
+               __cl_char8 v8;
+#endif
+       } cl_char8;
+
+       typedef union {
+               cl_char CL_ALIGNED(16) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_char x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+               };
+               __extension__ struct
+               {
+                       cl_char s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+               };
+               __extension__ struct
+               {
+                       cl_char8 lo, hi;
+               };
+#endif
+#if defined(__CL_CHAR2__)
+               __cl_char2 v2[8];
+#endif
+#if defined(__CL_CHAR4__)
+               __cl_char4 v4[4];
+#endif
+#if defined(__CL_CHAR8__)
+               __cl_char8 v8[2];
+#endif
+#if defined(__CL_CHAR16__)
+               __cl_char16 v16;
+#endif
+       } cl_char16;
+
+       /* ---- cl_ucharn ---- */
+       typedef union {
+               cl_uchar CL_ALIGNED(2) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_uchar x, y;
+               };
+               __extension__ struct
+               {
+                       cl_uchar s0, s1;
+               };
+               __extension__ struct
+               {
+                       cl_uchar lo, hi;
+               };
+#endif
+#if defined(__cl_uchar2__)
+               __cl_uchar2 v2;
+#endif
+       } cl_uchar2;
+
+       typedef union {
+               cl_uchar CL_ALIGNED(4) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_uchar x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_uchar s0, s1, s2, s3;
+               };
+               __extension__ struct
+               {
+                       cl_uchar2 lo, hi;
+               };
+#endif
+#if defined(__CL_UCHAR2__)
+               __cl_uchar2 v2[2];
+#endif
+#if defined(__CL_UCHAR4__)
+               __cl_uchar4 v4;
+#endif
+       } cl_uchar4;
+
+       /* cl_uchar3 is identical in size, alignment and behavior to cl_uchar4. See section 6.1.5. */
+       typedef cl_uchar4 cl_uchar3;
+
+       typedef union {
+               cl_uchar CL_ALIGNED(8) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_uchar x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_uchar s0, s1, s2, s3, s4, s5, s6, s7;
+               };
+               __extension__ struct
+               {
+                       cl_uchar4 lo, hi;
+               };
+#endif
+#if defined(__CL_UCHAR2__)
+               __cl_uchar2 v2[4];
+#endif
+#if defined(__CL_UCHAR4__)
+               __cl_uchar4 v4[2];
+#endif
+#if defined(__CL_UCHAR8__)
+               __cl_uchar8 v8;
+#endif
+       } cl_uchar8;
+
+       typedef union {
+               cl_uchar CL_ALIGNED(16) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_uchar x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+               };
+               __extension__ struct
+               {
+                       cl_uchar s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+               };
+               __extension__ struct
+               {
+                       cl_uchar8 lo, hi;
+               };
+#endif
+#if defined(__CL_UCHAR2__)
+               __cl_uchar2 v2[8];
+#endif
+#if defined(__CL_UCHAR4__)
+               __cl_uchar4 v4[4];
+#endif
+#if defined(__CL_UCHAR8__)
+               __cl_uchar8 v8[2];
+#endif
+#if defined(__CL_UCHAR16__)
+               __cl_uchar16 v16;
+#endif
+       } cl_uchar16;
+
+       /* ---- cl_shortn ---- */
+       typedef union {
+               cl_short CL_ALIGNED(4) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_short x, y;
+               };
+               __extension__ struct
+               {
+                       cl_short s0, s1;
+               };
+               __extension__ struct
+               {
+                       cl_short lo, hi;
+               };
+#endif
+#if defined(__CL_SHORT2__)
+               __cl_short2 v2;
+#endif
+       } cl_short2;
+
+       typedef union {
+               cl_short CL_ALIGNED(8) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_short x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_short s0, s1, s2, s3;
+               };
+               __extension__ struct
+               {
+                       cl_short2 lo, hi;
+               };
+#endif
+#if defined(__CL_SHORT2__)
+               __cl_short2 v2[2];
+#endif
+#if defined(__CL_SHORT4__)
+               __cl_short4 v4;
+#endif
+       } cl_short4;
+
+       /* cl_short3 is identical in size, alignment and behavior to cl_short4. See section 6.1.5. */
+       typedef cl_short4 cl_short3;
+
+       typedef union {
+               cl_short CL_ALIGNED(16) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_short x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_short s0, s1, s2, s3, s4, s5, s6, s7;
+               };
+               __extension__ struct
+               {
+                       cl_short4 lo, hi;
+               };
+#endif
+#if defined(__CL_SHORT2__)
+               __cl_short2 v2[4];
+#endif
+#if defined(__CL_SHORT4__)
+               __cl_short4 v4[2];
+#endif
+#if defined(__CL_SHORT8__)
+               __cl_short8 v8;
+#endif
+       } cl_short8;
+
+       typedef union {
+               cl_short CL_ALIGNED(32) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_short x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+               };
+               __extension__ struct
+               {
+                       cl_short s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+               };
+               __extension__ struct
+               {
+                       cl_short8 lo, hi;
+               };
+#endif
+#if defined(__CL_SHORT2__)
+               __cl_short2 v2[8];
+#endif
+#if defined(__CL_SHORT4__)
+               __cl_short4 v4[4];
+#endif
+#if defined(__CL_SHORT8__)
+               __cl_short8 v8[2];
+#endif
+#if defined(__CL_SHORT16__)
+               __cl_short16 v16;
+#endif
+       } cl_short16;
+
+       /* ---- cl_ushortn ---- */
+       typedef union {
+               cl_ushort CL_ALIGNED(4) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_ushort x, y;
+               };
+               __extension__ struct
+               {
+                       cl_ushort s0, s1;
+               };
+               __extension__ struct
+               {
+                       cl_ushort lo, hi;
+               };
+#endif
+#if defined(__CL_USHORT2__)
+               __cl_ushort2 v2;
+#endif
+       } cl_ushort2;
+
+       typedef union {
+               cl_ushort CL_ALIGNED(8) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_ushort x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_ushort s0, s1, s2, s3;
+               };
+               __extension__ struct
+               {
+                       cl_ushort2 lo, hi;
+               };
+#endif
+#if defined(__CL_USHORT2__)
+               __cl_ushort2 v2[2];
+#endif
+#if defined(__CL_USHORT4__)
+               __cl_ushort4 v4;
+#endif
+       } cl_ushort4;
+
+       /* cl_ushort3 is identical in size, alignment and behavior to cl_ushort4. See section 6.1.5. */
+       typedef cl_ushort4 cl_ushort3;
+
+       typedef union {
+               cl_ushort CL_ALIGNED(16) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_ushort x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_ushort s0, s1, s2, s3, s4, s5, s6, s7;
+               };
+               __extension__ struct
+               {
+                       cl_ushort4 lo, hi;
+               };
+#endif
+#if defined(__CL_USHORT2__)
+               __cl_ushort2 v2[4];
+#endif
+#if defined(__CL_USHORT4__)
+               __cl_ushort4 v4[2];
+#endif
+#if defined(__CL_USHORT8__)
+               __cl_ushort8 v8;
+#endif
+       } cl_ushort8;
+
+       typedef union {
+               cl_ushort CL_ALIGNED(32) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_ushort x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+               };
+               __extension__ struct
+               {
+                       cl_ushort s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+               };
+               __extension__ struct
+               {
+                       cl_ushort8 lo, hi;
+               };
+#endif
+#if defined(__CL_USHORT2__)
+               __cl_ushort2 v2[8];
+#endif
+#if defined(__CL_USHORT4__)
+               __cl_ushort4 v4[4];
+#endif
+#if defined(__CL_USHORT8__)
+               __cl_ushort8 v8[2];
+#endif
+#if defined(__CL_USHORT16__)
+               __cl_ushort16 v16;
+#endif
+       } cl_ushort16;
+
+       /* ---- cl_intn ---- */
+       typedef union {
+               cl_int CL_ALIGNED(8) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_int x, y;
+               };
+               __extension__ struct
+               {
+                       cl_int s0, s1;
+               };
+               __extension__ struct
+               {
+                       cl_int lo, hi;
+               };
+#endif
+#if defined(__CL_INT2__)
+               __cl_int2 v2;
+#endif
+       } cl_int2;
+
+       typedef union {
+               cl_int CL_ALIGNED(16) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_int x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_int s0, s1, s2, s3;
+               };
+               __extension__ struct
+               {
+                       cl_int2 lo, hi;
+               };
+#endif
+#if defined(__CL_INT2__)
+               __cl_int2 v2[2];
+#endif
+#if defined(__CL_INT4__)
+               __cl_int4 v4;
+#endif
+       } cl_int4;
+
+       /* cl_int3 is identical in size, alignment and behavior to cl_int4. See section 6.1.5. */
+       typedef cl_int4 cl_int3;
+
+       typedef union {
+               cl_int CL_ALIGNED(32) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_int x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_int s0, s1, s2, s3, s4, s5, s6, s7;
+               };
+               __extension__ struct
+               {
+                       cl_int4 lo, hi;
+               };
+#endif
+#if defined(__CL_INT2__)
+               __cl_int2 v2[4];
+#endif
+#if defined(__CL_INT4__)
+               __cl_int4 v4[2];
+#endif
+#if defined(__CL_INT8__)
+               __cl_int8 v8;
+#endif
+       } cl_int8;
+
+       typedef union {
+               cl_int CL_ALIGNED(64) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_int x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+               };
+               __extension__ struct
+               {
+                       cl_int s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+               };
+               __extension__ struct
+               {
+                       cl_int8 lo, hi;
+               };
+#endif
+#if defined(__CL_INT2__)
+               __cl_int2 v2[8];
+#endif
+#if defined(__CL_INT4__)
+               __cl_int4 v4[4];
+#endif
+#if defined(__CL_INT8__)
+               __cl_int8 v8[2];
+#endif
+#if defined(__CL_INT16__)
+               __cl_int16 v16;
+#endif
+       } cl_int16;
+
+       /* ---- cl_uintn ---- */
+       typedef union {
+               cl_uint CL_ALIGNED(8) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_uint x, y;
+               };
+               __extension__ struct
+               {
+                       cl_uint s0, s1;
+               };
+               __extension__ struct
+               {
+                       cl_uint lo, hi;
+               };
+#endif
+#if defined(__CL_UINT2__)
+               __cl_uint2 v2;
+#endif
+       } cl_uint2;
+
+       typedef union {
+               cl_uint CL_ALIGNED(16) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_uint x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_uint s0, s1, s2, s3;
+               };
+               __extension__ struct
+               {
+                       cl_uint2 lo, hi;
+               };
+#endif
+#if defined(__CL_UINT2__)
+               __cl_uint2 v2[2];
+#endif
+#if defined(__CL_UINT4__)
+               __cl_uint4 v4;
+#endif
+       } cl_uint4;
+
+       /* cl_uint3 is identical in size, alignment and behavior to cl_uint4. See section 6.1.5. */
+       typedef cl_uint4 cl_uint3;
+
+       typedef union {
+               cl_uint CL_ALIGNED(32) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_uint x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_uint s0, s1, s2, s3, s4, s5, s6, s7;
+               };
+               __extension__ struct
+               {
+                       cl_uint4 lo, hi;
+               };
+#endif
+#if defined(__CL_UINT2__)
+               __cl_uint2 v2[4];
+#endif
+#if defined(__CL_UINT4__)
+               __cl_uint4 v4[2];
+#endif
+#if defined(__CL_UINT8__)
+               __cl_uint8 v8;
+#endif
+       } cl_uint8;
+
+       typedef union {
+               cl_uint CL_ALIGNED(64) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_uint x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+               };
+               __extension__ struct
+               {
+                       cl_uint s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+               };
+               __extension__ struct
+               {
+                       cl_uint8 lo, hi;
+               };
+#endif
+#if defined(__CL_UINT2__)
+               __cl_uint2 v2[8];
+#endif
+#if defined(__CL_UINT4__)
+               __cl_uint4 v4[4];
+#endif
+#if defined(__CL_UINT8__)
+               __cl_uint8 v8[2];
+#endif
+#if defined(__CL_UINT16__)
+               __cl_uint16 v16;
+#endif
+       } cl_uint16;
+
+       /* ---- cl_longn ---- */
+       typedef union {
+               cl_long CL_ALIGNED(16) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_long x, y;
+               };
+               __extension__ struct
+               {
+                       cl_long s0, s1;
+               };
+               __extension__ struct
+               {
+                       cl_long lo, hi;
+               };
+#endif
+#if defined(__CL_LONG2__)
+               __cl_long2 v2;
+#endif
+       } cl_long2;
+
+       typedef union {
+               cl_long CL_ALIGNED(32) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_long x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_long s0, s1, s2, s3;
+               };
+               __extension__ struct
+               {
+                       cl_long2 lo, hi;
+               };
+#endif
+#if defined(__CL_LONG2__)
+               __cl_long2 v2[2];
+#endif
+#if defined(__CL_LONG4__)
+               __cl_long4 v4;
+#endif
+       } cl_long4;
+
+       /* cl_long3 is identical in size, alignment and behavior to cl_long4. See section 6.1.5. */
+       typedef cl_long4 cl_long3;
+
+       typedef union {
+               cl_long CL_ALIGNED(64) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_long x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_long s0, s1, s2, s3, s4, s5, s6, s7;
+               };
+               __extension__ struct
+               {
+                       cl_long4 lo, hi;
+               };
+#endif
+#if defined(__CL_LONG2__)
+               __cl_long2 v2[4];
+#endif
+#if defined(__CL_LONG4__)
+               __cl_long4 v4[2];
+#endif
+#if defined(__CL_LONG8__)
+               __cl_long8 v8;
+#endif
+       } cl_long8;
+
+       typedef union {
+               cl_long CL_ALIGNED(128) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_long x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+               };
+               __extension__ struct
+               {
+                       cl_long s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+               };
+               __extension__ struct
+               {
+                       cl_long8 lo, hi;
+               };
+#endif
+#if defined(__CL_LONG2__)
+               __cl_long2 v2[8];
+#endif
+#if defined(__CL_LONG4__)
+               __cl_long4 v4[4];
+#endif
+#if defined(__CL_LONG8__)
+               __cl_long8 v8[2];
+#endif
+#if defined(__CL_LONG16__)
+               __cl_long16 v16;
+#endif
+       } cl_long16;
+
+       /* ---- cl_ulongn ---- */
+       typedef union {
+               cl_ulong CL_ALIGNED(16) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_ulong x, y;
+               };
+               __extension__ struct
+               {
+                       cl_ulong s0, s1;
+               };
+               __extension__ struct
+               {
+                       cl_ulong lo, hi;
+               };
+#endif
+#if defined(__CL_ULONG2__)
+               __cl_ulong2 v2;
+#endif
+       } cl_ulong2;
+
+       typedef union {
+               cl_ulong CL_ALIGNED(32) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_ulong x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_ulong s0, s1, s2, s3;
+               };
+               __extension__ struct
+               {
+                       cl_ulong2 lo, hi;
+               };
+#endif
+#if defined(__CL_ULONG2__)
+               __cl_ulong2 v2[2];
+#endif
+#if defined(__CL_ULONG4__)
+               __cl_ulong4 v4;
+#endif
+       } cl_ulong4;
+
+       /* cl_ulong3 is identical in size, alignment and behavior to cl_ulong4. See section 6.1.5. */
+       typedef cl_ulong4 cl_ulong3;
+
+       typedef union {
+               cl_ulong CL_ALIGNED(64) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_ulong x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_ulong s0, s1, s2, s3, s4, s5, s6, s7;
+               };
+               __extension__ struct
+               {
+                       cl_ulong4 lo, hi;
+               };
+#endif
+#if defined(__CL_ULONG2__)
+               __cl_ulong2 v2[4];
+#endif
+#if defined(__CL_ULONG4__)
+               __cl_ulong4 v4[2];
+#endif
+#if defined(__CL_ULONG8__)
+               __cl_ulong8 v8;
+#endif
+       } cl_ulong8;
+
+       typedef union {
+               cl_ulong CL_ALIGNED(128) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_ulong x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+               };
+               __extension__ struct
+               {
+                       cl_ulong s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+               };
+               __extension__ struct
+               {
+                       cl_ulong8 lo, hi;
+               };
+#endif
+#if defined(__CL_ULONG2__)
+               __cl_ulong2 v2[8];
+#endif
+#if defined(__CL_ULONG4__)
+               __cl_ulong4 v4[4];
+#endif
+#if defined(__CL_ULONG8__)
+               __cl_ulong8 v8[2];
+#endif
+#if defined(__CL_ULONG16__)
+               __cl_ulong16 v16;
+#endif
+       } cl_ulong16;
+
+       /* --- cl_floatn ---- */
+
+       typedef union {
+               cl_float CL_ALIGNED(8) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_float x, y;
+               };
+               __extension__ struct
+               {
+                       cl_float s0, s1;
+               };
+               __extension__ struct
+               {
+                       cl_float lo, hi;
+               };
+#endif
+#if defined(__CL_FLOAT2__)
+               __cl_float2 v2;
+#endif
+       } cl_float2;
+
+       typedef union {
+               cl_float CL_ALIGNED(16) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_float x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_float s0, s1, s2, s3;
+               };
+               __extension__ struct
+               {
+                       cl_float2 lo, hi;
+               };
+#endif
+#if defined(__CL_FLOAT2__)
+               __cl_float2 v2[2];
+#endif
+#if defined(__CL_FLOAT4__)
+               __cl_float4 v4;
+#endif
+       } cl_float4;
+
+       /* cl_float3 is identical in size, alignment and behavior to cl_float4. See section 6.1.5. */
+       typedef cl_float4 cl_float3;
+
+       typedef union {
+               cl_float CL_ALIGNED(32) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_float x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_float s0, s1, s2, s3, s4, s5, s6, s7;
+               };
+               __extension__ struct
+               {
+                       cl_float4 lo, hi;
+               };
+#endif
+#if defined(__CL_FLOAT2__)
+               __cl_float2 v2[4];
+#endif
+#if defined(__CL_FLOAT4__)
+               __cl_float4 v4[2];
+#endif
+#if defined(__CL_FLOAT8__)
+               __cl_float8 v8;
+#endif
+       } cl_float8;
+
+       typedef union {
+               cl_float CL_ALIGNED(64) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_float x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+               };
+               __extension__ struct
+               {
+                       cl_float s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+               };
+               __extension__ struct
+               {
+                       cl_float8 lo, hi;
+               };
+#endif
+#if defined(__CL_FLOAT2__)
+               __cl_float2 v2[8];
+#endif
+#if defined(__CL_FLOAT4__)
+               __cl_float4 v4[4];
+#endif
+#if defined(__CL_FLOAT8__)
+               __cl_float8 v8[2];
+#endif
+#if defined(__CL_FLOAT16__)
+               __cl_float16 v16;
+#endif
+       } cl_float16;
+
+       /* --- cl_doublen ---- */
+
+       typedef union {
+               cl_double CL_ALIGNED(16) s[2];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_double x, y;
+               };
+               __extension__ struct
+               {
+                       cl_double s0, s1;
+               };
+               __extension__ struct
+               {
+                       cl_double lo, hi;
+               };
+#endif
+#if defined(__CL_DOUBLE2__)
+               __cl_double2 v2;
+#endif
+       } cl_double2;
+
+       typedef union {
+               cl_double CL_ALIGNED(32) s[4];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_double x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_double s0, s1, s2, s3;
+               };
+               __extension__ struct
+               {
+                       cl_double2 lo, hi;
+               };
+#endif
+#if defined(__CL_DOUBLE2__)
+               __cl_double2 v2[2];
+#endif
+#if defined(__CL_DOUBLE4__)
+               __cl_double4 v4;
+#endif
+       } cl_double4;
+
+       /* cl_double3 is identical in size, alignment and behavior to cl_double4. See section 6.1.5. */
+       typedef cl_double4 cl_double3;
+
+       typedef union {
+               cl_double CL_ALIGNED(64) s[8];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_double x, y, z, w;
+               };
+               __extension__ struct
+               {
+                       cl_double s0, s1, s2, s3, s4, s5, s6, s7;
+               };
+               __extension__ struct
+               {
+                       cl_double4 lo, hi;
+               };
+#endif
+#if defined(__CL_DOUBLE2__)
+               __cl_double2 v2[4];
+#endif
+#if defined(__CL_DOUBLE4__)
+               __cl_double4 v4[2];
+#endif
+#if defined(__CL_DOUBLE8__)
+               __cl_double8 v8;
+#endif
+       } cl_double8;
+
+       typedef union {
+               cl_double CL_ALIGNED(128) s[16];
+#if defined(CL_NAMED_STRUCT_SUPPORTED)
+               __extension__ struct
+               {
+                       cl_double x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
+               };
+               __extension__ struct
+               {
+                       cl_double s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
+               };
+               __extension__ struct
+               {
+                       cl_double8 lo, hi;
+               };
+#endif
+#if defined(__CL_DOUBLE2__)
+               __cl_double2 v2[8];
+#endif
+#if defined(__CL_DOUBLE4__)
+               __cl_double4 v4[4];
+#endif
+#if defined(__CL_DOUBLE8__)
+               __cl_double8 v8[2];
+#endif
+#if defined(__CL_DOUBLE16__)
+               __cl_double16 v16;
+#endif
+       } cl_double16;
+
+/* Macro to facilitate debugging 
+ * Usage:
+ *   Place CL_PROGRAM_STRING_DEBUG_INFO on the line before the first line of your source. 
+ *   The first line ends with:   CL_PROGRAM_STRING_BEGIN \"
+ *   Each line thereafter of OpenCL C source must end with: \n\
+ *   The last line ends in ";
+ *
+ *   Example:
+ *
+ *   const char *my_program = CL_PROGRAM_STRING_BEGIN "\
+ *   kernel void foo( int a, float * b )             \n\
+ *   {                                               \n\
+ *      // my comment                                \n\
+ *      *b[ get_global_id(0)] = a;                   \n\
+ *   }                                               \n\
+ *   ";
+ *
+ * This should correctly set up the line, (column) and file information for your source 
+ * string so you can do source level debugging.
+ */
+#define __CL_STRINGIFY(_x) #_x
+#define _CL_STRINGIFY(_x) __CL_STRINGIFY(_x)
+#define CL_PROGRAM_STRING_DEBUG_INFO "#line " _CL_STRINGIFY(__LINE__) " \"" __FILE__ "\" \n\n"
+
+       //  CL.h contents
+       /******************************************************************************/
+
+       typedef struct _cl_platform_id *cl_platform_id;
+       typedef struct _cl_device_id *cl_device_id;
+       typedef struct _cl_context *cl_context;
+       typedef struct _cl_command_queue *cl_command_queue;
+       typedef struct _cl_mem *cl_mem;
+       typedef struct _cl_program *cl_program;
+       typedef struct _cl_kernel *cl_kernel;
+       typedef struct _cl_event *cl_event;
+       typedef struct _cl_sampler *cl_sampler;
+
+       typedef cl_uint cl_bool; /* WARNING!  Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */
+       typedef cl_ulong cl_bitfield;
+       typedef cl_bitfield cl_device_type;
+       typedef cl_uint cl_platform_info;
+       typedef cl_uint cl_device_info;
+       typedef cl_bitfield cl_device_fp_config;
+       typedef cl_uint cl_device_mem_cache_type;
+       typedef cl_uint cl_device_local_mem_type;
+       typedef cl_bitfield cl_device_exec_capabilities;
+       typedef cl_bitfield cl_command_queue_properties;
+
+       typedef intptr_t cl_context_properties;
+       typedef cl_uint cl_context_info;
+       typedef cl_uint cl_command_queue_info;
+       typedef cl_uint cl_channel_order;
+       typedef cl_uint cl_channel_type;
+       typedef cl_bitfield cl_mem_flags;
+       typedef cl_uint cl_mem_object_type;
+       typedef cl_uint cl_mem_info;
+       typedef cl_uint cl_image_info;
+       typedef cl_uint cl_buffer_create_type;
+       typedef cl_uint cl_addressing_mode;
+       typedef cl_uint cl_filter_mode;
+       typedef cl_uint cl_sampler_info;
+       typedef cl_bitfield cl_map_flags;
+       typedef cl_uint cl_program_info;
+       typedef cl_uint cl_program_build_info;
+       typedef cl_int cl_build_status;
+       typedef cl_uint cl_kernel_info;
+       typedef cl_uint cl_kernel_work_group_info;
+       typedef cl_uint cl_event_info;
+       typedef cl_uint cl_command_type;
+       typedef cl_uint cl_profiling_info;
+
+       typedef struct _cl_image_format
+       {
+               cl_channel_order image_channel_order;
+               cl_channel_type image_channel_data_type;
+       } cl_image_format;
+
+       typedef struct _cl_buffer_region
+       {
+               size_t origin;
+               size_t size;
+       } cl_buffer_region;
+
+/******************************************************************************/
+
+/* Error Codes */
+#define CL_SUCCESS 0
+#define CL_DEVICE_NOT_FOUND -1
+#define CL_DEVICE_NOT_AVAILABLE -2
+#define CL_COMPILER_NOT_AVAILABLE -3
+#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4
+#define CL_OUT_OF_RESOURCES -5
+#define CL_OUT_OF_HOST_MEMORY -6
+#define CL_PROFILING_INFO_NOT_AVAILABLE -7
+#define CL_MEM_COPY_OVERLAP -8
+#define CL_IMAGE_FORMAT_MISMATCH -9
+#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10
+#define CL_BUILD_PROGRAM_FAILURE -11
+#define CL_MAP_FAILURE -12
+#define CL_MISALIGNED_SUB_BUFFER_OFFSET -13
+#define CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST -14
+
+#define CL_INVALID_VALUE -30
+#define CL_INVALID_DEVICE_TYPE -31
+#define CL_INVALID_PLATFORM -32
+#define CL_INVALID_DEVICE -33
+#define CL_INVALID_CONTEXT -34
+#define CL_INVALID_QUEUE_PROPERTIES -35
+#define CL_INVALID_COMMAND_QUEUE -36
+#define CL_INVALID_HOST_PTR -37
+#define CL_INVALID_MEM_OBJECT -38
+#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39
+#define CL_INVALID_IMAGE_SIZE -40
+#define CL_INVALID_SAMPLER -41
+#define CL_INVALID_BINARY -42
+#define CL_INVALID_BUILD_OPTIONS -43
+#define CL_INVALID_PROGRAM -44
+#define CL_INVALID_PROGRAM_EXECUTABLE -45
+#define CL_INVALID_KERNEL_NAME -46
+#define CL_INVALID_KERNEL_DEFINITION -47
+#define CL_INVALID_KERNEL -48
+#define CL_INVALID_ARG_INDEX -49
+#define CL_INVALID_ARG_VALUE -50
+#define CL_INVALID_ARG_SIZE -51
+#define CL_INVALID_KERNEL_ARGS -52
+#define CL_INVALID_WORK_DIMENSION -53
+#define CL_INVALID_WORK_GROUP_SIZE -54
+#define CL_INVALID_WORK_ITEM_SIZE -55
+#define CL_INVALID_GLOBAL_OFFSET -56
+#define CL_INVALID_EVENT_WAIT_LIST -57
+#define CL_INVALID_EVENT -58
+#define CL_INVALID_OPERATION -59
+#define CL_INVALID_GL_OBJECT -60
+#define CL_INVALID_BUFFER_SIZE -61
+#define CL_INVALID_MIP_LEVEL -62
+#define CL_INVALID_GLOBAL_WORK_SIZE -63
+#define CL_INVALID_PROPERTY -64
+
+/* OpenCL Version */
+#define CL_VERSION_1_0 1
+#define CL_VERSION_1_1 1
+
+/* cl_bool */
+#define CL_FALSE 0
+#define CL_TRUE 1
+
+/* cl_platform_info */
+#define CL_PLATFORM_PROFILE 0x0900
+#define CL_PLATFORM_VERSION 0x0901
+#define CL_PLATFORM_NAME 0x0902
+#define CL_PLATFORM_VENDOR 0x0903
+#define CL_PLATFORM_EXTENSIONS 0x0904
+
+/* cl_device_type - bitfield */
+#define CL_DEVICE_TYPE_DEFAULT (1 << 0)
+#define CL_DEVICE_TYPE_CPU (1 << 1)
+#define CL_DEVICE_TYPE_GPU (1 << 2)
+#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3)
+#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF
+
+/* cl_device_info */
+#define CL_DEVICE_TYPE 0x1000
+#define CL_DEVICE_VENDOR_ID 0x1001
+#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002
+#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003
+#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004
+#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B
+#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C
+#define CL_DEVICE_ADDRESS_BITS 0x100D
+#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E
+#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F
+#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010
+#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011
+#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012
+#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013
+#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014
+#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015
+#define CL_DEVICE_IMAGE_SUPPORT 0x1016
+#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017
+#define CL_DEVICE_MAX_SAMPLERS 0x1018
+#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019
+#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A
+#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B
+#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C
+#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D
+#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E
+#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F
+#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020
+#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021
+#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022
+#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023
+#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024
+#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025
+#define CL_DEVICE_ENDIAN_LITTLE 0x1026
+#define CL_DEVICE_AVAILABLE 0x1027
+#define CL_DEVICE_COMPILER_AVAILABLE 0x1028
+#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029
+#define CL_DEVICE_QUEUE_PROPERTIES 0x102A
+#define CL_DEVICE_NAME 0x102B
+#define CL_DEVICE_VENDOR 0x102C
+#define CL_DRIVER_VERSION 0x102D
+#define CL_DEVICE_PROFILE 0x102E
+#define CL_DEVICE_VERSION 0x102F
+#define CL_DEVICE_EXTENSIONS 0x1030
+#define CL_DEVICE_PLATFORM 0x1031
+/* 0x1032 reserved for CL_DEVICE_DOUBLE_FP_CONFIG */
+/* 0x1033 reserved for CL_DEVICE_HALF_FP_CONFIG */
+#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF 0x1034
+#define CL_DEVICE_HOST_UNIFIED_MEMORY 0x1035
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR 0x1036
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT 0x1037
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_INT 0x1038
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG 0x1039
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT 0x103A
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE 0x103B
+#define CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF 0x103C
+#define CL_DEVICE_OPENCL_C_VERSION 0x103D
+
+/* cl_device_fp_config - bitfield */
+#define CL_FP_DENORM (1 << 0)
+#define CL_FP_INF_NAN (1 << 1)
+#define CL_FP_ROUND_TO_NEAREST (1 << 2)
+#define CL_FP_ROUND_TO_ZERO (1 << 3)
+#define CL_FP_ROUND_TO_INF (1 << 4)
+#define CL_FP_FMA (1 << 5)
+#define CL_FP_SOFT_FLOAT (1 << 6)
+
+/* cl_device_mem_cache_type */
+#define CL_NONE 0x0
+#define CL_READ_ONLY_CACHE 0x1
+#define CL_READ_WRITE_CACHE 0x2
+
+/* cl_device_local_mem_type */
+#define CL_LOCAL 0x1
+#define CL_GLOBAL 0x2
+
+/* cl_device_exec_capabilities - bitfield */
+#define CL_EXEC_KERNEL (1 << 0)
+#define CL_EXEC_NATIVE_KERNEL (1 << 1)
+
+/* cl_command_queue_properties - bitfield */
+#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0)
+#define CL_QUEUE_PROFILING_ENABLE (1 << 1)
+
+/* cl_context_info  */
+#define CL_CONTEXT_REFERENCE_COUNT 0x1080
+#define CL_CONTEXT_DEVICES 0x1081
+#define CL_CONTEXT_PROPERTIES 0x1082
+#define CL_CONTEXT_NUM_DEVICES 0x1083
+
+/* cl_context_info + cl_context_properties */
+#define CL_CONTEXT_PLATFORM 0x1084
+
+/* cl_command_queue_info */
+#define CL_QUEUE_CONTEXT 0x1090
+#define CL_QUEUE_DEVICE 0x1091
+#define CL_QUEUE_REFERENCE_COUNT 0x1092
+#define CL_QUEUE_PROPERTIES 0x1093
+
+/* cl_mem_flags - bitfield */
+#define CL_MEM_READ_WRITE (1 << 0)
+#define CL_MEM_WRITE_ONLY (1 << 1)
+#define CL_MEM_READ_ONLY (1 << 2)
+#define CL_MEM_USE_HOST_PTR (1 << 3)
+#define CL_MEM_ALLOC_HOST_PTR (1 << 4)
+#define CL_MEM_COPY_HOST_PTR (1 << 5)
+
+/* cl_channel_order */
+#define CL_R 0x10B0
+#define CL_A 0x10B1
+#define CL_RG 0x10B2
+#define CL_RA 0x10B3
+#define CL_RGB 0x10B4
+#define CL_RGBA 0x10B5
+#define CL_BGRA 0x10B6
+#define CL_ARGB 0x10B7
+#define CL_INTENSITY 0x10B8
+#define CL_LUMINANCE 0x10B9
+#define CL_Rx 0x10BA
+#define CL_RGx 0x10BB
+#define CL_RGBx 0x10BC
+
+/* cl_channel_type */
+#define CL_SNORM_INT8 0x10D0
+#define CL_SNORM_INT16 0x10D1
+#define CL_UNORM_INT8 0x10D2
+#define CL_UNORM_INT16 0x10D3
+#define CL_UNORM_SHORT_565 0x10D4
+#define CL_UNORM_SHORT_555 0x10D5
+#define CL_UNORM_INT_101010 0x10D6
+#define CL_SIGNED_INT8 0x10D7
+#define CL_SIGNED_INT16 0x10D8
+#define CL_SIGNED_INT32 0x10D9
+#define CL_UNSIGNED_INT8 0x10DA
+#define CL_UNSIGNED_INT16 0x10DB
+#define CL_UNSIGNED_INT32 0x10DC
+#define CL_HALF_FLOAT 0x10DD
+#define CL_FLOAT 0x10DE
+
+/* cl_mem_object_type */
+#define CL_MEM_OBJECT_BUFFER 0x10F0
+#define CL_MEM_OBJECT_IMAGE2D 0x10F1
+#define CL_MEM_OBJECT_IMAGE3D 0x10F2
+
+/* cl_mem_info */
+#define CL_MEM_TYPE 0x1100
+#define CL_MEM_FLAGS 0x1101
+#define CL_MEM_SIZE 0x1102
+#define CL_MEM_HOST_PTR 0x1103
+#define CL_MEM_MAP_COUNT 0x1104
+#define CL_MEM_REFERENCE_COUNT 0x1105
+#define CL_MEM_CONTEXT 0x1106
+#define CL_MEM_ASSOCIATED_MEMOBJECT 0x1107
+#define CL_MEM_OFFSET 0x1108
+
+/* cl_image_info */
+#define CL_IMAGE_FORMAT 0x1110
+#define CL_IMAGE_ELEMENT_SIZE 0x1111
+#define CL_IMAGE_ROW_PITCH 0x1112
+#define CL_IMAGE_SLICE_PITCH 0x1113
+#define CL_IMAGE_WIDTH 0x1114
+#define CL_IMAGE_HEIGHT 0x1115
+#define CL_IMAGE_DEPTH 0x1116
+
+/* cl_addressing_mode */
+#define CL_ADDRESS_NONE 0x1130
+#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131
+#define CL_ADDRESS_CLAMP 0x1132
+#define CL_ADDRESS_REPEAT 0x1133
+#define CL_ADDRESS_MIRRORED_REPEAT 0x1134
+
+/* cl_filter_mode */
+#define CL_FILTER_NEAREST 0x1140
+#define CL_FILTER_LINEAR 0x1141
+
+/* cl_sampler_info */
+#define CL_SAMPLER_REFERENCE_COUNT 0x1150
+#define CL_SAMPLER_CONTEXT 0x1151
+#define CL_SAMPLER_NORMALIZED_COORDS 0x1152
+#define CL_SAMPLER_ADDRESSING_MODE 0x1153
+#define CL_SAMPLER_FILTER_MODE 0x1154
+
+/* cl_map_flags - bitfield */
+#define CL_MAP_READ (1 << 0)
+#define CL_MAP_WRITE (1 << 1)
+
+/* cl_program_info */
+#define CL_PROGRAM_REFERENCE_COUNT 0x1160
+#define CL_PROGRAM_CONTEXT 0x1161
+#define CL_PROGRAM_NUM_DEVICES 0x1162
+#define CL_PROGRAM_DEVICES 0x1163
+#define CL_PROGRAM_SOURCE 0x1164
+#define CL_PROGRAM_BINARY_SIZES 0x1165
+#define CL_PROGRAM_BINARIES 0x1166
+
+/* cl_program_build_info */
+#define CL_PROGRAM_BUILD_STATUS 0x1181
+#define CL_PROGRAM_BUILD_OPTIONS 0x1182
+#define CL_PROGRAM_BUILD_LOG 0x1183
+
+/* cl_build_status */
+#define CL_BUILD_SUCCESS 0
+#define CL_BUILD_NONE -1
+#define CL_BUILD_ERROR -2
+#define CL_BUILD_IN_PROGRESS -3
+
+/* cl_kernel_info */
+#define CL_KERNEL_FUNCTION_NAME 0x1190
+#define CL_KERNEL_NUM_ARGS 0x1191
+#define CL_KERNEL_REFERENCE_COUNT 0x1192
+#define CL_KERNEL_CONTEXT 0x1193
+#define CL_KERNEL_PROGRAM 0x1194
+
+/* cl_kernel_work_group_info */
+#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0
+#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1
+#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2
+#define CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE 0x11B3
+#define CL_KERNEL_PRIVATE_MEM_SIZE 0x11B4
+
+/* cl_event_info  */
+#define CL_EVENT_COMMAND_QUEUE 0x11D0
+#define CL_EVENT_COMMAND_TYPE 0x11D1
+#define CL_EVENT_REFERENCE_COUNT 0x11D2
+#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3
+#define CL_EVENT_CONTEXT 0x11D4
+
+/* cl_command_type */
+#define CL_COMMAND_NDRANGE_KERNEL 0x11F0
+#define CL_COMMAND_TASK 0x11F1
+#define CL_COMMAND_NATIVE_KERNEL 0x11F2
+#define CL_COMMAND_READ_BUFFER 0x11F3
+#define CL_COMMAND_WRITE_BUFFER 0x11F4
+#define CL_COMMAND_COPY_BUFFER 0x11F5
+#define CL_COMMAND_READ_IMAGE 0x11F6
+#define CL_COMMAND_WRITE_IMAGE 0x11F7
+#define CL_COMMAND_COPY_IMAGE 0x11F8
+#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9
+#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA
+#define CL_COMMAND_MAP_BUFFER 0x11FB
+#define CL_COMMAND_MAP_IMAGE 0x11FC
+#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD
+#define CL_COMMAND_MARKER 0x11FE
+#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x11FF
+#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1200
+#define CL_COMMAND_READ_BUFFER_RECT 0x1201
+#define CL_COMMAND_WRITE_BUFFER_RECT 0x1202
+#define CL_COMMAND_COPY_BUFFER_RECT 0x1203
+#define CL_COMMAND_USER 0x1204
+
+/* command execution status */
+#define CL_COMPLETE 0x0
+#define CL_RUNNING 0x1
+#define CL_SUBMITTED 0x2
+#define CL_QUEUED 0x3
+
+/* cl_buffer_create_type  */
+#define CL_BUFFER_CREATE_TYPE_REGION 0x1220
+
+/* cl_profiling_info  */
+#define CL_PROFILING_COMMAND_QUEUED 0x1280
+#define CL_PROFILING_COMMAND_SUBMIT 0x1281
+#define CL_PROFILING_COMMAND_START 0x1282
+#define CL_PROFILING_COMMAND_END 0x1283
+
+       /********************************************************************************************************/
+
+       /********************************************************************************************************/
+
+       /*  Function signature typedef's */
+
+       /* Platform API */
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETPLATFORMIDS)(cl_uint /* num_entries */,
+                                                                                                                cl_platform_id * /* platforms */,
+                                                                                                                cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETPLATFORMINFO)(cl_platform_id /* platform */,
+                                                                                                                 cl_platform_info /* param_name */,
+                                                                                                                 size_t /* param_value_size */,
+                                                                                                                 void * /* param_value */,
+                                                                                                                 size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       /* Device APIs */
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETDEVICEIDS)(cl_platform_id /* platform */,
+                                                                                                          cl_device_type /* device_type */,
+                                                                                                          cl_uint /* num_entries */,
+                                                                                                          cl_device_id * /* devices */,
+                                                                                                          cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETDEVICEINFO)(cl_device_id /* device */,
+                                                                                                               cl_device_info /* param_name */,
+                                                                                                               size_t /* param_value_size */,
+                                                                                                               void * /* param_value */,
+                                                                                                               size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       // Context APIs
+       typedef CL_API_ENTRY cl_context(CL_API_CALL *
+                                                                               PFNCLCREATECONTEXT)(const cl_context_properties * /* properties */,
+                                                                                                                       cl_uint /* num_devices */,
+                                                                                                                       const cl_device_id * /* devices */,
+                                                                                                                       void(CL_CALLBACK * /* pfn_notify */)(const char *, const void *, size_t, void *),
+                                                                                                                       void * /* user_data */,
+                                                                                                                       cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_context(CL_API_CALL *
+                                                                               PFNCLCREATECONTEXTFROMTYPE)(const cl_context_properties * /* properties */,
+                                                                                                                                       cl_device_type /* device_type */,
+                                                                                                                                       void(CL_CALLBACK * /* pfn_notify*/)(const char *, const void *, size_t, void *),
+                                                                                                                                       void * /* user_data */,
+                                                                                                                                       cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRETAINCONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRELEASECONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETCONTEXTINFO)(cl_context /* context */,
+                                                                                                                cl_context_info /* param_name */,
+                                                                                                                size_t /* param_value_size */,
+                                                                                                                void * /* param_value */,
+                                                                                                                size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       /* Command Queue APIs */
+       typedef CL_API_ENTRY cl_command_queue(CL_API_CALL *
+                                                                                         PFNCLCREATECOMMANDQUEUE)(cl_context /* context */,
+                                                                                                                                          cl_device_id /* device */,
+                                                                                                                                          cl_command_queue_properties /* properties */,
+                                                                                                                                          cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRETAINCOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRELEASECOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETCOMMANDQUEUEINFO)(cl_command_queue /* command_queue */,
+                                                                                                                         cl_command_queue_info /* param_name */,
+                                                                                                                         size_t /* param_value_size */,
+                                                                                                                         void * /* param_value */,
+                                                                                                                         size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLSETCOMMANDQUEUEPROPERTY)(cl_command_queue /* command_queue */,
+                                                                                                                                 cl_command_queue_properties /* properties */,
+                                                                                                                                 cl_bool /* enable */,
+                                                                                                                                 cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0;
+
+       /* Memory Object APIs */
+       typedef CL_API_ENTRY cl_mem(CL_API_CALL *
+                                                                       PFNCLCREATEBUFFER)(cl_context /* context */,
+                                                                                                          cl_mem_flags /* flags */,
+                                                                                                          size_t /* size */,
+                                                                                                          void * /* host_ptr */,
+                                                                                                          cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_mem(CL_API_CALL *
+                                                                       PFNCLCREATESUBBUFFER)(cl_mem /* buffer */,
+                                                                                                                 cl_mem_flags /* flags */,
+                                                                                                                 cl_buffer_create_type /* buffer_create_type */,
+                                                                                                                 const void * /* buffer_create_info */,
+                                                                                                                 cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
+
+       typedef CL_API_ENTRY cl_mem(CL_API_CALL *
+                                                                       PFNCLCREATEIMAGE2D)(cl_context /* context */,
+                                                                                                               cl_mem_flags /* flags */,
+                                                                                                               const cl_image_format * /* image_format */,
+                                                                                                               size_t /* image_width */,
+                                                                                                               size_t /* image_height */,
+                                                                                                               size_t /* image_row_pitch */,
+                                                                                                               void * /* host_ptr */,
+                                                                                                               cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_mem(CL_API_CALL *
+                                                                       PFNCLCREATEIMAGE3D)(cl_context /* context */,
+                                                                                                               cl_mem_flags /* flags */,
+                                                                                                               const cl_image_format * /* image_format */,
+                                                                                                               size_t /* image_width */,
+                                                                                                               size_t /* image_height */,
+                                                                                                               size_t /* image_depth */,
+                                                                                                               size_t /* image_row_pitch */,
+                                                                                                               size_t /* image_slice_pitch */,
+                                                                                                               void * /* host_ptr */,
+                                                                                                               cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRETAINMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRELEASEMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETSUPPORTEDIMAGEFORMATS)(cl_context /* context */,
+                                                                                                                                  cl_mem_flags /* flags */,
+                                                                                                                                  cl_mem_object_type /* image_type */,
+                                                                                                                                  cl_uint /* num_entries */,
+                                                                                                                                  cl_image_format * /* image_formats */,
+                                                                                                                                  cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETMEMOBJECTINFO)(cl_mem /* memobj */,
+                                                                                                                  cl_mem_info /* param_name */,
+                                                                                                                  size_t /* param_value_size */,
+                                                                                                                  void * /* param_value */,
+                                                                                                                  size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETIMAGEINFO)(cl_mem /* image */,
+                                                                                                          cl_image_info /* param_name */,
+                                                                                                          size_t /* param_value_size */,
+                                                                                                          void * /* param_value */,
+                                                                                                          size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)(cl_mem /* memobj */,
+                                                                                                                                                void(CL_CALLBACK * /*pfn_notify*/)(cl_mem /* memobj */, void * /*user_data*/),
+                                                                                                                                                void * /*user_data */) CL_API_SUFFIX__VERSION_1_1;
+
+       /* Sampler APIs  */
+       typedef CL_API_ENTRY cl_sampler(CL_API_CALL *
+                                                                               PFNCLCREATESAMPLER)(cl_context /* context */,
+                                                                                                                       cl_bool /* normalized_coords */,
+                                                                                                                       cl_addressing_mode /* addressing_mode */,
+                                                                                                                       cl_filter_mode /* filter_mode */,
+                                                                                                                       cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRETAINSAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRELEASESAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETSAMPLERINFO)(cl_sampler /* sampler */,
+                                                                                                                cl_sampler_info /* param_name */,
+                                                                                                                size_t /* param_value_size */,
+                                                                                                                void * /* param_value */,
+                                                                                                                size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       /* Program Object APIs  */
+       typedef CL_API_ENTRY cl_program(CL_API_CALL *
+                                                                               PFNCLCREATEPROGRAMWITHSOURCE)(cl_context /* context */,
+                                                                                                                                         cl_uint /* count */,
+                                                                                                                                         const char ** /* strings */,
+                                                                                                                                         const size_t * /* lengths */,
+                                                                                                                                         cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_program(CL_API_CALL *
+                                                                               PFNCLCREATEPROGRAMWITHBINARY)(cl_context /* context */,
+                                                                                                                                         cl_uint /* num_devices */,
+                                                                                                                                         const cl_device_id * /* device_list */,
+                                                                                                                                         const size_t * /* lengths */,
+                                                                                                                                         const unsigned char ** /* binaries */,
+                                                                                                                                         cl_int * /* binary_status */,
+                                                                                                                                         cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRETAINPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRELEASEPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLBUILDPROGRAM)(cl_program /* program */,
+                                                                                                          cl_uint /* num_devices */,
+                                                                                                          const cl_device_id * /* device_list */,
+                                                                                                          const char * /* options */,
+                                                                                                          void(CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
+                                                                                                          void * /* user_data */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLUNLOADCOMPILER)(void) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETPROGRAMINFO)(cl_program /* program */,
+                                                                                                                cl_program_info /* param_name */,
+                                                                                                                size_t /* param_value_size */,
+                                                                                                                void * /* param_value */,
+                                                                                                                size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETPROGRAMBUILDINFO)(cl_program /* program */,
+                                                                                                                         cl_device_id /* device */,
+                                                                                                                         cl_program_build_info /* param_name */,
+                                                                                                                         size_t /* param_value_size */,
+                                                                                                                         void * /* param_value */,
+                                                                                                                         size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       /* Kernel Object APIs */
+       typedef CL_API_ENTRY cl_kernel(CL_API_CALL *
+                                                                          PFNCLCREATEKERNEL)(cl_program /* program */,
+                                                                                                                 const char * /* kernel_name */,
+                                                                                                                 cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLCREATEKERNELSINPROGRAM)(cl_program /* program */,
+                                                                                                                                cl_uint /* num_kernels */,
+                                                                                                                                cl_kernel * /* kernels */,
+                                                                                                                                cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRETAINKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRELEASEKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLSETKERNELARG)(cl_kernel /* kernel */,
+                                                                                                          cl_uint /* arg_index */,
+                                                                                                          size_t /* arg_size */,
+                                                                                                          const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETKERNELINFO)(cl_kernel /* kernel */,
+                                                                                                               cl_kernel_info /* param_name */,
+                                                                                                               size_t /* param_value_size */,
+                                                                                                               void * /* param_value */,
+                                                                                                               size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETKERNELWORKGROUPINFO)(cl_kernel /* kernel */,
+                                                                                                                                cl_device_id /* device */,
+                                                                                                                                cl_kernel_work_group_info /* param_name */,
+                                                                                                                                size_t /* param_value_size */,
+                                                                                                                                void * /* param_value */,
+                                                                                                                                size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       // Event Object APIs
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLWAITFOREVENTS)(cl_uint /* num_events */,
+                                                                                                               const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETEVENTINFO)(cl_event /* event */,
+                                                                                                          cl_event_info /* param_name */,
+                                                                                                          size_t /* param_value_size */,
+                                                                                                          void * /* param_value */,
+                                                                                                          size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_event(CL_API_CALL *
+                                                                         PFNCLCREATEUSEREVENT)(cl_context /* context */,
+                                                                                                                       cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRETAINEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLRELEASEEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLSETUSEREVENTSTATUS)(cl_event /* event */,
+                                                                                                                        cl_int /* execution_status */) CL_API_SUFFIX__VERSION_1_1;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLSETEVENTCALLBACK)(cl_event /* event */,
+                                                                                                                  cl_int /* command_exec_callback_type */,
+                                                                                                                  void(CL_CALLBACK * /* pfn_notify */)(cl_event, cl_int, void *),
+                                                                                                                  void * /* user_data */) CL_API_SUFFIX__VERSION_1_1;
+
+       /* Profiling APIs  */
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLGETEVENTPROFILINGINFO)(cl_event /* event */,
+                                                                                                                               cl_profiling_info /* param_name */,
+                                                                                                                               size_t /* param_value_size */,
+                                                                                                                               void * /* param_value */,
+                                                                                                                               size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
+
+       // Flush and Finish APIs
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLFLUSH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLFINISH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+       /* Enqueued Commands APIs */
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUEREADBUFFER)(cl_command_queue /* command_queue */,
+                                                                                                                       cl_mem /* buffer */,
+                                                                                                                       cl_bool /* blocking_read */,
+                                                                                                                       size_t /* offset */,
+                                                                                                                       size_t /* cb */,
+                                                                                                                       void * /* ptr */,
+                                                                                                                       cl_uint /* num_events_in_wait_list */,
+                                                                                                                       const cl_event * /* event_wait_list */,
+                                                                                                                       cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUEREADBUFFERRECT)(cl_command_queue /* command_queue */,
+                                                                                                                               cl_mem /* buffer */,
+                                                                                                                               cl_bool /* blocking_read */,
+                                                                                                                               const size_t * /* buffer_origin */,
+                                                                                                                               const size_t * /* host_origin */,
+                                                                                                                               const size_t * /* region */,
+                                                                                                                               size_t /* buffer_row_pitch */,
+                                                                                                                               size_t /* buffer_slice_pitch */,
+                                                                                                                               size_t /* host_row_pitch */,
+                                                                                                                               size_t /* host_slice_pitch */,
+                                                                                                                               void * /* ptr */,
+                                                                                                                               cl_uint /* num_events_in_wait_list */,
+                                                                                                                               const cl_event * /* event_wait_list */,
+                                                                                                                               cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUEWRITEBUFFER)(cl_command_queue /* command_queue */,
+                                                                                                                        cl_mem /* buffer */,
+                                                                                                                        cl_bool /* blocking_write */,
+                                                                                                                        size_t /* offset */,
+                                                                                                                        size_t /* cb */,
+                                                                                                                        const void * /* ptr */,
+                                                                                                                        cl_uint /* num_events_in_wait_list */,
+                                                                                                                        const cl_event * /* event_wait_list */,
+                                                                                                                        cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUEWRITEBUFFERRECT)(cl_command_queue /* command_queue */,
+                                                                                                                                cl_mem /* buffer */,
+                                                                                                                                cl_bool /* blocking_write */,
+                                                                                                                                const size_t * /* buffer_origin */,
+                                                                                                                                const size_t * /* host_origin */,
+                                                                                                                                const size_t * /* region */,
+                                                                                                                                size_t /* buffer_row_pitch */,
+                                                                                                                                size_t /* buffer_slice_pitch */,
+                                                                                                                                size_t /* host_row_pitch */,
+                                                                                                                                size_t /* host_slice_pitch */,
+                                                                                                                                const void * /* ptr */,
+                                                                                                                                cl_uint /* num_events_in_wait_list */,
+                                                                                                                                const cl_event * /* event_wait_list */,
+                                                                                                                                cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUECOPYBUFFER)(cl_command_queue /* command_queue */,
+                                                                                                                       cl_mem /* src_buffer */,
+                                                                                                                       cl_mem /* dst_buffer */,
+                                                                                                                       size_t /* src_offset */,
+                                                                                                                       size_t /* dst_offset */,
+                                                                                                                       size_t /* cb */,
+                                                                                                                       cl_uint /* num_events_in_wait_list */,
+                                                                                                                       const cl_event * /* event_wait_list */,
+                                                                                                                       cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUECOPYBUFFERRECT)(cl_command_queue /* command_queue */,
+                                                                                                                               cl_mem /* src_buffer */,
+                                                                                                                               cl_mem /* dst_buffer */,
+                                                                                                                               const size_t * /* src_origin */,
+                                                                                                                               const size_t * /* dst_origin */,
+                                                                                                                               const size_t * /* region */,
+                                                                                                                               size_t /* src_row_pitch */,
+                                                                                                                               size_t /* src_slice_pitch */,
+                                                                                                                               size_t /* dst_row_pitch */,
+                                                                                                                               size_t /* dst_slice_pitch */,
+                                                                                                                               cl_uint /* num_events_in_wait_list */,
+                                                                                                                               const cl_event * /* event_wait_list */,
+                                                                                                                               cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUEREADIMAGE)(cl_command_queue /* command_queue */,
+                                                                                                                  cl_mem /* image */,
+                                                                                                                  cl_bool /* blocking_read */,
+                                                                                                                  const size_t * /* origin[3] */,
+                                                                                                                  const size_t * /* region[3] */,
+                                                                                                                  size_t /* row_pitch */,
+                                                                                                                  size_t /* slice_pitch */,
+                                                                                                                  void * /* ptr */,
+                                                                                                                  cl_uint /* num_events_in_wait_list */,
+                                                                                                                  const cl_event * /* event_wait_list */,
+                                                                                                                  cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUEWRITEIMAGE)(cl_command_queue /* command_queue */,
+                                                                                                                       cl_mem /* image */,
+                                                                                                                       cl_bool /* blocking_write */,
+                                                                                                                       const size_t * /* origin[3] */,
+                                                                                                                       const size_t * /* region[3] */,
+                                                                                                                       size_t /* input_row_pitch */,
+                                                                                                                       size_t /* input_slice_pitch */,
+                                                                                                                       const void * /* ptr */,
+                                                                                                                       cl_uint /* num_events_in_wait_list */,
+                                                                                                                       const cl_event * /* event_wait_list */,
+                                                                                                                       cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUECOPYIMAGE)(cl_command_queue /* command_queue */,
+                                                                                                                  cl_mem /* src_image */,
+                                                                                                                  cl_mem /* dst_image */,
+                                                                                                                  const size_t * /* src_origin[3] */,
+                                                                                                                  const size_t * /* dst_origin[3] */,
+                                                                                                                  const size_t * /* region[3] */,
+                                                                                                                  cl_uint /* num_events_in_wait_list */,
+                                                                                                                  const cl_event * /* event_wait_list */,
+                                                                                                                  cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUECOPYIMAGETOBUFFER)(cl_command_queue /* command_queue */,
+                                                                                                                                  cl_mem /* src_image */,
+                                                                                                                                  cl_mem /* dst_buffer */,
+                                                                                                                                  const size_t * /* src_origin[3] */,
+                                                                                                                                  const size_t * /* region[3] */,
+                                                                                                                                  size_t /* dst_offset */,
+                                                                                                                                  cl_uint /* num_events_in_wait_list */,
+                                                                                                                                  const cl_event * /* event_wait_list */,
+                                                                                                                                  cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUECOPYBUFFERTOIMAGE)(cl_command_queue /* command_queue */,
+                                                                                                                                  cl_mem /* src_buffer */,
+                                                                                                                                  cl_mem /* dst_image */,
+                                                                                                                                  size_t /* src_offset */,
+                                                                                                                                  const size_t * /* dst_origin[3] */,
+                                                                                                                                  const size_t * /* region[3] */,
+                                                                                                                                  cl_uint /* num_events_in_wait_list */,
+                                                                                                                                  const cl_event * /* event_wait_list */,
+                                                                                                                                  cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY void *(CL_API_CALL *
+                                                                       PFNCLENQUEUEMAPBUFFER)(cl_command_queue /* command_queue */,
+                                                                                                                  cl_mem /* buffer */,
+                                                                                                                  cl_bool /* blocking_map */,
+                                                                                                                  cl_map_flags /* map_flags */,
+                                                                                                                  size_t /* offset */,
+                                                                                                                  size_t /* cb */,
+                                                                                                                  cl_uint /* num_events_in_wait_list */,
+                                                                                                                  const cl_event * /* event_wait_list */,
+                                                                                                                  cl_event * /* event */,
+                                                                                                                  cl_int * /* errcode_ret */)CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY void *(CL_API_CALL *
+                                                                       PFNCLENQUEUEMAPIMAGE)(cl_command_queue /* command_queue */,
+                                                                                                                 cl_mem /* image */,
+                                                                                                                 cl_bool /* blocking_map */,
+                                                                                                                 cl_map_flags /* map_flags */,
+                                                                                                                 const size_t * /* origin[3] */,
+                                                                                                                 const size_t * /* region[3] */,
+                                                                                                                 size_t * /* image_row_pitch */,
+                                                                                                                 size_t * /* image_slice_pitch */,
+                                                                                                                 cl_uint /* num_events_in_wait_list */,
+                                                                                                                 const cl_event * /* event_wait_list */,
+                                                                                                                 cl_event * /* event */,
+                                                                                                                 cl_int * /* errcode_ret */)CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUEUNMAPMEMOBJECT)(cl_command_queue /* command_queue */,
+                                                                                                                               cl_mem /* memobj */,
+                                                                                                                               void * /* mapped_ptr */,
+                                                                                                                               cl_uint /* num_events_in_wait_list */,
+                                                                                                                               const cl_event * /* event_wait_list */,
+                                                                                                                               cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUENDRANGEKERNEL)(cl_command_queue /* command_queue */,
+                                                                                                                          cl_kernel /* kernel */,
+                                                                                                                          cl_uint /* work_dim */,
+                                                                                                                          const size_t * /* global_work_offset */,
+                                                                                                                          const size_t * /* global_work_size */,
+                                                                                                                          const size_t * /* local_work_size */,
+                                                                                                                          cl_uint /* num_events_in_wait_list */,
+                                                                                                                          const cl_event * /* event_wait_list */,
+                                                                                                                          cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUETASK)(cl_command_queue /* command_queue */,
+                                                                                                         cl_kernel /* kernel */,
+                                                                                                         cl_uint /* num_events_in_wait_list */,
+                                                                                                         const cl_event * /* event_wait_list */,
+                                                                                                         cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUENATIVEKERNEL)(cl_command_queue /* command_queue */,
+                                                                                                                         void (*user_func)(void *),
+                                                                                                                         void * /* args */,
+                                                                                                                         size_t /* cb_args */,
+                                                                                                                         cl_uint /* num_mem_objects */,
+                                                                                                                         const cl_mem * /* mem_list */,
+                                                                                                                         const void ** /* args_mem_loc */,
+                                                                                                                         cl_uint /* num_events_in_wait_list */,
+                                                                                                                         const cl_event * /* event_wait_list */,
+                                                                                                                         cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUEMARKER)(cl_command_queue /* command_queue */,
+                                                                                                               cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUEWAITFOREVENTS)(cl_command_queue /* command_queue */,
+                                                                                                                          cl_uint /* num_events */,
+                                                                                                                          const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
+
+       typedef CL_API_ENTRY cl_int(CL_API_CALL *
+                                                                       PFNCLENQUEUEBARRIER)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
+
+       // Extension function access
+       //
+       // Returns the extension function address for the given function name,
+       // or NULL if a valid function can not be found.  The client must
+       // check to make sure the address is not NULL, before using or
+       // calling the returned function address.
+       //
+       typedef CL_API_ENTRY void *(CL_API_CALL *PFNCLGETEXTENSIONFUNCTIONADDRESS)(const char * /* func_name */)CL_API_SUFFIX__VERSION_1_0;
+
+#define CLEW_STATIC
+
+#ifdef CLEW_STATIC
+#define CLEWAPI extern
+#else
+#ifdef CLEW_BUILD
+#define CLEWAPI extern __declspec(dllexport)
+#else
+#define CLEWAPI extern __declspec(dllimport)
+#endif
+#endif
+
+#if defined(_WIN32)
+#define CLEW_FUN_EXPORT extern
+#else
+#define CLEW_FUN_EXPORT CLEWAPI
+#endif
+
+#define CLEW_GET_FUN(x) x
+
+       //  Variables holding function entry points
+       CLEW_FUN_EXPORT PFNCLGETPLATFORMIDS __clewGetPlatformIDs;
+       CLEW_FUN_EXPORT PFNCLGETPLATFORMINFO __clewGetPlatformInfo;
+       CLEW_FUN_EXPORT PFNCLGETDEVICEIDS __clewGetDeviceIDs;
+       CLEW_FUN_EXPORT PFNCLGETDEVICEINFO __clewGetDeviceInfo;
+       CLEW_FUN_EXPORT PFNCLCREATECONTEXT __clewCreateContext;
+       CLEW_FUN_EXPORT PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType;
+       CLEW_FUN_EXPORT PFNCLRETAINCONTEXT __clewRetainContext;
+       CLEW_FUN_EXPORT PFNCLRELEASECONTEXT __clewReleaseContext;
+       CLEW_FUN_EXPORT PFNCLGETCONTEXTINFO __clewGetContextInfo;
+       CLEW_FUN_EXPORT PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue;
+       CLEW_FUN_EXPORT PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue;
+       CLEW_FUN_EXPORT PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue;
+       CLEW_FUN_EXPORT PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo;
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+       CLEW_FUN_EXPORT PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty;
+#endif
+       CLEW_FUN_EXPORT PFNCLCREATEBUFFER __clewCreateBuffer;
+       CLEW_FUN_EXPORT PFNCLCREATESUBBUFFER __clewCreateSubBuffer;
+       CLEW_FUN_EXPORT PFNCLCREATEIMAGE2D __clewCreateImage2D;
+       CLEW_FUN_EXPORT PFNCLCREATEIMAGE3D __clewCreateImage3D;
+       CLEW_FUN_EXPORT PFNCLRETAINMEMOBJECT __clewRetainMemObject;
+       CLEW_FUN_EXPORT PFNCLRELEASEMEMOBJECT __clewReleaseMemObject;
+       CLEW_FUN_EXPORT PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats;
+       CLEW_FUN_EXPORT PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo;
+       CLEW_FUN_EXPORT PFNCLGETIMAGEINFO __clewGetImageInfo;
+       CLEW_FUN_EXPORT PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback;
+       CLEW_FUN_EXPORT PFNCLCREATESAMPLER __clewCreateSampler;
+       CLEW_FUN_EXPORT PFNCLRETAINSAMPLER __clewRetainSampler;
+       CLEW_FUN_EXPORT PFNCLRELEASESAMPLER __clewReleaseSampler;
+       CLEW_FUN_EXPORT PFNCLGETSAMPLERINFO __clewGetSamplerInfo;
+       CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource;
+       CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary;
+       CLEW_FUN_EXPORT PFNCLRETAINPROGRAM __clewRetainProgram;
+       CLEW_FUN_EXPORT PFNCLRELEASEPROGRAM __clewReleaseProgram;
+       CLEW_FUN_EXPORT PFNCLBUILDPROGRAM __clewBuildProgram;
+       CLEW_FUN_EXPORT PFNCLUNLOADCOMPILER __clewUnloadCompiler;
+       CLEW_FUN_EXPORT PFNCLGETPROGRAMINFO __clewGetProgramInfo;
+       CLEW_FUN_EXPORT PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo;
+       CLEW_FUN_EXPORT PFNCLCREATEKERNEL __clewCreateKernel;
+       CLEW_FUN_EXPORT PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram;
+       CLEW_FUN_EXPORT PFNCLRETAINKERNEL __clewRetainKernel;
+       CLEW_FUN_EXPORT PFNCLRELEASEKERNEL __clewReleaseKernel;
+       CLEW_FUN_EXPORT PFNCLSETKERNELARG __clewSetKernelArg;
+       CLEW_FUN_EXPORT PFNCLGETKERNELINFO __clewGetKernelInfo;
+       CLEW_FUN_EXPORT PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo;
+       CLEW_FUN_EXPORT PFNCLWAITFOREVENTS __clewWaitForEvents;
+       CLEW_FUN_EXPORT PFNCLGETEVENTINFO __clewGetEventInfo;
+       CLEW_FUN_EXPORT PFNCLCREATEUSEREVENT __clewCreateUserEvent;
+       CLEW_FUN_EXPORT PFNCLRETAINEVENT __clewRetainEvent;
+       CLEW_FUN_EXPORT PFNCLRELEASEEVENT __clewReleaseEvent;
+       CLEW_FUN_EXPORT PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus;
+       CLEW_FUN_EXPORT PFNCLSETEVENTCALLBACK __clewSetEventCallback;
+       CLEW_FUN_EXPORT PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo;
+       CLEW_FUN_EXPORT PFNCLFLUSH __clewFlush;
+       CLEW_FUN_EXPORT PFNCLFINISH __clewFinish;
+       CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer;
+       CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect;
+       CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer;
+       CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect;
+       CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer;
+       CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect;
+       CLEW_FUN_EXPORT PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage;
+       CLEW_FUN_EXPORT PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage;
+       CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage;
+       CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer;
+       CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage;
+       CLEW_FUN_EXPORT PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer;
+       CLEW_FUN_EXPORT PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage;
+       CLEW_FUN_EXPORT PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject;
+       CLEW_FUN_EXPORT PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel;
+       CLEW_FUN_EXPORT PFNCLENQUEUETASK __clewEnqueueTask;
+       CLEW_FUN_EXPORT PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel;
+       CLEW_FUN_EXPORT PFNCLENQUEUEMARKER __clewEnqueueMarker;
+       CLEW_FUN_EXPORT PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents;
+       CLEW_FUN_EXPORT PFNCLENQUEUEBARRIER __clewEnqueueBarrier;
+       CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress;
+
+#define clGetPlatformIDs CLEW_GET_FUN(__clewGetPlatformIDs)
+#define clGetPlatformInfo CLEW_GET_FUN(__clewGetPlatformInfo)
+#define clGetDeviceIDs CLEW_GET_FUN(__clewGetDeviceIDs)
+#define clGetDeviceInfo CLEW_GET_FUN(__clewGetDeviceInfo)
+#define clCreateContext CLEW_GET_FUN(__clewCreateContext)
+#define clCreateContextFromType CLEW_GET_FUN(__clewCreateContextFromType)
+#define clRetainContext CLEW_GET_FUN(__clewRetainContext)
+#define clReleaseContext CLEW_GET_FUN(__clewReleaseContext)
+#define clGetContextInfo CLEW_GET_FUN(__clewGetContextInfo)
+#define clCreateCommandQueue CLEW_GET_FUN(__clewCreateCommandQueue)
+#define clRetainCommandQueue CLEW_GET_FUN(__clewRetainCommandQueue)
+#define clReleaseCommandQueue CLEW_GET_FUN(__clewReleaseCommandQueue)
+#define clGetCommandQueueInfo CLEW_GET_FUN(__clewGetCommandQueueInfo)
+#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
+#warning CL_USE_DEPRECATED_OPENCL_1_0_APIS is defined. These APIs are unsupported and untested in OpenCL 1.1!
+/* 
+ *  WARNING:
+ *     This API introduces mutable state into the OpenCL implementation. It has been REMOVED
+ *  to better facilitate thread safety.  The 1.0 API is not thread safe. It is not tested by the
+ *  OpenCL 1.1 conformance test, and consequently may not work or may not work dependably.
+ *  It is likely to be non-performant. Use of this API is not advised. Use at your own risk.
+ *
+ *  Software developers previously relying on this API are instructed to set the command queue 
+ *  properties when creating the queue, instead. 
+ */
+#define clSetCommandQueueProperty CLEW_GET_FUN(__clewSetCommandQueueProperty)
+#endif /* CL_USE_DEPRECATED_OPENCL_1_0_APIS */
+#define clCreateBuffer CLEW_GET_FUN(__clewCreateBuffer)
+#define clCreateSubBuffer CLEW_GET_FUN(__clewCreateSubBuffer)
+#define clCreateImage2D CLEW_GET_FUN(__clewCreateImage2D)
+#define clCreateImage3D CLEW_GET_FUN(__clewCreateImage3D)
+#define clRetainMemObject CLEW_GET_FUN(__clewRetainMemObject)
+#define clReleaseMemObject CLEW_GET_FUN(__clewReleaseMemObject)
+#define clGetSupportedImageFormats CLEW_GET_FUN(__clewGetSupportedImageFormats)
+#define clGetMemObjectInfo CLEW_GET_FUN(__clewGetMemObjectInfo)
+#define clGetImageInfo CLEW_GET_FUN(__clewGetImageInfo)
+#define clSetMemObjectDestructorCallback CLEW_GET_FUN(__clewSetMemObjectDestructorCallback)
+#define clCreateSampler CLEW_GET_FUN(__clewCreateSampler)
+#define clRetainSampler CLEW_GET_FUN(__clewRetainSampler)
+#define clReleaseSampler CLEW_GET_FUN(__clewReleaseSampler)
+#define clGetSamplerInfo CLEW_GET_FUN(__clewGetSamplerInfo)
+#define clCreateProgramWithSource CLEW_GET_FUN(__clewCreateProgramWithSource)
+#define clCreateProgramWithBinary CLEW_GET_FUN(__clewCreateProgramWithBinary)
+#define clRetainProgram CLEW_GET_FUN(__clewRetainProgram)
+#define clReleaseProgram CLEW_GET_FUN(__clewReleaseProgram)
+#define clBuildProgram CLEW_GET_FUN(__clewBuildProgram)
+#define clUnloadCompiler CLEW_GET_FUN(__clewUnloadCompiler)
+#define clGetProgramInfo CLEW_GET_FUN(__clewGetProgramInfo)
+#define clGetProgramBuildInfo CLEW_GET_FUN(__clewGetProgramBuildInfo)
+#define clCreateKernel CLEW_GET_FUN(__clewCreateKernel)
+#define clCreateKernelsInProgram CLEW_GET_FUN(__clewCreateKernelsInProgram)
+#define clRetainKernel CLEW_GET_FUN(__clewRetainKernel)
+#define clReleaseKernel CLEW_GET_FUN(__clewReleaseKernel)
+#define clSetKernelArg CLEW_GET_FUN(__clewSetKernelArg)
+#define clGetKernelInfo CLEW_GET_FUN(__clewGetKernelInfo)
+#define clGetKernelWorkGroupInfo CLEW_GET_FUN(__clewGetKernelWorkGroupInfo)
+#define clWaitForEvents CLEW_GET_FUN(__clewWaitForEvents)
+#define clGetEventInfo CLEW_GET_FUN(__clewGetEventInfo)
+#define clCreateUserEvent CLEW_GET_FUN(__clewCreateUserEvent)
+#define clRetainEvent CLEW_GET_FUN(__clewRetainEvent)
+#define clReleaseEvent CLEW_GET_FUN(__clewReleaseEvent)
+#define clSetUserEventStatus CLEW_GET_FUN(__clewSetUserEventStatus)
+#define clSetEventCallback CLEW_GET_FUN(__clewSetEventCallback)
+#define clGetEventProfilingInfo CLEW_GET_FUN(__clewGetEventProfilingInfo)
+#define clFlush CLEW_GET_FUN(__clewFlush)
+#define clFinish CLEW_GET_FUN(__clewFinish)
+#define clEnqueueReadBuffer CLEW_GET_FUN(__clewEnqueueReadBuffer)
+#define clEnqueueReadBufferRect CLEW_GET_FUN(__clewEnqueueReadBufferRect)
+#define clEnqueueWriteBuffer CLEW_GET_FUN(__clewEnqueueWriteBuffer)
+#define clEnqueueWriteBufferRect CLEW_GET_FUN(__clewEnqueueWriteBufferRect)
+#define clEnqueueCopyBuffer CLEW_GET_FUN(__clewEnqueueCopyBuffer)
+#define clEnqueueCopyBufferRect CLEW_GET_FUN(__clewEnqueueCopyBufferRect)
+#define clEnqueueReadImage CLEW_GET_FUN(__clewEnqueueReadImage)
+#define clEnqueueWriteImage CLEW_GET_FUN(__clewEnqueueWriteImage)
+#define clEnqueueCopyImage CLEW_GET_FUN(__clewEnqueueCopyImage)
+#define clEnqueueCopyImageToBuffer CLEW_GET_FUN(__clewEnqueueCopyImageToBuffer)
+#define clEnqueueCopyBufferToImage CLEW_GET_FUN(__clewEnqueueCopyBufferToImage)
+#define clEnqueueMapBuffer CLEW_GET_FUN(__clewEnqueueMapBuffer)
+#define clEnqueueMapImage CLEW_GET_FUN(__clewEnqueueMapImage)
+#define clEnqueueUnmapMemObject CLEW_GET_FUN(__clewEnqueueUnmapMemObject)
+#define clEnqueueNDRangeKernel CLEW_GET_FUN(__clewEnqueueNDRangeKernel)
+#define clEnqueueTask CLEW_GET_FUN(__clewEnqueueTask)
+#define clEnqueueNativeKernel CLEW_GET_FUN(__clewEnqueueNativeKernel)
+#define clEnqueueMarker CLEW_GET_FUN(__clewEnqueueMarker)
+#define clEnqueueWaitForEvents CLEW_GET_FUN(__clewEnqueueWaitForEvents)
+#define clEnqueueBarrier CLEW_GET_FUN(__clewEnqueueBarrier)
+#define clGetExtensionFunctionAddress CLEW_GET_FUN(__clewGetExtensionFunctionAddress)
+
+#define CLEW_SUCCESS 0               //!<    Success error code
+#define CLEW_ERROR_OPEN_FAILED -1    //!<    Error code for failing to open the dynamic library
+#define CLEW_ERROR_ATEXIT_FAILED -2  //!<    Error code for failing to queue the closing of the dynamic library to atexit()
+
+       //! \brief Load OpenCL dynamic library and set function entry points
+       int clewInit(const char *);
+
+       //! \brief Exit clew and unload OpenCL dynamic library
+       void clewExit();
+
+       //! \brief Convert an OpenCL error code to its string equivalent
+       const char *clewErrorString(cl_int error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  //  CLEW_HPP_INCLUDED
diff --git a/dali-physics/third-party/chipmunk2d/.gitignore b/dali-physics/third-party/chipmunk2d/.gitignore
new file mode 100644 (file)
index 0000000..1167175
--- /dev/null
@@ -0,0 +1,60 @@
+.DS_Store\r
+doc/index.html\r
+\r
+*.pbxuser\r
+*.perspectivev3\r
+xcshareddata\r
+xcuserdata\r
+project.xcworkspace\r
+DerivedData\r
+build\r
+Chipmunk-Mac\r
+Chipmunk-iOS\r
+ObjectiveChipmunk-Mac\r
+ObjectiveChipmunk-iOS\r
+generated_docs\r
+\r
+CMakeCache.txt\r
+CMakeFiles\r
+Makefile\r
+cmake_install.cmake\r
+install_manifest.txt\r
+\r
+*.o\r
+*.obj\r
+*.dll\r
+*.so\r
+*.so.*\r
+*.dylib\r
+*.a\r
+*.exe\r
+*.lib\r
+chipmunk_demos\r
+\r
+# Visual studio\r
+*.opensdf\r
+*.opendb\r
+*.sdf\r
+*.suo\r
+*.pdb\r
+*.vcxproj.user\r
+msvc/vc10/demo/ipch/\r
+msvc/vc10/chipmunk/Win32/\r
+msvc/vc10/chipmunk/x64/\r
+msvc/vc10/demo/Win32/\r
+msvc/vc10/demo/x64/\r
+msvc/vc12/chipmunk/Win32/\r
+msvc/vc12/chipmunk/x64/\r
+msvc/vc12/demo/Win32/\r
+msvc/vc12/demo/x64/\r
+msvc/vc13/chipmunk/Win32/\r
+msvc/vc13/chipmunk/x64/\r
+msvc/vc13/demo/Win32/\r
+msvc/vc13/demo/x64/\r
+msvc/vc14/demo/Win32/\r
+msvc/vc14/demo/x64/\r
+*.log\r
+*.tlog\r
+*.db\r
+\r
+.vscode\r
diff --git a/dali-physics/third-party/chipmunk2d/CMakeLists.txt b/dali-physics/third-party/chipmunk2d/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9166edb
--- /dev/null
@@ -0,0 +1,53 @@
+cmake_minimum_required(VERSION 3.7)
+
+project(chipmunk)
+
+# to change the prefix, run cmake with the parameter:
+#   -D CMAKE_INSTALL_PREFIX=/my/prefix
+
+# to change the build type, run cmake with the parameter:
+#   -D CMAKE_BUILD_TYPE=<build-type>
+# run "cmake --help-variable CMAKE_BUILD_TYPE" for details
+if(NOT CMAKE_BUILD_TYPE)
+  SET(CMAKE_BUILD_TYPE Release CACHE STRING
+      "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
+      FORCE)
+endif()
+
+# to manually select install locations of libraries and executables
+#   -D LIB_INSTALL_DIR mylib
+#   -D BIN_INSTALL_DIR newbin
+set(LIB_INSTALL_DIR ${LIB_DIR} CACHE STRING "Install location of libraries")
+set(BIN_INSTALL_DIR bin CACHE STRING "Install location of executables")
+
+# other options for the build, you can i.e. activate the shared library by passing
+#   -D BUILD_SHARED=ON
+# to cmake. Other options analog
+if(ANDROID)
+  option(BUILD_SHARED "Build and install the shared library" ON)
+  option(BUILD_STATIC "Build as static library" ON)
+  option(INSTALL_STATIC "Install the static library" OFF)
+else()
+  option(BUILD_SHARED "Build and install the shared library" ON)
+  option(BUILD_STATIC "Build as static library" ON)
+  option(INSTALL_STATIC "Install the static library" ON)
+endif()
+
+if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+  option(FORCE_CLANG_BLOCKS "Force enable Clang blocks" YES)
+endif()
+
+if(INSTALL_STATIC)
+  set(BUILD_STATIC ON FORCE)
+endif()
+
+if(NOT MSVC)
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") # always use gnu99
+  if(FORCE_CLANG_BLOCKS)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fblocks")
+  endif()
+  set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ffast-math") # extend release-profile with fast-math
+  set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall") # extend debug-profile with -Wall
+endif()
+
+add_subdirectory(src)
diff --git a/dali-physics/third-party/chipmunk2d/LICENSE.txt b/dali-physics/third-party/chipmunk2d/LICENSE.txt
new file mode 100644 (file)
index 0000000..55c24c9
--- /dev/null
@@ -0,0 +1,19 @@
+Copyright (c) 2007-2015 Scott Lembcke and Howling Moon Software
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/dali-physics/third-party/chipmunk2d/README.md b/dali-physics/third-party/chipmunk2d/README.md
new file mode 100644 (file)
index 0000000..1eca892
--- /dev/null
@@ -0,0 +1,8 @@
+# Bullet Physics SDK
+
+This is the Chipmunk2D Physics Library Version 7.0.3.
+
+The commit used is: [87340c2](https://github.com/slembcke/Chipmunk2D/commit/87340c216bf97554dc552371bbdecf283f7c540e).
+
+Please refer to [Chipmunk2D Physics Library Github](https://github.com/slembcke/Chipmunk2D/tree/Chipmunk-7.0.3) for further information.
+
diff --git a/dali-physics/third-party/chipmunk2d/TODO.txt b/dali-physics/third-party/chipmunk2d/TODO.txt
new file mode 100644 (file)
index 0000000..e813c82
--- /dev/null
@@ -0,0 +1,52 @@
+Priorities:
+       Basics tutorial.
+       Simple top down player controls.
+       * test tiny omega bug in cpvslerp().
+       User definable default winding.
+       User definable fast collision filtering.
+       Assertion (or warning?) for destroying a body with things still attached
+       Bilinearly sampled image sampler function. (override the sample method to always take bilinear samples)
+       RGB Image Sampler class.
+       Reorganize Chimpnuk Pro directory structure. Too flat and confusing.
+       Improve the ACD splitting plane algorithm.
+       Fishing game
+       Motorcycle in a spinning cage
+       Squid thingy like TomorrowPlusX.
+
+       Investigate getting better PhysicsEditor support.
+
+Unordered
+       Fix solver issues with the groove joint.
+       Use a slop tolerance on joint boundaries.
+
+Website things
+       Don't make any mistakes: http://www.gamasutra.com/view/feature/185773/the_top_10_mistakes_tool_.php
+       Several people want a Chipmunk Facebook page.
+       figure out and redo front page. Chipmunk js examples.
+
+Future things to think about:
+       breakable object support functions?
+       Serialization
+       Tests for the query methods
+       Building bodies from shape collections.
+       Per body iterations and timestep?
+       Per body damping and gravity coefs?
+       Easy callback programable joint?
+       Top down racing game. (Need the callback constraint)
+       cpBodyActivateStatic() should also activate joints?
+
+Chipmunk 7:
+       Speculative contacts
+       User definable constraint
+       Custom contact constraint with rolling friction and per contact surface v.
+       Serialization
+       API changes, different body/shape instantiation.
+       Collision handler objects with additional callbacks.
+       Calculate contact anchors to get rid of contact pos. (needed for speculative contacts anyway)
+       Mass property calculation changes.
+       Change apply force/impulse and point velocity functions.
+       Separate doxygen docs for Objective-C parts and C parts.
+       Cocos2D xcode templates.
+       Custom contacts using cpArbiter user data.
+       Built in transform type.
+       
\ No newline at end of file
diff --git a/dali-physics/third-party/chipmunk2d/VERSION.txt b/dali-physics/third-party/chipmunk2d/VERSION.txt
new file mode 100644 (file)
index 0000000..489f434
--- /dev/null
@@ -0,0 +1,300 @@
+What's new in 7.0.3:
+* MISC: Replacing GLFW with Sokol in the demo application. No need to push GLFW binaries and has a nice x-platform renderer to build on.
+* MISC: Fixed some 'const' warnings for MSCV.
+
+What's new in 7.0.2:
+* MISC: Merging pull requests. Build fixes and the like.
+
+What's new in 7.0.1:
+* BUG: Remove references to M_PI sinces it's not actually part of C and causes problems with MSVC.
+* BUG: Build fixes for Mac/CMake and MSVC 13.
+* BUG: Move to using __declspec(dllexport) for Windows builds.
+* BUG: Fixed a precision issue with the EPA algorithm that would cause excessive iteration.
+* BUG: cpPolyshapeNewRaw() was undefined.
+* BUG: Changing gravity will wake up all objects in a space.
+
+What's new in 7.0.0:
+* All features from Chipmunk Pro are now free and open source! (threaded and NEON solver, autogeometry)
+* API: Lots of cleanup to the API naming for better consistency.
+* API: Renamed nearest point queries to simply point queries.
+* API: Removed many deprecated functions.
+* API: Struct definitions have become fully opaque instead of mangling names with the CP_PRIVATE() macro.
+* API: Replaced templated accessor functions with concrete ones. Should be simpler to deal with for FFIs.
+* API: Optional automatic mass properties for shapes. Calculates the moment of inertia and center of gravity for you.
+* API: Optional anchor point for bodies that is separate from the center of gravity.
+* API: Added radius parameters to many functions dealing with shapes (moment calculation, initialization, etc).
+* API: The convex hull and winding is automatically calculated when creating a poly shape.
+* API: Added a cpShapesCollide() function to check overlap of arbitrary shapes.
+* API: cpShape filter property to supersede layers and groups.
+* API: Collision handlers now return a collision handler struct to make it simpler to set up callbacks.
+* API: Wildcard collision types.
+* API: The cpArbiterTotalImpulseWithFriction() function was renamed to cpArbiterTotalImpulse(). The old useless cpArbiterTotalImpulse() implementation was removed.
+* API: Contacts now store the colliding point on the surface of both shapes.
+* API: cpArbiterIsRemoval() to check if a separate callback is called due to a removal and not a true separating collision.
+* API: Arbiters now only store one normal per pair of colliding shapes.
+* API: cpBBNewForExtents().
+* API: Added a concrete kinematic body type to replace the confusing "rogue" body concept.
+* API: Added a 2x3 affine transform type, cpTransform.
+* API: Added a new debug rendering API.
+* MISC: Numerous improvements to the collision detection.
+* MISC: cpPolyline structs are passed by reference instead of value. (I've regretted that decision for years!)
+
+What's new in 6.2.2:
+* Fixed some issues on arm64.
+* PRO: Added a 64 bit NEON solver to use on arm64.
+
+What's new in 6.2.1:
+* Added Android support to the CMake files. (Thanks Eric Wing!)
+* Added a MSVC 2012 project file. (Thanks Leonid Usov!)
+* Merged a fix for VAOs on Windows. (Thanks Leonid Usov!)
+* Merged a couple of other minor fixes.
+* BUG: Fixed a crash issue with the ChipmunkTileCache and ChipmunkPointCloudSampler classes. (Pro only).
+
+What's new in 6.2.0:
+* Collision detection now primarily uses the GJK and EPA algorithms instead of SAT. Internally this was a rather huge change. o_O
+* Improved collision point quality and better collision point identification.
+* All shape types can now be given a rounding radius.
+* Collisions are now guaranteed to have a maximum of 2 collision points.
+* Poly to poly collision performance is slightly better when they have a radius. Slightly worse with none.
+* Implemented smoothed segment collisions to prevent colliding with the "cracks" between segment shapes.
+* API: (Officially) added cpSegmentShapeSetNeighbors() used to enable smoothed line collisions.
+* API: Added cpBBCenter() to get the center of a bounding box.
+* API: Added cpPolyShapeInit2() and cpPolyShapeNew2() to create poly shapes with a radius. (Horrible names yes, but it will go away in Chipmunk 7)
+* API: Added cpBoxShapeInit3() and cpBoxShapeNew3() to create boxes with a radius.
+* API: Added cpPolyShapeGetRadius() and cpPolyShapeSetRadius() (the latter only in chipmunk_unsafe.h).
+* API: Added cpNearestPointQueryInfo.g which returns the gradient of the signed distance field for the shape.
+* BUG: cpMomentForPoly() will now return a correct value for degenerate 2 vertex polygons.
+* BUG: Fixed an issue where certain segment query calls would return a t value of 0 instead of 1 for a missed query.
+* MISC: Passing cpvzero to cpvnormalize() will now return cpvzero. No need to worry about NaNs or cpvnormalize_safe().
+* MISC: Demo app now uses GLFW instead of GLUT, and has improved drawing and text rendering routines.
+
+What's new in 6.1.5:
+* API: Added cpArbiter*SurfaceVelocity() to allow for custom surface velocity calculation.
+* API: Added cpArbiteSetContactPointSet() to allow changing the contact geometry on the fly.
+* API: Added cpSpaceConvertBodyToStatic() and cpSpaceConvertBodyToDynamic().
+* API: Added [ChipmunkBody velocityAt*Point:] methods to wrap their C equivalents. (Pro only)
+* API: Added overridable [ChipmunkBody updateVelocity:...] and [ChipmunkBody updatePosition:] methods. (Pro only)
+* API: Added .space properties to ChipmunkBody, ChipmunkShape and ChipmunkConstaint to wrap their C equivalents. (Pro only)
+* API: Added overridable [ChipmunkConstraint preSolve:] and [ChipmunkConstraint postSolve:] methods. (Pro only)
+* API: Added an ChipmunkMultiGrab.grabSort property that allows you to prioritize which shape is grabbed when there is overlap. (Pro only)
+* MISC: Segment queries started inside of a shape now return t=0 and n=cpvzero instead of being undefined.
+* MISC: Cleaned up a lot of common assertion messages to be more clear.
+* MISC: Added a new demo called Shatter.
+* MISC: Added a crushing force estimation example to the ContactGraph demo and a static/dynamic conversion example to Plink.
+* MISC: Modified the Sticky demo to use the new cpArbiteSetContactPointSet() to avoid the use of unnecessary sensor shapes.
+* MISC: [ChipmunkSpace addBounds:...] now returns a NSArray of the bounding segments. (Pro only)
+
+What's new in 6.1.4:
+* MISC: Fixed a build script issue that was preventing the documentation from being generated.
+
+What's new in 6.1.3:
+* BUG: Fixed a couple of very specific but fatal bugs that occur when sleeping is enabled and filtering collisions.
+* BUG: Fixed an issue with cpvslerp() between very similar vectors.
+* BUG: Fixed an issue with grab friction in ChipmunkMultiGrab. (Pro only)
+* MISC: Implemented the cpConstraintGetImpulse() functionality for spring joints.
+* MISC: Added more functions to chipmunk_ffi.h
+
+What's new in 6.1.2:
+* API: Added a cpArbiter.data pointer. Now you can tag collisions with custom persistent data.
+* API: Added segment to segment collisions (thanks to LegoCylon)
+* API: cpSpaceAddPostStepCallback() now returns false if the callback was a duplicate.
+* API: Added the ChipmunkAbstractSampler.marchThreshold property instead of hardcoding it to 0.5.
+* API: Added ChipmunkGrooveJoint properties for the groove and joint anchors.
+* API: ChipmunkMultiGrab now returns information about grabbed shapes.
+* BUG: Fixed a minor (non-crashing, non-leaking) memory pooling issue with reindexing lots of static shapes.
+* BUG: Fixed an issue with the slerp functions that would cause them to return incorrect results when given non-unit length input.
+* BUG: Fixed a precision bug with the ChipmunkImage sampler classes that could cause artifacts or miss small features.
+* BUG: Fixed a number of properties in Objective-Chipmunk that should have been nonatomic.
+* BUG: Fixed a number of types in Objective-Chipmunk that were incorrectly id that should have been cpGroup, cpCollisionType etc. It's now possible to redefine them at compile time if you wish.
+* MISC: Dropped armv6 support in favor of armv7s on iOS. (You can switch it back easily if you need.)
+* MISC: Updated iOS build scripts to guess the latest SDK.
+* MISC: Added the "Sticky Surfaces" demo as a cpArbiter.data example.
+* MISC: Updated Objective-Chipmunk build scripts to always use the latest iOS SDK.
+
+What's new in 6.1.1:
+* API: Renamed the new block based iterators as soon as possible to match the Apple convention ("_b" suffix).
+
+What's new in 6.1.0:
+* API: Added a pthread based, multi-threaded solver to accelerate the game on multi-core systems. (Pro only)
+* API: Added cpConvexHull() and CP_CONVEX_HULL() for generating convex hulls.
+* API: Added cpPolylineConvexDecomposition_BETA() to generate an approximate concave decomposition of a polyline. (Pro only)
+* API: Added [ChipmunkPolyline toConvexHull:] to generate approximate convex hulls. (Pro only).
+* API: Added [ChipmunkPolylineSet toConvexHulls_BETA:]. (Pro only)
+* API: Added nearest point queries.
+* API: Added a push mode to ChipmunkMultiGrab so touches can interact with the scene even if they didn't initially touch a shape. (Pro only)
+* API: Added optional block based iterators.
+* API: Added a space property to cpBody, cpShape and cpConstraint types.
+* BUG: Fixed an issue with changing the floating point and vector type on OS X.
+* BUG: Fixed a pixel offset in ChipmunkImageSampler that could cause minor sampling artifacts. (Pro only)
+* BUG: Fixed an issue where cpShape and cpConstraint structs could have garbage space pointers if cpcalloc() was redefined.
+* BUG: Fixed assertions in cpArbiter getters to correctly reflect a contact count of 0 from separate() callbacks.
+* BUG: Fixed a regression relating to registering post-step() callbacks from other post-step() callbacks.
+* BUG: Fixed a minor memory leak for sleeping bodies when destroying a space.
+* MISC: Point queries are now deprecated in preference to point queries.
+* MISC: cpSpatialIndexPointQuery() was redundant and has been removed. Use cpSpatialIndexQuery() instead.
+* MISC: cpShape*Query() functions now accept a NULL info pointer if you don't want detailed query info.
+* MISC: The enableContactGraph property of cpSpace is deprecated and always be true.
+* MISC: Added a new demos of the convex hull functions and a self balancing Unicycle.
+
+What's new in 6.0.3:
+* API: Added a cpBBForCircle() convenience function.
+* API: Added cpBBSegmentQuery() to check where a segment hits a cpBB.
+* API: Added cpBodyGetVelAtWorldPoint() and cpBodyGetVelAtLocalPoint() to get point velocities on a body.
+* API: Added cpArbiterTotalKE() to calculate the energy lost due to a collision. Great for calculating damage accurately.
+* API: Added methods to get an ObjC pointer from a C chipmunk struct.
+* API: Added a CHIPMUNK_ARBITER_GET_BODIES() macro for Objective-Chipmunk.
+* API: The Objective-Chipmunk headers are now ARC compatible.
+* API: Added a [ChipmunkSpace contains:] method to check if a ChipmunkObject has been added to the space or not.
+* API: Added a cpBBNewForCircle() function.
+* API: Added a cpBBSegmentQuery() function for raycasting againsts AABBs.
+* BUG: Fixed a regression with ChipmunkSpace.bodies and ChipmunkSpace.shapes that caused crashes.
+* BUG: Fixed a rare bug with postStep() callbacks and iterators.
+* BUG: Fixed a border case in cpBBIntersectsSegment() that could cause missed segment queries.
+* MISC: Added some new assertions for error conditions that were previously uncaught.
+* MISC: Accelerated segment queries in cpBBTree by sorting the nodes.
+* MISC: Added a new "Slice" demo that lets you cut up a polygon.
+* MISC: Added NEON optimizations for Chipmunk Pro. Expect running on most ARM platforms to be 25-35% faster for contact heavy simulations.
+* MISC: All ChipmunkObject instances added to a space are now retained, even composite ones.
+
+What's new in 6.0.2:
+* API: Added cpSpaceIsLocked() to check if you are in a callback or not.
+* API: Removed the long deprecated [ChipmunkSpace addShapeAHandler:] and [ChipmunkSpace addShapeBHandler:] methods.
+* API: The ChipmunkObject protocol now can return any id<NSFastEnumeration> object instead of just an NSSet.
+* API: The largely useless [ChipmunkSpace addBaseObjects:] and [ChipmunkSpace removeBaseObjects:] methods were removed.
+* API: Added [ChipmunkSpace smartAdd:] and [ChipmunkSpace smartRemove:] methods for a consistent API to remove objects inside and out of callbacks.
+* API: Added [ChipmunkSpace addPostStepBlock:key:] to complement [ChipmunkSpace addPostStepCallback:selector:key:].
+* API: Added [ChipmunkSpace addPostStepAddition:].
+* API: Objective-Chipmunk collision handlers no longer retain their target to avoid reference cycles.
+* API: Added callbacks to joints.
+* BUG: Soft errors (only checked when debug mode is enabled) and warnings were disabled. Whoops.
+* BUG: cpShapeIsSensor() was incorrectly named in chipmunk_ffi.h.
+* BUG: It should be safe to call cpActivateBody() from an space iterator callback now.
+* MISC: Very nice bouyancy demo added based on callbacks.
+* MISC: Breakable Joints demo showing how to use the new joint callbacks.
+* MISC: Player demo updated and greatly enhanced by Chipmunk 6 features.
+* MISC: Changed adding a static body to a space from a warning to a hard error.
+* MISC: cpGroup and cpCollisionType now default to uintptr_t so you can safely use pointers instead of ints for these types.
+* MISC: Updated the MSVC10 project file.
+* MISC: Updated the FFI defs.
+
+What's new in 6.0.1:
+* BUG: Calling cpBodySetPos() on a sleeping body was delaying the Separate() handler callback if one existed.
+* BUG: Fixed a bug where Separate() handler callbacks were not occuring when removing shapes.
+* BUG: Calling cpBodyApplyForce() or cpBodyResetForces() was not activating sleeping bodies.
+* API: Added cpSpaceEachConstraint().
+* API: Added a "CurrentTimeStep" property to cpSpace to retrieve the current (or most recent) timestep.
+* MISC: Got rid of anonymous unions so that it is C99 clean again.
+
+What's new in 6.0.0:
+Chipmunk 6.x's API is not quite 100% compatible with 5.x. Make sure you read the list of changes carefully.
+Keep in mind that this is a x.0.0 release and that it's likely there are still some bugs I don't know about yet. I've spent a lot of effort rewritting the collision detection, sleeping, and contact graph algorithms that have required large changes and cleanup to the 5.x codebase. I've ironed out all the bugs that I know of, and the beta test went well. So it's finally time for 6!
+
+* API: Chipmunk now has hard runtime assertions that aren't disabled in release mode for many error conditions. Most people have been using release builds of Chipmunk during development and were missing out on very important error checking.
+* API: Access to the private API has been disabled by default now and much of the private API has changed. I've added official APIs for all the uses of the private API I knew of.
+* API: Added accessor functions for every property on every type. As Chipmunk's complexity has grown, it's become more difficult to ignore accessors. You are encouraged to use them, but are not required to.
+* API: Added cpSpaceEachBody() and cpSpaceEachShape() to iterate bodies/shapes in a space.
+* API: Added cpSpaceReindexShapesForBody() to reindex all the shapes attached to a particular body.
+* API: Added a 'data' pointer to spaces now too.
+* API: cpSpace.staticBody is a pointer to the static body instead of a static reference.
+* API: The globals cp_bias_coef, cp_collision_slop, cp_contact_persistence have been moved to properties of a space. (collisionBias, collisionSlop, collisionPersistence respectively)
+* API: Added cpBodyActivateStatic() to wake up bodies touching a static body with an optional shape filter parameter.
+* API: Added cpBodyEachShape() and cpBodyEachConstraint() iterators to iterate the active shapes/constraints attached to a body.
+* API: Added cpBodyEeachArbiter() to iterate the collision pairs a body is involved in. This makes it easy to perform grounding checks or find how much collision force is being applied to an object.
+* API: The error correction applied by the collision bias and joint bias is now timestep independent and the units have completely changed.
+* FIX: Units of damping for springs are correct regardless of the number of iterations. Previously they were only correct if you had 1 or 2 iterations.
+* MISC: Numerous changes to help make Chipmunk work better with variable timesteps. Use of constant timesteps is still highly recommended, but it is now easier to change the time scale without introducing artifacts.
+* MISC: Performance! Chipmunk 6 should be way faster than Chipmunk 5 for almost any game.
+* MISC: Chipmunk supports multiple spatial indexes and uses a bounding box tree similar to the one found in the Bullet physics library by default. This should provide much better performance for scenes with objects of differening size and works without any tuning for any scale.
+
+
+What's new in 5.3.5
+* FIX: Fixed spelling of cpArbiterGetDepth(). Was cpArbiteGetDepth() before. Apparently nobody ever used this function.
+* FIX: Added defines for M_PI and M_E. Apparently these values were never part of the C standard math library. Who knew!?
+* FIX: Added a guard to cpBodyActivate() so that it's a noop for rouge bodies.
+* FIX: Shape queries now work with (and against) sensor shapes.
+* FIX: Fixed an issue where removing a collision handler while a separate() callback was waiting to fire the next step would cause crashes.
+* FIX: Fixed an issue where the default callback would not be called for sensor shapes.
+* FIX: Resetting or applying forces or impulses on a body causes it to wake up now.
+* MISC: Added a check that a space was not locked when adding or removing a callback.
+* MISC: Removed cpmalloc from the API and replaced all occurences with cpcalloc
+* MISC: Added a benchmarking mode to the demo app. -trial runs it in time trial mode and -bench makes it run some benchmarking demos.
+
+What's new in 5.3.4:
+* FIX: cpBodyActivate() can now be called from collision and query callbacks. This way you can use the setter functions to change properties without indirectly calling cpBodyActivate() and causing an assertion.
+* FIX: cpArbiterGetContactPointSet() was returning the collision points for the normals.
+* FIX: cpSpaceEachBody() now includes sleeping bodies.
+* FIX: Shapes attached to static rogue bodies created with cpBodyNewStatic() are added as static shapes.
+* MISC: Applied a user patch to update the MSVC project and add a .def file.
+
+What's new in 5.3.3:
+* API: Added cpArbiteGetCount() to return the number of contact points.
+* API: Added helper functions for calculating areas of Chipmunk shapes as well as calculating polygon centroids and centering polygons on their centroid.
+* API: Shape queries. Query a shape to test for collisions if it were to be inserted into a space.
+* API: cpBodyInitStatic() and cpBodyNewStatic() for creating additional static (rogue) bodies.
+* API: cpBodySleepWithGroup() to allow you to create groups of sleeping objects that are woken up together.
+* API: Added overloaded *, +, - and == operators for C++ users.
+* API: Added cpSpaceActivateShapesTouchingShape() to query for and activate any shapes touching a given shape. Useful if you ever need to move a static body.
+* FIX: Fixed an extremely rare memory bug in the collision cache.
+* FIX: Fixed a memory leak in Objective-Chipmunk that could cause ChipmunkSpace objects to be leaked.
+* MISC: C struct fields and function that are considered private have been explicitly marked as such. Defining CP_ALLOW_PRIVATE_ACCESS to 0 in Chipmunk.h will let you test which parts of the private API that you are using and give me feedback about how to build proper APIs in Chipmunk 6 for what you are trying to do.
+* MISC: Allow CGPoints to be used as cpVect on Mac OS X as well as iOS.
+
+
+What's new in 5.3.2:
+* FIX: Collision begin callbacks were being called continuously for sensors or collisions rejected from the pre-solve callback.
+* FIX: Plugged a nasty memory leak when adding post-step callbacks.
+* FIX: Shapes were being added to the spatial hash using an uninitialized bounding box in some cases.
+* FIX: Perfectly aligned circle shapes now push each other apart.
+* FIX: cpBody setter functions now call cpBodyActivate().
+* FIX: Collision handler targets are released in Objective-Chipmunk when they are no longer needed instead of waiting for the space to be deallocated.
+* API: cpSpaceSegmentQuery() no longer returns a boolean. Use cpSpaceSegmentQueryFirst() instead as it's more efficient.
+* NEW: cpSpaceRehashShape() Rehash an individual shape, active or static.
+* NEW: cpBodySleep() Force a body to fall asleep immediately.
+* NEW: cpConstraintGetImpulse() Return the most recent impulse applied by a constraint.
+* NEW: Added setter functions for the groove joint endpoints.
+* MISC: A number of other minor optimizations and fixes.
+
+What's new in 5.3.1:
+ * NEW: Added a brand new tutorial for Objective-Chipmunk: SimpleObjectiveChipmunk that can be found in the Objective-Chipmunk folder.
+ * NEW: Proper API docs for Objective-Chipmunk.
+ * NEW: Updated the included Objective-Chipmunk library.
+ * FIX: Fixed a rare memory crash in the sensor demo.
+ * FIX: Fixed some warnings that users submitted.
+
+What's new in 5.3.0:
+ * FIX: Fixed the source so it can compile as C, C++, Objective-C, and Objective-C++.
+ * FIX: Fixed cp_contact_persistence. It was broken so that it would forget collision solutions after 1 frame instead of respecting the value set.
+ * OPTIMIZATION: Several minor optimizations have been added. Though performance should only differ by a few percent.
+ * OPTIMIZATION: Chipmunk now supports putting bodies to sleep when they become inactive.
+ * API: Elastic iterations are now deprecated as they should no longer be necessary.
+ * API: Added API elements to support body sleeping.
+ * API: Added a statically allocated static body to each space for attaching static shapes to.
+ * API: Static shapes attached to the space's static body can simply be added to the space using cpSpaceAddShape().
+ * NEW: New MSVC projects.
+ * NEW: Added boolean and time stamp types for clarity.
+
+What's new in 5.2.0:
+ * OPTIMIZATION: Chipmunk structs used within the solver are now allocated linearly in large blocks. This is much more CPU cache friendly. Programs have seen up to 50% performance improvements though 15-20% should be expected.
+ * API: Shape references in cpArbiter structs changed to private_a and private_b to discourage accessing the fields directly and getting them out of order. You should be using cpArbiterGetShapes() or CP_ARBITER_GET_SHAPES() to access the shapes in the correct order.
+ * API: Added assertion error messages as well as warnings and covered many new assertion cases.
+ * FIX: separate() callbacks are called before shapes are removed from the space to prevent dangling pointers.
+ * NEW: Added convenience functions for creating box shapes and calculating moments.
+
+What's new in 5.1.0:
+ * FIX: fixed a NaN issue that was causing raycasts for horizontal or vertical lines to end up in an infinite loop
+ * FIX: fixed a number of memory leaks
+ * FIX: fixed warnings for various compiler/OS combinations
+ * API: Rejecting a collision from a begin() callback permanently rejects the collision until separation
+ * API: Erroneous collision type parameterns removed from cpSpaceDefaulteCollisionHandler()
+ * MOVE: FFI declarations of inlined functions into their own header
+ * MOVE: Rearranged the project structure to separate out the header files into a separate include/ directory.
+ * NEW: Added a static library target for the iPhone.
+ * NEW: Type changes when building on the iPhone to make it friendlier to other iPhone APIs
+ * NEW: Added an AABB query to complement point and segment queries
+ * NEW: CP_NO_GROUP and CP_ALL_LAYERS constants
+
+What's new in 5.0.0:
+ * Brand new Joint/Constraint API: New constraints can be added easily and are much more flexible than the old joint system
+ * Efficient Segment Queries - Like raycasting, but with line segments.
+ * Brand new collision callback API: Collision begin/separate events, API for removal of objects within callbacks, more programable control over collision handling.
\ No newline at end of file
diff --git a/dali-physics/third-party/chipmunk2d/android/Android.mk b/dali-physics/third-party/chipmunk2d/android/Android.mk
new file mode 100644 (file)
index 0000000..defb992
--- /dev/null
@@ -0,0 +1,86 @@
+# Copyright (C) PlayControl Software, LLC. 
+# Eric Wing <ewing . public @ playcontrol.net>
+#
+# This is a "Prebuilt" Android Makefile provided as an example/template (or direct use if no tweaking is required).
+# The idea is that you have already built the chipmunk .so and .a libraries using CMake.
+# Now you want to use those prebuilt libraries in your own project.
+# Android support prebuilt exteneral modules through its ndk-build system, but you need to have all the pieces setup and in the right place. This is one of those pieces.
+# 
+# This file assumes you built all your chipmunk libs and put things into a directory structure like so:
+# 
+# Android.mk (this file)
+#      libs/armeabi/libchipmunk.a
+#      libs/armeabi/libchipmunk.a
+#      libs/armeabi-v7a/libchipmunk.a
+#      libs/armeabi-v7a/libchipmunk.a
+#      libs/x86/libchipmunk.a
+#      libs/x86/libchipmunk.a
+# 
+#      include/chipmunk/chipmunk.h
+#      ... (the other header files here)
+#
+# Note that this file is copied into the directory above libs and include.
+# Below is the code you need to make this Makefile export the correct headers, libraries, and flags for both dynamic and static versions.
+
+# LOCAL_PATH needs to be before include
+LOCAL_PATH := $(call my-dir)
+
+# For the dynamic library
+include $(CLEAR_VARS)
+# This is the name of module the caller will use in LOCAL_SHARED_LIBRARIES
+LOCAL_MODULE := chipmunk_shared
+LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libchipmunk.so
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include/chipmunk
+# Use LOCAL_EXPORT_CFLAGS to automatically export the correct flags (as necessary) to the calling module so the caller doesn't need to know the details.
+#LOCAL_EXPORT_CFLAGS := -DFOO=1 -DCP_USE_DOUBLES=1 -DCP_USE_CGPOINTS=0
+# The .so is already linked so we don't really need to export this.
+#LOCAL_EXPORT_LDLIBS := -lm
+include $(PREBUILT_SHARED_LIBRARY)
+
+# For the static library
+include $(CLEAR_VARS)
+# This is the name of module the caller will use in LOCAL_STATIC_LIBRARIES
+LOCAL_MODULE := chipmunk_static
+LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libchipmunk.a
+# Use LOCAL_EXPORT_CFLAGS to automatically export the correct flags (as necessary) to the calling module so the caller doesn't need to know the details.
+#LOCAL_EXPORT_CFLAGS := -DFOO=1 -DCP_USE_DOUBLES=1 -DCP_USE_CGPOINTS=0
+# Since the .a isn't linked, it's link dependencies must be passed on to the calling project.
+LOCAL_EXPORT_LDLIBS := -lm
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include/chipmunk
+include $(PREBUILT_STATIC_LIBRARY)
+
+
+
+# Two other pieces are needed to make this work which fall outside the scope of this file.
+# First, you must have a directory convention for the calling makefile.
+# So let's say we put all the above in a directory called Chipmunk2D. The layout looks like this:
+# Chipmunk2D/
+#      Android.mk (this file)
+#              libs/armeabi/libchipmunk.a
+#              libs/armeabi/libchipmunk.a
+#              libs/armeabi-v7a/libchipmunk.a
+#              libs/armeabi-v7a/libchipmunk.a
+#              libs/x86/libchipmunk.a
+#              libs/x86/libchipmunk.a
+# 
+#              include/chipmunk/chipmunk.h
+#              ... (the other header files here)
+
+# So the calling makefile looks something like:
+# LOCAL_PATH := $(call my-dir)
+# include $(CLEAR_VARS)
+# LOCAL_MODULE    := hello-jni
+# LOCAL_SRC_FILES := hello-jni.c
+# These are the LOCAL_MODULE names as defined in the prebuilt module's Android.mk. Define either shared or static, but not both. If you use dynamic, don't forget you need to do a System.loadLibrary("chipmunk") in your Java code.
+# #LOCAL_SHARED_LIBRARIES := chipmunk_shared
+# LOCAL_STATIC_LIBRARIES := chipmunk_static
+# include $(BUILD_SHARED_LIBRARY)
+# Android build system will look for folder `Chipmunk2D` in all import paths:
+# $(call import-module,Chipmunk2D) 
+# ------     end      -----
+
+# Second, you need to set the environmental variable NDK_MODULE_PATH to list the directory containing Chipmunk2D.
+# So if Chipmunk2D is in /Library/Frameworks/Android/PrebuiltModules
+# export NDK_MODULE_PATH=/Library/Frameworks/Android/PrebuiltModules
+# Note that NDK_MODULE_PATH may contain multiple directories like the PATH environmental variable.
+
diff --git a/dali-physics/third-party/chipmunk2d/codeblocks/Chipmunk.cbp b/dali-physics/third-party/chipmunk2d/codeblocks/Chipmunk.cbp
new file mode 100644 (file)
index 0000000..a6cc9ea
--- /dev/null
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+       <FileVersion major="1" minor="6" />
+       <Project>
+               <Option title="Chipmunk" />
+               <Option pch_mode="2" />
+               <Option compiler="gcc" />
+               <Build>
+                       <Target title="Debug">
+                               <Option output="bin/Debug/libChipmunk" prefix_auto="1" extension_auto="1" />
+                               <Option object_output="obj/Debug/" />
+                               <Option type="3" />
+                               <Option compiler="gcc" />
+                               <Option createDefFile="1" />
+                               <Option createStaticLib="1" />
+                               <Compiler>
+                                       <Add option="-g" />
+                                       <Add directory="../include" />
+                                       <Add directory="../include/chipmunk" />
+                               </Compiler>
+                       </Target>
+                       <Target title="Release">
+                               <Option output="bin/Release/libChipmunk" prefix_auto="1" extension_auto="1" />
+                               <Option object_output="obj/Release/" />
+                               <Option type="3" />
+                               <Option compiler="gcc" />
+                               <Option createDefFile="1" />
+                               <Option createStaticLib="1" />
+                               <Compiler>
+                                       <Add option="-O2" />
+                               </Compiler>
+                               <Linker>
+                                       <Add option="-s" />
+                               </Linker>
+                       </Target>
+               </Build>
+               <Compiler>
+                       <Add option="-Wall" />
+                       <Add option="-std=c99" />
+               </Compiler>
+               <Unit filename="../include/chipmunk/chipmunk.h" />
+               <Unit filename="../include/chipmunk/chipmunk_ffi.h" />
+               <Unit filename="../include/chipmunk/chipmunk_private.h" />
+               <Unit filename="../include/chipmunk/chipmunk_types.h" />
+               <Unit filename="../include/chipmunk/chipmunk_unsafe.h" />
+               <Unit filename="../include/chipmunk/cpArbiter.h" />
+               <Unit filename="../include/chipmunk/cpBB.h" />
+               <Unit filename="../include/chipmunk/cpBody.h" />
+               <Unit filename="../include/chipmunk/cpConstraint.h" />
+               <Unit filename="../include/chipmunk/cpDampedRotarySpring.h" />
+               <Unit filename="../include/chipmunk/cpDampedSpring.h" />
+               <Unit filename="../include/chipmunk/cpGearJoint.h" />
+               <Unit filename="../include/chipmunk/cpGrooveJoint.h" />
+               <Unit filename="../include/chipmunk/cpPinJoint.h" />
+               <Unit filename="../include/chipmunk/cpPivotJoint.h" />
+               <Unit filename="../include/chipmunk/cpPolyShape.h" />
+               <Unit filename="../include/chipmunk/cpRatchetJoint.h" />
+               <Unit filename="../include/chipmunk/cpRotaryLimitJoint.h" />
+               <Unit filename="../include/chipmunk/cpShape.h" />
+               <Unit filename="../include/chipmunk/cpSimpleMotor.h" />
+               <Unit filename="../include/chipmunk/cpSlideJoint.h" />
+               <Unit filename="../include/chipmunk/cpSpace.h" />
+               <Unit filename="../include/chipmunk/cpSpatialIndex.h" />
+               <Unit filename="../include/chipmunk/cpTransform.h" />
+               <Unit filename="../include/chipmunk/cpVect.h" />
+               <Unit filename="../src/chipmunk.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpArbiter.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpArray.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpBBTree.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpBody.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpCollision.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpConstraint.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpDampedRotarySpring.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpDampedSpring.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpGearJoint.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpGrooveJoint.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpHashSet.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpPinJoint.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpPivotJoint.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpPolyShape.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpRatchetJoint.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpRotaryLimitJoint.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpShape.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpSimpleMotor.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpSlideJoint.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpSpace.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpSpaceComponent.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpSpaceDebug.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpSpaceHash.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpSpaceQuery.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpSpaceStep.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpSpatialIndex.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/cpSweep1D.c">
+                       <Option compilerVar="CC" />
+               </Unit>
+               <Unit filename="../src/prime.h" />
+               <Extensions>
+                       <code_completion />
+                       <envvars />
+                       <debugger />
+               </Extensions>
+       </Project>
+</CodeBlocks_project_file>
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk.h
new file mode 100644 (file)
index 0000000..d98ba7e
--- /dev/null
@@ -0,0 +1,232 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_H
+#define CHIPMUNK_H
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifndef alloca
+       #ifdef _WIN32
+               #include <malloc.h>
+       #elif defined(__FreeBSD__)
+               /* already included in <stdlib.h> */
+       #else
+               #include <alloca.h>
+       #endif
+#endif
+
+#ifdef _WIN32
+       #define CP_EXPORT __declspec(dllexport)
+#else
+       #define CP_EXPORT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CP_EXPORT void cpMessage(const char *condition, const char *file, int line, int isError, int isHardError, const char *message, ...);
+#ifdef NDEBUG
+       #define cpAssertWarn(__condition__, ...)
+       #define cpAssertSoft(__condition__, ...)
+#else
+       #define cpAssertSoft(__condition__, ...) if(!(__condition__)){cpMessage(#__condition__, __FILE__, __LINE__, 1, 0, __VA_ARGS__); abort();}
+       #define cpAssertWarn(__condition__, ...) if(!(__condition__)) cpMessage(#__condition__, __FILE__, __LINE__, 0, 0, __VA_ARGS__)
+#endif
+
+// Hard assertions are used in situations where the program definitely will crash anyway, and the reason is inexpensive to detect.
+#define cpAssertHard(__condition__, ...) if(!(__condition__)){cpMessage(#__condition__, __FILE__, __LINE__, 1, 1, __VA_ARGS__); abort();}
+
+#include "chipmunk_types.h"
+       
+/// @defgroup misc Misc
+/// @{
+
+/// Allocated size for various Chipmunk buffers
+#ifndef CP_BUFFER_BYTES
+       #define CP_BUFFER_BYTES (32*1024)
+#endif
+
+#ifndef cpcalloc
+       /// Chipmunk calloc() alias.
+       #define cpcalloc calloc
+#endif
+
+#ifndef cprealloc
+       /// Chipmunk realloc() alias.
+       #define cprealloc realloc
+#endif
+
+#ifndef cpfree
+       /// Chipmunk free() alias.
+       #define cpfree free
+#endif
+
+typedef struct cpArray cpArray;
+typedef struct cpHashSet cpHashSet;
+
+typedef struct cpBody cpBody;
+
+typedef struct cpShape cpShape;
+typedef struct cpCircleShape cpCircleShape;
+typedef struct cpSegmentShape cpSegmentShape;
+typedef struct cpPolyShape cpPolyShape;
+
+typedef struct cpConstraint cpConstraint;
+typedef struct cpPinJoint cpPinJoint;
+typedef struct cpSlideJoint cpSlideJoint;
+typedef struct cpPivotJoint cpPivotJoint;
+typedef struct cpGrooveJoint cpGrooveJoint;
+typedef struct cpDampedSpring cpDampedSpring;
+typedef struct cpDampedRotarySpring cpDampedRotarySpring;
+typedef struct cpRotaryLimitJoint cpRotaryLimitJoint;
+typedef struct cpRatchetJoint cpRatchetJoint;
+typedef struct cpGearJoint cpGearJoint;
+typedef struct cpSimpleMotorJoint cpSimpleMotorJoint;
+
+typedef struct cpCollisionHandler cpCollisionHandler;
+typedef struct cpContactPointSet cpContactPointSet;
+typedef struct cpArbiter cpArbiter;
+
+typedef struct cpSpace cpSpace;
+
+#include "cpVect.h"
+#include "cpBB.h"
+#include "cpTransform.h"
+#include "cpSpatialIndex.h"
+
+#include "cpArbiter.h" 
+
+#include "cpBody.h"
+#include "cpShape.h"
+#include "cpPolyShape.h"
+
+#include "cpConstraint.h"
+
+#include "cpSpace.h"
+
+// Chipmunk 7.0.3
+#define CP_VERSION_MAJOR 7
+#define CP_VERSION_MINOR 0
+#define CP_VERSION_RELEASE 3
+
+/// Version string.
+CP_EXPORT extern const char *cpVersionString;
+
+/// Calculate the moment of inertia for a circle.
+/// @c r1 and @c r2 are the inner and outer diameters. A solid circle has an inner diameter of 0.
+CP_EXPORT cpFloat cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset);
+
+/// Calculate area of a hollow circle.
+/// @c r1 and @c r2 are the inner and outer diameters. A solid circle has an inner diameter of 0.
+CP_EXPORT cpFloat cpAreaForCircle(cpFloat r1, cpFloat r2);
+
+/// Calculate the moment of inertia for a line segment.
+/// Beveling radius is not supported.
+CP_EXPORT cpFloat cpMomentForSegment(cpFloat m, cpVect a, cpVect b, cpFloat radius);
+
+/// Calculate the area of a fattened (capsule shaped) line segment.
+CP_EXPORT cpFloat cpAreaForSegment(cpVect a, cpVect b, cpFloat radius);
+
+/// Calculate the moment of inertia for a solid polygon shape assuming it's center of gravity is at it's centroid. The offset is added to each vertex.
+CP_EXPORT cpFloat cpMomentForPoly(cpFloat m, int count, const cpVect *verts, cpVect offset, cpFloat radius);
+
+/// Calculate the signed area of a polygon. A Clockwise winding gives positive area.
+/// This is probably backwards from what you expect, but matches Chipmunk's the winding for poly shapes.
+CP_EXPORT cpFloat cpAreaForPoly(const int count, const cpVect *verts, cpFloat radius);
+
+/// Calculate the natural centroid of a polygon.
+CP_EXPORT cpVect cpCentroidForPoly(const int count, const cpVect *verts);
+
+/// Calculate the moment of inertia for a solid box.
+CP_EXPORT cpFloat cpMomentForBox(cpFloat m, cpFloat width, cpFloat height);
+
+/// Calculate the moment of inertia for a solid box.
+CP_EXPORT cpFloat cpMomentForBox2(cpFloat m, cpBB box);
+
+/// Calculate the convex hull of a given set of points. Returns the count of points in the hull.
+/// @c result must be a pointer to a @c cpVect array with at least @c count elements. If @c verts == @c result, then @c verts will be reduced inplace.
+/// @c first is an optional pointer to an integer to store where the first vertex in the hull came from (i.e. verts[first] == result[0])
+/// @c tol is the allowed amount to shrink the hull when simplifying it. A tolerance of 0.0 creates an exact hull.
+CP_EXPORT int cpConvexHull(int count, const cpVect *verts, cpVect *result, int *first, cpFloat tol);
+
+/// Convenience macro to work with cpConvexHull.
+/// @c count and @c verts is the input array passed to cpConvexHull().
+/// @c count_var and @c verts_var are the names of the variables the macro creates to store the result.
+/// The output vertex array is allocated on the stack using alloca() so it will be freed automatically, but cannot be returned from the current scope.
+#define CP_CONVEX_HULL(__count__, __verts__, __count_var__, __verts_var__) \
+cpVect *__verts_var__ = (cpVect *)alloca(__count__*sizeof(cpVect)); \
+int __count_var__ = cpConvexHull(__count__, __verts__, __verts_var__, NULL, 0.0); \
+
+/// Returns the closest point on the line segment ab, to the point p.
+static inline cpVect
+cpClosetPointOnSegment(const cpVect p, const cpVect a, const cpVect b)
+{
+       cpVect delta = cpvsub(a, b);
+       cpFloat t = cpfclamp01(cpvdot(delta, cpvsub(p, b))/cpvlengthsq(delta));
+       return cpvadd(b, cpvmult(delta, t));
+}
+
+#if defined(__has_extension)
+#if __has_extension(blocks)
+// Define alternate block based alternatives for a few of the callback heavy functions.
+// Collision handlers are post-step callbacks are not included to avoid memory management issues.
+// If you want to use blocks for those and are aware of how to correctly manage the memory, the implementation is trivial. 
+
+void cpSpaceEachBody_b(cpSpace *space, void (^block)(cpBody *body));
+void cpSpaceEachShape_b(cpSpace *space, void (^block)(cpShape *shape));
+void cpSpaceEachConstraint_b(cpSpace *space, void (^block)(cpConstraint *constraint));
+
+void cpBodyEachShape_b(cpBody *body, void (^block)(cpShape *shape));
+void cpBodyEachConstraint_b(cpBody *body, void (^block)(cpConstraint *constraint));
+void cpBodyEachArbiter_b(cpBody *body, void (^block)(cpArbiter *arbiter));
+
+typedef void (^cpSpacePointQueryBlock)(cpShape *shape, cpVect point, cpFloat distance, cpVect gradient);
+void cpSpacePointQuery_b(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryBlock block);
+
+typedef void (^cpSpaceSegmentQueryBlock)(cpShape *shape, cpVect point, cpVect normal, cpFloat alpha);
+void cpSpaceSegmentQuery_b(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryBlock block);
+
+typedef void (^cpSpaceBBQueryBlock)(cpShape *shape);
+void cpSpaceBBQuery_b(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryBlock block);
+
+typedef void (^cpSpaceShapeQueryBlock)(cpShape *shape, cpContactPointSet *points);
+cpBool cpSpaceShapeQuery_b(cpSpace *space, cpShape *shape, cpSpaceShapeQueryBlock block);
+
+#endif
+#endif
+
+
+//@}
+
+#ifdef __cplusplus
+}
+
+static inline cpVect operator *(const cpVect v, const cpFloat s){return cpvmult(v, s);}
+static inline cpVect operator +(const cpVect v1, const cpVect v2){return cpvadd(v1, v2);}
+static inline cpVect operator -(const cpVect v1, const cpVect v2){return cpvsub(v1, v2);}
+static inline cpBool operator ==(const cpVect v1, const cpVect v2){return cpveql(v1, v2);}
+static inline cpVect operator -(const cpVect v){return cpvneg(v);}
+
+#endif
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_ffi.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_ffi.h
new file mode 100644 (file)
index 0000000..86e3d9f
--- /dev/null
@@ -0,0 +1,105 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef CHIPMUNK_FFI
+
+// Create non static inlined copies of Chipmunk functions, useful for working with dynamic FFIs
+// For many languages, it may be faster to reimplement these functions natively instead.
+// Note: This file should only be included by chipmunk.c.
+
+#ifdef _MSC_VER
+ #if _MSC_VER >= 1600
+  #define MAKE_REF(name) CP_EXPORT decltype(name) *_##name = name
+ #else
+  #define MAKE_REF(name)
+ #endif
+#else
+ #define MAKE_REF(name) __typeof__(name) *_##name = name
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+MAKE_REF(cpv); // makes a variable named _cpv that contains the function pointer for cpv()
+MAKE_REF(cpveql);
+MAKE_REF(cpvadd);
+MAKE_REF(cpvneg);
+MAKE_REF(cpvsub);
+MAKE_REF(cpvmult);
+MAKE_REF(cpvdot);
+MAKE_REF(cpvcross);
+MAKE_REF(cpvperp);
+MAKE_REF(cpvrperp);
+MAKE_REF(cpvproject);
+MAKE_REF(cpvforangle);
+MAKE_REF(cpvtoangle);
+MAKE_REF(cpvrotate);
+MAKE_REF(cpvunrotate);
+MAKE_REF(cpvlengthsq);
+MAKE_REF(cpvlength);
+MAKE_REF(cpvlerp);
+MAKE_REF(cpvnormalize);
+MAKE_REF(cpvclamp);
+MAKE_REF(cpvlerpconst);
+MAKE_REF(cpvdist);
+MAKE_REF(cpvdistsq);
+MAKE_REF(cpvnear);
+
+MAKE_REF(cpfmax);
+MAKE_REF(cpfmin);
+MAKE_REF(cpfabs);
+MAKE_REF(cpfclamp);
+MAKE_REF(cpflerp);
+MAKE_REF(cpflerpconst);
+
+MAKE_REF(cpBBNew);
+MAKE_REF(cpBBNewForExtents);
+MAKE_REF(cpBBNewForCircle);
+MAKE_REF(cpBBIntersects);
+MAKE_REF(cpBBContainsBB);
+MAKE_REF(cpBBContainsVect);
+MAKE_REF(cpBBMerge);
+MAKE_REF(cpBBExpand);
+MAKE_REF(cpBBCenter);
+MAKE_REF(cpBBArea);
+MAKE_REF(cpBBMergedArea);
+MAKE_REF(cpBBSegmentQuery);
+MAKE_REF(cpBBIntersectsSegment);
+MAKE_REF(cpBBClampVect);
+
+MAKE_REF(cpSpatialIndexDestroy);
+MAKE_REF(cpSpatialIndexCount);
+MAKE_REF(cpSpatialIndexEach);
+MAKE_REF(cpSpatialIndexContains);
+MAKE_REF(cpSpatialIndexInsert);
+MAKE_REF(cpSpatialIndexRemove);
+MAKE_REF(cpSpatialIndexReindex);
+MAKE_REF(cpSpatialIndexReindexObject);
+MAKE_REF(cpSpatialIndexSegmentQuery);
+MAKE_REF(cpSpatialIndexQuery);
+MAKE_REF(cpSpatialIndexReindexQuery);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_private.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_private.h
new file mode 100644 (file)
index 0000000..e606ba1
--- /dev/null
@@ -0,0 +1,344 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_PRIVATE_H
+#define CHIPMUNK_PRIVATE_H
+
+#include "chipmunk/chipmunk.h"
+#include "chipmunk/chipmunk_structs.h"
+
+#define CP_HASH_COEF (3344921057ul)
+#define CP_HASH_PAIR(A, B) ((cpHashValue)(A)*CP_HASH_COEF ^ (cpHashValue)(B)*CP_HASH_COEF)
+
+// TODO: Eww. Magic numbers.
+#define MAGIC_EPSILON 1e-5
+
+
+//MARK: cpArray
+
+cpArray *cpArrayNew(int size);
+
+void cpArrayFree(cpArray *arr);
+
+void cpArrayPush(cpArray *arr, void *object);
+void *cpArrayPop(cpArray *arr);
+void cpArrayDeleteObj(cpArray *arr, void *obj);
+cpBool cpArrayContains(cpArray *arr, void *ptr);
+
+void cpArrayFreeEach(cpArray *arr, void (freeFunc)(void*));
+
+
+//MARK: cpHashSet
+
+typedef cpBool (*cpHashSetEqlFunc)(const void *ptr, const void *elt);
+typedef void *(*cpHashSetTransFunc)(const void *ptr, void *data);
+
+cpHashSet *cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc);
+void cpHashSetSetDefaultValue(cpHashSet *set, void *default_value);
+
+void cpHashSetFree(cpHashSet *set);
+
+int cpHashSetCount(cpHashSet *set);
+const void *cpHashSetInsert(cpHashSet *set, cpHashValue hash, const void *ptr, cpHashSetTransFunc trans, void *data);
+const void *cpHashSetRemove(cpHashSet *set, cpHashValue hash, const void *ptr);
+const void *cpHashSetFind(cpHashSet *set, cpHashValue hash, const void *ptr);
+
+typedef void (*cpHashSetIteratorFunc)(void *elt, void *data);
+void cpHashSetEach(cpHashSet *set, cpHashSetIteratorFunc func, void *data);
+
+typedef cpBool (*cpHashSetFilterFunc)(void *elt, void *data);
+void cpHashSetFilter(cpHashSet *set, cpHashSetFilterFunc func, void *data);
+
+
+//MARK: Bodies
+
+void cpBodyAddShape(cpBody *body, cpShape *shape);
+void cpBodyRemoveShape(cpBody *body, cpShape *shape);
+
+//void cpBodyAccumulateMassForShape(cpBody *body, cpShape *shape);
+void cpBodyAccumulateMassFromShapes(cpBody *body);
+
+void cpBodyRemoveConstraint(cpBody *body, cpConstraint *constraint);
+
+
+//MARK: Spatial Index Functions
+
+cpSpatialIndex *cpSpatialIndexInit(cpSpatialIndex *index, cpSpatialIndexClass *klass, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+
+
+//MARK: Arbiters
+
+cpArbiter* cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b);
+
+static inline struct cpArbiterThread *
+cpArbiterThreadForBody(cpArbiter *arb, cpBody *body)
+{
+       return (arb->body_a == body ? &arb->thread_a : &arb->thread_b);
+}
+
+void cpArbiterUnthread(cpArbiter *arb);
+
+void cpArbiterUpdate(cpArbiter *arb, struct cpCollisionInfo *info, cpSpace *space);
+void cpArbiterPreStep(cpArbiter *arb, cpFloat dt, cpFloat bias, cpFloat slop);
+void cpArbiterApplyCachedImpulse(cpArbiter *arb, cpFloat dt_coef);
+void cpArbiterApplyImpulse(cpArbiter *arb);
+
+
+//MARK: Shapes/Collisions
+
+cpShape *cpShapeInit(cpShape *shape, const cpShapeClass *klass, cpBody *body, struct cpShapeMassInfo massInfo);
+
+static inline cpBool
+cpShapeActive(cpShape *shape)
+{
+       // checks if the shape is added to a shape list.
+       // TODO could this just check the space now?
+       return (shape->prev || (shape->body && shape->body->shapeList == shape));
+}
+
+// Note: This function returns contact points with r1/r2 in absolute coordinates, not body relative.
+struct cpCollisionInfo cpCollide(const cpShape *a, const cpShape *b, cpCollisionID id, struct cpContact *contacts);
+
+static inline void
+CircleSegmentQuery(cpShape *shape, cpVect center, cpFloat r1, cpVect a, cpVect b, cpFloat r2, cpSegmentQueryInfo *info)
+{
+       cpVect da = cpvsub(a, center);
+       cpVect db = cpvsub(b, center);
+       cpFloat rsum = r1 + r2;
+       
+       cpFloat qa = cpvdot(da, da) - 2.0f*cpvdot(da, db) + cpvdot(db, db);
+       cpFloat qb = cpvdot(da, db) - cpvdot(da, da);
+       cpFloat det = qb*qb - qa*(cpvdot(da, da) - rsum*rsum);
+       
+       if(det >= 0.0f){
+               cpFloat t = (-qb - cpfsqrt(det))/(qa);
+               if(0.0f<= t && t <= 1.0f){
+                       cpVect n = cpvnormalize(cpvlerp(da, db, t));
+                       
+                       info->shape = shape;
+                       info->point = cpvsub(cpvlerp(a, b, t), cpvmult(n, r2));
+                       info->normal = n;
+                       info->alpha = t;
+               }
+       }
+}
+
+static inline cpBool
+cpShapeFilterReject(cpShapeFilter a, cpShapeFilter b)
+{
+       // Reject the collision if:
+       return (
+               // They are in the same non-zero group.
+               (a.group != 0 && a.group == b.group) ||
+               // One of the category/mask combinations fails.
+               (a.categories & b.mask) == 0 ||
+               (b.categories & a.mask) == 0
+       );
+}
+
+void cpLoopIndexes(const cpVect *verts, int count, int *start, int *end);
+
+
+//MARK: Constraints
+// TODO naming conventions here
+
+void cpConstraintInit(cpConstraint *constraint, const struct cpConstraintClass *klass, cpBody *a, cpBody *b);
+
+static inline void
+cpConstraintActivateBodies(cpConstraint *constraint)
+{
+       cpBody *a = constraint->a; cpBodyActivate(a);
+       cpBody *b = constraint->b; cpBodyActivate(b);
+}
+
+static inline cpVect
+relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){
+       cpVect v1_sum = cpvadd(a->v, cpvmult(cpvperp(r1), a->w));
+       cpVect v2_sum = cpvadd(b->v, cpvmult(cpvperp(r2), b->w));
+       
+       return cpvsub(v2_sum, v1_sum);
+}
+
+static inline cpFloat
+normal_relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n){
+       return cpvdot(relative_velocity(a, b, r1, r2), n);
+}
+
+static inline void
+apply_impulse(cpBody *body, cpVect j, cpVect r){
+       body->v = cpvadd(body->v, cpvmult(j, body->m_inv));
+       body->w += body->i_inv*cpvcross(r, j);
+}
+
+static inline void
+apply_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)
+{
+       apply_impulse(a, cpvneg(j), r1);
+       apply_impulse(b, j, r2);
+}
+
+static inline void
+apply_bias_impulse(cpBody *body, cpVect j, cpVect r)
+{
+       body->v_bias = cpvadd(body->v_bias, cpvmult(j, body->m_inv));
+       body->w_bias += body->i_inv*cpvcross(r, j);
+}
+
+static inline void
+apply_bias_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j)
+{
+       apply_bias_impulse(a, cpvneg(j), r1);
+       apply_bias_impulse(b, j, r2);
+}
+
+static inline cpFloat
+k_scalar_body(cpBody *body, cpVect r, cpVect n)
+{
+       cpFloat rcn = cpvcross(r, n);
+       return body->m_inv + body->i_inv*rcn*rcn;
+}
+
+static inline cpFloat
+k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n)
+{
+       cpFloat value = k_scalar_body(a, r1, n) + k_scalar_body(b, r2, n);
+       cpAssertSoft(value != 0.0, "Unsolvable collision or constraint.");
+       
+       return value;
+}
+
+static inline cpMat2x2
+k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2)
+{
+       cpFloat m_sum = a->m_inv + b->m_inv;
+       
+       // start with Identity*m_sum
+       cpFloat k11 = m_sum, k12 = 0.0f;
+       cpFloat k21 = 0.0f,  k22 = m_sum;
+       
+       // add the influence from r1
+       cpFloat a_i_inv = a->i_inv;
+       cpFloat r1xsq =  r1.x * r1.x * a_i_inv;
+       cpFloat r1ysq =  r1.y * r1.y * a_i_inv;
+       cpFloat r1nxy = -r1.x * r1.y * a_i_inv;
+       k11 += r1ysq; k12 += r1nxy;
+       k21 += r1nxy; k22 += r1xsq;
+       
+       // add the influnce from r2
+       cpFloat b_i_inv = b->i_inv;
+       cpFloat r2xsq =  r2.x * r2.x * b_i_inv;
+       cpFloat r2ysq =  r2.y * r2.y * b_i_inv;
+       cpFloat r2nxy = -r2.x * r2.y * b_i_inv;
+       k11 += r2ysq; k12 += r2nxy;
+       k21 += r2nxy; k22 += r2xsq;
+       
+       // invert
+       cpFloat det = k11*k22 - k12*k21;
+       cpAssertSoft(det != 0.0, "Unsolvable constraint.");
+       
+       cpFloat det_inv = 1.0f/det;
+       return cpMat2x2New(
+                k22*det_inv, -k12*det_inv,
+               -k21*det_inv,  k11*det_inv
+       );
+}
+
+static inline cpFloat
+bias_coef(cpFloat errorBias, cpFloat dt)
+{
+       return 1.0f - cpfpow(errorBias, dt);
+}
+
+
+//MARK: Spaces
+
+#define cpAssertSpaceUnlocked(space) \
+       cpAssertHard(!space->locked, \
+               "This operation cannot be done safely during a call to cpSpaceStep() or during a query. " \
+               "Put these calls into a post-step callback." \
+       );
+
+void cpSpaceSetStaticBody(cpSpace *space, cpBody *body);
+
+extern cpCollisionHandler cpCollisionHandlerDoNothing;
+
+void cpSpaceProcessComponents(cpSpace *space, cpFloat dt);
+
+void cpSpacePushFreshContactBuffer(cpSpace *space);
+struct cpContact *cpContactBufferGetArray(cpSpace *space);
+void cpSpacePushContacts(cpSpace *space, int count);
+
+cpPostStepCallback *cpSpaceGetPostStepCallback(cpSpace *space, void *key);
+
+cpBool cpSpaceArbiterSetFilter(cpArbiter *arb, cpSpace *space);
+void cpSpaceFilterArbiters(cpSpace *space, cpBody *body, cpShape *filter);
+
+void cpSpaceActivateBody(cpSpace *space, cpBody *body);
+void cpSpaceLock(cpSpace *space);
+void cpSpaceUnlock(cpSpace *space, cpBool runPostStep);
+
+static inline void
+cpSpaceUncacheArbiter(cpSpace *space, cpArbiter *arb)
+{
+       const cpShape *a = arb->a, *b = arb->b;
+       const cpShape *shape_pair[] = {a, b};
+       cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)a, (cpHashValue)b);
+       cpHashSetRemove(space->cachedArbiters, arbHashID, shape_pair);
+       cpArrayDeleteObj(space->arbiters, arb);
+}
+
+static inline cpArray *
+cpSpaceArrayForBodyType(cpSpace *space, cpBodyType type)
+{
+       return (type == CP_BODY_TYPE_STATIC ? space->staticBodies : space->dynamicBodies);
+}
+
+void cpShapeUpdateFunc(cpShape *shape, void *unused);
+cpCollisionID cpSpaceCollideShapes(cpShape *a, cpShape *b, cpCollisionID id, cpSpace *space);
+
+
+//MARK: Foreach loops
+
+static inline cpConstraint *
+cpConstraintNext(cpConstraint *node, cpBody *body)
+{
+       return (node->a == body ? node->next_a : node->next_b);
+}
+
+#define CP_BODY_FOREACH_CONSTRAINT(bdy, var)\
+       for(cpConstraint *var = bdy->constraintList; var; var = cpConstraintNext(var, bdy))
+
+static inline cpArbiter *
+cpArbiterNext(cpArbiter *node, cpBody *body)
+{
+       return (node->body_a == body ? node->thread_a.next : node->thread_b.next);
+}
+
+#define CP_BODY_FOREACH_ARBITER(bdy, var)\
+       for(cpArbiter *var = bdy->arbiterList; var; var = cpArbiterNext(var, bdy))
+
+#define CP_BODY_FOREACH_SHAPE(body, var)\
+       for(cpShape *var = body->shapeList; var; var = var->next)
+
+#define CP_BODY_FOREACH_COMPONENT(root, var)\
+       for(cpBody *var = root; var; var = var->sleeping.next)
+
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_structs.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_structs.h
new file mode 100644 (file)
index 0000000..d8b1e6f
--- /dev/null
@@ -0,0 +1,450 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+// All of the struct definitions for Chipmunk should be considered part of the private API.
+// However, it is very valuable to know the struct sizes for preallocating memory.
+
+#ifndef CHIPMUNK_STRUCTS_H
+#define CHIPMUNK_STRUCTS_H
+
+#include "chipmunk/chipmunk.h"
+
+struct cpArray {
+       int num, max;
+       void **arr;
+};
+
+struct cpBody {
+       // Integration functions
+       cpBodyVelocityFunc velocity_func;
+       cpBodyPositionFunc position_func;
+       
+       // mass and it's inverse
+       cpFloat m;
+       cpFloat m_inv;
+       
+       // moment of inertia and it's inverse
+       cpFloat i;
+       cpFloat i_inv;
+       
+       // center of gravity
+       cpVect cog;
+       
+       // position, velocity, force
+       cpVect p;
+       cpVect v;
+       cpVect f;
+       
+       // Angle, angular velocity, torque (radians)
+       cpFloat a;
+       cpFloat w;
+       cpFloat t;
+       
+       cpTransform transform;
+       
+       cpDataPointer userData;
+       
+       // "pseudo-velocities" used for eliminating overlap.
+       // Erin Catto has some papers that talk about what these are.
+       cpVect v_bias;
+       cpFloat w_bias;
+       
+       cpSpace *space;
+       
+       cpShape *shapeList;
+       cpArbiter *arbiterList;
+       cpConstraint *constraintList;
+       
+       struct {
+               cpBody *root;
+               cpBody *next;
+               cpFloat idleTime;
+       } sleeping;
+};
+
+enum cpArbiterState {
+       // Arbiter is active and its the first collision.
+       CP_ARBITER_STATE_FIRST_COLLISION,
+       // Arbiter is active and its not the first collision.
+       CP_ARBITER_STATE_NORMAL,
+       // Collision has been explicitly ignored.
+       // Either by returning false from a begin collision handler or calling cpArbiterIgnore().
+       CP_ARBITER_STATE_IGNORE,
+       // Collison is no longer active. A space will cache an arbiter for up to cpSpace.collisionPersistence more steps.
+       CP_ARBITER_STATE_CACHED,
+       // Collison arbiter is invalid because one of the shapes was removed.
+       CP_ARBITER_STATE_INVALIDATED,
+};
+
+struct cpArbiterThread {
+       struct cpArbiter *next, *prev;
+};
+
+struct cpContact {
+       cpVect r1, r2;
+       
+       cpFloat nMass, tMass;
+       cpFloat bounce; // TODO: look for an alternate bounce solution.
+
+       cpFloat jnAcc, jtAcc, jBias;
+       cpFloat bias;
+       
+       cpHashValue hash;
+};
+
+struct cpCollisionInfo {
+       const cpShape *a, *b;
+       cpCollisionID id;
+       
+       cpVect n;
+       
+       int count;
+       // TODO Should this be a unique struct type?
+       struct cpContact *arr;
+};
+
+struct cpArbiter {
+       cpFloat e;
+       cpFloat u;
+       cpVect surface_vr;
+       
+       cpDataPointer data;
+       
+       const cpShape *a, *b;
+       cpBody *body_a, *body_b;
+       struct cpArbiterThread thread_a, thread_b;
+       
+       int count;
+       struct cpContact *contacts;
+       cpVect n;
+       
+       // Regular, wildcard A and wildcard B collision handlers.
+       cpCollisionHandler *handler, *handlerA, *handlerB;
+       cpBool swapped;
+       
+       cpTimestamp stamp;
+       enum cpArbiterState state;
+};
+
+struct cpShapeMassInfo {
+       cpFloat m;
+       cpFloat i;
+       cpVect cog;
+       cpFloat area;
+};
+
+typedef enum cpShapeType{
+       CP_CIRCLE_SHAPE,
+       CP_SEGMENT_SHAPE,
+       CP_POLY_SHAPE,
+       CP_NUM_SHAPES
+} cpShapeType;
+
+typedef cpBB (*cpShapeCacheDataImpl)(cpShape *shape, cpTransform transform);
+typedef void (*cpShapeDestroyImpl)(cpShape *shape);
+typedef void (*cpShapePointQueryImpl)(const cpShape *shape, cpVect p, cpPointQueryInfo *info);
+typedef void (*cpShapeSegmentQueryImpl)(const cpShape *shape, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info);
+
+typedef struct cpShapeClass cpShapeClass;
+
+struct cpShapeClass {
+       cpShapeType type;
+       
+       cpShapeCacheDataImpl cacheData;
+       cpShapeDestroyImpl destroy;
+       cpShapePointQueryImpl pointQuery;
+       cpShapeSegmentQueryImpl segmentQuery;
+};
+
+struct cpShape {
+       const cpShapeClass *klass;
+       
+       cpSpace *space;
+       cpBody *body;
+       struct cpShapeMassInfo massInfo;
+       cpBB bb;
+       
+       cpBool sensor;
+       
+       cpFloat e;
+       cpFloat u;
+       cpVect surfaceV;
+
+       cpDataPointer userData;
+       
+       cpCollisionType type;
+       cpShapeFilter filter;
+       
+       cpShape *next;
+       cpShape *prev;
+       
+       cpHashValue hashid;
+};
+
+struct cpCircleShape {
+       cpShape shape;
+       
+       cpVect c, tc;
+       cpFloat r;
+};
+
+struct cpSegmentShape {
+       cpShape shape;
+       
+       cpVect a, b, n;
+       cpVect ta, tb, tn;
+       cpFloat r;
+       
+       cpVect a_tangent, b_tangent;
+};
+
+struct cpSplittingPlane {
+       cpVect v0, n;
+};
+
+#define CP_POLY_SHAPE_INLINE_ALLOC 6
+
+struct cpPolyShape {
+       cpShape shape;
+       
+       cpFloat r;
+       
+       int count;
+       // The untransformed planes are appended at the end of the transformed planes.
+       struct cpSplittingPlane *planes;
+       
+       // Allocate a small number of splitting planes internally for simple poly.
+       struct cpSplittingPlane _planes[2*CP_POLY_SHAPE_INLINE_ALLOC];
+};
+
+typedef void (*cpConstraintPreStepImpl)(cpConstraint *constraint, cpFloat dt);
+typedef void (*cpConstraintApplyCachedImpulseImpl)(cpConstraint *constraint, cpFloat dt_coef);
+typedef void (*cpConstraintApplyImpulseImpl)(cpConstraint *constraint, cpFloat dt);
+typedef cpFloat (*cpConstraintGetImpulseImpl)(cpConstraint *constraint);
+
+typedef struct cpConstraintClass {
+       cpConstraintPreStepImpl preStep;
+       cpConstraintApplyCachedImpulseImpl applyCachedImpulse;
+       cpConstraintApplyImpulseImpl applyImpulse;
+       cpConstraintGetImpulseImpl getImpulse;
+} cpConstraintClass;
+
+struct cpConstraint {
+       const cpConstraintClass *klass;
+       
+       cpSpace *space;
+       
+       cpBody *a, *b;
+       cpConstraint *next_a, *next_b;
+       
+       cpFloat maxForce;
+       cpFloat errorBias;
+       cpFloat maxBias;
+       
+       cpBool collideBodies;
+       
+       cpConstraintPreSolveFunc preSolve;
+       cpConstraintPostSolveFunc postSolve;
+       
+       cpDataPointer userData;
+};
+
+struct cpPinJoint {
+       cpConstraint constraint;
+       cpVect anchorA, anchorB;
+       cpFloat dist;
+       
+       cpVect r1, r2;
+       cpVect n;
+       cpFloat nMass;
+       
+       cpFloat jnAcc;
+       cpFloat bias;
+};
+
+struct cpSlideJoint {
+       cpConstraint constraint;
+       cpVect anchorA, anchorB;
+       cpFloat min, max;
+       
+       cpVect r1, r2;
+       cpVect n;
+       cpFloat nMass;
+       
+       cpFloat jnAcc;
+       cpFloat bias;
+};
+
+struct cpPivotJoint {
+       cpConstraint constraint;
+       cpVect anchorA, anchorB;
+       
+       cpVect r1, r2;
+       cpMat2x2 k;
+       
+       cpVect jAcc;
+       cpVect bias;
+};
+
+struct cpGrooveJoint {
+       cpConstraint constraint;
+       cpVect grv_n, grv_a, grv_b;
+       cpVect  anchorB;
+       
+       cpVect grv_tn;
+       cpFloat clamp;
+       cpVect r1, r2;
+       cpMat2x2 k;
+       
+       cpVect jAcc;
+       cpVect bias;
+};
+
+struct cpDampedSpring {
+       cpConstraint constraint;
+       cpVect anchorA, anchorB;
+       cpFloat restLength;
+       cpFloat stiffness;
+       cpFloat damping;
+       cpDampedSpringForceFunc springForceFunc;
+       
+       cpFloat target_vrn;
+       cpFloat v_coef;
+       
+       cpVect r1, r2;
+       cpFloat nMass;
+       cpVect n;
+       
+       cpFloat jAcc;
+};
+
+struct cpDampedRotarySpring {
+       cpConstraint constraint;
+       cpFloat restAngle;
+       cpFloat stiffness;
+       cpFloat damping;
+       cpDampedRotarySpringTorqueFunc springTorqueFunc;
+       
+       cpFloat target_wrn;
+       cpFloat w_coef;
+       
+       cpFloat iSum;
+       cpFloat jAcc;
+};
+
+struct cpRotaryLimitJoint {
+       cpConstraint constraint;
+       cpFloat min, max;
+       
+       cpFloat iSum;
+               
+       cpFloat bias;
+       cpFloat jAcc;
+};
+
+struct cpRatchetJoint {
+       cpConstraint constraint;
+       cpFloat angle, phase, ratchet;
+       
+       cpFloat iSum;
+               
+       cpFloat bias;
+       cpFloat jAcc;
+};
+
+struct cpGearJoint {
+       cpConstraint constraint;
+       cpFloat phase, ratio;
+       cpFloat ratio_inv;
+       
+       cpFloat iSum;
+               
+       cpFloat bias;
+       cpFloat jAcc;
+};
+
+struct cpSimpleMotor {
+       cpConstraint constraint;
+       cpFloat rate;
+       
+       cpFloat iSum;
+               
+       cpFloat jAcc;
+};
+
+typedef struct cpContactBufferHeader cpContactBufferHeader;
+typedef void (*cpSpaceArbiterApplyImpulseFunc)(cpArbiter *arb);
+
+struct cpSpace {
+       int iterations;
+       
+       cpVect gravity;
+       cpFloat damping;
+       
+       cpFloat idleSpeedThreshold;
+       cpFloat sleepTimeThreshold;
+       
+       cpFloat collisionSlop;
+       cpFloat collisionBias;
+       cpTimestamp collisionPersistence;
+       
+       cpDataPointer userData;
+       
+       cpTimestamp stamp;
+       cpFloat curr_dt;
+
+       cpArray *dynamicBodies;
+       cpArray *staticBodies;
+       cpArray *rousedBodies;
+       cpArray *sleepingComponents;
+       
+       cpHashValue shapeIDCounter;
+       cpSpatialIndex *staticShapes;
+       cpSpatialIndex *dynamicShapes;
+       
+       cpArray *constraints;
+       
+       cpArray *arbiters;
+       cpContactBufferHeader *contactBuffersHead;
+       cpHashSet *cachedArbiters;
+       cpArray *pooledArbiters;
+       
+       cpArray *allocatedBuffers;
+       unsigned int locked;
+       
+       cpBool usesWildcards;
+       cpHashSet *collisionHandlers;
+       cpCollisionHandler defaultHandler;
+       
+       cpBool skipPostStep;
+       cpArray *postStepCallbacks;
+       
+       cpBody *staticBody;
+       cpBody _staticBody;
+};
+
+typedef struct cpPostStepCallback {
+       cpPostStepFunc func;
+       void *key;
+       void *data;
+} cpPostStepCallback;
+
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_types.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_types.h
new file mode 100644 (file)
index 0000000..adc5c7e
--- /dev/null
@@ -0,0 +1,270 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_TYPES_H
+#define CHIPMUNK_TYPES_H
+
+#include <stdint.h>
+#include <float.h>
+#include <math.h>
+
+#ifdef __APPLE__
+   #include "TargetConditionals.h"
+#endif
+
+// Use CGTypes by default on iOS and Mac.
+// Also enables usage of doubles on 64 bit.
+// Performance is usually very comparable when the CPU cache is well utilised.
+#if (TARGET_OS_IPHONE || TARGET_OS_MAC) && (!defined CP_USE_CGTYPES)
+       #define CP_USE_CGTYPES 1
+#endif
+
+#if CP_USE_CGTYPES
+       #if TARGET_OS_IPHONE
+               #include <CoreGraphics/CGGeometry.h>
+               #include <CoreGraphics/CGAffineTransform.h>
+       #elif TARGET_OS_MAC
+               #include <ApplicationServices/ApplicationServices.h>
+       #endif
+       
+       #if defined(__LP64__) && __LP64__
+               #define CP_USE_DOUBLES 1
+       #else
+               #define CP_USE_DOUBLES 0
+       #endif
+#endif
+
+#ifndef CP_USE_DOUBLES
+  #if !__arm__
+         // Use doubles by default for higher precision (but not for 32 bit ARM).
+         #define CP_USE_DOUBLES 1
+  #endif
+#endif
+
+/// @defgroup basicTypes Basic Types
+/// Most of these types can be configured at compile time.
+/// @{
+
+#if CP_USE_DOUBLES
+/// Chipmunk's floating point type.
+/// Can be reconfigured at compile time.
+       typedef double cpFloat;
+       #define cpfsqrt sqrt
+       #define cpfsin sin
+       #define cpfcos cos
+       #define cpfacos acos
+       #define cpfatan2 atan2
+       #define cpfmod fmod
+       #define cpfexp exp
+       #define cpfpow pow
+       #define cpffloor floor
+       #define cpfceil ceil
+       #define CPFLOAT_MIN DBL_MIN
+#else
+       typedef float cpFloat;
+       #define cpfsqrt sqrtf
+       #define cpfsin sinf
+       #define cpfcos cosf
+       #define cpfacos acosf
+       #define cpfatan2 atan2f
+       #define cpfmod fmodf
+       #define cpfexp expf
+       #define cpfpow powf
+       #define cpffloor floorf
+       #define cpfceil ceilf
+       #define CPFLOAT_MIN FLT_MIN
+#endif
+
+#ifndef INFINITY
+       #ifdef _MSC_VER
+               union MSVC_EVIL_FLOAT_HACK
+               {
+                       unsigned __int8 Bytes[4];
+                       float Value;
+               };
+               static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}};
+               #define INFINITY (INFINITY_HACK.Value)
+       #endif
+       
+       #ifdef __GNUC__
+               #define INFINITY (__builtin_inf())
+       #endif
+       
+       #ifndef INFINITY
+               #define INFINITY (1e1000)
+       #endif
+#endif
+
+
+#define CP_PI ((cpFloat)3.14159265358979323846264338327950288)
+
+
+/// Return the max of two cpFloats.
+static inline cpFloat cpfmax(cpFloat a, cpFloat b)
+{
+       return (a > b) ? a : b;
+}
+
+/// Return the min of two cpFloats.
+static inline cpFloat cpfmin(cpFloat a, cpFloat b)
+{
+       return (a < b) ? a : b;
+}
+
+/// Return the absolute value of a cpFloat.
+static inline cpFloat cpfabs(cpFloat f)
+{
+       return (f < 0) ? -f : f;
+}
+
+/// Clamp @c f to be between @c min and @c max.
+static inline cpFloat cpfclamp(cpFloat f, cpFloat min, cpFloat max)
+{
+       return cpfmin(cpfmax(f, min), max);
+}
+
+/// Clamp @c f to be between 0 and 1.
+static inline cpFloat cpfclamp01(cpFloat f)
+{
+       return cpfmax(0.0f, cpfmin(f, 1.0f));
+}
+
+
+
+/// Linearly interpolate (or extrapolate) between @c f1 and @c f2 by @c t percent.
+static inline cpFloat cpflerp(cpFloat f1, cpFloat f2, cpFloat t)
+{
+       return f1*(1.0f - t) + f2*t;
+}
+
+/// Linearly interpolate from @c f1 to @c f2 by no more than @c d.
+static inline cpFloat cpflerpconst(cpFloat f1, cpFloat f2, cpFloat d)
+{
+       return f1 + cpfclamp(f2 - f1, -d, d);
+}
+
+/// Hash value type.
+#ifdef CP_HASH_VALUE_TYPE
+       typedef CP_HASH_VALUE_TYPE cpHashValue;
+#else
+       typedef uintptr_t cpHashValue;
+#endif
+
+/// Type used internally to cache colliding object info for cpCollideShapes().
+/// Should be at least 32 bits.
+typedef uint32_t cpCollisionID;
+
+// Oh C, how we love to define our own boolean types to get compiler compatibility
+/// Chipmunk's boolean type.
+#ifdef CP_BOOL_TYPE
+       typedef CP_BOOL_TYPE cpBool;
+#else
+       typedef unsigned char cpBool;
+#endif
+
+#ifndef cpTrue
+/// true value.
+       #define cpTrue 1
+#endif
+
+#ifndef cpFalse
+/// false value.
+       #define cpFalse 0
+#endif
+
+#ifdef CP_DATA_POINTER_TYPE
+       typedef CP_DATA_POINTER_TYPE cpDataPointer;
+#else
+/// Type used for user data pointers.
+       typedef void * cpDataPointer;
+#endif
+
+#ifdef CP_COLLISION_TYPE_TYPE
+       typedef CP_COLLISION_TYPE_TYPE cpCollisionType;
+#else
+/// Type used for cpSpace.collision_type.
+       typedef uintptr_t cpCollisionType;
+#endif
+
+#ifdef CP_GROUP_TYPE
+       typedef CP_GROUP_TYPE cpGroup;
+#else
+/// Type used for cpShape.group.
+       typedef uintptr_t cpGroup;
+#endif
+
+#ifdef CP_BITMASK_TYPE
+       typedef CP_BITMASK_TYPE cpBitmask;
+#else
+/// Type used for cpShapeFilter category and mask.
+       typedef unsigned int cpBitmask;
+#endif
+
+#ifdef CP_TIMESTAMP_TYPE
+       typedef CP_TIMESTAMP_TYPE cpTimestamp;
+#else
+/// Type used for various timestamps in Chipmunk.
+       typedef unsigned int cpTimestamp;
+#endif
+
+#ifndef CP_NO_GROUP
+/// Value for cpShape.group signifying that a shape is in no group.
+       #define CP_NO_GROUP ((cpGroup)0)
+#endif
+
+#ifndef CP_ALL_CATEGORIES
+/// Value for cpShape.layers signifying that a shape is in every layer.
+       #define CP_ALL_CATEGORIES (~(cpBitmask)0)
+#endif
+
+#ifndef CP_WILDCARD_COLLISION_TYPE
+/// cpCollisionType value internally reserved for hashing wildcard handlers.
+       #define CP_WILDCARD_COLLISION_TYPE (~(cpCollisionType)0)
+#endif
+
+/// @}
+
+// CGPoints are structurally the same, and allow
+// easy interoperability with other Cocoa libraries
+#if CP_USE_CGTYPES
+       typedef CGPoint cpVect;
+#else
+/// Chipmunk's 2D vector type.
+/// @addtogroup cpVect
+       typedef struct cpVect{cpFloat x,y;} cpVect;
+#endif
+
+#if CP_USE_CGTYPES
+       typedef CGAffineTransform cpTransform;
+#else
+       /// Column major affine transform.
+       typedef struct cpTransform {
+               cpFloat a, b, c, d, tx, ty;
+       } cpTransform;
+#endif
+
+// NUKE
+typedef struct cpMat2x2 {
+       // Row major [[a, b][c d]]
+       cpFloat a, b, c, d;
+} cpMat2x2;
+
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_unsafe.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_unsafe.h
new file mode 100644 (file)
index 0000000..990bd01
--- /dev/null
@@ -0,0 +1,66 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* This header defines a number of "unsafe" operations on Chipmunk objects.
+ * In this case "unsafe" is referring to operations which may reduce the
+ * physical accuracy or numerical stability of the simulation, but will not
+ * cause crashes.
+ *
+ * The prime example is mutating collision shapes. Chipmunk does not support
+ * this directly. Mutating shapes using this API will caused objects in contact
+ * to be pushed apart using Chipmunk's overlap solver, but not using real
+ * persistent velocities. Probably not what you meant, but perhaps close enough.
+ */
+
+/// @defgroup unsafe Chipmunk Unsafe Shape Operations
+/// These functions are used for mutating collision shapes.
+/// Chipmunk does not have any way to get velocity information on changing shapes,
+/// so the results will be unrealistic. You must explicity include the chipmunk_unsafe.h header to use them.
+/// @{
+
+#ifndef CHIPMUNK_UNSAFE_H
+#define CHIPMUNK_UNSAFE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Set the radius of a circle shape.
+CP_EXPORT void cpCircleShapeSetRadius(cpShape *shape, cpFloat radius);
+/// Set the offset of a circle shape.
+CP_EXPORT void cpCircleShapeSetOffset(cpShape *shape, cpVect offset);
+
+/// Set the endpoints of a segment shape.
+CP_EXPORT void cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b);
+/// Set the radius of a segment shape.
+CP_EXPORT void cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius);
+
+/// Set the vertexes of a poly shape.
+CP_EXPORT void cpPolyShapeSetVerts(cpShape *shape, int count, cpVect *verts, cpTransform transform);
+CP_EXPORT void cpPolyShapeSetVertsRaw(cpShape *shape, int count, cpVect *verts);
+/// Set the radius of a poly shape.
+CP_EXPORT void cpPolyShapeSetRadius(cpShape *shape, cpFloat radius);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpArbiter.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpArbiter.h
new file mode 100644 (file)
index 0000000..1dc130a
--- /dev/null
@@ -0,0 +1,145 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpArbiter cpArbiter
+/// The cpArbiter struct tracks pairs of colliding shapes.
+/// They are also used in conjuction with collision handler callbacks
+/// allowing you to retrieve information on the collision or change it.
+/// A unique arbiter value is used for each pair of colliding objects. It persists until the shapes separate.
+/// @{
+
+#define CP_MAX_CONTACTS_PER_ARBITER 2
+
+/// Get the restitution (elasticity) that will be applied to the pair of colliding objects.
+CP_EXPORT cpFloat cpArbiterGetRestitution(const cpArbiter *arb);
+/// Override the restitution (elasticity) that will be applied to the pair of colliding objects.
+CP_EXPORT void cpArbiterSetRestitution(cpArbiter *arb, cpFloat restitution);
+/// Get the friction coefficient that will be applied to the pair of colliding objects.
+CP_EXPORT cpFloat cpArbiterGetFriction(const cpArbiter *arb);
+/// Override the friction coefficient that will be applied to the pair of colliding objects.
+CP_EXPORT void cpArbiterSetFriction(cpArbiter *arb, cpFloat friction);
+
+// Get the relative surface velocity of the two shapes in contact.
+CP_EXPORT cpVect cpArbiterGetSurfaceVelocity(cpArbiter *arb);
+
+// Override the relative surface velocity of the two shapes in contact.
+// By default this is calculated to be the difference of the two surface velocities clamped to the tangent plane.
+CP_EXPORT void cpArbiterSetSurfaceVelocity(cpArbiter *arb, cpVect vr);
+
+/// Get the user data pointer associated with this pair of colliding objects.
+CP_EXPORT cpDataPointer cpArbiterGetUserData(const cpArbiter *arb);
+/// Set a user data point associated with this pair of colliding objects.
+/// If you need to perform any cleanup for this pointer, you must do it yourself, in the separate callback for instance.
+CP_EXPORT void cpArbiterSetUserData(cpArbiter *arb, cpDataPointer userData);
+
+/// Calculate the total impulse including the friction that was applied by this arbiter.
+/// This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback.
+CP_EXPORT cpVect cpArbiterTotalImpulse(const cpArbiter *arb);
+/// Calculate the amount of energy lost in a collision including static, but not dynamic friction.
+/// This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback.
+CP_EXPORT cpFloat cpArbiterTotalKE(const cpArbiter *arb);
+
+/// Mark a collision pair to be ignored until the two objects separate.
+/// Pre-solve and post-solve callbacks will not be called, but the separate callback will be called.
+CP_EXPORT cpBool cpArbiterIgnore(cpArbiter *arb);
+
+/// Return the colliding shapes involved for this arbiter.
+/// The order of their cpSpace.collision_type values will match
+/// the order set when the collision handler was registered.
+CP_EXPORT void cpArbiterGetShapes(const cpArbiter *arb, cpShape **a, cpShape **b);
+
+/// A macro shortcut for defining and retrieving the shapes from an arbiter.
+#define CP_ARBITER_GET_SHAPES(__arb__, __a__, __b__) cpShape *__a__, *__b__; cpArbiterGetShapes(__arb__, &__a__, &__b__);
+
+/// Return the colliding bodies involved for this arbiter.
+/// The order of the cpSpace.collision_type the bodies are associated with values will match
+/// the order set when the collision handler was registered.
+CP_EXPORT void cpArbiterGetBodies(const cpArbiter *arb, cpBody **a, cpBody **b);
+
+/// A macro shortcut for defining and retrieving the bodies from an arbiter.
+#define CP_ARBITER_GET_BODIES(__arb__, __a__, __b__) cpBody *__a__, *__b__; cpArbiterGetBodies(__arb__, &__a__, &__b__);
+
+/// A struct that wraps up the important collision data for an arbiter.
+struct cpContactPointSet {
+       /// The number of contact points in the set.
+       int count;
+       
+       /// The normal of the collision.
+       cpVect normal;
+       
+       /// The array of contact points.
+       struct {
+               /// The position of the contact on the surface of each shape.
+               cpVect pointA, pointB;
+               /// Penetration distance of the two shapes. Overlapping means it will be negative.
+               /// This value is calculated as cpvdot(cpvsub(point2, point1), normal) and is ignored by cpArbiterSetContactPointSet().
+               cpFloat distance;
+       } points[CP_MAX_CONTACTS_PER_ARBITER];
+};
+
+/// Return a contact set from an arbiter.
+CP_EXPORT cpContactPointSet cpArbiterGetContactPointSet(const cpArbiter *arb);
+
+/// Replace the contact point set for an arbiter.
+/// This can be a very powerful feature, but use it with caution!
+CP_EXPORT void cpArbiterSetContactPointSet(cpArbiter *arb, cpContactPointSet *set);
+
+/// Returns true if this is the first step a pair of objects started colliding.
+CP_EXPORT cpBool cpArbiterIsFirstContact(const cpArbiter *arb);
+/// Returns true if the separate callback is due to a shape being removed from the space.
+CP_EXPORT cpBool cpArbiterIsRemoval(const cpArbiter *arb);
+
+/// Get the number of contact points for this arbiter.
+CP_EXPORT int cpArbiterGetCount(const cpArbiter *arb);
+/// Get the normal of the collision.
+CP_EXPORT cpVect cpArbiterGetNormal(const cpArbiter *arb);
+/// Get the position of the @c ith contact point on the surface of the first shape.
+CP_EXPORT cpVect cpArbiterGetPointA(const cpArbiter *arb, int i);
+/// Get the position of the @c ith contact point on the surface of the second shape.
+CP_EXPORT cpVect cpArbiterGetPointB(const cpArbiter *arb, int i);
+/// Get the depth of the @c ith contact point.
+CP_EXPORT cpFloat cpArbiterGetDepth(const cpArbiter *arb, int i);
+
+/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly.
+/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own.
+CP_EXPORT cpBool cpArbiterCallWildcardBeginA(cpArbiter *arb, cpSpace *space);
+/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly.
+/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own.
+CP_EXPORT cpBool cpArbiterCallWildcardBeginB(cpArbiter *arb, cpSpace *space);
+
+/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly.
+/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own.
+CP_EXPORT cpBool cpArbiterCallWildcardPreSolveA(cpArbiter *arb, cpSpace *space);
+/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly.
+/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own.
+CP_EXPORT cpBool cpArbiterCallWildcardPreSolveB(cpArbiter *arb, cpSpace *space);
+
+/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly.
+CP_EXPORT void cpArbiterCallWildcardPostSolveA(cpArbiter *arb, cpSpace *space);
+/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly.
+CP_EXPORT void cpArbiterCallWildcardPostSolveB(cpArbiter *arb, cpSpace *space);
+
+/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly.
+CP_EXPORT void cpArbiterCallWildcardSeparateA(cpArbiter *arb, cpSpace *space);
+/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly.
+CP_EXPORT void cpArbiterCallWildcardSeparateB(cpArbiter *arb, cpSpace *space);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpBB.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpBB.h
new file mode 100644 (file)
index 0000000..8fc8704
--- /dev/null
@@ -0,0 +1,187 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_BB_H
+#define CHIPMUNK_BB_H
+
+#include "chipmunk_types.h"
+#include "cpVect.h"
+
+/// @defgroup cpBBB cpBB
+/// Chipmunk's axis-aligned 2D bounding box type along with a few handy routines.
+/// @{
+
+/// Chipmunk's axis-aligned 2D bounding box type. (left, bottom, right, top)
+typedef struct cpBB{
+       cpFloat l, b, r ,t;
+} cpBB;
+
+/// Convenience constructor for cpBB structs.
+static inline cpBB cpBBNew(const cpFloat l, const cpFloat b, const cpFloat r, const cpFloat t)
+{
+       cpBB bb = {l, b, r, t};
+       return bb;
+}
+
+/// Constructs a cpBB centered on a point with the given extents (half sizes).
+static inline cpBB
+cpBBNewForExtents(const cpVect c, const cpFloat hw, const cpFloat hh)
+{
+       return cpBBNew(c.x - hw, c.y - hh, c.x + hw, c.y + hh);
+}
+
+/// Constructs a cpBB for a circle with the given position and radius.
+static inline cpBB cpBBNewForCircle(const cpVect p, const cpFloat r)
+{
+       return cpBBNewForExtents(p, r, r);
+}
+
+/// Returns true if @c a and @c b intersect.
+static inline cpBool cpBBIntersects(const cpBB a, const cpBB b)
+{
+       return (a.l <= b.r && b.l <= a.r && a.b <= b.t && b.b <= a.t);
+}
+
+/// Returns true if @c other lies completely within @c bb.
+static inline cpBool cpBBContainsBB(const cpBB bb, const cpBB other)
+{
+       return (bb.l <= other.l && bb.r >= other.r && bb.b <= other.b && bb.t >= other.t);
+}
+
+/// Returns true if @c bb contains @c v.
+static inline cpBool cpBBContainsVect(const cpBB bb, const cpVect v)
+{
+       return (bb.l <= v.x && bb.r >= v.x && bb.b <= v.y && bb.t >= v.y);
+}
+
+/// Returns a bounding box that holds both bounding boxes.
+static inline cpBB cpBBMerge(const cpBB a, const cpBB b){
+       return cpBBNew(
+               cpfmin(a.l, b.l),
+               cpfmin(a.b, b.b),
+               cpfmax(a.r, b.r),
+               cpfmax(a.t, b.t)
+       );
+}
+
+/// Returns a bounding box that holds both @c bb and @c v.
+static inline cpBB cpBBExpand(const cpBB bb, const cpVect v){
+       return cpBBNew(
+               cpfmin(bb.l, v.x),
+               cpfmin(bb.b, v.y),
+               cpfmax(bb.r, v.x),
+               cpfmax(bb.t, v.y)
+       );
+}
+
+/// Returns the center of a bounding box.
+static inline cpVect
+cpBBCenter(cpBB bb)
+{
+       return cpvlerp(cpv(bb.l, bb.b), cpv(bb.r, bb.t), 0.5f);
+}
+
+/// Returns the area of the bounding box.
+static inline cpFloat cpBBArea(cpBB bb)
+{
+       return (bb.r - bb.l)*(bb.t - bb.b);
+}
+
+/// Merges @c a and @c b and returns the area of the merged bounding box.
+static inline cpFloat cpBBMergedArea(cpBB a, cpBB b)
+{
+       return (cpfmax(a.r, b.r) - cpfmin(a.l, b.l))*(cpfmax(a.t, b.t) - cpfmin(a.b, b.b));
+}
+
+/// Returns the fraction along the segment query the cpBB is hit. Returns INFINITY if it doesn't hit.
+static inline cpFloat cpBBSegmentQuery(cpBB bb, cpVect a, cpVect b)
+{
+       cpVect delta = cpvsub(b, a);
+       cpFloat tmin = -INFINITY, tmax = INFINITY;
+       
+       if(delta.x == 0.0f){
+               if(a.x < bb.l || bb.r < a.x) return INFINITY;
+       } else {
+               cpFloat t1 = (bb.l - a.x)/delta.x;
+               cpFloat t2 = (bb.r - a.x)/delta.x;
+               tmin = cpfmax(tmin, cpfmin(t1, t2));
+               tmax = cpfmin(tmax, cpfmax(t1, t2));
+       }
+       
+       if(delta.y == 0.0f){
+               if(a.y < bb.b || bb.t < a.y) return INFINITY;
+       } else {
+               cpFloat t1 = (bb.b - a.y)/delta.y;
+               cpFloat t2 = (bb.t - a.y)/delta.y;
+               tmin = cpfmax(tmin, cpfmin(t1, t2));
+               tmax = cpfmin(tmax, cpfmax(t1, t2));
+       }
+       
+       if(tmin <= tmax && 0.0f <= tmax && tmin <= 1.0f){
+               return cpfmax(tmin, 0.0f);
+       } else {
+               return INFINITY;
+       }
+}
+
+/// Return true if the bounding box intersects the line segment with ends @c a and @c b.
+static inline cpBool cpBBIntersectsSegment(cpBB bb, cpVect a, cpVect b)
+{
+       return (cpBBSegmentQuery(bb, a, b) != INFINITY);
+}
+
+/// Clamp a vector to a bounding box.
+static inline cpVect
+cpBBClampVect(const cpBB bb, const cpVect v)
+{
+       return cpv(cpfclamp(v.x, bb.l, bb.r), cpfclamp(v.y, bb.b, bb.t));
+}
+
+/// Wrap a vector to a bounding box.
+static inline cpVect
+cpBBWrapVect(const cpBB bb, const cpVect v)
+{
+       cpFloat dx = cpfabs(bb.r - bb.l);
+       cpFloat modx = cpfmod(v.x - bb.l, dx);
+       cpFloat x = (modx > 0.0f) ? modx : modx + dx;
+       
+       cpFloat dy = cpfabs(bb.t - bb.b);
+       cpFloat mody = cpfmod(v.y - bb.b, dy);
+       cpFloat y = (mody > 0.0f) ? mody : mody + dy;
+       
+       return cpv(x + bb.l, y + bb.b);
+}
+
+/// Returns a bounding box offseted by @c v.
+static inline cpBB
+cpBBOffset(const cpBB bb, const cpVect v)
+{
+       return cpBBNew(
+               bb.l + v.x,
+               bb.b + v.y,
+               bb.r + v.x,
+               bb.t + v.y
+       );
+}
+
+///@}
+
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpBody.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpBody.h
new file mode 100644 (file)
index 0000000..7e6943d
--- /dev/null
@@ -0,0 +1,189 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpBody cpBody
+/// Chipmunk's rigid body type. Rigid bodies hold the physical properties of an object like
+/// it's mass, and position and velocity of it's center of gravity. They don't have an shape on their own.
+/// They are given a shape by creating collision shapes (cpShape) that point to the body.
+/// @{
+
+typedef enum cpBodyType {
+       /// A dynamic body is one that is affected by gravity, forces, and collisions.
+       /// This is the default body type.
+       CP_BODY_TYPE_DYNAMIC,
+       /// A kinematic body is an infinite mass, user controlled body that is not affected by gravity, forces or collisions.
+       /// Instead the body only moves based on it's velocity.
+       /// Dynamic bodies collide normally with kinematic bodies, though the kinematic body will be unaffected.
+       /// Collisions between two kinematic bodies, or a kinematic body and a static body produce collision callbacks, but no collision response.
+       CP_BODY_TYPE_KINEMATIC,
+       /// A static body is a body that never (or rarely) moves. If you move a static body, you must call one of the cpSpaceReindex*() functions.
+       /// Chipmunk uses this information to optimize the collision detection.
+       /// Static bodies do not produce collision callbacks when colliding with other static bodies.
+       CP_BODY_TYPE_STATIC,
+} cpBodyType;
+
+/// Rigid body velocity update function type.
+typedef void (*cpBodyVelocityFunc)(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
+/// Rigid body position update function type.
+typedef void (*cpBodyPositionFunc)(cpBody *body, cpFloat dt);
+
+/// Allocate a cpBody.
+CP_EXPORT cpBody* cpBodyAlloc(void);
+/// Initialize a cpBody.
+CP_EXPORT cpBody* cpBodyInit(cpBody *body, cpFloat mass, cpFloat moment);
+/// Allocate and initialize a cpBody.
+CP_EXPORT cpBody* cpBodyNew(cpFloat mass, cpFloat moment);
+
+/// Allocate and initialize a cpBody, and set it as a kinematic body.
+CP_EXPORT cpBody* cpBodyNewKinematic(void);
+/// Allocate and initialize a cpBody, and set it as a static body.
+CP_EXPORT cpBody* cpBodyNewStatic(void);
+
+/// Destroy a cpBody.
+CP_EXPORT void cpBodyDestroy(cpBody *body);
+/// Destroy and free a cpBody.
+CP_EXPORT void cpBodyFree(cpBody *body);
+
+// Defined in cpSpace.c
+/// Wake up a sleeping or idle body.
+CP_EXPORT void cpBodyActivate(cpBody *body);
+/// Wake up any sleeping or idle bodies touching a static body.
+CP_EXPORT void cpBodyActivateStatic(cpBody *body, cpShape *filter);
+
+/// Force a body to fall asleep immediately.
+CP_EXPORT void cpBodySleep(cpBody *body);
+/// Force a body to fall asleep immediately along with other bodies in a group.
+CP_EXPORT void cpBodySleepWithGroup(cpBody *body, cpBody *group);
+
+/// Returns true if the body is sleeping.
+CP_EXPORT cpBool cpBodyIsSleeping(const cpBody *body);
+
+/// Get the type of the body.
+CP_EXPORT cpBodyType cpBodyGetType(cpBody *body);
+/// Set the type of the body.
+CP_EXPORT void cpBodySetType(cpBody *body, cpBodyType type);
+
+/// Get the space this body is added to.
+CP_EXPORT cpSpace* cpBodyGetSpace(const cpBody *body);
+
+/// Get the mass of the body.
+CP_EXPORT cpFloat cpBodyGetMass(const cpBody *body);
+/// Set the mass of the body.
+CP_EXPORT void cpBodySetMass(cpBody *body, cpFloat m);
+
+/// Get the moment of inertia of the body.
+CP_EXPORT cpFloat cpBodyGetMoment(const cpBody *body);
+/// Set the moment of inertia of the body.
+CP_EXPORT void cpBodySetMoment(cpBody *body, cpFloat i);
+
+/// Set the position of a body.
+CP_EXPORT cpVect cpBodyGetPosition(const cpBody *body);
+/// Set the position of the body.
+CP_EXPORT void cpBodySetPosition(cpBody *body, cpVect pos);
+
+/// Get the offset of the center of gravity in body local coordinates.
+CP_EXPORT cpVect cpBodyGetCenterOfGravity(const cpBody *body);
+/// Set the offset of the center of gravity in body local coordinates.
+CP_EXPORT void cpBodySetCenterOfGravity(cpBody *body, cpVect cog);
+
+/// Get the velocity of the body.
+CP_EXPORT cpVect cpBodyGetVelocity(const cpBody *body);
+/// Set the velocity of the body.
+CP_EXPORT void cpBodySetVelocity(cpBody *body, cpVect velocity);
+
+/// Get the force applied to the body for the next time step.
+CP_EXPORT cpVect cpBodyGetForce(const cpBody *body);
+/// Set the force applied to the body for the next time step.
+CP_EXPORT void cpBodySetForce(cpBody *body, cpVect force);
+
+/// Get the angle of the body.
+CP_EXPORT cpFloat cpBodyGetAngle(const cpBody *body);
+/// Set the angle of a body.
+CP_EXPORT void cpBodySetAngle(cpBody *body, cpFloat a);
+
+/// Get the angular velocity of the body.
+CP_EXPORT cpFloat cpBodyGetAngularVelocity(const cpBody *body);
+/// Set the angular velocity of the body.
+CP_EXPORT void cpBodySetAngularVelocity(cpBody *body, cpFloat angularVelocity);
+
+/// Get the torque applied to the body for the next time step.
+CP_EXPORT cpFloat cpBodyGetTorque(const cpBody *body);
+/// Set the torque applied to the body for the next time step.
+CP_EXPORT void cpBodySetTorque(cpBody *body, cpFloat torque);
+
+/// Get the rotation vector of the body. (The x basis vector of it's transform.)
+CP_EXPORT cpVect cpBodyGetRotation(const cpBody *body);
+
+/// Get the user data pointer assigned to the body.
+CP_EXPORT cpDataPointer cpBodyGetUserData(const cpBody *body);
+/// Set the user data pointer assigned to the body.
+CP_EXPORT void cpBodySetUserData(cpBody *body, cpDataPointer userData);
+
+/// Set the callback used to update a body's velocity.
+CP_EXPORT void cpBodySetVelocityUpdateFunc(cpBody *body, cpBodyVelocityFunc velocityFunc);
+/// Set the callback used to update a body's position.
+/// NOTE: It's not generally recommended to override this unless you call the default position update function.
+CP_EXPORT void cpBodySetPositionUpdateFunc(cpBody *body, cpBodyPositionFunc positionFunc);
+
+/// Default velocity integration function..
+CP_EXPORT void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt);
+/// Default position integration function.
+CP_EXPORT void cpBodyUpdatePosition(cpBody *body, cpFloat dt);
+
+/// Convert body relative/local coordinates to absolute/world coordinates.
+CP_EXPORT cpVect cpBodyLocalToWorld(const cpBody *body, const cpVect point);
+/// Convert body absolute/world coordinates to  relative/local coordinates.
+CP_EXPORT cpVect cpBodyWorldToLocal(const cpBody *body, const cpVect point);
+
+/// Apply a force to a body. Both the force and point are expressed in world coordinates.
+CP_EXPORT void cpBodyApplyForceAtWorldPoint(cpBody *body, cpVect force, cpVect point);
+/// Apply a force to a body. Both the force and point are expressed in body local coordinates.
+CP_EXPORT void cpBodyApplyForceAtLocalPoint(cpBody *body, cpVect force, cpVect point);
+
+/// Apply an impulse to a body. Both the impulse and point are expressed in world coordinates.
+CP_EXPORT void cpBodyApplyImpulseAtWorldPoint(cpBody *body, cpVect impulse, cpVect point);
+/// Apply an impulse to a body. Both the impulse and point are expressed in body local coordinates.
+CP_EXPORT void cpBodyApplyImpulseAtLocalPoint(cpBody *body, cpVect impulse, cpVect point);
+
+/// Get the velocity on a body (in world units) at a point on the body in world coordinates.
+CP_EXPORT cpVect cpBodyGetVelocityAtWorldPoint(const cpBody *body, cpVect point);
+/// Get the velocity on a body (in world units) at a point on the body in local coordinates.
+CP_EXPORT cpVect cpBodyGetVelocityAtLocalPoint(const cpBody *body, cpVect point);
+
+/// Get the amount of kinetic energy contained by the body.
+CP_EXPORT cpFloat cpBodyKineticEnergy(const cpBody *body);
+
+/// Body/shape iterator callback function type. 
+typedef void (*cpBodyShapeIteratorFunc)(cpBody *body, cpShape *shape, void *data);
+/// Call @c func once for each shape attached to @c body and added to the space.
+CP_EXPORT void cpBodyEachShape(cpBody *body, cpBodyShapeIteratorFunc func, void *data);
+
+/// Body/constraint iterator callback function type. 
+typedef void (*cpBodyConstraintIteratorFunc)(cpBody *body, cpConstraint *constraint, void *data);
+/// Call @c func once for each constraint attached to @c body and added to the space.
+CP_EXPORT void cpBodyEachConstraint(cpBody *body, cpBodyConstraintIteratorFunc func, void *data);
+
+/// Body/arbiter iterator callback function type. 
+typedef void (*cpBodyArbiterIteratorFunc)(cpBody *body, cpArbiter *arbiter, void *data);
+/// Call @c func once for each arbiter that is currently active on the body.
+CP_EXPORT void cpBodyEachArbiter(cpBody *body, cpBodyArbiterIteratorFunc func, void *data);
+
+///@}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpConstraint.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpConstraint.h
new file mode 100644 (file)
index 0000000..b1a439f
--- /dev/null
@@ -0,0 +1,95 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpConstraint cpConstraint
+/// @{
+
+/// Callback function type that gets called before solving a joint.
+typedef void (*cpConstraintPreSolveFunc)(cpConstraint *constraint, cpSpace *space);
+/// Callback function type that gets called after solving a joint.
+typedef void (*cpConstraintPostSolveFunc)(cpConstraint *constraint, cpSpace *space);
+
+/// Destroy a constraint.
+CP_EXPORT void cpConstraintDestroy(cpConstraint *constraint);
+/// Destroy and free a constraint.
+CP_EXPORT void cpConstraintFree(cpConstraint *constraint);
+
+/// Get the cpSpace this constraint is added to.
+CP_EXPORT cpSpace* cpConstraintGetSpace(const cpConstraint *constraint);
+
+/// Get the first body the constraint is attached to.
+CP_EXPORT cpBody* cpConstraintGetBodyA(const cpConstraint *constraint);
+
+/// Get the second body the constraint is attached to.
+CP_EXPORT cpBody* cpConstraintGetBodyB(const cpConstraint *constraint);
+
+/// Get the maximum force that this constraint is allowed to use.
+CP_EXPORT cpFloat cpConstraintGetMaxForce(const cpConstraint *constraint);
+/// Set the maximum force that this constraint is allowed to use. (defaults to INFINITY)
+CP_EXPORT void cpConstraintSetMaxForce(cpConstraint *constraint, cpFloat maxForce);
+
+/// Get rate at which joint error is corrected.
+CP_EXPORT cpFloat cpConstraintGetErrorBias(const cpConstraint *constraint);
+/// Set rate at which joint error is corrected.
+/// Defaults to pow(1.0 - 0.1, 60.0) meaning that it will
+/// correct 10% of the error every 1/60th of a second.
+CP_EXPORT void cpConstraintSetErrorBias(cpConstraint *constraint, cpFloat errorBias);
+
+/// Get the maximum rate at which joint error is corrected.
+CP_EXPORT cpFloat cpConstraintGetMaxBias(const cpConstraint *constraint);
+/// Set the maximum rate at which joint error is corrected. (defaults to INFINITY)
+CP_EXPORT void cpConstraintSetMaxBias(cpConstraint *constraint, cpFloat maxBias);
+
+/// Get if the two bodies connected by the constraint are allowed to collide or not.
+CP_EXPORT cpBool cpConstraintGetCollideBodies(const cpConstraint *constraint);
+/// Set if the two bodies connected by the constraint are allowed to collide or not. (defaults to cpFalse)
+CP_EXPORT void cpConstraintSetCollideBodies(cpConstraint *constraint, cpBool collideBodies);
+
+/// Get the pre-solve function that is called before the solver runs.
+CP_EXPORT cpConstraintPreSolveFunc cpConstraintGetPreSolveFunc(const cpConstraint *constraint);
+/// Set the pre-solve function that is called before the solver runs.
+CP_EXPORT void cpConstraintSetPreSolveFunc(cpConstraint *constraint, cpConstraintPreSolveFunc preSolveFunc);
+
+/// Get the post-solve function that is called before the solver runs.
+CP_EXPORT cpConstraintPostSolveFunc cpConstraintGetPostSolveFunc(const cpConstraint *constraint);
+/// Set the post-solve function that is called before the solver runs.
+CP_EXPORT void cpConstraintSetPostSolveFunc(cpConstraint *constraint, cpConstraintPostSolveFunc postSolveFunc);
+
+/// Get the user definable data pointer for this constraint
+CP_EXPORT cpDataPointer cpConstraintGetUserData(const cpConstraint *constraint);
+/// Set the user definable data pointer for this constraint
+CP_EXPORT void cpConstraintSetUserData(cpConstraint *constraint, cpDataPointer userData);
+
+/// Get the last impulse applied by this constraint.
+CP_EXPORT cpFloat cpConstraintGetImpulse(cpConstraint *constraint);
+
+#include "cpPinJoint.h"
+#include "cpSlideJoint.h"
+#include "cpPivotJoint.h"
+#include "cpGrooveJoint.h"
+#include "cpDampedSpring.h"
+#include "cpDampedRotarySpring.h"
+#include "cpRotaryLimitJoint.h"
+#include "cpRatchetJoint.h"
+#include "cpGearJoint.h"
+#include "cpSimpleMotor.h"
+
+///@}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpDampedRotarySpring.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpDampedRotarySpring.h
new file mode 100644 (file)
index 0000000..6f60e86
--- /dev/null
@@ -0,0 +1,58 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpDampedRotarySpring cpDampedRotarySpring
+/// @{
+
+/// Check if a constraint is a damped rotary springs.
+CP_EXPORT cpBool cpConstraintIsDampedRotarySpring(const cpConstraint *constraint);
+
+/// Function type used for damped rotary spring force callbacks.
+typedef cpFloat (*cpDampedRotarySpringTorqueFunc)(struct cpConstraint *spring, cpFloat relativeAngle);
+
+/// Allocate a damped rotary spring.
+CP_EXPORT cpDampedRotarySpring* cpDampedRotarySpringAlloc(void);
+/// Initialize a damped rotary spring.
+CP_EXPORT cpDampedRotarySpring* cpDampedRotarySpringInit(cpDampedRotarySpring *joint, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping);
+/// Allocate and initialize a damped rotary spring.
+CP_EXPORT cpConstraint* cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping);
+
+/// Get the rest length of the spring.
+CP_EXPORT cpFloat cpDampedRotarySpringGetRestAngle(const cpConstraint *constraint);
+/// Set the rest length of the spring.
+CP_EXPORT void cpDampedRotarySpringSetRestAngle(cpConstraint *constraint, cpFloat restAngle);
+
+/// Get the stiffness of the spring in force/distance.
+CP_EXPORT cpFloat cpDampedRotarySpringGetStiffness(const cpConstraint *constraint);
+/// Set the stiffness of the spring in force/distance.
+CP_EXPORT void cpDampedRotarySpringSetStiffness(cpConstraint *constraint, cpFloat stiffness);
+
+/// Get the damping of the spring.
+CP_EXPORT cpFloat cpDampedRotarySpringGetDamping(const cpConstraint *constraint);
+/// Set the damping of the spring.
+CP_EXPORT void cpDampedRotarySpringSetDamping(cpConstraint *constraint, cpFloat damping);
+
+/// Get the damping of the spring.
+CP_EXPORT cpDampedRotarySpringTorqueFunc cpDampedRotarySpringGetSpringTorqueFunc(const cpConstraint *constraint);
+/// Set the damping of the spring.
+CP_EXPORT void cpDampedRotarySpringSetSpringTorqueFunc(cpConstraint *constraint, cpDampedRotarySpringTorqueFunc springTorqueFunc);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpDampedSpring.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpDampedSpring.h
new file mode 100644 (file)
index 0000000..b332fc7
--- /dev/null
@@ -0,0 +1,68 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpDampedSpring cpDampedSpring
+/// @{
+
+/// Check if a constraint is a slide joint.
+CP_EXPORT cpBool cpConstraintIsDampedSpring(const cpConstraint *constraint);
+
+/// Function type used for damped spring force callbacks.
+typedef cpFloat (*cpDampedSpringForceFunc)(cpConstraint *spring, cpFloat dist);
+
+/// Allocate a damped spring.
+CP_EXPORT cpDampedSpring* cpDampedSpringAlloc(void);
+/// Initialize a damped spring.
+CP_EXPORT cpDampedSpring* cpDampedSpringInit(cpDampedSpring *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping);
+/// Allocate and initialize a damped spring.
+CP_EXPORT cpConstraint* cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping);
+
+/// Get the location of the first anchor relative to the first body.
+CP_EXPORT cpVect cpDampedSpringGetAnchorA(const cpConstraint *constraint);
+/// Set the location of the first anchor relative to the first body.
+CP_EXPORT void cpDampedSpringSetAnchorA(cpConstraint *constraint, cpVect anchorA);
+
+/// Get the location of the second anchor relative to the second body.
+CP_EXPORT cpVect cpDampedSpringGetAnchorB(const cpConstraint *constraint);
+/// Set the location of the second anchor relative to the second body.
+CP_EXPORT void cpDampedSpringSetAnchorB(cpConstraint *constraint, cpVect anchorB);
+
+/// Get the rest length of the spring.
+CP_EXPORT cpFloat cpDampedSpringGetRestLength(const cpConstraint *constraint);
+/// Set the rest length of the spring.
+CP_EXPORT void cpDampedSpringSetRestLength(cpConstraint *constraint, cpFloat restLength);
+
+/// Get the stiffness of the spring in force/distance.
+CP_EXPORT cpFloat cpDampedSpringGetStiffness(const cpConstraint *constraint);
+/// Set the stiffness of the spring in force/distance.
+CP_EXPORT void cpDampedSpringSetStiffness(cpConstraint *constraint, cpFloat stiffness);
+
+/// Get the damping of the spring.
+CP_EXPORT cpFloat cpDampedSpringGetDamping(const cpConstraint *constraint);
+/// Set the damping of the spring.
+CP_EXPORT void cpDampedSpringSetDamping(cpConstraint *constraint, cpFloat damping);
+
+/// Get the damping of the spring.
+CP_EXPORT cpDampedSpringForceFunc cpDampedSpringGetSpringForceFunc(const cpConstraint *constraint);
+/// Set the damping of the spring.
+CP_EXPORT void cpDampedSpringSetSpringForceFunc(cpConstraint *constraint, cpDampedSpringForceFunc springForceFunc);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpGearJoint.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpGearJoint.h
new file mode 100644 (file)
index 0000000..8cd80e0
--- /dev/null
@@ -0,0 +1,45 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpGearJoint cpGearJoint
+/// @{
+
+/// Check if a constraint is a damped rotary springs.
+CP_EXPORT cpBool cpConstraintIsGearJoint(const cpConstraint *constraint);
+
+/// Allocate a gear joint.
+CP_EXPORT cpGearJoint* cpGearJointAlloc(void);
+/// Initialize a gear joint.
+CP_EXPORT cpGearJoint* cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio);
+/// Allocate and initialize a gear joint.
+CP_EXPORT cpConstraint* cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio);
+
+/// Get the phase offset of the gears.
+CP_EXPORT cpFloat cpGearJointGetPhase(const cpConstraint *constraint);
+/// Set the phase offset of the gears.
+CP_EXPORT void cpGearJointSetPhase(cpConstraint *constraint, cpFloat phase);
+
+/// Get the angular distance of each ratchet.
+CP_EXPORT cpFloat cpGearJointGetRatio(const cpConstraint *constraint);
+/// Set the ratio of a gear joint.
+CP_EXPORT void cpGearJointSetRatio(cpConstraint *constraint, cpFloat ratio);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpGrooveJoint.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpGrooveJoint.h
new file mode 100644 (file)
index 0000000..8bdafc1
--- /dev/null
@@ -0,0 +1,50 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpGrooveJoint cpGrooveJoint
+/// @{
+
+/// Check if a constraint is a slide joint.
+CP_EXPORT cpBool cpConstraintIsGrooveJoint(const cpConstraint *constraint);
+
+/// Allocate a groove joint.
+CP_EXPORT cpGrooveJoint* cpGrooveJointAlloc(void);
+/// Initialize a groove joint.
+CP_EXPORT cpGrooveJoint* cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB);
+/// Allocate and initialize a groove joint.
+CP_EXPORT cpConstraint* cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB);
+
+/// Get the first endpoint of the groove relative to the first body.
+CP_EXPORT cpVect cpGrooveJointGetGrooveA(const cpConstraint *constraint);
+/// Set the first endpoint of the groove relative to the first body.
+CP_EXPORT void cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect grooveA);
+
+/// Get the first endpoint of the groove relative to the first body.
+CP_EXPORT cpVect cpGrooveJointGetGrooveB(const cpConstraint *constraint);
+/// Set the first endpoint of the groove relative to the first body.
+CP_EXPORT void cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect grooveB);
+
+/// Get the location of the second anchor relative to the second body.
+CP_EXPORT cpVect cpGrooveJointGetAnchorB(const cpConstraint *constraint);
+/// Set the location of the second anchor relative to the second body.
+CP_EXPORT void cpGrooveJointSetAnchorB(cpConstraint *constraint, cpVect anchorB);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpHastySpace.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpHastySpace.h
new file mode 100644 (file)
index 0000000..6de2283
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+/// cpHastySpace is exclusive to Chipmunk Pro
+/// Currently it enables ARM NEON optimizations in the solver, but in the future will include other optimizations such as
+/// a multi-threaded solver and multi-threaded collision broadphases.
+
+struct cpHastySpace;
+typedef struct cpHastySpace cpHastySpace;
+
+/// Create a new hasty space.
+/// On ARM platforms that support NEON, this will enable the vectorized solver.
+/// cpHastySpace also supports multiple threads, but runs single threaded by default for determinism.
+CP_EXPORT cpSpace *cpHastySpaceNew(void);
+CP_EXPORT void cpHastySpaceFree(cpSpace *space);
+
+/// Set the number of threads to use for the solver.
+/// Currently Chipmunk is limited to 2 threads as using more generally provides very minimal performance gains.
+/// Passing 0 as the thread count on iOS or OS X will cause Chipmunk to automatically detect the number of threads it should use.
+/// On other platforms passing 0 for the thread count will set 1 thread.
+CP_EXPORT void cpHastySpaceSetThreads(cpSpace *space, unsigned long threads);
+
+/// Returns the number of threads the solver is using to run.
+CP_EXPORT unsigned long cpHastySpaceGetThreads(cpSpace *space);
+
+/// When stepping a hasty space, you must use this function.
+CP_EXPORT void cpHastySpaceStep(cpSpace *space, cpFloat dt);
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpMarch.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpMarch.h
new file mode 100644 (file)
index 0000000..cc1f5c0
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+/// Function type used as a callback from the marching squares algorithm to sample an image function.
+/// It passes you the point to sample and your context pointer, and you return the density.
+typedef cpFloat (*cpMarchSampleFunc)(cpVect point, void *data);
+
+/// Function type used as a callback from the marching squares algorithm to output a line segment.
+/// It passes you the two endpoints and your context pointer.
+typedef void (*cpMarchSegmentFunc)(cpVect v0, cpVect v1, void *data);
+
+/// Trace an anti-aliased contour of an image along a particular threshold.
+/// The given number of samples will be taken and spread across the bounding box area using the sampling function and context.
+/// The segment function will be called for each segment detected that lies along the density contour for @c threshold.
+CP_EXPORT void cpMarchSoft(
+  cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat threshold,
+  cpMarchSegmentFunc segment, void *segment_data,
+  cpMarchSampleFunc sample, void *sample_data
+);
+
+/// Trace an aliased curve of an image along a particular threshold.
+/// The given number of samples will be taken and spread across the bounding box area using the sampling function and context.
+/// The segment function will be called for each segment detected that lies along the density contour for @c threshold.
+CP_EXPORT void cpMarchHard(
+  cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat threshold,
+  cpMarchSegmentFunc segment, void *segment_data,
+  cpMarchSampleFunc sample, void *sample_data
+);
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpPinJoint.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpPinJoint.h
new file mode 100644 (file)
index 0000000..45aaa3e
--- /dev/null
@@ -0,0 +1,50 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpPinJoint cpPinJoint
+/// @{
+
+/// Check if a constraint is a pin joint.
+CP_EXPORT cpBool cpConstraintIsPinJoint(const cpConstraint *constraint);
+
+/// Allocate a pin joint.
+CP_EXPORT cpPinJoint* cpPinJointAlloc(void);
+/// Initialize a pin joint.
+CP_EXPORT cpPinJoint* cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB);
+/// Allocate and initialize a pin joint.
+CP_EXPORT cpConstraint* cpPinJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB);
+
+/// Get the location of the first anchor relative to the first body.
+CP_EXPORT cpVect cpPinJointGetAnchorA(const cpConstraint *constraint);
+/// Set the location of the first anchor relative to the first body.
+CP_EXPORT void cpPinJointSetAnchorA(cpConstraint *constraint, cpVect anchorA);
+
+/// Get the location of the second anchor relative to the second body.
+CP_EXPORT cpVect cpPinJointGetAnchorB(const cpConstraint *constraint);
+/// Set the location of the second anchor relative to the second body.
+CP_EXPORT void cpPinJointSetAnchorB(cpConstraint *constraint, cpVect anchorB);
+
+/// Get the distance the joint will maintain between the two anchors.
+CP_EXPORT cpFloat cpPinJointGetDist(const cpConstraint *constraint);
+/// Set the distance the joint will maintain between the two anchors.
+CP_EXPORT void cpPinJointSetDist(cpConstraint *constraint, cpFloat dist);
+
+///@}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpPivotJoint.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpPivotJoint.h
new file mode 100644 (file)
index 0000000..4a620ef
--- /dev/null
@@ -0,0 +1,47 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpPivotJoint cpPivotJoint
+/// @{
+
+/// Check if a constraint is a slide joint.
+CP_EXPORT cpBool cpConstraintIsPivotJoint(const cpConstraint *constraint);
+
+/// Allocate a pivot joint
+CP_EXPORT cpPivotJoint* cpPivotJointAlloc(void);
+/// Initialize a pivot joint.
+CP_EXPORT cpPivotJoint* cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB);
+/// Allocate and initialize a pivot joint.
+CP_EXPORT cpConstraint* cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot);
+/// Allocate and initialize a pivot joint with specific anchors.
+CP_EXPORT cpConstraint* cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB);
+
+/// Get the location of the first anchor relative to the first body.
+CP_EXPORT cpVect cpPivotJointGetAnchorA(const cpConstraint *constraint);
+/// Set the location of the first anchor relative to the first body.
+CP_EXPORT void cpPivotJointSetAnchorA(cpConstraint *constraint, cpVect anchorA);
+
+/// Get the location of the second anchor relative to the second body.
+CP_EXPORT cpVect cpPivotJointGetAnchorB(const cpConstraint *constraint);
+/// Set the location of the second anchor relative to the second body.
+CP_EXPORT void cpPivotJointSetAnchorB(cpConstraint *constraint, cpVect anchorB);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpPolyShape.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpPolyShape.h
new file mode 100644 (file)
index 0000000..25f688b
--- /dev/null
@@ -0,0 +1,56 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpPolyShape cpPolyShape
+/// @{
+
+/// Allocate a polygon shape.
+CP_EXPORT cpPolyShape* cpPolyShapeAlloc(void);
+/// Initialize a polygon shape with rounded corners.
+/// A convex hull will be created from the vertexes.
+CP_EXPORT cpPolyShape* cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius);
+/// Initialize a polygon shape with rounded corners.
+/// The vertexes must be convex with a counter-clockwise winding.
+CP_EXPORT cpPolyShape* cpPolyShapeInitRaw(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpFloat radius);
+/// Allocate and initialize a polygon shape with rounded corners.
+/// A convex hull will be created from the vertexes.
+CP_EXPORT cpShape* cpPolyShapeNew(cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius);
+/// Allocate and initialize a polygon shape with rounded corners.
+/// The vertexes must be convex with a counter-clockwise winding.
+CP_EXPORT cpShape* cpPolyShapeNewRaw(cpBody *body, int count, const cpVect *verts, cpFloat radius);
+
+/// Initialize a box shaped polygon shape with rounded corners.
+CP_EXPORT cpPolyShape* cpBoxShapeInit(cpPolyShape *poly, cpBody *body, cpFloat width, cpFloat height, cpFloat radius);
+/// Initialize an offset box shaped polygon shape with rounded corners.
+CP_EXPORT cpPolyShape* cpBoxShapeInit2(cpPolyShape *poly, cpBody *body, cpBB box, cpFloat radius);
+/// Allocate and initialize a box shaped polygon shape.
+CP_EXPORT cpShape* cpBoxShapeNew(cpBody *body, cpFloat width, cpFloat height, cpFloat radius);
+/// Allocate and initialize an offset box shaped polygon shape.
+CP_EXPORT cpShape* cpBoxShapeNew2(cpBody *body, cpBB box, cpFloat radius);
+
+/// Get the number of verts in a polygon shape.
+CP_EXPORT int cpPolyShapeGetCount(const cpShape *shape);
+/// Get the @c ith vertex of a polygon shape.
+CP_EXPORT cpVect cpPolyShapeGetVert(const cpShape *shape, int index);
+/// Get the radius of a polygon shape.
+CP_EXPORT cpFloat cpPolyShapeGetRadius(const cpShape *shape);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpPolyline.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpPolyline.h
new file mode 100644 (file)
index 0000000..4e878f0
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+// Polylines are just arrays of vertexes.
+// They are looped if the first vertex is equal to the last.
+// cpPolyline structs are intended to be passed by value and destroyed when you are done with them.
+typedef struct cpPolyline {
+  int count, capacity;
+  cpVect verts[];
+} cpPolyline;
+
+/// Destroy and free a polyline instance.
+CP_EXPORT void cpPolylineFree(cpPolyline *line);
+
+/// Returns true if the first vertex is equal to the last.
+CP_EXPORT cpBool cpPolylineIsClosed(cpPolyline *line);
+
+/**
+       Returns a copy of a polyline simplified by using the Douglas-Peucker algorithm.
+       This works very well on smooth or gently curved shapes, but not well on straight edged or angular shapes.
+*/
+CP_EXPORT cpPolyline *cpPolylineSimplifyCurves(cpPolyline *line, cpFloat tol);
+
+/**
+       Returns a copy of a polyline simplified by discarding "flat" vertexes.
+       This works well on straigt edged or angular shapes, not as well on smooth shapes.
+*/
+CP_EXPORT cpPolyline *cpPolylineSimplifyVertexes(cpPolyline *line, cpFloat tol);
+
+/// Get the convex hull of a polyline as a looped polyline.
+CP_EXPORT cpPolyline *cpPolylineToConvexHull(cpPolyline *line, cpFloat tol);
+
+
+/// Polyline sets are collections of polylines, generally built by cpMarchSoft() or cpMarchHard().
+typedef struct cpPolylineSet {
+  int count, capacity;
+  cpPolyline **lines;
+} cpPolylineSet;
+
+/// Allocate a new polyline set.
+CP_EXPORT cpPolylineSet *cpPolylineSetAlloc(void);
+
+/// Initialize a new polyline set.
+CP_EXPORT cpPolylineSet *cpPolylineSetInit(cpPolylineSet *set);
+
+/// Allocate and initialize a polyline set.
+CP_EXPORT cpPolylineSet *cpPolylineSetNew(void);
+
+/// Destroy a polyline set.
+CP_EXPORT void cpPolylineSetDestroy(cpPolylineSet *set, cpBool freePolylines);
+
+/// Destroy and free a polyline set.
+CP_EXPORT void cpPolylineSetFree(cpPolylineSet *set, cpBool freePolylines);
+
+/**
+       Add a line segment to a polyline set.
+       A segment will either start a new polyline, join two others, or add to or loop an existing polyline.
+       This is mostly intended to be used as a callback directly from cpMarchSoft() or cpMarchHard().
+*/
+CP_EXPORT void cpPolylineSetCollectSegment(cpVect v0, cpVect v1, cpPolylineSet *lines);
+
+/**
+       Get an approximate convex decomposition from a polyline.
+       Returns a cpPolylineSet of convex hulls that match the original shape to within 'tol'.
+       NOTE: If the input is a self intersecting polygon, the output might end up overly simplified.
+*/
+
+CP_EXPORT cpPolylineSet *cpPolylineConvexDecomposition(cpPolyline *line, cpFloat tol);
+
+#define cpPolylineConvexDecomposition_BETA cpPolylineConvexDecomposition
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpRatchetJoint.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpRatchetJoint.h
new file mode 100644 (file)
index 0000000..3ed4c91
--- /dev/null
@@ -0,0 +1,50 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpRatchetJoint cpRatchetJoint
+/// @{
+
+/// Check if a constraint is a damped rotary springs.
+CP_EXPORT cpBool cpConstraintIsRatchetJoint(const cpConstraint *constraint);
+
+/// Allocate a ratchet joint.
+CP_EXPORT cpRatchetJoint* cpRatchetJointAlloc(void);
+/// Initialize a ratched joint.
+CP_EXPORT cpRatchetJoint* cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);
+/// Allocate and initialize a ratchet joint.
+CP_EXPORT cpConstraint* cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);
+
+/// Get the angle of the current ratchet tooth.
+CP_EXPORT cpFloat cpRatchetJointGetAngle(const cpConstraint *constraint);
+/// Set the angle of the current ratchet tooth.
+CP_EXPORT void cpRatchetJointSetAngle(cpConstraint *constraint, cpFloat angle);
+
+/// Get the phase offset of the ratchet.
+CP_EXPORT cpFloat cpRatchetJointGetPhase(const cpConstraint *constraint);
+/// Get the phase offset of the ratchet.
+CP_EXPORT void cpRatchetJointSetPhase(cpConstraint *constraint, cpFloat phase);
+
+/// Get the angular distance of each ratchet.
+CP_EXPORT cpFloat cpRatchetJointGetRatchet(const cpConstraint *constraint);
+/// Set the angular distance of each ratchet.
+CP_EXPORT void cpRatchetJointSetRatchet(cpConstraint *constraint, cpFloat ratchet);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpRobust.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpRobust.h
new file mode 100644 (file)
index 0000000..e4b2c42
--- /dev/null
@@ -0,0 +1,11 @@
+#include "chipmunk/cpVect.h"
+
+// This is a private header for functions (currently just one) that need strict floating point results.
+// It was easier to put this in it's own file than to fiddle with 4 different compiler specific pragmas or attributes.
+// "Fast math" should be disabled here.
+
+// Check if c is to the left of segment (a, b).
+cpBool cpCheckPointGreater(const cpVect a, const cpVect b, const cpVect c);
+
+// Check if p is behind one of v0 or v1 on axis n.
+cpBool cpCheckAxis(cpVect v0, cpVect v1, cpVect p, cpVect n);
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpRotaryLimitJoint.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpRotaryLimitJoint.h
new file mode 100644 (file)
index 0000000..fac7ad8
--- /dev/null
@@ -0,0 +1,45 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpRotaryLimitJoint cpRotaryLimitJoint
+/// @{
+
+/// Check if a constraint is a damped rotary springs.
+CP_EXPORT cpBool cpConstraintIsRotaryLimitJoint(const cpConstraint *constraint);
+
+/// Allocate a damped rotary limit joint.
+CP_EXPORT cpRotaryLimitJoint* cpRotaryLimitJointAlloc(void);
+/// Initialize a damped rotary limit joint.
+CP_EXPORT cpRotaryLimitJoint* cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max);
+/// Allocate and initialize a damped rotary limit joint.
+CP_EXPORT cpConstraint* cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max);
+
+/// Get the minimum distance the joint will maintain between the two anchors.
+CP_EXPORT cpFloat cpRotaryLimitJointGetMin(const cpConstraint *constraint);
+/// Set the minimum distance the joint will maintain between the two anchors.
+CP_EXPORT void cpRotaryLimitJointSetMin(cpConstraint *constraint, cpFloat min);
+
+/// Get the maximum distance the joint will maintain between the two anchors.
+CP_EXPORT cpFloat cpRotaryLimitJointGetMax(const cpConstraint *constraint);
+/// Set the maximum distance the joint will maintain between the two anchors.
+CP_EXPORT void cpRotaryLimitJointSetMax(cpConstraint *constraint, cpFloat max);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpShape.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpShape.h
new file mode 100644 (file)
index 0000000..c78ed05
--- /dev/null
@@ -0,0 +1,199 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpShape cpShape
+/// The cpShape struct defines the shape of a rigid body.
+/// @{
+
+/// Point query info struct.
+typedef struct cpPointQueryInfo {
+       /// The nearest shape, NULL if no shape was within range.
+       const cpShape *shape;
+       /// The closest point on the shape's surface. (in world space coordinates)
+       cpVect point;
+       /// The distance to the point. The distance is negative if the point is inside the shape.
+       cpFloat distance;
+       /// The gradient of the signed distance function.
+       /// The value should be similar to info.p/info.d, but accurate even for very small values of info.d.
+       cpVect gradient;
+} cpPointQueryInfo;
+
+/// Segment query info struct.
+typedef struct cpSegmentQueryInfo {
+       /// The shape that was hit, or NULL if no collision occured.
+       const cpShape *shape;
+       /// The point of impact.
+       cpVect point;
+       /// The normal of the surface hit.
+       cpVect normal;
+       /// The normalized distance along the query segment in the range [0, 1].
+       cpFloat alpha;
+} cpSegmentQueryInfo;
+
+/// Fast collision filtering type that is used to determine if two objects collide before calling collision or query callbacks.
+typedef struct cpShapeFilter {
+       /// Two objects with the same non-zero group value do not collide.
+       /// This is generally used to group objects in a composite object together to disable self collisions.
+       cpGroup group;
+       /// A bitmask of user definable categories that this object belongs to.
+       /// The category/mask combinations of both objects in a collision must agree for a collision to occur.
+       cpBitmask categories;
+       /// A bitmask of user definable category types that this object object collides with.
+       /// The category/mask combinations of both objects in a collision must agree for a collision to occur.
+       cpBitmask mask;
+} cpShapeFilter;
+
+/// Collision filter value for a shape that will collide with anything except CP_SHAPE_FILTER_NONE.
+static const cpShapeFilter CP_SHAPE_FILTER_ALL = {CP_NO_GROUP, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES};
+/// Collision filter value for a shape that does not collide with anything.
+static const cpShapeFilter CP_SHAPE_FILTER_NONE = {CP_NO_GROUP, ~CP_ALL_CATEGORIES, ~CP_ALL_CATEGORIES};
+
+/// Create a new collision filter.
+static inline cpShapeFilter
+cpShapeFilterNew(cpGroup group, cpBitmask categories, cpBitmask mask)
+{
+       cpShapeFilter filter = {group, categories, mask};
+       return filter;
+}
+
+/// Destroy a shape.
+CP_EXPORT void cpShapeDestroy(cpShape *shape);
+/// Destroy and Free a shape.
+CP_EXPORT void cpShapeFree(cpShape *shape);
+
+/// Update, cache and return the bounding box of a shape based on the body it's attached to.
+CP_EXPORT cpBB cpShapeCacheBB(cpShape *shape);
+/// Update, cache and return the bounding box of a shape with an explicit transformation.
+CP_EXPORT cpBB cpShapeUpdate(cpShape *shape, cpTransform transform);
+
+/// Perform a nearest point query. It finds the closest point on the surface of shape to a specific point.
+/// The value returned is the distance between the points. A negative distance means the point is inside the shape.
+CP_EXPORT cpFloat cpShapePointQuery(const cpShape *shape, cpVect p, cpPointQueryInfo *out);
+
+/// Perform a segment query against a shape. @c info must be a pointer to a valid cpSegmentQueryInfo structure.
+CP_EXPORT cpBool cpShapeSegmentQuery(const cpShape *shape, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info);
+
+/// Return contact information about two shapes.
+CP_EXPORT cpContactPointSet cpShapesCollide(const cpShape *a, const cpShape *b);
+
+/// The cpSpace this body is added to.
+CP_EXPORT cpSpace* cpShapeGetSpace(const cpShape *shape);
+
+/// The cpBody this shape is connected to.
+CP_EXPORT cpBody* cpShapeGetBody(const cpShape *shape);
+/// Set the cpBody this shape is connected to.
+/// Can only be used if the shape is not currently added to a space.
+CP_EXPORT void cpShapeSetBody(cpShape *shape, cpBody *body);
+
+/// Get the mass of the shape if you are having Chipmunk calculate mass properties for you.
+CP_EXPORT cpFloat cpShapeGetMass(cpShape *shape);
+/// Set the mass of this shape to have Chipmunk calculate mass properties for you.
+CP_EXPORT void cpShapeSetMass(cpShape *shape, cpFloat mass);
+
+/// Get the density of the shape if you are having Chipmunk calculate mass properties for you.
+CP_EXPORT cpFloat cpShapeGetDensity(cpShape *shape);
+/// Set the density  of this shape to have Chipmunk calculate mass properties for you.
+CP_EXPORT void cpShapeSetDensity(cpShape *shape, cpFloat density);
+
+/// Get the calculated moment of inertia for this shape.
+CP_EXPORT cpFloat cpShapeGetMoment(cpShape *shape);
+/// Get the calculated area of this shape.
+CP_EXPORT cpFloat cpShapeGetArea(cpShape *shape);
+/// Get the centroid of this shape.
+CP_EXPORT cpVect cpShapeGetCenterOfGravity(cpShape *shape);
+
+/// Get the bounding box that contains the shape given it's current position and angle.
+CP_EXPORT cpBB cpShapeGetBB(const cpShape *shape);
+
+/// Get if the shape is set to be a sensor or not.
+CP_EXPORT cpBool cpShapeGetSensor(const cpShape *shape);
+/// Set if the shape is a sensor or not.
+CP_EXPORT void cpShapeSetSensor(cpShape *shape, cpBool sensor);
+
+/// Get the elasticity of this shape.
+CP_EXPORT cpFloat cpShapeGetElasticity(const cpShape *shape);
+/// Set the elasticity of this shape.
+CP_EXPORT void cpShapeSetElasticity(cpShape *shape, cpFloat elasticity);
+
+/// Get the friction of this shape.
+CP_EXPORT cpFloat cpShapeGetFriction(const cpShape *shape);
+/// Set the friction of this shape.
+CP_EXPORT void cpShapeSetFriction(cpShape *shape, cpFloat friction);
+
+/// Get the surface velocity of this shape.
+CP_EXPORT cpVect cpShapeGetSurfaceVelocity(const cpShape *shape);
+/// Set the surface velocity of this shape.
+CP_EXPORT void cpShapeSetSurfaceVelocity(cpShape *shape, cpVect surfaceVelocity);
+
+/// Get the user definable data pointer of this shape.
+CP_EXPORT cpDataPointer cpShapeGetUserData(const cpShape *shape);
+/// Set the user definable data pointer of this shape.
+CP_EXPORT void cpShapeSetUserData(cpShape *shape, cpDataPointer userData);
+
+/// Set the collision type of this shape.
+CP_EXPORT cpCollisionType cpShapeGetCollisionType(const cpShape *shape);
+/// Get the collision type of this shape.
+CP_EXPORT void cpShapeSetCollisionType(cpShape *shape, cpCollisionType collisionType);
+
+/// Get the collision filtering parameters of this shape.
+CP_EXPORT cpShapeFilter cpShapeGetFilter(const cpShape *shape);
+/// Set the collision filtering parameters of this shape.
+CP_EXPORT void cpShapeSetFilter(cpShape *shape, cpShapeFilter filter);
+
+
+/// @}
+/// @defgroup cpCircleShape cpCircleShape
+
+/// Allocate a circle shape.
+CP_EXPORT cpCircleShape* cpCircleShapeAlloc(void);
+/// Initialize a circle shape.
+CP_EXPORT cpCircleShape* cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset);
+/// Allocate and initialize a circle shape.
+CP_EXPORT cpShape* cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset);
+
+/// Get the offset of a circle shape.
+CP_EXPORT cpVect cpCircleShapeGetOffset(const cpShape *shape);
+/// Get the radius of a circle shape.
+CP_EXPORT cpFloat cpCircleShapeGetRadius(const cpShape *shape);
+
+/// @}
+/// @defgroup cpSegmentShape cpSegmentShape
+
+/// Allocate a segment shape.
+CP_EXPORT cpSegmentShape* cpSegmentShapeAlloc(void);
+/// Initialize a segment shape.
+CP_EXPORT cpSegmentShape* cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat radius);
+/// Allocate and initialize a segment shape.
+CP_EXPORT cpShape* cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat radius);
+
+/// Let Chipmunk know about the geometry of adjacent segments to avoid colliding with endcaps.
+CP_EXPORT void cpSegmentShapeSetNeighbors(cpShape *shape, cpVect prev, cpVect next);
+
+/// Get the first endpoint of a segment shape.
+CP_EXPORT cpVect cpSegmentShapeGetA(const cpShape *shape);
+/// Get the second endpoint of a segment shape.
+CP_EXPORT cpVect cpSegmentShapeGetB(const cpShape *shape);
+/// Get the normal of a segment shape.
+CP_EXPORT cpVect cpSegmentShapeGetNormal(const cpShape *shape);
+/// Get the first endpoint of a segment shape.
+CP_EXPORT cpFloat cpSegmentShapeGetRadius(const cpShape *shape);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpSimpleMotor.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpSimpleMotor.h
new file mode 100644 (file)
index 0000000..811b011
--- /dev/null
@@ -0,0 +1,43 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpSimpleMotor cpSimpleMotor
+/// @{
+
+/// Opaque struct type for damped rotary springs.
+typedef struct cpSimpleMotor cpSimpleMotor;
+
+/// Check if a constraint is a damped rotary springs.
+CP_EXPORT cpBool cpConstraintIsSimpleMotor(const cpConstraint *constraint);
+
+/// Allocate a simple motor.
+CP_EXPORT cpSimpleMotor* cpSimpleMotorAlloc(void);
+/// initialize a simple motor.
+CP_EXPORT cpSimpleMotor* cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate);
+/// Allocate and initialize a simple motor.
+CP_EXPORT cpConstraint* cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate);
+
+/// Get the rate of the motor.
+CP_EXPORT cpFloat cpSimpleMotorGetRate(const cpConstraint *constraint);
+/// Set the rate of the motor.
+CP_EXPORT void cpSimpleMotorSetRate(cpConstraint *constraint, cpFloat rate);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpSlideJoint.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpSlideJoint.h
new file mode 100644 (file)
index 0000000..c41f9a4
--- /dev/null
@@ -0,0 +1,55 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpSlideJoint cpSlideJoint
+/// @{
+
+/// Check if a constraint is a slide joint.
+CP_EXPORT cpBool cpConstraintIsSlideJoint(const cpConstraint *constraint);
+
+/// Allocate a slide joint.
+CP_EXPORT cpSlideJoint* cpSlideJointAlloc(void);
+/// Initialize a slide joint.
+CP_EXPORT cpSlideJoint* cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max);
+/// Allocate and initialize a slide joint.
+CP_EXPORT cpConstraint* cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max);
+
+/// Get the location of the first anchor relative to the first body.
+CP_EXPORT cpVect cpSlideJointGetAnchorA(const cpConstraint *constraint);
+/// Set the location of the first anchor relative to the first body.
+CP_EXPORT void cpSlideJointSetAnchorA(cpConstraint *constraint, cpVect anchorA);
+
+/// Get the location of the second anchor relative to the second body.
+CP_EXPORT cpVect cpSlideJointGetAnchorB(const cpConstraint *constraint);
+/// Set the location of the second anchor relative to the second body.
+CP_EXPORT void cpSlideJointSetAnchorB(cpConstraint *constraint, cpVect anchorB);
+
+/// Get the minimum distance the joint will maintain between the two anchors.
+CP_EXPORT cpFloat cpSlideJointGetMin(const cpConstraint *constraint);
+/// Set the minimum distance the joint will maintain between the two anchors.
+CP_EXPORT void cpSlideJointSetMin(cpConstraint *constraint, cpFloat min);
+
+/// Get the maximum distance the joint will maintain between the two anchors.
+CP_EXPORT cpFloat cpSlideJointGetMax(const cpConstraint *constraint);
+/// Set the maximum distance the joint will maintain between the two anchors.
+CP_EXPORT void cpSlideJointSetMax(cpConstraint *constraint, cpFloat max);
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpSpace.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpSpace.h
new file mode 100644 (file)
index 0000000..7bbabb8
--- /dev/null
@@ -0,0 +1,319 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/// @defgroup cpSpace cpSpace
+/// @{
+
+//MARK: Definitions
+
+/// Collision begin event function callback type.
+/// Returning false from a begin callback causes the collision to be ignored until
+/// the the separate callback is called when the objects stop colliding.
+typedef cpBool (*cpCollisionBeginFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData);
+/// Collision pre-solve event function callback type.
+/// Returning false from a pre-step callback causes the collision to be ignored until the next step.
+typedef cpBool (*cpCollisionPreSolveFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData);
+/// Collision post-solve event function callback type.
+typedef void (*cpCollisionPostSolveFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData);
+/// Collision separate event function callback type.
+typedef void (*cpCollisionSeparateFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData);
+
+/// Struct that holds function callback pointers to configure custom collision handling.
+/// Collision handlers have a pair of types; when a collision occurs between two shapes that have these types, the collision handler functions are triggered.
+struct cpCollisionHandler {
+       /// Collision type identifier of the first shape that this handler recognizes.
+       /// In the collision handler callback, the shape with this type will be the first argument. Read only.
+       const cpCollisionType typeA;
+       /// Collision type identifier of the second shape that this handler recognizes.
+       /// In the collision handler callback, the shape with this type will be the second argument. Read only.
+       const cpCollisionType typeB;
+       /// This function is called when two shapes with types that match this collision handler begin colliding.
+       cpCollisionBeginFunc beginFunc;
+       /// This function is called each step when two shapes with types that match this collision handler are colliding.
+       /// It's called before the collision solver runs so that you can affect a collision's outcome.
+       cpCollisionPreSolveFunc preSolveFunc;
+       /// This function is called each step when two shapes with types that match this collision handler are colliding.
+       /// It's called after the collision solver runs so that you can read back information about the collision to trigger events in your game.
+       cpCollisionPostSolveFunc postSolveFunc;
+       /// This function is called when two shapes with types that match this collision handler stop colliding.
+       cpCollisionSeparateFunc separateFunc;
+       /// This is a user definable context pointer that is passed to all of the collision handler functions.
+       cpDataPointer userData;
+};
+
+// TODO: Make timestep a parameter?
+
+
+//MARK: Memory and Initialization
+
+/// Allocate a cpSpace.
+CP_EXPORT cpSpace* cpSpaceAlloc(void);
+/// Initialize a cpSpace.
+CP_EXPORT cpSpace* cpSpaceInit(cpSpace *space);
+/// Allocate and initialize a cpSpace.
+CP_EXPORT cpSpace* cpSpaceNew(void);
+
+/// Destroy a cpSpace.
+CP_EXPORT void cpSpaceDestroy(cpSpace *space);
+/// Destroy and free a cpSpace.
+CP_EXPORT void cpSpaceFree(cpSpace *space);
+
+
+//MARK: Properties
+
+/// Number of iterations to use in the impulse solver to solve contacts and other constraints.
+CP_EXPORT int cpSpaceGetIterations(const cpSpace *space);
+CP_EXPORT void cpSpaceSetIterations(cpSpace *space, int iterations);
+
+/// Gravity to pass to rigid bodies when integrating velocity.
+CP_EXPORT cpVect cpSpaceGetGravity(const cpSpace *space);
+CP_EXPORT void cpSpaceSetGravity(cpSpace *space, cpVect gravity);
+
+/// Damping rate expressed as the fraction of velocity bodies retain each second.
+/// A value of 0.9 would mean that each body's velocity will drop 10% per second.
+/// The default value is 1.0, meaning no damping is applied.
+/// @note This damping value is different than those of cpDampedSpring and cpDampedRotarySpring.
+CP_EXPORT cpFloat cpSpaceGetDamping(const cpSpace *space);
+CP_EXPORT void cpSpaceSetDamping(cpSpace *space, cpFloat damping);
+
+/// Speed threshold for a body to be considered idle.
+/// The default value of 0 means to let the space guess a good threshold based on gravity.
+CP_EXPORT cpFloat cpSpaceGetIdleSpeedThreshold(const cpSpace *space);
+CP_EXPORT void cpSpaceSetIdleSpeedThreshold(cpSpace *space, cpFloat idleSpeedThreshold);
+
+/// Time a group of bodies must remain idle in order to fall asleep.
+/// Enabling sleeping also implicitly enables the the contact graph.
+/// The default value of INFINITY disables the sleeping algorithm.
+CP_EXPORT cpFloat cpSpaceGetSleepTimeThreshold(const cpSpace *space);
+CP_EXPORT void cpSpaceSetSleepTimeThreshold(cpSpace *space, cpFloat sleepTimeThreshold);
+
+/// Amount of encouraged penetration between colliding shapes.
+/// Used to reduce oscillating contacts and keep the collision cache warm.
+/// Defaults to 0.1. If you have poor simulation quality,
+/// increase this number as much as possible without allowing visible amounts of overlap.
+CP_EXPORT cpFloat cpSpaceGetCollisionSlop(const cpSpace *space);
+CP_EXPORT void cpSpaceSetCollisionSlop(cpSpace *space, cpFloat collisionSlop);
+
+/// Determines how fast overlapping shapes are pushed apart.
+/// Expressed as a fraction of the error remaining after each second.
+/// Defaults to pow(1.0 - 0.1, 60.0) meaning that Chipmunk fixes 10% of overlap each frame at 60Hz.
+CP_EXPORT cpFloat cpSpaceGetCollisionBias(const cpSpace *space);
+CP_EXPORT void cpSpaceSetCollisionBias(cpSpace *space, cpFloat collisionBias);
+
+/// Number of frames that contact information should persist.
+/// Defaults to 3. There is probably never a reason to change this value.
+CP_EXPORT cpTimestamp cpSpaceGetCollisionPersistence(const cpSpace *space);
+CP_EXPORT void cpSpaceSetCollisionPersistence(cpSpace *space, cpTimestamp collisionPersistence);
+
+/// User definable data pointer.
+/// Generally this points to your game's controller or game state
+/// class so you can access it when given a cpSpace reference in a callback.
+CP_EXPORT cpDataPointer cpSpaceGetUserData(const cpSpace *space);
+CP_EXPORT void cpSpaceSetUserData(cpSpace *space, cpDataPointer userData);
+
+/// The Space provided static body for a given cpSpace.
+/// This is merely provided for convenience and you are not required to use it.
+CP_EXPORT cpBody* cpSpaceGetStaticBody(const cpSpace *space);
+
+/// Returns the current (or most recent) time step used with the given space.
+/// Useful from callbacks if your time step is not a compile-time global.
+CP_EXPORT cpFloat cpSpaceGetCurrentTimeStep(const cpSpace *space);
+
+/// returns true from inside a callback when objects cannot be added/removed.
+CP_EXPORT cpBool cpSpaceIsLocked(cpSpace *space);
+
+
+//MARK: Collision Handlers
+
+/// Create or return the existing collision handler that is called for all collisions that are not handled by a more specific collision handler.
+CP_EXPORT cpCollisionHandler *cpSpaceAddDefaultCollisionHandler(cpSpace *space);
+/// Create or return the existing collision handler for the specified pair of collision types.
+/// If wildcard handlers are used with either of the collision types, it's the responibility of the custom handler to invoke the wildcard handlers.
+CP_EXPORT cpCollisionHandler *cpSpaceAddCollisionHandler(cpSpace *space, cpCollisionType a, cpCollisionType b);
+/// Create or return the existing wildcard collision handler for the specified type.
+CP_EXPORT cpCollisionHandler *cpSpaceAddWildcardHandler(cpSpace *space, cpCollisionType type);
+
+
+//MARK: Add/Remove objects
+
+/// Add a collision shape to the simulation.
+/// If the shape is attached to a static body, it will be added as a static shape.
+CP_EXPORT cpShape* cpSpaceAddShape(cpSpace *space, cpShape *shape);
+/// Add a rigid body to the simulation.
+CP_EXPORT cpBody* cpSpaceAddBody(cpSpace *space, cpBody *body);
+/// Add a constraint to the simulation.
+CP_EXPORT cpConstraint* cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint);
+
+/// Remove a collision shape from the simulation.
+CP_EXPORT void cpSpaceRemoveShape(cpSpace *space, cpShape *shape);
+/// Remove a rigid body from the simulation.
+CP_EXPORT void cpSpaceRemoveBody(cpSpace *space, cpBody *body);
+/// Remove a constraint from the simulation.
+CP_EXPORT void cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint);
+
+/// Test if a collision shape has been added to the space.
+CP_EXPORT cpBool cpSpaceContainsShape(cpSpace *space, cpShape *shape);
+/// Test if a rigid body has been added to the space.
+CP_EXPORT cpBool cpSpaceContainsBody(cpSpace *space, cpBody *body);
+/// Test if a constraint has been added to the space.
+CP_EXPORT cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint);
+
+//MARK: Post-Step Callbacks
+
+/// Post Step callback function type.
+typedef void (*cpPostStepFunc)(cpSpace *space, void *key, void *data);
+/// Schedule a post-step callback to be called when cpSpaceStep() finishes.
+/// You can only register one callback per unique value for @c key.
+/// Returns true only if @c key has never been scheduled before.
+/// It's possible to pass @c NULL for @c func if you only want to mark @c key as being used.
+CP_EXPORT cpBool cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data);
+
+
+//MARK: Queries
+
+// TODO: Queries and iterators should take a cpSpace parametery.
+// TODO: They should also be abortable.
+
+/// Nearest point query callback function type.
+typedef void (*cpSpacePointQueryFunc)(cpShape *shape, cpVect point, cpFloat distance, cpVect gradient, void *data);
+/// Query the space at a point and call @c func for each shape found.
+CP_EXPORT void cpSpacePointQuery(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryFunc func, void *data);
+/// Query the space at a point and return the nearest shape found. Returns NULL if no shapes were found.
+CP_EXPORT cpShape *cpSpacePointQueryNearest(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpPointQueryInfo *out);
+
+/// Segment query callback function type.
+typedef void (*cpSpaceSegmentQueryFunc)(cpShape *shape, cpVect point, cpVect normal, cpFloat alpha, void *data);
+/// Perform a directed line segment query (like a raycast) against the space calling @c func for each shape intersected.
+CP_EXPORT void cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryFunc func, void *data);
+/// Perform a directed line segment query (like a raycast) against the space and return the first shape hit. Returns NULL if no shapes were hit.
+CP_EXPORT cpShape *cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSegmentQueryInfo *out);
+
+/// Rectangle Query callback function type.
+typedef void (*cpSpaceBBQueryFunc)(cpShape *shape, void *data);
+/// Perform a fast rectangle query on the space calling @c func for each shape found.
+/// Only the shape's bounding boxes are checked for overlap, not their full shape.
+CP_EXPORT void cpSpaceBBQuery(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryFunc func, void *data);
+
+/// Shape query callback function type.
+typedef void (*cpSpaceShapeQueryFunc)(cpShape *shape, cpContactPointSet *points, void *data);
+/// Query a space for any shapes overlapping the given shape and call @c func for each shape found.
+CP_EXPORT cpBool cpSpaceShapeQuery(cpSpace *space, cpShape *shape, cpSpaceShapeQueryFunc func, void *data);
+
+
+//MARK: Iteration
+
+/// Space/body iterator callback function type.
+typedef void (*cpSpaceBodyIteratorFunc)(cpBody *body, void *data);
+/// Call @c func for each body in the space.
+CP_EXPORT void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIteratorFunc func, void *data);
+
+/// Space/body iterator callback function type.
+typedef void (*cpSpaceShapeIteratorFunc)(cpShape *shape, void *data);
+/// Call @c func for each shape in the space.
+CP_EXPORT void cpSpaceEachShape(cpSpace *space, cpSpaceShapeIteratorFunc func, void *data);
+
+/// Space/constraint iterator callback function type.
+typedef void (*cpSpaceConstraintIteratorFunc)(cpConstraint *constraint, void *data);
+/// Call @c func for each shape in the space.
+CP_EXPORT void cpSpaceEachConstraint(cpSpace *space, cpSpaceConstraintIteratorFunc func, void *data);
+
+
+//MARK: Indexing
+
+/// Update the collision detection info for the static shapes in the space.
+CP_EXPORT void cpSpaceReindexStatic(cpSpace *space);
+/// Update the collision detection data for a specific shape in the space.
+CP_EXPORT void cpSpaceReindexShape(cpSpace *space, cpShape *shape);
+/// Update the collision detection data for all shapes attached to a body.
+CP_EXPORT void cpSpaceReindexShapesForBody(cpSpace *space, cpBody *body);
+
+/// Switch the space to use a spatial has as it's spatial index.
+CP_EXPORT void cpSpaceUseSpatialHash(cpSpace *space, cpFloat dim, int count);
+
+
+//MARK: Time Stepping
+
+/// Step the space forward in time by @c dt.
+CP_EXPORT void cpSpaceStep(cpSpace *space, cpFloat dt);
+
+
+//MARK: Debug API
+
+#ifndef CP_SPACE_DISABLE_DEBUG_API
+
+/// Color type to use with the space debug drawing API.
+typedef struct cpSpaceDebugColor {
+       float r, g, b, a;
+} cpSpaceDebugColor;
+
+/// Callback type for a function that draws a filled, stroked circle.
+typedef void (*cpSpaceDebugDrawCircleImpl)(cpVect pos, cpFloat angle, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer data);
+/// Callback type for a function that draws a line segment.
+typedef void (*cpSpaceDebugDrawSegmentImpl)(cpVect a, cpVect b, cpSpaceDebugColor color, cpDataPointer data);
+/// Callback type for a function that draws a thick line segment.
+typedef void (*cpSpaceDebugDrawFatSegmentImpl)(cpVect a, cpVect b, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer data);
+/// Callback type for a function that draws a convex polygon.
+typedef void (*cpSpaceDebugDrawPolygonImpl)(int count, const cpVect *verts, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer data);
+/// Callback type for a function that draws a dot.
+typedef void (*cpSpaceDebugDrawDotImpl)(cpFloat size, cpVect pos, cpSpaceDebugColor color, cpDataPointer data);
+/// Callback type for a function that returns a color for a given shape. This gives you an opportunity to color shapes based on how they are used in your engine.
+typedef cpSpaceDebugColor (*cpSpaceDebugDrawColorForShapeImpl)(cpShape *shape, cpDataPointer data);
+
+typedef enum cpSpaceDebugDrawFlags {
+       CP_SPACE_DEBUG_DRAW_SHAPES = 1<<0,
+       CP_SPACE_DEBUG_DRAW_CONSTRAINTS = 1<<1,
+       CP_SPACE_DEBUG_DRAW_COLLISION_POINTS = 1<<2,
+} cpSpaceDebugDrawFlags;
+
+/// Struct used with cpSpaceDebugDraw() containing drawing callbacks and other drawing settings.
+typedef struct cpSpaceDebugDrawOptions {
+       /// Function that will be invoked to draw circles.
+       cpSpaceDebugDrawCircleImpl drawCircle;
+       /// Function that will be invoked to draw line segments.
+       cpSpaceDebugDrawSegmentImpl drawSegment;
+       /// Function that will be invoked to draw thick line segments.
+       cpSpaceDebugDrawFatSegmentImpl drawFatSegment;
+       /// Function that will be invoked to draw convex polygons.
+       cpSpaceDebugDrawPolygonImpl drawPolygon;
+       /// Function that will be invoked to draw dots.
+       cpSpaceDebugDrawDotImpl drawDot;
+       
+       /// Flags that request which things to draw (collision shapes, constraints, contact points).
+       cpSpaceDebugDrawFlags flags;
+       /// Outline color passed to the drawing function.
+       cpSpaceDebugColor shapeOutlineColor;
+       /// Function that decides what fill color to draw shapes using.
+       cpSpaceDebugDrawColorForShapeImpl colorForShape;
+       /// Color passed to drawing functions for constraints.
+       cpSpaceDebugColor constraintColor;
+       /// Color passed to drawing functions for collision points.
+       cpSpaceDebugColor collisionPointColor;
+       
+       /// User defined context pointer passed to all of the callback functions as the 'data' argument.
+       cpDataPointer data;
+} cpSpaceDebugDrawOptions;
+
+/// Debug draw the current state of the space using the supplied drawing options.
+CP_EXPORT void cpSpaceDebugDraw(cpSpace *space, cpSpaceDebugDrawOptions *options);
+
+#endif
+
+/// @}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpSpatialIndex.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpSpatialIndex.h
new file mode 100644 (file)
index 0000000..1f7c68c
--- /dev/null
@@ -0,0 +1,227 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+       @defgroup cpSpatialIndex cpSpatialIndex
+       
+       Spatial indexes are data structures that are used to accelerate collision detection
+       and spatial queries. Chipmunk provides a number of spatial index algorithms to pick from
+       and they are programmed in a generic way so that you can use them for holding more than
+       just cpShape structs.
+       
+       It works by using @c void pointers to the objects you add and using a callback to ask your code
+       for bounding boxes when it needs them. Several types of queries can be performed an index as well
+       as reindexing and full collision information. All communication to the spatial indexes is performed
+       through callback functions.
+       
+       Spatial indexes should be treated as opaque structs.
+       This meanns you shouldn't be reading any of the struct fields.
+       @{
+*/
+
+//MARK: Spatial Index
+
+/// Spatial index bounding box callback function type.
+/// The spatial index calls this function and passes you a pointer to an object you added
+/// when it needs to get the bounding box associated with that object.
+typedef cpBB (*cpSpatialIndexBBFunc)(void *obj);
+/// Spatial index/object iterator callback function type.
+typedef void (*cpSpatialIndexIteratorFunc)(void *obj, void *data);
+/// Spatial query callback function type.
+typedef cpCollisionID (*cpSpatialIndexQueryFunc)(void *obj1, void *obj2, cpCollisionID id, void *data);
+/// Spatial segment query callback function type.
+typedef cpFloat (*cpSpatialIndexSegmentQueryFunc)(void *obj1, void *obj2, void *data);
+
+
+typedef struct cpSpatialIndexClass cpSpatialIndexClass;
+typedef struct cpSpatialIndex cpSpatialIndex;
+
+/// @private
+struct cpSpatialIndex {
+       cpSpatialIndexClass *klass;
+       
+       cpSpatialIndexBBFunc bbfunc;
+       
+       cpSpatialIndex *staticIndex, *dynamicIndex;
+};
+
+
+//MARK: Spatial Hash
+
+typedef struct cpSpaceHash cpSpaceHash;
+
+/// Allocate a spatial hash.
+CP_EXPORT cpSpaceHash* cpSpaceHashAlloc(void);
+/// Initialize a spatial hash. 
+CP_EXPORT cpSpatialIndex* cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+/// Allocate and initialize a spatial hash.
+CP_EXPORT cpSpatialIndex* cpSpaceHashNew(cpFloat celldim, int cells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+
+/// Change the cell dimensions and table size of the spatial hash to tune it.
+/// The cell dimensions should roughly match the average size of your objects
+/// and the table size should be ~10 larger than the number of objects inserted.
+/// Some trial and error is required to find the optimum numbers for efficiency.
+CP_EXPORT void cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells);
+
+//MARK: AABB Tree
+
+typedef struct cpBBTree cpBBTree;
+
+/// Allocate a bounding box tree.
+CP_EXPORT cpBBTree* cpBBTreeAlloc(void);
+/// Initialize a bounding box tree.
+CP_EXPORT cpSpatialIndex* cpBBTreeInit(cpBBTree *tree, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+/// Allocate and initialize a bounding box tree.
+CP_EXPORT cpSpatialIndex* cpBBTreeNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+
+/// Perform a static top down optimization of the tree.
+CP_EXPORT void cpBBTreeOptimize(cpSpatialIndex *index);
+
+/// Bounding box tree velocity callback function.
+/// This function should return an estimate for the object's velocity.
+typedef cpVect (*cpBBTreeVelocityFunc)(void *obj);
+/// Set the velocity function for the bounding box tree to enable temporal coherence.
+CP_EXPORT void cpBBTreeSetVelocityFunc(cpSpatialIndex *index, cpBBTreeVelocityFunc func);
+
+//MARK: Single Axis Sweep
+
+typedef struct cpSweep1D cpSweep1D;
+
+/// Allocate a 1D sort and sweep broadphase.
+CP_EXPORT cpSweep1D* cpSweep1DAlloc(void);
+/// Initialize a 1D sort and sweep broadphase.
+CP_EXPORT cpSpatialIndex* cpSweep1DInit(cpSweep1D *sweep, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+/// Allocate and initialize a 1D sort and sweep broadphase.
+CP_EXPORT cpSpatialIndex* cpSweep1DNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex);
+
+//MARK: Spatial Index Implementation
+
+typedef void (*cpSpatialIndexDestroyImpl)(cpSpatialIndex *index);
+
+typedef int (*cpSpatialIndexCountImpl)(cpSpatialIndex *index);
+typedef void (*cpSpatialIndexEachImpl)(cpSpatialIndex *index, cpSpatialIndexIteratorFunc func, void *data);
+
+typedef cpBool (*cpSpatialIndexContainsImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
+typedef void (*cpSpatialIndexInsertImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
+typedef void (*cpSpatialIndexRemoveImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
+
+typedef void (*cpSpatialIndexReindexImpl)(cpSpatialIndex *index);
+typedef void (*cpSpatialIndexReindexObjectImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid);
+typedef void (*cpSpatialIndexReindexQueryImpl)(cpSpatialIndex *index, cpSpatialIndexQueryFunc func, void *data);
+
+typedef void (*cpSpatialIndexQueryImpl)(cpSpatialIndex *index, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data);
+typedef void (*cpSpatialIndexSegmentQueryImpl)(cpSpatialIndex *index, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data);
+
+struct cpSpatialIndexClass {
+       cpSpatialIndexDestroyImpl destroy;
+       
+       cpSpatialIndexCountImpl count;
+       cpSpatialIndexEachImpl each;
+       
+       cpSpatialIndexContainsImpl contains;
+       cpSpatialIndexInsertImpl insert;
+       cpSpatialIndexRemoveImpl remove;
+       
+       cpSpatialIndexReindexImpl reindex;
+       cpSpatialIndexReindexObjectImpl reindexObject;
+       cpSpatialIndexReindexQueryImpl reindexQuery;
+       
+       cpSpatialIndexQueryImpl query;
+       cpSpatialIndexSegmentQueryImpl segmentQuery;
+};
+
+/// Destroy and free a spatial index.
+CP_EXPORT void cpSpatialIndexFree(cpSpatialIndex *index);
+/// Collide the objects in @c dynamicIndex against the objects in @c staticIndex using the query callback function.
+CP_EXPORT void cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data);
+
+/// Destroy a spatial index.
+static inline void cpSpatialIndexDestroy(cpSpatialIndex *index)
+{
+       if(index->klass) index->klass->destroy(index);
+}
+
+/// Get the number of objects in the spatial index.
+static inline int cpSpatialIndexCount(cpSpatialIndex *index)
+{
+       return index->klass->count(index);
+}
+
+/// Iterate the objects in the spatial index. @c func will be called once for each object.
+static inline void cpSpatialIndexEach(cpSpatialIndex *index, cpSpatialIndexIteratorFunc func, void *data)
+{
+       index->klass->each(index, func, data);
+}
+
+/// Returns true if the spatial index contains the given object.
+/// Most spatial indexes use hashed storage, so you must provide a hash value too.
+static inline cpBool cpSpatialIndexContains(cpSpatialIndex *index, void *obj, cpHashValue hashid)
+{
+       return index->klass->contains(index, obj, hashid);
+}
+
+/// Add an object to a spatial index.
+/// Most spatial indexes use hashed storage, so you must provide a hash value too.
+static inline void cpSpatialIndexInsert(cpSpatialIndex *index, void *obj, cpHashValue hashid)
+{
+       index->klass->insert(index, obj, hashid);
+}
+
+/// Remove an object from a spatial index.
+/// Most spatial indexes use hashed storage, so you must provide a hash value too.
+static inline void cpSpatialIndexRemove(cpSpatialIndex *index, void *obj, cpHashValue hashid)
+{
+       index->klass->remove(index, obj, hashid);
+}
+
+/// Perform a full reindex of a spatial index.
+static inline void cpSpatialIndexReindex(cpSpatialIndex *index)
+{
+       index->klass->reindex(index);
+}
+
+/// Reindex a single object in the spatial index.
+static inline void cpSpatialIndexReindexObject(cpSpatialIndex *index, void *obj, cpHashValue hashid)
+{
+       index->klass->reindexObject(index, obj, hashid);
+}
+
+/// Perform a rectangle query against the spatial index, calling @c func for each potential match.
+static inline void cpSpatialIndexQuery(cpSpatialIndex *index, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
+{
+       index->klass->query(index, obj, bb, func, data);
+}
+
+/// Perform a segment query against the spatial index, calling @c func for each potential match.
+static inline void cpSpatialIndexSegmentQuery(cpSpatialIndex *index, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+       index->klass->segmentQuery(index, obj, a, b, t_exit, func, data);
+}
+
+/// Simultaneously reindex and find all colliding objects.
+/// @c func will be called once for each potentially overlapping pair of objects found.
+/// If the spatial index was initialized with a static index, it will collide it's objects against that as well.
+static inline void cpSpatialIndexReindexQuery(cpSpatialIndex *index, cpSpatialIndexQueryFunc func, void *data)
+{
+       index->klass->reindexQuery(index, func, data);
+}
+
+///@}
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpTransform.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpTransform.h
new file mode 100644 (file)
index 0000000..4a6256b
--- /dev/null
@@ -0,0 +1,198 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_TRANSFORM_H
+#define CHIPMUNK_TRANSFORM_H
+
+#include "chipmunk_types.h"
+#include "cpVect.h"
+#include "cpBB.h"
+
+/// Identity transform matrix.
+static const cpTransform cpTransformIdentity = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
+
+/// Construct a new transform matrix.
+/// (a, b) is the x basis vector.
+/// (c, d) is the y basis vector.
+/// (tx, ty) is the translation.
+static inline cpTransform
+cpTransformNew(cpFloat a, cpFloat b, cpFloat c, cpFloat d, cpFloat tx, cpFloat ty)
+{
+       cpTransform t = {a, b, c, d, tx, ty};
+       return t;
+}
+
+/// Construct a new transform matrix in transposed order.
+static inline cpTransform
+cpTransformNewTranspose(cpFloat a, cpFloat c, cpFloat tx, cpFloat b, cpFloat d, cpFloat ty)
+{
+       cpTransform t = {a, b, c, d, tx, ty};
+       return t;
+}
+
+/// Get the inverse of a transform matrix.
+static inline cpTransform
+cpTransformInverse(cpTransform t)
+{
+  cpFloat inv_det = 1.0/(t.a*t.d - t.c*t.b);
+  return cpTransformNewTranspose(
+     t.d*inv_det, -t.c*inv_det, (t.c*t.ty - t.tx*t.d)*inv_det,
+    -t.b*inv_det,  t.a*inv_det, (t.tx*t.b - t.a*t.ty)*inv_det
+  );
+}
+
+/// Multiply two transformation matrices.
+static inline cpTransform
+cpTransformMult(cpTransform t1, cpTransform t2)
+{
+  return cpTransformNewTranspose(
+    t1.a*t2.a + t1.c*t2.b, t1.a*t2.c + t1.c*t2.d, t1.a*t2.tx + t1.c*t2.ty + t1.tx,
+    t1.b*t2.a + t1.d*t2.b, t1.b*t2.c + t1.d*t2.d, t1.b*t2.tx + t1.d*t2.ty + t1.ty
+  );
+}
+
+/// Transform an absolute point. (i.e. a vertex)
+static inline cpVect
+cpTransformPoint(cpTransform t, cpVect p)
+{
+  return cpv(t.a*p.x + t.c*p.y + t.tx, t.b*p.x + t.d*p.y + t.ty);
+}
+
+/// Transform a vector (i.e. a normal)
+static inline cpVect
+cpTransformVect(cpTransform t, cpVect v)
+{
+  return cpv(t.a*v.x + t.c*v.y, t.b*v.x + t.d*v.y);
+}
+
+/// Transform a cpBB.
+static inline cpBB
+cpTransformbBB(cpTransform t, cpBB bb)
+{
+       cpVect center = cpBBCenter(bb);
+       cpFloat hw = (bb.r - bb.l)*0.5;
+       cpFloat hh = (bb.t - bb.b)*0.5;
+       
+       cpFloat a = t.a*hw, b = t.c*hh, d = t.b*hw, e = t.d*hh;
+       cpFloat hw_max = cpfmax(cpfabs(a + b), cpfabs(a - b));
+       cpFloat hh_max = cpfmax(cpfabs(d + e), cpfabs(d - e));
+       return cpBBNewForExtents(cpTransformPoint(t, center), hw_max, hh_max);
+}
+
+/// Create a transation matrix.
+static inline cpTransform
+cpTransformTranslate(cpVect translate)
+{
+  return cpTransformNewTranspose(
+    1.0, 0.0, translate.x,
+    0.0, 1.0, translate.y
+  );
+}
+
+/// Create a scale matrix.
+static inline cpTransform
+cpTransformScale(cpFloat scaleX, cpFloat scaleY)
+{
+       return cpTransformNewTranspose(
+               scaleX,    0.0, 0.0,
+                  0.0, scaleY, 0.0
+       );
+}
+
+/// Create a rotation matrix.
+static inline cpTransform
+cpTransformRotate(cpFloat radians)
+{
+       cpVect rot = cpvforangle(radians);
+       return cpTransformNewTranspose(
+               rot.x, -rot.y, 0.0,
+               rot.y,  rot.x, 0.0
+       );
+}
+
+/// Create a rigid transformation matrix. (transation + rotation)
+static inline cpTransform
+cpTransformRigid(cpVect translate, cpFloat radians)
+{
+       cpVect rot = cpvforangle(radians);
+       return cpTransformNewTranspose(
+               rot.x, -rot.y, translate.x,
+               rot.y,  rot.x, translate.y
+       );
+}
+
+/// Fast inverse of a rigid transformation matrix.
+static inline cpTransform
+cpTransformRigidInverse(cpTransform t)
+{
+  return cpTransformNewTranspose(
+     t.d, -t.c, (t.c*t.ty - t.tx*t.d),
+    -t.b,  t.a, (t.tx*t.b - t.a*t.ty)
+  );
+}
+
+//MARK: Miscellaneous (but useful) transformation matrices.
+// See source for documentation...
+
+static inline cpTransform
+cpTransformWrap(cpTransform outer, cpTransform inner)
+{
+  return cpTransformMult(cpTransformInverse(outer), cpTransformMult(inner, outer));
+}
+
+static inline cpTransform
+cpTransformWrapInverse(cpTransform outer, cpTransform inner)
+{
+  return cpTransformMult(outer, cpTransformMult(inner, cpTransformInverse(outer)));
+}
+
+static inline cpTransform
+cpTransformOrtho(cpBB bb)
+{
+  return cpTransformNewTranspose(
+    2.0/(bb.r - bb.l), 0.0, -(bb.r + bb.l)/(bb.r - bb.l),
+    0.0, 2.0/(bb.t - bb.b), -(bb.t + bb.b)/(bb.t - bb.b)
+  );
+}
+
+static inline cpTransform
+cpTransformBoneScale(cpVect v0, cpVect v1)
+{
+  cpVect d = cpvsub(v1, v0); 
+  return cpTransformNewTranspose(
+    d.x, -d.y, v0.x,
+    d.y,  d.x, v0.y
+  );
+}
+
+static inline cpTransform
+cpTransformAxialScale(cpVect axis, cpVect pivot, cpFloat scale)
+{
+  cpFloat A = axis.x*axis.y*(scale - 1.0);
+  cpFloat B = cpvdot(axis, pivot)*(1.0 - scale);
+  
+  return cpTransformNewTranspose(
+    scale*axis.x*axis.x + axis.y*axis.y, A, axis.x*B,
+    A, axis.x*axis.x + scale*axis.y*axis.y, axis.y*B
+  );
+}
+
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpVect.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpVect.h
new file mode 100644 (file)
index 0000000..8ec02bd
--- /dev/null
@@ -0,0 +1,230 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef CHIPMUNK_VECT_H
+#define CHIPMUNK_VECT_H
+
+#include "chipmunk_types.h"
+
+/// @defgroup cpVect cpVect
+/// Chipmunk's 2D vector type along with a handy 2D vector math lib.
+/// @{
+
+/// Constant for the zero vector.
+static const cpVect cpvzero = {0.0f,0.0f};
+
+/// Convenience constructor for cpVect structs.
+static inline cpVect cpv(const cpFloat x, const cpFloat y)
+{
+       cpVect v = {x, y};
+       return v;
+}
+
+/// Check if two vectors are equal. (Be careful when comparing floating point numbers!)
+static inline cpBool cpveql(const cpVect v1, const cpVect v2)
+{
+       return (v1.x == v2.x && v1.y == v2.y);
+}
+
+/// Add two vectors
+static inline cpVect cpvadd(const cpVect v1, const cpVect v2)
+{
+       return cpv(v1.x + v2.x, v1.y + v2.y);
+}
+
+/// Subtract two vectors.
+static inline cpVect cpvsub(const cpVect v1, const cpVect v2)
+{
+       return cpv(v1.x - v2.x, v1.y - v2.y);
+}
+
+/// Negate a vector.
+static inline cpVect cpvneg(const cpVect v)
+{
+       return cpv(-v.x, -v.y);
+}
+
+/// Scalar multiplication.
+static inline cpVect cpvmult(const cpVect v, const cpFloat s)
+{
+       return cpv(v.x*s, v.y*s);
+}
+
+/// Vector dot product.
+static inline cpFloat cpvdot(const cpVect v1, const cpVect v2)
+{
+       return v1.x*v2.x + v1.y*v2.y;
+}
+
+/// 2D vector cross product analog.
+/// The cross product of 2D vectors results in a 3D vector with only a z component.
+/// This function returns the magnitude of the z value.
+static inline cpFloat cpvcross(const cpVect v1, const cpVect v2)
+{
+       return v1.x*v2.y - v1.y*v2.x;
+}
+
+/// Returns a perpendicular vector. (90 degree rotation)
+static inline cpVect cpvperp(const cpVect v)
+{
+       return cpv(-v.y, v.x);
+}
+
+/// Returns a perpendicular vector. (-90 degree rotation)
+static inline cpVect cpvrperp(const cpVect v)
+{
+       return cpv(v.y, -v.x);
+}
+
+/// Returns the vector projection of v1 onto v2.
+static inline cpVect cpvproject(const cpVect v1, const cpVect v2)
+{
+       return cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2));
+}
+
+/// Returns the unit length vector for the given angle (in radians).
+static inline cpVect cpvforangle(const cpFloat a)
+{
+       return cpv(cpfcos(a), cpfsin(a));
+}
+
+/// Returns the angular direction v is pointing in (in radians).
+static inline cpFloat cpvtoangle(const cpVect v)
+{
+       return cpfatan2(v.y, v.x);
+}
+
+/// Uses complex number multiplication to rotate v1 by v2. Scaling will occur if v1 is not a unit vector.
+static inline cpVect cpvrotate(const cpVect v1, const cpVect v2)
+{
+       return cpv(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);
+}
+
+/// Inverse of cpvrotate().
+static inline cpVect cpvunrotate(const cpVect v1, const cpVect v2)
+{
+       return cpv(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);
+}
+
+/// Returns the squared length of v. Faster than cpvlength() when you only need to compare lengths.
+static inline cpFloat cpvlengthsq(const cpVect v)
+{
+       return cpvdot(v, v);
+}
+
+/// Returns the length of v.
+static inline cpFloat cpvlength(const cpVect v)
+{
+       return cpfsqrt(cpvdot(v, v));
+}
+
+/// Linearly interpolate between v1 and v2.
+static inline cpVect cpvlerp(const cpVect v1, const cpVect v2, const cpFloat t)
+{
+       return cpvadd(cpvmult(v1, 1.0f - t), cpvmult(v2, t));
+}
+
+/// Returns a normalized copy of v.
+static inline cpVect cpvnormalize(const cpVect v)
+{
+       // Neat trick I saw somewhere to avoid div/0.
+       return cpvmult(v, 1.0f/(cpvlength(v) + CPFLOAT_MIN));
+}
+
+/// Spherical linearly interpolate between v1 and v2.
+static inline cpVect
+cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t)
+{
+       cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2));
+       cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f));
+       
+       if(omega < 1e-3){
+               // If the angle between two vectors is very small, lerp instead to avoid precision issues.
+               return cpvlerp(v1, v2, t);
+       } else {
+               cpFloat denom = 1.0f/cpfsin(omega);
+               return cpvadd(cpvmult(v1, cpfsin((1.0f - t)*omega)*denom), cpvmult(v2, cpfsin(t*omega)*denom));
+       }
+}
+
+/// Spherical linearly interpolate between v1 towards v2 by no more than angle a radians
+static inline cpVect
+cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a)
+{
+       cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2));
+       cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f));
+       
+       return cpvslerp(v1, v2, cpfmin(a, omega)/omega);
+}
+
+/// Clamp v to length len.
+static inline cpVect cpvclamp(const cpVect v, const cpFloat len)
+{
+       return (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v;
+}
+
+/// Linearly interpolate between v1 towards v2 by distance d.
+static inline cpVect cpvlerpconst(cpVect v1, cpVect v2, cpFloat d)
+{
+       return cpvadd(v1, cpvclamp(cpvsub(v2, v1), d));
+}
+
+/// Returns the distance between v1 and v2.
+static inline cpFloat cpvdist(const cpVect v1, const cpVect v2)
+{
+       return cpvlength(cpvsub(v1, v2));
+}
+
+/// Returns the squared distance between v1 and v2. Faster than cpvdist() when you only need to compare distances.
+static inline cpFloat cpvdistsq(const cpVect v1, const cpVect v2)
+{
+       return cpvlengthsq(cpvsub(v1, v2));
+}
+
+/// Returns true if the distance between v1 and v2 is less than dist.
+static inline cpBool cpvnear(const cpVect v1, const cpVect v2, const cpFloat dist)
+{
+       return cpvdistsq(v1, v2) < dist*dist;
+}
+
+/// @}
+
+/// @defgroup cpMat2x2 cpMat2x2
+/// 2x2 matrix type used for tensors and such.
+/// @{
+
+// NUKE
+static inline cpMat2x2
+cpMat2x2New(cpFloat a, cpFloat b, cpFloat c, cpFloat d)
+{
+       cpMat2x2 m = {a, b, c, d};
+       return m;
+}
+
+static inline cpVect
+cpMat2x2Transform(cpMat2x2 m, cpVect v)
+{
+       return cpv(v.x*m.a + v.y*m.b, v.x*m.c + v.y*m.d);
+}
+
+///@}
+
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkAutoGeometry.h b/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkAutoGeometry.h
new file mode 100644 (file)
index 0000000..0a5c683
--- /dev/null
@@ -0,0 +1,136 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
+
+#import "chipmunk/cpMarch.h"
+#import "chipmunk/cpPolyline.h"
+
+@class ChipmunkPolylineSet;
+
+/// Wrapper for the cpPolyline type.
+@interface ChipmunkPolyline : NSObject {
+@private
+       cpPolyline *_line;
+       cpFloat _area;
+}
+
+-(id)initWithPolyline:(cpPolyline *)line;
++(ChipmunkPolyline *)fromPolyline:(cpPolyline *)line;
+
+/// Returns true if the first and last vertex are equal.
+@property(nonatomic, readonly) bool isClosed;
+
+/// Returns the signed area of the polyline calculated by cpAreaForPoly.
+/// Non-closed polylines return an area of 0.
+@property(nonatomic, readonly) cpFloat area;
+
+/// Centroid of the polyline calculated by cpCentroidForPoly.
+/// It is an error to call this on a non-closed polyline.
+@property(nonatomic, readonly) cpVect centroid;
+
+/// Calculates the moment of inertia for a closed polyline with the given mass and offset.
+-(cpFloat)momentForMass:(cpFloat)mass offset:(cpVect)offset;
+
+
+/// Vertex count.
+@property(nonatomic, readonly) NSUInteger count;
+
+/// Array of vertexes.
+@property(nonatomic, readonly) const cpVect *verts;
+
+/**
+       Returns a copy of a polyline simplified by using the Douglas-Peucker algorithm.
+       This works very well on smooth or gently curved shapes, but not well on straight edged or angular shapes.
+*/
+-(ChipmunkPolyline *)simplifyCurves:(cpFloat)tolerance;
+
+/**
+       Returns a copy of a polyline simplified by discarding "flat" vertexes.
+       This works well on straigt edged or angular shapes, not as well on smooth shapes.
+*/
+-(ChipmunkPolyline *)simplifyVertexes:(cpFloat)tolerance;
+
+/// Generate a convex hull that contains a polyline. (closed or not)
+-(ChipmunkPolyline *)toConvexHull;
+
+/// Generate an approximate convex hull that contains a polyline. (closed or not)
+-(ChipmunkPolyline *)toConvexHull:(cpFloat)tolerance;
+
+/// Generate a set of convex hulls for a polyline.
+/// See the note on cpPolylineConvexDecomposition_BETA() for more information.
+-(ChipmunkPolylineSet *)toConvexHulls_BETA:(cpFloat)tolerance;
+
+/// Create an array of segments for each segment in this polyline.
+-(NSArray *)asChipmunkSegmentsWithBody:(ChipmunkBody *)body radius:(cpFloat)radius offset:(cpVect)offset;
+
+/// Create a ChipmunkPolyShape from this polyline. (Must be convex!)
+-(ChipmunkPolyShape *)asChipmunkPolyShapeWithBody:(ChipmunkBody *)body transform:(cpTransform)transform radius:(cpFloat)radius;
+
+@end
+
+
+/// Wrapper for the cpPolylineSet type.
+@interface ChipmunkPolylineSet : NSObject<NSFastEnumeration> {
+@private
+       NSMutableArray *_lines;
+}
+
+-(id)initWithPolylineSet:(cpPolylineSet *)set;
++(ChipmunkPolylineSet *)fromPolylineSet:(cpPolylineSet *)set;
+
+@property(nonatomic, readonly) NSUInteger count;
+
+-(ChipmunkPolyline *)lineAtIndex:(NSUInteger)index;
+
+@end
+
+
+/**
+       A sampler is an object that provides a basis function to build shapes from.
+       This can be from a block of pixel data (loaded from a file, or dumped from the screen), or even a mathematical function such as Perlin noise.
+*/
+@interface ChipmunkAbstractSampler : NSObject {
+@protected
+       cpFloat _marchThreshold;
+       cpMarchSampleFunc _sampleFunc;
+}
+
+/// The threshold passed to the cpMarch*() functions.
+/// The value of the contour you want to extract.
+@property(nonatomic, assign) cpFloat marchThreshold;
+
+/// Get the primitive cpMarchSampleFunc used by this sampler.
+@property(nonatomic, readonly) cpMarchSampleFunc sampleFunc;
+
+/// Designated initializer.
+-(id)initWithSamplingFunction:(cpMarchSampleFunc)sampleFunc;
+
+/// Sample at a specific point.
+-(cpFloat)sample:(cpVect)pos;
+
+/// March a certain area of the sampler.
+-(ChipmunkPolylineSet *)march:(cpBB)bb xSamples:(NSUInteger)xSamples ySamples:(NSUInteger)ySamples hard:(bool)hard;
+
+@end
+
+
+
+/// A simple sampler type that wraps a block as it's sampling function.
+typedef cpFloat (^ChipmunkMarchSampleBlock)(cpVect point);
+
+@interface ChipmunkBlockSampler : ChipmunkAbstractSampler {
+       ChipmunkMarchSampleBlock _block;
+}
+
+/// Initializes the sampler using a copy of the passed block.
+-(id)initWithBlock:(ChipmunkMarchSampleBlock)block;
++(ChipmunkBlockSampler *)samplerWithBlock:(ChipmunkMarchSampleBlock)block;
+
+@end
+
+
+
+#import "ChipmunkImageSampler.h"
+#import "ChipmunkPointCloudSampler.h"
+#import "ChipmunkTileCache.h"
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkBody.h b/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkBody.h
new file mode 100644 (file)
index 0000000..2427b9b
--- /dev/null
@@ -0,0 +1,192 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+@class ChipmunkShape;
+@class ChipmunkConstraint;
+
+/**
+       Rigid bodies are the basic unit of simulation in Chipmunk.
+       They hold the physical properties of an object (mass, position, rotation, velocity, etc.). After creating a ChipmunkBody object, you can attach collision shapes (ChipmunkShape) and joints (ChipmunkConstraint) to it.
+*/
+@interface ChipmunkBody : NSObject <ChipmunkBaseObject>
+
+/// Get the ChipmunkBody object associciated with a cpBody pointer.
+/// Undefined if the cpBody wasn't created using Objective-Chipmunk.
++(ChipmunkBody *)bodyFromCPBody:(cpBody *)body;
+
+/**
+  Create an autoreleased rigid body with the given mass and moment.
+  Guessing the moment of inertia is usually a bad idea. Use the moment estimation functions (cpMomentFor*()).
+*/
++ (id)bodyWithMass:(cpFloat)mass andMoment:(cpFloat)moment;
+
+/**
+  Create an autoreleased static body.
+*/
++ (id)staticBody;
+
+/**
+  Create an autoreleased kinematic body.
+*/
++ (id)kinematicBody;
+
+/**
+  Initialize a rigid body with the given mass and moment of inertia.
+  Guessing the moment of inertia is usually a bad idea. Use the moment estimation functions (cpMomentFor*()).
+*/
+- (id)initWithMass:(cpFloat)mass andMoment:(cpFloat)moment;
+
+/// Type of the body (dynamic, kinematic, static).
+@property(nonatomic, assign) cpBodyType type;
+
+/// Mass of the rigid body. Mass does not have to be expressed in any particular units, but relative masses should be consistent.
+@property(nonatomic, assign) cpFloat mass;
+
+/// Moment of inertia of the body. The mass tells you how hard it is to push an object, the MoI tells you how hard it is to spin the object. Don't try to guess the MoI, use the cpMomentFor*() functions to try and estimate it.
+@property(nonatomic, assign) cpFloat moment;
+
+/// Location of the body's center of gravity relative to it's position. Defaults to @c cpvzero.
+@property(nonatomic, assign) cpVect centerOfGravity;
+
+/// The position of the rigid body's center of gravity.
+@property(nonatomic, assign) cpVect position;
+
+/// The linear velocity of the rigid body.
+@property(nonatomic, assign) cpVect velocity;
+
+/// The linear force applied to the rigid body. Unlike in some physics engines, the force does not reset itself during each step. Make sure that you are reseting the force between frames if that is what you intended.
+@property(nonatomic, assign) cpVect force;
+
+/// The rotation angle of the rigid body in radians.
+@property(nonatomic, assign) cpFloat angle;
+
+/// The angular velocity of the rigid body in radians per second.
+@property(nonatomic, assign) cpFloat angularVelocity;
+
+/// The torque being applied to the rigid body. Like force, this property is not reset every frame.
+@property(nonatomic, assign) cpFloat torque;
+
+/// The rigid transform of the body.
+@property(nonatomic, readonly) cpTransform transform;
+
+/// Returns a pointer to the underlying cpBody C struct.
+@property(nonatomic, readonly) cpBody *body;
+
+/**
+       An object that this constraint is associated with. You can use this get a reference to your game object or controller object from within callbacks.
+       @attention Like most @c delegate properties this is a weak reference and does not call @c retain. This prevents reference cycles from occuring.
+*/
+@property(nonatomic, assign) id userData;
+
+/// Has the body been put to sleep by the space?
+@property(nonatomic, readonly) bool isSleeping;
+
+/// Get the kinetic energy of this body.
+@property(nonatomic, readonly) cpFloat kineticEnergy;
+
+/// Get the space the body is added to.
+@property(nonatomic, readonly) ChipmunkSpace *space;
+
+/**
+  Convert from body local to world coordinates.
+  Convert a point in world (absolute) coordinates to body local coordinates affected by the position and rotation of the rigid body.
+*/
+- (cpVect)localToWorld:(cpVect)v;
+
+/**
+  Convert from world to body local Coordinates.
+  Convert a point in body local coordinates coordinates to world (absolute) coordinates.
+*/
+- (cpVect)worldToLocal:(cpVect)v;
+
+/**
+       Get the velocity of a point on a body.
+       Get the world (absolute) velocity of a point on a rigid body specified in body local coordinates.
+*/
+- (cpVect)velocityAtLocalPoint:(cpVect)p;
+
+/**
+       Get the velocity of a point on a body.
+       Get the world (absolute) velocity of a point on a rigid body specified in world coordinates.
+*/
+- (cpVect)velocityAtWorldPoint:(cpVect)p;
+
+/**
+  Apply a force to a rigid body. An offset of cpvzero is equivalent to adding directly to the force property.
+  @param force A force in expressed in absolute (word) coordinates.
+       @param offset An offset expressed in world coordinates. Note that it is still an offset, meaning that it's position is relative, but the rotation is not.
+*/
+- (void)applyForce:(cpVect)force atLocalPoint:(cpVect)point;
+- (void)applyForce:(cpVect)force atWorldPoint:(cpVect)point;
+
+/**
+  Apply an impulse to a rigid body.
+  @param impulse An impulse in expressed in absolute (word) coordinates.
+       @param offset An offset expressed in world coordinates. Note that it is still an offset, meaning that it's position is relative, but the rotation is not.
+*/
+- (void)applyImpulse:(cpVect)impulse atLocalPoint:(cpVect)point;
+- (void)applyImpulse:(cpVect)impulse atWorldPoint:(cpVect)point;
+
+/// Wake up the body if it's sleeping, or reset the idle timer if it's active.
+- (void)activate;
+
+/// Wake up any bodies touching a static body through shape @c filter Pass @c nil for @c filter to away all touching bodies.
+- (void)activateStatic:(ChipmunkShape *)filter;
+
+/**
+       Force the body to sleep immediately. The body will be added to the same group as @c group. When any object in a group is woken up, all of the bodies are woken up with it.
+       If @c group is nil, then a new group is created and the body is added to it. It is an error pass a non-sleeping body as @c group.
+       This is useful if you want an object to be inactive until something hits it such as a pile of boxes you want the player to plow through or a stalactite hanging from a cave ceiling.
+       Make sure the body is fully set up before you call this. Adding this body or any shapes or constraints attached to it to a space, or modifying any of their properties automatically wake a body up.
+*/
+- (void)sleepWithGroup:(ChipmunkBody *)group;
+
+/**
+       Equivalent to [ChipmunkBody sleepWithGroup:nil]. That is the object is forced to sleep immediately, but is not grouped with any other sleeping bodies.
+*/
+- (void)sleep;
+
+/// Get a list of shapes that are attached to this body and currently added to a space.
+- (NSArray *)shapes;
+
+/// Get a list of constraints that are attached to this body and currently added to a space.
+- (NSArray *)constraints;
+
+/// Body/arbiter iterator callback block type.
+typedef void (^ChipmunkBodyArbiterIteratorBlock)(cpArbiter *arbiter);
+
+/// Call @c block once for each arbiter that is currently active on the body.
+- (void)eachArbiter:(ChipmunkBodyArbiterIteratorBlock)block;
+
+/// Implements the ChipmunkBaseObject protocol, not particularly useful outside of the library code
+- (void)addToSpace:(ChipmunkSpace *)space;
+/// Implements the ChipmunkBaseObject protocol, not particularly useful outside of the library code
+- (void)removeFromSpace:(ChipmunkSpace *)space;
+
+/// Override this to change the way that the body's velocity is integrated.
+/// You should either understand how the cpBodyUpdateVelocity() function works, or use the super method.
+-(void)updateVelocity:(cpFloat)dt gravity:(cpVect)gravity damping:(cpFloat)damping;
+
+/// OVerride this to change the way that the body's position is intgrated.
+/// You should either understand how the cpBodyUpdatePosition() function works, or use the super method.
+-(void)updatePosition:(cpFloat)dt;
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkConstraint.h b/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkConstraint.h
new file mode 100644 (file)
index 0000000..d72af0f
--- /dev/null
@@ -0,0 +1,405 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+       Constraints connect two ChipmunkBody objects together. Most often constraints are simple joints, but can also be things like motors, friction generators or servos.
+       
+       @htmlonly
+       <object width="425" height="344">
+               <param name="movie" value="http://www.youtube.com/v/ZgJJZTS0aMM?fs=1&amp;hl=en_US&amp;rel=0"></param>
+               <param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param>
+               <embed src="http://www.youtube.com/v/ZgJJZTS0aMM?fs=1&amp;hl=en_US&amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed>
+       </object>
+       @endhtmlonly
+*/
+@interface ChipmunkConstraint : NSObject <ChipmunkBaseObject> {
+@private
+       id _userData;
+}
+
+/// Returns a pointer to the underlying cpConstraint C struct.
+@property(nonatomic, readonly) cpConstraint *constraint;
+
+/// The first ChipmunkBody the constraint controls.
+@property(nonatomic, readonly) ChipmunkBody *bodyA;
+
+/// The second ChipmunkBody the constraint controls.
+@property(nonatomic, readonly) ChipmunkBody *bodyB;
+
+/// Get the ChipmunkConstraint object associciated with a cpConstraint pointer.
+/// Undefined if the cpConstraint wasn't created using Objective-Chipmunk.
++(ChipmunkConstraint *)constraintFromCPConstraint:(cpConstraint *)constraint;
+
+/**
+       Maximum force this constraint is allowed to use (defalts to infinity).
+       This allows joints to be pulled apart if too much force is applied to them.
+       It also allows you to use constraints as force or friction generators for controlling bodies.
+*/
+@property(nonatomic, assign) cpFloat maxForce;
+
+/**
+       The rate at which joint error is corrected.
+       Defaults to pow(1.0 - 0.1, 60.0) meaning that it will correct 10% of the error every 1/60th of a second.
+*/
+@property(nonatomic, assign) cpFloat errorBias;
+
+/**
+       Maximum rate (speed) that a joint can be corrected at (defaults to infinity).
+       Setting this value to a finite value allows you to control a joint like a servo motor.
+*/
+@property(nonatomic, assign) cpFloat maxBias;
+
+/**
+       Whether or not the connected bodies should checked for collisions.
+       Collisions are filtered before calling callbacks.
+       Defaults to TRUE.
+*/
+@property(nonatomic, assign) BOOL collideBodies;
+
+/// Get the most recent impulse applied by this constraint.
+@property(nonatomic, readonly) cpFloat impulse;
+
+/// Get the space the body is added to.
+@property(nonatomic, readonly) ChipmunkSpace *space;
+
+/**
+       An object that this constraint is associated with. You can use this get a reference to your game object or controller object from within callbacks.
+       @attention Like most @c delegate properties this is a weak reference and does not call @c retain. This prevents reference cycles from occuring.
+*/
+@property(nonatomic, assign) id userData;
+
+/// Override this method to update a constraints parameters just before running the physics each step.
+-(void)preSolve:(ChipmunkSpace *)space;
+
+/// Override this method to poll values from a constraint each frame after the physics runs.
+/// This can be used to implement breakable joints for instance.
+-(void)postSolve:(ChipmunkSpace *)space;
+
+@end
+
+
+/**
+       Pin joints hold a set distance between points on two bodies.
+       Think of them as connecting a solid pin or rod between the two anchor points.
+*/
+@interface ChipmunkPinJoint : ChipmunkConstraint
+
+/**
+       Create an autoreleased pin joint between the two bodies with the given anchor points.
+       The distance is calculated when the joint is initialized. It can be set explicitly using the property.
+*/
++ (ChipmunkPinJoint *)pinJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB;
+
+/**
+       Initialize a pin joint between the two bodies with the given anchor points.
+       The distance is calculated when the joint is initialized. It can be set explicitly using the property.
+*/
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB;
+
+/// The anchor point on the first body.
+@property(nonatomic, assign) cpVect anchorA;
+
+/// The anchor point on the second body.
+@property(nonatomic, assign) cpVect anchorB;
+
+/// The distance between the two anchor points that the joint keeps.
+@property(nonatomic, assign) cpFloat dist;
+
+@end
+
+
+/**
+       Slide joints hold the distance between points on two bodies between a minimum and a maximum.
+       Think of them as a telescoping ChipmunkPinJoint.
+*/
+@interface ChipmunkSlideJoint : ChipmunkConstraint
+
+/**
+       Create an autoreleased slide joint between the two bodies with the given anchor points and distance range.
+*/
++ (ChipmunkSlideJoint *)slideJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB min:(cpFloat)min max:(cpFloat)max;
+
+/**
+       Initialize a slide joint between the two bodies with the given anchor points and distance range.
+*/
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB min:(cpFloat)min max:(cpFloat)max;
+
+/// The anchor point on the first body.
+@property(nonatomic, assign) cpVect anchorA;
+
+/// The anchor point on the second body.
+@property(nonatomic, assign) cpVect anchorB;
+
+/// The minimum allowed distance between anchor points.
+@property(nonatomic, assign) cpFloat min;
+
+/// The maximum allowed distance between anchor points.
+@property(nonatomic, assign) cpFloat max;
+
+@end
+
+
+/**
+       Pivot joints hold two points on two bodies together allowing them to rotate freely around the pivot.
+*/
+@interface ChipmunkPivotJoint : ChipmunkConstraint
+
+/**
+       Create an autoreleased pivot joint between the two bodies with the two anchor points.
+       Make sure you have the bodies in the right place as the joint will fix itself as soon as you start simulating the space.
+*/
++ (ChipmunkPivotJoint *)pivotJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB;
+
+/**
+       Create an autoreleased pivot joint between the two bodies by calculating the anchor points from the pivot point given in absolute coordinates.
+*/
++ (ChipmunkPivotJoint *)pivotJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b pivot:(cpVect)pivot;
+
+/**
+       Initialize a pivot joint between the two bodies with the two anchor points.
+       Make sure you have the bodies in the right place as the joint will fix itself as soon as you start simulating the space.
+*/
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB;
+
+/**
+       Initialize a pivot joint between the two bodies by calculating the anchor points from the pivot point given in absolute coordinates.
+*/
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b pivot:(cpVect)pivot;
+
+/// The anchor point on the first body.
+@property(nonatomic, assign) cpVect anchorA;
+
+/// The anchor point on the second body.
+@property(nonatomic, assign) cpVect anchorB;
+
+@end
+
+
+/**
+       Groove joints hold a pivot point on one body to line along a line segment on another like a pin in a groove.
+*/
+@interface ChipmunkGrooveJoint : ChipmunkConstraint
+
+/**
+       Create an autoreleased groove joint between the two bodies.
+       Make sure you have the bodies in the right place as the joint will snap into shape as soon as you start simulating the space.
+       @param grooveA The start of the line segment on the first body.
+       @param grooveB The end of the line segment on the first body.
+       @param anchorB The anchor point on the second body that is held to the line segment on the first.
+*/
++ (ChipmunkGrooveJoint *)grooveJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b grooveA:(cpVect)grooveA grooveB:(cpVect)grooveB anchorB:(cpVect)anchorB;
+
+/**
+       Initialize a groove joint between the two bodies.
+       Make sure you have the bodies in the right place as the joint will snap into shape as soon as you start simulating the space.
+       @param grooveA The start of the line segment on the first body.
+       @param grooveB The end of the line segment on the first body.
+       @param anchorB The anchor point on the second body that is held to the line segment on the first.
+*/
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b grooveA:(cpVect)grooveA grooveB:(cpVect)grooveB anchorB:(cpVect)anchorB;
+
+/// The start point of the groove on the first body.
+@property(nonatomic, assign) cpVect grooveA;
+/// The end point of the groove on the first body.
+@property(nonatomic, assign) cpVect grooveB;
+
+/// The anchor point on the second body.
+@property(nonatomic, assign) cpVect anchorB;
+
+@end
+
+
+/**
+       A spring with a damper.
+       While a spring is not technically a constraint, the damper is. The spring forces are simply a convenience.
+*/
+@interface ChipmunkDampedSpring : ChipmunkConstraint
+
+/**
+       Create an autoreleased damped spring between two bodies at the given anchor points.
+       @param restLength The length the spring wants to contract or expand to.
+       @param stiffness The <a href="http://en.wikipedia.org/wiki/Young's_modulus">young's modulus</a> of the spring.
+       @param damping The amount of viscous damping to apply.
+*/
++ (ChipmunkDampedSpring *)dampedSpringWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB restLength:(cpFloat)restLength stiffness:(cpFloat)stiffness damping:(cpFloat)damping;
+
+/**
+       Initialize a damped spring between two bodies at the given anchor points.
+       @param restLength The length the spring wants to contract or expand to.
+       @param stiffness The <a href="http://en.wikipedia.org/wiki/Young's_modulus">young's modulus</a> of the spring.
+       @param damping The amount of viscous damping to apply.
+*/
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB restLength:(cpFloat)restLength stiffness:(cpFloat)stiffness damping:(cpFloat)damping;
+
+/// The anchor point on the first body.
+@property(nonatomic, assign) cpVect anchorA;
+
+/// The anchor point on the second body.
+@property(nonatomic, assign) cpVect anchorB;
+
+/// The length the spring wants to contract or expand to.
+@property(nonatomic, assign) cpFloat restLength;
+
+/// The <a href="http://en.wikipedia.org/wiki/Young's_modulus">young's modulus</a> of the spring.
+@property(nonatomic, assign) cpFloat stiffness;
+
+/// The amount of viscous damping to apply.
+@property(nonatomic, assign) cpFloat damping;
+
+@end
+
+
+/**
+       Like a ChipmunkDampedSpring, but operates in a rotational fashion.
+*/
+@interface ChipmunkDampedRotarySpring : ChipmunkConstraint
+
+
+/**
+       Create an autoreleased damped rotary spring between the given bodies.
+       @param restAngle The angular offset in radians the spring attempts to keep between the two bodies.
+       @param stiffness The <a href="http://en.wikipedia.org/wiki/Young's_modulus">young's modulus</a> of the spring.
+       @param damping The amount of viscous damping to apply.
+*/
++ (ChipmunkDampedRotarySpring *)dampedRotarySpringWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b restAngle:(cpFloat)restAngle stiffness:(cpFloat)stiffness damping:(cpFloat)damping;
+
+/**
+       Initialize a damped rotary spring between the given bodies.
+       @param restAngle The angular offset in radians the spring attempts to keep between the two bodies.
+       @param stiffness The <a href="http://en.wikipedia.org/wiki/Young's_modulus">young's modulus</a> of the spring.
+       @param damping The amount of viscous damping to apply.
+*/
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b restAngle:(cpFloat)restAngle stiffness:(cpFloat)stiffness damping:(cpFloat)damping;
+
+/// The angular offset the spring attempts to keep between the two bodies.
+@property(nonatomic, assign) cpFloat restAngle;
+
+/// The <a href="http://en.wikipedia.org/wiki/Young's_modulus">young's modulus</a> of the spring.
+@property(nonatomic, assign) cpFloat stiffness;
+
+/// The amount of viscous damping to apply.
+@property(nonatomic, assign) cpFloat damping;
+
+@end
+
+
+/**
+       Constrains the angle between two bodies.
+       This joint is often used in conjuction with a separate ChipmunkPivotJoint in order to limit the rotation around the pivot.
+*/
+@interface ChipmunkRotaryLimitJoint : ChipmunkConstraint
+
+/**
+       Create an autoreleased rotary limit joint between the two bodies and angular range in radians.
+       Make sure you have the bodies in the right place as the joint will snap into shape as soon as you start simulating the space.
+*/
++ (ChipmunkRotaryLimitJoint *)rotaryLimitJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b min:(cpFloat)min max:(cpFloat)max;
+
+/**
+       Create an autoreleased rotary limit joint between the two bodies and angular range in radians.
+       Make sure you have the bodies in the right place as the joint will snap into shape as soon as you start simulating the space.
+*/
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b min:(cpFloat)min max:(cpFloat)max;
+
+/// The minimum angular delta of the joint in radians.
+@property(nonatomic, assign) cpFloat min;
+
+/// The maximum angular delta of the joint in radians.
+@property(nonatomic, assign) cpFloat max;
+
+@end
+
+
+/**
+       Simple motors make two objects spin relative to each other.
+       They are most often used with the ChipmunkConstraint.maxForce property set to a finite value.
+*/
+@interface ChipmunkSimpleMotor : ChipmunkConstraint
+
+/// Create an autoreleased simple motor between the given bodies and relative rotation rate in radians per second.
++ (ChipmunkSimpleMotor *)simpleMotorWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b rate:(cpFloat)rate;
+
+/// Initialize a simple motor between the given bodies and relative rotation rate in radians per second.
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b rate:(cpFloat)rate;
+
+/// The relative rotation speed of the two bodies in radians per second.
+@property(nonatomic, assign) cpFloat rate;
+
+@end
+
+
+/**
+       Gear joints constrain the rotational speed of one body to another.
+       A ratio of 1.0 will lock the rotation of two bodies together, and negative ratios will cause them to spin in opposite directions.
+       You can also use gear joints as rotary servos by setting ChipmunkConstraint.maxForce and ChipmunkConstraint.maxBias to finite values and changing the ChipmunkGearJoint.phase property.
+*/
+@interface ChipmunkGearJoint : ChipmunkConstraint
+
+/**
+       Create an autoreleased gear joint between the given bodies.
+       @param phase The angular offset.
+       @param ratio The ratio of the rotational speeds.
+*/
++ (ChipmunkGearJoint *)gearJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratio:(cpFloat)ratio;
+
+/**
+       Initialize a gear joint between the given bodies.
+       @param phase The angular offset in radians.
+       @param ratio The ratio of the rotational speeds.
+*/
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratio:(cpFloat)ratio;
+
+/// The angular offset in radians.
+@property(nonatomic, assign) cpFloat phase;
+/// The ratio of the rotational speeds.
+@property(nonatomic, assign) cpFloat ratio;
+
+@end
+
+/**
+       Ratchet joints create rotary ratches similar to a socket wrench.
+*/
+@interface ChipmunkRatchetJoint : ChipmunkConstraint
+
+/**
+       Create an autoreleased ratchet joint between the given bodies.
+       @param phase The angular offset of the ratchet positions in radians.
+       @param ratchet The angle in radians of each ratchet position. Negative values cause the ratchet to operate in the opposite direction.
+*/
++ (ChipmunkRatchetJoint *)ratchetJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratchet:(cpFloat)ratchet;
+
+/**
+       Initialize a ratchet joint between the given bodies.
+       @param phase The angular offset of the ratchet positions in radians.
+       @param ratchet The angle in radians of each ratchet position. Negative values cause the ratchet to operate in the opposite direction.
+*/
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratchet:(cpFloat)ratchet;
+
+/// The current ratchet position in radians.
+@property(nonatomic, assign) cpFloat angle;
+
+/// The angular offset of the ratchet positions in radians
+@property(nonatomic, assign) cpFloat phase;
+
+/// The angle in radians of each ratchet position. Negative values cause the ratchet to operate in the opposite direction.
+@property(nonatomic, assign) cpFloat ratchet;
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkImageSampler.h b/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkImageSampler.h
new file mode 100644 (file)
index 0000000..cba21c8
--- /dev/null
@@ -0,0 +1,114 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
+#import "ChipmunkAutoGeometry.h"
+
+#import <TargetConditionals.h>
+
+#if TARGET_OS_IPHONE == 1
+       #import <CoreGraphics/CoreGraphics.h>
+#endif
+
+
+/**
+       Generic sampler used with bitmap data.
+       Currently limited to 8 bit per component data.
+       Bitmap samplers currently provide no filtering, but could be easily extended to do so.
+*/
+@interface ChipmunkBitmapSampler : ChipmunkAbstractSampler {
+@private
+       NSUInteger _width, _height, _stride;
+       NSUInteger _bytesPerPixel, _component;
+       
+       bool _flip;
+       const uint8_t *_pixels;
+       NSData *_pixelData;
+       
+       cpFloat _borderValue;
+       
+       cpBB _outputRect;
+}
+
+/// Width of the bitmap in pixels.
+@property(nonatomic, readonly) NSUInteger width;
+
+/// Height of the bitmap in pixels.
+@property(nonatomic, readonly) NSUInteger height;
+
+/// Bytes per pixel of the bitmap. (ex: RGBA8888 would be 4)
+@property(nonatomic, readonly) NSUInteger bytesPerPixel;
+
+/// Zero-based ndex of the component to sample. (ex: alpha of RGBA would be 3)
+@property(nonatomic, assign) NSUInteger component;
+
+/// NSData object holding the pixel data.
+@property(nonatomic, readonly) NSData *pixelData;
+
+/// Rect that the image maps to.
+/// Defaults to (0.5, 0.5, width - 0.5, height - 0.5) so that pixel centers will be cleanly sampled.
+@property(nonatomic, assign) cpBB outputRect;
+
+/**
+       Init a sampler from bitmap data.
+       Stride refers to the length of a row of pixels in bytes. (Generally just w*h*bytesPerPixel unless there is padding)
+       Image must use one byte per component, but can have any number of components.
+       @c component refers to the 0-based index of the component to sample. (i.e. 3 would sample the alpha in an RGBA bitmap)
+       @c flip allows you to flip the image vertically to match how it migh be drawn.
+       @c pixelData can be either a NSData or NSMutableData (i.e. for deformable terrain) that contains the bitmap data.
+*/
+-(id)initWithWidth:(NSUInteger)width height:(NSUInteger)height stride:(NSUInteger)stride bytesPerPixel:(NSUInteger)bytesPerPixel component:(NSUInteger)component flip:(bool)flip pixelData:(NSData *)pixelData;
+
+/// Set the border of the bitmap to repeat the edge pixels.
+-(void)setBorderRepeat;
+
+/// Set the border of the bitmap to be a specific value.
+-(void)setBorderValue:(cpFloat)borderValue;
+
+/// March the entire image.
+-(ChipmunkPolylineSet *)marchAllWithBorder:(bool)bordered hard:(bool)hard;
+
+@end
+
+
+
+/// Sampler built on top of a CGBitmapContext to allow deformable geometry.
+/// Very efficient when paired with a ChipmunkTileCache.
+@interface ChipmunkCGContextSampler : ChipmunkBitmapSampler {
+@private
+       CGContextRef _context;
+}
+
+/// CGBitmapContext for this sampler.
+@property(nonatomic, readonly) CGContextRef context;
+
+/// NSMutableData object holding the pixel data.
+@property(nonatomic, readonly) NSMutableData *pixelData;
+
+/// Initialize a context based sampler. Must provide options for a valid context.
+/// Find out more here in the Quartz 2D Programming Guide.
+-(id)initWithWidth:(unsigned long)width height:(unsigned long)height colorSpace:(CGColorSpaceRef)colorSpace bitmapInfo:(CGBitmapInfo)bitmapInfo component:(NSUInteger)component;
+
+@end
+
+
+
+/// A CGBitmapContext sampler initialized with an CGImage.
+@interface ChipmunkImageSampler : ChipmunkCGContextSampler
+
+/// Helper method to easily load CGImageRefs by path. You are responsible for releasing the CGImage.
++(CGImageRef)loadImage:(NSURL *)url;
+
+/// Initialize an image sampler of a certain size with a CGImage.
+/// If isMask is TRUE, the image will be loaded as a black and white image, if FALSE only the image alpha will be loaded.
+-(id)initWithImage:(CGImageRef)image isMask:(bool)isMask contextWidth:(NSUInteger)width contextHeight:(NSUInteger)height;
+
+/// Initialize an image sampler with an image file.
+/// If isMask is TRUE, the image will be loaded as a black and white image, if FALSE only the image alpha will be loaded.
+-(id)initWithImageFile:(NSURL *)url isMask:(bool)isMask;
+
+/// Return an autoreleased image sampler initialized with an image file.
+/// If isMask is TRUE, the image will be loaded as a black and white image, if FALSE only the image alpha will be loaded.
++(ChipmunkImageSampler *)samplerWithImageFile:(NSURL *)url isMask:(bool)isMask;
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkMultiGrab.h b/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkMultiGrab.h
new file mode 100644 (file)
index 0000000..8cb59ce
--- /dev/null
@@ -0,0 +1,136 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
+
+@interface ChipmunkGrab : NSObject<ChipmunkObject> {
+       NSArray *_chipmunkObjects;
+       
+       cpVect _pos;
+       cpFloat _smoothing;
+       
+       ChipmunkShape *_grabbedShape;
+       
+       id _data;
+}
+
+/// Last touch location of the grab.
+@property(nonatomic, readonly) cpVect pos;
+
+/// The ChipmunkShape that this grab was created for.
+@property(nonatomic, readonly) ChipmunkShape *grabbedShape;
+
+/// User definable pointer
+@property(nonatomic, retain) id data;
+
+@end
+
+
+/// Simple class to implement multitouch grabbing of physics objects.
+@interface ChipmunkMultiGrab : NSObject {
+       ChipmunkSpace *_space;
+       NSMutableArray *_grabs;
+       
+       cpFloat _smoothing;
+       cpFloat _grabForce;
+       
+       cpFloat _grabFriction;
+       cpFloat _grabRotaryFriction;
+       cpFloat _grabRadius;
+       
+       cpShapeFilter filter;
+       bool (^_grabFilter)(ChipmunkShape *shape);
+       cpFloat (^_grabSort)(ChipmunkShape *shape, cpFloat depth);
+       
+       bool _pushMode, _pullMode;
+       
+       cpFloat _pushMass;
+       cpFloat _pushFriction;
+       cpFloat _pushElasticity;
+       cpCollisionType _pushCollisionType;
+}
+
+@property(nonatomic, assign) cpFloat smoothing;
+@property(nonatomic, assign) cpFloat grabForce;
+
+/// Layers used for the point query when grabbing objects.
+@property(nonatomic, assign) cpShapeFilter filter;
+
+/// Group used for the point query when grabbing objects
+@property(nonatomic, assign) cpGroup group;
+
+/// Gives you the opportunity to further filter shapes. Return FALSE to ignore a shape.
+/// The default implementation always returns TRUE.
+@property(nonatomic, copy) bool (^grabFilter)(ChipmunkShape *shape);
+
+/// When clicking on a spot where two shapes overlap, the default behavior is to grab the shape that
+/// overlaps the grab point the most. It's possible to use a custom sorting order instead however.
+/// The block is called with each shape and the grab depth.
+/// It should return a positive float. The shape with the highest value is grabbed.
+/// The block is only called if the touch location is within a shape.
+@property(nonatomic, copy) cpFloat (^grabSort)(ChipmunkShape *shape, cpFloat depth);
+
+/// Amount of friction applied by the touch.
+/// Should be less than the grabForce. Defaults to 0.0.
+@property(nonatomic, assign) cpFloat grabFriction;
+
+/// The amount torque to apply to the grab to keep it from spinning.
+/// Defaults to 0.0.
+@property(nonatomic, assign) cpFloat grabRotaryFriction;
+
+/// On a touch screen, a single point query can make it really hard to grab small objects with a fat finger.
+/// By providing a radius, it will make it much easier for users to grab objects.
+/// Defaults to 0.0.
+@property(nonatomic, assign) cpFloat grabRadius;
+
+@property(nonatomic, assign) bool pullMode;
+@property(nonatomic, assign) bool pushMode;
+
+@property(nonatomic, assign) cpFloat pushMass;
+@property(nonatomic, assign) cpFloat pushFriction;
+@property(nonatomic, assign) cpFloat pushElasticity;
+@property(nonatomic, assign) cpCollisionType pushCollisionType;
+
+@property(nonatomic, readonly) NSArray *grabs;
+
+
+/**
+       @c space is the space to grab shapes in.
+       @c smoothing is the amount of mouse smoothing to apply as percentage of remaining error per second.
+       cpfpow(0.8, 60) is a good starting point that provides fast response, but smooth mouse updates.
+       @c force is the force the grab points can apply.
+*/
+-(id)initForSpace:(ChipmunkSpace *)space withSmoothing:(cpFloat)smoothing withGrabForce:(cpFloat)grabForce;
+
+/// Start tracking a new grab point
+/// Returns the ChipmunkGrab that is tracking the touch, but only if a shape was grabbed.
+/// Returns nil when creating a push shape (if push mode is enabled), or when no shape is grabbed.
+-(ChipmunkGrab *)beginLocation:(cpVect)pos;
+
+/// Update a grab point.
+/// Returns the ChipmunkGrab that is tracking the touch, but only if the grab is tracking a shape.
+-(ChipmunkGrab *)updateLocation:(cpVect)pos;
+
+/// End a grab point.
+/// Returns the ChipmunkGrab that was tracking the touch, but only if the grab was tracking a shape.
+-(ChipmunkGrab *)endLocation:(cpVect)pos;
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkPointCloudSampler.h b/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkPointCloudSampler.h
new file mode 100644 (file)
index 0000000..e18ea17
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
+#import "ChipmunkAutoGeometry.h"
+
+/**
+       A point cloud sampler allows you to perform deformable terrain like with a bitmap backed sampler,
+       but without any bounds. It only requires memory for the points you add instead of large RAM chewing bitmap.
+       However, unlike a bitmap, the deformation can only go one way. (i.e. You can add or remove terrain, but not both).
+       Without any points, the sampler will return 1.0. Adding points will put "holes" in it causing it to return lower values.
+*/
+@interface ChipmunkPointCloudSampler : ChipmunkAbstractSampler {
+@private
+       cpFloat _cellSize;
+       cpSpatialIndex *_index;
+}
+
+/// Initialize the sampler with the given cell size,
+/// which should roughly match the size of the points added to the sampler.
+- (id)initWithCellSize:(cpFloat)cellSize;
+
+/// Add a point to the cloud and return the dirty rect for the point.
+-(cpBB)addPoint:(cpVect)pos radius:(cpFloat)radius fuzz:(cpFloat)fuzz;
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkShape.h b/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkShape.h
new file mode 100644 (file)
index 0000000..ab982e8
--- /dev/null
@@ -0,0 +1,249 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+@class ChipmunkPointQueryInfo;
+@class ChipmunkSegmentQueryInfo;
+
+
+/// Abstract base class for collsion shape types.
+@interface ChipmunkShape : NSObject <ChipmunkBaseObject> {
+@private
+       id _userData;
+}
+
+/// Get the ChipmunkShape object associciated with a cpShape pointer.
+/// Undefined if the cpShape wasn't created using Objective-Chipmunk.
++(ChipmunkShape *)shapeFromCPShape:(cpShape *)shape;
+
+/// Returns a pointer to the underlying cpShape C struct.
+@property(nonatomic, readonly) cpShape *shape;
+
+/// The ChipmunkBody that this shape is attached to.
+@property(nonatomic, retain) ChipmunkBody *body;
+
+// TODO doc
+@property(nonatomic, assign) cpFloat mass;
+@property(nonatomic, assign) cpFloat density;
+@property(nonatomic, readonly) cpFloat moment;
+@property(nonatomic, readonly) cpFloat area;
+@property(nonatomic, readonly) cpVect centerOfGravity;
+
+/// The axis-aligned bounding box for this shape.
+@property(nonatomic, readonly) cpBB bb;
+
+/// Sensor shapes send collision callback messages, but don't create a collision response.
+@property(nonatomic, assign) BOOL sensor;
+
+/// How bouncy this shape is.
+@property(nonatomic, assign) cpFloat elasticity;
+
+/// How much friction this shape has.
+@property(nonatomic, assign) cpFloat friction;
+
+/**
+       The velocity of the shape's surface.
+       This velocity is used in the collision response when calculating the friction only.
+*/
+@property(nonatomic, assign) cpVect surfaceVelocity;
+
+/**
+       An object reference used as a collision type identifier. This is used when defining collision handlers.
+       @attention Like most @c delegate properties this is a weak reference and does not call @c retain.
+*/
+@property(nonatomic, assign) cpCollisionType collisionType;
+
+/**
+       The collision filtering parameters of this shape.
+*/
+@property(nonatomic, assign) cpShapeFilter filter;
+
+/// Get the space the body is added to.
+@property(nonatomic, readonly) ChipmunkSpace *space;
+
+/**
+       An object that this shape is associated with. You can use this get a reference to your game object or controller object from within callbacks.
+       @attention Like most @c delegate properties this is a weak reference and does not call @c retain. This prevents reference cycles from occuring.
+*/
+@property(nonatomic, assign) id userData;
+
+/// Update and cache the axis-aligned bounding box for this shape.
+- (cpBB)cacheBB;
+
+- (ChipmunkPointQueryInfo *)pointQuery:(cpVect)point;
+- (ChipmunkSegmentQueryInfo *)segmentQueryFrom:(cpVect)start to:(cpVect)end radius:(cpFloat)radius;
+
+@end
+
+
+@interface ChipmunkPointQueryInfo : NSObject {
+       @private
+       cpPointQueryInfo _info;
+}
+
+- (id)initWithInfo:(cpPointQueryInfo *)info;
+
+/// Returns a pointer to the underlying cpNearestPointQueryInfo C struct.
+@property(nonatomic, readonly) cpPointQueryInfo *info;
+
+/// The ChipmunkShape found.
+@property(nonatomic, readonly) ChipmunkShape *shape;
+
+/// The closest point on the surface of the shape to the point.
+@property(nonatomic, readonly) cpVect point;
+
+/// The distance between the point and the surface of the shape.
+/// Negative distances mean that the point is that depth inside the shape.
+@property(nonatomic, readonly) cpFloat distance;
+
+/// The gradient of the signed distance function.
+/// The same as info.point/info.dist, but accurate even for very small values of info.dist.
+@property(nonatomic, readonly) cpVect gradient;
+
+@end
+
+
+/// Holds collision information from segment queries. You should never need to create one.
+@interface ChipmunkSegmentQueryInfo : NSObject {
+@private
+       cpSegmentQueryInfo _info;
+       cpVect _start, _end;
+}
+
+- (id)initWithInfo:(cpSegmentQueryInfo *)info start:(cpVect)start end:(cpVect)end;
+
+/// Returns a pointer to the underlying cpSegmentQueryInfo C struct.
+@property(nonatomic, readonly) cpSegmentQueryInfo *info;
+
+/// The ChipmunkShape found.
+@property(nonatomic, readonly) ChipmunkShape *shape;
+
+/// The percentage between the start and end points where the collision occurred.
+@property(nonatomic, readonly) cpFloat t;
+
+/// The normal of the collision with the shape.
+@property(nonatomic, readonly) cpVect normal;
+
+/// The point of the collision in absolute (world) coordinates.
+@property(nonatomic, readonly) cpVect point;
+
+/// The distance from the start point where the collision occurred.
+@property(nonatomic, readonly) cpFloat dist;
+
+/// The start point.
+@property(nonatomic, readonly) cpVect start;
+
+/// The end point.
+@property(nonatomic, readonly) cpVect end;
+
+@end
+
+
+/// Holds collision information from segment queries. You should never need to create one.
+@interface ChipmunkShapeQueryInfo : NSObject {
+@private
+       ChipmunkShape *_shape;
+       cpContactPointSet _contactPoints;
+}
+
+- (id)initWithShape:(ChipmunkShape *)shape andPoints:(cpContactPointSet *)set;
+
+@property(nonatomic, readonly) ChipmunkShape *shape;
+@property(nonatomic, readonly) cpContactPointSet *contactPoints;
+
+@end
+
+
+/// A perfect circle shape.
+@interface ChipmunkCircleShape : ChipmunkShape
+
+/// Create an autoreleased circle shape with the given radius and offset from the center of gravity.
++ (id)circleWithBody:(ChipmunkBody *)body radius:(cpFloat)radius offset:(cpVect)offset;
+
+/// Initialize a circle shape with the given radius and offset from the center of gravity.
+- (id)initWithBody:(ChipmunkBody *)body radius:(cpFloat)radius offset:(cpVect)offset;
+
+/// The radius of the circle.
+@property(nonatomic, readonly) cpFloat radius;
+
+/// The offset from the center of gravity.
+@property(nonatomic, readonly) cpVect offset;
+
+@end
+
+
+/// A beveled (rounded) segment shape.
+@interface ChipmunkSegmentShape : ChipmunkShape
+
+/// Create an autoreleased segment shape with the given endpoints and radius.
++ (id)segmentWithBody:(ChipmunkBody *)body from:(cpVect)a to:(cpVect)b radius:(cpFloat)radius;
+
+/// Initialize a segment shape with the given endpoints and radius.
+- (id)initWithBody:(ChipmunkBody *)body from:(cpVect)a to:(cpVect)b radius:(cpFloat)radius;
+
+/// Let Chipmunk know about the geometry of adjacent segments to avoid colliding with endcaps.
+- (void)setPrevNeighbor:(cpVect)prev nextNeighbor:(cpVect)next;
+
+/// The start of the segment shape.
+@property(nonatomic, readonly) cpVect a;
+
+/// The end of the segment shape.
+@property(nonatomic, readonly) cpVect b;
+
+/// The normal of the segment shape.
+@property(nonatomic, readonly) cpVect normal;
+
+/// The beveling radius of the segment shape.
+@property(nonatomic, readonly) cpFloat radius;
+
+@end
+
+
+/// A convex polygon shape.
+@interface ChipmunkPolyShape : ChipmunkShape
+
+/// Create an autoreleased polygon shape from the given vertexes after applying the transform and with the given rounding radius.
++ (id)polyWithBody:(ChipmunkBody *)body count:(int)count verts:(const cpVect *)verts transform:(cpTransform)transform radius:(cpFloat)radius;
+
+/// Create an autoreleased box shape centered on the center of gravity.
++ (id)boxWithBody:(ChipmunkBody *)body width:(cpFloat)width height:(cpFloat)height radius:(cpFloat)radius;
+
+/// Create an autoreleased box shape with the given bounding box in body local coordinates and rounding radius.
++ (id)boxWithBody:(ChipmunkBody *)body bb:(cpBB)bb radius:(cpFloat)radius;
+
+/// Initialize a polygon shape from the given vertexes after applying the transform and with the given rounding radius.
+- (id)initWithBody:(ChipmunkBody *)body count:(int)count verts:(const cpVect *)verts transform:(cpTransform)transform radius:(cpFloat)radius;
+
+/// Initialize a box shape centered on the center of gravity.
+- (id)initBoxWithBody:(ChipmunkBody *)body width:(cpFloat)width height:(cpFloat)height radius:(cpFloat)radius;
+
+/// Initialize a box shape with the given bounding box in body local coordinates and rounding radius.
+- (id)initBoxWithBody:(ChipmunkBody *)body bb:(cpBB)bb radius:(cpFloat)radius;
+
+/// The number of vertexes in this polygon.
+@property(nonatomic, readonly) int count;
+
+/// Get the rounding radius of the polygon.
+@property(nonatomic, readonly) cpFloat radius;
+
+/// Access the vertexes of this polygon.
+- (cpVect)getVertex:(int)index;
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkSpace.h b/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkSpace.h
new file mode 100644 (file)
index 0000000..5d8534a
--- /dev/null
@@ -0,0 +1,313 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+/// Default to using the NEON optimized solver.
+#define CHIPMUNK_SPACE_USE_HASTY_SPACE 1
+
+
+/**
+       Chipmunk spaces are simulation containers. You add a bunch of physics objects to a space (rigid bodies, collision shapes, and joints) and step the entire space forward through time as a whole.
+       If you have Chipmunk Pro, you'll want to use the ChipmunkHastySpace subclass instead as it has iPhone specific optimizations.
+       Unfortunately because of how Objective-C code is linked I can't dynamically substitute a ChipmunkHastySpace from a static library.
+*/
+@interface ChipmunkSpace : NSObject {
+@protected
+       struct cpSpace *_space;
+       ChipmunkBody *_staticBody;
+       
+       NSMutableSet *_children;
+       NSMutableArray *_handlers;
+       
+       id _userData;
+}
+
+/**
+       The iteration count is how many solver passes the space should use when solving collisions and joints (default is 10).
+       Fewer iterations mean less CPU usage, but lower quality (mushy looking) physics.
+*/
+@property(nonatomic, assign) int iterations;
+
+/// Global gravity value to use for all rigid bodies in this space (default value is @c cpvzero).
+@property(nonatomic, assign) cpVect gravity;
+
+/**
+       Global viscous damping value to use for all rigid bodies in this space (default value is 1.0 which disables damping).
+       This value is the fraction of velocity a body should have after 1 second.
+       A value of 0.9 would mean that each second, a body would have 80% of the velocity it had the previous second.
+*/
+@property(nonatomic, assign) cpFloat damping;
+
+/// If a body is moving slower than this speed, it is considered idle. The default value is 0, which signals that the space should guess a good value based on the current gravity.
+@property(nonatomic, assign) cpFloat idleSpeedThreshold;
+
+/**
+       Elapsed time before a group of idle bodies is put to sleep (defaults to infinity which disables sleeping).
+       If an entire group of touching or jointed bodies has been idle for at least this long, the space will put all of the bodies into a sleeping state where they consume very little CPU.
+*/
+@property(nonatomic, assign) cpFloat sleepTimeThreshold;
+
+/**
+       Amount of encouraged penetration between colliding shapes..
+       Used to reduce oscillating contacts and keep the collision cache warm.
+       Defaults to 0.1. If you have poor simulation quality,
+       increase this number as much as possible without allowing visible amounts of overlap.
+*/
+@property(nonatomic, assign) cpFloat collisionSlop;
+
+/**
+       Determines how fast overlapping shapes are pushed apart.
+       Expressed as a fraction of the error remaining after each second.
+       Defaults to pow(1.0 - 0.1, 60.0) meaning that Chipmunk fixes 10% of overlap each frame at 60Hz.
+*/
+@property(nonatomic, assign) cpFloat collisionBias;
+
+/**
+       Number of frames that contact information should persist.
+       Defaults to 3. There is probably never a reason to change this value.
+*/
+@property(nonatomic, assign) cpTimestamp collisionPersistence;
+
+/// Returns a pointer to the underlying cpSpace C struct
+@property(nonatomic, readonly) cpSpace *space;
+
+/**
+       The space's designated static body.
+       Collision shapes added to the body will automatically be marked as static shapes, and rigid bodies that come to rest while touching or jointed to this body will fall asleep.
+*/
+@property(nonatomic, readonly) ChipmunkBody *staticBody;
+
+/**
+       Retrieves the current (if you are in a callback from [ChipmunkSpace step:]) or most recent (outside of a [ChipmunkSpace step:] call) timestep.
+*/
+@property(nonatomic, readonly) cpFloat currentTimeStep;
+
+/**
+       Returns true if the space is currently executing a timestep.
+*/
+@property(nonatomic, readonly) BOOL isLocked;
+@property(nonatomic, readonly) BOOL locked __deprecated;
+
+/**
+       An object that this space is associated with. You can use this get a reference to your game state or controller object from within callbacks.
+       @attention Like most @c delegate properties this is a weak reference and does not call @c retain. This prevents reference cycles from occuring.
+*/
+@property(nonatomic, assign) id userData;
+
+/// Get the ChipmunkSpace object associciated with a cpSpace pointer.
+/// Undefined if the cpSpace wasn't created using Objective-Chipmunk.
++(ChipmunkSpace *)spaceFromCPSpace:(cpSpace *)space;
+
+/**
+  Set the default collision handler.
+  The default handler is used for all collisions when a specific collision handler cannot be found.
+  
+  The expected method selectors are as follows:
+       @code
+- (bool)begin:(cpArbiter *)arbiter space:(ChipmunkSpace*)space
+- (bool)preSolve:(cpArbiter *)arbiter space:(ChipmunkSpace*)space
+- (void)postSolve:(cpArbiter *)arbiter space:(ChipmunkSpace*)space
+- (void)separate:(cpArbiter *)arbiter space:(ChipmunkSpace*)space
+       @endcode
+*/
+- (void)setDefaultCollisionHandler:(id)delegate
+       begin:(SEL)begin
+       preSolve:(SEL)preSolve
+       postSolve:(SEL)postSolve
+       separate:(SEL)separate;
+
+/**
+  Set a collision handler to handle specific collision types.
+  The methods are called only when shapes with the specified collisionTypes collide.
+  
+  @c typeA and @c typeB should be the same object references set to ChipmunkShape.collisionType. They can be any uniquely identifying object.
+       Class and global NSString objects work well as collision types as they are easy to get a reference to and do not require you to allocate any objects.
+  
+  The expected method selectors are as follows:
+       @code
+- (bool)begin:(cpArbiter *)arbiter space:(ChipmunkSpace*)space
+- (bool)preSolve:(cpArbiter *)arbiter space:(ChipmunkSpace*)space
+- (void)postSolve:(cpArbiter *)arbiter space:(ChipmunkSpace*)space
+- (void)separate:(cpArbiter *)arbiter space:(ChipmunkSpace*)space
+       @endcode
+*/
+- (void)addCollisionHandler:(id)delegate
+       typeA:(cpCollisionType)a typeB:(cpCollisionType)b
+       begin:(SEL)begin
+       preSolve:(SEL)preSolve
+       postSolve:(SEL)postSolve
+       separate:(SEL)separate;
+
+
+/**
+  Add an object to the space.
+  This can be any object that implements the ChipmunkObject protocol.
+       This includes all the basic types such as ChipmunkBody, ChipmunkShape and ChipmunkConstraint as well as any composite game objects you may define that implement the protocol.
+       @warning This method may not be called from a collision handler callback. See smartAdd: or ChipmunkSpace.addPostStepCallback:selector:context: for information on how to do that.
+*/
+-(id)add:(NSObject<ChipmunkObject> *)obj;
+
+/**
+  Remove an object from the space.
+  This can be any object that implements the ChipmunkObject protocol.
+       This includes all the basic types such as ChipmunkBody, ChipmunkShape and ChipmunkConstraint as well as any composite game objects you may define that implement the protocol.
+       @warning This method may not be called from a collision handler callback. See smartRemove: or ChipmunkSpace.addPostStepCallback:selector:context: for information on how to do that.
+*/
+-(id)remove:(NSObject<ChipmunkObject> *)obj;
+
+/// Check if a space already contains a particular object:
+-(BOOL)contains:(NSObject<ChipmunkObject> *)obj;
+
+/// If the space is locked and it's unsafe to call add: it will call addPostStepAddition: instead.
+- (id)smartAdd:(NSObject<ChipmunkObject> *)obj;
+
+/// If the space is locked and it's unsafe to call remove: it will call addPostStepRemoval: instead.
+- (id)smartRemove:(NSObject<ChipmunkObject> *)obj;
+
+/// Handy utility method to add a border of collision segments around a box. See ChipmunkShape for more information on the other parameters.
+/// Returns an NSArray of the shapes. Since NSArray implements the ChipmunkObject protocol, you can use the [ChipmunkSpace remove:] method to remove the bounds.
+- (NSArray *)addBounds:(cpBB)bounds thickness:(cpFloat)radius
+       elasticity:(cpFloat)elasticity friction:(cpFloat)friction
+       filter:(cpShapeFilter)filter collisionType:(id)collisionType;
+
+
+/**
+  Define a callback to be run just before [ChipmunkSpace step:] finishes.
+  The main reason you want to define post-step callbacks is to get around the restriction that you cannot call the add/remove methods from a collision handler callback.
+       Post-step callbacks run right before the next (or current) call to ChipmunkSpace.step: returns when it is safe to add and remove objects.
+       You can only schedule one post-step callback per key value, this prevents you from accidentally removing an object twice. Registering a second callback for the same key is a no-op.
+  
+  The method signature of the method should be:
+  @code
+- (void)postStepCallback:(id)key</code></pre>
+       @endcode
+       
+  This makes it easy to call a removal method on your game controller to remove a game object that died or was destroyed as the result of a collision:
+  @code
+[space addPostStepCallback:gameController selector:@selector(remove:) key:gameObject];
+       @endcode
+       
+       @attention Not to be confused with post-solve collision handler callbacks.
+       @warning @c target and @c object cannot be retained by the ChipmunkSpace. If you need to release either after registering the callback, use autorelease to ensure that they won't be deallocated until after [ChipmunkSpace step:] returns.
+       @see ChipmunkSpace.addPostStepRemoval:
+*/
+- (BOOL)addPostStepCallback:(id)target selector:(SEL)selector key:(id)key;
+
+/// Block type used with [ChipmunkSpace addPostStepBlock:]
+typedef void (^ChipmunkPostStepBlock)(void);
+
+/// Same as [ChipmunkSpace addPostStepCallback:] but with a block. The block is copied.
+- (BOOL)addPostStepBlock:(ChipmunkPostStepBlock)block key:(id)key;
+
+/// Add the Chipmunk Object to the space at the end of the step.
+- (void)addPostStepAddition:(NSObject<ChipmunkObject> *)obj;
+
+/// Remove the Chipmunk Object from the space at the end of the step.
+- (void)addPostStepRemoval:(NSObject<ChipmunkObject> *)obj;
+
+/// Return an array of ChipmunkNearestPointQueryInfo objects for shapes within @c maxDistance of @c point.
+/// The point is treated as having the given group and layers.
+- (NSArray *)pointQueryAll:(cpVect)point maxDistance:(cpFloat)maxDistance filter:(cpShapeFilter)filter;
+
+/// Find the closest shape to a point that is within @c maxDistance of @c point.
+/// The point is treated as having the given layers and group.
+- (ChipmunkPointQueryInfo *)pointQueryNearest:(cpVect)point maxDistance:(cpFloat)maxDistance filter:(cpShapeFilter)filter;
+
+/// Return a NSArray of ChipmunkSegmentQueryInfo objects for all the shapes that overlap the segment. The objects are unsorted.
+- (NSArray *)segmentQueryAllFrom:(cpVect)start to:(cpVect)end radius:(cpFloat)radius filter:(cpShapeFilter)filter;
+
+/// Returns the first shape that overlaps the given segment. The segment is treated as having the given group and layers. 
+- (ChipmunkSegmentQueryInfo *)segmentQueryFirstFrom:(cpVect)start to:(cpVect)end radius:(cpFloat)radius filter:(cpShapeFilter)filter;
+
+/// Returns a NSArray of all shapes whose bounding boxes overlap the given bounding box. The box is treated as having the given group and layers. 
+- (NSArray *)bbQueryAll:(cpBB)bb filter:(cpShapeFilter)filter;
+
+/// Returns a NSArray of ChipmunkShapeQueryInfo objects for all the shapes that overlap @c shape.
+- (NSArray *)shapeQueryAll:(ChipmunkShape *)shape;
+
+/// Returns true if the shape overlaps anything in the space.
+- (BOOL)shapeTest:(ChipmunkShape *)shape;
+
+/// Get a copy of the list of all the bodies in the space.
+- (NSArray *)bodies;
+
+/// Get a copy of the list of all the shapes in the space
+- (NSArray *)shapes;
+
+/// Get a copy of the list of all the constraints in the space
+- (NSArray *)constraints;
+
+/// Update all the static shapes.
+- (void)reindexStatic;
+
+/// Update the collision info for a single shape.
+/// Can be used to update individual static shapes that were moved or active shapes that were moved that you want to query against.
+- (void)reindexShape:(ChipmunkShape *)shape;
+
+/// Update the collision info for all shapes attached to a body.
+- (void)reindexShapesForBody:(ChipmunkBody *)body;
+
+/// Step time forward. While variable timesteps may be used, a constant timestep will allow you to reduce CPU usage by using fewer iterations.
+- (void)step:(cpFloat)dt;
+
+@end
+
+
+/// ChipmunkHastySpace is an Objective-Chipmunk wrapper for cpHastySpace.
+/// Subclass this class instead of ChipmunkSpace if you want to enable the cpHastySpace optimizations.
+/// If ChipmunkHastySpace is linked correctly, calling [[ChipmunkSpace alloc] init] will actually return a ChipmunkHastySpace.
+@interface ChipmunkHastySpace : ChipmunkSpace
+
+/// Number of threads to use for the solver.
+///    Setting 0 will choose the thread count automatically (recommended).
+/// There is currently little benefit in using more than 2 threads.
+/// Defaults to 1.
+@property(nonatomic, assign) NSUInteger threads;
+
+@end
+
+
+//MARK: Misc
+
+/**
+       A macro that defines and initializes shape variables for you in a collision callback.
+       They are initialized in the order that they were defined in the collision handler associated with the arbiter.
+       If you defined the handler as:
+       
+       @code
+               [space addCollisionHandler:target typeA:foo typeB:bar ...]
+       @endcode
+       
+       You you will find that @code a->collision_type == 1 @endcode and @code b->collision_type == 2 @endcode.
+*/
+#define CHIPMUNK_ARBITER_GET_SHAPES(__arb__, __a__, __b__) ChipmunkShape *__a__, *__b__; { \
+       cpShape *__shapeA__, *__shapeB__; \
+       cpArbiterGetShapes(__arb__, &__shapeA__, &__shapeB__); \
+       __a__ = cpShapeGetUserData(__shapeA__); __b__ = cpShapeGetUserData(__shapeB__); \
+}
+
+#define CHIPMUNK_ARBITER_GET_BODIES(__arb__, __a__, __b__) ChipmunkBody *__a__, *__b__; { \
+       cpBody *__bodyA__, *__bodyB__; \
+       cpArbiterGetBodies(__arb__, &__bodyA__, &__bodyB__); \
+       __a__ = cpBodyGetUserData(__bodyA__); __b__ = cpBodyGetUserData(__bodyB__); \
+}
+
+
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkTileCache.h b/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ChipmunkTileCache.h
new file mode 100644 (file)
index 0000000..a6c79dc
--- /dev/null
@@ -0,0 +1,100 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
+#import "ChipmunkAutoGeometry.h"
+
+
+@class ChipmunkCachedTile;
+
+/// A tile cache enables an efficient means of updating a large deformable terrain.
+/// General usage would be to pass a rectangle covering the viewport to ensureRect:
+/// and calling markDirtyRect: each time a change is made that requires an area to be resampled.
+@interface ChipmunkAbstractTileCache : NSObject {
+@private
+       ChipmunkAbstractSampler *_sampler;
+       ChipmunkSpace *_space;
+       
+       cpFloat _tileSize;
+       cpFloat _samplesPerTile;
+       cpVect _tileOffset;
+       
+       NSUInteger _tileCount, _cacheSize;
+       cpSpatialIndex *_tileIndex;
+       ChipmunkCachedTile *_cacheHead, *_cacheTail;
+       
+       cpBB _ensuredBB;
+       bool _ensuredDirty;
+       
+       bool _marchHard;
+}
+
+/// Should the marching be hard or soft?
+/// See cpMarchHard() and cpMarchSoft() for more information.
+@property(nonatomic, assign) bool marchHard;
+
+/// Offset of the tile grid origin.
+@property(nonatomic, assign) cpVect tileOffset;
+
+/// The sampling function to use.
+@property(nonatomic, readonly) ChipmunkAbstractSampler *sampler;
+
+/// Create the cache from the given sampler, space to add the generated segments to,
+/// size of the tiles, and the number of samples for each tile.
+-(id)initWithSampler:(ChipmunkAbstractSampler *)sampler space:(ChipmunkSpace *)space tileSize:(cpFloat)tileSize samplesPerTile:(NSUInteger)samplesPerTile cacheSize:(NSUInteger)cacheSize;
+
+/// Clear out all the cached tiles to force a full regen.
+-(void)resetCache;
+
+/// Mark a region as needing an update.
+/// Geometry is not regenerated until ensureRect: is called.
+-(void)markDirtyRect:(cpBB)bounds;
+
+/// Ensure that the given rect has been fully generated and contains no dirty rects.
+-(void)ensureRect:(cpBB)bounds;
+
+/// Override this in a subclass to make custom polygon simplification behavior.
+/// Defaults to cpPolylineSimplifyCurves(polyline, 2.0f)
+-(cpPolyline *)simplify:(cpPolyline *)polyline;
+
+/// Override this method to construct the segment shapes.
+/// By default, it creates a 0 radius segment and sets 1.0 for friction and elasticity and nothing else.
+-(ChipmunkSegmentShape *)makeSegmentFor:(ChipmunkBody *)staticBody from:(cpVect)a to:(cpVect)b;
+
+@end
+
+
+/// Generic tile cache. Configurable enough to be useful for most uses.
+@interface ChipmunkBasicTileCache : ChipmunkAbstractTileCache {
+@private
+       cpFloat _simplifyThreshold;
+       
+       cpFloat _segmentRadius;
+       
+       cpFloat _segmentFriction;
+       cpFloat _segmentElasticity;
+       
+       cpShapeFilter _segmentFilter;
+       
+       cpCollisionType _segmentCollisionType;
+}
+
+/// Threshold value used by cpPolylineSimplifyCurves().
+@property(nonatomic, assign) cpFloat simplifyThreshold;
+
+/// Radius of the generated segments.
+@property(nonatomic, assign) cpFloat segmentRadius;
+
+/// Friction of the generated segments.
+@property(nonatomic, assign) cpFloat segmentFriction;
+
+/// Elasticity of the generated segments.
+@property(nonatomic, assign) cpFloat segmentElasticity;
+
+/// Collision filter of the generated segments.
+@property(nonatomic, assign) cpShapeFilter segmentFilter;
+
+/// Collision type of the generated segments.
+@property(nonatomic, assign) cpCollisionType segmentCollisionType;
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ObjectiveChipmunk.h b/dali-physics/third-party/chipmunk2d/objectivec/include/ObjectiveChipmunk/ObjectiveChipmunk.h
new file mode 100644 (file)
index 0000000..18e7ee2
--- /dev/null
@@ -0,0 +1,77 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#import <Foundation/Foundation.h>
+
+#if __has_feature(objc_arc)
+       #define CP_DATA_POINTER_TYPE __unsafe_unretained id
+       #define CP_GROUP_TYPE __unsafe_unretained id
+       #define CP_COLLISION_TYPE_TYPE __unsafe_unretained id
+#else
+       #define CP_DATA_POINTER_TYPE id
+       #define CP_GROUP_TYPE id
+       #define CP_COLLISION_TYPE_TYPE id
+#endif
+
+#ifdef CP_ALLOW_PRIVATE_ACCESS
+       #import "chipmunk/chipmunk_private.h"
+#else
+       #import "chipmunk/chipmunk.h"
+       #import "chipmunk/chipmunk_structs.h"
+#endif
+
+/**
+       Allows you to add composite objects to a space in a single method call.
+       The easiest way to implement the ChipmunkObject protocol is to add a @c chipmunkObjects instance variable with a type of @c NSArray* to your class,
+       create a synthesized property for it, and initialize it with the ChipmunkObjectFlatten() function.
+*/
+@protocol ChipmunkObject
+
+/// Returns a list of ChipmunkBaseObject objects.
+- (id <NSFastEnumeration>)chipmunkObjects;
+
+@end
+
+
+/// A category to have NSArray implement the ChipmunkObject protocol.
+/// They make for very easy containers.
+@interface NSArray(ChipmunkObject) <ChipmunkObject>
+@end
+
+
+@class ChipmunkSpace;
+
+/**
+       This protocol is implemented by objects that know how to add themselves to a space.
+       It's used internally as part of the ChipmunkObject protocol. You should never need to implement it yourself.
+*/
+@protocol ChipmunkBaseObject <ChipmunkObject>
+
+- (void)addToSpace:(ChipmunkSpace *)space;
+- (void)removeFromSpace:(ChipmunkSpace *)space;
+
+@end
+
+#import "ChipmunkBody.h"
+#import "ChipmunkShape.h"
+#import "ChipmunkConstraint.h"
+#import "ChipmunkSpace.h"
+#import "ChipmunkMultiGrab.h"
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkAutoGeometry.m b/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkAutoGeometry.m
new file mode 100644 (file)
index 0000000..640096f
--- /dev/null
@@ -0,0 +1,232 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#import <malloc/malloc.h>
+
+#import "ChipmunkAutoGeometry.h"
+
+@implementation ChipmunkPolyline
+
+-(id)initWithPolyline:(cpPolyline *)line
+{
+       if((self = [super init])){
+               _line = line;
+       }
+       
+       return self;
+}
+
+-(void)dealloc
+{
+       cpPolylineFree(_line);
+       
+       [super dealloc];
+}
+
++(ChipmunkPolyline *)fromPolyline:(cpPolyline *)line
+{
+       return [[[self alloc] initWithPolyline:line] autorelease];
+}
+
+-(bool)isClosed
+{
+       return cpPolylineIsClosed(_line);
+}
+
+-(cpFloat)area
+{
+       if(_area == 0.0 && [self isClosed]){
+               _area = cpAreaForPoly(_line->count - 1, _line->verts, 0.0);
+       }
+       
+       return _area;
+}
+
+-(cpVect)centroid
+{
+       cpAssertHard([self isClosed], "Cannot compute the centroid of a non-looped polyline.");
+       return cpCentroidForPoly(_line->count - 1, _line->verts);
+}
+
+-(cpFloat)momentForMass:(cpFloat)mass offset:(cpVect)offset
+{
+       cpAssertHard([self isClosed], "Cannot compute the moment of a non-looped polyline.");
+       return cpMomentForPoly(mass, _line->count - 1, _line->verts, offset, 0.0);
+}
+
+-(NSUInteger)count {return _line->count;}
+-(const cpVect *)verts {return _line->verts;}
+
+-(ChipmunkPolyline *)simplifyCurves:(cpFloat)tolerance
+{
+       return [ChipmunkPolyline fromPolyline:cpPolylineSimplifyCurves(_line, tolerance)];
+}
+
+-(ChipmunkPolyline *)simplifyVertexes:(cpFloat)tolerance
+{
+       return [ChipmunkPolyline fromPolyline:cpPolylineSimplifyVertexes(_line, tolerance)];
+}
+
+-(ChipmunkPolyline *)toConvexHull:(cpFloat)tolerance
+{
+       return [ChipmunkPolyline fromPolyline:cpPolylineToConvexHull(_line, tolerance)];
+}
+
+-(ChipmunkPolyline *)toConvexHull
+{
+       return [self toConvexHull:0.0];
+}
+
+-(ChipmunkPolylineSet *)toConvexHulls_BETA:(cpFloat)tolerance
+{
+       cpPolylineSet *set = cpPolylineConvexDecomposition_BETA(_line, tolerance);
+       ChipmunkPolylineSet *value = [ChipmunkPolylineSet fromPolylineSet:set];
+       cpPolylineSetFree(set, FALSE);
+       
+       return value;
+}
+
+-(NSArray *)asChipmunkSegmentsWithBody:(ChipmunkBody *)body radius:(cpFloat)radius offset:(cpVect)offset
+{
+       NSMutableArray *arr = [NSMutableArray arrayWithCapacity:_line->count];
+       
+       
+       cpVect a = cpvadd(_line->verts[0], offset);
+       for(int i=1; i<_line->count; i++){
+               cpVect b = cpvadd(_line->verts[i], offset);
+               [arr addObject:[ChipmunkSegmentShape segmentWithBody:body from:a to:b radius:radius]];
+               a = b;
+       }
+       
+       return arr;
+}
+
+-(ChipmunkPolyShape *)asChipmunkPolyShapeWithBody:(ChipmunkBody *)body transform:(cpTransform)transform radius:(cpFloat)radius
+{
+       cpAssertHard([self isClosed], "Cannot create a poly shape for a non-closed polyline.");
+       return [ChipmunkPolyShape polyWithBody:body count:_line->count - 1 verts:_line->verts transform:transform radius:radius];
+}
+
+@end
+
+
+
+@implementation ChipmunkPolylineSet
+
+-(id)initWithPolylineSet:(cpPolylineSet *)set
+{
+       if((self = [super init])){
+               _lines = [[NSMutableArray alloc] initWithCapacity:set->count];
+               for(int i=0; i<set->count; i++) [_lines addObject:[ChipmunkPolyline fromPolyline:set->lines[i]]];
+       }
+       
+       return self;
+}
+
+-(void)dealloc
+{
+       [_lines release];
+       
+       [super dealloc];
+}
+
++(ChipmunkPolylineSet *)fromPolylineSet:(cpPolylineSet *)set
+{
+       return [[[self alloc] initWithPolylineSet:set] autorelease];
+}
+
+-(NSUInteger)count {return _lines.count;}
+
+-(ChipmunkPolyline *)lineAtIndex:(NSUInteger)index
+{
+       return [_lines objectAtIndex:index];
+}
+
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len
+{
+       return [_lines countByEnumeratingWithState:state objects:stackbuf count:len];
+}
+
+@end
+
+
+
+@implementation ChipmunkAbstractSampler
+
+@synthesize marchThreshold = _marchThreshold;
+@synthesize sampleFunc = _sampleFunc;
+
+-(id)init {
+       @throw [NSException
+               exceptionWithName:NSInternalInconsistencyException
+               reason:[NSString stringWithFormat:@"Use designated initializer initWithSamplingFunction: to initialize a sampler."]
+               userInfo:nil
+       ];
+}
+
+-(id)initWithSamplingFunction:(cpMarchSampleFunc)sampleFunc
+{
+       if((self = [super init])){
+               _sampleFunc = sampleFunc;
+               _marchThreshold = 0.5;
+       }
+       
+       return self;
+}
+
+-(cpFloat)sample:(cpVect)pos
+{
+       return _sampleFunc(pos, self);
+}
+
+
+-(ChipmunkPolylineSet *)march:(cpBB)bb xSamples:(NSUInteger)xSamples ySamples:(NSUInteger)ySamples hard:(bool)hard
+{
+       cpPolylineSet set;
+       cpPolylineSetInit(&set);
+       
+       (hard ? cpMarchHard : cpMarchSoft)(
+               bb, xSamples, ySamples, _marchThreshold,
+               (cpMarchSegmentFunc)cpPolylineSetCollectSegment, &set,
+               _sampleFunc, self
+       );
+       
+       ChipmunkPolylineSet *value = [ChipmunkPolylineSet fromPolylineSet:&set];
+       
+       cpPolylineSetDestroy(&set, FALSE);
+       return value;
+}
+
+@end
+
+
+
+@implementation ChipmunkBlockSampler
+
+static cpFloat
+SampleFromBlock(cpVect point, ChipmunkBlockSampler *self)
+{
+       return self->_block(point);
+}
+
+-(id)initWithBlock:(ChipmunkMarchSampleBlock)block
+{
+       if((self = [super initWithSamplingFunction:(cpMarchSampleFunc)SampleFromBlock])){
+               _block = [block copy];
+       }
+       
+       return self;
+}
+
++(ChipmunkBlockSampler *)samplerWithBlock:(ChipmunkMarchSampleBlock)block
+{
+       return [[[self alloc] initWithBlock:block] autorelease];
+}
+
+-(void)dealloc
+{
+       [_block release];
+       [super dealloc];
+}
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkBody.m b/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkBody.m
new file mode 100644 (file)
index 0000000..95dbadc
--- /dev/null
@@ -0,0 +1,205 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
+
+@interface ChipmunkSpace(DoubleDispatch)
+
+- (ChipmunkBody *)addBody:(ChipmunkBody *)obj;
+- (ChipmunkBody *)removeBody:(ChipmunkBody *)obj;
+
+@end
+
+@implementation ChipmunkBody {
+       cpBody _body;
+       id _userData;
+}
+
+// MARK: Integration Helpers
+
+-(void)updateVelocity:(cpFloat)dt gravity:(cpVect)gravity damping:(cpFloat)damping
+{
+       cpBodyUpdateVelocity(&_body, gravity, damping, dt);
+}
+
+-(void)updatePosition:(cpFloat)dt
+{
+       cpBodyUpdatePosition(&_body, dt);
+}
+
+static void
+VelocityFunction
+(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
+{
+       [(ChipmunkBody *)body->userData updateVelocity:dt gravity:gravity damping:damping];
+}
+
+static void
+PositionFunction
+(cpBody *body, cpFloat dt)
+{
+       [(ChipmunkBody *)body->userData updatePosition:dt];
+}
+
+// Check if the method was overridden.
+// No reason to add the extra method overhead if it's not needed.
+-(BOOL)methodIsOverriden:(SEL)selector
+{
+       return ([self methodForSelector:selector] != [[ChipmunkBody class] instanceMethodForSelector:selector]);
+}
+
+// MARK: Constructors
+
++(ChipmunkBody *)bodyFromCPBody:(cpBody *)body
+{      
+       ChipmunkBody *obj = body->userData;
+       cpAssertHard([obj isKindOfClass:[ChipmunkBody class]], "'body->data' is not a pointer to a ChipmunkBody object.");
+       
+       return obj;
+}
+
++ (id)bodyWithMass:(cpFloat)mass andMoment:(cpFloat)moment
+{
+       return [[[self alloc] initWithMass:mass andMoment:moment] autorelease];
+}
+
++ (id)staticBody
+{
+       ChipmunkBody *body = [[self alloc] initWithMass:0.0f andMoment:0.0f];
+       body.type = CP_BODY_TYPE_STATIC;
+       
+       return [body autorelease];
+}
+
++ (id)kinematicBody
+{
+       ChipmunkBody *body = [[self alloc] initWithMass:0.0f andMoment:0.0f];
+       body.type = CP_BODY_TYPE_KINEMATIC;
+       
+       return [body autorelease];
+}
+
+- (id)initWithMass:(cpFloat)mass andMoment:(cpFloat)moment
+{
+       if((self = [super init])){
+               cpBodyInit(&_body, mass, moment);
+               _body.userData = self;
+               
+               // Setup integration callbacks if necessary.
+               if([self methodIsOverriden:@selector(updateVelocity:gravity:damping:)]){
+                       _body.velocity_func = VelocityFunction;
+               }
+               
+               if([self methodIsOverriden:@selector(updatePosition:)]){
+                       _body.position_func = PositionFunction;
+               }
+       }
+       
+       return self;
+}
+
+- (void) dealloc
+{
+       cpBodyDestroy(&_body);
+       [super dealloc];
+}
+
+- (cpTransform)transform {return _body.transform;}
+- (cpBody *)body {return &_body;}
+
+
+@synthesize userData = _userData;
+
+// accessor macros
+#define getter(type, lower, upper) \
+- (type)lower {return cpBodyGet##upper(&_body);}
+#define setter(type, lower, upper) \
+- (void)set##upper:(type)value {cpBodySet##upper(&_body, value);};
+#define both(type, lower, upper) \
+getter(type, lower, upper) \
+setter(type, lower, upper)
+
+
+both(cpBodyType, type, Type)
+both(cpFloat, mass, Mass)
+both(cpFloat, moment, Moment)
+both(cpVect, centerOfGravity, CenterOfGravity)
+both(cpVect, position, Position)
+both(cpVect, velocity, Velocity)
+both(cpVect, force, Force)
+both(cpFloat, angle, Angle)
+both(cpFloat, angularVelocity, AngularVelocity)
+both(cpFloat, torque, Torque)
+
+-(ChipmunkSpace *)space {
+       cpSpace *space = cpBodyGetSpace(&_body);
+       return (ChipmunkSpace *)(space ? cpSpaceGetUserData(space) : nil);
+}
+
+- (cpFloat)kineticEnergy {return cpBodyKineticEnergy(&_body);}
+
+- (cpVect)localToWorld:(cpVect)v {return cpBodyLocalToWorld(&_body, v);}
+- (cpVect)worldToLocal:(cpVect)v {return cpBodyWorldToLocal(&_body, v);}
+
+- (cpVect)velocityAtLocalPoint:(cpVect)p {return cpBodyGetVelocityAtLocalPoint(&_body, p);}
+- (cpVect)velocityAtWorldPoint:(cpVect)p {return cpBodyGetVelocityAtWorldPoint(&_body, p);}
+
+- (void)applyForce:(cpVect)force atLocalPoint:(cpVect)point {cpBodyApplyForceAtLocalPoint(&_body, force, point);}
+- (void)applyForce:(cpVect)force atWorldPoint:(cpVect)point {cpBodyApplyForceAtWorldPoint(&_body, force, point);}
+- (void)applyImpulse:(cpVect)impulse atLocalPoint:(cpVect)point {cpBodyApplyImpulseAtLocalPoint(&_body, impulse, point);}
+- (void)applyImpulse:(cpVect)impulse atWorldPoint:(cpVect)point {cpBodyApplyImpulseAtWorldPoint(&_body, impulse, point);}
+
+- (bool)isSleeping {return cpBodyIsSleeping(&_body);}
+
+- (void)activate {cpBodyActivate(&_body);}
+- (void)activateStatic:(ChipmunkShape *)filter {cpBodyActivateStatic(&_body, filter.shape);}
+- (void)sleepWithGroup:(ChipmunkBody *)group {cpBodySleepWithGroup(&_body, group.body);}
+- (void)sleep {cpBodySleep(&_body);}
+
+- (NSArray *)chipmunkObjects {return [NSArray arrayWithObject:self];}
+- (void)addToSpace:(ChipmunkSpace *)space {[space addBody:self];}
+- (void)removeFromSpace:(ChipmunkSpace *)space {[space removeBody:self];}
+
+static void PushShape(cpBody *ignored, cpShape *shape, NSMutableArray *arr){[arr addObject:shape->userData];}
+- (NSArray *)shapes
+{
+       NSMutableArray *arr = [NSMutableArray array];
+       cpBodyEachShape(&_body, (cpBodyShapeIteratorFunc)PushShape, arr);
+       
+       return arr;
+}
+
+static void PushConstraint(cpBody *ignored, cpConstraint *constraint, NSMutableArray *arr){[arr addObject:constraint->userData];}
+- (NSArray *)constraints
+{
+       NSMutableArray *arr = [NSMutableArray array];
+       cpBodyEachConstraint(&_body, (cpBodyConstraintIteratorFunc)PushConstraint, arr);
+       
+       return arr;
+}
+
+static void CallArbiterBlock(cpBody *body, cpArbiter *arbiter, ChipmunkBodyArbiterIteratorBlock block){block(arbiter);}
+- (void)eachArbiter:(ChipmunkBodyArbiterIteratorBlock)block
+{
+       cpBodyEachArbiter(&_body, (cpBodyArbiterIteratorFunc)CallArbiterBlock, block);
+}
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkConstraint.m b/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkConstraint.m
new file mode 100644 (file)
index 0000000..74ebff0
--- /dev/null
@@ -0,0 +1,481 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
+
+@interface ChipmunkSpace(DoubleDispatch)
+
+- (ChipmunkConstraint *)addConstraint:(ChipmunkConstraint *)obj;
+- (ChipmunkConstraint *)removeConstraint:(ChipmunkConstraint *)obj;
+
+@end
+
+@implementation ChipmunkConstraint
+
+@synthesize userData = _userData;
+
++(ChipmunkConstraint *)constraintFromCPConstraint:(cpConstraint *)constraint
+{      
+       ChipmunkConstraint *obj = constraint->userData;
+       cpAssertHard([obj isKindOfClass:[ChipmunkConstraint class]], "'constraint->data' is not a pointer to a ChipmunkConstraint object.");
+       
+       return obj;
+}
+
+- (void) dealloc
+{
+       cpConstraint *constraint = self.constraint;
+       [self.bodyA release];
+       [self.bodyB release];
+       cpConstraintDestroy(constraint);
+       
+       [super dealloc];
+}
+
+- (cpConstraint *)constraint
+{
+       [self doesNotRecognizeSelector:_cmd];
+       return nil;
+}
+
+// accessor macros
+#define getter(type, lower, upper) \
+- (type)lower {return cpConstraintGet##upper(self.constraint);}
+#define setter(type, lower, upper) \
+- (void)set##upper:(type)value {cpConstraintSet##upper(self.constraint, value);};
+#define both(type, lower, upper) \
+getter(type, lower, upper) \
+setter(type, lower, upper)
+
+both(cpFloat, maxForce, MaxForce)
+both(cpFloat, errorBias, ErrorBias)
+both(cpFloat, maxBias, MaxBias)
+both(BOOL, collideBodies, CollideBodies)
+
+-(cpFloat)impulse {return cpConstraintGetImpulse(self.constraint);}
+
+-(ChipmunkSpace *)space {
+       cpSpace *space = cpConstraintGetSpace(self.constraint);
+       return (ChipmunkSpace *)(space ? cpSpaceGetUserData(space) : nil);
+}
+
+- (ChipmunkBody *)bodyA
+{
+       cpBody *body = cpConstraintGetBodyA(self.constraint);
+       return (body ? cpBodyGetUserData(body) : nil);
+}
+
+//- (void)setBodyA:(ChipmunkBody *)value {
+//     if(self.bodyA != value){
+//             [self.bodyA release];
+//             self.constraint->a = [[value retain] body];
+//     }
+//}
+
+- (ChipmunkBody *)bodyB
+{
+       cpBody *body = cpConstraintGetBodyB(self.constraint);
+       return (body ? cpBodyGetUserData(body) : nil);
+}
+
+//- (void)setBodyB:(ChipmunkBody *)value {
+//     if(self.bodyB != value){
+//             [self.bodyB release];
+//             self.constraint->b = [[value retain] body];
+//     }
+//}
+
+- (NSArray *)chipmunkObjects {return [NSArray arrayWithObject:self];}
+- (void)addToSpace:(ChipmunkSpace *)space {[space addConstraint:self];}
+- (void)removeFromSpace:(ChipmunkSpace *)space {[space removeConstraint:self];}
+
+-(void)preSolve:(ChipmunkSpace *)space {}
+-(void)postSolve:(ChipmunkSpace *)space {}
+
+// MARK: Callbacks
+static void
+PreSolve(cpConstraint *constraint, cpSpace *space)
+{
+       [(ChipmunkConstraint *)constraint->userData preSolve:(ChipmunkSpace *)space->userData];
+}
+
+static void
+PostSolve(cpConstraint *constraint, cpSpace *space)
+{
+       [(ChipmunkConstraint *)constraint->userData postSolve:(ChipmunkSpace *)space->userData];
+}
+
+// Check if the method was overridden.
+// No reason to add the extra method overhead if it's not needed.
+-(BOOL)methodIsOverriden:(SEL)selector
+{
+       return ([self methodForSelector:selector] != [[ChipmunkConstraint class] instanceMethodForSelector:selector]);
+}
+
+-(void)setupCallbacks
+{
+       if([self methodIsOverriden:@selector(preSolve:)]){
+               cpConstraintSetPreSolveFunc(self.constraint, PreSolve);
+       }
+       
+       if([self methodIsOverriden:@selector(postSolve:)]){
+               cpConstraintSetPostSolveFunc(self.constraint, PostSolve);
+       }
+}
+
+@end
+
+// accessor macros
+#define getter2(type, struct, lower, upper) \
+- (type)lower {return struct##Get##upper((cpConstraint *)&_constraint);}
+#define setter2(type, struct, lower, upper) \
+- (void)set##upper:(type)value {struct##Set##upper((cpConstraint *)&_constraint, value);};
+#define both2(type, struct, lower, upper) \
+getter2(type, struct, lower, upper) \
+setter2(type, struct, lower, upper)
+
+
+@implementation ChipmunkPinJoint {
+       cpPinJoint _constraint;
+}
+
++ (id)pinJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b anchorA:anchorA anchorB:anchorB] autorelease];
+}
+
+- (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB
+{
+       if((self = [super init])){
+               [a retain];
+               [b retain];
+               cpPinJointInit(&_constraint, a.body, b.body, anchorA, anchorB);
+               self.constraint->userData = self;
+               
+               [self setupCallbacks];
+       }
+       
+       return self;
+}
+
+both2(cpVect, cpPinJoint, anchorA, AnchorA)
+both2(cpVect, cpPinJoint, anchorB, AnchorB)
+both2(cpFloat, cpPinJoint, dist, Dist)
+
+@end
+
+
+@implementation ChipmunkSlideJoint {
+       cpSlideJoint _constraint;
+}
+
++ (id)slideJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB min:(cpFloat)min max:(cpFloat)max
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b anchorA:anchorA anchorB:anchorB min:min max:max] autorelease];
+}
+
+- (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB min:(cpFloat)min max:(cpFloat)max
+{
+       if((self = [super init])){
+               [a retain];
+               [b retain];
+               cpSlideJointInit(&_constraint, a.body, b.body, anchorA, anchorB, min, max);
+               self.constraint->userData = self;
+               
+               [self setupCallbacks];
+       }
+       
+       return self;
+}
+
+both2(cpVect, cpSlideJoint, anchorA, AnchorA)
+both2(cpVect, cpSlideJoint, anchorB, AnchorB)
+both2(cpFloat, cpSlideJoint, min, Min)
+both2(cpFloat, cpSlideJoint, max, Max)
+
+@end
+
+
+@implementation ChipmunkPivotJoint {
+       cpPivotJoint _constraint;
+}
+
++ (id)pivotJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b anchorA:anchorA anchorB:anchorB] autorelease];
+}
+
++ (id)pivotJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b pivot:(cpVect)pivot
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b pivot:pivot] autorelease];
+}
+
+- (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB
+{
+       if((self = [super init])){
+               [a retain];
+               [b retain];
+               cpPivotJointInit(&_constraint, a.body, b.body, anchorA, anchorB);
+               self.constraint->userData = self;
+               
+               [self setupCallbacks];
+       }
+       
+       return self;
+}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b pivot:(cpVect)pivot
+{
+       return [self initWithBodyA:a bodyB:b anchorA:[a worldToLocal:pivot] anchorB:[b worldToLocal:pivot]];
+}
+
+both2(cpVect, cpPivotJoint, anchorA, AnchorA)
+both2(cpVect, cpPivotJoint, anchorB, AnchorB)
+
+@end
+
+
+@implementation ChipmunkGrooveJoint {
+       cpGrooveJoint _constraint;
+}
+
++ (id)grooveJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b grooveA:(cpVect)grooveA grooveB:(cpVect)grooveB anchorB:(cpVect)anchorB
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b grooveA:grooveA grooveB:grooveB anchorB:anchorB] autorelease];
+}
+
+- (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b grooveA:(cpVect)grooveA grooveB:(cpVect)grooveB anchorB:(cpVect)anchorB
+{
+       if((self = [super init])){
+               [a retain];
+               [b retain];
+               cpGrooveJointInit(&_constraint, a.body, b.body, grooveA, grooveB, anchorB);
+               self.constraint->userData = self;
+               
+               [self setupCallbacks];
+       }
+       
+       return self;
+}
+
+both2(cpVect, cpGrooveJoint, grooveA, GrooveA)
+both2(cpVect, cpGrooveJoint, grooveB, GrooveB)
+both2(cpVect, cpGrooveJoint, anchorB, AnchorB)
+
+@end
+
+
+@implementation ChipmunkDampedSpring {
+       cpDampedSpring _constraint;
+}
+
++ (id)dampedSpringWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB restLength:(cpFloat)restLength stiffness:(cpFloat)stiffness damping:(cpFloat)damping
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b anchorA:anchorA anchorB:anchorB restLength:restLength stiffness:stiffness damping:damping] autorelease];
+}
+
+- (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB restLength:(cpFloat)restLength stiffness:(cpFloat)stiffness damping:(cpFloat)damping
+{
+       if((self = [super init])){
+               [a retain];
+               [b retain];
+               cpDampedSpringInit(&_constraint, a.body, b.body, anchorA, anchorB, restLength, stiffness, damping);
+               self.constraint->userData = self;
+               
+               [self setupCallbacks];
+       }
+       
+       return self;
+}
+
+both2(cpVect, cpDampedSpring, anchorA, AnchorA)
+both2(cpVect, cpDampedSpring, anchorB, AnchorB)
+both2(cpFloat, cpDampedSpring, restLength, RestLength)
+both2(cpFloat, cpDampedSpring, stiffness, Stiffness)
+both2(cpFloat, cpDampedSpring, damping, Damping)
+
+@end
+
+
+@implementation ChipmunkDampedRotarySpring {
+       cpDampedRotarySpring _constraint;
+}
+
++ (id)dampedRotarySpringWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b restAngle:(cpFloat)restAngle stiffness:(cpFloat)stiffness damping:(cpFloat)damping
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b restAngle:restAngle stiffness:stiffness damping:damping] autorelease];
+}
+
+- (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b restAngle:(cpFloat)restAngle stiffness:(cpFloat)stiffness damping:(cpFloat)damping
+{
+       if((self = [super init])){
+               [a retain];
+               [b retain];
+               cpDampedRotarySpringInit(&_constraint, a.body, b.body, restAngle, stiffness, damping);
+               self.constraint->userData = self;
+               
+               [self setupCallbacks];
+       }
+       
+       return self;
+}
+
+both2(cpFloat, cpDampedRotarySpring, restAngle, RestAngle)
+both2(cpFloat, cpDampedRotarySpring, stiffness, Stiffness)
+both2(cpFloat, cpDampedRotarySpring, damping, Damping)
+
+@end
+
+
+@implementation ChipmunkRotaryLimitJoint {
+       cpRotaryLimitJoint _constraint;
+}
+
++ (id)rotaryLimitJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b min:(cpFloat)min max:(cpFloat)max
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b min:min max:max] autorelease];
+}
+
+- (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b min:(cpFloat)min max:(cpFloat)max
+{
+       if((self = [super init])){
+               [a retain];
+               [b retain];
+               cpRotaryLimitJointInit(&_constraint, a.body, b.body, min, max);
+               self.constraint->userData = self;
+               
+               [self setupCallbacks];
+       }
+       
+       return self;
+}
+
+both2(cpFloat, cpRotaryLimitJoint, min, Min)
+both2(cpFloat, cpRotaryLimitJoint, max, Max)
+
+@end
+
+
+@implementation ChipmunkSimpleMotor {
+       cpSimpleMotor _constraint;
+}
+
++ (id)simpleMotorWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b rate:(cpFloat)rate
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b rate:rate] autorelease];
+}
+
+- (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b rate:(cpFloat)rate
+{
+       if((self = [super init])){
+               [a retain];
+               [b retain];
+               cpSimpleMotorInit(&_constraint, a.body, b.body, rate);
+               self.constraint->userData = self;
+               
+               [self setupCallbacks];
+       }
+       
+       return self;
+}
+
+both2(cpFloat, cpSimpleMotor, rate, Rate)
+
+@end
+
+
+@implementation ChipmunkGearJoint {
+       cpGearJoint _constraint;
+}
+
++ (id)gearJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratio:(cpFloat)ratio
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b phase:phase ratio:ratio] autorelease];
+}
+
+- (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratio:(cpFloat)ratio
+{
+       if((self = [super init])){
+               [a retain];
+               [b retain];
+               cpGearJointInit(&_constraint, a.body, b.body, phase, ratio);
+               self.constraint->userData = self;
+               
+               [self setupCallbacks];
+       }
+       
+       return self;
+}
+
+both2(cpFloat, cpGearJoint, phase, Phase)
+both2(cpFloat, cpGearJoint, ratio, Ratio)
+
+@end
+
+
+@implementation ChipmunkRatchetJoint {
+       cpRatchetJoint _constraint;
+}
+
++ (id)ratchetJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratchet:(cpFloat)ratchet
+{
+       return [[[self alloc] initWithBodyA:a bodyB:b phase:phase ratchet:ratchet] autorelease];
+}
+
+- (cpConstraint *)constraint {return (cpConstraint *)&_constraint;}
+
+- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b phase:(cpFloat)phase ratchet:(cpFloat)ratchet
+{
+       if((self = [super init])){
+               [a retain];
+               [b retain];
+               cpRatchetJointInit(&_constraint, a.body, b.body, phase, ratchet);
+               self.constraint->userData = self;
+               
+               [self setupCallbacks];
+       }
+       
+       return self;
+}
+
+both2(cpFloat, cpRatchetJoint, angle, Angle)
+both2(cpFloat, cpRatchetJoint, phase, Phase)
+both2(cpFloat, cpRatchetJoint, ratchet, Ratchet)
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkImageSampler.m b/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkImageSampler.m
new file mode 100644 (file)
index 0000000..61be81e
--- /dev/null
@@ -0,0 +1,233 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+//
+//  ChipmunkImageSampler.m
+//  DeformableChipmunk
+//
+//  Created by Scott Lembcke on 8/26/11.
+//  Copyright 2011 __MyCompanyName__. All rights reserved.
+//
+
+#import <TargetConditionals.h>
+
+#if TARGET_OS_IPHONE == 1
+       #import <ImageIO/ImageIO.h>
+#endif
+
+#import "ChipmunkImageSampler.h"
+
+@implementation ChipmunkBitmapSampler
+
+@synthesize width = _width, height = _height, bytesPerPixel = _bytesPerPixel, component = _component, pixelData = _pixelData, outputRect = _outputRect;
+
+// Much faster than (int)floor(f)
+// Profiling showed floor() to be a sizable performance hog
+static inline int
+floor_int(cpFloat f)
+{
+       int i = (int)f;
+       return (f < 0.0f && f != i ? i - 1 : i);
+}
+
+// TODO finish this?
+//static inline cpFloat
+//SampleFunc4444(cpVect point, ChipmunkImageSampler *self)
+//{
+//     int x = (int)point.x;
+//     int y = (int)point.y - (self->_flip ? self->_height - 1 : 0);
+//     
+//     int com = self->_component;
+//     int byte = self->_pixels[y*self->_stride + x*self->_bytesPerPixel + com/2];
+//     int value = 
+//     return (cpFloat)(byte>>())/15.0;
+//}
+
+static cpFloat
+SampleFunc8Clamp(cpVect point, ChipmunkBitmapSampler *self)
+{
+       unsigned long w = self->_width;
+       unsigned long h = self->_height;
+       
+       cpBB bb = self->_outputRect;
+       cpVect clamped = cpBBClampVect(bb, point);
+       
+       unsigned long x = floor_int((w - 1)*(clamped.x - bb.l)/(bb.r - bb.l) + 0.5);
+       unsigned long y = floor_int((h - 1)*(clamped.y - bb.b)/(bb.t - bb.b) + 0.5);
+       
+       if(self->_flip) y = h - 1 - y;
+       
+//     printf("(%6.2f, %6.2f) -> (% 4d, % 4d) : %d\n", point.x, point.y, x, y, self->_pixels[y*self->_stride + x*self->_bytesPerPixel + self->_component]);
+       return (cpFloat)self->_pixels[y*self->_stride + x*self->_bytesPerPixel + self->_component]/255.0;
+}
+
+static cpFloat
+SampleFunc8Border(cpVect point, ChipmunkBitmapSampler *self)
+{
+       unsigned long w = self->_width;
+       unsigned long h = self->_height;
+       
+       cpBB bb = self->_outputRect;
+       if(cpBBContainsVect(bb, point)){
+               unsigned long x = floor_int((w - 1)*(point.x - bb.l)/(bb.r - bb.l) + 0.5);
+               unsigned long y = floor_int((h - 1)*(point.y - bb.b)/(bb.t - bb.b) + 0.5);
+               
+               if(self->_flip) y = h - 1 - y;
+               
+//             printf("(%6.2f, %6.2f) -> (% 4d, % 4d)\n", point.x, point.y, x, y);
+               return (cpFloat)self->_pixels[y*self->_stride + x*self->_bytesPerPixel + self->_component]/255.0;
+       } else {
+               return self->_borderValue;
+       }
+}
+
+-(id)initWithWidth:(NSUInteger)width height:(NSUInteger)height stride:(NSUInteger)stride bytesPerPixel:(NSUInteger)bytesPerPixel component:(NSUInteger)component flip:(bool)flip pixelData:(NSData *)pixelData
+{
+       if((self = [super initWithSamplingFunction:(cpMarchSampleFunc)SampleFunc8Clamp])){
+               _width = width;
+               _height = height;
+               _stride = stride;
+               
+               _bytesPerPixel = bytesPerPixel;
+               _component = component;
+               
+               _flip = flip;
+               _pixelData = [pixelData retain];
+               _pixels = [pixelData bytes];
+               
+               _outputRect = cpBBNew(0.5, 0.5, self.width - 0.5, self.height - 0.5);
+       }
+
+       return self;
+}
+
+
+- (void)dealloc
+{
+       [_pixelData release];
+       
+       [super dealloc];
+}
+
+-(void)setBorderRepeat
+{
+       _sampleFunc = (cpMarchSampleFunc)SampleFunc8Clamp;
+}
+
+-(void)setBorderValue:(cpFloat)borderValue
+{
+       _sampleFunc = (cpMarchSampleFunc)SampleFunc8Border;
+       _borderValue = borderValue;
+}
+
+static cpBB
+BorderedBB(cpBB bb, NSUInteger width, NSUInteger height)
+{
+       cpFloat xBorder = (bb.r - bb.l)/(cpFloat)(width - 1);
+       cpFloat yBorder = (bb.t - bb.b)/(cpFloat)(height - 1);
+       
+       return cpBBNew(bb.l - xBorder, bb.b - yBorder, bb.r + xBorder, bb.t + yBorder);
+}
+
+-(ChipmunkPolylineSet *)marchAllWithBorder:(bool)bordered hard:(bool)hard
+{
+       NSUInteger width = self.width;
+       NSUInteger height = self.height;
+       cpBB bb = self.outputRect;
+       
+       if(bordered){
+               return [self march:BorderedBB(bb, width, height) xSamples:width+2 ySamples:height+2 hard:hard];
+       } else {
+               return [self march:bb xSamples:width ySamples:height hard:hard];
+       }
+}
+
+@end
+
+
+
+@implementation ChipmunkCGContextSampler
+
+@synthesize context = _context;
+
+-(NSMutableData *)pixelData {return (NSMutableData *)super.pixelData;}
+
+-(id)initWithWidth:(unsigned long)width height:(unsigned long)height colorSpace:(CGColorSpaceRef)colorSpace bitmapInfo:(CGBitmapInfo)bitmapInfo component:(NSUInteger)component
+{
+       // Need to create a context to get info about the context.
+       // If you let the context allocate it's own memory it seems to move it around. O_o
+       CGContextRef temp = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, bitmapInfo);
+       cpAssertHard(temp, "Failed to create temporary CGBitmapContext");
+       
+       unsigned long bpc = CGBitmapContextGetBitsPerComponent(temp);
+       unsigned long bpp = CGBitmapContextGetBitsPerPixel(temp)/8;
+       cpAssertHard(bpc == 8, "Cannot handle non-8bit-per-pixel bitmap data!");
+       
+       CGContextRelease(temp); 
+       
+       unsigned long stride = width*bpp;
+       NSMutableData *pixelData = [NSMutableData dataWithLength:stride*height];
+       _context = CGBitmapContextCreate([pixelData mutableBytes], width, height, bpc, stride, colorSpace, bitmapInfo);
+       
+       return [self initWithWidth:width height:height stride:stride bytesPerPixel:bpp component:component flip:TRUE pixelData:pixelData];
+}
+
+-(void)dealloc
+{
+       CGContextRelease(_context);
+       
+       [super dealloc];
+}
+
+@end
+
+
+
+@implementation ChipmunkImageSampler
+
++(CGImageRef)loadImage:(NSURL *)url
+{
+       CGImageSourceRef image_source = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
+       CGImageRef image = CGImageSourceCreateImageAtIndex(image_source, 0, NULL);
+       cpAssertHard(image, "Image %s could not be loaded.", [[url description] UTF8String]);
+       
+       CFRelease(image_source);
+       return image;
+}
+
+-(id)initWithImage:(CGImageRef)image isMask:(bool)isMask contextWidth:(NSUInteger)width contextHeight:(NSUInteger)height
+{
+       if(width == 0) width = CGImageGetWidth(image);
+       if(height == 0)  height = CGImageGetHeight(image);
+       
+       CGColorSpaceRef colorSpace = (isMask ? CGColorSpaceCreateDeviceGray() : NULL);
+       CGBitmapInfo bitmapInfo = (CGBitmapInfo)(isMask ? kCGImageAlphaNone : kCGImageAlphaOnly);
+       
+       if((self = [super initWithWidth:width height:height colorSpace:colorSpace bitmapInfo:bitmapInfo component:0])){
+               CGContextDrawImage(self.context, CGRectMake(0, 0, width, height), image);
+       }
+       
+       CGColorSpaceRelease(colorSpace);
+       
+       return self;
+}
+
+-(id)initWithImageFile:(NSURL *)url isMask:(bool)isMask
+{
+       CGImageRef image = [[self class] loadImage:url];
+       unsigned long width = CGImageGetWidth(image);
+       unsigned long height = CGImageGetHeight(image);
+       
+       self = [self initWithImage:image isMask:isMask contextWidth:width contextHeight:height];
+       
+       CGImageRelease(image);
+       
+       return self;
+}
+
++(ChipmunkImageSampler *)samplerWithImageFile:(NSURL *)url isMask:(bool)isMask
+{
+       return [[[self alloc] initWithImageFile:url     isMask:isMask] autorelease];
+}
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkMultiGrab.m b/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkMultiGrab.m
new file mode 100644 (file)
index 0000000..9d4927d
--- /dev/null
@@ -0,0 +1,264 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#import "ChipmunkMultiGrab.h"
+
+
+// A constraint subclass that tracks a grab point
+@interface ChipmunkGrab() <ChipmunkObject>
+
+@property(nonatomic, readwrite) cpVect pos;
+@property(nonatomic, readonly) NSArray *chipmunkObjects;
+
+@end
+
+
+@implementation ChipmunkGrab
+
+@synthesize pos = _pos;
+@synthesize chipmunkObjects = _chipmunkObjects;
+@synthesize grabbedShape = _grabbedShape;
+@synthesize data = _data;
+
+static void 
+GrabPreSolve(cpConstraint *constraint, cpSpace *space)
+{
+       cpBody *grabBody = cpConstraintGetBodyA(constraint);
+       ChipmunkGrab *grab = [ChipmunkConstraint constraintFromCPConstraint:constraint].userData;
+       cpFloat dt = cpSpaceGetCurrentTimeStep(space);
+       cpFloat coef = cpfpow(grab->_smoothing, dt);
+       
+       // Smooth out the mouse position.
+       cpVect pos = cpvlerp(grab->_pos, cpBodyGetPosition(grabBody), coef);
+       cpBodySetVelocity(grabBody, cpvmult(cpvsub(pos, cpBodyGetPosition(grabBody)), 1.0/dt));
+//     cpBodySetPosition(grabBody, pos);
+}
+
+// Body will be nil if no object was grabbed.
+-(id)initWithMultiGrab:(ChipmunkMultiGrab *)multiGrab pos:(cpVect)pos nearest:(cpVect)nearest
+       body:(ChipmunkBody *)body grabbedShape:(ChipmunkShape *)grabbedShape
+       chipmunkObjects:(NSArray *)chipmunkObjects
+{
+       ChipmunkBody *grabBody = [ChipmunkBody kinematicBody];
+       grabBody.position = pos;
+       // TODO the repeated appending is a little silly here.
+       chipmunkObjects = [chipmunkObjects arrayByAddingObject:grabBody];
+       
+       if((self = [super init])){
+               _pos = pos;
+               _smoothing = multiGrab.smoothing;
+               _grabbedShape = grabbedShape;
+               
+               if(body){
+                       ChipmunkPivotJoint *pivot = [ChipmunkPivotJoint pivotJointWithBodyA:grabBody bodyB:body anchorA:cpvzero anchorB:[body worldToLocal:nearest]];
+                       pivot.maxForce = multiGrab.grabForce;
+                       pivot.userData = self;
+                       cpConstraintSetPreSolveFunc(pivot.constraint, GrabPreSolve);
+                       chipmunkObjects = [chipmunkObjects arrayByAddingObject:pivot];
+                       
+                       if(grabbedShape){
+                               cpFloat frictionForce = multiGrab.grabFriction;
+                               if(frictionForce > 0.0 && (1.0/body.mass + 1.0/grabBody.mass != 0.0)){
+                                       ChipmunkPivotJoint *friction = [ChipmunkPivotJoint pivotJointWithBodyA:grabBody bodyB:body anchorA:cpvzero anchorB:[body worldToLocal:nearest]];
+                                       friction.maxForce = frictionForce;
+                                       friction.maxBias = 0.0;
+                                       chipmunkObjects = [chipmunkObjects arrayByAddingObject:friction];
+                               }
+                               
+                               cpFloat rotaryFriction = multiGrab.grabRotaryFriction;
+                               if(rotaryFriction > 0.0 && (1.0/body.moment + 1.0/grabBody.moment != 0.0)){
+                                       ChipmunkGearJoint *friction = [ChipmunkGearJoint gearJointWithBodyA:grabBody bodyB:body phase:0.0 ratio:1.0];
+                                       friction.maxForce = rotaryFriction;
+                                       friction.maxBias = 0.0;
+                                       chipmunkObjects = [chipmunkObjects arrayByAddingObject:friction];
+                               }
+                       }
+                       
+                       _chipmunkObjects = [chipmunkObjects retain];
+               }
+       }
+       
+       return self;
+}
+
+-(void)dealloc
+{
+       [_chipmunkObjects release]; _chipmunkObjects = nil;
+       [super dealloc];
+}
+
+@end
+
+
+@implementation ChipmunkMultiGrab
+
+@synthesize grabForce = _grabForce;
+@synthesize smoothing = _smoothing;
+
+@synthesize filter = _filter;
+@synthesize grabFilter = _grabFilter;
+@synthesize grabSort = _grabSort;
+
+@synthesize grabFriction = _grabFriction, grabRotaryFriction = _grabRotaryFriction;
+@synthesize grabRadius = _grabRadius;
+
+@synthesize pullMode = _pullMode, pushMode = _pushMode;
+
+@synthesize pushMass = _pushMass;
+@synthesize pushFriction = _pushFriction, pushElasticity = _pushElasticity;
+@synthesize pushCollisionType = _pushCollisionType;
+
+-(id)initForSpace:(ChipmunkSpace *)space withSmoothing:(cpFloat)smoothing withGrabForce:(cpFloat)grabForce
+{
+       if((self = [super init])){
+               _space = [space retain];
+               _grabs = [[NSMutableArray alloc] init];
+               
+               _smoothing = smoothing;
+               _grabForce = grabForce;
+               
+               _filter = CP_SHAPE_FILTER_ALL;
+               
+               _grabFilter = ^(ChipmunkShape *shape){return (bool)TRUE;};
+               _grabSort = ^(ChipmunkShape *shape, cpFloat depth){return depth;};
+               
+               _pullMode = TRUE;
+               _pushMode = FALSE;
+       }
+       
+       return self;
+}
+
+-(void)dealloc
+{
+       [_space release];
+       [_grabs release];
+       
+       [super dealloc];
+}
+
+// Don't integrate push bodies.
+static void PushBodyVelocityUpdate(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt){}
+
+-(ChipmunkGrab *)beginLocation:(cpVect)pos
+{
+       __block cpFloat min = INFINITY;
+       __block cpVect nearest = pos;
+       __block ChipmunkShape *grabbedShape = nil;
+       
+       if(_pullMode){
+               cpSpacePointQuery_b(_space.space, pos, _grabRadius, _filter, ^(cpShape *c_shape, cpVect point, cpFloat dist, cpVect gradient){
+                       ChipmunkShape *shape = [ChipmunkShape shapeFromCPShape:c_shape];
+                       cpFloat sort = dist;
+                       
+                       // Call the sorting callback if dist is negative.
+                       // Otherwise just take the nearest shape.
+                       if(dist <= 0.0f){
+                               sort = -_grabSort(shape, -dist);
+                               cpAssertWarn(sort <= 0.0f, "You must return a positive value from the sorting callback.");
+                       }
+                       
+                       if(sort < min && cpBodyGetMass(cpShapeGetBody(c_shape)) != INFINITY){
+                               if(_grabFilter(shape)){
+                                       min = sort;
+                                       nearest = (dist > 0.0 ? point : pos);
+                                       grabbedShape = shape;
+                               }
+                       }
+               });
+       }
+       
+       ChipmunkBody *pushBody = nil;
+       NSArray *chipmunkObjects = [NSArray array];
+       
+       if(!grabbedShape && _pushMode){
+               pushBody = [ChipmunkBody bodyWithMass:_pushMass andMoment:INFINITY];
+               pushBody.position = pos;
+               cpBodySetVelocityUpdateFunc(pushBody.body, PushBodyVelocityUpdate);
+               
+               ChipmunkShape *pushShape = [ChipmunkCircleShape circleWithBody:pushBody radius:_grabRadius offset:cpvzero];
+               pushShape.friction = _pushFriction;
+               pushShape.elasticity = _pushElasticity;
+               pushShape.filter = _filter;
+               pushShape.collisionType = _pushCollisionType;
+               
+               chipmunkObjects = [NSArray arrayWithObjects:pushBody, pushShape, nil];
+       }
+       
+       ChipmunkBody *grabBody = (grabbedShape ? grabbedShape.body : pushBody);
+       ChipmunkGrab *grab = [[ChipmunkGrab alloc] initWithMultiGrab:self pos:pos nearest:nearest body:grabBody grabbedShape:grabbedShape chipmunkObjects:chipmunkObjects];
+       
+       [_grabs addObject:grab];
+       [_space add:grab];
+       [grab release];
+       
+       return (grab.grabbedShape ? grab : nil);
+}
+
+static ChipmunkGrab *
+BestGrab(NSArray *grabs, cpVect pos)
+{
+       ChipmunkGrab *match = nil;
+       cpFloat best = INFINITY;
+       
+       for(ChipmunkGrab *grab in grabs){
+               cpFloat dist = cpvdistsq(pos, grab.pos);
+               if(dist < best){
+                       match = grab;
+                       best = dist;
+               }
+       }
+       
+       return match;
+}
+
+-(ChipmunkGrab *)updateLocation:(cpVect)pos
+{
+       ChipmunkGrab *grab = BestGrab(_grabs, pos);
+       grab.pos = pos;
+       
+       return (grab.grabbedShape ? grab : nil);
+}
+
+-(ChipmunkGrab *)endLocation:(cpVect)pos
+{
+       cpAssertHard([_grabs count] != 0, "Grab set is already empty!");
+       ChipmunkGrab *grab = BestGrab(_grabs, pos);
+       [grab retain];
+       
+       [_space remove:grab];
+       [_grabs removeObject:grab];
+       
+       [grab autorelease];
+       return (grab.grabbedShape ? grab : nil);
+}
+
+-(NSArray *)grabs
+{
+       NSMutableArray *grabs = [NSMutableArray array];
+       for(ChipmunkGrab *grab in _grabs){
+               if(grab.grabbedShape) [grabs addObject:grab];
+       }
+       
+       return grabs;
+}
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkPointCloudSampler.m b/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkPointCloudSampler.m
new file mode 100644 (file)
index 0000000..8e858ad
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#import "ChipmunkPointCloudSampler.h"
+
+
+typedef struct DeformPoint {
+       cpVect pos;
+       cpFloat radius;
+       cpFloat fuzz;
+} DeformPoint;
+
+static cpBB
+PointBB(DeformPoint *point)
+{
+       cpVect v = point->pos;
+       cpFloat r = point->radius;
+       
+       return cpBBNew(v.x - r, v.y - r, v.x + r, v.y + r);
+}
+
+
+
+@implementation ChipmunkPointCloudSampler
+
+static inline cpFloat
+fuzz(cpVect v, cpVect c, cpFloat r, cpFloat softness)
+{
+       cpFloat distsq = cpvdistsq(v, c);
+       return (distsq < r*r ? 1.0f - cpfclamp01((r - cpfsqrt(distsq))/(softness*r)) : 1.0f);
+}
+
+static void
+PointQuery(cpVect *v, DeformPoint *point, cpCollisionID id, cpFloat *density)
+{
+       (*density) *= fuzz(*v, point->pos, point->radius, point->fuzz);
+}
+
+static cpFloat
+PointCloudSample(ChipmunkPointCloudSampler *cloud, cpVect pos)
+{
+       cpFloat density = 1.0f;
+       cpSpatialIndexQuery(cloud->_index, &pos, cpBBNewForCircle(pos, 0.0f), (cpSpatialIndexQueryFunc)PointQuery, &density);
+       
+       return density;
+}
+
+- (id)initWithCellSize:(cpFloat)cellSize
+{
+       if((self = [super initWithSamplingFunction:(cpMarchSampleFunc)PointCloudSample])){
+               _cellSize = cellSize;
+               // TODO table size
+               _index = cpSpaceHashNew(cellSize, 1000, (cpSpatialIndexBBFunc)PointBB, NULL);
+       }
+       
+       return self;
+}
+
+static void freeWrap(void *ptr, void *unused){cpfree(ptr);}
+
+- (void)dealloc
+{
+       cpSpatialIndexEach(_index, (cpSpatialIndexIteratorFunc)freeWrap, NULL);
+       cpSpatialIndexFree(_index);
+       
+       [super dealloc];
+}
+
+-(cpBB)addPoint:(cpVect)pos radius:(cpFloat)radius fuzz:(cpFloat)fuzz
+{
+       DeformPoint *point = (DeformPoint *)cpcalloc(1, sizeof(DeformPoint));
+       point->pos = pos;
+       point->radius = radius;
+       point->fuzz = fuzz;
+       
+       cpSpatialIndexInsert(_index, point, (cpHashValue)point);
+       
+       return PointBB(point);
+}
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkShape.m b/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkShape.m
new file mode 100644 (file)
index 0000000..5042811
--- /dev/null
@@ -0,0 +1,330 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
+
+@interface ChipmunkSpace(DoubleDispatch)
+
+- (ChipmunkShape *)addShape:(ChipmunkShape *)obj;
+- (ChipmunkShape *)removeShape:(ChipmunkShape *)obj;
+
+@end
+
+@implementation ChipmunkShape
+
+@synthesize userData = _userData;
+
++(ChipmunkShape *)shapeFromCPShape:(cpShape *)shape
+{
+       ChipmunkShape *obj = shape->userData;
+       cpAssertHard([obj isKindOfClass:[ChipmunkShape class]], "'shape->data' is not a pointer to a ChipmunkShape object.");
+       
+       return obj;
+}
+
+- (void) dealloc {
+       [self.body release];
+       cpShapeDestroy(self.shape);
+       [super dealloc];
+}
+
+
+- (cpShape *)shape {
+       [self doesNotRecognizeSelector:_cmd];
+       return nil;
+}
+
+- (ChipmunkBody *)body {
+       cpBody *body = cpShapeGetBody(self.shape);
+       return (body ? cpBodyGetUserData(body) : nil);
+}
+
+- (void)setBody:(ChipmunkBody *)body {
+       if(self.body != body){
+               [self.body release];
+               cpShapeSetBody(self.shape, [body retain].body);
+       }
+}
+
+-(cpFloat)mass {return cpShapeGetMass(self.shape);}
+-(void)setMass:(cpFloat)mass {cpShapeSetMass(self.shape, mass);}
+
+-(cpFloat)density {return cpShapeGetDensity(self.shape);}
+-(void)setDensity:(cpFloat)density {cpShapeSetDensity(self.shape, density);}
+
+-(cpFloat)moment {return cpShapeGetMoment(self.shape);}
+-(cpFloat)area {return cpShapeGetArea(self.shape);}
+-(cpVect)centerOfGravity {return cpShapeGetCenterOfGravity(self.shape);}
+
+// accessor macros
+#define getter(type, lower, upper) \
+- (type)lower {return cpShapeGet##upper(self.shape);}
+#define setter(type, lower, upper) \
+- (void)set##upper:(type)value {cpShapeSet##upper(self.shape, value);};
+#define both(type, lower, upper) \
+getter(type, lower, upper) \
+setter(type, lower, upper)
+
+getter(cpBB, bb, BB)
+both(BOOL, sensor, Sensor)
+both(cpFloat, elasticity, Elasticity)
+both(cpFloat, friction, Friction)
+both(cpVect, surfaceVelocity, SurfaceVelocity)
+both(cpCollisionType, collisionType, CollisionType)
+both(cpShapeFilter, filter, Filter)
+
+-(ChipmunkSpace *)space {
+       cpSpace *space = cpShapeGetSpace(self.shape);
+       return (ChipmunkSpace *)(space ? cpSpaceGetUserData(space) : nil);
+}
+
+- (cpBB)cacheBB {return cpShapeCacheBB(self.shape);}
+
+- (ChipmunkPointQueryInfo *)pointQuery:(cpVect)point
+{
+       cpPointQueryInfo info;
+       cpShapePointQuery(self.shape, point, &info);
+       return (info.shape ? [[[ChipmunkPointQueryInfo alloc] initWithInfo:&info] autorelease] : nil);
+}
+
+- (ChipmunkSegmentQueryInfo *)segmentQueryFrom:(cpVect)start to:(cpVect)end radius:(cpFloat)radius
+{
+       cpSegmentQueryInfo info;
+       if(cpShapeSegmentQuery(self.shape, start, end, radius, &info)){
+               return [[[ChipmunkSegmentQueryInfo alloc] initWithInfo:&info start:start end:end] autorelease];
+       } else {
+               return nil;
+       }
+}
+
+
+- (NSArray *)chipmunkObjects {return [NSArray arrayWithObject:self];}
+- (void)addToSpace:(ChipmunkSpace *)space {[space addShape:self];}
+- (void)removeFromSpace:(ChipmunkSpace *)space {[space removeShape:self];}
+
+@end
+
+
+@implementation ChipmunkPointQueryInfo
+
+- (id)initWithInfo:(cpPointQueryInfo *)info
+{
+       if((self = [super init])){
+               _info = (*info);
+               [self.shape retain];
+       }
+       
+       return self;
+}
+
+- (cpPointQueryInfo *)info {return &_info;}
+- (ChipmunkShape *)shape {return (_info.shape ? _info.shape->userData : nil);}
+- (cpVect)point {return _info.point;}
+- (cpFloat)distance {return _info.distance;}
+- (cpVect)gradient {return _info.gradient;}
+
+- (void)dealloc
+{
+       [self.shape release];
+       [super dealloc];
+}
+
+
+@end
+
+
+@implementation ChipmunkSegmentQueryInfo
+
+- (id)initWithInfo:(cpSegmentQueryInfo *)info start:(cpVect)start end:(cpVect)end
+{
+       if((self = [super init])){
+               _info = (*info);
+               _start = start;
+               _end = end;
+               
+               [self.shape retain];
+       }
+       
+       return self;
+}
+
+- (cpSegmentQueryInfo *)info {return &_info;}
+- (ChipmunkShape *)shape {return (_info.shape ? _info.shape->userData : nil);}
+- (cpFloat)t {return _info.alpha;}
+- (cpVect)normal {return _info.normal;}
+- (cpVect)point {return _info.point;}
+- (cpFloat)dist {return cpvdist(_start, _end)*_info.alpha;}
+- (cpVect)start {return _start;}
+- (cpVect)end {return _end;}
+
+- (void)dealloc
+{
+       [self.shape release];
+       [super dealloc];
+}
+
+
+@end
+
+
+@implementation ChipmunkShapeQueryInfo
+
+@synthesize shape = _shape;
+- (cpContactPointSet *)contactPoints {return &_contactPoints;}
+
+- (id)initWithShape:(ChipmunkShape *)shape andPoints:(cpContactPointSet *)set
+{
+       if((self = [super init])){
+               _shape = [shape retain];
+               _contactPoints = *set;
+       }
+       
+       return self;
+}
+
+- (void)dealloc {
+       [_shape release];
+       [super dealloc];
+}
+
+@end
+
+@implementation ChipmunkCircleShape {
+       cpCircleShape _shape;
+}
+
+
++ (ChipmunkCircleShape *)circleWithBody:(ChipmunkBody *)body radius:(cpFloat)radius offset:(cpVect)offset
+{
+       return [[[self alloc] initWithBody:body radius:radius offset:offset] autorelease];
+}
+
+- (cpShape *)shape {return (cpShape *)&_shape;}
+
+- (id)initWithBody:(ChipmunkBody *)body radius:(cpFloat)radius offset:(cpVect)offset {
+       if((self = [super init])){
+               [body retain];
+               cpCircleShapeInit(&_shape, body.body, radius, offset);
+               self.shape->userData = self;
+       }
+       
+       return self;
+}
+
+- (cpFloat)radius {return cpCircleShapeGetRadius((cpShape *)&_shape);}
+- (cpVect)offset {return cpCircleShapeGetOffset((cpShape *)&_shape);}
+
+@end
+
+
+@implementation ChipmunkSegmentShape {
+       cpSegmentShape _shape;
+}
+
++ (ChipmunkSegmentShape *)segmentWithBody:(ChipmunkBody *)body from:(cpVect)a to:(cpVect)b radius:(cpFloat)radius
+{
+       return [[[self alloc] initWithBody:body from:a to:b radius:radius] autorelease];
+}
+
+- (cpShape *)shape {return (cpShape *)&_shape;}
+
+- (id)initWithBody:(ChipmunkBody *)body from:(cpVect)a to:(cpVect)b radius:(cpFloat)radius {
+       if((self = [super init])){
+               [body retain];
+               cpSegmentShapeInit(&_shape, body.body, a, b, radius);
+               self.shape->userData = self;
+       }
+       
+       return self;
+}
+
+- (void)setPrevNeighbor:(cpVect)prev nextNeighbor:(cpVect)next
+{
+       cpSegmentShapeSetNeighbors((cpShape *)&_shape, prev, next);
+}
+
+- (cpVect)a {return cpSegmentShapeGetA((cpShape *)&_shape);}
+- (cpVect)b {return cpSegmentShapeGetB((cpShape *)&_shape);}
+- (cpVect)normal {return cpSegmentShapeGetNormal((cpShape *)&_shape);}
+- (cpFloat)radius {return cpSegmentShapeGetRadius((cpShape *)&_shape);}
+
+@end
+
+
+@implementation ChipmunkPolyShape {
+       cpPolyShape _shape;
+}
+
++ (id)polyWithBody:(ChipmunkBody *)body count:(int)count verts:(const cpVect *)verts transform:(cpTransform)transform radius:(cpFloat)radius
+{
+       return [[[self alloc] initWithBody:body count:count verts:verts transform:transform radius:radius] autorelease];
+}
+
++ (id)boxWithBody:(ChipmunkBody *)body width:(cpFloat)width height:(cpFloat)height radius:(cpFloat)radius
+{
+       return [[[self alloc] initBoxWithBody:body width:width height:height radius:radius] autorelease];
+}
+
++ (id)boxWithBody:(ChipmunkBody *)body bb:(cpBB)bb radius:(cpFloat)radius
+{
+       return [[[self alloc] initBoxWithBody:body bb:bb radius:radius] autorelease];
+}
+
+- (cpShape *)shape {return (cpShape *)&_shape;}
+
+- (id)initWithBody:(ChipmunkBody *)body count:(int)count verts:(const cpVect *)verts transform:(cpTransform)transform radius:(cpFloat)radius
+{
+       if((self = [super init])){
+               [body retain];
+               cpPolyShapeInit(&_shape, body.body, count, verts, transform, radius);
+               self.shape->userData = self;
+       }
+       
+       return self;
+}
+
+- (id)initBoxWithBody:(ChipmunkBody *)body width:(cpFloat)width height:(cpFloat)height radius:(cpFloat)radius
+{
+       if((self = [super init])){
+               [body retain];
+               cpBoxShapeInit(&_shape, body.body, width, height, radius);
+               self.shape->userData = self;
+       }
+       
+       return self;
+}
+
+- (id)initBoxWithBody:(ChipmunkBody *)body bb:(cpBB)bb radius:(cpFloat)radius
+{
+       if((self = [super init])){
+               [body retain];
+               cpBoxShapeInit2(&_shape, body.body, bb, radius);
+               self.shape->userData = self;
+       }
+       
+       return self;
+}
+
+- (int)count {return cpPolyShapeGetCount((cpShape *)&_shape);}
+- (cpFloat)radius {return cpPolyShapeGetRadius((cpShape *)&_shape);}
+- (cpVect)getVertex:(int)index {return cpPolyShapeGetVert((cpShape *)&_shape, index);}
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkSpace.m b/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkSpace.m
new file mode 100644 (file)
index 0000000..7eebc83
--- /dev/null
@@ -0,0 +1,575 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#import "ObjectiveChipmunk/ObjectiveChipmunk.h"
+#import "chipmunk/chipmunk_private.h"
+#import "chipmunk/cpHastySpace.h"
+
+#import <objc/message.h>
+#import <TargetConditionals.h>
+
+// Just in case the user doesn't have -ObjC in their linker flags.
+// Annoyingly, this is the case more often than not.
+@interface NSArrayChipmunkObject : NSArray<ChipmunkObject>
+
+@property(nonatomic, retain) NSArray *chipmunkObjects;
+
+@end
+
+@implementation NSArrayChipmunkObject
+
+@synthesize chipmunkObjects = _chipmunkObjects;
+
+-(id)initWithArray:(NSArray *)objects {
+       if((self = [super init])){
+               self.chipmunkObjects = objects;
+       }
+       
+       return self;
+}
+
+-(NSUInteger)count
+{
+       return [_chipmunkObjects count];
+}
+
+-(id)objectAtIndex:(NSUInteger)index
+{
+       return [_chipmunkObjects objectAtIndex:index];
+}
+
+@end
+
+@implementation NSArray(ChipmunkObject)
+
+-(id<NSFastEnumeration>)chipmunkObjects
+{
+       return self;
+}
+
+@end
+
+
+// Private class used to wrap the statically allocated staticBody attached to each space.
+@interface _ChipmunkStaticBodySingleton : ChipmunkBody {
+       cpBody *_bodyPtr;
+       ChipmunkSpace *space; // weak ref
+}
+
+@end
+
+typedef struct HandlerContext {
+       ChipmunkSpace *space;
+       id delegate;
+       cpCollisionType typeA, typeB;
+       SEL beginSelector;
+       SEL preSolveSelector;
+       SEL postSolveSelector;
+       SEL separateSelector;
+} HandlerContext;
+
+@implementation ChipmunkSpace
+
++(ChipmunkSpace *)spaceFromCPSpace:(cpSpace *)space
+{      
+       ChipmunkSpace *obj = space->userData;
+       cpAssertHard([obj isKindOfClass:[ChipmunkSpace class]], "'space->data' is not a pointer to a ChipmunkSpace object.");
+       
+       return obj;
+}
+
++(instancetype)allocWithZone:(struct _NSZone *)zone
+{
+    Class class = self;
+#if CHIPMUNK_SPACE_USE_HASTY_SPACE
+    if (self == [ChipmunkSpace class]) {
+        class = [ChipmunkHastySpace class];
+    }
+#endif
+
+       return NSAllocateObject(class, 0, zone);
+}
+
+- (id)initWithSpace:(cpSpace *)space
+{
+       if((self = [super init])){
+               _children = [[NSMutableSet alloc] init];
+               _handlers = [[NSMutableArray alloc] init];
+               
+               _space = space;
+               cpSpaceSetUserData(_space, self);
+               
+               _staticBody = [[ChipmunkBody alloc] initWithMass:0.0f andMoment:0.0f];
+               _staticBody.type = CP_BODY_TYPE_STATIC;
+               cpSpaceSetStaticBody(_space, _staticBody.body);
+       }
+       
+       return self;
+}
+
+- (id)init {
+       return [self initWithSpace:cpSpaceNew()];
+}
+
+-(void)freeSpace
+{
+       cpSpaceFree(_space);
+}
+
+- (void) dealloc {
+       [self freeSpace];
+       [_staticBody release];
+       
+       [_children release];
+       [_handlers release];
+       
+       [super dealloc];
+}
+
+- (cpSpace *)space {return _space;}
+
+@synthesize userData = _userData;
+
+// accessor macros
+#define getter(type, lower, upper) \
+- (type)lower {return cpSpaceGet##upper(_space);}
+#define setter(type, lower, upper) \
+- (void)set##upper:(type)value {cpSpaceSet##upper(_space, value);};
+#define both(type, lower, upper) \
+getter(type, lower, upper) \
+setter(type, lower, upper)
+
+both(int, iterations, Iterations);
+both(cpVect, gravity, Gravity);
+both(cpFloat, damping, Damping);
+both(cpFloat, idleSpeedThreshold, IdleSpeedThreshold);
+both(cpFloat, sleepTimeThreshold, SleepTimeThreshold);
+both(cpFloat, collisionSlop, CollisionSlop);
+both(cpFloat, collisionBias, CollisionBias);
+both(cpTimestamp, collisionPersistence, CollisionPersistence);
+getter(cpFloat, currentTimeStep, CurrentTimeStep);
+
+- (BOOL)isLocked {return cpSpaceIsLocked(_space);}
+- (BOOL)locked {return self.isLocked;}
+
+- (ChipmunkBody *)staticBody {return _staticBody;}
+
+typedef BOOL (*BeginProto)(id, SEL, cpArbiter *, ChipmunkSpace *);
+static bool Begin(cpArbiter *arb, struct cpSpace *space, HandlerContext *ctx){return ((BeginProto)objc_msgSend)(ctx->delegate, ctx->beginSelector, arb, ctx->space);}
+
+typedef BOOL (*PreSolveProto)(id, SEL, cpArbiter *, ChipmunkSpace *);
+static bool PreSolve(cpArbiter *arb, struct cpSpace *space, HandlerContext *ctx){return ((PreSolveProto)objc_msgSend)(ctx->delegate, ctx->preSolveSelector, arb, ctx->space);}
+
+typedef void (*PostSolveProto)(id, SEL, cpArbiter *, ChipmunkSpace *);
+static void PostSolve(cpArbiter *arb, struct cpSpace *space, HandlerContext *ctx){((PostSolveProto)objc_msgSend)(ctx->delegate, ctx->postSolveSelector, arb, ctx->space);}
+
+typedef void (*SeparateProto)(id, SEL, cpArbiter *, ChipmunkSpace *);
+static void Separate(cpArbiter *arb, struct cpSpace *space, HandlerContext *ctx){((SeparateProto)objc_msgSend)(ctx->delegate, ctx->separateSelector, arb, ctx->space);}
+
+// TODO handlers are never filtered.
+
+- (void)setDefaultCollisionHandler:(id)delegate
+       begin:(SEL)begin
+       preSolve:(SEL)preSolve
+       postSolve:(SEL)postSolve
+       separate:(SEL)separate
+{
+       cpCollisionType sentinel = (cpCollisionType)@"DEFAULT";
+       
+       HandlerContext context = {self, delegate, sentinel, sentinel, begin, preSolve, postSolve, separate};
+       NSData *data = [NSData dataWithBytes:&context length:sizeof(context)];
+       [_handlers addObject:data];
+       
+       cpCollisionHandler *handler = cpSpaceAddDefaultCollisionHandler(_space);
+       if(begin) handler->beginFunc = (cpCollisionBeginFunc)Begin;
+       if(preSolve) handler->preSolveFunc = (cpCollisionPreSolveFunc)PreSolve;
+       if(postSolve) handler->postSolveFunc = (cpCollisionPostSolveFunc)PostSolve;
+       if(separate) handler->separateFunc = (cpCollisionSeparateFunc)Separate;
+       handler->userData = (void *)[data bytes];
+}
+       
+- (void)addCollisionHandler:(id)delegate
+       typeA:(cpCollisionType)a typeB:(cpCollisionType)b
+       begin:(SEL)begin
+       preSolve:(SEL)preSolve
+       postSolve:(SEL)postSolve
+       separate:(SEL)separate
+{
+       HandlerContext context = {self, delegate, a, b, begin, preSolve, postSolve, separate};
+       NSData *data = [NSData dataWithBytes:&context length:sizeof(context)];
+       [_handlers addObject:data];
+       
+       cpCollisionHandler *handler = cpSpaceAddCollisionHandler(_space, a, b);
+       if(begin) handler->beginFunc = (cpCollisionBeginFunc)Begin;
+       if(preSolve) handler->preSolveFunc = (cpCollisionPreSolveFunc)PreSolve;
+       if(postSolve) handler->postSolveFunc = (cpCollisionPostSolveFunc)PostSolve;
+       if(separate) handler->separateFunc = (cpCollisionSeparateFunc)Separate;
+       handler->userData = (void *)[data bytes];
+}
+
+- (id)add:(NSObject<ChipmunkObject> *)obj
+{
+       if([obj conformsToProtocol:@protocol(ChipmunkBaseObject)]){
+               [(NSObject<ChipmunkBaseObject> *)obj addToSpace:self];
+       } else if([obj conformsToProtocol:@protocol(ChipmunkObject)]){
+               for(NSObject<ChipmunkBaseObject> *child in [obj chipmunkObjects]) [self add:child];
+       } else {
+               [NSException raise:@"NSArgumentError" format:@"Attempted to add an object of type %@ to a ChipmunkSpace.", [obj class]];
+       }
+       
+       [_children addObject:obj];
+       return obj;
+}
+
+- (id)remove:(NSObject<ChipmunkObject> *)obj
+{
+       if([obj conformsToProtocol:@protocol(ChipmunkBaseObject)]){
+               [(NSObject<ChipmunkBaseObject> *)obj removeFromSpace:self];
+       } else if([obj conformsToProtocol:@protocol(ChipmunkObject)]){
+               for(NSObject<ChipmunkBaseObject> *child in [obj chipmunkObjects]) [self remove:child];
+       } else {
+               [NSException raise:@"NSArgumentError" format:@"Attempted to remove an object of type %@ from a ChipmunkSpace.", [obj class]];
+       }
+       
+       [_children removeObject:obj];
+       return obj;
+}
+
+-(BOOL)contains:(NSObject<ChipmunkObject> *)obj
+{
+       return [_children containsObject:obj];
+}
+
+- (NSObject<ChipmunkObject> *)smartAdd:(NSObject<ChipmunkObject> *)obj
+{
+       if(cpSpaceIsLocked(_space)){
+               [self addPostStepAddition:obj];
+       } else {
+               [self add:obj];
+       }
+       
+       return obj;
+}
+
+- (NSObject<ChipmunkObject> *)smartRemove:(NSObject<ChipmunkObject> *)obj
+{
+       if(cpSpaceIsLocked(_space)){
+               [self addPostStepRemoval:obj];
+       } else {
+               [self remove:obj];
+       }
+       
+       return obj;
+}
+
+struct PostStepTargetContext {
+       id target;
+       SEL selector;
+};
+
+static void
+postStepPerform(cpSpace *unused, id key, struct PostStepTargetContext *context)
+{
+       [context->target performSelector:context->selector withObject:key];
+       
+       [context->target release];
+       cpfree(context);
+       [key release];
+}
+
+- (BOOL)addPostStepCallback:(id)target selector:(SEL)selector key:(id)key
+{
+       if(!cpSpaceGetPostStepCallback(_space, key)){
+               struct PostStepTargetContext *context = cpcalloc(1, sizeof(struct PostStepTargetContext));
+               (*context) = (struct PostStepTargetContext){target, selector};
+               cpSpaceAddPostStepCallback(_space, (cpPostStepFunc)postStepPerform, key, context);
+               
+               [target retain];
+               [key retain];
+               
+               return TRUE;
+       } else {
+               return FALSE;
+       }
+}
+
+static void
+postStepPerformBlock(cpSpace *unused, id key, ChipmunkPostStepBlock block)
+{
+       block();
+       
+       [block release];
+       [key release];
+}
+
+- (BOOL)addPostStepBlock:(ChipmunkPostStepBlock)block key:(id)key
+{
+       if(!cpSpaceGetPostStepCallback(_space, key)){
+               cpSpaceAddPostStepCallback(_space, (cpPostStepFunc)postStepPerformBlock, key, [block copy]);
+               
+               [key retain];
+               
+               return TRUE;
+       } else {
+               return FALSE;
+       }
+}
+
+- (void)addPostStepAddition:(NSObject<ChipmunkObject> *)obj
+{
+       [self addPostStepCallback:self selector:@selector(add:) key:obj];
+}
+
+- (void)addPostStepRemoval:(NSObject<ChipmunkObject> *)obj
+{
+       [self addPostStepCallback:self selector:@selector(remove:) key:obj];
+}
+
+- (NSArray *)pointQueryAll:(cpVect)point maxDistance:(cpFloat)maxDistance filter:(cpShapeFilter)filter
+{
+       NSMutableArray *array = [NSMutableArray array];
+       cpSpacePointQuery_b(_space, point, maxDistance, filter, ^(cpShape *shape, cpVect p, cpFloat d, cpVect g){
+               ChipmunkPointQueryInfo *info = [[ChipmunkPointQueryInfo alloc] initWithInfo:&(cpPointQueryInfo){shape, p, d, g}];
+               [array addObject:info];
+               [info release];
+       });
+       
+       return array;
+}
+
+- (ChipmunkPointQueryInfo *)pointQueryNearest:(cpVect)point maxDistance:(cpFloat)maxDistance filter:(cpShapeFilter)filter
+{
+       cpPointQueryInfo info;
+       cpSpacePointQueryNearest(_space, point, maxDistance, filter, &info);
+       return (info.shape ? [[[ChipmunkPointQueryInfo alloc] initWithInfo:&info] autorelease] : nil);
+}
+
+typedef struct segmentQueryContext {
+       cpVect start, end;
+       NSMutableArray *array;
+} segmentQueryContext;
+
+- (NSArray *)segmentQueryAllFrom:(cpVect)start to:(cpVect)end radius:(cpFloat)radius filter:(cpShapeFilter)filter
+{
+       NSMutableArray *array = [NSMutableArray array];
+       cpSpaceSegmentQuery_b(_space, start, end, radius, filter, ^(cpShape *shape, cpVect p, cpVect n, cpFloat t){
+               // TODO point
+               ChipmunkSegmentQueryInfo *info = [[ChipmunkSegmentQueryInfo alloc] initWithInfo:&(cpSegmentQueryInfo){shape, p, n, t} start:start end:end];
+               [array addObject:info];
+               [info release];
+       });
+       
+       return array;
+}
+
+- (ChipmunkSegmentQueryInfo *)segmentQueryFirstFrom:(cpVect)start to:(cpVect)end radius:(cpFloat)radius filter:(cpShapeFilter)filter
+{
+       cpSegmentQueryInfo info;
+       cpSpaceSegmentQueryFirst(_space, start, end, radius, filter, &info);
+       
+       return (info.shape ? [[[ChipmunkSegmentQueryInfo alloc] initWithInfo:&info start:start end:end] autorelease] : nil);
+}
+
+- (NSArray *)bbQueryAll:(cpBB)bb filter:(cpShapeFilter)filter
+{
+       NSMutableArray *array = [NSMutableArray array];
+       cpSpaceBBQuery_b(_space, bb, filter, ^(cpShape *shape){
+               [array addObject:shape->userData];
+       });
+       
+       return array;
+}
+
+//static void
+//shapeQueryAll(cpShape *shape, cpContactPointSet *points, NSMutableArray *array)
+//{
+//     ChipmunkShapeQueryInfo *info = [[ChipmunkShapeQueryInfo alloc] initWithShape:shape->userData andPoints:points];
+//     [array addObject:info];
+//     [info release];
+//}
+
+- (NSArray *)shapeQueryAll:(ChipmunkShape *)shape
+{
+       NSMutableArray *array = [NSMutableArray array];
+       cpSpaceShapeQuery_b(_space, shape.shape, ^(cpShape *shape, cpContactPointSet *points){
+               ChipmunkShapeQueryInfo *info = [[ChipmunkShapeQueryInfo alloc] initWithShape:shape->userData andPoints:points];
+               [array addObject:info];
+               [info release];
+       });
+       
+       return array;
+}
+
+- (BOOL)shapeTest:(ChipmunkShape *)shape
+{
+       return cpSpaceShapeQuery(_space, shape.shape, NULL, NULL);
+}
+
+static void PushBody(cpBody *body, NSMutableArray *arr){[arr addObject:body->userData];}
+- (NSArray *)bodies
+{
+       NSMutableArray *arr = [NSMutableArray array];
+       cpSpaceEachBody(_space, (cpSpaceBodyIteratorFunc)PushBody, arr);
+       
+       return arr;
+}
+
+static void PushShape(cpShape *shape, NSMutableArray *arr){[arr addObject:shape->userData];}
+- (NSArray *)shapes
+{
+       NSMutableArray *arr = [NSMutableArray array];
+       cpSpaceEachShape(_space, (cpSpaceShapeIteratorFunc)PushShape, arr);
+       
+       return arr;
+}
+
+static void PushConstraint(cpConstraint *constraint, NSMutableArray *arr){[arr addObject:constraint->userData];}
+- (NSArray *)constraints
+{
+       NSMutableArray *arr = [NSMutableArray array];
+       cpSpaceEachConstraint(_space, (cpSpaceConstraintIteratorFunc)PushConstraint, arr);
+       
+       return arr;
+}
+
+
+- (void)reindexStatic
+{
+       cpSpaceReindexStatic(_space);
+}
+
+- (void)reindexShape:(ChipmunkShape *)shape
+{
+       cpSpaceReindexShape(_space, shape.shape);
+}
+
+- (void)reindexShapesForBody:(ChipmunkBody *)body
+{
+       cpSpaceReindexShapesForBody(_space, body.body);
+}
+
+- (void)step:(cpFloat)dt
+{
+       cpSpaceStep(_space, dt);
+}
+
+//MARK: Extras
+
+- (ChipmunkBody *)addBody:(ChipmunkBody *)obj {
+       cpSpaceAddBody(_space, obj.body);
+       [_children addObject:obj];
+       return obj;
+}
+
+- (ChipmunkBody *)removeBody:(ChipmunkBody *)obj {
+       cpSpaceRemoveBody(_space, obj.body);
+       [_children removeObject:obj];
+       return obj;
+}
+
+
+- (ChipmunkShape *)addShape:(ChipmunkShape *)obj {
+       cpSpaceAddShape(_space, obj.shape);
+       [_children addObject:obj];
+       return obj;
+}
+
+- (ChipmunkShape *)removeShape:(ChipmunkShape *)obj {
+       cpSpaceRemoveShape(_space, obj.shape);
+       [_children removeObject:obj];
+       return obj;
+}
+
+- (ChipmunkConstraint *)addConstraint:(ChipmunkConstraint *)obj {
+       cpSpaceAddConstraint(_space, obj.constraint);
+       [_children addObject:obj];
+       return obj;
+}
+
+- (ChipmunkConstraint *)removeConstraint:(ChipmunkConstraint *)obj {
+       cpSpaceRemoveConstraint(_space, obj.constraint);
+       [_children removeObject:obj];
+       return obj;
+}
+
+static ChipmunkSegmentShape *
+boundSeg(ChipmunkBody *body, cpVect a, cpVect b, cpFloat radius, cpFloat elasticity,cpFloat friction, cpShapeFilter filter, cpCollisionType collisionType)
+{
+       ChipmunkSegmentShape *seg = [ChipmunkSegmentShape segmentWithBody:body from:a to:b radius:radius];
+       seg.elasticity = elasticity;
+       seg.friction = friction;
+       seg.filter = filter;
+       seg.collisionType = collisionType;
+       
+       return seg;
+}
+
+- (NSArray *)addBounds:(cpBB)bounds thickness:(cpFloat)radius
+       elasticity:(cpFloat)elasticity friction:(cpFloat)friction
+       filter:(cpShapeFilter)filter collisionType:(cpCollisionType)collisionType
+{
+       cpFloat l = bounds.l - radius;
+       cpFloat b = bounds.b - radius;
+       cpFloat r = bounds.r + radius;
+       cpFloat t = bounds.t + radius;
+       
+       NSArray *segs = [[NSArrayChipmunkObject alloc] initWithArray:[NSArray arrayWithObjects:
+               boundSeg(_staticBody, cpv(l,b), cpv(l,t), radius, elasticity, friction, filter, collisionType),
+               boundSeg(_staticBody, cpv(l,t), cpv(r,t), radius, elasticity, friction, filter, collisionType),
+               boundSeg(_staticBody, cpv(r,t), cpv(r,b), radius, elasticity, friction, filter, collisionType),
+               boundSeg(_staticBody, cpv(r,b), cpv(l,b), radius, elasticity, friction, filter, collisionType),
+               nil
+       ]];
+       
+       [self add:segs];
+       return [segs autorelease];
+}
+
+@end
+
+
+@implementation ChipmunkHastySpace
+
+- (id)init {
+       return [self initWithSpace:cpHastySpaceNew()];
+}
+
+-(void)freeSpace
+{
+       cpHastySpaceFree(_space);
+}
+
+- (void)step:(cpFloat)dt
+{
+       cpHastySpaceStep(_space, dt);
+}
+
+-(NSUInteger)threads
+{
+       return cpHastySpaceGetThreads(_space);
+}
+
+-(void)setThreads:(NSUInteger)threads
+{
+       cpHastySpaceSetThreads(_space, threads);
+}
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkTileCache.m b/dali-physics/third-party/chipmunk2d/objectivec/src/ChipmunkTileCache.m
new file mode 100644 (file)
index 0000000..7af8f73
--- /dev/null
@@ -0,0 +1,354 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#import "ChipmunkTileCache.h"
+
+
+@interface ChipmunkCachedTile : NSObject {
+       cpBB _bb;
+       bool _dirty;
+       
+       ChipmunkCachedTile *_next, *_prev;
+       
+       NSArray *_shapes;
+}
+
+@property(nonatomic, readonly) cpBB bb;
+@property(nonatomic, assign) bool dirty;
+
+@property(nonatomic, assign) ChipmunkCachedTile *next;
+@property(nonatomic, assign) ChipmunkCachedTile *prev;
+
+@property(nonatomic, retain) NSArray *shapes;
+
+@end
+
+
+
+@implementation ChipmunkCachedTile
+
+@synthesize bb = _bb, dirty = _dirty, shapes = _shapes, next = _next, prev = _prev;
+
+static cpBB
+ChipmunkCachedTileBB(ChipmunkCachedTile *tile)
+{
+       return tile->_bb;
+}
+
+static void
+ChipmunkCachedTileQuery(cpVect *pos, ChipmunkCachedTile *tile, cpCollisionID id, ChipmunkCachedTile **out)
+{
+       if(cpBBContainsVect(tile->_bb, *pos)) (*out) = tile;
+}
+
+
+-(id)initWithBB:(cpBB)bb
+{
+       if((self = [super init])) _bb = bb;
+       return self;
+}
+
+-(void)dealloc
+{
+       self.shapes = nil;
+       [super dealloc];
+}
+
+@end
+
+
+
+@implementation ChipmunkAbstractTileCache
+
+@synthesize marchHard = _marchHard, sampler = _sampler, tileOffset = _tileOffset;
+
+-(id)initWithSampler:(ChipmunkAbstractSampler *)sampler space:(ChipmunkSpace *)space tileSize:(cpFloat)tileSize samplesPerTile:(NSUInteger)samplesPerTile cacheSize:(NSUInteger)cacheSize
+{
+       if((self = [super init])){
+               _sampler = [sampler retain];
+               _space = [space retain];
+               
+               _tileSize = tileSize;
+               _samplesPerTile =samplesPerTile;
+               _tileOffset = cpvzero;
+               
+               _cacheSize = cacheSize;
+               [self resetCache];
+       }
+
+       return self;
+}
+
+-(void)removeShapesForTile:(ChipmunkCachedTile *)tile
+{
+       for(ChipmunkShape *shape in tile.shapes) [_space remove:shape];
+}
+
+-(void)dealloc
+{
+       for(ChipmunkCachedTile *tile = _cacheTail; tile; tile = tile.next){
+               [tile autorelease];
+       }
+       
+       [_sampler release];
+       [_space release];
+       
+       cpSpatialIndexFree(_tileIndex);
+       
+       [super dealloc];
+}
+
+-(void)resetCache
+{
+       _ensuredDirty = TRUE;
+       
+       // Reset the spatial index.
+       if(_tileIndex) cpSpatialIndexFree(_tileIndex);
+       _tileIndex = cpSpaceHashNew(_tileSize, (int)_cacheSize, (cpSpatialIndexBBFunc)ChipmunkCachedTileBB, NULL);
+       
+       // Remove all the shapes and release all the tiles.
+       for(ChipmunkCachedTile *tile = _cacheTail; tile; tile = tile.next){
+               [self removeShapesForTile:tile];
+               [tile autorelease];
+       }
+       
+       // Clear out the tile list.
+       _cacheHead = _cacheTail = nil;
+       _tileCount = 0;
+}
+
+-(void)marchTile:(ChipmunkCachedTile *)tile
+{
+       // Remove old shapes for this tile.
+       for(ChipmunkShape *shape in tile.shapes) [_space remove:shape];
+       cpPolylineSet *set = cpPolylineSetNew();
+       
+       (_marchHard ? cpMarchHard : cpMarchSoft)(
+               tile.bb, _samplesPerTile, _samplesPerTile, _sampler.marchThreshold,
+               (cpMarchSegmentFunc)cpPolylineSetCollectSegment, set,
+               _sampler.sampleFunc, _sampler
+       );
+       
+       if(set->count){
+               ChipmunkBody *staticBody = [ChipmunkBody staticBody];
+               NSMutableArray *shapes = [NSMutableArray array];
+               
+               for(int i=0; i<set->count; i++){
+                       cpPolyline *simplified = [self simplify:set->lines[i]];
+                       
+                       for(int i=0; i<simplified->count - 1; i++){
+                               ChipmunkSegmentShape *segment = [self makeSegmentFor:staticBody from:simplified->verts[i] to:simplified->verts[i+1]];
+                               [shapes addObject:segment];
+                               [_space add:segment];
+                       }
+                       
+                       cpPolylineFree(simplified);
+               }
+               
+               tile.shapes = shapes;
+       } else {
+               tile.shapes = nil;
+       }
+       
+       cpPolylineSetFree(set, TRUE);
+       tile.dirty = FALSE;
+}
+
+static inline ChipmunkCachedTile *
+GetTileAt(cpSpatialIndex *index, int i, int j, cpFloat size, cpVect offset)
+{
+       // Cannot directly get spatial hash cells, so we'll point query at the centers.
+       cpVect point = cpv((i + 0.5)*size + offset.x, (j + 0.5)*size + offset.y);
+       ChipmunkCachedTile *tile = nil;
+       cpSpatialIndexQuery(index, &point, cpBBNewForCircle(point, 0.0f), (cpSpatialIndexQueryFunc)ChipmunkCachedTileQuery, &tile);
+       
+       return tile;
+}
+
+struct TileRect {int l, b, r, t;};
+
+static inline cpBB
+BBForTileRect(struct TileRect rect, cpFloat size, cpVect offset)
+{
+       return cpBBNew(rect.l*size + offset.x, rect.b*size + offset.y, rect.r*size + offset.x, rect.t*size + offset.y);
+}
+
+static inline struct TileRect
+TileRectForBB(cpBB bb, cpFloat size, cpVect offset, cpFloat spt_inv)
+{
+       return (struct TileRect){
+               (int)cpffloor((bb.l - offset.x)/size - spt_inv),
+               (int)cpffloor((bb.b - offset.x)/size - spt_inv),
+               (int) cpfceil((bb.r - offset.y)/size + spt_inv),
+               (int) cpfceil((bb.t - offset.y)/size + spt_inv),
+       };
+}
+
+-(void)markDirtyRect:(cpBB)bounds
+{
+       cpFloat size = _tileSize;
+       cpVect offset = _tileOffset;
+       struct TileRect rect = TileRectForBB(bounds, size, offset, 1.0/(cpFloat)_samplesPerTile);
+       
+       if(!_ensuredDirty && cpBBContainsBB(_ensuredBB, BBForTileRect(rect, size, offset))){
+               _ensuredDirty = TRUE;
+       }
+       
+       for(int i=rect.l; i<rect.r; i++){
+               for(int j=rect.b; j<rect.t; j++){
+                       ChipmunkCachedTile *tile = GetTileAt(_tileIndex, i, j, size, offset);
+                       if(tile) tile.dirty = TRUE;
+               }       
+       }
+}
+
+-(void)pushTile:(ChipmunkCachedTile *)tile
+{
+       [tile retain];
+       
+       _cacheHead.next = tile;
+       tile.prev = _cacheHead;
+       
+       _cacheHead = tile;
+       _cacheTail = _cacheTail ?: tile;
+}
+
+-(void)removeTile:(ChipmunkCachedTile *)tile
+{
+       if(tile.prev == nil && _cacheTail == tile) _cacheTail = tile.next;
+       if(tile.next == nil && _cacheHead == tile) _cacheHead = tile.prev;
+       
+       tile.prev.next = tile.next;
+       tile.next.prev = tile.prev;
+       tile.prev = tile.next = nil;
+       
+       [tile autorelease];
+}
+
+#define LOADING_FACTOR 1.0
+
+//extern double GetMilliseconds();
+
+-(void)ensureRect:(cpBB)bounds
+{
+//     double time = GetMilliseconds();
+       
+       cpFloat size = _tileSize;
+       cpVect offset = _tileOffset;
+       struct TileRect rect = TileRectForBB(bounds, size, offset, 1.0/(cpFloat)_samplesPerTile);
+       
+       cpBB ensure = BBForTileRect(rect, size, offset);
+       if(!_ensuredDirty && cpBBContainsBB(_ensuredBB, ensure)) return;
+       
+//     int count = 0;
+//     printf("Marching tiles in (% 4d, % 4d) - (% 4d, % 4d):\n", l, b, r, t);
+       for(int i=rect.l; i<rect.r; i++){
+               for(int j=rect.b; j<rect.t; j++){
+//                     printf("Marching tile (% 4d, % 4d)\n", i, j);
+                       
+                       ChipmunkCachedTile *tile = GetTileAt(_tileIndex, i, j, size, offset);
+                       
+                       if(!tile){
+                               // Tile does not exist yet, make a new dirty tile.
+                               // Let the code below push it into the tile list.
+                               tile = [[ChipmunkCachedTile alloc] initWithBB:BBForTileRect((struct TileRect){i, j, i+1, j+1}, size, offset)];
+                               tile.dirty = TRUE;
+                               
+                               cpSpatialIndexInsert(_tileIndex, tile, (cpHashValue)tile);
+                               _tileCount++;
+                       }
+                       
+                       if(tile.dirty) [self marchTile:tile];
+                       
+                       // Move tile to the front of the cache. (or add it for the first time)
+                       [self removeTile:tile];
+                       [self pushTile:tile];
+               }
+       }
+       
+       _ensuredBB = ensure;
+       _ensuredDirty = FALSE;
+       
+       // Remove tiles used the longest ago if over the cache count;
+       NSInteger removeCount = _tileCount - _cacheSize;
+       for(int i=0; i<removeCount; i++){
+               cpSpatialIndexRemove(_tileIndex, _cacheTail, (cpHashValue)_cacheTail);
+               [self removeShapesForTile:_cacheTail];
+               [self removeTile:_cacheTail];
+               
+               _tileCount--;
+       }
+       
+//     NSLog(@"Updated %3d tiles in %6.3fms", count, GetMilliseconds() - time);
+}
+
+-(cpPolyline *)simplify:(cpPolyline *)polyline
+{
+       @throw [NSException
+               exceptionWithName:NSInternalInconsistencyException
+               reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
+               userInfo:nil
+       ];
+}
+
+-(ChipmunkSegmentShape *)makeSegmentFor:(ChipmunkBody *)staticBody from:(cpVect)a to:(cpVect)b
+{
+       @throw [NSException
+               exceptionWithName:NSInternalInconsistencyException
+               reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
+               userInfo:nil
+       ];
+}
+
+@end
+
+
+
+@implementation ChipmunkBasicTileCache
+
+@synthesize simplifyThreshold = _simplifyThreshold;
+
+@synthesize segmentRadius = _segmentRadius;
+
+@synthesize segmentFriction = _segmentFriction;
+@synthesize segmentElasticity = _segmentElasticity;
+
+@synthesize segmentFilter = _segmentFilter;
+
+@synthesize segmentCollisionType = _segmentCollisionType;
+
+-(id)initWithSampler:(ChipmunkAbstractSampler *)sampler space:(ChipmunkSpace *)space tileSize:(cpFloat)tileSize samplesPerTile:(NSUInteger)samplesPerTile cacheSize:(NSUInteger)cacheSize
+{
+       if((self = [super initWithSampler:sampler space:space tileSize:tileSize samplesPerTile:samplesPerTile cacheSize:cacheSize])){
+               _simplifyThreshold = 2.0;
+               
+               _segmentRadius = 0.0;
+               
+               _segmentFriction = 1.0;
+               _segmentElasticity = 1.0;
+               
+               _segmentFilter = CP_SHAPE_FILTER_ALL;
+               
+               _segmentCollisionType = (cpCollisionType)0;
+       }
+       
+       return self;
+}
+
+-(cpPolyline *)simplify:(cpPolyline *)polyline
+{
+       return cpPolylineSimplifyCurves(polyline, _simplifyThreshold);
+}
+
+-(ChipmunkSegmentShape *)makeSegmentFor:(ChipmunkBody *)staticBody from:(cpVect)a to:(cpVect)b
+{
+       ChipmunkSegmentShape *segment = [ChipmunkSegmentShape segmentWithBody:staticBody from:a to:b radius:_segmentRadius];
+       segment.friction = _segmentFriction;
+       segment.elasticity = _segmentElasticity;
+       segment.filter = _segmentFilter;
+       segment.collisionType = _segmentCollisionType;
+       
+       return segment;
+}
+
+@end
diff --git a/dali-physics/third-party/chipmunk2d/src/CMakeLists.txt b/dali-physics/third-party/chipmunk2d/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1c45355
--- /dev/null
@@ -0,0 +1,101 @@
+file(GLOB chipmunk_source_files "*.c")
+file(GLOB chipmunk_public_header "${chipmunk_SOURCE_DIR}/include/chipmunk/*.h")
+
+include_directories(${chipmunk_SOURCE_DIR}/include)
+
+# Chipmunk2D 7.0.3
+set(CHIPMUNK_VERSION_MAJOR 7)
+set(CHIPMUNK_VERSION_MINOR 0)
+set(CHIPMUNK_VERSION_PATCH 3)
+set(CHIPMUNK_VERSION "${CHIPMUNK_VERSION_MAJOR}.${CHIPMUNK_VERSION_MINOR}.${CHIPMUNK_VERSION_PATCH}")
+message("Configuring Chipmunk2D version ${CHIPMUNK_VERSION}")
+
+set(prefix ${CMAKE_INSTALL_PREFIX})
+option(ENABLE_PKG_CONFIGURE "Use pkgconfig" ON)
+
+if(ENABLE_PKG_CONFIGURE)
+    find_package(PkgConfig REQUIRED)
+
+    # Configure the pkg-config file
+    # Requires the following variables to be setup:
+    # @PREFIX@ @EXEC_PREFIX@ @CHIPMUNK_VERSION@ @LIB_DIR@ @DEV_INCLUDE_PATH@
+    set( LIB_DIR $ENV{libdir} )
+    if( NOT LIB_DIR )
+        set( LIB_DIR ${CMAKE_INSTALL_LIBDIR} )
+    endif()
+    if( NOT LIB_DIR )
+        set( LIB_DIR ${prefix}/lib )
+    endif()
+
+    set(PREFIX ${prefix})
+    set(EXEC_PREFIX ${CMAKE_INSTALL_PREFIX})
+    set(DEV_INCLUDE_PATH ${INCLUDE_DIR})
+
+    set(chipmunk_pkg_cfg_file chipmunk2d.pc)
+    configure_file(${CMAKE_CURRENT_LIST_DIR}/${chipmunk_pkg_cfg_file}.in ${chipmunk_pkg_cfg_file} @ONLY)
+endif(ENABLE_PKG_CONFIGURE)
+
+if(ANDROID)
+  FIND_LIBRARY(LOGLIB log)
+endif(ANDROID)
+
+if(BUILD_SHARED)
+  add_library(chipmunk SHARED
+    ${chipmunk_source_files}
+  )
+  # Tell MSVC to compile the code as C++.
+  if(MSVC)
+    set_source_files_properties(${chipmunk_source_files} PROPERTIES LANGUAGE CXX)
+    set_target_properties(chipmunk PROPERTIES LINKER_LANGUAGE CXX)
+  endif(MSVC)
+  # set the lib's version number
+  # But avoid on Android because symlinks to version numbered .so's don't work with Android's Java-side loadLibrary.
+  if(NOT ANDROID)
+    set_target_properties(chipmunk PROPERTIES
+      SOVERSION ${CHIPMUNK_VERSION_MAJOR}
+      VERSION ${CHIPMUNK_VERSION})
+  endif(NOT ANDROID)
+  if(ANDROID OR UNIX)
+    # need to explicitly link to the math library because the CMake/Android toolchains may not do it automatically
+    target_link_libraries(chipmunk m ${COVERAGE})
+  endif(ANDROID OR UNIX)
+  if(ANDROID)
+    target_link_libraries(chipmunk ${LOGLIB})
+  endif(ANDROID)
+  install(TARGETS chipmunk RUNTIME DESTINATION ${BIN_INSTALL_DIR}
+                           LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+                           ARCHIVE DESTINATION ${LIB_INSTALL_DIR})
+endif(BUILD_SHARED)
+
+if(BUILD_STATIC)
+  add_library(chipmunk_static STATIC
+    ${chipmunk_source_files}
+  )
+  # Tell MSVC to compile the code as C++.
+  if(MSVC)
+    set_source_files_properties(${chipmunk_source_files} PROPERTIES LANGUAGE CXX)
+    set_target_properties(chipmunk_static PROPERTIES LINKER_LANGUAGE CXX)
+  endif(MSVC)
+  # Sets chipmunk_static to output "libchipmunk.a" not "libchipmunk_static.a"
+  set_target_properties(chipmunk_static PROPERTIES OUTPUT_NAME chipmunk)
+  target_link_libraries(chipmunk m ${COVERAGE})
+  if(ANDROID)
+    target_link_libraries(chipmunk ${LOGLIB})
+  endif(ANDROID)
+  if(INSTALL_STATIC)
+    install(TARGETS chipmunk_static ARCHIVE DESTINATION ${LIB_INSTALL_DIR})
+  endif(INSTALL_STATIC)
+endif(BUILD_STATIC)
+
+if(BUILD_SHARED OR INSTALL_STATIC)
+  # FIXME: change to PUBLIC_HEADER to allow building frameworks
+  install(FILES ${chipmunk_public_header} DESTINATION include/chipmunk)
+  install(FILES ${chipmunk_constraint_header} DESTINATION include/chipmunk/constraints)
+endif(BUILD_SHARED OR INSTALL_STATIC)
+
+if (ENABLE_PKG_CONFIGURE)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${chipmunk_pkg_cfg_file}
+        DESTINATION ${LIB_DIR}/pkgconfig
+    )
+endif()
+
diff --git a/dali-physics/third-party/chipmunk2d/src/chipmunk.c b/dali-physics/third-party/chipmunk2d/src/chipmunk.c
new file mode 100644 (file)
index 0000000..a6cc9d6
--- /dev/null
@@ -0,0 +1,331 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#if defined(ANDROID)
+#      include <android/log.h>
+#endif
+
+#include "chipmunk/chipmunk_private.h"
+
+void
+cpMessage(const char *condition, const char *file, int line, int isError, int isHardError, const char *message, ...)
+{
+       fprintf(stderr, (isError ? "Aborting due to Chipmunk error: " : "Chipmunk warning: "));
+       
+       va_list vargs;
+       va_start(vargs, message); {
+#if defined(ANDROID)
+               __android_log_print( ANDROID_LOG_INFO, "Chipmunk", "%s(%d)", file, line );
+               __android_log_print( ANDROID_LOG_INFO, "Chipmunk", message, vargs );
+#else
+               vfprintf(stderr, message, vargs);
+               fprintf(stderr, "\n");
+#endif
+       } va_end(vargs);
+       
+#if defined(ANDROID)
+       __android_log_print(ANDROID_LOG_INFO, "Chipmunk", "\tFailed condition: %s\n", condition);
+       __android_log_print(ANDROID_LOG_INFO, "Chipmunk", "\tSource:%s:%d\n", file, line);
+#else
+       fprintf(stderr, "\tFailed condition: %s\n", condition);
+       fprintf(stderr, "\tSource:%s:%d\n", file, line);
+#endif
+}
+
+#define STR(s) #s
+#define XSTR(s) STR(s)
+
+const char *cpVersionString = XSTR(CP_VERSION_MAJOR) "." XSTR(CP_VERSION_MINOR) "." XSTR(CP_VERSION_RELEASE);
+
+//MARK: Misc Functions
+
+cpFloat
+cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset)
+{
+       return m*(0.5f*(r1*r1 + r2*r2) + cpvlengthsq(offset));
+}
+
+cpFloat
+cpAreaForCircle(cpFloat r1, cpFloat r2)
+{
+       return (cpFloat)CP_PI*cpfabs(r1*r1 - r2*r2);
+}
+
+cpFloat
+cpMomentForSegment(cpFloat m, cpVect a, cpVect b, cpFloat r)
+{
+       cpVect offset = cpvlerp(a, b, 0.5f);
+       
+       // This approximates the shape as a box for rounded segments, but it's quite close.
+       cpFloat length = cpvdist(b, a) + 2.0f*r;
+       return m*((length*length + 4.0f*r*r)/12.0f + cpvlengthsq(offset));
+}
+
+cpFloat
+cpAreaForSegment(cpVect a, cpVect b, cpFloat r)
+{
+       return r*((cpFloat)CP_PI*r + 2.0f*cpvdist(a, b));
+}
+
+cpFloat
+cpMomentForPoly(cpFloat m, int count, const cpVect *verts, cpVect offset, cpFloat r)
+{
+       // TODO account for radius.
+       if(count == 2) return cpMomentForSegment(m, verts[0], verts[1], 0.0f);
+       
+       cpFloat sum1 = 0.0f;
+       cpFloat sum2 = 0.0f;
+       for(int i=0; i<count; i++){
+               cpVect v1 = cpvadd(verts[i], offset);
+               cpVect v2 = cpvadd(verts[(i+1)%count], offset);
+               
+               cpFloat a = cpvcross(v2, v1);
+               cpFloat b = cpvdot(v1, v1) + cpvdot(v1, v2) + cpvdot(v2, v2);
+               
+               sum1 += a*b;
+               sum2 += a;
+       }
+       
+       return (m*sum1)/(6.0f*sum2);
+}
+
+cpFloat
+cpAreaForPoly(const int count, const cpVect *verts, cpFloat r)
+{
+       cpFloat area = 0.0f;
+       cpFloat perimeter = 0.0f;
+       for(int i=0; i<count; i++){
+               cpVect v1 = verts[i];
+               cpVect v2 = verts[(i+1)%count];
+               
+               area += cpvcross(v1, v2);
+               perimeter += cpvdist(v1, v2);
+       }
+       
+       return r*(CP_PI*cpfabs(r) + perimeter) + area/2.0f;
+}
+
+cpVect
+cpCentroidForPoly(const int count, const cpVect *verts)
+{
+       cpFloat sum = 0.0f;
+       cpVect vsum = cpvzero;
+       
+       for(int i=0; i<count; i++){
+               cpVect v1 = verts[i];
+               cpVect v2 = verts[(i+1)%count];
+               cpFloat cross = cpvcross(v1, v2);
+               
+               sum += cross;
+               vsum = cpvadd(vsum, cpvmult(cpvadd(v1, v2), cross));
+       }
+       
+       return cpvmult(vsum, 1.0f/(3.0f*sum));
+}
+
+//void
+//cpRecenterPoly(const int count, cpVect *verts){
+//     cpVect centroid = cpCentroidForPoly(count, verts);
+//     
+//     for(int i=0; i<count; i++){
+//             verts[i] = cpvsub(verts[i], centroid);
+//     }
+//}
+
+cpFloat
+cpMomentForBox(cpFloat m, cpFloat width, cpFloat height)
+{
+       return m*(width*width + height*height)/12.0f;
+}
+
+cpFloat
+cpMomentForBox2(cpFloat m, cpBB box)
+{
+       cpFloat width = box.r - box.l;
+       cpFloat height = box.t - box.b;
+       cpVect offset = cpvmult(cpv(box.l + box.r, box.b + box.t), 0.5f);
+       
+       // TODO: NaN when offset is 0 and m is INFINITY
+       return cpMomentForBox(m, width, height) + m*cpvlengthsq(offset);
+}
+
+//MARK: Quick Hull
+
+void
+cpLoopIndexes(const cpVect *verts, int count, int *start, int *end)
+{
+       (*start) = (*end) = 0;
+       cpVect min = verts[0];
+       cpVect max = min;
+       
+  for(int i=1; i<count; i++){
+    cpVect v = verts[i];
+               
+    if(v.x < min.x || (v.x == min.x && v.y < min.y)){
+      min = v;
+      (*start) = i;
+    } else if(v.x > max.x || (v.x == max.x && v.y > max.y)){
+                       max = v;
+                       (*end) = i;
+               }
+       }
+}
+
+#define SWAP(__A__, __B__) {cpVect __TMP__ = __A__; __A__ = __B__; __B__ = __TMP__;}
+
+static int
+QHullPartition(cpVect *verts, int count, cpVect a, cpVect b, cpFloat tol)
+{
+       if(count == 0) return 0;
+       
+       cpFloat max = 0;
+       int pivot = 0;
+       
+       cpVect delta = cpvsub(b, a);
+       cpFloat valueTol = tol*cpvlength(delta);
+       
+       int head = 0;
+       for(int tail = count-1; head <= tail;){
+               cpFloat value = cpvcross(cpvsub(verts[head], a), delta);
+               if(value > valueTol){
+                       if(value > max){
+                               max = value;
+                               pivot = head;
+                       }
+                       
+                       head++;
+               } else {
+                       SWAP(verts[head], verts[tail]);
+                       tail--;
+               }
+       }
+       
+       // move the new pivot to the front if it's not already there.
+       if(pivot != 0) SWAP(verts[0], verts[pivot]);
+       return head;
+}
+
+static int
+QHullReduce(cpFloat tol, cpVect *verts, int count, cpVect a, cpVect pivot, cpVect b, cpVect *result)
+{
+       if(count < 0){
+               return 0;
+       } else if(count == 0) {
+               result[0] = pivot;
+               return 1;
+       } else {
+               int left_count = QHullPartition(verts, count, a, pivot, tol);
+               int index = QHullReduce(tol, verts + 1, left_count - 1, a, verts[0], pivot, result);
+               
+               result[index++] = pivot;
+               
+               int right_count = QHullPartition(verts + left_count, count - left_count, pivot, b, tol);
+               return index + QHullReduce(tol, verts + left_count + 1, right_count - 1, pivot, verts[left_count], b, result + index);
+       }
+}
+
+// QuickHull seemed like a neat algorithm, and efficient-ish for large input sets.
+// My implementation performs an in place reduction using the result array as scratch space.
+int
+cpConvexHull(int count, const cpVect *verts, cpVect *result, int *first, cpFloat tol)
+{
+       if(verts != result){
+               // Copy the line vertexes into the empty part of the result polyline to use as a scratch buffer.
+               memcpy(result, verts, count*sizeof(cpVect));
+       }
+       
+       // Degenerate case, all points are the same.
+       int start, end;
+       cpLoopIndexes(verts, count, &start, &end);
+       if(start == end){
+               if(first) (*first) = 0;
+               return 1;
+       }
+       
+       SWAP(result[0], result[start]);
+       SWAP(result[1], result[end == 0 ? start : end]);
+       
+       cpVect a = result[0];
+       cpVect b = result[1];
+       
+       if(first) (*first) = start;
+       return QHullReduce(tol, result + 2, count - 2, a, b, a, result + 1) + 1;
+}
+
+//MARK: Alternate Block Iterators
+
+#if defined(__has_extension)
+#if __has_extension(blocks)
+
+static void IteratorFunc(void *ptr, void (^block)(void *ptr)){block(ptr);}
+
+void cpSpaceEachBody_b(cpSpace *space, void (^block)(cpBody *body)){
+       cpSpaceEachBody(space, (cpSpaceBodyIteratorFunc)IteratorFunc, block);
+}
+
+void cpSpaceEachShape_b(cpSpace *space, void (^block)(cpShape *shape)){
+       cpSpaceEachShape(space, (cpSpaceShapeIteratorFunc)IteratorFunc, block);
+}
+
+void cpSpaceEachConstraint_b(cpSpace *space, void (^block)(cpConstraint *constraint)){
+       cpSpaceEachConstraint(space, (cpSpaceConstraintIteratorFunc)IteratorFunc, block);
+}
+
+static void BodyIteratorFunc(cpBody *body, void *ptr, void (^block)(void *ptr)){block(ptr);}
+
+void cpBodyEachShape_b(cpBody *body, void (^block)(cpShape *shape)){
+       cpBodyEachShape(body, (cpBodyShapeIteratorFunc)BodyIteratorFunc, block);
+}
+
+void cpBodyEachConstraint_b(cpBody *body, void (^block)(cpConstraint *constraint)){
+       cpBodyEachConstraint(body, (cpBodyConstraintIteratorFunc)BodyIteratorFunc, block);
+}
+
+void cpBodyEachArbiter_b(cpBody *body, void (^block)(cpArbiter *arbiter)){
+       cpBodyEachArbiter(body, (cpBodyArbiterIteratorFunc)BodyIteratorFunc, block);
+}
+
+static void PointQueryIteratorFunc(cpShape *shape, cpVect p, cpFloat d, cpVect g, cpSpacePointQueryBlock block){block(shape, p, d, g);}
+void cpSpacePointQuery_b(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryBlock block){
+       cpSpacePointQuery(space, point, maxDistance, filter, (cpSpacePointQueryFunc)PointQueryIteratorFunc, block);
+}
+
+static void SegmentQueryIteratorFunc(cpShape *shape, cpVect p, cpVect n, cpFloat t, cpSpaceSegmentQueryBlock block){block(shape, p, n, t);}
+void cpSpaceSegmentQuery_b(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryBlock block){
+       cpSpaceSegmentQuery(space, start, end, radius, filter, (cpSpaceSegmentQueryFunc)SegmentQueryIteratorFunc, block);
+}
+
+void cpSpaceBBQuery_b(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryBlock block){
+       cpSpaceBBQuery(space, bb, filter, (cpSpaceBBQueryFunc)IteratorFunc, block);
+}
+
+static void ShapeQueryIteratorFunc(cpShape *shape, cpContactPointSet *points, cpSpaceShapeQueryBlock block){block(shape, points);}
+cpBool cpSpaceShapeQuery_b(cpSpace *space, cpShape *shape, cpSpaceShapeQueryBlock block){
+       return cpSpaceShapeQuery(space, shape, (cpSpaceShapeQueryFunc)ShapeQueryIteratorFunc, block);
+}
+
+#endif
+#endif
+
+#include "chipmunk/chipmunk_ffi.h"
diff --git a/dali-physics/third-party/chipmunk2d/src/chipmunk2d.pc.in b/dali-physics/third-party/chipmunk2d/src/chipmunk2d.pc.in
new file mode 100644 (file)
index 0000000..1f26f46
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+apiversion=@CHIPMUNK_VERSION@
+libdir=@LIB_DIR@
+includedir=@DEV_INCLUDE_PATH@
+
+Name: Chipmunk2D
+Description: Chipmunk2D Rigid Body Physics Library
+Version: ${apiversion}
+Requires:
+Libs: -L${libdir} -lchipmunk
+Cflags: -I${includedir}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpArbiter.c b/dali-physics/third-party/chipmunk2d/src/cpArbiter.c
new file mode 100644 (file)
index 0000000..6c52cee
--- /dev/null
@@ -0,0 +1,496 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+// TODO: make this generic so I can reuse it for constraints also.
+static inline void
+unthreadHelper(cpArbiter *arb, cpBody *body)
+{
+       struct cpArbiterThread *thread = cpArbiterThreadForBody(arb, body);
+       cpArbiter *prev = thread->prev;
+       cpArbiter *next = thread->next;
+       
+       if(prev){
+               cpArbiterThreadForBody(prev, body)->next = next;
+       } else if(body->arbiterList == arb) {
+               // IFF prev is NULL and body->arbiterList == arb, is arb at the head of the list.
+               // This function may be called for an arbiter that was never in a list.
+               // In that case, we need to protect it from wiping out the body->arbiterList pointer.
+               body->arbiterList = next;
+       }
+       
+       if(next) cpArbiterThreadForBody(next, body)->prev = prev;
+       
+       thread->prev = NULL;
+       thread->next = NULL;
+}
+
+void
+cpArbiterUnthread(cpArbiter *arb)
+{
+       unthreadHelper(arb, arb->body_a);
+       unthreadHelper(arb, arb->body_b);
+}
+
+cpBool cpArbiterIsFirstContact(const cpArbiter *arb)
+{
+       return arb->state == CP_ARBITER_STATE_FIRST_COLLISION;
+}
+
+cpBool cpArbiterIsRemoval(const cpArbiter *arb)
+{
+       return arb->state == CP_ARBITER_STATE_INVALIDATED;
+}
+
+int cpArbiterGetCount(const cpArbiter *arb)
+{
+       // Return 0 contacts if we are in a separate callback.
+       return (arb->state < CP_ARBITER_STATE_CACHED ? arb->count : 0);
+}
+
+cpVect
+cpArbiterGetNormal(const cpArbiter *arb)
+{
+       return cpvmult(arb->n, arb->swapped ? -1.0f : 1.0);
+}
+
+cpVect
+cpArbiterGetPointA(const cpArbiter *arb, int i)
+{
+       cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
+       return cpvadd(arb->body_a->p, arb->contacts[i].r1);
+}
+
+cpVect
+cpArbiterGetPointB(const cpArbiter *arb, int i)
+{
+       cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
+       return cpvadd(arb->body_b->p, arb->contacts[i].r2);
+}
+
+cpFloat
+cpArbiterGetDepth(const cpArbiter *arb, int i)
+{
+       cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter");
+       
+       struct cpContact *con = &arb->contacts[i];
+       return cpvdot(cpvadd(cpvsub(con->r2, con->r1), cpvsub(arb->body_b->p, arb->body_a->p)), arb->n);
+}
+
+cpContactPointSet
+cpArbiterGetContactPointSet(const cpArbiter *arb)
+{
+       cpContactPointSet set;
+       set.count = cpArbiterGetCount(arb);
+       
+       cpBool swapped = arb->swapped;
+       cpVect n = arb->n;
+       set.normal = (swapped ? cpvneg(n) : n);
+       
+       for(int i=0; i<set.count; i++){
+               // Contact points are relative to body CoGs;
+               cpVect p1 = cpvadd(arb->body_a->p, arb->contacts[i].r1);
+               cpVect p2 = cpvadd(arb->body_b->p, arb->contacts[i].r2);
+               
+               set.points[i].pointA = (swapped ? p2 : p1);
+               set.points[i].pointB = (swapped ? p1 : p2);
+               set.points[i].distance = cpvdot(cpvsub(p2, p1), n);
+       }
+       
+       return set;
+}
+
+void
+cpArbiterSetContactPointSet(cpArbiter *arb, cpContactPointSet *set)
+{
+       int count = set->count;
+       cpAssertHard(count == arb->count, "The number of contact points cannot be changed.");
+       
+       cpBool swapped = arb->swapped;
+       arb->n = (swapped ? cpvneg(set->normal) : set->normal);
+       
+       for(int i=0; i<count; i++){
+               // Convert back to CoG relative offsets.
+               cpVect p1 = set->points[i].pointA;
+               cpVect p2 = set->points[i].pointB;
+               
+               arb->contacts[i].r1 = cpvsub(swapped ? p2 : p1, arb->body_a->p);
+               arb->contacts[i].r2 = cpvsub(swapped ? p1 : p2, arb->body_b->p);
+       }
+}
+
+cpVect
+cpArbiterTotalImpulse(const cpArbiter *arb)
+{
+       struct cpContact *contacts = arb->contacts;
+       cpVect n = arb->n;
+       cpVect sum = cpvzero;
+       
+       for(int i=0, count=cpArbiterGetCount(arb); i<count; i++){
+               struct cpContact *con = &contacts[i];
+               sum = cpvadd(sum, cpvrotate(n, cpv(con->jnAcc, con->jtAcc)));
+       }
+               
+       return (arb->swapped ? sum : cpvneg(sum));
+       return cpvzero;
+}
+
+cpFloat
+cpArbiterTotalKE(const cpArbiter *arb)
+{
+       cpFloat eCoef = (1 - arb->e)/(1 + arb->e);
+       cpFloat sum = 0.0;
+       
+       struct cpContact *contacts = arb->contacts;
+       for(int i=0, count=cpArbiterGetCount(arb); i<count; i++){
+               struct cpContact *con = &contacts[i];
+               cpFloat jnAcc = con->jnAcc;
+               cpFloat jtAcc = con->jtAcc;
+               
+               sum += eCoef*jnAcc*jnAcc/con->nMass + jtAcc*jtAcc/con->tMass;
+       }
+       
+       return sum;
+}
+
+cpBool
+cpArbiterIgnore(cpArbiter *arb)
+{
+       arb->state = CP_ARBITER_STATE_IGNORE;
+       return cpFalse;
+}
+
+cpFloat
+cpArbiterGetRestitution(const cpArbiter *arb)
+{
+       return arb->e;
+}
+
+void
+cpArbiterSetRestitution(cpArbiter *arb, cpFloat restitution)
+{
+       arb->e = restitution;
+}
+
+cpFloat
+cpArbiterGetFriction(const cpArbiter *arb)
+{
+       return arb->u;
+}
+
+void
+cpArbiterSetFriction(cpArbiter *arb, cpFloat friction)
+{
+       arb->u = friction;
+}
+
+cpVect
+cpArbiterGetSurfaceVelocity(cpArbiter *arb)
+{
+       return cpvmult(arb->surface_vr, arb->swapped ? -1.0f : 1.0);
+}
+
+void
+cpArbiterSetSurfaceVelocity(cpArbiter *arb, cpVect vr)
+{
+       arb->surface_vr = cpvmult(vr, arb->swapped ? -1.0f : 1.0);
+}
+
+cpDataPointer
+cpArbiterGetUserData(const cpArbiter *arb)
+{
+       return arb->data;
+}
+
+void
+cpArbiterSetUserData(cpArbiter *arb, cpDataPointer userData)
+{
+       arb->data = userData;
+}
+
+void
+cpArbiterGetShapes(const cpArbiter *arb, cpShape **a, cpShape **b)
+{
+       if(arb->swapped){
+               (*a) = (cpShape *)arb->b, (*b) = (cpShape *)arb->a;
+       } else {
+               (*a) = (cpShape *)arb->a, (*b) = (cpShape *)arb->b;
+       }
+}
+
+void cpArbiterGetBodies(const cpArbiter *arb, cpBody **a, cpBody **b)
+{
+       CP_ARBITER_GET_SHAPES(arb, shape_a, shape_b);
+       (*a) = shape_a->body;
+       (*b) = shape_b->body;
+}
+
+cpBool
+cpArbiterCallWildcardBeginA(cpArbiter *arb, cpSpace *space)
+{
+       cpCollisionHandler *handler = arb->handlerA;
+       return handler->beginFunc(arb, space, handler->userData);
+}
+
+cpBool
+cpArbiterCallWildcardBeginB(cpArbiter *arb, cpSpace *space)
+{
+       cpCollisionHandler *handler = arb->handlerB;
+       arb->swapped = !arb->swapped;
+       cpBool retval = handler->beginFunc(arb, space, handler->userData);
+       arb->swapped = !arb->swapped;
+       return retval;
+}
+
+cpBool
+cpArbiterCallWildcardPreSolveA(cpArbiter *arb, cpSpace *space)
+{
+       cpCollisionHandler *handler = arb->handlerA;
+       return handler->preSolveFunc(arb, space, handler->userData);
+}
+
+cpBool
+cpArbiterCallWildcardPreSolveB(cpArbiter *arb, cpSpace *space)
+{
+       cpCollisionHandler *handler = arb->handlerB;
+       arb->swapped = !arb->swapped;
+       cpBool retval = handler->preSolveFunc(arb, space, handler->userData);
+       arb->swapped = !arb->swapped;
+       return retval;
+}
+
+void
+cpArbiterCallWildcardPostSolveA(cpArbiter *arb, cpSpace *space)
+{
+       cpCollisionHandler *handler = arb->handlerA;
+       handler->postSolveFunc(arb, space, handler->userData);
+}
+
+void
+cpArbiterCallWildcardPostSolveB(cpArbiter *arb, cpSpace *space)
+{
+       cpCollisionHandler *handler = arb->handlerB;
+       arb->swapped = !arb->swapped;
+       handler->postSolveFunc(arb, space, handler->userData);
+       arb->swapped = !arb->swapped;
+}
+
+void
+cpArbiterCallWildcardSeparateA(cpArbiter *arb, cpSpace *space)
+{
+       cpCollisionHandler *handler = arb->handlerA;
+       handler->separateFunc(arb, space, handler->userData);
+}
+
+void
+cpArbiterCallWildcardSeparateB(cpArbiter *arb, cpSpace *space)
+{
+       cpCollisionHandler *handler = arb->handlerB;
+       arb->swapped = !arb->swapped;
+       handler->separateFunc(arb, space, handler->userData);
+       arb->swapped = !arb->swapped;
+}
+
+cpArbiter*
+cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b)
+{
+       arb->handler = NULL;
+       arb->swapped = cpFalse;
+       
+       arb->handler = NULL;
+       arb->handlerA = NULL;
+       arb->handlerB = NULL;
+       
+       arb->e = 0.0f;
+       arb->u = 0.0f;
+       arb->surface_vr = cpvzero;
+       
+       arb->count = 0;
+       arb->contacts = NULL;
+       
+       arb->a = a; arb->body_a = a->body;
+       arb->b = b; arb->body_b = b->body;
+       
+       arb->thread_a.next = NULL;
+       arb->thread_b.next = NULL;
+       arb->thread_a.prev = NULL;
+       arb->thread_b.prev = NULL;
+       
+       arb->stamp = 0;
+       arb->state = CP_ARBITER_STATE_FIRST_COLLISION;
+       
+       arb->data = NULL;
+       
+       return arb;
+}
+
+static inline cpCollisionHandler *
+cpSpaceLookupHandler(cpSpace *space, cpCollisionType a, cpCollisionType b, cpCollisionHandler *defaultValue)
+{
+       cpCollisionType types[] = {a, b};
+       cpCollisionHandler *handler = (cpCollisionHandler *)cpHashSetFind(space->collisionHandlers, CP_HASH_PAIR(a, b), types);
+       return (handler ? handler : defaultValue);
+}
+
+void
+cpArbiterUpdate(cpArbiter *arb, struct cpCollisionInfo *info, cpSpace *space)
+{
+       const cpShape *a = info->a, *b = info->b;
+       
+       // For collisions between two similar primitive types, the order could have been swapped since the last frame.
+       arb->a = a; arb->body_a = a->body;
+       arb->b = b; arb->body_b = b->body;
+       
+       // Iterate over the possible pairs to look for hash value matches.
+       for(int i=0; i<info->count; i++){
+               struct cpContact *con = &info->arr[i];
+               
+               // r1 and r2 store absolute offsets at init time.
+               // Need to convert them to relative offsets.
+               con->r1 = cpvsub(con->r1, a->body->p);
+               con->r2 = cpvsub(con->r2, b->body->p);
+               
+               // Cached impulses are not zeroed at init time.
+               con->jnAcc = con->jtAcc = 0.0f;
+               
+               for(int j=0; j<arb->count; j++){
+                       struct cpContact *old = &arb->contacts[j];
+                       
+                       // This could trigger false positives, but is fairly unlikely nor serious if it does.
+                       if(con->hash == old->hash){
+                               // Copy the persistant contact information.
+                               con->jnAcc = old->jnAcc;
+                               con->jtAcc = old->jtAcc;
+                       }
+               }
+       }
+       
+       arb->contacts = info->arr;
+       arb->count = info->count;
+       arb->n = info->n;
+       
+       arb->e = a->e * b->e;
+       arb->u = a->u * b->u;
+       
+       cpVect surface_vr = cpvsub(b->surfaceV, a->surfaceV);
+       arb->surface_vr = cpvsub(surface_vr, cpvmult(info->n, cpvdot(surface_vr, info->n)));
+       
+       cpCollisionType typeA = info->a->type, typeB = info->b->type;
+       cpCollisionHandler *defaultHandler = &space->defaultHandler;
+       cpCollisionHandler *handler = arb->handler = cpSpaceLookupHandler(space, typeA, typeB, defaultHandler);
+       
+       // Check if the types match, but don't swap for a default handler which use the wildcard for type A.
+       cpBool swapped = arb->swapped = (typeA != handler->typeA && handler->typeA != CP_WILDCARD_COLLISION_TYPE);
+       
+       if(handler != defaultHandler || space->usesWildcards){
+               // The order of the main handler swaps the wildcard handlers too. Uffda.
+               arb->handlerA = cpSpaceLookupHandler(space, (swapped ? typeB : typeA), CP_WILDCARD_COLLISION_TYPE, &cpCollisionHandlerDoNothing);
+               arb->handlerB = cpSpaceLookupHandler(space, (swapped ? typeA : typeB), CP_WILDCARD_COLLISION_TYPE, &cpCollisionHandlerDoNothing);
+       }
+               
+       // mark it as new if it's been cached
+       if(arb->state == CP_ARBITER_STATE_CACHED) arb->state = CP_ARBITER_STATE_FIRST_COLLISION;
+}
+
+void
+cpArbiterPreStep(cpArbiter *arb, cpFloat dt, cpFloat slop, cpFloat bias)
+{
+       cpBody *a = arb->body_a;
+       cpBody *b = arb->body_b;
+       cpVect n = arb->n;
+       cpVect body_delta = cpvsub(b->p, a->p);
+       
+       for(int i=0; i<arb->count; i++){
+               struct cpContact *con = &arb->contacts[i];
+               
+               // Calculate the mass normal and mass tangent.
+               con->nMass = 1.0f/k_scalar(a, b, con->r1, con->r2, n);
+               con->tMass = 1.0f/k_scalar(a, b, con->r1, con->r2, cpvperp(n));
+                               
+               // Calculate the target bias velocity.
+               cpFloat dist = cpvdot(cpvadd(cpvsub(con->r2, con->r1), body_delta), n);
+               con->bias = -bias*cpfmin(0.0f, dist + slop)/dt;
+               con->jBias = 0.0f;
+               
+               // Calculate the target bounce velocity.
+               con->bounce = normal_relative_velocity(a, b, con->r1, con->r2, n)*arb->e;
+       }
+}
+
+void
+cpArbiterApplyCachedImpulse(cpArbiter *arb, cpFloat dt_coef)
+{
+       if(cpArbiterIsFirstContact(arb)) return;
+       
+       cpBody *a = arb->body_a;
+       cpBody *b = arb->body_b;
+       cpVect n = arb->n;
+       
+       for(int i=0; i<arb->count; i++){
+               struct cpContact *con = &arb->contacts[i];
+               cpVect j = cpvrotate(n, cpv(con->jnAcc, con->jtAcc));
+               apply_impulses(a, b, con->r1, con->r2, cpvmult(j, dt_coef));
+       }
+}
+
+// TODO: is it worth splitting velocity/position correction?
+
+void
+cpArbiterApplyImpulse(cpArbiter *arb)
+{
+       cpBody *a = arb->body_a;
+       cpBody *b = arb->body_b;
+       cpVect n = arb->n;
+       cpVect surface_vr = arb->surface_vr;
+       cpFloat friction = arb->u;
+
+       for(int i=0; i<arb->count; i++){
+               struct cpContact *con = &arb->contacts[i];
+               cpFloat nMass = con->nMass;
+               cpVect r1 = con->r1;
+               cpVect r2 = con->r2;
+               
+               cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias));
+               cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias));
+               cpVect vr = cpvadd(relative_velocity(a, b, r1, r2), surface_vr);
+               
+               cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n);
+               cpFloat vrn = cpvdot(vr, n);
+               cpFloat vrt = cpvdot(vr, cpvperp(n));
+               
+               cpFloat jbn = (con->bias - vbn)*nMass;
+               cpFloat jbnOld = con->jBias;
+               con->jBias = cpfmax(jbnOld + jbn, 0.0f);
+               
+               cpFloat jn = -(con->bounce + vrn)*nMass;
+               cpFloat jnOld = con->jnAcc;
+               con->jnAcc = cpfmax(jnOld + jn, 0.0f);
+               
+               cpFloat jtMax = friction*con->jnAcc;
+               cpFloat jt = -vrt*con->tMass;
+               cpFloat jtOld = con->jtAcc;
+               con->jtAcc = cpfclamp(jtOld + jt, -jtMax, jtMax);
+               
+               apply_bias_impulses(a, b, r1, r2, cpvmult(n, con->jBias - jbnOld));
+               apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(con->jnAcc - jnOld, con->jtAcc - jtOld)));
+       }
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpArray.c b/dali-physics/third-party/chipmunk2d/src/cpArray.c
new file mode 100644 (file)
index 0000000..a1f8df5
--- /dev/null
@@ -0,0 +1,101 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "chipmunk/chipmunk_private.h"
+
+
+cpArray *
+cpArrayNew(int size)
+{
+       cpArray *arr = (cpArray *)cpcalloc(1, sizeof(cpArray));
+       
+       arr->num = 0;
+       arr->max = (size ? size : 4);
+       arr->arr = (void **)cpcalloc(arr->max, sizeof(void*));
+       
+       return arr;
+}
+
+void
+cpArrayFree(cpArray *arr)
+{
+       if(arr){
+               cpfree(arr->arr);
+               arr->arr = NULL;
+               
+               cpfree(arr);
+       }
+}
+
+void
+cpArrayPush(cpArray *arr, void *object)
+{
+       if(arr->num == arr->max){
+               arr->max = 3*(arr->max + 1)/2;
+               arr->arr = (void **)cprealloc(arr->arr, arr->max*sizeof(void*));
+       }
+       
+       arr->arr[arr->num] = object;
+       arr->num++;
+}
+
+void *
+cpArrayPop(cpArray *arr)
+{
+       arr->num--;
+       
+       void *value = arr->arr[arr->num];
+       arr->arr[arr->num] = NULL;
+       
+       return value;
+}
+
+void
+cpArrayDeleteObj(cpArray *arr, void *obj)
+{
+       for(int i=0; i<arr->num; i++){
+               if(arr->arr[i] == obj){
+                       arr->num--;
+                       
+                       arr->arr[i] = arr->arr[arr->num];
+                       arr->arr[arr->num] = NULL;
+                       
+                       return;
+               }
+       }
+}
+
+void
+cpArrayFreeEach(cpArray *arr, void (freeFunc)(void*))
+{
+       for(int i=0; i<arr->num; i++) freeFunc(arr->arr[i]);
+}
+
+cpBool
+cpArrayContains(cpArray *arr, void *ptr)
+{
+       for(int i=0; i<arr->num; i++)
+               if(arr->arr[i] == ptr) return cpTrue;
+       
+       return cpFalse;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpBBTree.c b/dali-physics/third-party/chipmunk2d/src/cpBBTree.c
new file mode 100644 (file)
index 0000000..eb2944b
--- /dev/null
@@ -0,0 +1,896 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "stdlib.h"
+#include "stdio.h"
+
+#include "chipmunk/chipmunk_private.h"
+
+static inline cpSpatialIndexClass *Klass();
+
+typedef struct Node Node;
+typedef struct Pair Pair;
+
+struct cpBBTree {
+       cpSpatialIndex spatialIndex;
+       cpBBTreeVelocityFunc velocityFunc;
+       
+       cpHashSet *leaves;
+       Node *root;
+       
+       Node *pooledNodes;
+       Pair *pooledPairs;
+       cpArray *allocatedBuffers;
+       
+       cpTimestamp stamp;
+};
+
+struct Node {
+       void *obj;
+       cpBB bb;
+       Node *parent;
+       
+       union {
+               // Internal nodes
+               struct { Node *a, *b; } children;
+               
+               // Leaves
+               struct {
+                       cpTimestamp stamp;
+                       Pair *pairs;
+               } leaf;
+       } node;
+};
+
+// Can't use anonymous unions and still get good x-compiler compatability
+#define A node.children.a
+#define B node.children.b
+#define STAMP node.leaf.stamp
+#define PAIRS node.leaf.pairs
+
+typedef struct Thread {
+       Pair *prev;
+       Node *leaf;
+       Pair *next;
+} Thread;
+
+struct Pair {
+       Thread a, b;
+       cpCollisionID id;
+};
+
+//MARK: Misc Functions
+
+static inline cpBB
+GetBB(cpBBTree *tree, void *obj)
+{
+       cpBB bb = tree->spatialIndex.bbfunc(obj);
+       
+       cpBBTreeVelocityFunc velocityFunc = tree->velocityFunc;
+       if(velocityFunc){
+               cpFloat coef = 0.1f;
+               cpFloat x = (bb.r - bb.l)*coef;
+               cpFloat y = (bb.t - bb.b)*coef;
+               
+               cpVect v = cpvmult(velocityFunc(obj), 0.1f);
+               return cpBBNew(bb.l + cpfmin(-x, v.x), bb.b + cpfmin(-y, v.y), bb.r + cpfmax(x, v.x), bb.t + cpfmax(y, v.y));
+       } else {
+               return bb;
+       }
+}
+
+static inline cpBBTree *
+GetTree(cpSpatialIndex *index)
+{
+       return (index && index->klass == Klass() ? (cpBBTree *)index : NULL);
+}
+
+static inline Node *
+GetRootIfTree(cpSpatialIndex *index){
+       return (index && index->klass == Klass() ? ((cpBBTree *)index)->root : NULL);
+}
+
+static inline cpBBTree *
+GetMasterTree(cpBBTree *tree)
+{
+       cpBBTree *dynamicTree = GetTree(tree->spatialIndex.dynamicIndex);
+       return (dynamicTree ? dynamicTree : tree);
+}
+
+static inline void
+IncrementStamp(cpBBTree *tree)
+{
+       cpBBTree *dynamicTree = GetTree(tree->spatialIndex.dynamicIndex);
+       if(dynamicTree){
+               dynamicTree->stamp++;
+       } else {
+               tree->stamp++;
+       }
+}
+
+//MARK: Pair/Thread Functions
+
+static void
+PairRecycle(cpBBTree *tree, Pair *pair)
+{
+       // Share the pool of the master tree.
+       // TODO: would be lovely to move the pairs stuff into an external data structure.
+       tree = GetMasterTree(tree);
+       
+       pair->a.next = tree->pooledPairs;
+       tree->pooledPairs = pair;
+}
+
+static Pair *
+PairFromPool(cpBBTree *tree)
+{
+       // Share the pool of the master tree.
+       // TODO: would be lovely to move the pairs stuff into an external data structure.
+       tree = GetMasterTree(tree);
+       
+       Pair *pair = tree->pooledPairs;
+       
+       if(pair){
+               tree->pooledPairs = pair->a.next;
+               return pair;
+       } else {
+               // Pool is exhausted, make more
+               int count = CP_BUFFER_BYTES/sizeof(Pair);
+               cpAssertHard(count, "Internal Error: Buffer size is too small.");
+               
+               Pair *buffer = (Pair *)cpcalloc(1, CP_BUFFER_BYTES);
+               cpArrayPush(tree->allocatedBuffers, buffer);
+               
+               // push all but the first one, return the first instead
+               for(int i=1; i<count; i++) PairRecycle(tree, buffer + i);
+               return buffer;
+       }
+}
+
+static inline void
+ThreadUnlink(Thread thread)
+{
+       Pair *next = thread.next;
+       Pair *prev = thread.prev;
+       
+       if(next){
+               if(next->a.leaf == thread.leaf) next->a.prev = prev; else next->b.prev = prev;
+       }
+       
+       if(prev){
+               if(prev->a.leaf == thread.leaf) prev->a.next = next; else prev->b.next = next;
+       } else {
+               thread.leaf->PAIRS = next;
+       }
+}
+
+static void
+PairsClear(Node *leaf, cpBBTree *tree)
+{
+       Pair *pair = leaf->PAIRS;
+       leaf->PAIRS = NULL;
+       
+       while(pair){
+               if(pair->a.leaf == leaf){
+                       Pair *next = pair->a.next;
+                       ThreadUnlink(pair->b);
+                       PairRecycle(tree, pair);
+                       pair = next;
+               } else {
+                       Pair *next = pair->b.next;
+                       ThreadUnlink(pair->a);
+                       PairRecycle(tree, pair);
+                       pair = next;
+               }
+       }
+}
+
+static void
+PairInsert(Node *a, Node *b, cpBBTree *tree)
+{
+       Pair *nextA = a->PAIRS, *nextB = b->PAIRS;
+       Pair *pair = PairFromPool(tree);
+       Pair temp = {{NULL, a, nextA},{NULL, b, nextB}, 0};
+       
+       a->PAIRS = b->PAIRS = pair;
+       *pair = temp;
+       
+       if(nextA){
+               if(nextA->a.leaf == a) nextA->a.prev = pair; else nextA->b.prev = pair;
+       }
+       
+       if(nextB){
+               if(nextB->a.leaf == b) nextB->a.prev = pair; else nextB->b.prev = pair;
+       }
+}
+
+
+//MARK: Node Functions
+
+static void
+NodeRecycle(cpBBTree *tree, Node *node)
+{
+       node->parent = tree->pooledNodes;
+       tree->pooledNodes = node;
+}
+
+static Node *
+NodeFromPool(cpBBTree *tree)
+{
+       Node *node = tree->pooledNodes;
+       
+       if(node){
+               tree->pooledNodes = node->parent;
+               return node;
+       } else {
+               // Pool is exhausted, make more
+               int count = CP_BUFFER_BYTES/sizeof(Node);
+               cpAssertHard(count, "Internal Error: Buffer size is too small.");
+               
+               Node *buffer = (Node *)cpcalloc(1, CP_BUFFER_BYTES);
+               cpArrayPush(tree->allocatedBuffers, buffer);
+               
+               // push all but the first one, return the first instead
+               for(int i=1; i<count; i++) NodeRecycle(tree, buffer + i);
+               return buffer;
+       }
+}
+
+static inline void
+NodeSetA(Node *node, Node *value)
+{
+       node->A = value;
+       value->parent = node;
+}
+
+static inline void
+NodeSetB(Node *node, Node *value)
+{
+       node->B = value;
+       value->parent = node;
+}
+
+static Node *
+NodeNew(cpBBTree *tree, Node *a, Node *b)
+{
+       Node *node = NodeFromPool(tree);
+       
+       node->obj = NULL;
+       node->bb = cpBBMerge(a->bb, b->bb);
+       node->parent = NULL;
+       
+       NodeSetA(node, a);
+       NodeSetB(node, b);
+       
+       return node;
+}
+
+static inline cpBool
+NodeIsLeaf(Node *node)
+{
+       return (node->obj != NULL);
+}
+
+static inline Node *
+NodeOther(Node *node, Node *child)
+{
+       return (node->A == child ? node->B : node->A);
+}
+
+static inline void
+NodeReplaceChild(Node *parent, Node *child, Node *value, cpBBTree *tree)
+{
+       cpAssertSoft(!NodeIsLeaf(parent), "Internal Error: Cannot replace child of a leaf.");
+       cpAssertSoft(child == parent->A || child == parent->B, "Internal Error: Node is not a child of parent.");
+       
+       if(parent->A == child){
+               NodeRecycle(tree, parent->A);
+               NodeSetA(parent, value);
+       } else {
+               NodeRecycle(tree, parent->B);
+               NodeSetB(parent, value);
+       }
+       
+       for(Node *node=parent; node; node = node->parent){
+               node->bb = cpBBMerge(node->A->bb, node->B->bb);
+       }
+}
+
+//MARK: Subtree Functions
+
+static inline cpFloat
+cpBBProximity(cpBB a, cpBB b)
+{
+       return cpfabs(a.l + a.r - b.l - b.r) + cpfabs(a.b + a.t - b.b - b.t);
+}
+
+static Node *
+SubtreeInsert(Node *subtree, Node *leaf, cpBBTree *tree)
+{
+       if(subtree == NULL){
+               return leaf;
+       } else if(NodeIsLeaf(subtree)){
+               return NodeNew(tree, leaf, subtree);
+       } else {
+               cpFloat cost_a = cpBBArea(subtree->B->bb) + cpBBMergedArea(subtree->A->bb, leaf->bb);
+               cpFloat cost_b = cpBBArea(subtree->A->bb) + cpBBMergedArea(subtree->B->bb, leaf->bb);
+               
+               if(cost_a == cost_b){
+                       cost_a = cpBBProximity(subtree->A->bb, leaf->bb);
+                       cost_b = cpBBProximity(subtree->B->bb, leaf->bb);
+               }
+               
+               if(cost_b < cost_a){
+                       NodeSetB(subtree, SubtreeInsert(subtree->B, leaf, tree));
+               } else {
+                       NodeSetA(subtree, SubtreeInsert(subtree->A, leaf, tree));
+               }
+               
+               subtree->bb = cpBBMerge(subtree->bb, leaf->bb);
+               return subtree;
+       }
+}
+
+static void
+SubtreeQuery(Node *subtree, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
+{
+       if(cpBBIntersects(subtree->bb, bb)){
+               if(NodeIsLeaf(subtree)){
+                       func(obj, subtree->obj, 0, data);
+               } else {
+                       SubtreeQuery(subtree->A, obj, bb, func, data);
+                       SubtreeQuery(subtree->B, obj, bb, func, data);
+               }
+       }
+}
+
+
+static cpFloat
+SubtreeSegmentQuery(Node *subtree, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+       if(NodeIsLeaf(subtree)){
+               return func(obj, subtree->obj, data);
+       } else {
+               cpFloat t_a = cpBBSegmentQuery(subtree->A->bb, a, b);
+               cpFloat t_b = cpBBSegmentQuery(subtree->B->bb, a, b);
+               
+               if(t_a < t_b){
+                       if(t_a < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->A, obj, a, b, t_exit, func, data));
+                       if(t_b < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->B, obj, a, b, t_exit, func, data));
+               } else {
+                       if(t_b < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->B, obj, a, b, t_exit, func, data));
+                       if(t_a < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->A, obj, a, b, t_exit, func, data));
+               }
+               
+               return t_exit;
+       }
+}
+
+static void
+SubtreeRecycle(cpBBTree *tree, Node *node)
+{
+       if(!NodeIsLeaf(node)){
+               SubtreeRecycle(tree, node->A);
+               SubtreeRecycle(tree, node->B);
+               NodeRecycle(tree, node);
+       }
+}
+
+static inline Node *
+SubtreeRemove(Node *subtree, Node *leaf, cpBBTree *tree)
+{
+       if(leaf == subtree){
+               return NULL;
+       } else {
+               Node *parent = leaf->parent;
+               if(parent == subtree){
+                       Node *other = NodeOther(subtree, leaf);
+                       other->parent = subtree->parent;
+                       NodeRecycle(tree, subtree);
+                       return other;
+               } else {
+                       NodeReplaceChild(parent->parent, parent, NodeOther(parent, leaf), tree);
+                       return subtree;
+               }
+       }
+}
+
+//MARK: Marking Functions
+
+typedef struct MarkContext {
+       cpBBTree *tree;
+       Node *staticRoot;
+       cpSpatialIndexQueryFunc func;
+       void *data;
+} MarkContext;
+
+static void
+MarkLeafQuery(Node *subtree, Node *leaf, cpBool left, MarkContext *context)
+{
+       if(cpBBIntersects(leaf->bb, subtree->bb)){
+               if(NodeIsLeaf(subtree)){
+                       if(left){
+                               PairInsert(leaf, subtree, context->tree);
+                       } else {
+                               if(subtree->STAMP < leaf->STAMP) PairInsert(subtree, leaf, context->tree);
+                               context->func(leaf->obj, subtree->obj, 0, context->data);
+                       }
+               } else {
+                       MarkLeafQuery(subtree->A, leaf, left, context);
+                       MarkLeafQuery(subtree->B, leaf, left, context);
+               }
+       }
+}
+
+static void
+MarkLeaf(Node *leaf, MarkContext *context)
+{
+       cpBBTree *tree = context->tree;
+       if(leaf->STAMP == GetMasterTree(tree)->stamp){
+               Node *staticRoot = context->staticRoot;
+               if(staticRoot) MarkLeafQuery(staticRoot, leaf, cpFalse, context);
+               
+               for(Node *node = leaf; node->parent; node = node->parent){
+                       if(node == node->parent->A){
+                               MarkLeafQuery(node->parent->B, leaf, cpTrue, context);
+                       } else {
+                               MarkLeafQuery(node->parent->A, leaf, cpFalse, context);
+                       }
+               }
+       } else {
+               Pair *pair = leaf->PAIRS;
+               while(pair){
+                       if(leaf == pair->b.leaf){
+                               pair->id = context->func(pair->a.leaf->obj, leaf->obj, pair->id, context->data);
+                               pair = pair->b.next;
+                       } else {
+                               pair = pair->a.next;
+                       }
+               }
+       }
+}
+
+static void
+MarkSubtree(Node *subtree, MarkContext *context)
+{
+       if(NodeIsLeaf(subtree)){
+               MarkLeaf(subtree, context);
+       } else {
+               MarkSubtree(subtree->A, context);
+               MarkSubtree(subtree->B, context); // TODO: Force TCO here?
+       }
+}
+
+//MARK: Leaf Functions
+
+static Node *
+LeafNew(cpBBTree *tree, void *obj, cpBB bb)
+{
+       Node *node = NodeFromPool(tree);
+       node->obj = obj;
+       node->bb = GetBB(tree, obj);
+       
+       node->parent = NULL;
+       node->STAMP = 0;
+       node->PAIRS = NULL;
+       
+       return node;
+}
+
+static cpBool
+LeafUpdate(Node *leaf, cpBBTree *tree)
+{
+       Node *root = tree->root;
+       cpBB bb = tree->spatialIndex.bbfunc(leaf->obj);
+       
+       if(!cpBBContainsBB(leaf->bb, bb)){
+               leaf->bb = GetBB(tree, leaf->obj);
+               
+               root = SubtreeRemove(root, leaf, tree);
+               tree->root = SubtreeInsert(root, leaf, tree);
+               
+               PairsClear(leaf, tree);
+               leaf->STAMP = GetMasterTree(tree)->stamp;
+               
+               return cpTrue;
+       } else {
+               return cpFalse;
+       }
+}
+
+static cpCollisionID VoidQueryFunc(void *obj1, void *obj2, cpCollisionID id, void *data){return id;}
+
+static void
+LeafAddPairs(Node *leaf, cpBBTree *tree)
+{
+       cpSpatialIndex *dynamicIndex = tree->spatialIndex.dynamicIndex;
+       if(dynamicIndex){
+               Node *dynamicRoot = GetRootIfTree(dynamicIndex);
+               if(dynamicRoot){
+                       cpBBTree *dynamicTree = GetTree(dynamicIndex);
+                       MarkContext context = {dynamicTree, NULL, NULL, NULL};
+                       MarkLeafQuery(dynamicRoot, leaf, cpTrue, &context);
+               }
+       } else {
+               Node *staticRoot = GetRootIfTree(tree->spatialIndex.staticIndex);
+               MarkContext context = {tree, staticRoot, VoidQueryFunc, NULL};
+               MarkLeaf(leaf, &context);
+       }
+}
+
+//MARK: Memory Management Functions
+
+cpBBTree *
+cpBBTreeAlloc(void)
+{
+       return (cpBBTree *)cpcalloc(1, sizeof(cpBBTree));
+}
+
+static int
+leafSetEql(void *obj, Node *node)
+{
+       return (obj == node->obj);
+}
+
+static void *
+leafSetTrans(void *obj, cpBBTree *tree)
+{
+       return LeafNew(tree, obj, tree->spatialIndex.bbfunc(obj));
+}
+
+cpSpatialIndex *
+cpBBTreeInit(cpBBTree *tree, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+       cpSpatialIndexInit((cpSpatialIndex *)tree, Klass(), bbfunc, staticIndex);
+       
+       tree->velocityFunc = NULL;
+       
+       tree->leaves = cpHashSetNew(0, (cpHashSetEqlFunc)leafSetEql);
+       tree->root = NULL;
+       
+       tree->pooledNodes = NULL;
+       tree->allocatedBuffers = cpArrayNew(0);
+       
+       tree->stamp = 0;
+       
+       return (cpSpatialIndex *)tree;
+}
+
+void
+cpBBTreeSetVelocityFunc(cpSpatialIndex *index, cpBBTreeVelocityFunc func)
+{
+       if(index->klass != Klass()){
+               cpAssertWarn(cpFalse, "Ignoring cpBBTreeSetVelocityFunc() call to non-tree spatial index.");
+               return;
+       }
+       
+       ((cpBBTree *)index)->velocityFunc = func;
+}
+
+cpSpatialIndex *
+cpBBTreeNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+       return cpBBTreeInit(cpBBTreeAlloc(), bbfunc, staticIndex);
+}
+
+static void
+cpBBTreeDestroy(cpBBTree *tree)
+{
+       cpHashSetFree(tree->leaves);
+       
+       if(tree->allocatedBuffers) cpArrayFreeEach(tree->allocatedBuffers, cpfree);
+       cpArrayFree(tree->allocatedBuffers);
+}
+
+//MARK: Insert/Remove
+
+static void
+cpBBTreeInsert(cpBBTree *tree, void *obj, cpHashValue hashid)
+{
+       Node *leaf = (Node *)cpHashSetInsert(tree->leaves, hashid, obj, (cpHashSetTransFunc)leafSetTrans, tree);
+       
+       Node *root = tree->root;
+       tree->root = SubtreeInsert(root, leaf, tree);
+       
+       leaf->STAMP = GetMasterTree(tree)->stamp;
+       LeafAddPairs(leaf, tree);
+       IncrementStamp(tree);
+}
+
+static void
+cpBBTreeRemove(cpBBTree *tree, void *obj, cpHashValue hashid)
+{
+       Node *leaf = (Node *)cpHashSetRemove(tree->leaves, hashid, obj);
+       
+       tree->root = SubtreeRemove(tree->root, leaf, tree);
+       PairsClear(leaf, tree);
+       NodeRecycle(tree, leaf);
+}
+
+static cpBool
+cpBBTreeContains(cpBBTree *tree, void *obj, cpHashValue hashid)
+{
+       return (cpHashSetFind(tree->leaves, hashid, obj) != NULL);
+}
+
+//MARK: Reindex
+
+static void LeafUpdateWrap(Node *leaf, cpBBTree *tree) {LeafUpdate(leaf, tree);}
+
+static void
+cpBBTreeReindexQuery(cpBBTree *tree, cpSpatialIndexQueryFunc func, void *data)
+{
+       if(!tree->root) return;
+       
+       // LeafUpdate() may modify tree->root. Don't cache it.
+       cpHashSetEach(tree->leaves, (cpHashSetIteratorFunc)LeafUpdateWrap, tree);
+       
+       cpSpatialIndex *staticIndex = tree->spatialIndex.staticIndex;
+       Node *staticRoot = (staticIndex && staticIndex->klass == Klass() ? ((cpBBTree *)staticIndex)->root : NULL);
+       
+       MarkContext context = {tree, staticRoot, func, data};
+       MarkSubtree(tree->root, &context);
+       if(staticIndex && !staticRoot) cpSpatialIndexCollideStatic((cpSpatialIndex *)tree, staticIndex, func, data);
+       
+       IncrementStamp(tree);
+}
+
+static void
+cpBBTreeReindex(cpBBTree *tree)
+{
+       cpBBTreeReindexQuery(tree, VoidQueryFunc, NULL);
+}
+
+static void
+cpBBTreeReindexObject(cpBBTree *tree, void *obj, cpHashValue hashid)
+{
+       Node *leaf = (Node *)cpHashSetFind(tree->leaves, hashid, obj);
+       if(leaf){
+               if(LeafUpdate(leaf, tree)) LeafAddPairs(leaf, tree);
+               IncrementStamp(tree);
+       }
+}
+
+//MARK: Query
+
+static void
+cpBBTreeSegmentQuery(cpBBTree *tree, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+       Node *root = tree->root;
+       if(root) SubtreeSegmentQuery(root, obj, a, b, t_exit, func, data);
+}
+
+static void
+cpBBTreeQuery(cpBBTree *tree, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
+{
+       if(tree->root) SubtreeQuery(tree->root, obj, bb, func, data);
+}
+
+//MARK: Misc
+
+static int
+cpBBTreeCount(cpBBTree *tree)
+{
+       return cpHashSetCount(tree->leaves);
+}
+
+typedef struct eachContext {
+       cpSpatialIndexIteratorFunc func;
+       void *data;
+} eachContext;
+
+static void each_helper(Node *node, eachContext *context){context->func(node->obj, context->data);}
+
+static void
+cpBBTreeEach(cpBBTree *tree, cpSpatialIndexIteratorFunc func, void *data)
+{
+       eachContext context = {func, data};
+       cpHashSetEach(tree->leaves, (cpHashSetIteratorFunc)each_helper, &context);
+}
+
+static cpSpatialIndexClass klass = {
+       (cpSpatialIndexDestroyImpl)cpBBTreeDestroy,
+       
+       (cpSpatialIndexCountImpl)cpBBTreeCount,
+       (cpSpatialIndexEachImpl)cpBBTreeEach,
+       
+       (cpSpatialIndexContainsImpl)cpBBTreeContains,
+       (cpSpatialIndexInsertImpl)cpBBTreeInsert,
+       (cpSpatialIndexRemoveImpl)cpBBTreeRemove,
+       
+       (cpSpatialIndexReindexImpl)cpBBTreeReindex,
+       (cpSpatialIndexReindexObjectImpl)cpBBTreeReindexObject,
+       (cpSpatialIndexReindexQueryImpl)cpBBTreeReindexQuery,
+       
+       (cpSpatialIndexQueryImpl)cpBBTreeQuery,
+       (cpSpatialIndexSegmentQueryImpl)cpBBTreeSegmentQuery,
+};
+
+static inline cpSpatialIndexClass *Klass(){return &klass;}
+
+
+//MARK: Tree Optimization
+
+static int
+cpfcompare(const cpFloat *a, const cpFloat *b){
+       return (*a < *b ? -1 : (*b < *a ? 1 : 0));
+}
+
+static void
+fillNodeArray(Node *node, Node ***cursor){
+       (**cursor) = node;
+       (*cursor)++;
+}
+
+static Node *
+partitionNodes(cpBBTree *tree, Node **nodes, int count)
+{
+       if(count == 1){
+               return nodes[0];
+       } else if(count == 2) {
+               return NodeNew(tree, nodes[0], nodes[1]);
+       }
+       
+       // Find the AABB for these nodes
+       cpBB bb = nodes[0]->bb;
+       for(int i=1; i<count; i++) bb = cpBBMerge(bb, nodes[i]->bb);
+       
+       // Split it on it's longest axis
+       cpBool splitWidth = (bb.r - bb.l > bb.t - bb.b);
+       
+       // Sort the bounds and use the median as the splitting point
+       cpFloat *bounds = (cpFloat *)cpcalloc(count*2, sizeof(cpFloat));
+       if(splitWidth){
+               for(int i=0; i<count; i++){
+                       bounds[2*i + 0] = nodes[i]->bb.l;
+                       bounds[2*i + 1] = nodes[i]->bb.r;
+               }
+       } else {
+               for(int i=0; i<count; i++){
+                       bounds[2*i + 0] = nodes[i]->bb.b;
+                       bounds[2*i + 1] = nodes[i]->bb.t;
+               }
+       }
+       
+       qsort(bounds, count*2, sizeof(cpFloat), (int (*)(const void *, const void *))cpfcompare);
+       cpFloat split = (bounds[count - 1] + bounds[count])*0.5f; // use the medain as the split
+       cpfree(bounds);
+
+       // Generate the child BBs
+       cpBB a = bb, b = bb;
+       if(splitWidth) a.r = b.l = split; else a.t = b.b = split;
+       
+       // Partition the nodes
+       int right = count;
+       for(int left=0; left < right;){
+               Node *node = nodes[left];
+               if(cpBBMergedArea(node->bb, b) < cpBBMergedArea(node->bb, a)){
+//             if(cpBBProximity(node->bb, b) < cpBBProximity(node->bb, a)){
+                       right--;
+                       nodes[left] = nodes[right];
+                       nodes[right] = node;
+               } else {
+                       left++;
+               }
+       }
+       
+       if(right == count){
+               Node *node = NULL;
+               for(int i=0; i<count; i++) node = SubtreeInsert(node, nodes[i], tree);
+               return node;
+       }
+       
+       // Recurse and build the node!
+       return NodeNew(tree,
+               partitionNodes(tree, nodes, right),
+               partitionNodes(tree, nodes + right, count - right)
+       );
+}
+
+//static void
+//cpBBTreeOptimizeIncremental(cpBBTree *tree, int passes)
+//{
+//     for(int i=0; i<passes; i++){
+//             Node *root = tree->root;
+//             Node *node = root;
+//             int bit = 0;
+//             unsigned int path = tree->opath;
+//             
+//             while(!NodeIsLeaf(node)){
+//                     node = (path&(1<<bit) ? node->a : node->b);
+//                     bit = (bit + 1)&(sizeof(unsigned int)*8 - 1);
+//             }
+//             
+//             root = subtreeRemove(root, node, tree);
+//             tree->root = subtreeInsert(root, node, tree);
+//     }
+//}
+
+void
+cpBBTreeOptimize(cpSpatialIndex *index)
+{
+       if(index->klass != &klass){
+               cpAssertWarn(cpFalse, "Ignoring cpBBTreeOptimize() call to non-tree spatial index.");
+               return;
+       }
+       
+       cpBBTree *tree = (cpBBTree *)index;
+       Node *root = tree->root;
+       if(!root) return;
+       
+       int count = cpBBTreeCount(tree);
+       Node **nodes = (Node **)cpcalloc(count, sizeof(Node *));
+       Node **cursor = nodes;
+       
+       cpHashSetEach(tree->leaves, (cpHashSetIteratorFunc)fillNodeArray, &cursor);
+       
+       SubtreeRecycle(tree, root);
+       tree->root = partitionNodes(tree, nodes, count);
+       cpfree(nodes);
+}
+
+//MARK: Debug Draw
+
+//#define CP_BBTREE_DEBUG_DRAW
+#ifdef CP_BBTREE_DEBUG_DRAW
+#include "OpenGL/gl.h"
+#include "OpenGL/glu.h"
+#include <GLUT/glut.h>
+
+static void
+NodeRender(Node *node, int depth)
+{
+       if(!NodeIsLeaf(node) && depth <= 10){
+               NodeRender(node->a, depth + 1);
+               NodeRender(node->b, depth + 1);
+       }
+       
+       cpBB bb = node->bb;
+       
+//     GLfloat v = depth/2.0f; 
+//     glColor3f(1.0f - v, v, 0.0f);
+       glLineWidth(cpfmax(5.0f - depth, 1.0f));
+       glBegin(GL_LINES); {
+               glVertex2f(bb.l, bb.b);
+               glVertex2f(bb.l, bb.t);
+               
+               glVertex2f(bb.l, bb.t);
+               glVertex2f(bb.r, bb.t);
+               
+               glVertex2f(bb.r, bb.t);
+               glVertex2f(bb.r, bb.b);
+               
+               glVertex2f(bb.r, bb.b);
+               glVertex2f(bb.l, bb.b);
+       }; glEnd();
+}
+
+void
+cpBBTreeRenderDebug(cpSpatialIndex *index){
+       if(index->klass != &klass){
+               cpAssertWarn(cpFalse, "Ignoring cpBBTreeRenderDebug() call to non-tree spatial index.");
+               return;
+       }
+       
+       cpBBTree *tree = (cpBBTree *)index;
+       if(tree->root) NodeRender(tree->root, 0);
+}
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/src/cpBody.c b/dali-physics/third-party/chipmunk2d/src/cpBody.c
new file mode 100644 (file)
index 0000000..8ad2bc9
--- /dev/null
@@ -0,0 +1,626 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <float.h>
+#include <stdarg.h>
+
+#include "chipmunk/chipmunk_private.h"
+
+cpBody*
+cpBodyAlloc(void)
+{
+       return (cpBody *)cpcalloc(1, sizeof(cpBody));
+}
+
+cpBody *
+cpBodyInit(cpBody *body, cpFloat mass, cpFloat moment)
+{
+       body->space = NULL;
+       body->shapeList = NULL;
+       body->arbiterList = NULL;
+       body->constraintList = NULL;
+       
+       body->velocity_func = cpBodyUpdateVelocity;
+       body->position_func = cpBodyUpdatePosition;
+       
+       body->sleeping.root = NULL;
+       body->sleeping.next = NULL;
+       body->sleeping.idleTime = 0.0f;
+       
+       body->p = cpvzero;
+       body->v = cpvzero;
+       body->f = cpvzero;
+       
+       body->w = 0.0f;
+       body->t = 0.0f;
+       
+       body->v_bias = cpvzero;
+       body->w_bias = 0.0f;
+       
+       body->userData = NULL;
+       
+       // Setters must be called after full initialization so the sanity checks don't assert on garbage data.
+       cpBodySetMass(body, mass);
+       cpBodySetMoment(body, moment);
+       cpBodySetAngle(body, 0.0f);
+       
+       return body;
+}
+
+cpBody*
+cpBodyNew(cpFloat mass, cpFloat moment)
+{
+       return cpBodyInit(cpBodyAlloc(), mass, moment);
+}
+
+cpBody*
+cpBodyNewKinematic()
+{
+       cpBody *body = cpBodyNew(0.0f, 0.0f);
+       cpBodySetType(body, CP_BODY_TYPE_KINEMATIC);
+       
+       return body;
+}
+
+cpBody*
+cpBodyNewStatic()
+{
+       cpBody *body = cpBodyNew(0.0f, 0.0f);
+       cpBodySetType(body, CP_BODY_TYPE_STATIC);
+       
+       return body;
+}
+
+void cpBodyDestroy(cpBody *body){}
+
+void
+cpBodyFree(cpBody *body)
+{
+       if(body){
+               cpBodyDestroy(body);
+               cpfree(body);
+       }
+}
+
+#ifdef NDEBUG
+       #define cpAssertSaneBody(body)
+#else
+       static void cpv_assert_nan(cpVect v, char *message){cpAssertHard(v.x == v.x && v.y == v.y, message);}
+       static void cpv_assert_infinite(cpVect v, char *message){cpAssertHard(cpfabs(v.x) != INFINITY && cpfabs(v.y) != INFINITY, message);}
+       static void cpv_assert_sane(cpVect v, char *message){cpv_assert_nan(v, message); cpv_assert_infinite(v, message);}
+       
+       static void
+       cpBodySanityCheck(const cpBody *body)
+       {
+               cpAssertHard(body->m == body->m && body->m_inv == body->m_inv, "Body's mass is NaN.");
+               cpAssertHard(body->i == body->i && body->i_inv == body->i_inv, "Body's moment is NaN.");
+               cpAssertHard(body->m >= 0.0f, "Body's mass is negative.");
+               cpAssertHard(body->i >= 0.0f, "Body's moment is negative.");
+               
+               cpv_assert_sane(body->p, "Body's position is invalid.");
+               cpv_assert_sane(body->v, "Body's velocity is invalid.");
+               cpv_assert_sane(body->f, "Body's force is invalid.");
+
+               cpAssertHard(body->a == body->a && cpfabs(body->a) != INFINITY, "Body's angle is invalid.");
+               cpAssertHard(body->w == body->w && cpfabs(body->w) != INFINITY, "Body's angular velocity is invalid.");
+               cpAssertHard(body->t == body->t && cpfabs(body->t) != INFINITY, "Body's torque is invalid.");
+       }
+       
+       #define cpAssertSaneBody(body) cpBodySanityCheck(body)
+#endif
+
+cpBool
+cpBodyIsSleeping(const cpBody *body)
+{
+       return (body->sleeping.root != ((cpBody*)0));
+}
+
+cpBodyType
+cpBodyGetType(cpBody *body)
+{
+       if(body->sleeping.idleTime == INFINITY){
+               return CP_BODY_TYPE_STATIC;
+       } else if(body->m == INFINITY){
+               return CP_BODY_TYPE_KINEMATIC;
+       } else {
+               return CP_BODY_TYPE_DYNAMIC;
+       }
+}
+
+void
+cpBodySetType(cpBody *body, cpBodyType type)
+{
+       cpBodyType oldType = cpBodyGetType(body);
+       if(oldType == type) return;
+       
+       // Static bodies have their idle timers set to infinity.
+       // Non-static bodies should have their idle timer reset.
+       body->sleeping.idleTime = (type == CP_BODY_TYPE_STATIC ? INFINITY : 0.0f);
+       
+       if(type == CP_BODY_TYPE_DYNAMIC){
+               body->m = body->i = 0.0f;
+               body->m_inv = body->i_inv = INFINITY;
+               
+               cpBodyAccumulateMassFromShapes(body);
+       } else {
+               body->m = body->i = INFINITY;
+               body->m_inv = body->i_inv = 0.0f;
+               
+               body->v = cpvzero;
+               body->w = 0.0f;
+       }
+       
+       // If the body is added to a space already, we'll need to update some space data structures.
+       cpSpace *space = cpBodyGetSpace(body);
+       if(space != NULL){
+               cpAssertSpaceUnlocked(space);
+               
+               if(oldType == CP_BODY_TYPE_STATIC){
+                       // TODO This is probably not necessary
+//                     cpBodyActivateStatic(body, NULL);
+               } else {
+                       cpBodyActivate(body);
+               }
+               
+               // Move the bodies to the correct array.
+               cpArray *fromArray = cpSpaceArrayForBodyType(space, oldType);
+               cpArray *toArray = cpSpaceArrayForBodyType(space, type);
+               if(fromArray != toArray){
+                       cpArrayDeleteObj(fromArray, body);
+                       cpArrayPush(toArray, body);
+               }
+               
+               // Move the body's shapes to the correct spatial index.
+               cpSpatialIndex *fromIndex = (oldType == CP_BODY_TYPE_STATIC ? space->staticShapes : space->dynamicShapes);
+               cpSpatialIndex *toIndex = (type == CP_BODY_TYPE_STATIC ? space->staticShapes : space->dynamicShapes);
+               if(fromIndex != toIndex){
+                       CP_BODY_FOREACH_SHAPE(body, shape){
+                               cpSpatialIndexRemove(fromIndex, shape, shape->hashid);
+                               cpSpatialIndexInsert(toIndex, shape, shape->hashid);
+                       }
+               }
+       }
+}
+
+
+
+// Should *only* be called when shapes with mass info are modified, added or removed.
+void
+cpBodyAccumulateMassFromShapes(cpBody *body)
+{
+       if(body == NULL || cpBodyGetType(body) != CP_BODY_TYPE_DYNAMIC) return;
+       
+       // Reset the body's mass data.
+       body->m = body->i = 0.0f;
+       body->cog = cpvzero;
+       
+       // Cache the position to realign it at the end.
+       cpVect pos = cpBodyGetPosition(body);
+       
+       // Accumulate mass from shapes.
+       CP_BODY_FOREACH_SHAPE(body, shape){
+               struct cpShapeMassInfo *info = &shape->massInfo;
+               cpFloat m = info->m;
+               
+               if(m > 0.0f){
+                       cpFloat msum = body->m + m;
+                       
+                       body->i += m*info->i + cpvdistsq(body->cog, info->cog)*(m*body->m)/msum;
+                       body->cog = cpvlerp(body->cog, info->cog, m/msum);
+                       body->m = msum;
+               }
+       }
+       
+       // Recalculate the inverses.
+       body->m_inv = 1.0f/body->m;
+       body->i_inv = 1.0f/body->i;
+       
+       // Realign the body since the CoG has probably moved.
+       cpBodySetPosition(body, pos);
+       cpAssertSaneBody(body);
+}
+
+cpSpace *
+cpBodyGetSpace(const cpBody *body)
+{
+       return body->space;
+}
+
+cpFloat
+cpBodyGetMass(const cpBody *body)
+{
+       return body->m;
+}
+
+void
+cpBodySetMass(cpBody *body, cpFloat mass)
+{
+       cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "You cannot set the mass of kinematic or static bodies.");
+       cpAssertHard(0.0f <= mass && mass < INFINITY, "Mass must be positive and finite.");
+       
+       cpBodyActivate(body);
+       body->m = mass;
+       body->m_inv = mass == 0.0f ? INFINITY : 1.0f/mass;
+       cpAssertSaneBody(body);
+}
+
+cpFloat
+cpBodyGetMoment(const cpBody *body)
+{
+       return body->i;
+}
+
+void
+cpBodySetMoment(cpBody *body, cpFloat moment)
+{
+       cpAssertHard(moment >= 0.0f, "Moment of Inertia must be positive.");
+       
+       cpBodyActivate(body);
+       body->i = moment;
+       body->i_inv = moment == 0.0f ? INFINITY : 1.0f/moment;
+       cpAssertSaneBody(body);
+}
+
+cpVect
+cpBodyGetRotation(const cpBody *body)
+{
+       return cpv(body->transform.a, body->transform.b);
+}
+
+void
+cpBodyAddShape(cpBody *body, cpShape *shape)
+{
+       cpShape *next = body->shapeList;
+       if(next) next->prev = shape;
+       
+       shape->next = next;
+       body->shapeList = shape;
+       
+       if(shape->massInfo.m > 0.0f){
+               cpBodyAccumulateMassFromShapes(body);
+       }
+}
+
+void
+cpBodyRemoveShape(cpBody *body, cpShape *shape)
+{
+  cpShape *prev = shape->prev;
+  cpShape *next = shape->next;
+  
+  if(prev){
+               prev->next = next;
+  } else {
+               body->shapeList = next;
+  }
+  
+  if(next){
+               next->prev = prev;
+       }
+  
+  shape->prev = NULL;
+  shape->next = NULL;
+       
+       if(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC && shape->massInfo.m > 0.0f){
+               cpBodyAccumulateMassFromShapes(body);
+       }
+}
+
+static cpConstraint *
+filterConstraints(cpConstraint *node, cpBody *body, cpConstraint *filter)
+{
+       if(node == filter){
+               return cpConstraintNext(node, body);
+       } else if(node->a == body){
+               node->next_a = filterConstraints(node->next_a, body, filter);
+       } else {
+               node->next_b = filterConstraints(node->next_b, body, filter);
+       }
+       
+       return node;
+}
+
+void
+cpBodyRemoveConstraint(cpBody *body, cpConstraint *constraint)
+{
+       body->constraintList = filterConstraints(body->constraintList, body, constraint);
+}
+
+// 'p' is the position of the CoG
+static void
+SetTransform(cpBody *body, cpVect p, cpFloat a)
+{
+       cpVect rot = cpvforangle(a);
+       cpVect c = body->cog;
+       
+       body->transform = cpTransformNewTranspose(
+               rot.x, -rot.y, p.x - (c.x*rot.x - c.y*rot.y),
+               rot.y,  rot.x, p.y - (c.x*rot.y + c.y*rot.x)
+       );
+}
+
+static inline cpFloat
+SetAngle(cpBody *body, cpFloat a)
+{
+       body->a = a;
+       cpAssertSaneBody(body);
+       
+       return a;
+}
+
+cpVect
+cpBodyGetPosition(const cpBody *body)
+{
+       return cpTransformPoint(body->transform, cpvzero);
+}
+
+void
+cpBodySetPosition(cpBody *body, cpVect position)
+{
+       cpBodyActivate(body);
+       cpVect p = body->p = cpvadd(cpTransformVect(body->transform, body->cog), position);
+       cpAssertSaneBody(body);
+       
+       SetTransform(body, p, body->a);
+}
+
+cpVect
+cpBodyGetCenterOfGravity(const cpBody *body)
+{
+       return body->cog;
+}
+
+void
+cpBodySetCenterOfGravity(cpBody *body, cpVect cog)
+{
+       cpBodyActivate(body);
+       body->cog = cog;
+       cpAssertSaneBody(body);
+}
+
+cpVect
+cpBodyGetVelocity(const cpBody *body)
+{
+       return body->v;
+}
+
+void
+cpBodySetVelocity(cpBody *body, cpVect velocity)
+{
+       cpBodyActivate(body);
+       body->v = velocity;
+       cpAssertSaneBody(body);
+}
+
+cpVect
+cpBodyGetForce(const cpBody *body)
+{
+       return body->f;
+}
+
+void
+cpBodySetForce(cpBody *body, cpVect force)
+{
+       cpBodyActivate(body);
+       body->f = force;
+       cpAssertSaneBody(body);
+}
+
+cpFloat
+cpBodyGetAngle(const cpBody *body)
+{
+       return body->a;
+}
+
+void
+cpBodySetAngle(cpBody *body, cpFloat angle)
+{
+       cpBodyActivate(body);
+       SetAngle(body, angle);
+       
+       SetTransform(body, body->p, angle);
+}
+
+cpFloat
+cpBodyGetAngularVelocity(const cpBody *body)
+{
+       return body->w;
+}
+
+void
+cpBodySetAngularVelocity(cpBody *body, cpFloat angularVelocity)
+{
+       cpBodyActivate(body);
+       body->w = angularVelocity;
+       cpAssertSaneBody(body);
+}
+
+cpFloat
+cpBodyGetTorque(const cpBody *body)
+{
+       return body->t;
+}
+
+void
+cpBodySetTorque(cpBody *body, cpFloat torque)
+{
+       cpBodyActivate(body);
+       body->t = torque;
+       cpAssertSaneBody(body);
+}
+
+cpDataPointer
+cpBodyGetUserData(const cpBody *body)
+{
+       return body->userData;
+}
+
+void
+cpBodySetUserData(cpBody *body, cpDataPointer userData)
+{
+       body->userData = userData;
+}
+
+void
+cpBodySetVelocityUpdateFunc(cpBody *body, cpBodyVelocityFunc velocityFunc)
+{
+       body->velocity_func = velocityFunc;
+}
+
+void
+cpBodySetPositionUpdateFunc(cpBody *body, cpBodyPositionFunc positionFunc)
+{
+       body->position_func = positionFunc;
+}
+
+void
+cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
+{
+       // Skip kinematic bodies.
+       if(cpBodyGetType(body) == CP_BODY_TYPE_KINEMATIC) return;
+       
+       cpAssertSoft(body->m > 0.0f && body->i > 0.0f, "Body's mass and moment must be positive to simulate. (Mass: %f Moment: %f)", body->m, body->i);
+       
+       body->v = cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt));
+       body->w = body->w*damping + body->t*body->i_inv*dt;
+       
+       // Reset forces.
+       body->f = cpvzero;
+       body->t = 0.0f;
+       
+       cpAssertSaneBody(body);
+}
+
+void
+cpBodyUpdatePosition(cpBody *body, cpFloat dt)
+{
+       cpVect p = body->p = cpvadd(body->p, cpvmult(cpvadd(body->v, body->v_bias), dt));
+       cpFloat a = SetAngle(body, body->a + (body->w + body->w_bias)*dt);
+       SetTransform(body, p, a);
+       
+       body->v_bias = cpvzero;
+       body->w_bias = 0.0f;
+       
+       cpAssertSaneBody(body);
+}
+
+cpVect
+cpBodyLocalToWorld(const cpBody *body, const cpVect point)
+{
+       return cpTransformPoint(body->transform, point);
+}
+
+cpVect
+cpBodyWorldToLocal(const cpBody *body, const cpVect point)
+{
+       return cpTransformPoint(cpTransformRigidInverse(body->transform), point);
+}
+
+void
+cpBodyApplyForceAtWorldPoint(cpBody *body, cpVect force, cpVect point)
+{
+       cpBodyActivate(body);
+       body->f = cpvadd(body->f, force);
+       
+       cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog));
+       body->t += cpvcross(r, force);
+}
+
+void
+cpBodyApplyForceAtLocalPoint(cpBody *body, cpVect force, cpVect point)
+{
+       cpBodyApplyForceAtWorldPoint(body, cpTransformVect(body->transform, force), cpTransformPoint(body->transform, point));
+}
+
+void
+cpBodyApplyImpulseAtWorldPoint(cpBody *body, cpVect impulse, cpVect point)
+{
+       cpBodyActivate(body);
+       
+       cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog));
+       apply_impulse(body, impulse, r);
+}
+
+void
+cpBodyApplyImpulseAtLocalPoint(cpBody *body, cpVect impulse, cpVect point)
+{
+       cpBodyApplyImpulseAtWorldPoint(body, cpTransformVect(body->transform, impulse), cpTransformPoint(body->transform, point));
+}
+
+cpVect
+cpBodyGetVelocityAtLocalPoint(const cpBody *body, cpVect point)
+{
+       cpVect r = cpTransformVect(body->transform, cpvsub(point, body->cog));
+       return cpvadd(body->v, cpvmult(cpvperp(r), body->w));
+}
+
+cpVect
+cpBodyGetVelocityAtWorldPoint(const cpBody *body, cpVect point)
+{
+       cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog));
+       return cpvadd(body->v, cpvmult(cpvperp(r), body->w));
+}
+
+cpFloat
+cpBodyKineticEnergy(const cpBody *body)
+{
+       // Need to do some fudging to avoid NaNs
+       cpFloat vsq = cpvdot(body->v, body->v);
+       cpFloat wsq = body->w*body->w;
+       return (vsq ? vsq*body->m : 0.0f) + (wsq ? wsq*body->i : 0.0f);
+}
+
+void
+cpBodyEachShape(cpBody *body, cpBodyShapeIteratorFunc func, void *data)
+{
+       cpShape *shape = body->shapeList;
+       while(shape){
+               cpShape *next = shape->next;
+               func(body, shape, data);
+               shape = next;
+       }
+}
+
+void
+cpBodyEachConstraint(cpBody *body, cpBodyConstraintIteratorFunc func, void *data)
+{
+       cpConstraint *constraint = body->constraintList;
+       while(constraint){
+               cpConstraint *next = cpConstraintNext(constraint, body);
+               func(body, constraint, data);
+               constraint = next;
+       }
+}
+
+void
+cpBodyEachArbiter(cpBody *body, cpBodyArbiterIteratorFunc func, void *data)
+{
+       cpArbiter *arb = body->arbiterList;
+       while(arb){
+               cpArbiter *next = cpArbiterNext(arb, body);
+               
+               cpBool swapped = arb->swapped; {
+                       arb->swapped = (body == arb->body_b);
+                       func(body, arb, data);
+               } arb->swapped = swapped;
+               
+               arb = next;
+       }
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpCollision.c b/dali-physics/third-party/chipmunk2d/src/cpCollision.c
new file mode 100644 (file)
index 0000000..0d31473
--- /dev/null
@@ -0,0 +1,726 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "chipmunk/chipmunk_private.h"
+#include "chipmunk/cpRobust.h"
+
+#if DEBUG && 0
+#include "ChipmunkDemo.h"
+#define DRAW_ALL 0
+#define DRAW_GJK (0 || DRAW_ALL)
+#define DRAW_EPA (0 || DRAW_ALL)
+#define DRAW_CLOSEST (0 || DRAW_ALL)
+#define DRAW_CLIP (0 || DRAW_ALL)
+
+#define PRINT_LOG 0
+#endif
+
+#define MAX_GJK_ITERATIONS 30
+#define MAX_EPA_ITERATIONS 30
+#define WARN_GJK_ITERATIONS 20
+#define WARN_EPA_ITERATIONS 20
+
+static inline void
+cpCollisionInfoPushContact(struct cpCollisionInfo *info, cpVect p1, cpVect p2, cpHashValue hash)
+{
+       cpAssertSoft(info->count <= CP_MAX_CONTACTS_PER_ARBITER, "Internal error: Tried to push too many contacts.");
+       
+       struct cpContact *con = &info->arr[info->count];
+       con->r1 = p1;
+       con->r2 = p2;
+       con->hash = hash;
+       
+       info->count++;
+}
+
+//MARK: Support Points and Edges:
+
+// Support points are the maximal points on a shape's perimeter along a certain axis.
+// The GJK and EPA algorithms use support points to iteratively sample the surface of the two shapes' minkowski difference.
+
+static inline int
+PolySupportPointIndex(const int count, const struct cpSplittingPlane *planes, const cpVect n)
+{
+       cpFloat max = -INFINITY;
+       int index = 0;
+       
+       for(int i=0; i<count; i++){
+               cpVect v = planes[i].v0;
+               cpFloat d = cpvdot(v, n);
+               if(d > max){
+                       max = d;
+                       index = i;
+               }
+       }
+       
+       return index;
+}
+
+struct SupportPoint {
+       cpVect p;
+       // Save an index of the point so it can be cheaply looked up as a starting point for the next frame.
+       cpCollisionID index;
+};
+
+static inline struct SupportPoint
+SupportPointNew(cpVect p, cpCollisionID index)
+{
+       struct SupportPoint point = {p, index};
+       return point;
+}
+
+typedef struct SupportPoint (*SupportPointFunc)(const cpShape *shape, const cpVect n);
+
+static inline struct SupportPoint
+CircleSupportPoint(const cpCircleShape *circle, const cpVect n)
+{
+       return SupportPointNew(circle->tc, 0);
+}
+
+static inline struct SupportPoint
+SegmentSupportPoint(const cpSegmentShape *seg, const cpVect n)
+{
+       if(cpvdot(seg->ta, n) > cpvdot(seg->tb, n)){
+               return SupportPointNew(seg->ta, 0);
+       } else {
+               return SupportPointNew(seg->tb, 1);
+       }
+}
+
+static inline struct SupportPoint
+PolySupportPoint(const cpPolyShape *poly, const cpVect n)
+{
+       const struct cpSplittingPlane *planes = poly->planes;
+       int i = PolySupportPointIndex(poly->count, planes, n);
+       return SupportPointNew(planes[i].v0, i);
+}
+
+// A point on the surface of two shape's minkowski difference.
+struct MinkowskiPoint {
+       // Cache the two original support points.
+       cpVect a, b;
+       // b - a
+       cpVect ab;
+       // Concatenate the two support point indexes.
+       cpCollisionID id;
+};
+
+static inline struct MinkowskiPoint
+MinkowskiPointNew(const struct SupportPoint a, const struct SupportPoint b)
+{
+       struct MinkowskiPoint point = {a.p, b.p, cpvsub(b.p, a.p), (a.index & 0xFF)<<8 | (b.index & 0xFF)};
+       return point;
+}
+
+struct SupportContext {
+       const cpShape *shape1, *shape2;
+       SupportPointFunc func1, func2;
+};
+
+// Calculate the maximal point on the minkowski difference of two shapes along a particular axis.
+static inline struct MinkowskiPoint
+Support(const struct SupportContext *ctx, const cpVect n)
+{
+       struct SupportPoint a = ctx->func1(ctx->shape1, cpvneg(n));
+       struct SupportPoint b = ctx->func2(ctx->shape2, n);
+       return MinkowskiPointNew(a, b);
+}
+
+struct EdgePoint {
+       cpVect p;
+       // Keep a hash value for Chipmunk's collision hashing mechanism.
+       cpHashValue hash;
+};
+
+// Support edges are the edges of a polygon or segment shape that are in contact.
+struct Edge {
+       struct EdgePoint a, b;
+       cpFloat r;
+       cpVect n;
+};
+
+static struct Edge
+SupportEdgeForPoly(const cpPolyShape *poly, const cpVect n)
+{
+       int count = poly->count;
+       int i1 = PolySupportPointIndex(poly->count, poly->planes, n);
+       
+       // TODO: get rid of mod eventually, very expensive on ARM
+       int i0 = (i1 - 1 + count)%count;
+       int i2 = (i1 + 1)%count;
+       
+       const struct cpSplittingPlane *planes = poly->planes;
+       cpHashValue hashid = poly->shape.hashid;
+       if(cpvdot(n, planes[i1].n) > cpvdot(n, planes[i2].n)){
+               struct Edge edge = {{planes[i0].v0, CP_HASH_PAIR(hashid, i0)}, {planes[i1].v0, CP_HASH_PAIR(hashid, i1)}, poly->r, planes[i1].n};
+               return edge;
+       } else {
+               struct Edge edge = {{planes[i1].v0, CP_HASH_PAIR(hashid, i1)}, {planes[i2].v0, CP_HASH_PAIR(hashid, i2)}, poly->r, planes[i2].n};
+               return edge;
+       }
+}
+
+static struct Edge
+SupportEdgeForSegment(const cpSegmentShape *seg, const cpVect n)
+{
+       cpHashValue hashid = seg->shape.hashid;
+       if(cpvdot(seg->tn, n) > 0.0){
+               struct Edge edge = {{seg->ta, CP_HASH_PAIR(hashid, 0)}, {seg->tb, CP_HASH_PAIR(hashid, 1)}, seg->r, seg->tn};
+               return edge;
+       } else {
+               struct Edge edge = {{seg->tb, CP_HASH_PAIR(hashid, 1)}, {seg->ta, CP_HASH_PAIR(hashid, 0)}, seg->r, cpvneg(seg->tn)};
+               return edge;
+       }
+}
+
+// Find the closest p(t) to (0, 0) where p(t) = a*(1-t)/2 + b*(1+t)/2
+// The range for t is [-1, 1] to avoid floating point issues if the parameters are swapped.
+static inline cpFloat
+ClosestT(const cpVect a, const cpVect b)
+{
+       cpVect delta = cpvsub(b, a);
+       return -cpfclamp(cpvdot(delta, cpvadd(a, b))/cpvlengthsq(delta), -1.0f, 1.0f);
+}
+
+// Basically the same as cpvlerp(), except t = [-1, 1]
+static inline cpVect
+LerpT(const cpVect a, const cpVect b, const cpFloat t)
+{
+       cpFloat ht = 0.5f*t;
+       return cpvadd(cpvmult(a, 0.5f - ht), cpvmult(b, 0.5f + ht));
+}
+
+// Closest points on the surface of two shapes.
+struct ClosestPoints {
+       // Surface points in absolute coordinates.
+       cpVect a, b;
+       // Minimum separating axis of the two shapes.
+       cpVect n;
+       // Signed distance between the points.
+       cpFloat d;
+       // Concatenation of the id's of the minkoski points.
+       cpCollisionID id;
+};
+
+// Calculate the closest points on two shapes given the closest edge on their minkowski difference to (0, 0)
+static inline struct ClosestPoints
+ClosestPointsNew(const struct MinkowskiPoint v0, const struct MinkowskiPoint v1)
+{
+       // Find the closest p(t) on the minkowski difference to (0, 0)
+       cpFloat t = ClosestT(v0.ab, v1.ab);
+       cpVect p = LerpT(v0.ab, v1.ab, t);
+       
+       // Interpolate the original support points using the same 't' value as above.
+       // This gives you the closest surface points in absolute coordinates. NEAT!
+       cpVect pa = LerpT(v0.a, v1.a, t);
+       cpVect pb = LerpT(v0.b, v1.b, t);
+       cpCollisionID id = (v0.id & 0xFFFF)<<16 | (v1.id & 0xFFFF);
+       
+       // First try calculating the MSA from the minkowski difference edge.
+       // This gives us a nice, accurate MSA when the surfaces are close together.
+       cpVect delta = cpvsub(v1.ab, v0.ab);
+       cpVect n = cpvnormalize(cpvrperp(delta));
+       cpFloat d = cpvdot(n, p);
+       
+       if(d <= 0.0f || (-1.0f < t && t < 1.0f)){
+               // If the shapes are overlapping, or we have a regular vertex/edge collision, we are done.
+               struct ClosestPoints points = {pa, pb, n, d, id};
+               return points;
+       } else {
+               // Vertex/vertex collisions need special treatment since the MSA won't be shared with an axis of the minkowski difference.
+               cpFloat d2 = cpvlength(p);
+               cpVect n2 = cpvmult(p, 1.0f/(d2 + CPFLOAT_MIN));
+               
+               struct ClosestPoints points = {pa, pb, n2, d2, id};
+               return points;
+       }
+}
+
+//MARK: EPA Functions
+
+static inline cpFloat
+ClosestDist(const cpVect v0,const cpVect v1)
+{
+       return cpvlengthsq(LerpT(v0, v1, ClosestT(v0, v1)));
+}
+
+// Recursive implementation of the EPA loop.
+// Each recursion adds a point to the convex hull until it's known that we have the closest point on the surface.
+static struct ClosestPoints
+EPARecurse(const struct SupportContext *ctx, const int count, const struct MinkowskiPoint *hull, const int iteration)
+{
+       int mini = 0;
+       cpFloat minDist = INFINITY;
+       
+       // TODO: precalculate this when building the hull and save a step.
+       // Find the closest segment hull[i] and hull[i + 1] to (0, 0)
+       for(int j=0, i=count-1; j<count; i=j, j++){
+               cpFloat d = ClosestDist(hull[i].ab, hull[j].ab);
+               if(d < minDist){
+                       minDist = d;
+                       mini = i;
+               }
+       }
+       
+       struct MinkowskiPoint v0 = hull[mini];
+       struct MinkowskiPoint v1 = hull[(mini + 1)%count];
+       cpAssertSoft(!cpveql(v0.ab, v1.ab), "Internal Error: EPA vertexes are the same (%d and %d)", mini, (mini + 1)%count);
+       
+       // Check if there is a point on the minkowski difference beyond this edge.
+       struct MinkowskiPoint p = Support(ctx, cpvperp(cpvsub(v1.ab, v0.ab)));
+       
+#if DRAW_EPA
+       cpVect verts[count];
+       for(int i=0; i<count; i++) verts[i] = hull[i].ab;
+       
+       ChipmunkDebugDrawPolygon(count, verts, 0.0, RGBAColor(1, 1, 0, 1), RGBAColor(1, 1, 0, 0.25));
+       ChipmunkDebugDrawSegment(v0.ab, v1.ab, RGBAColor(1, 0, 0, 1));
+       
+       ChipmunkDebugDrawDot(5, p.ab, LAColor(1, 1));
+#endif
+       
+       // The usual exit condition is a duplicated vertex.
+       // Much faster to check the ids than to check the signed area.
+       cpBool duplicate = (p.id == v0.id || p.id == v1.id);
+       
+       if(!duplicate && cpCheckPointGreater(v0.ab, v1.ab, p.ab) && iteration < MAX_EPA_ITERATIONS){
+               // Rebuild the convex hull by inserting p.
+               struct MinkowskiPoint *hull2 = (struct MinkowskiPoint *)alloca((count + 1)*sizeof(struct MinkowskiPoint));
+               int count2 = 1;
+               hull2[0] = p;
+               
+               for(int i=0; i<count; i++){
+                       int index = (mini + 1 + i)%count;
+                       
+                       cpVect h0 = hull2[count2 - 1].ab;
+                       cpVect h1 = hull[index].ab;
+                       cpVect h2 = (i + 1 < count ? hull[(index + 1)%count] : p).ab;
+                       
+                       if(cpCheckPointGreater(h0, h2, h1)){
+                               hull2[count2] = hull[index];
+                               count2++;
+                       }
+               }
+               
+               return EPARecurse(ctx, count2, hull2, iteration + 1);
+       } else {
+               // Could not find a new point to insert, so we have found the closest edge of the minkowski difference.
+               cpAssertWarn(iteration < WARN_EPA_ITERATIONS, "High EPA iterations: %d", iteration);
+               return ClosestPointsNew(v0, v1);
+       }
+}
+
+// Find the closest points on the surface of two overlapping shapes using the EPA algorithm.
+// EPA is called from GJK when two shapes overlap.
+// This is a moderately expensive step! Avoid it by adding radii to your shapes so their inner polygons won't overlap.
+static struct ClosestPoints
+EPA(const struct SupportContext *ctx, const struct MinkowskiPoint v0, const struct MinkowskiPoint v1, const struct MinkowskiPoint v2)
+{
+       // TODO: allocate a NxM array here and do an in place convex hull reduction in EPARecurse?
+       struct MinkowskiPoint hull[3] = {v0, v1, v2};
+       return EPARecurse(ctx, 3, hull, 1);
+}
+
+//MARK: GJK Functions.
+
+// Recursive implementation of the GJK loop.
+static inline struct ClosestPoints
+GJKRecurse(const struct SupportContext *ctx, const struct MinkowskiPoint v0, const struct MinkowskiPoint v1, const int iteration)
+{
+       if(iteration > MAX_GJK_ITERATIONS){
+               cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration);
+               return ClosestPointsNew(v0, v1);
+       }
+       
+       if(cpCheckPointGreater(v1.ab, v0.ab, cpvzero)){
+               // Origin is behind axis. Flip and try again.
+               return GJKRecurse(ctx, v1, v0, iteration);
+       } else {
+               cpFloat t = ClosestT(v0.ab, v1.ab);
+               cpVect n = (-1.0f < t && t < 1.0f ? cpvperp(cpvsub(v1.ab, v0.ab)) : cpvneg(LerpT(v0.ab, v1.ab, t)));
+               struct MinkowskiPoint p = Support(ctx, n);
+               
+#if DRAW_GJK
+               ChipmunkDebugDrawSegment(v0.ab, v1.ab, RGBAColor(1, 1, 1, 1));
+               cpVect c = cpvlerp(v0.ab, v1.ab, 0.5);
+               ChipmunkDebugDrawSegment(c, cpvadd(c, cpvmult(cpvnormalize(n), 5.0)), RGBAColor(1, 0, 0, 1));
+               
+               ChipmunkDebugDrawDot(5.0, p.ab, LAColor(1, 1));
+#endif
+               
+               if(cpCheckPointGreater(p.ab, v0.ab, cpvzero) && cpCheckPointGreater(v1.ab, p.ab, cpvzero)){
+                       // The triangle v0, p, v1 contains the origin. Use EPA to find the MSA.
+                       cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK->EPA iterations: %d", iteration);
+                       return EPA(ctx, v0, p, v1);
+               } else {
+                       if(cpCheckAxis(v0.ab, v1.ab, p.ab, n)){
+                               // The edge v0, v1 that we already have is the closest to (0, 0) since p was not closer.
+                               cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration);
+                               return ClosestPointsNew(v0, v1);
+                       } else {
+                               // p was closer to the origin than our existing edge.
+                               // Need to figure out which existing point to drop.
+                               if(ClosestDist(v0.ab, p.ab) < ClosestDist(p.ab, v1.ab)){
+                                       return GJKRecurse(ctx, v0, p, iteration + 1);
+                               } else {
+                                       return GJKRecurse(ctx, p, v1, iteration + 1);
+                               }
+                       }
+               }
+       }
+}
+
+// Get a SupportPoint from a cached shape and index.
+static struct SupportPoint
+ShapePoint(const cpShape *shape, const int i)
+{
+       switch(shape->klass->type){
+               case CP_CIRCLE_SHAPE: {
+                       return SupportPointNew(((cpCircleShape *)shape)->tc, 0);
+               } case CP_SEGMENT_SHAPE: {
+                       cpSegmentShape *seg = (cpSegmentShape *)shape;
+                       return SupportPointNew(i == 0 ? seg->ta : seg->tb, i);
+               } case CP_POLY_SHAPE: {
+                       cpPolyShape *poly = (cpPolyShape *)shape;
+                       // Poly shapes may change vertex count.
+                       int index = (i < poly->count ? i : 0);
+                       return SupportPointNew(poly->planes[index].v0, index);
+               } default: {
+                       return SupportPointNew(cpvzero, 0);
+               }
+       }
+}
+
+// Find the closest points between two shapes using the GJK algorithm.
+static struct ClosestPoints
+GJK(const struct SupportContext *ctx, cpCollisionID *id)
+{
+#if DRAW_GJK || DRAW_EPA
+       int count1 = 1;
+       int count2 = 1;
+       
+       switch(ctx->shape1->klass->type){
+               case CP_SEGMENT_SHAPE: count1 = 2; break;
+               case CP_POLY_SHAPE: count1 = ((cpPolyShape *)ctx->shape1)->count; break;
+               default: break;
+       }
+       
+       switch(ctx->shape2->klass->type){
+               case CP_SEGMENT_SHAPE: count1 = 2; break;
+               case CP_POLY_SHAPE: count2 = ((cpPolyShape *)ctx->shape2)->count; break;
+               default: break;
+       }
+       
+       
+       // draw the minkowski difference origin
+       cpVect origin = cpvzero;
+       ChipmunkDebugDrawDot(5.0, origin, RGBAColor(1,0,0,1));
+       
+       int mdiffCount = count1*count2;
+       cpVect *mdiffVerts = alloca(mdiffCount*sizeof(cpVect));
+       
+       for(int i=0; i<count1; i++){
+               for(int j=0; j<count2; j++){
+                       cpVect v = cpvsub(ShapePoint(ctx->shape2, j).p, ShapePoint(ctx->shape1, i).p);
+                       mdiffVerts[i*count2 + j] = v;
+                       ChipmunkDebugDrawDot(2.0, v, RGBAColor(1, 0, 0, 1));
+               }
+       }
+        
+       cpVect *hullVerts = alloca(mdiffCount*sizeof(cpVect));
+       int hullCount = cpConvexHull(mdiffCount, mdiffVerts, hullVerts, NULL, 0.0);
+       
+       ChipmunkDebugDrawPolygon(hullCount, hullVerts, 0.0, RGBAColor(1, 0, 0, 1), RGBAColor(1, 0, 0, 0.25));
+#endif
+       
+       struct MinkowskiPoint v0, v1;
+       if(*id){
+               // Use the minkowski points from the last frame as a starting point using the cached indexes.
+               v0 = MinkowskiPointNew(ShapePoint(ctx->shape1, (*id>>24)&0xFF), ShapePoint(ctx->shape2, (*id>>16)&0xFF));
+               v1 = MinkowskiPointNew(ShapePoint(ctx->shape1, (*id>> 8)&0xFF), ShapePoint(ctx->shape2, (*id    )&0xFF));
+       } else {
+               // No cached indexes, use the shapes' bounding box centers as a guess for a starting axis.
+               cpVect axis = cpvperp(cpvsub(cpBBCenter(ctx->shape1->bb), cpBBCenter(ctx->shape2->bb)));
+               v0 = Support(ctx, axis);
+               v1 = Support(ctx, cpvneg(axis));
+       }
+       
+       struct ClosestPoints points = GJKRecurse(ctx, v0, v1, 1);
+       *id = points.id;
+       return points;
+}
+
+//MARK: Contact Clipping
+
+// Given two support edges, find contact point pairs on their surfaces.
+static inline void
+ContactPoints(const struct Edge e1, const struct Edge e2, const struct ClosestPoints points, struct cpCollisionInfo *info)
+{
+       cpFloat mindist = e1.r + e2.r;
+       if(points.d <= mindist){
+#ifdef DRAW_CLIP
+       ChipmunkDebugDrawFatSegment(e1.a.p, e1.b.p, e1.r, RGBAColor(0, 1, 0, 1), LAColor(0, 0));
+       ChipmunkDebugDrawFatSegment(e2.a.p, e2.b.p, e2.r, RGBAColor(1, 0, 0, 1), LAColor(0, 0));
+#endif
+               cpVect n = info->n = points.n;
+               
+               // Distances along the axis parallel to n
+               cpFloat d_e1_a = cpvcross(e1.a.p, n);
+               cpFloat d_e1_b = cpvcross(e1.b.p, n);
+               cpFloat d_e2_a = cpvcross(e2.a.p, n);
+               cpFloat d_e2_b = cpvcross(e2.b.p, n);
+               
+               // TODO + min isn't a complete fix.
+               cpFloat e1_denom = 1.0f/(d_e1_b - d_e1_a + CPFLOAT_MIN);
+               cpFloat e2_denom = 1.0f/(d_e2_b - d_e2_a + CPFLOAT_MIN);
+               
+               // Project the endpoints of the two edges onto the opposing edge, clamping them as necessary.
+               // Compare the projected points to the collision normal to see if the shapes overlap there.
+               {
+                       cpVect p1 = cpvadd(cpvmult(n,  e1.r), cpvlerp(e1.a.p, e1.b.p, cpfclamp01((d_e2_b - d_e1_a)*e1_denom)));
+                       cpVect p2 = cpvadd(cpvmult(n, -e2.r), cpvlerp(e2.a.p, e2.b.p, cpfclamp01((d_e1_a - d_e2_a)*e2_denom)));
+                       cpFloat dist = cpvdot(cpvsub(p2, p1), n);
+                       if(dist <= 0.0f){
+                               cpHashValue hash_1a2b = CP_HASH_PAIR(e1.a.hash, e2.b.hash);
+                               cpCollisionInfoPushContact(info, p1, p2, hash_1a2b);
+                       }
+               }{
+                       cpVect p1 = cpvadd(cpvmult(n,  e1.r), cpvlerp(e1.a.p, e1.b.p, cpfclamp01((d_e2_a - d_e1_a)*e1_denom)));
+                       cpVect p2 = cpvadd(cpvmult(n, -e2.r), cpvlerp(e2.a.p, e2.b.p, cpfclamp01((d_e1_b - d_e2_a)*e2_denom)));
+                       cpFloat dist = cpvdot(cpvsub(p2, p1), n);
+                       if(dist <= 0.0f){
+                               cpHashValue hash_1b2a = CP_HASH_PAIR(e1.b.hash, e2.a.hash);
+                               cpCollisionInfoPushContact(info, p1, p2, hash_1b2a);
+                       }
+               }
+       }
+}
+
+//MARK: Collision Functions
+
+typedef void (*CollisionFunc)(const cpShape *a, const cpShape *b, struct cpCollisionInfo *info);
+
+// Collide circle shapes.
+static void
+CircleToCircle(const cpCircleShape *c1, const cpCircleShape *c2, struct cpCollisionInfo *info)
+{
+       cpFloat mindist = c1->r + c2->r;
+       cpVect delta = cpvsub(c2->tc, c1->tc);
+       cpFloat distsq = cpvlengthsq(delta);
+       
+       if(distsq < mindist*mindist){
+               cpFloat dist = cpfsqrt(distsq);
+               cpVect n = info->n = (dist ? cpvmult(delta, 1.0f/dist) : cpv(1.0f, 0.0f));
+               cpCollisionInfoPushContact(info, cpvadd(c1->tc, cpvmult(n, c1->r)), cpvadd(c2->tc, cpvmult(n, -c2->r)), 0);
+       }
+}
+
+static void
+CircleToSegment(const cpCircleShape *circle, const cpSegmentShape *segment, struct cpCollisionInfo *info)
+{
+       cpVect seg_a = segment->ta;
+       cpVect seg_b = segment->tb;
+       cpVect center = circle->tc;
+       
+       // Find the closest point on the segment to the circle.
+       cpVect seg_delta = cpvsub(seg_b, seg_a);
+       cpFloat closest_t = cpfclamp01(cpvdot(seg_delta, cpvsub(center, seg_a))/cpvlengthsq(seg_delta));
+       cpVect closest = cpvadd(seg_a, cpvmult(seg_delta, closest_t));
+       
+       // Compare the radii of the two shapes to see if they are colliding.
+       cpFloat mindist = circle->r + segment->r;
+       cpVect delta = cpvsub(closest, center);
+       cpFloat distsq = cpvlengthsq(delta);
+       if(distsq < mindist*mindist){
+               cpFloat dist = cpfsqrt(distsq);
+               // Handle coincident shapes as gracefully as possible.
+               cpVect n = info->n = (dist ? cpvmult(delta, 1.0f/dist) : segment->tn);
+               
+               // Reject endcap collisions if tangents are provided.
+               cpVect rot = cpBodyGetRotation(segment->shape.body);
+               if(
+                       (closest_t != 0.0f || cpvdot(n, cpvrotate(segment->a_tangent, rot)) >= 0.0) &&
+                       (closest_t != 1.0f || cpvdot(n, cpvrotate(segment->b_tangent, rot)) >= 0.0)
+               ){
+                       cpCollisionInfoPushContact(info, cpvadd(center, cpvmult(n, circle->r)), cpvadd(closest, cpvmult(n, -segment->r)), 0);
+               }
+       }
+}
+
+static void
+SegmentToSegment(const cpSegmentShape *seg1, const cpSegmentShape *seg2, struct cpCollisionInfo *info)
+{
+       struct SupportContext context = {(cpShape *)seg1, (cpShape *)seg2, (SupportPointFunc)SegmentSupportPoint, (SupportPointFunc)SegmentSupportPoint};
+       struct ClosestPoints points = GJK(&context, &info->id);
+       
+#if DRAW_CLOSEST
+#if PRINT_LOG
+//     ChipmunkDemoPrintString("Distance: %.2f\n", points.d);
+#endif
+       
+       ChipmunkDebugDrawDot(6.0, points.a, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawDot(6.0, points.b, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1));
+#endif
+       
+       cpVect n = points.n;
+       cpVect rot1 = cpBodyGetRotation(seg1->shape.body);
+       cpVect rot2 = cpBodyGetRotation(seg2->shape.body);
+       
+       // If the closest points are nearer than the sum of the radii...
+       if(
+               points.d <= (seg1->r + seg2->r) && (
+                       // Reject endcap collisions if tangents are provided.
+                       (!cpveql(points.a, seg1->ta) || cpvdot(n, cpvrotate(seg1->a_tangent, rot1)) <= 0.0) &&
+                       (!cpveql(points.a, seg1->tb) || cpvdot(n, cpvrotate(seg1->b_tangent, rot1)) <= 0.0) &&
+                       (!cpveql(points.b, seg2->ta) || cpvdot(n, cpvrotate(seg2->a_tangent, rot2)) >= 0.0) &&
+                       (!cpveql(points.b, seg2->tb) || cpvdot(n, cpvrotate(seg2->b_tangent, rot2)) >= 0.0)
+               )
+       ){
+               ContactPoints(SupportEdgeForSegment(seg1, n), SupportEdgeForSegment(seg2, cpvneg(n)), points, info);
+       }
+}
+
+static void
+PolyToPoly(const cpPolyShape *poly1, const cpPolyShape *poly2, struct cpCollisionInfo *info)
+{
+       struct SupportContext context = {(cpShape *)poly1, (cpShape *)poly2, (SupportPointFunc)PolySupportPoint, (SupportPointFunc)PolySupportPoint};
+       struct ClosestPoints points = GJK(&context, &info->id);
+       
+#if DRAW_CLOSEST
+#if PRINT_LOG
+//     ChipmunkDemoPrintString("Distance: %.2f\n", points.d);
+#endif
+       
+       ChipmunkDebugDrawDot(3.0, points.a, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawDot(3.0, points.b, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1));
+#endif
+       
+       // If the closest points are nearer than the sum of the radii...
+       if(points.d - poly1->r - poly2->r <= 0.0){
+               ContactPoints(SupportEdgeForPoly(poly1, points.n), SupportEdgeForPoly(poly2, cpvneg(points.n)), points, info);
+       }
+}
+
+static void
+SegmentToPoly(const cpSegmentShape *seg, const cpPolyShape *poly, struct cpCollisionInfo *info)
+{
+       struct SupportContext context = {(cpShape *)seg, (cpShape *)poly, (SupportPointFunc)SegmentSupportPoint, (SupportPointFunc)PolySupportPoint};
+       struct ClosestPoints points = GJK(&context, &info->id);
+       
+#if DRAW_CLOSEST
+#if PRINT_LOG
+//     ChipmunkDemoPrintString("Distance: %.2f\n", points.d);
+#endif
+       
+       ChipmunkDebugDrawDot(3.0, points.a, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawDot(3.0, points.b, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1));
+#endif
+       
+       cpVect n = points.n;
+       cpVect rot = cpBodyGetRotation(seg->shape.body);
+       
+       if(
+               // If the closest points are nearer than the sum of the radii...
+               points.d - seg->r - poly->r <= 0.0 && (
+                       // Reject endcap collisions if tangents are provided.
+                       (!cpveql(points.a, seg->ta) || cpvdot(n, cpvrotate(seg->a_tangent, rot)) <= 0.0) &&
+                       (!cpveql(points.a, seg->tb) || cpvdot(n, cpvrotate(seg->b_tangent, rot)) <= 0.0)
+               )
+       ){
+               ContactPoints(SupportEdgeForSegment(seg, n), SupportEdgeForPoly(poly, cpvneg(n)), points, info);
+       }
+}
+
+static void
+CircleToPoly(const cpCircleShape *circle, const cpPolyShape *poly, struct cpCollisionInfo *info)
+{
+       struct SupportContext context = {(cpShape *)circle, (cpShape *)poly, (SupportPointFunc)CircleSupportPoint, (SupportPointFunc)PolySupportPoint};
+       struct ClosestPoints points = GJK(&context, &info->id);
+       
+#if DRAW_CLOSEST
+       ChipmunkDebugDrawDot(3.0, points.a, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawDot(3.0, points.b, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1));
+       ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1));
+#endif
+       
+       // If the closest points are nearer than the sum of the radii...
+       if(points.d <= circle->r + poly->r){
+               cpVect n = info->n = points.n;
+               cpCollisionInfoPushContact(info, cpvadd(points.a, cpvmult(n, circle->r)), cpvadd(points.b, cpvmult(n, poly->r)), 0);
+       }
+}
+
+static void
+CollisionError(const cpShape *circle, const cpShape *poly, struct cpCollisionInfo *info)
+{
+       cpAssertHard(cpFalse, "Internal Error: Shape types are not sorted.");
+}
+
+
+static const CollisionFunc BuiltinCollisionFuncs[9] = {
+       (CollisionFunc)CircleToCircle,
+       CollisionError,
+       CollisionError,
+       (CollisionFunc)CircleToSegment,
+       (CollisionFunc)SegmentToSegment,
+       CollisionError,
+       (CollisionFunc)CircleToPoly,
+       (CollisionFunc)SegmentToPoly,
+       (CollisionFunc)PolyToPoly,
+};
+static const CollisionFunc *CollisionFuncs = BuiltinCollisionFuncs;
+
+struct cpCollisionInfo
+cpCollide(const cpShape *a, const cpShape *b, cpCollisionID id, struct cpContact *contacts)
+{
+       struct cpCollisionInfo info = {a, b, id, cpvzero, 0, contacts};
+       
+       // Make sure the shape types are in order.
+       if(a->klass->type > b->klass->type){
+               info.a = b;
+               info.b = a;
+       }
+       
+       CollisionFuncs[info.a->klass->type + info.b->klass->type*CP_NUM_SHAPES](info.a, info.b, &info);
+       
+//     if(0){
+//             for(int i=0; i<info.count; i++){
+//                     cpVect r1 = info.arr[i].r1;
+//                     cpVect r2 = info.arr[i].r2;
+//                     cpVect mid = cpvlerp(r1, r2, 0.5f);
+//                     
+//                     ChipmunkDebugDrawSegment(r1, mid, RGBAColor(1, 0, 0, 1));
+//                     ChipmunkDebugDrawSegment(r2, mid, RGBAColor(0, 0, 1, 1));
+//             }
+//     }
+       
+       return info;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpConstraint.c b/dali-physics/third-party/chipmunk2d/src/cpConstraint.c
new file mode 100644 (file)
index 0000000..7952ea1
--- /dev/null
@@ -0,0 +1,173 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+// TODO: Comment me!
+
+void cpConstraintDestroy(cpConstraint *constraint){}
+
+void
+cpConstraintFree(cpConstraint *constraint)
+{
+       if(constraint){
+               cpConstraintDestroy(constraint);
+               cpfree(constraint);
+       }
+}
+
+void
+cpConstraintInit(cpConstraint *constraint, const cpConstraintClass *klass, cpBody *a, cpBody *b)
+{
+       constraint->klass = klass;
+       
+       constraint->a = a;
+       constraint->b = b;
+       constraint->space = NULL;
+       
+       constraint->next_a = NULL;
+       constraint->next_b = NULL;
+       
+       constraint->maxForce = (cpFloat)INFINITY;
+       constraint->errorBias = cpfpow(1.0f - 0.1f, 60.0f);
+       constraint->maxBias = (cpFloat)INFINITY;
+       
+       constraint->collideBodies = cpTrue;
+       
+       constraint->preSolve = NULL;
+       constraint->postSolve = NULL;
+}
+
+cpSpace *
+cpConstraintGetSpace(const cpConstraint *constraint)
+{
+       return constraint->space;
+}
+
+cpBody *
+cpConstraintGetBodyA(const cpConstraint *constraint)
+{
+       return constraint->a;
+}
+
+cpBody *
+cpConstraintGetBodyB(const cpConstraint *constraint)
+{
+       return constraint->b;
+}
+
+cpFloat
+cpConstraintGetMaxForce(const cpConstraint *constraint)
+{
+       return constraint->maxForce;
+}
+
+void
+cpConstraintSetMaxForce(cpConstraint *constraint, cpFloat maxForce)
+{
+       cpAssertHard(maxForce >= 0.0f, "maxForce must be positive.");
+       cpConstraintActivateBodies(constraint);
+       constraint->maxForce = maxForce;
+}
+
+cpFloat
+cpConstraintGetErrorBias(const cpConstraint *constraint)
+{
+       return constraint->errorBias;
+}
+
+void
+cpConstraintSetErrorBias(cpConstraint *constraint, cpFloat errorBias)
+{
+       cpAssertHard(errorBias >= 0.0f, "errorBias must be positive.");
+       cpConstraintActivateBodies(constraint);
+       constraint->errorBias = errorBias;
+}
+
+cpFloat
+cpConstraintGetMaxBias(const cpConstraint *constraint)
+{
+       return constraint->maxBias;
+}
+
+void
+cpConstraintSetMaxBias(cpConstraint *constraint, cpFloat maxBias)
+{
+       cpAssertHard(maxBias >= 0.0f, "maxBias must be positive.");
+       cpConstraintActivateBodies(constraint);
+       constraint->maxBias = maxBias;
+}
+
+cpBool
+cpConstraintGetCollideBodies(const cpConstraint *constraint)
+{
+       return constraint->collideBodies;
+}
+
+void
+cpConstraintSetCollideBodies(cpConstraint *constraint, cpBool collideBodies)
+{
+       cpConstraintActivateBodies(constraint);
+       constraint->collideBodies = collideBodies;
+}
+
+cpConstraintPreSolveFunc
+cpConstraintGetPreSolveFunc(const cpConstraint *constraint)
+{
+       return constraint->preSolve;
+}
+
+void
+cpConstraintSetPreSolveFunc(cpConstraint *constraint, cpConstraintPreSolveFunc preSolveFunc)
+{
+       constraint->preSolve = preSolveFunc;
+}
+
+cpConstraintPostSolveFunc
+cpConstraintGetPostSolveFunc(const cpConstraint *constraint)
+{
+       return constraint->postSolve;
+}
+
+void
+cpConstraintSetPostSolveFunc(cpConstraint *constraint, cpConstraintPostSolveFunc postSolveFunc)
+{
+       constraint->postSolve = postSolveFunc;
+}
+
+cpDataPointer
+cpConstraintGetUserData(const cpConstraint *constraint)
+{
+       return constraint->userData;
+}
+
+void
+cpConstraintSetUserData(cpConstraint *constraint, cpDataPointer userData)
+{
+       constraint->userData = userData;
+}
+
+
+cpFloat
+cpConstraintGetImpulse(cpConstraint *constraint)
+{
+       return constraint->klass->getImpulse(constraint);
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpDampedRotarySpring.c b/dali-physics/third-party/chipmunk2d/src/cpDampedRotarySpring.c
new file mode 100644 (file)
index 0000000..8d38a54
--- /dev/null
@@ -0,0 +1,178 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static cpFloat
+defaultSpringTorque(cpDampedRotarySpring *spring, cpFloat relativeAngle){
+       return (relativeAngle - spring->restAngle)*spring->stiffness;
+}
+
+static void
+preStep(cpDampedRotarySpring *spring, cpFloat dt)
+{
+       cpBody *a = spring->constraint.a;
+       cpBody *b = spring->constraint.b;
+       
+       cpFloat moment = a->i_inv + b->i_inv;
+       cpAssertSoft(moment != 0.0, "Unsolvable spring.");
+       spring->iSum = 1.0f/moment;
+
+       spring->w_coef = 1.0f - cpfexp(-spring->damping*dt*moment);
+       spring->target_wrn = 0.0f;
+
+       // apply spring torque
+       cpFloat j_spring = spring->springTorqueFunc((cpConstraint *)spring, a->a - b->a)*dt;
+       spring->jAcc = j_spring;
+       
+       a->w -= j_spring*a->i_inv;
+       b->w += j_spring*b->i_inv;
+}
+
+static void applyCachedImpulse(cpDampedRotarySpring *spring, cpFloat dt_coef){}
+
+static void
+applyImpulse(cpDampedRotarySpring *spring, cpFloat dt)
+{
+       cpBody *a = spring->constraint.a;
+       cpBody *b = spring->constraint.b;
+       
+       // compute relative velocity
+       cpFloat wrn = a->w - b->w;//normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn;
+       
+       // compute velocity loss from drag
+       // not 100% certain this is derived correctly, though it makes sense
+       cpFloat w_damp = (spring->target_wrn - wrn)*spring->w_coef;
+       spring->target_wrn = wrn + w_damp;
+       
+       //apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass));
+       cpFloat j_damp = w_damp*spring->iSum;
+       spring->jAcc += j_damp;
+       
+       a->w += j_damp*a->i_inv;
+       b->w -= j_damp*b->i_inv;
+}
+
+static cpFloat
+getImpulse(cpDampedRotarySpring *spring)
+{
+       return spring->jAcc;
+}
+
+static const cpConstraintClass klass = {
+       (cpConstraintPreStepImpl)preStep,
+       (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+       (cpConstraintApplyImpulseImpl)applyImpulse,
+       (cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpDampedRotarySpring *
+cpDampedRotarySpringAlloc(void)
+{
+       return (cpDampedRotarySpring *)cpcalloc(1, sizeof(cpDampedRotarySpring));
+}
+
+cpDampedRotarySpring *
+cpDampedRotarySpringInit(cpDampedRotarySpring *spring, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)
+{
+       cpConstraintInit((cpConstraint *)spring, &klass, a, b);
+       
+       spring->restAngle = restAngle;
+       spring->stiffness = stiffness;
+       spring->damping = damping;
+       spring->springTorqueFunc = (cpDampedRotarySpringTorqueFunc)defaultSpringTorque;
+       
+       spring->jAcc = 0.0f;
+       
+       return spring;
+}
+
+cpConstraint *
+cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)
+{
+       return (cpConstraint *)cpDampedRotarySpringInit(cpDampedRotarySpringAlloc(), a, b, restAngle, stiffness, damping);
+}
+
+cpBool
+cpConstraintIsDampedRotarySpring(const cpConstraint *constraint)
+{
+       return (constraint->klass == &klass);
+}
+
+cpFloat
+cpDampedRotarySpringGetRestAngle(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+       return ((cpDampedRotarySpring *)constraint)->restAngle;
+}
+
+void
+cpDampedRotarySpringSetRestAngle(cpConstraint *constraint, cpFloat restAngle)
+{
+       cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+       cpConstraintActivateBodies(constraint);
+       ((cpDampedRotarySpring *)constraint)->restAngle = restAngle;
+}
+
+cpFloat
+cpDampedRotarySpringGetStiffness(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+       return ((cpDampedRotarySpring *)constraint)->stiffness;
+}
+
+void
+cpDampedRotarySpringSetStiffness(cpConstraint *constraint, cpFloat stiffness)
+{
+       cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+       cpConstraintActivateBodies(constraint);
+       ((cpDampedRotarySpring *)constraint)->stiffness = stiffness;
+}
+
+cpFloat
+cpDampedRotarySpringGetDamping(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+       return ((cpDampedRotarySpring *)constraint)->damping;
+}
+
+void
+cpDampedRotarySpringSetDamping(cpConstraint *constraint, cpFloat damping)
+{
+       cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+       cpConstraintActivateBodies(constraint);
+       ((cpDampedRotarySpring *)constraint)->damping = damping;
+}
+
+cpDampedRotarySpringTorqueFunc
+cpDampedRotarySpringGetSpringTorqueFunc(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+       return ((cpDampedRotarySpring *)constraint)->springTorqueFunc;
+}
+
+void
+cpDampedRotarySpringSetSpringTorqueFunc(cpConstraint *constraint, cpDampedRotarySpringTorqueFunc springTorqueFunc)
+{
+       cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring.");
+       cpConstraintActivateBodies(constraint);
+       ((cpDampedRotarySpring *)constraint)->springTorqueFunc = springTorqueFunc;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpDampedSpring.c b/dali-physics/third-party/chipmunk2d/src/cpDampedSpring.c
new file mode 100644 (file)
index 0000000..e4d019e
--- /dev/null
@@ -0,0 +1,216 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static cpFloat
+defaultSpringForce(cpDampedSpring *spring, cpFloat dist){
+       return (spring->restLength - dist)*spring->stiffness;
+}
+
+static void
+preStep(cpDampedSpring *spring, cpFloat dt)
+{
+       cpBody *a = spring->constraint.a;
+       cpBody *b = spring->constraint.b;
+       
+       spring->r1 = cpTransformVect(a->transform, cpvsub(spring->anchorA, a->cog));
+       spring->r2 = cpTransformVect(b->transform, cpvsub(spring->anchorB, b->cog));
+       
+       cpVect delta = cpvsub(cpvadd(b->p, spring->r2), cpvadd(a->p, spring->r1));
+       cpFloat dist = cpvlength(delta);
+       spring->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY));
+       
+       cpFloat k = k_scalar(a, b, spring->r1, spring->r2, spring->n);
+       cpAssertSoft(k != 0.0, "Unsolvable spring.");
+       spring->nMass = 1.0f/k;
+       
+       spring->target_vrn = 0.0f;
+       spring->v_coef = 1.0f - cpfexp(-spring->damping*dt*k);
+
+       // apply spring force
+       cpFloat f_spring = spring->springForceFunc((cpConstraint *)spring, dist);
+       cpFloat j_spring = spring->jAcc = f_spring*dt;
+       apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, j_spring));
+}
+
+static void applyCachedImpulse(cpDampedSpring *spring, cpFloat dt_coef){}
+
+static void
+applyImpulse(cpDampedSpring *spring, cpFloat dt)
+{
+       cpBody *a = spring->constraint.a;
+       cpBody *b = spring->constraint.b;
+       
+       cpVect n = spring->n;
+       cpVect r1 = spring->r1;
+       cpVect r2 = spring->r2;
+
+       // compute relative velocity
+       cpFloat vrn = normal_relative_velocity(a, b, r1, r2, n);
+       
+       // compute velocity loss from drag
+       cpFloat v_damp = (spring->target_vrn - vrn)*spring->v_coef;
+       spring->target_vrn = vrn + v_damp;
+       
+       cpFloat j_damp = v_damp*spring->nMass;
+       spring->jAcc += j_damp;
+       apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, j_damp));
+}
+
+static cpFloat
+getImpulse(cpDampedSpring *spring)
+{
+       return spring->jAcc;
+}
+
+static const cpConstraintClass klass = {
+       (cpConstraintPreStepImpl)preStep,
+       (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+       (cpConstraintApplyImpulseImpl)applyImpulse,
+       (cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpDampedSpring *
+cpDampedSpringAlloc(void)
+{
+       return (cpDampedSpring *)cpcalloc(1, sizeof(cpDampedSpring));
+}
+
+cpDampedSpring *
+cpDampedSpringInit(cpDampedSpring *spring, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping)
+{
+       cpConstraintInit((cpConstraint *)spring, &klass, a, b);
+       
+       spring->anchorA = anchorA;
+       spring->anchorB = anchorB;
+       
+       spring->restLength = restLength;
+       spring->stiffness = stiffness;
+       spring->damping = damping;
+       spring->springForceFunc = (cpDampedSpringForceFunc)defaultSpringForce;
+       
+       spring->jAcc = 0.0f;
+       
+       return spring;
+}
+
+cpConstraint *
+cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping)
+{
+       return (cpConstraint *)cpDampedSpringInit(cpDampedSpringAlloc(), a, b, anchorA, anchorB, restLength, stiffness, damping);
+}
+
+cpBool
+cpConstraintIsDampedSpring(const cpConstraint *constraint)
+{
+       return (constraint->klass == &klass);
+}
+
+cpVect
+cpDampedSpringGetAnchorA(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       return ((cpDampedSpring *)constraint)->anchorA;
+}
+
+void
+cpDampedSpringSetAnchorA(cpConstraint *constraint, cpVect anchorA)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       cpConstraintActivateBodies(constraint);
+       ((cpDampedSpring *)constraint)->anchorA = anchorA;
+}
+
+cpVect
+cpDampedSpringGetAnchorB(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       return ((cpDampedSpring *)constraint)->anchorB;
+}
+
+void
+cpDampedSpringSetAnchorB(cpConstraint *constraint, cpVect anchorB)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       cpConstraintActivateBodies(constraint);
+       ((cpDampedSpring *)constraint)->anchorB = anchorB;
+}
+
+cpFloat
+cpDampedSpringGetRestLength(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       return ((cpDampedSpring *)constraint)->restLength;
+}
+
+void
+cpDampedSpringSetRestLength(cpConstraint *constraint, cpFloat restLength)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       cpConstraintActivateBodies(constraint);
+       ((cpDampedSpring *)constraint)->restLength = restLength;
+}
+
+cpFloat
+cpDampedSpringGetStiffness(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       return ((cpDampedSpring *)constraint)->stiffness;
+}
+
+void
+cpDampedSpringSetStiffness(cpConstraint *constraint, cpFloat stiffness)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       cpConstraintActivateBodies(constraint);
+       ((cpDampedSpring *)constraint)->stiffness = stiffness;
+}
+
+cpFloat
+cpDampedSpringGetDamping(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       return ((cpDampedSpring *)constraint)->damping;
+}
+
+void
+cpDampedSpringSetDamping(cpConstraint *constraint, cpFloat damping)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       cpConstraintActivateBodies(constraint);
+       ((cpDampedSpring *)constraint)->damping = damping;
+}
+
+cpDampedSpringForceFunc
+cpDampedSpringGetSpringForceFunc(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       return ((cpDampedSpring *)constraint)->springForceFunc;
+}
+
+void
+cpDampedSpringSetSpringForceFunc(cpConstraint *constraint, cpDampedSpringForceFunc springForceFunc)
+{
+       cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring.");
+       cpConstraintActivateBodies(constraint);
+       ((cpDampedSpring *)constraint)->springForceFunc = springForceFunc;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpGearJoint.c b/dali-physics/third-party/chipmunk2d/src/cpGearJoint.c
new file mode 100644 (file)
index 0000000..3670173
--- /dev/null
@@ -0,0 +1,145 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpGearJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       // calculate moment of inertia coefficient.
+       joint->iSum = 1.0f/(a->i_inv*joint->ratio_inv + joint->ratio*b->i_inv);
+       
+       // calculate bias velocity
+       cpFloat maxBias = joint->constraint.maxBias;
+       joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(b->a*joint->ratio - a->a - joint->phase)/dt, -maxBias, maxBias);
+}
+
+static void
+applyCachedImpulse(cpGearJoint *joint, cpFloat dt_coef)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpFloat j = joint->jAcc*dt_coef;
+       a->w -= j*a->i_inv*joint->ratio_inv;
+       b->w += j*b->i_inv;
+}
+
+static void
+applyImpulse(cpGearJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       // compute relative rotational velocity
+       cpFloat wr = b->w*joint->ratio - a->w;
+       
+       cpFloat jMax = joint->constraint.maxForce*dt;
+       
+       // compute normal impulse       
+       cpFloat j = (joint->bias - wr)*joint->iSum;
+       cpFloat jOld = joint->jAcc;
+       joint->jAcc = cpfclamp(jOld + j, -jMax, jMax);
+       j = joint->jAcc - jOld;
+       
+       // apply impulse
+       a->w -= j*a->i_inv*joint->ratio_inv;
+       b->w += j*b->i_inv;
+}
+
+static cpFloat
+getImpulse(cpGearJoint *joint)
+{
+       return cpfabs(joint->jAcc);
+}
+
+static const cpConstraintClass klass = {
+       (cpConstraintPreStepImpl)preStep,
+       (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+       (cpConstraintApplyImpulseImpl)applyImpulse,
+       (cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpGearJoint *
+cpGearJointAlloc(void)
+{
+       return (cpGearJoint *)cpcalloc(1, sizeof(cpGearJoint));
+}
+
+cpGearJoint *
+cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)
+{
+       cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+       
+       joint->phase = phase;
+       joint->ratio = ratio;
+       joint->ratio_inv = 1.0f/ratio;
+       
+       joint->jAcc = 0.0f;
+       
+       return joint;
+}
+
+cpConstraint *
+cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)
+{
+       return (cpConstraint *)cpGearJointInit(cpGearJointAlloc(), a, b, phase, ratio);
+}
+
+cpBool
+cpConstraintIsGearJoint(const cpConstraint *constraint)
+{
+       return (constraint->klass == &klass);
+}
+
+cpFloat
+cpGearJointGetPhase(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint.");
+       return ((cpGearJoint *)constraint)->phase;
+}
+
+void
+cpGearJointSetPhase(cpConstraint *constraint, cpFloat phase)
+{
+       cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpGearJoint *)constraint)->phase = phase;
+}
+
+cpFloat
+cpGearJointGetRatio(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint.");
+       return ((cpGearJoint *)constraint)->ratio;
+}
+
+void
+cpGearJointSetRatio(cpConstraint *constraint, cpFloat ratio)
+{
+       cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpGearJoint *)constraint)->ratio = ratio;
+       ((cpGearJoint *)constraint)->ratio_inv = 1.0f/ratio;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpGrooveJoint.c b/dali-physics/third-party/chipmunk2d/src/cpGrooveJoint.c
new file mode 100644 (file)
index 0000000..50d1857
--- /dev/null
@@ -0,0 +1,197 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpGrooveJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       // calculate endpoints in worldspace
+       cpVect ta = cpTransformPoint(a->transform, joint->grv_a);
+       cpVect tb = cpTransformPoint(a->transform, joint->grv_b);
+
+       // calculate axis
+       cpVect n = cpTransformVect(a->transform, joint->grv_n);
+       cpFloat d = cpvdot(ta, n);
+       
+       joint->grv_tn = n;
+       joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog));
+       
+       // calculate tangential distance along the axis of r2
+       cpFloat td = cpvcross(cpvadd(b->p, joint->r2), n);
+       // calculate clamping factor and r2
+       if(td <= cpvcross(ta, n)){
+               joint->clamp = 1.0f;
+               joint->r1 = cpvsub(ta, a->p);
+       } else if(td >= cpvcross(tb, n)){
+               joint->clamp = -1.0f;
+               joint->r1 = cpvsub(tb, a->p);
+       } else {
+               joint->clamp = 0.0f;
+               joint->r1 = cpvsub(cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)), a->p);
+       }
+       
+       // Calculate mass tensor
+       joint->k = k_tensor(a, b, joint->r1, joint->r2);
+       
+       // calculate bias velocity
+       cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
+       joint->bias = cpvclamp(cpvmult(delta, -bias_coef(joint->constraint.errorBias, dt)/dt), joint->constraint.maxBias);
+}
+
+static void
+applyCachedImpulse(cpGrooveJoint *joint, cpFloat dt_coef)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+               
+       apply_impulses(a, b, joint->r1, joint->r2, cpvmult(joint->jAcc, dt_coef));
+}
+
+static inline cpVect
+grooveConstrain(cpGrooveJoint *joint, cpVect j, cpFloat dt){
+       cpVect n = joint->grv_tn;
+       cpVect jClamp = (joint->clamp*cpvcross(j, n) > 0.0f) ? j : cpvproject(j, n);
+       return cpvclamp(jClamp, joint->constraint.maxForce*dt);
+}
+
+static void
+applyImpulse(cpGrooveJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpVect r1 = joint->r1;
+       cpVect r2 = joint->r2;
+       
+       // compute impulse
+       cpVect vr = relative_velocity(a, b, r1, r2);
+
+       cpVect j = cpMat2x2Transform(joint->k, cpvsub(joint->bias, vr));
+       cpVect jOld = joint->jAcc;
+       joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j), dt);
+       j = cpvsub(joint->jAcc, jOld);
+       
+       // apply impulse
+       apply_impulses(a, b, joint->r1, joint->r2, j);
+}
+
+static cpFloat
+getImpulse(cpGrooveJoint *joint)
+{
+       return cpvlength(joint->jAcc);
+}
+
+static const cpConstraintClass klass = {
+       (cpConstraintPreStepImpl)preStep,
+       (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+       (cpConstraintApplyImpulseImpl)applyImpulse,
+       (cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpGrooveJoint *
+cpGrooveJointAlloc(void)
+{
+       return (cpGrooveJoint *)cpcalloc(1, sizeof(cpGrooveJoint));
+}
+
+cpGrooveJoint *
+cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB)
+{
+       cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+       
+       joint->grv_a = groove_a;
+       joint->grv_b = groove_b;
+       joint->grv_n = cpvperp(cpvnormalize(cpvsub(groove_b, groove_a)));
+       joint->anchorB = anchorB;
+       
+       joint->jAcc = cpvzero;
+       
+       return joint;
+}
+
+cpConstraint *
+cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB)
+{
+       return (cpConstraint *)cpGrooveJointInit(cpGrooveJointAlloc(), a, b, groove_a, groove_b, anchorB);
+}
+
+cpBool
+cpConstraintIsGrooveJoint(const cpConstraint *constraint)
+{
+       return (constraint->klass == &klass);
+}
+
+cpVect
+cpGrooveJointGetGrooveA(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+       return ((cpGrooveJoint *)constraint)->grv_a;
+}
+
+void
+cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect value)
+{
+       cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+       cpGrooveJoint *g = (cpGrooveJoint *)constraint;
+       
+       g->grv_a = value;
+       g->grv_n = cpvperp(cpvnormalize(cpvsub(g->grv_b, value)));
+       
+       cpConstraintActivateBodies(constraint);
+}
+
+cpVect
+cpGrooveJointGetGrooveB(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+       return ((cpGrooveJoint *)constraint)->grv_b;
+}
+
+void
+cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect value)
+{
+       cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+       cpGrooveJoint *g = (cpGrooveJoint *)constraint;
+       
+       g->grv_b = value;
+       g->grv_n = cpvperp(cpvnormalize(cpvsub(value, g->grv_a)));
+       
+       cpConstraintActivateBodies(constraint);
+}
+
+cpVect
+cpGrooveJointGetAnchorB(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+       return ((cpGrooveJoint *)constraint)->anchorB;
+}
+
+void
+cpGrooveJointSetAnchorB(cpConstraint *constraint, cpVect anchorB)
+{
+       cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpGrooveJoint *)constraint)->anchorB = anchorB;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpHashSet.c b/dali-physics/third-party/chipmunk2d/src/cpHashSet.c
new file mode 100644 (file)
index 0000000..b2918de
--- /dev/null
@@ -0,0 +1,253 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+#include "prime.h"
+
+typedef struct cpHashSetBin {
+       void *elt;
+       cpHashValue hash;
+       struct cpHashSetBin *next;
+} cpHashSetBin;
+
+struct cpHashSet {
+       unsigned int entries, size;
+       
+       cpHashSetEqlFunc eql;
+       void *default_value;
+       
+       cpHashSetBin **table;
+       cpHashSetBin *pooledBins;
+       
+       cpArray *allocatedBuffers;
+};
+
+void
+cpHashSetFree(cpHashSet *set)
+{
+       if(set){
+               cpfree(set->table);
+               
+               cpArrayFreeEach(set->allocatedBuffers, cpfree);
+               cpArrayFree(set->allocatedBuffers);
+               
+               cpfree(set);
+       }
+}
+
+cpHashSet *
+cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc)
+{
+       cpHashSet *set = (cpHashSet *)cpcalloc(1, sizeof(cpHashSet));
+       
+       set->size = next_prime(size);
+       set->entries = 0;
+       
+       set->eql = eqlFunc;
+       set->default_value = NULL;
+       
+       set->table = (cpHashSetBin **)cpcalloc(set->size, sizeof(cpHashSetBin *));
+       set->pooledBins = NULL;
+       
+       set->allocatedBuffers = cpArrayNew(0);
+       
+       return set;
+}
+
+void
+cpHashSetSetDefaultValue(cpHashSet *set, void *default_value)
+{
+       set->default_value = default_value;
+}
+
+static int
+setIsFull(cpHashSet *set)
+{
+       return (set->entries >= set->size);
+}
+
+static void
+cpHashSetResize(cpHashSet *set)
+{
+       // Get the next approximate doubled prime.
+       unsigned int newSize = next_prime(set->size + 1);
+       // Allocate a new table.
+       cpHashSetBin **newTable = (cpHashSetBin **)cpcalloc(newSize, sizeof(cpHashSetBin *));
+       
+       // Iterate over the chains.
+       for(unsigned int i=0; i<set->size; i++){
+               // Rehash the bins into the new table.
+               cpHashSetBin *bin = set->table[i];
+               while(bin){
+                       cpHashSetBin *next = bin->next;
+                       
+                       cpHashValue idx = bin->hash%newSize;
+                       bin->next = newTable[idx];
+                       newTable[idx] = bin;
+                       
+                       bin = next;
+               }
+       }
+       
+       cpfree(set->table);
+       
+       set->table = newTable;
+       set->size = newSize;
+}
+
+static inline void
+recycleBin(cpHashSet *set, cpHashSetBin *bin)
+{
+       bin->next = set->pooledBins;
+       set->pooledBins = bin;
+       bin->elt = NULL;
+}
+
+static cpHashSetBin *
+getUnusedBin(cpHashSet *set)
+{
+       cpHashSetBin *bin = set->pooledBins;
+       
+       if(bin){
+               set->pooledBins = bin->next;
+               return bin;
+       } else {
+               // Pool is exhausted, make more
+               int count = CP_BUFFER_BYTES/sizeof(cpHashSetBin);
+               cpAssertHard(count, "Internal Error: Buffer size is too small.");
+               
+               cpHashSetBin *buffer = (cpHashSetBin *)cpcalloc(1, CP_BUFFER_BYTES);
+               cpArrayPush(set->allocatedBuffers, buffer);
+               
+               // push all but the first one, return it instead
+               for(int i=1; i<count; i++) recycleBin(set, buffer + i);
+               return buffer;
+       }
+}
+
+int
+cpHashSetCount(cpHashSet *set)
+{
+       return set->entries;
+}
+
+const void *
+cpHashSetInsert(cpHashSet *set, cpHashValue hash, const void *ptr, cpHashSetTransFunc trans, void *data)
+{
+       cpHashValue idx = hash%set->size;
+       
+       // Find the bin with the matching element.
+       cpHashSetBin *bin = set->table[idx];
+       while(bin && !set->eql(ptr, bin->elt))
+               bin = bin->next;
+       
+       // Create it if necessary.
+       if(!bin){
+               bin = getUnusedBin(set);
+               bin->hash = hash;
+               bin->elt = (trans ? trans(ptr, data) : data);
+               
+               bin->next = set->table[idx];
+               set->table[idx] = bin;
+               
+               set->entries++;
+               if(setIsFull(set)) cpHashSetResize(set);
+       }
+       
+       return bin->elt;
+}
+
+const void *
+cpHashSetRemove(cpHashSet *set, cpHashValue hash, const void *ptr)
+{
+       cpHashValue idx = hash%set->size;
+       
+       cpHashSetBin **prev_ptr = &set->table[idx];
+       cpHashSetBin *bin = set->table[idx];
+       
+       // Find the bin
+       while(bin && !set->eql(ptr, bin->elt)){
+               prev_ptr = &bin->next;
+               bin = bin->next;
+       }
+       
+       // Remove it if it exists.
+       if(bin){
+               // Update the previous linked list pointer
+               (*prev_ptr) = bin->next;
+               set->entries--;
+               
+               const void *elt = bin->elt;
+               recycleBin(set, bin);
+               
+               return elt;
+       }
+       
+       return NULL;
+}
+
+const void *
+cpHashSetFind(cpHashSet *set, cpHashValue hash, const void *ptr)
+{      
+       cpHashValue idx = hash%set->size;
+       cpHashSetBin *bin = set->table[idx];
+       while(bin && !set->eql(ptr, bin->elt))
+               bin = bin->next;
+               
+       return (bin ? bin->elt : set->default_value);
+}
+
+void
+cpHashSetEach(cpHashSet *set, cpHashSetIteratorFunc func, void *data)
+{
+       for(unsigned int i=0; i<set->size; i++){
+               cpHashSetBin *bin = set->table[i];
+               while(bin){
+                       cpHashSetBin *next = bin->next;
+                       func(bin->elt, data);
+                       bin = next;
+               }
+       }
+}
+
+void
+cpHashSetFilter(cpHashSet *set, cpHashSetFilterFunc func, void *data)
+{
+       for(unsigned int i=0; i<set->size; i++){
+               // The rest works similarly to cpHashSetRemove() above.
+               cpHashSetBin **prev_ptr = &set->table[i];
+               cpHashSetBin *bin = set->table[i];
+               while(bin){
+                       cpHashSetBin *next = bin->next;
+                       
+                       if(func(bin->elt, data)){
+                               prev_ptr = &bin->next;
+                       } else {
+                               (*prev_ptr) = next;
+
+                               set->entries--;
+                               recycleBin(set, bin);
+                       }
+                       
+                       bin = next;
+               }
+       }
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpHastySpace.c b/dali-physics/third-party/chipmunk2d/src/cpHastySpace.c
new file mode 100644 (file)
index 0000000..8422c3e
--- /dev/null
@@ -0,0 +1,700 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#include <stdlib.h>
+#include <stdio.h>
+
+//TODO: Move all the thread stuff to another file
+
+//#include <sys/param.h >
+
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
+
+#ifndef _WIN32
+#include <pthread.h>
+#elif defined(__MINGW32__)
+#include <pthread.h>
+#else
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+
+#include <process.h> // _beginthreadex
+#include <windows.h>
+
+#ifndef ETIMEDOUT
+#define ETIMEDOUT 1
+#endif
+
+// Simple pthread implementation for Windows
+// Made from scratch to avoid the LGPL licence from pthread-win32
+enum {
+       SIGNAL = 0,
+       BROADCAST = 1,
+       MAX_EVENTS = 2
+};
+
+typedef HANDLE pthread_t;
+typedef struct
+{
+       // Based on http://www.cs.wustl.edu/~schmidt/win32-cv-1.html since Windows has no condition variable until NT6
+       UINT waiters_count;
+       // Count of the number of waiters.
+
+       CRITICAL_SECTION waiters_count_lock;
+       // Serialize access to <waiters_count_>.
+
+       HANDLE events[MAX_EVENTS];
+} pthread_cond_t;
+typedef CRITICAL_SECTION pthread_mutex_t;
+
+typedef struct {} pthread_condattr_t; // Dummy;
+
+int pthread_cond_destroy(pthread_cond_t* cv)
+{
+       CloseHandle(cv->events[BROADCAST]);
+       CloseHandle(cv->events[SIGNAL]);
+
+       DeleteCriticalSection(&cv->waiters_count_lock);
+
+       return 0;
+}
+
+int pthread_cond_init(pthread_cond_t* cv, const pthread_condattr_t* attr)
+{
+       // Initialize the count to 0.
+       cv->waiters_count = 0;
+
+       // Create an auto-reset event.
+       cv->events[SIGNAL] = CreateEvent(NULL,  // no security
+                                        FALSE, // auto-reset event
+                                        FALSE, // non-signaled initially
+                                        NULL); // unnamed
+
+       // Create a manual-reset event.
+       cv->events[BROADCAST] = CreateEvent(NULL,  // no security
+                                           TRUE,  // manual-reset
+                                           FALSE, // non-signaled initially
+                                           NULL); // unnamed
+
+       InitializeCriticalSection(&cv->waiters_count_lock);
+
+       return 0;
+}
+
+int pthread_cond_broadcast(pthread_cond_t *cv)
+{
+       // Avoid race conditions.
+       EnterCriticalSection(&cv->waiters_count_lock);
+       int have_waiters = cv->waiters_count > 0;
+       LeaveCriticalSection(&cv->waiters_count_lock);
+
+       if (have_waiters)
+               SetEvent(cv->events[BROADCAST]);
+
+       return 0;
+}
+
+int pthread_cond_signal(pthread_cond_t* cv)
+{
+       // Avoid race conditions.
+       EnterCriticalSection(&cv->waiters_count_lock);
+       int have_waiters = cv->waiters_count > 0;
+       LeaveCriticalSection(&cv->waiters_count_lock);
+
+       if (have_waiters)
+               SetEvent(cv->events[SIGNAL]);
+
+       return 0;
+}
+
+int pthread_cond_wait(pthread_cond_t* cv, pthread_mutex_t* external_mutex)
+{
+       // Avoid race conditions.
+       EnterCriticalSection(&cv->waiters_count_lock);
+       cv->waiters_count++;
+       LeaveCriticalSection(&cv->waiters_count_lock);
+
+       // It's ok to release the <external_mutex> here since Win32
+       // manual-reset events maintain state when used with
+       // <SetEvent>.  This avoids the "lost wakeup" bug...
+       LeaveCriticalSection(external_mutex);
+
+       // Wait for either event to become signaled due to <pthread_cond_signal>
+       // being called or <pthread_cond_broadcast> being called.
+       int result = WaitForMultipleObjects(2, cv->events, FALSE, INFINITE);
+
+       EnterCriticalSection(&cv->waiters_count_lock);
+       cv->waiters_count--;
+       int last_waiter =
+               result == WAIT_OBJECT_0 + BROADCAST
+               && cv->waiters_count == 0;
+       LeaveCriticalSection(&cv->waiters_count_lock);
+
+       // Some thread called <pthread_cond_broadcast>.
+       if (last_waiter)
+               // We're the last waiter to be notified or to stop waiting, so
+               // reset the manual event. 
+               ResetEvent(cv->events[BROADCAST]);
+
+       // Reacquire the <external_mutex>.
+       EnterCriticalSection(external_mutex);
+
+       return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
+}
+
+typedef struct {} pthread_mutexattr_t; //< Dummy
+
+int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr)
+{
+       InitializeCriticalSection(mutex);
+       return 0;
+}
+
+int pthread_mutex_destroy(pthread_mutex_t* mutex)
+{
+       DeleteCriticalSection(mutex);
+       return 0;
+}
+
+int pthread_mutex_lock(pthread_mutex_t* mutex)
+{
+       EnterCriticalSection(mutex);
+       return 0;
+}
+
+int pthread_mutex_unlock(pthread_mutex_t* mutex)
+{
+       LeaveCriticalSection(mutex);
+       return 0;
+}
+
+typedef struct {} pthread_attr_t;
+
+typedef struct
+{
+       void *(*start_routine) (void *);
+       void* arg;
+} pthread_internal_thread;
+
+unsigned int __stdcall ThreadProc(void* userdata)
+{
+       pthread_internal_thread* ud = (pthread_internal_thread*) userdata;
+       ud->start_routine(ud->arg);
+
+       free(ud);
+
+       return 0;
+}
+
+int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void *(*start_routine) (void *), void *arg)
+{
+       pthread_internal_thread* ud = (pthread_internal_thread*) malloc(sizeof(pthread_internal_thread));
+       ud->start_routine = start_routine;
+       ud->arg = arg;
+
+       *thread = (HANDLE) (_beginthreadex(NULL, 0, &ThreadProc, ud, 0, NULL));
+       if (!*thread)
+               return 1;
+
+       return 0;
+}
+
+int pthread_join(pthread_t thread, void **value_ptr)
+{
+       WaitForSingleObject(thread, INFINITE);
+       CloseHandle(thread);
+
+       return 0;
+}
+
+#endif
+
+#include "chipmunk/chipmunk_private.h"
+#include "chipmunk/cpHastySpace.h"
+
+
+//MARK: ARM NEON Solver
+
+#if __ARM_NEON__
+#include <arm_neon.h>
+
+// Tested and known to work fine with Clang 3.0 and GCC 4.2
+// Doesn't work with Clang 1.6, and I have no idea why.
+#if defined(__clang_major__) && __clang_major__ < 3
+       #error Compiler not supported.
+#endif
+
+#if CP_USE_DOUBLES
+       #if !__arm64
+               #error Cannot use CP_USE_DOUBLES on 32 bit ARM.
+       #endif
+       
+       typedef float64_t cpFloat_t;
+       typedef float64x2_t cpFloatx2_t;
+       #define vld vld1q_f64
+       #define vdup_n vdupq_n_f64
+       #define vst vst1q_f64
+       #define vst_lane vst1q_lane_f64
+       #define vadd vaddq_f64
+       #define vsub vsubq_f64
+       #define vpadd vpaddq_f64
+       #define vmul vmulq_f64
+       #define vmul_n vmulq_n_f64
+       #define vneg vnegq_f64
+       #define vget_lane vgetq_lane_f64
+       #define vset_lane vsetq_lane_f64
+       #define vmin vminq_f64
+       #define vmax vmaxq_f64
+       #define vrev(__a) __builtin_shufflevector(__a, __a, 1, 0)
+#else
+       typedef float32_t cpFloat_t;
+       typedef float32x2_t cpFloatx2_t;
+       #define vld vld1_f32
+       #define vdup_n vdup_n_f32
+       #define vst vst1_f32
+       #define vst_lane vst1_lane_f32
+       #define vadd vadd_f32
+       #define vsub vsub_f32
+       #define vpadd vpadd_f32
+       #define vmul vmul_f32
+       #define vmul_n vmul_n_f32
+       #define vneg vneg_f32
+       #define vget_lane vget_lane_f32
+       #define vset_lane vset_lane_f32
+       #define vmin vmin_f32
+       #define vmax vmax_f32
+       #define vrev vrev64_f32
+#endif
+
+// TODO could probably do better here, maybe using vcreate?
+// especially for the constants
+// Maybe use the {} notation for GCC/Clang?
+static inline cpFloatx2_t
+vmake(cpFloat_t x, cpFloat_t y)
+{
+//     cpFloatx2_t v = {};
+//     v = vset_lane(x, v, 0);
+//     v = vset_lane(y, v, 1);
+//     
+//     return v;
+       
+       // This might not be super compatible, but all the NEON headers use it...
+       return (cpFloatx2_t){x, y};
+}
+
+static void
+cpArbiterApplyImpulse_NEON(cpArbiter *arb)
+{
+       cpBody *a = arb->body_a;
+       cpBody *b = arb->body_b;
+       cpFloatx2_t surface_vr = vld((cpFloat_t *)&arb->surface_vr);
+       cpFloatx2_t n = vld((cpFloat_t *)&arb->n);
+       cpFloat_t friction = arb->u;
+       
+       int numContacts = arb->count;
+       struct cpContact *contacts = arb->contacts;
+       for(int i=0; i<numContacts; i++){
+               struct cpContact *con = contacts + i;
+               cpFloatx2_t r1 = vld((cpFloat_t *)&con->r1);
+               cpFloatx2_t r2 = vld((cpFloat_t *)&con->r2);
+               
+               cpFloatx2_t perp = vmake(-1.0, 1.0);
+               cpFloatx2_t r1p = vmul(vrev(r1), perp);
+               cpFloatx2_t r2p = vmul(vrev(r2), perp);
+               
+               cpFloatx2_t vBias_a = vld((cpFloat_t *)&a->v_bias);
+               cpFloatx2_t vBias_b = vld((cpFloat_t *)&b->v_bias);
+               cpFloatx2_t wBias = vmake(a->w_bias, b->w_bias);
+               
+               cpFloatx2_t vb1 = vadd(vBias_a, vmul_n(r1p, vget_lane(wBias, 0)));
+               cpFloatx2_t vb2 = vadd(vBias_b, vmul_n(r2p, vget_lane(wBias, 1)));
+               cpFloatx2_t vbr = vsub(vb2, vb1);
+               
+               cpFloatx2_t v_a = vld((cpFloat_t *)&a->v);
+               cpFloatx2_t v_b = vld((cpFloat_t *)&b->v);
+               cpFloatx2_t w = vmake(a->w, b->w);
+               cpFloatx2_t v1 = vadd(v_a, vmul_n(r1p, vget_lane(w, 0)));
+               cpFloatx2_t v2 = vadd(v_b, vmul_n(r2p, vget_lane(w, 1)));
+               cpFloatx2_t vr = vsub(v2, v1);
+               
+               cpFloatx2_t vbn_vrn = vpadd(vmul(vbr, n), vmul(vr, n));
+               
+               cpFloatx2_t v_offset = vmake(con->bias, -con->bounce);
+               cpFloatx2_t jOld = vmake(con->jBias, con->jnAcc);
+               cpFloatx2_t jbn_jn = vmul_n(vsub(v_offset, vbn_vrn), con->nMass);
+               jbn_jn = vmax(vadd(jOld, jbn_jn), vdup_n(0.0));
+               cpFloatx2_t jApply = vsub(jbn_jn, jOld);
+               
+               cpFloatx2_t t = vmul(vrev(n), perp);
+               cpFloatx2_t vrt_tmp = vmul(vadd(vr, surface_vr), t);
+               cpFloatx2_t vrt = vpadd(vrt_tmp, vrt_tmp);
+               
+               cpFloatx2_t jtOld = {}; jtOld = vset_lane(con->jtAcc, jtOld, 0);
+               cpFloatx2_t jtMax = vrev(vmul_n(jbn_jn, friction));
+               cpFloatx2_t jt = vmul_n(vrt, -con->tMass);
+               jt = vmax(vneg(jtMax), vmin(vadd(jtOld, jt), jtMax));
+               cpFloatx2_t jtApply = vsub(jt, jtOld);
+               
+               cpFloatx2_t i_inv = vmake(-a->i_inv, b->i_inv);
+               cpFloatx2_t nperp = vmake(1.0, -1.0);
+               
+               cpFloatx2_t jBias = vmul_n(n, vget_lane(jApply, 0));
+               cpFloatx2_t jBiasCross = vmul(vrev(jBias), nperp);
+               cpFloatx2_t biasCrosses = vpadd(vmul(r1, jBiasCross), vmul(r2, jBiasCross));
+               wBias = vadd(wBias, vmul(i_inv, biasCrosses));
+               
+               vBias_a = vsub(vBias_a, vmul_n(jBias, a->m_inv));
+               vBias_b = vadd(vBias_b, vmul_n(jBias, b->m_inv));
+               
+               cpFloatx2_t j = vadd(vmul_n(n, vget_lane(jApply, 1)), vmul_n(t, vget_lane(jtApply, 0)));
+               cpFloatx2_t jCross = vmul(vrev(j), nperp);
+               cpFloatx2_t crosses = vpadd(vmul(r1, jCross), vmul(r2, jCross));
+               w = vadd(w, vmul(i_inv, crosses));
+               
+               v_a = vsub(v_a, vmul_n(j, a->m_inv));
+               v_b = vadd(v_b, vmul_n(j, b->m_inv));
+               
+               // TODO would moving these earlier help pipeline them better?
+               vst((cpFloat_t *)&a->v_bias, vBias_a);
+               vst((cpFloat_t *)&b->v_bias, vBias_b);
+               vst_lane((cpFloat_t *)&a->w_bias, wBias, 0);
+               vst_lane((cpFloat_t *)&b->w_bias, wBias, 1);
+               
+               vst((cpFloat_t *)&a->v, v_a);
+               vst((cpFloat_t *)&b->v, v_b);
+               vst_lane((cpFloat_t *)&a->w, w, 0);
+               vst_lane((cpFloat_t *)&b->w, w, 1);
+               
+               vst_lane((cpFloat_t *)&con->jBias, jbn_jn, 0);
+               vst_lane((cpFloat_t *)&con->jnAcc, jbn_jn, 1);
+               vst_lane((cpFloat_t *)&con->jtAcc, jt, 0);
+       }
+}
+
+#endif
+
+//MARK: PThreads
+
+// Right now using more than 2 threads probably wont help your performance any.
+// If you are using a ridiculous number of iterations it could help though.
+#define MAX_THREADS 2
+
+struct ThreadContext {
+       pthread_t thread;
+       cpHastySpace *space;
+       unsigned long thread_num;
+};
+
+typedef        void (*cpHastySpaceWorkFunction)(cpSpace *space, unsigned long worker, unsigned long worker_count);
+
+struct cpHastySpace {
+       cpSpace space;
+       
+       // Number of worker threads (including the main thread)
+       unsigned long num_threads;
+       
+       // Number of worker threads currently executing. (also including the main thread)
+       unsigned long num_working;
+       
+       // Number of constraints (plus contacts) that must exist per step to start the worker threads.
+       unsigned long constraint_count_threshold;
+       
+       pthread_mutex_t mutex;
+       pthread_cond_t cond_work, cond_resume;
+       
+       // Work function to invoke.
+       cpHastySpaceWorkFunction work;
+       
+       struct ThreadContext workers[MAX_THREADS - 1];
+};
+
+static void *
+WorkerThreadLoop(struct ThreadContext *context)
+{
+       cpHastySpace *hasty = context->space;
+       
+       unsigned long thread = context->thread_num;
+       unsigned long num_threads = hasty->num_threads;
+       
+       for(;;){
+               pthread_mutex_lock(&hasty->mutex); {
+                       if(--hasty->num_working == 0){
+                               pthread_cond_signal(&hasty->cond_resume);
+                       }
+                       
+                       pthread_cond_wait(&hasty->cond_work, &hasty->mutex);
+               } pthread_mutex_unlock(&hasty->mutex);
+               
+               cpHastySpaceWorkFunction func = hasty->work;
+               if(func){
+                       hasty->work(&hasty->space, thread, num_threads);
+               } else {
+                       break;
+               }
+       }
+       
+       return NULL;
+}
+
+static void
+RunWorkers(cpHastySpace *hasty, cpHastySpaceWorkFunction func)
+{
+       hasty->num_working = hasty->num_threads - 1;
+       hasty->work = func;
+       
+       if(hasty->num_working > 0){
+               pthread_mutex_lock(&hasty->mutex); {
+                       pthread_cond_broadcast(&hasty->cond_work);
+               } pthread_mutex_unlock(&hasty->mutex);
+               
+               func((cpSpace *)hasty, 0, hasty->num_threads);
+                       
+               pthread_mutex_lock(&hasty->mutex); {
+                       if(hasty->num_working > 0){
+                               pthread_cond_wait(&hasty->cond_resume, &hasty->mutex);
+                       }
+               } pthread_mutex_unlock(&hasty->mutex);
+       } else {
+               func((cpSpace *)hasty, 0, hasty->num_threads);
+       }
+       
+       hasty->work = NULL;
+}
+
+static void
+Solver(cpSpace *space, unsigned long worker, unsigned long worker_count)
+{
+       cpArray *constraints = space->constraints;
+       cpArray *arbiters = space->arbiters;
+       
+       cpFloat dt = space->curr_dt;
+       unsigned long iterations = (space->iterations + worker_count - 1)/worker_count;
+       
+       for(unsigned long i=0; i<iterations; i++){
+               for(int j=0; j<arbiters->num; j++){
+                       cpArbiter *arb = (cpArbiter *)arbiters->arr[j];
+                       #ifdef __ARM_NEON__
+                               cpArbiterApplyImpulse_NEON(arb);
+                       #else
+                               cpArbiterApplyImpulse(arb);
+                       #endif
+               }
+                       
+               for(int j=0; j<constraints->num; j++){
+                       cpConstraint *constraint = (cpConstraint *)constraints->arr[j];
+                       constraint->klass->applyImpulse(constraint, dt);
+               }
+       }
+}
+
+//MARK: Thread Management Functions
+
+static void
+HaltThreads(cpHastySpace *hasty)
+{
+       pthread_mutex_t *mutex = &hasty->mutex;
+       pthread_mutex_lock(mutex); {
+               hasty->work = NULL; // NULL work function means break and exit
+               pthread_cond_broadcast(&hasty->cond_work);
+       } pthread_mutex_unlock(mutex);
+       
+       for(unsigned long i=0; i<(hasty->num_threads-1); i++){
+               pthread_join(hasty->workers[i].thread, NULL);
+       }
+}
+
+void
+cpHastySpaceSetThreads(cpSpace *space, unsigned long threads)
+{
+#if TARGET_IPHONE_SIMULATOR == 1
+       // Individual values appear to be written non-atomically when compiled as debug for the simulator.
+       // No idea why, so threads are disabled.
+       threads = 1;
+#endif 
+       
+       cpHastySpace *hasty = (cpHastySpace *)space;
+       HaltThreads(hasty);
+       
+#ifdef __APPLE__
+       if(threads == 0){
+               size_t size = sizeof(threads);
+               sysctlbyname("hw.ncpu", &threads, &size, NULL, 0);
+       }
+#else
+       if(threads == 0) threads = 1;
+#endif
+       
+       hasty->num_threads = (threads < MAX_THREADS ? threads : MAX_THREADS);
+       hasty->num_working = hasty->num_threads - 1;
+       
+       // Create the worker threads and wait for them to signal ready.
+       if(hasty->num_working > 0){
+               pthread_mutex_lock(&hasty->mutex);
+               for(unsigned long i=0; i<(hasty->num_threads-1); i++){
+                       hasty->workers[i].space = hasty;
+                       hasty->workers[i].thread_num = i + 1;
+                       
+                       pthread_create(&hasty->workers[i].thread, NULL, (void*(*)(void*))WorkerThreadLoop, &hasty->workers[i]);
+               }
+               
+               pthread_cond_wait(&hasty->cond_resume, &hasty->mutex);
+               pthread_mutex_unlock(&hasty->mutex);
+       }
+}
+
+unsigned long
+cpHastySpaceGetThreads(cpSpace *space)
+{
+       return ((cpHastySpace *)space)->num_threads;
+}
+
+//MARK: Overriden cpSpace Functions.
+
+cpSpace *
+cpHastySpaceNew(void)
+{
+       cpHastySpace *hasty = (cpHastySpace *)cpcalloc(1, sizeof(cpHastySpace));
+       cpSpaceInit((cpSpace *)hasty);
+       
+       pthread_mutex_init(&hasty->mutex, NULL);
+       pthread_cond_init(&hasty->cond_work, NULL);
+       pthread_cond_init(&hasty->cond_resume, NULL);
+       
+       // TODO magic number, should test this more thoroughly.
+       hasty->constraint_count_threshold = 50;
+       
+       // Default to 1 thread for determinism.
+       hasty->num_threads = 1;
+       cpHastySpaceSetThreads((cpSpace *)hasty, 1);
+
+       return (cpSpace *)hasty;
+}
+
+void
+cpHastySpaceFree(cpSpace *space)
+{
+       cpHastySpace *hasty = (cpHastySpace *)space;
+       
+       HaltThreads(hasty);
+       
+       pthread_mutex_destroy(&hasty->mutex);
+       pthread_cond_destroy(&hasty->cond_work);
+       pthread_cond_destroy(&hasty->cond_resume);
+       
+       cpSpaceFree(space);
+}
+
+void
+cpHastySpaceStep(cpSpace *space, cpFloat dt)
+{
+       // don't step if the timestep is 0!
+       if(dt == 0.0f) return;
+       
+       space->stamp++;
+       
+       cpFloat prev_dt = space->curr_dt;
+       space->curr_dt = dt;
+               
+       cpArray *bodies = space->dynamicBodies;
+       cpArray *constraints = space->constraints;
+       cpArray *arbiters = space->arbiters;
+       
+       // Reset and empty the arbiter list.
+       for(int i=0; i<arbiters->num; i++){
+               cpArbiter *arb = (cpArbiter *)arbiters->arr[i];
+               arb->state = CP_ARBITER_STATE_NORMAL;
+               
+               // If both bodies are awake, unthread the arbiter from the contact graph.
+               if(!cpBodyIsSleeping(arb->body_a) && !cpBodyIsSleeping(arb->body_b)){
+                       cpArbiterUnthread(arb);
+               }
+       }
+       arbiters->num = 0;
+       
+       cpSpaceLock(space); {
+               // Integrate positions
+               for(int i=0; i<bodies->num; i++){
+                       cpBody *body = (cpBody *)bodies->arr[i];
+                       body->position_func(body, dt);
+               }
+               
+               // Find colliding pairs.
+               cpSpacePushFreshContactBuffer(space);
+               cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)cpShapeUpdateFunc, NULL);
+               cpSpatialIndexReindexQuery(space->dynamicShapes, (cpSpatialIndexQueryFunc)cpSpaceCollideShapes, space);
+       } cpSpaceUnlock(space, cpFalse);
+       
+       // Rebuild the contact graph (and detect sleeping components if sleeping is enabled)
+       cpSpaceProcessComponents(space, dt);
+       
+       cpSpaceLock(space); {
+               // Clear out old cached arbiters and call separate callbacks
+               cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cpSpaceArbiterSetFilter, space);
+
+               // Prestep the arbiters and constraints.
+               cpFloat slop = space->collisionSlop;
+               cpFloat biasCoef = 1.0f - cpfpow(space->collisionBias, dt);
+               for(int i=0; i<arbiters->num; i++){
+                       cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt, slop, biasCoef);
+               }
+
+               for(int i=0; i<constraints->num; i++){
+                       cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+                       
+                       cpConstraintPreSolveFunc preSolve = constraint->preSolve;
+                       if(preSolve) preSolve(constraint, space);
+                       
+                       constraint->klass->preStep(constraint, dt);
+               }
+       
+               // Integrate velocities.
+               cpFloat damping = cpfpow(space->damping, dt);
+               cpVect gravity = space->gravity;
+               for(int i=0; i<bodies->num; i++){
+                       cpBody *body = (cpBody *)bodies->arr[i];
+                       body->velocity_func(body, gravity, damping, dt);
+               }
+               
+               // Apply cached impulses
+               cpFloat dt_coef = (prev_dt == 0.0f ? 0.0f : dt/prev_dt);
+               for(int i=0; i<arbiters->num; i++){
+                       cpArbiterApplyCachedImpulse((cpArbiter *)arbiters->arr[i], dt_coef);
+               }
+               
+               for(int i=0; i<constraints->num; i++){
+                       cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+                       constraint->klass->applyCachedImpulse(constraint, dt_coef);
+               }
+               
+               // Run the impulse solver.
+               cpHastySpace *hasty = (cpHastySpace *)space;
+               if((unsigned long)(arbiters->num + constraints->num) > hasty->constraint_count_threshold){
+                       RunWorkers(hasty, Solver);
+               } else {
+                       Solver(space, 0, 1);
+               }
+               
+               // Run the constraint post-solve callbacks
+               for(int i=0; i<constraints->num; i++){
+                       cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+                       
+                       cpConstraintPostSolveFunc postSolve = constraint->postSolve;
+                       if(postSolve) postSolve(constraint, space);
+               }
+               
+               // run the post-solve callbacks
+               for(int i=0; i<arbiters->num; i++){
+                       cpArbiter *arb = (cpArbiter *) arbiters->arr[i];
+                       
+                       cpCollisionHandler *handler = arb->handler;
+                       handler->postSolveFunc(arb, space, handler->userData);
+               }
+       } cpSpaceUnlock(space, cpTrue);
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpMarch.c b/dali-physics/third-party/chipmunk2d/src/cpMarch.c
new file mode 100644 (file)
index 0000000..c666bd2
--- /dev/null
@@ -0,0 +1,157 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "chipmunk/chipmunk.h"
+#include "chipmunk/cpMarch.h"
+
+
+typedef void (*cpMarchCellFunc)(
+       cpFloat t, cpFloat a, cpFloat b, cpFloat c, cpFloat d,
+       cpFloat x0, cpFloat x1, cpFloat y0, cpFloat y1,
+       cpMarchSegmentFunc segment, void *segment_data
+);
+
+// The looping and sample caching code is shared between cpMarchHard() and cpMarchSoft().
+static void
+cpMarchCells(
+  cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat t,
+  cpMarchSegmentFunc segment, void *segment_data,
+  cpMarchSampleFunc sample, void *sample_data,
+       cpMarchCellFunc cell
+){
+       cpFloat x_denom = 1.0/(cpFloat)(x_samples - 1);
+       cpFloat y_denom = 1.0/(cpFloat)(y_samples - 1);
+       
+       // TODO range assertions and short circuit for 0 sized windows.
+       
+       // Keep a copy of the previous row to avoid double lookups.
+       cpFloat *buffer = (cpFloat *)cpcalloc(x_samples, sizeof(cpFloat));
+       for(unsigned long i=0; i<x_samples; i++) buffer[i] = sample(cpv(cpflerp(bb.l, bb.r, i*x_denom), bb.b), sample_data);
+       
+       for(unsigned long j=0; j<y_samples-1; j++){
+               cpFloat y0 = cpflerp(bb.b, bb.t, (j+0)*y_denom);
+               cpFloat y1 = cpflerp(bb.b, bb.t, (j+1)*y_denom);
+               
+               cpFloat a, b = buffer[0];
+               cpFloat c, d = sample(cpv(bb.l, y1), sample_data);
+               buffer[0] = d;
+               
+               for(unsigned long i=0; i<x_samples-1; i++){
+                       cpFloat x0 = cpflerp(bb.l, bb.r, (i+0)*x_denom);
+                       cpFloat x1 = cpflerp(bb.l, bb.r, (i+1)*x_denom);
+                       
+                       a = b, b = buffer[i + 1];
+                       c = d, d = sample(cpv(x1, y1), sample_data);
+                       buffer[i + 1] = d;
+                       
+                       cell(t, a, b, c, d, x0, x1, y0, y1, segment, segment_data);
+               }
+       }
+       
+       cpfree(buffer);
+}
+
+
+// TODO should flip this around eventually.
+static inline void
+seg(cpVect v0, cpVect v1, cpMarchSegmentFunc f, void *data)
+{
+       if(!cpveql(v0, v1)) f(v1, v0, data);
+}
+
+// Lerps between two positions based on their sample values.
+static inline cpFloat
+midlerp(cpFloat x0, cpFloat x1, cpFloat s0, cpFloat s1, cpFloat t)
+{
+       return cpflerp(x0, x1, (t - s0)/(s1 - s0));
+}
+
+static void
+cpMarchCellSoft(
+       cpFloat t, cpFloat a, cpFloat b, cpFloat c, cpFloat d,
+       cpFloat x0, cpFloat x1, cpFloat y0, cpFloat y1,
+       cpMarchSegmentFunc segment, void *segment_data
+){
+       // TODO this switch part is super expensive, can it be NEONized?
+       switch((a>t)<<0 | (b>t)<<1 | (c>t)<<2 | (d>t)<<3){
+               case 0x1: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data); break;
+               case 0x2: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data); break;
+               case 0x3: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data); break;
+               case 0x4: seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break;
+               case 0x5: seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data); break;
+               case 0x6: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data);
+                                                       seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break;
+               case 0x7: seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data); break;
+               case 0x8: seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break;
+               case 0x9: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data);
+                                                       seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break;
+               case 0xA: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break;
+               case 0xB: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break;
+               case 0xC: seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break;
+               case 0xD: seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data); break;
+               case 0xE: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break;
+               default: break; // 0x0 and 0xF
+       }
+}
+
+void
+cpMarchSoft(
+  cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat t,
+  cpMarchSegmentFunc segment, void *segment_data,
+  cpMarchSampleFunc sample, void *sample_data
+){
+       cpMarchCells(bb, x_samples, y_samples, t, segment, segment_data, sample, sample_data, cpMarchCellSoft);
+}
+
+
+// TODO should flip this around eventually.
+static inline void
+segs(cpVect a, cpVect b, cpVect c, cpMarchSegmentFunc f, void *data)
+{
+       seg(b, c, f, data);
+       seg(a, b, f, data);
+}
+
+static void
+cpMarchCellHard(
+       cpFloat t, cpFloat a, cpFloat b, cpFloat c, cpFloat d,
+       cpFloat x0, cpFloat x1, cpFloat y0, cpFloat y1,
+       cpMarchSegmentFunc segment, void *segment_data
+){
+       // midpoints
+       cpFloat xm = cpflerp(x0, x1, 0.5f);
+       cpFloat ym = cpflerp(y0, y1, 0.5f);
+       
+       switch((a>t)<<0 | (b>t)<<1 | (c>t)<<2 | (d>t)<<3){
+               case 0x1: segs(cpv(x0, ym), cpv(xm, ym), cpv(xm, y0), segment, segment_data); break;
+               case 0x2: segs(cpv(xm, y0), cpv(xm, ym), cpv(x1, ym), segment, segment_data); break;
+               case 0x3: seg(cpv(x0, ym), cpv(x1, ym), segment, segment_data); break;
+               case 0x4: segs(cpv(xm, y1), cpv(xm, ym), cpv(x0, ym), segment, segment_data); break;
+               case 0x5: seg(cpv(xm, y1), cpv(xm, y0), segment, segment_data); break;
+               case 0x6: segs(cpv(xm, y0), cpv(xm, ym), cpv(x0, ym), segment, segment_data);
+                         segs(cpv(xm, y1), cpv(xm, ym), cpv(x1, ym), segment, segment_data); break;
+               case 0x7: segs(cpv(xm, y1), cpv(xm, ym), cpv(x1, ym), segment, segment_data); break;
+               case 0x8: segs(cpv(x1, ym), cpv(xm, ym), cpv(xm, y1), segment, segment_data); break;
+               case 0x9: segs(cpv(x1, ym), cpv(xm, ym), cpv(xm, y0), segment, segment_data);
+                         segs(cpv(x0, ym), cpv(xm, ym), cpv(xm, y1), segment, segment_data); break;
+               case 0xA: seg(cpv(xm, y0), cpv(xm, y1), segment, segment_data); break;
+               case 0xB: segs(cpv(x0, ym), cpv(xm, ym), cpv(xm, y1), segment, segment_data); break;
+               case 0xC: seg(cpv(x1, ym), cpv(x0, ym), segment, segment_data); break;
+               case 0xD: segs(cpv(x1, ym), cpv(xm, ym), cpv(xm, y0), segment, segment_data); break;
+               case 0xE: segs(cpv(xm, y0), cpv(xm, ym), cpv(x0, ym), segment, segment_data); break;
+               default: break; // 0x0 and 0xF
+       }
+}
+
+void
+cpMarchHard(
+  cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat t,
+  cpMarchSegmentFunc segment, void *segment_data,
+  cpMarchSampleFunc sample, void *sample_data
+){
+       cpMarchCells(bb, x_samples, y_samples, t, segment, segment_data, sample, sample_data, cpMarchCellHard);
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpPinJoint.c b/dali-physics/third-party/chipmunk2d/src/cpPinJoint.c
new file mode 100644 (file)
index 0000000..545e78b
--- /dev/null
@@ -0,0 +1,172 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpPinJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       joint->r1 = cpTransformVect(a->transform, cpvsub(joint->anchorA, a->cog));
+       joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog));
+       
+       cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
+       cpFloat dist = cpvlength(delta);
+       joint->n = cpvmult(delta, 1.0f/(dist ? dist : (cpFloat)INFINITY));
+       
+       // calculate mass normal
+       joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);
+       
+       // calculate bias velocity
+       cpFloat maxBias = joint->constraint.maxBias;
+       joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(dist - joint->dist)/dt, -maxBias, maxBias);
+}
+
+static void
+applyCachedImpulse(cpPinJoint *joint, cpFloat dt_coef)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpVect j = cpvmult(joint->n, joint->jnAcc*dt_coef);
+       apply_impulses(a, b, joint->r1, joint->r2, j);
+}
+
+static void
+applyImpulse(cpPinJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       cpVect n = joint->n;
+
+       // compute relative velocity
+       cpFloat vrn = normal_relative_velocity(a, b, joint->r1, joint->r2, n);
+       
+       cpFloat jnMax = joint->constraint.maxForce*dt;
+       
+       // compute normal impulse
+       cpFloat jn = (joint->bias - vrn)*joint->nMass;
+       cpFloat jnOld = joint->jnAcc;
+       joint->jnAcc = cpfclamp(jnOld + jn, -jnMax, jnMax);
+       jn = joint->jnAcc - jnOld;
+       
+       // apply impulse
+       apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn));
+}
+
+static cpFloat
+getImpulse(cpPinJoint *joint)
+{
+       return cpfabs(joint->jnAcc);
+}
+
+static const cpConstraintClass klass = {
+       (cpConstraintPreStepImpl)preStep,
+       (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+       (cpConstraintApplyImpulseImpl)applyImpulse,
+       (cpConstraintGetImpulseImpl)getImpulse,
+};
+
+
+cpPinJoint *
+cpPinJointAlloc(void)
+{
+       return (cpPinJoint *)cpcalloc(1, sizeof(cpPinJoint));
+}
+
+cpPinJoint *
+cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB)
+{
+       cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+       
+       joint->anchorA = anchorA;
+       joint->anchorB = anchorB;
+       
+       // STATIC_BODY_CHECK
+       cpVect p1 = (a ? cpTransformPoint(a->transform, anchorA) : anchorA);
+       cpVect p2 = (b ? cpTransformPoint(b->transform, anchorB) : anchorB);
+       joint->dist = cpvlength(cpvsub(p2, p1));
+       
+       cpAssertWarn(joint->dist > 0.0, "You created a 0 length pin joint. A pivot joint will be much more stable.");
+
+       joint->jnAcc = 0.0f;
+       
+       return joint;
+}
+
+cpConstraint *
+cpPinJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB)
+{
+       return (cpConstraint *)cpPinJointInit(cpPinJointAlloc(), a, b, anchorA, anchorB);
+}
+
+cpBool
+cpConstraintIsPinJoint(const cpConstraint *constraint)
+{
+       return (constraint->klass == &klass);
+}
+
+cpVect
+cpPinJointGetAnchorA(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+       return ((cpPinJoint *)constraint)->anchorA;
+}
+
+void
+cpPinJointSetAnchorA(cpConstraint *constraint, cpVect anchorA)
+{
+       cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpPinJoint *)constraint)->anchorA = anchorA;
+}
+
+cpVect
+cpPinJointGetAnchorB(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+       return ((cpPinJoint *)constraint)->anchorB;
+}
+
+void
+cpPinJointSetAnchorB(cpConstraint *constraint, cpVect anchorB)
+{
+       cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpPinJoint *)constraint)->anchorB = anchorB;
+}
+
+cpFloat
+cpPinJointGetDist(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+       return ((cpPinJoint *)constraint)->dist;
+}
+
+void
+cpPinJointSetDist(cpConstraint *constraint, cpFloat dist)
+{
+       cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpPinJoint *)constraint)->dist = dist;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpPivotJoint.c b/dali-physics/third-party/chipmunk2d/src/cpPivotJoint.c
new file mode 100644 (file)
index 0000000..e45ba07
--- /dev/null
@@ -0,0 +1,152 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpPivotJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       joint->r1 = cpTransformVect(a->transform, cpvsub(joint->anchorA, a->cog));
+       joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog));
+       
+       // Calculate mass tensor
+       joint-> k = k_tensor(a, b, joint->r1, joint->r2);
+       
+       // calculate bias velocity
+       cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
+       joint->bias = cpvclamp(cpvmult(delta, -bias_coef(joint->constraint.errorBias, dt)/dt), joint->constraint.maxBias);
+}
+
+static void
+applyCachedImpulse(cpPivotJoint *joint, cpFloat dt_coef)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       apply_impulses(a, b, joint->r1, joint->r2, cpvmult(joint->jAcc, dt_coef));
+}
+
+static void
+applyImpulse(cpPivotJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpVect r1 = joint->r1;
+       cpVect r2 = joint->r2;
+               
+       // compute relative velocity
+       cpVect vr = relative_velocity(a, b, r1, r2);
+       
+       // compute normal impulse
+       cpVect j = cpMat2x2Transform(joint->k, cpvsub(joint->bias, vr));
+       cpVect jOld = joint->jAcc;
+       joint->jAcc = cpvclamp(cpvadd(joint->jAcc, j), joint->constraint.maxForce*dt);
+       j = cpvsub(joint->jAcc, jOld);
+       
+       // apply impulse
+       apply_impulses(a, b, joint->r1, joint->r2, j);
+}
+
+static cpFloat
+getImpulse(cpConstraint *joint)
+{
+       return cpvlength(((cpPivotJoint *)joint)->jAcc);
+}
+
+static const cpConstraintClass klass = {
+       (cpConstraintPreStepImpl)preStep,
+       (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+       (cpConstraintApplyImpulseImpl)applyImpulse,
+       (cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpPivotJoint *
+cpPivotJointAlloc(void)
+{
+       return (cpPivotJoint *)cpcalloc(1, sizeof(cpPivotJoint));
+}
+
+cpPivotJoint *
+cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB)
+{
+       cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+       
+       joint->anchorA = anchorA;
+       joint->anchorB = anchorB;
+       
+       joint->jAcc = cpvzero;
+       
+       return joint;
+}
+
+cpConstraint *
+cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB)
+{
+       return (cpConstraint *)cpPivotJointInit(cpPivotJointAlloc(), a, b, anchorA, anchorB);
+}
+
+cpConstraint *
+cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot)
+{
+       cpVect anchorA = (a ? cpBodyWorldToLocal(a, pivot) : pivot);
+       cpVect anchorB = (b ? cpBodyWorldToLocal(b, pivot) : pivot);
+       return cpPivotJointNew2(a, b, anchorA, anchorB);
+}
+
+cpBool
+cpConstraintIsPivotJoint(const cpConstraint *constraint)
+{
+       return (constraint->klass == &klass);
+}
+
+cpVect
+cpPivotJointGetAnchorA(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint.");
+       return ((cpPivotJoint *)constraint)->anchorA;
+}
+
+void
+cpPivotJointSetAnchorA(cpConstraint *constraint, cpVect anchorA)
+{
+       cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpPivotJoint *)constraint)->anchorA = anchorA;
+}
+
+cpVect
+cpPivotJointGetAnchorB(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint.");
+       return ((cpPivotJoint *)constraint)->anchorB;
+}
+
+void
+cpPivotJointSetAnchorB(cpConstraint *constraint, cpVect anchorB)
+{
+       cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpPivotJoint *)constraint)->anchorB = anchorB;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpPolyShape.c b/dali-physics/third-party/chipmunk2d/src/cpPolyShape.c
new file mode 100644 (file)
index 0000000..db68cdc
--- /dev/null
@@ -0,0 +1,323 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+#include "chipmunk/chipmunk_unsafe.h"
+
+cpPolyShape *
+cpPolyShapeAlloc(void)
+{
+       return (cpPolyShape *)cpcalloc(1, sizeof(cpPolyShape));
+}
+
+static void
+cpPolyShapeDestroy(cpPolyShape *poly)
+{
+       if(poly->count > CP_POLY_SHAPE_INLINE_ALLOC){
+               cpfree(poly->planes);
+       }
+}
+
+static cpBB
+cpPolyShapeCacheData(cpPolyShape *poly, cpTransform transform)
+{
+       int count = poly->count;
+       struct cpSplittingPlane *dst = poly->planes;
+       struct cpSplittingPlane *src = dst + count;
+       
+       cpFloat l = (cpFloat)INFINITY, r = -(cpFloat)INFINITY;
+       cpFloat b = (cpFloat)INFINITY, t = -(cpFloat)INFINITY;
+       
+       for(int i=0; i<count; i++){
+               cpVect v = cpTransformPoint(transform, src[i].v0);
+               cpVect n = cpTransformVect(transform, src[i].n);
+               
+               dst[i].v0 = v;
+               dst[i].n = n;
+               
+               l = cpfmin(l, v.x);
+               r = cpfmax(r, v.x);
+               b = cpfmin(b, v.y);
+               t = cpfmax(t, v.y);
+       }
+       
+       cpFloat radius = poly->r;
+       return (poly->shape.bb = cpBBNew(l - radius, b - radius, r + radius, t + radius));
+}
+
+static void
+cpPolyShapePointQuery(cpPolyShape *poly, cpVect p, cpPointQueryInfo *info){
+       int count = poly->count;
+       struct cpSplittingPlane *planes = poly->planes;
+       cpFloat r = poly->r;
+       
+       cpVect v0 = planes[count - 1].v0;
+       cpFloat minDist = INFINITY;
+       cpVect closestPoint = cpvzero;
+       cpVect closestNormal = cpvzero;
+       cpBool outside = cpFalse;
+       
+       for(int i=0; i<count; i++){
+               cpVect v1 = planes[i].v0;
+               outside = outside || (cpvdot(planes[i].n, cpvsub(p,v1)) > 0.0f);
+               
+               cpVect closest = cpClosetPointOnSegment(p, v0, v1);
+               
+               cpFloat dist = cpvdist(p, closest);
+               if(dist < minDist){
+                       minDist = dist;
+                       closestPoint = closest;
+                       closestNormal = planes[i].n;
+               }
+               
+               v0 = v1;
+       }
+       
+       cpFloat dist = (outside ? minDist : -minDist);
+       cpVect g = cpvmult(cpvsub(p, closestPoint), 1.0f/dist);
+       
+       info->shape = (cpShape *)poly;
+       info->point = cpvadd(closestPoint, cpvmult(g, r));
+       info->distance = dist - r;
+       
+       // Use the normal of the closest segment if the distance is small.
+       info->gradient = (minDist > MAGIC_EPSILON ? g : closestNormal);
+}
+
+static void
+cpPolyShapeSegmentQuery(cpPolyShape *poly, cpVect a, cpVect b, cpFloat r2, cpSegmentQueryInfo *info)
+{
+       struct cpSplittingPlane *planes = poly->planes;
+       int count = poly->count;
+       cpFloat r = poly->r;
+       cpFloat rsum = r + r2;
+       
+       for(int i=0; i<count; i++){
+               cpVect n = planes[i].n;
+               cpFloat an = cpvdot(a, n);
+               cpFloat d =  an - cpvdot(planes[i].v0, n) - rsum;
+               if(d < 0.0f) continue;
+               
+               cpFloat bn = cpvdot(b, n);
+               cpFloat t = d/(an - bn);
+               if(t < 0.0f || 1.0f < t) continue;
+               
+               cpVect point = cpvlerp(a, b, t);
+               cpFloat dt = cpvcross(n, point);
+               cpFloat dtMin = cpvcross(n, planes[(i - 1 + count)%count].v0);
+               cpFloat dtMax = cpvcross(n, planes[i].v0);
+               
+               if(dtMin <= dt && dt <= dtMax){
+                       info->shape = (cpShape *)poly;
+                       info->point = cpvsub(cpvlerp(a, b, t), cpvmult(n, r2));
+                       info->normal = n;
+                       info->alpha = t;
+               }
+       }
+       
+       // Also check against the beveled vertexes.
+       if(rsum > 0.0f){
+               for(int i=0; i<count; i++){
+                       cpSegmentQueryInfo circle_info = {NULL, b, cpvzero, 1.0f};
+                       CircleSegmentQuery(&poly->shape, planes[i].v0, r, a, b, r2, &circle_info);
+                       if(circle_info.alpha < info->alpha) (*info) = circle_info;
+               }
+       }
+}
+
+static void
+SetVerts(cpPolyShape *poly, int count, const cpVect *verts)
+{
+       poly->count = count;
+       if(count <= CP_POLY_SHAPE_INLINE_ALLOC){
+               poly->planes = poly->_planes;
+       } else {
+               poly->planes = (struct cpSplittingPlane *)cpcalloc(2*count, sizeof(struct cpSplittingPlane));
+       }
+       
+       for(int i=0; i<count; i++){
+               cpVect a = verts[(i - 1 + count)%count];
+               cpVect b = verts[i];
+               cpVect n = cpvnormalize(cpvrperp(cpvsub(b, a)));
+               
+               poly->planes[i + count].v0 = b;
+               poly->planes[i + count].n = n;
+       }
+}
+
+static struct cpShapeMassInfo
+cpPolyShapeMassInfo(cpFloat mass, int count, const cpVect *verts, cpFloat radius)
+{
+       // TODO moment is approximate due to radius.
+       
+       cpVect centroid = cpCentroidForPoly(count, verts);
+       struct cpShapeMassInfo info = {
+               mass, cpMomentForPoly(1.0f, count, verts, cpvneg(centroid), radius),
+               centroid,
+               cpAreaForPoly(count, verts, radius),
+       };
+       
+       return info;
+}
+
+static const cpShapeClass polyClass = {
+       CP_POLY_SHAPE,
+       (cpShapeCacheDataImpl)cpPolyShapeCacheData,
+       (cpShapeDestroyImpl)cpPolyShapeDestroy,
+       (cpShapePointQueryImpl)cpPolyShapePointQuery,
+       (cpShapeSegmentQueryImpl)cpPolyShapeSegmentQuery,
+};
+
+cpPolyShape *
+cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius)
+{
+       cpVect *hullVerts = (cpVect *)alloca(count*sizeof(cpVect));
+       
+       // Transform the verts before building the hull in case of a negative scale.
+       for(int i=0; i<count; i++) hullVerts[i] = cpTransformPoint(transform, verts[i]);
+       
+       unsigned int hullCount = cpConvexHull(count, hullVerts, hullVerts, NULL, 0.0);
+       return cpPolyShapeInitRaw(poly, body, hullCount, hullVerts, radius);
+}
+
+cpPolyShape *
+cpPolyShapeInitRaw(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpFloat radius)
+{
+       cpShapeInit((cpShape *)poly, &polyClass, body, cpPolyShapeMassInfo(0.0f, count, verts, radius));
+       
+       SetVerts(poly, count, verts);
+       poly->r = radius;
+
+       return poly;
+}
+
+cpShape *
+cpPolyShapeNew(cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius)
+{
+       return (cpShape *)cpPolyShapeInit(cpPolyShapeAlloc(), body, count, verts, transform, radius);
+}
+
+cpShape *
+cpPolyShapeNewRaw(cpBody *body, int count, const cpVect *verts, cpFloat radius)
+{
+       return (cpShape *)cpPolyShapeInitRaw(cpPolyShapeAlloc(), body, count, verts, radius);
+}
+
+cpPolyShape *
+cpBoxShapeInit(cpPolyShape *poly, cpBody *body, cpFloat width, cpFloat height, cpFloat radius)
+{
+       cpFloat hw = width/2.0f;
+       cpFloat hh = height/2.0f;
+       
+       return cpBoxShapeInit2(poly, body, cpBBNew(-hw, -hh, hw, hh), radius);
+}
+
+cpPolyShape *
+cpBoxShapeInit2(cpPolyShape *poly, cpBody *body, cpBB box, cpFloat radius)
+{
+       cpVect verts[] = {
+               cpv(box.r, box.b),
+               cpv(box.r, box.t),
+               cpv(box.l, box.t),
+               cpv(box.l, box.b),
+       };
+       
+       return cpPolyShapeInitRaw(poly, body, 4, verts, radius);
+}
+
+cpShape *
+cpBoxShapeNew(cpBody *body, cpFloat width, cpFloat height, cpFloat radius)
+{
+       return (cpShape *)cpBoxShapeInit(cpPolyShapeAlloc(), body, width, height, radius);
+}
+
+cpShape *
+cpBoxShapeNew2(cpBody *body, cpBB box, cpFloat radius)
+{
+       return (cpShape *)cpBoxShapeInit2(cpPolyShapeAlloc(), body, box, radius);
+}
+
+int
+cpPolyShapeGetCount(const cpShape *shape)
+{
+       cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape.");
+       return ((cpPolyShape *)shape)->count;
+}
+
+cpVect
+cpPolyShapeGetVert(const cpShape *shape, int i)
+{
+       cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape.");
+       
+       int count = cpPolyShapeGetCount(shape);
+       cpAssertHard(0 <= i && i < count, "Index out of range.");
+       
+       return ((cpPolyShape *)shape)->planes[i + count].v0;
+}
+
+cpFloat
+cpPolyShapeGetRadius(const cpShape *shape)
+{
+       cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape.");
+       return ((cpPolyShape *)shape)->r;
+}
+
+// Unsafe API (chipmunk_unsafe.h)
+
+void
+cpPolyShapeSetVerts(cpShape *shape, int count, cpVect *verts, cpTransform transform)
+{
+       cpVect *hullVerts = (cpVect *)alloca(count*sizeof(cpVect));
+       
+       // Transform the verts before building the hull in case of a negative scale.
+       for(int i=0; i<count; i++) hullVerts[i] = cpTransformPoint(transform, verts[i]);
+       
+       unsigned int hullCount = cpConvexHull(count, hullVerts, hullVerts, NULL, 0.0);
+       cpPolyShapeSetVertsRaw(shape, hullCount, hullVerts);
+}
+
+void
+cpPolyShapeSetVertsRaw(cpShape *shape, int count, cpVect *verts)
+{
+       cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape.");
+       cpPolyShape *poly = (cpPolyShape *)shape;
+       cpPolyShapeDestroy(poly);
+       
+       SetVerts(poly, count, verts);
+       
+       cpFloat mass = shape->massInfo.m;
+       shape->massInfo = cpPolyShapeMassInfo(shape->massInfo.m, count, verts, poly->r);
+       if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
+
+void
+cpPolyShapeSetRadius(cpShape *shape, cpFloat radius)
+{
+       cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape.");
+       cpPolyShape *poly = (cpPolyShape *)shape;
+       poly->r = radius;
+       
+       
+       // TODO radius is not handled by moment/area
+//     cpFloat mass = shape->massInfo.m;
+//     shape->massInfo = cpPolyShapeMassInfo(shape->massInfo.m, poly->count, poly->verts, poly->r);
+//     if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpPolyline.c b/dali-physics/third-party/chipmunk2d/src/cpPolyline.c
new file mode 100644 (file)
index 0000000..5b37534
--- /dev/null
@@ -0,0 +1,652 @@
+// Copyright 2013 Howling Moon Software. All rights reserved.
+// See http://chipmunk2d.net/legal.php for more information.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "chipmunk/chipmunk_private.h"
+#include "chipmunk/cpPolyline.h"
+
+
+static inline int Next(int i, int count){return (i+1)%count;}
+
+//MARK: Polylines
+
+#define DEFAULT_POLYLINE_CAPACITY 16
+
+static int
+cpPolylineSizeForCapacity(int capacity)
+{
+       return sizeof(cpPolyline) + capacity*sizeof(cpVect);
+}
+
+static cpPolyline *
+cpPolylineMake(int capacity)
+{
+       capacity = (capacity > DEFAULT_POLYLINE_CAPACITY ? capacity : DEFAULT_POLYLINE_CAPACITY);
+       
+       cpPolyline *line = (cpPolyline *)cpcalloc(1, cpPolylineSizeForCapacity(capacity));
+       line->count = 0;
+       line->capacity = capacity;
+       
+       return line;
+}
+
+static cpPolyline *
+cpPolylineMake2(int capacity, cpVect a, cpVect b)
+{
+       cpPolyline *line = cpPolylineMake(capacity);
+       line->count = 2;
+       line->verts[0] = a;
+       line->verts[1] = b;
+       
+       return line;
+}
+
+static cpPolyline *
+cpPolylineShrink(cpPolyline *line)
+{
+       line->capacity = line->count;
+       return (cpPolyline*) cprealloc(line, cpPolylineSizeForCapacity(line->count));
+}
+
+void
+cpPolylineFree(cpPolyline *line)
+{
+       cpfree(line);
+}
+
+// Grow the allocated memory for a polyline.
+static cpPolyline *
+cpPolylineGrow(cpPolyline *line, int count)
+{
+  line->count += count;
+  
+  int capacity = line->capacity;
+  while(line->count > capacity) capacity *= 2;
+  
+  if(line->capacity < capacity){
+    line->capacity = capacity;
+               line = (cpPolyline*) cprealloc(line, cpPolylineSizeForCapacity(capacity));
+  }
+       
+       return line;
+}
+
+// Push v onto the end of line.
+static cpPolyline *
+cpPolylinePush(cpPolyline *line, cpVect v)
+{
+  int count = line->count;
+  line = cpPolylineGrow(line, 1);
+  line->verts[count] = v;
+       
+       return line;
+}
+
+// Push v onto the beginning of line.
+static cpPolyline *
+cpPolylineEnqueue(cpPolyline *line, cpVect v)
+{
+       // TODO could optimize this to grow in both directions.
+       // Probably doesn't matter though.
+  int count = line->count;
+  line = cpPolylineGrow(line, 1);
+  memmove(line->verts + 1, line->verts, count*sizeof(cpVect));
+  line->verts[0] = v;
+       
+       return line;
+}
+
+// Returns true if the polyline starts and ends with the same vertex.
+cpBool
+cpPolylineIsClosed(cpPolyline *line)
+{
+       return (line->count > 1 && cpveql(line->verts[0], line->verts[line->count-1]));
+}
+
+// Check if a cpPolyline is longer than a certain length
+// Takes a range which can wrap around if the polyline is looped.
+static cpBool
+cpPolylineIsShort(cpVect *points, int count, int start, int end, cpFloat min)
+{
+  cpFloat length = 0.0f;
+       for(int i=start; i!=end; i=Next(i, count)){
+               length += cpvdist(points[i], points[Next(i, count)]);
+               if(length > min) return cpFalse;
+       }
+  
+  return cpTrue;
+}
+
+//MARK: Polyline Simplification
+
+static inline cpFloat
+Sharpness(cpVect a, cpVect b, cpVect c)
+{
+       // TODO could speed this up by caching the normals instead of calculating each twice.
+  return cpvdot(cpvnormalize(cpvsub(a, b)), cpvnormalize(cpvsub(c, b)));
+}
+
+// Join similar adjacent line segments together. Works well for hard edged shapes.
+// 'tol' is the minimum anglular difference in radians of a vertex.
+cpPolyline *
+cpPolylineSimplifyVertexes(cpPolyline *line, cpFloat tol)
+{
+       cpPolyline *reduced = cpPolylineMake2(0, line->verts[0], line->verts[1]);
+       
+       cpFloat minSharp = -cpfcos(tol);
+       
+       for(int i=2; i<line->count; i++){
+               cpVect vert = line->verts[i];
+               cpFloat sharp = Sharpness(reduced->verts[reduced->count - 2], reduced->verts[reduced->count - 1], vert);
+               
+               if(sharp <= minSharp){
+                       reduced->verts[reduced->count - 1] = vert;
+               } else {
+                       reduced = cpPolylinePush(reduced, vert);
+               }
+       }
+       
+       if(
+               cpPolylineIsClosed(line) &&
+               Sharpness(reduced->verts[reduced->count - 2], reduced->verts[0], reduced->verts[1]) < minSharp
+       ){
+               reduced->verts[0] = reduced->verts[reduced->count - 2];
+               reduced->count--;
+       }
+       
+       // TODO shrink
+       return reduced;
+}
+
+// Recursive function used by cpPolylineSimplifyCurves().
+static cpPolyline *
+DouglasPeucker(
+       cpVect *verts, cpPolyline *reduced,
+       int length, int start, int end,
+       cpFloat min, cpFloat tol
+){
+       // Early exit if the points are adjacent
+  if((end - start + length)%length < 2) return reduced;
+  
+       cpVect a = verts[start];
+       cpVect b = verts[end];
+       
+       // Check if the length is below the threshold
+       if(cpvnear(a, b, min) && cpPolylineIsShort(verts, length, start, end, min)) return reduced;
+       
+       // Find the maximal vertex to split and recurse on
+       cpFloat max = 0.0;
+       int maxi = start;
+       
+       cpVect n = cpvnormalize(cpvperp(cpvsub(b, a)));
+       cpFloat d = cpvdot(n, a);
+       
+       for(int i=Next(start, length); i!=end; i=Next(i, length)){
+               cpFloat dist = fabs(cpvdot(n, verts[i]) - d);
+               
+               if(dist > max){
+                       max = dist;
+                       maxi = i;
+               }
+       }
+       
+       if(max > tol){
+    reduced = DouglasPeucker(verts, reduced, length, start, maxi, min, tol);
+               reduced = cpPolylinePush(reduced, verts[maxi]);
+    reduced = DouglasPeucker(verts, reduced, length, maxi, end, min, tol);
+       }
+       
+       return reduced;
+}
+
+// Recursively reduce the vertex count on a polyline. Works best for smooth shapes.
+// 'tol' is the maximum error for the reduction.
+// The reduced polyline will never be farther than this distance from the original polyline.
+cpPolyline *
+cpPolylineSimplifyCurves(cpPolyline *line, cpFloat tol)
+{
+       cpPolyline *reduced = cpPolylineMake(line->count);
+       
+       cpFloat min = tol/2.0f;
+  
+  if(cpPolylineIsClosed(line)){
+               int start, end;
+    cpLoopIndexes(line->verts, line->count - 1, &start, &end);
+    
+               reduced = cpPolylinePush(reduced, line->verts[start]);
+               reduced = DouglasPeucker(line->verts, reduced, line->count - 1, start, end, min, tol);
+               reduced = cpPolylinePush(reduced, line->verts[end]);
+               reduced = DouglasPeucker(line->verts, reduced, line->count - 1, end, start, min, tol);
+               reduced = cpPolylinePush(reduced, line->verts[start]);
+  } else {
+               reduced = cpPolylinePush(reduced, line->verts[0]);
+               reduced = DouglasPeucker(line->verts, reduced, line->count, 0, line->count - 1, min, tol);
+               reduced = cpPolylinePush(reduced, line->verts[line->count - 1]);
+  }
+       
+       return cpPolylineShrink(reduced);
+}
+
+//MARK: Polyline Sets
+
+cpPolylineSet *
+cpPolylineSetAlloc(void)
+{
+       return (cpPolylineSet *)cpcalloc(1, sizeof(cpPolylineSet));
+}
+
+cpPolylineSet *
+cpPolylineSetInit(cpPolylineSet *set)
+{
+       set->count = 0;
+       set->capacity = 8;
+       set->lines = (cpPolyline**) cpcalloc(set->capacity, sizeof(cpPolyline));
+       
+  return set;
+}
+
+
+cpPolylineSet *
+cpPolylineSetNew(void)
+{
+       return cpPolylineSetInit(cpPolylineSetAlloc());
+}
+
+void
+cpPolylineSetDestroy(cpPolylineSet *set, cpBool freePolylines)
+{
+       if(freePolylines){
+               for(int i=0; i<set->count; i++){
+                       cpPolylineFree(set->lines[i]);
+               }
+       }
+       
+       cpfree(set->lines);
+}
+
+
+void
+cpPolylineSetFree(cpPolylineSet *set, cpBool freePolylines)
+{
+       if(set){
+               cpPolylineSetDestroy(set, freePolylines);
+               cpfree(set);
+       }
+}
+
+// Find the polyline that ends with v.
+static int
+cpPolylineSetFindEnds(cpPolylineSet *set, cpVect v){
+       int count = set->count;
+       cpPolyline **lines = set->lines;
+       
+  for(int i=0; i<count; i++){
+               cpPolyline *line = lines[i];
+    if(cpveql(line->verts[line->count - 1], v)) return i;
+  }
+  
+  return -1;
+}
+
+// Find the polyline that starts with v.
+static int
+cpPolylineSetFindStarts(cpPolylineSet *set, cpVect v){
+       int count = set->count;
+       cpPolyline **lines = set->lines;
+       
+  for(int i=0; i<count; i++){
+    if(cpveql(lines[i]->verts[0], v)) return i;
+  }
+  
+  return -1;
+}
+
+// Add a new polyline to a polyline set.
+static void
+cpPolylineSetPush(cpPolylineSet *set, cpPolyline *line)
+{
+  // grow set
+  set->count++;
+  if(set->count > set->capacity){
+    set->capacity *= 2;
+    set->lines = (cpPolyline**) cprealloc(set->lines, set->capacity*sizeof(cpPolyline));
+  }
+  
+       set->lines[set->count - 1] = line;
+}
+
+// Add a new polyline to a polyline set.
+static void
+cpPolylineSetAdd(cpPolylineSet *set, cpVect v0, cpVect v1)
+{
+       cpPolylineSetPush(set, cpPolylineMake2(DEFAULT_POLYLINE_CAPACITY, v0, v1));
+}
+
+// Join two cpPolylines in a polyline set together.
+static void
+cpPolylineSetJoin(cpPolylineSet *set, int before, int after)
+{
+  cpPolyline *lbefore = set->lines[before];
+  cpPolyline *lafter = set->lines[after];
+  
+  // append
+  int count = lbefore->count;
+  lbefore = cpPolylineGrow(lbefore, lafter->count);
+  memmove(lbefore->verts + count, lafter->verts, lafter->count*sizeof(cpVect));
+       set->lines[before] = lbefore;
+  
+  // delete lafter
+  set->count--;
+       cpPolylineFree(set->lines[after]);
+  set->lines[after] = set->lines[set->count];
+}
+
+// Add a segment to a polyline set.
+// A segment will either start a new polyline, join two others, or add to or loop an existing polyline.
+void
+cpPolylineSetCollectSegment(cpVect v0, cpVect v1, cpPolylineSet *lines)
+{
+  int before = cpPolylineSetFindEnds(lines, v0);
+  int after = cpPolylineSetFindStarts(lines, v1);
+  
+  if(before >= 0 && after >= 0){
+    if(before == after){
+      // loop by pushing v1 onto before
+      lines->lines[before] = cpPolylinePush(lines->lines[before], v1);
+    } else {
+      // join before and after
+      cpPolylineSetJoin(lines, before, after);
+    }
+  } else if(before >= 0){
+    // push v1 onto before
+    lines->lines[before] = cpPolylinePush(lines->lines[before], v1);
+  } else if(after >= 0){
+    // enqueue v0 onto after
+    lines->lines[after] = cpPolylineEnqueue(lines->lines[after], v0);
+  } else {
+    // create new line from v0 and v1
+    cpPolylineSetAdd(lines, v0, v1);
+  }
+}
+
+//MARK: Convex Hull Functions
+
+cpPolyline *
+cpPolylineToConvexHull(cpPolyline *line, cpFloat tol)
+{
+       cpPolyline *hull = cpPolylineMake(line->count + 1);
+       hull->count = cpConvexHull(line->count, line->verts, hull->verts, NULL, tol);
+       hull = cpPolylinePush(hull, hull->verts[0]);
+       
+       return cpPolylineShrink(hull);
+}
+
+//MARK: Approximate Concave Decompostition
+
+struct Notch {
+       int i;
+       cpFloat d;
+       cpVect v;
+       cpVect n;
+};
+
+static cpFloat
+FindSteiner(int count, cpVect *verts, struct Notch notch)
+{
+       cpFloat min = INFINITY;
+       cpFloat feature = -1.0;
+       
+       for(int i=1; i<count-1; i++){
+               int index = (notch.i + i)%count;
+               
+               cpVect seg_a = verts[index];
+               cpVect seg_b = verts[Next(index, count)];
+               
+               cpFloat thing_a = cpvcross(notch.n, cpvsub(seg_a, notch.v));
+               cpFloat thing_b = cpvcross(notch.n, cpvsub(seg_b, notch.v));
+               if(thing_a*thing_b <= 0.0){
+                       cpFloat t = thing_a/(thing_a - thing_b);
+                       cpFloat dist = cpvdot(notch.n, cpvsub(cpvlerp(seg_a, seg_b, t), notch.v));
+                       
+                       if(dist >= 0.0 && dist <= min){
+                               min = dist;
+                               feature = index + t;
+                       }
+               }
+       }
+       
+       return feature;
+}
+
+//static cpFloat
+//FindSteiner2(cpVect *verts, int count, struct Notch notch)
+//{
+//     cpVect a = verts[(notch.i + count - 1)%count];
+//     cpVect b = verts[(notch.i + 1)%count];
+//     cpVect n = cpvnormalize(cpvadd(cpvnormalize(cpvsub(notch.v, a)), cpvnormalize(cpvsub(notch.v, b))));
+//     
+//     cpFloat min = INFINITY;
+//     cpFloat feature = -1.0;
+//     
+//     for(int i=1; i<count-1; i++){
+//             int index = (notch.i + i)%count;
+//             
+//             cpVect seg_a = verts[index];
+//             cpVect seg_b = verts[Next(index, count)];
+//             
+//             cpFloat thing_a = cpvcross(n, cpvsub(seg_a, notch.v));
+//             cpFloat thing_b = cpvcross(n, cpvsub(seg_b, notch.v));
+//             if(thing_a*thing_b <= 0.0){
+//                     cpFloat t = thing_a/(thing_a - thing_b);
+//                     cpFloat dist = cpvdot(n, cpvsub(cpvlerp(seg_a, seg_b, t), notch.v));
+//                     
+//                     if(dist >= 0.0 && dist <= min){
+//                             min = dist;
+//                             feature = index + t;
+//                     }
+//             }
+//     }
+//     
+//     cpAssertSoft(feature >= 0.0, "No closest features detected. This is likely due to a self intersecting polygon.");
+//     return feature;
+//}
+
+//struct Range {cpFloat min, max;};
+//static inline struct Range
+//clip_range(cpVect delta_a, cpVect delta_b, cpVect clip)
+//{
+//     cpFloat da = cpvcross(delta_a, clip);
+//     cpFloat db = cpvcross(delta_b, clip);
+//     cpFloat clamp = da/(da - db);
+//     if(da > db){
+//             return (struct Range){-INFINITY, clamp};
+//     } else if(da < db){
+//             return (struct Range){clamp, INFINITY};
+//     } else {
+//             return (struct Range){-INFINITY, INFINITY};
+//     }
+//}
+//
+//static cpFloat
+//FindSteiner3(cpVect *verts, int count, struct Notch notch)
+//{
+//     cpFloat min = INFINITY;
+//     cpFloat feature = -1.0;
+//     
+//     cpVect support_a = verts[(notch.i - 1 + count)%count];
+//     cpVect support_b = verts[(notch.i + 1)%count];
+//     
+//     cpVect clip_a = cpvlerp(support_a, support_b, 0.1);
+//     cpVect clip_b = cpvlerp(support_b, support_b, 0.9);
+//     
+//     for(int i=1; i<count - 1; i++){
+//             int index = (notch.i + i)%count;
+//             cpVect seg_a = verts[index];
+//             cpVect seg_b = verts[Next(index, count)];
+//             
+//             cpVect delta_a = cpvsub(seg_a, notch.v);
+//             cpVect delta_b = cpvsub(seg_b, notch.v);
+//             
+//             // Ignore if the segment faces away from the point.
+//             if(cpvcross(delta_b, delta_a) > 0.0){
+//                     struct Range range1 = clip_range(delta_a, delta_b, cpvsub(notch.v, clip_a));
+//                     struct Range range2 = clip_range(delta_a, delta_b, cpvsub(clip_b, notch.v));
+//                     
+//                     cpFloat min_t = cpfmax(0.0, cpfmax(range1.min, range2.min));
+//                     cpFloat max_t = cpfmin(1.0, cpfmin(range1.max, range2.max));
+//                     
+//                     // Ignore if the segment has been completely clipped away.
+//                     if(min_t < max_t){
+//                             cpVect seg_delta = cpvsub(seg_b, seg_a);
+//                             cpFloat closest_t = cpfclamp(cpvdot(seg_delta, cpvsub(notch.v, seg_a))/cpvlengthsq(seg_delta), min_t, max_t);
+//                             cpVect closest = cpvlerp(seg_a, seg_b, closest_t);
+//                             
+//                             cpFloat dist = cpvdistsq(notch.v, closest);
+//                             if(dist < min){
+//                                     min = dist;
+//                                     feature = index + closest_t;
+//                             }
+//                     }
+//             }
+//     }
+//     
+//     cpAssertWarn(feature >= 0.0, "Internal Error: No closest features detected.");
+//     return feature;
+//}
+
+//static cpBool
+//VertexUnobscured(int count, cpVect *verts, int index, int notch_i)
+//{
+//     cpVect v = verts[notch_i];
+//     cpVect n = cpvnormalize(cpvsub(verts[index], v));
+//     
+//     for(int i=0; i<count; i++){
+//             if(i == index || i == Next(i, count) || i == notch_i || i == Next(notch_i, count)) continue;
+//             
+//             cpVect seg_a = verts[i];
+//             cpVect seg_b = verts[Next(i, count)];
+//             
+//             cpFloat thing_a = cpvcross(n, cpvsub(seg_a, v));
+//             cpFloat thing_b = cpvcross(n, cpvsub(seg_b, v));
+//             if(thing_a*thing_b <= 0.0) return cpTrue;
+//     }
+//     
+//     return cpFalse;
+//}
+//
+//static cpFloat
+//FindSteiner4(int count, cpVect *verts, struct Notch notch, cpFloat *convexity)
+//{
+//     cpFloat min = INFINITY;
+//     cpFloat feature = -1.0;
+//     
+//     for(int i=Next(notch.b, count); i!=notch.a; i=Next(i, count)){
+//             cpVect v = verts[i];
+//             cpFloat weight = (1.0 + 0.1*convexity[i])/(1.0*cpvdist(notch.v, v));
+//             
+//             if(weight <= min && VertexUnobscured(count, verts, i, notch.i)){
+//                     min = weight;
+//                     feature = i;
+//             }
+//     }
+//     
+//     cpAssertSoft(feature >= 0.0, "No closest features detected. This is likely due to a self intersecting polygon.");
+//     return feature;
+//}
+
+static struct Notch
+DeepestNotch(int count, cpVect *verts, int hullCount, cpVect *hullVerts, int first, cpFloat tol)
+{
+       struct Notch notch = {};
+       int j = Next(first, count);
+       
+       for(int i=0; i<hullCount; i++){
+               cpVect a = hullVerts[i];
+               cpVect b = hullVerts[Next(i, hullCount)];
+               
+               // TODO use a cross check instead?
+               cpVect n = cpvnormalize(cpvrperp(cpvsub(a, b)));
+               cpFloat d = cpvdot(n, a);
+               
+               cpVect v = verts[j];
+               while(!cpveql(v, b)){
+                       cpFloat depth = cpvdot(n, v) - d;
+                       
+                       if(depth > notch.d){
+                               notch.d = depth;
+                               notch.i = j;
+                               notch.v = v;
+                               notch.n = n;
+                       }
+                       
+                       j = Next(j, count);
+                       v = verts[j];
+               }
+               
+               j = Next(j, count);
+       }
+       
+       return notch;
+}
+
+static inline int IMAX(int a, int b){return (a > b ? a : b);}
+
+static void
+ApproximateConcaveDecomposition(cpVect *verts, int count, cpFloat tol, cpPolylineSet *set)
+{
+       int first;
+       cpVect *hullVerts = (cpVect*) alloca(count*sizeof(cpVect));
+       int hullCount = cpConvexHull(count, verts, hullVerts, &first, 0.0);
+       
+       if(hullCount != count){
+               struct Notch notch = DeepestNotch(count, verts, hullCount, hullVerts, first, tol);
+               
+               if(notch.d > tol){
+                       cpFloat steiner_it = FindSteiner(count, verts, notch);
+                       
+                       if(steiner_it >= 0.0){
+                               int steiner_i = (int)steiner_it;
+                               cpVect steiner = cpvlerp(verts[steiner_i], verts[Next(steiner_i, count)], steiner_it - steiner_i);
+                               
+                               // Vertex counts NOT including the steiner point.
+                               int sub1_count = (steiner_i - notch.i + count)%count + 1;
+                               int sub2_count = count - (steiner_i - notch.i + count)%count;
+                               cpVect *scratch = (cpVect*) alloca((IMAX(sub1_count, sub2_count) + 1)*sizeof(cpVect));
+                               
+                               for(int i=0; i<sub1_count; i++) scratch[i] = verts[(notch.i + i)%count];
+                               scratch[sub1_count] = steiner;
+                               ApproximateConcaveDecomposition(scratch, sub1_count + 1, tol, set);
+                               
+                               for(int i=0; i<sub2_count; i++) scratch[i] = verts[(steiner_i + 1 + i)%count];
+                               scratch[sub2_count] = steiner;
+                               ApproximateConcaveDecomposition(scratch, sub2_count + 1, tol, set);
+                               
+                               return;
+                       }
+               }
+       }
+       
+       cpPolyline *hull = cpPolylineMake(hullCount + 1);
+       
+       memcpy(hull->verts, hullVerts, hullCount*sizeof(cpVect));
+       hull->verts[hullCount] = hullVerts[0];
+       hull->count = hullCount + 1;
+       
+       cpPolylineSetPush(set, hull);
+}
+
+cpPolylineSet *
+cpPolylineConvexDecomposition_BETA(cpPolyline *line, cpFloat tol)
+{
+       cpAssertSoft(cpPolylineIsClosed(line), "Cannot decompose an open polygon.");
+       cpAssertSoft(cpAreaForPoly(line->count, line->verts, 0.0) >= 0.0, "Winding is backwards. (Are you passing a hole?)");
+       
+       cpPolylineSet *set = cpPolylineSetNew();
+       ApproximateConcaveDecomposition(line->verts, line->count - 1, tol, set);
+       
+       return set;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpRatchetJoint.c b/dali-physics/third-party/chipmunk2d/src/cpRatchetJoint.c
new file mode 100644 (file)
index 0000000..b3c9687
--- /dev/null
@@ -0,0 +1,179 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpRatchetJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpFloat angle = joint->angle;
+       cpFloat phase = joint->phase;
+       cpFloat ratchet = joint->ratchet;
+       
+       cpFloat delta = b->a - a->a;
+       cpFloat diff = angle - delta;
+       cpFloat pdist = 0.0f;
+       
+       if(diff*ratchet > 0.0f){
+               pdist = diff;
+       } else {
+               joint->angle = cpffloor((delta - phase)/ratchet)*ratchet + phase;
+       }
+       
+       // calculate moment of inertia coefficient.
+       joint->iSum = 1.0f/(a->i_inv + b->i_inv);
+       
+       // calculate bias velocity
+       cpFloat maxBias = joint->constraint.maxBias;
+       joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias);
+
+       // If the bias is 0, the joint is not at a limit. Reset the impulse.
+       if(!joint->bias) joint->jAcc = 0.0f;
+}
+
+static void
+applyCachedImpulse(cpRatchetJoint *joint, cpFloat dt_coef)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpFloat j = joint->jAcc*dt_coef;
+       a->w -= j*a->i_inv;
+       b->w += j*b->i_inv;
+}
+
+static void
+applyImpulse(cpRatchetJoint *joint, cpFloat dt)
+{
+       if(!joint->bias) return; // early exit
+
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       // compute relative rotational velocity
+       cpFloat wr = b->w - a->w;
+       cpFloat ratchet = joint->ratchet;
+       
+       cpFloat jMax = joint->constraint.maxForce*dt;
+       
+       // compute normal impulse       
+       cpFloat j = -(joint->bias + wr)*joint->iSum;
+       cpFloat jOld = joint->jAcc;
+       joint->jAcc = cpfclamp((jOld + j)*ratchet, 0.0f, jMax*cpfabs(ratchet))/ratchet;
+       j = joint->jAcc - jOld;
+       
+       // apply impulse
+       a->w -= j*a->i_inv;
+       b->w += j*b->i_inv;
+}
+
+static cpFloat
+getImpulse(cpRatchetJoint *joint)
+{
+       return cpfabs(joint->jAcc);
+}
+
+static const cpConstraintClass klass = {
+       (cpConstraintPreStepImpl)preStep,
+       (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+       (cpConstraintApplyImpulseImpl)applyImpulse,
+       (cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpRatchetJoint *
+cpRatchetJointAlloc(void)
+{
+       return (cpRatchetJoint *)cpcalloc(1, sizeof(cpRatchetJoint));
+}
+
+cpRatchetJoint *
+cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet)
+{
+       cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+       
+       joint->angle = 0.0f;
+       joint->phase = phase;
+       joint->ratchet = ratchet;
+       
+       // STATIC_BODY_CHECK
+       joint->angle = (b ? b->a : 0.0f) - (a ? a->a : 0.0f);
+       
+       return joint;
+}
+
+cpConstraint *
+cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet)
+{
+       return (cpConstraint *)cpRatchetJointInit(cpRatchetJointAlloc(), a, b, phase, ratchet);
+}
+
+cpBool
+cpConstraintIsRatchetJoint(const cpConstraint *constraint)
+{
+       return (constraint->klass == &klass);
+}
+
+cpFloat
+cpRatchetJointGetAngle(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+       return ((cpRatchetJoint *)constraint)->angle;
+}
+
+void
+cpRatchetJointSetAngle(cpConstraint *constraint, cpFloat angle)
+{
+       cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpRatchetJoint *)constraint)->angle = angle;
+}
+
+cpFloat
+cpRatchetJointGetPhase(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+       return ((cpRatchetJoint *)constraint)->phase;
+}
+
+void
+cpRatchetJointSetPhase(cpConstraint *constraint, cpFloat phase)
+{
+       cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpRatchetJoint *)constraint)->phase = phase;
+}
+cpFloat
+cpRatchetJointGetRatchet(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+       return ((cpRatchetJoint *)constraint)->ratchet;
+}
+
+void
+cpRatchetJointSetRatchet(cpConstraint *constraint, cpFloat ratchet)
+{
+       cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpRatchetJoint *)constraint)->ratchet = ratchet;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpRobust.c b/dali-physics/third-party/chipmunk2d/src/cpRobust.c
new file mode 100644 (file)
index 0000000..57507d1
--- /dev/null
@@ -0,0 +1,13 @@
+#include "chipmunk/cpRobust.h"
+
+
+cpBool
+cpCheckPointGreater(const cpVect a, const cpVect b, const cpVect c)
+{
+       return (b.y - a.y)*(a.x + b.x - 2*c.x) > (b.x - a.x)*(a.y + b.y - 2*c.y);
+}
+
+cpBool
+cpCheckAxis(cpVect v0, cpVect v1, cpVect p, cpVect n){
+       return cpvdot(p, n) <= cpfmax(cpvdot(v0, n), cpvdot(v1, n));
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpRotaryLimitJoint.c b/dali-physics/third-party/chipmunk2d/src/cpRotaryLimitJoint.c
new file mode 100644 (file)
index 0000000..548adbe
--- /dev/null
@@ -0,0 +1,160 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpRotaryLimitJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpFloat dist = b->a - a->a;
+       cpFloat pdist = 0.0f;
+       if(dist > joint->max) {
+               pdist = joint->max - dist;
+       } else if(dist < joint->min) {
+               pdist = joint->min - dist;
+       }
+       
+       // calculate moment of inertia coefficient.
+       joint->iSum = 1.0f/(a->i_inv + b->i_inv);
+       
+       // calculate bias velocity
+       cpFloat maxBias = joint->constraint.maxBias;
+       joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias);
+
+       // If the bias is 0, the joint is not at a limit. Reset the impulse.
+       if(!joint->bias) joint->jAcc = 0.0f;
+}
+
+static void
+applyCachedImpulse(cpRotaryLimitJoint *joint, cpFloat dt_coef)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpFloat j = joint->jAcc*dt_coef;
+       a->w -= j*a->i_inv;
+       b->w += j*b->i_inv;
+}
+
+static void
+applyImpulse(cpRotaryLimitJoint *joint, cpFloat dt)
+{
+       if(!joint->bias) return; // early exit
+
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       // compute relative rotational velocity
+       cpFloat wr = b->w - a->w;
+       
+       cpFloat jMax = joint->constraint.maxForce*dt;
+       
+       // compute normal impulse       
+       cpFloat j = -(joint->bias + wr)*joint->iSum;
+       cpFloat jOld = joint->jAcc;
+       if(joint->bias < 0.0f){
+               joint->jAcc = cpfclamp(jOld + j, 0.0f, jMax);
+       } else {
+               joint->jAcc = cpfclamp(jOld + j, -jMax, 0.0f);
+       }
+       j = joint->jAcc - jOld;
+       
+       // apply impulse
+       a->w -= j*a->i_inv;
+       b->w += j*b->i_inv;
+}
+
+static cpFloat
+getImpulse(cpRotaryLimitJoint *joint)
+{
+       return cpfabs(joint->jAcc);
+}
+
+static const cpConstraintClass klass = {
+       (cpConstraintPreStepImpl)preStep,
+       (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+       (cpConstraintApplyImpulseImpl)applyImpulse,
+       (cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpRotaryLimitJoint *
+cpRotaryLimitJointAlloc(void)
+{
+       return (cpRotaryLimitJoint *)cpcalloc(1, sizeof(cpRotaryLimitJoint));
+}
+
+cpRotaryLimitJoint *
+cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max)
+{
+       cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+       
+       joint->min = min;
+       joint->max  = max;
+       
+       joint->jAcc = 0.0f;
+       
+       return joint;
+}
+
+cpConstraint *
+cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max)
+{
+       return (cpConstraint *)cpRotaryLimitJointInit(cpRotaryLimitJointAlloc(), a, b, min, max);
+}
+
+cpBool
+cpConstraintIsRotaryLimitJoint(const cpConstraint *constraint)
+{
+       return (constraint->klass == &klass);
+}
+
+cpFloat
+cpRotaryLimitJointGetMin(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint.");
+       return ((cpRotaryLimitJoint *)constraint)->min;
+}
+
+void
+cpRotaryLimitJointSetMin(cpConstraint *constraint, cpFloat min)
+{
+       cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpRotaryLimitJoint *)constraint)->min = min;
+}
+
+cpFloat
+cpRotaryLimitJointGetMax(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint.");
+       return ((cpRotaryLimitJoint *)constraint)->max;
+}
+
+void
+cpRotaryLimitJointSetMax(cpConstraint *constraint, cpFloat max)
+{
+       cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpRotaryLimitJoint *)constraint)->max = max;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpShape.c b/dali-physics/third-party/chipmunk2d/src/cpShape.c
new file mode 100644 (file)
index 0000000..513b535
--- /dev/null
@@ -0,0 +1,604 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+#include "chipmunk/chipmunk_unsafe.h"
+
+#define CP_DefineShapeGetter(struct, type, member, name) \
+CP_DeclareShapeGetter(struct, type, name){ \
+       cpAssertHard(shape->klass == &struct##Class, "shape is not a "#struct); \
+       return ((struct *)shape)->member; \
+}
+
+cpShape *
+cpShapeInit(cpShape *shape, const cpShapeClass *klass, cpBody *body, struct cpShapeMassInfo massInfo)
+{
+       shape->klass = klass;
+       
+       shape->body = body;
+       shape->massInfo = massInfo;
+       
+       shape->sensor = 0;
+       
+       shape->e = 0.0f;
+       shape->u = 0.0f;
+       shape->surfaceV = cpvzero;
+       
+       shape->type = 0;
+       shape->filter.group = CP_NO_GROUP;
+       shape->filter.categories = CP_ALL_CATEGORIES;
+       shape->filter.mask = CP_ALL_CATEGORIES;
+       
+       shape->userData = NULL;
+       
+       shape->space = NULL;
+       
+       shape->next = NULL;
+       shape->prev = NULL;
+       
+       return shape;
+}
+
+void
+cpShapeDestroy(cpShape *shape)
+{
+       if(shape->klass && shape->klass->destroy) shape->klass->destroy(shape);
+}
+
+void
+cpShapeFree(cpShape *shape)
+{
+       if(shape){
+               cpShapeDestroy(shape);
+               cpfree(shape);
+       }
+}
+
+cpSpace *
+cpShapeGetSpace(const cpShape *shape)
+{
+       return shape->space;
+}
+
+cpBody *
+cpShapeGetBody(const cpShape *shape)
+{
+       return shape->body;
+}
+
+void
+cpShapeSetBody(cpShape *shape, cpBody *body)
+{
+       cpAssertHard(!cpShapeActive(shape), "You cannot change the body on an active shape. You must remove the shape from the space before changing the body.");
+       shape->body = body;
+}
+
+cpFloat cpShapeGetMass(cpShape *shape){ return shape->massInfo.m; }
+
+void
+cpShapeSetMass(cpShape *shape, cpFloat mass){
+       cpBody *body = shape->body;
+       cpBodyActivate(body);
+       
+       shape->massInfo.m = mass;
+       cpBodyAccumulateMassFromShapes(body);
+}
+
+cpFloat cpShapeGetDensity(cpShape *shape){ return shape->massInfo.m/shape->massInfo.area; }
+void cpShapeSetDensity(cpShape *shape, cpFloat density){ cpShapeSetMass(shape, density*shape->massInfo.area); }
+
+cpFloat cpShapeGetMoment(cpShape *shape){ return shape->massInfo.m*shape->massInfo.i; }
+cpFloat cpShapeGetArea(cpShape *shape){ return shape->massInfo.area; }
+cpVect cpShapeGetCenterOfGravity(cpShape *shape) { return shape->massInfo.cog; }
+
+cpBB
+cpShapeGetBB(const cpShape *shape)
+{
+       return shape->bb;
+}
+
+cpBool
+cpShapeGetSensor(const cpShape *shape)
+{
+       return shape->sensor;
+}
+
+void
+cpShapeSetSensor(cpShape *shape, cpBool sensor)
+{
+       cpBodyActivate(shape->body);
+       shape->sensor = sensor;
+}
+
+cpFloat
+cpShapeGetElasticity(const cpShape *shape)
+{
+       return shape->e;
+}
+
+void
+cpShapeSetElasticity(cpShape *shape, cpFloat elasticity)
+{
+       cpAssertHard(elasticity >= 0.0f, "Elasticity must be positive.");
+       cpBodyActivate(shape->body);
+       shape->e = elasticity;
+}
+
+cpFloat
+cpShapeGetFriction(const cpShape *shape)
+{
+       return shape->u;
+}
+
+void
+cpShapeSetFriction(cpShape *shape, cpFloat friction)
+{
+       cpAssertHard(friction >= 0.0f, "Friction must be postive.");
+       cpBodyActivate(shape->body);
+       shape->u = friction;
+}
+
+cpVect
+cpShapeGetSurfaceVelocity(const cpShape *shape)
+{
+       return shape->surfaceV;
+}
+
+void
+cpShapeSetSurfaceVelocity(cpShape *shape, cpVect surfaceVelocity)
+{
+       cpBodyActivate(shape->body);
+       shape->surfaceV = surfaceVelocity;
+}
+
+cpDataPointer
+cpShapeGetUserData(const cpShape *shape)
+{
+       return shape->userData;
+}
+
+void
+cpShapeSetUserData(cpShape *shape, cpDataPointer userData)
+{
+       shape->userData = userData;
+}
+
+cpCollisionType
+cpShapeGetCollisionType(const cpShape *shape)
+{
+       return shape->type;
+}
+
+void
+cpShapeSetCollisionType(cpShape *shape, cpCollisionType collisionType)
+{
+       cpBodyActivate(shape->body);
+       shape->type = collisionType;
+}
+
+cpShapeFilter
+cpShapeGetFilter(const cpShape *shape)
+{
+       return shape->filter;
+}
+
+void
+cpShapeSetFilter(cpShape *shape, cpShapeFilter filter)
+{
+       cpBodyActivate(shape->body);
+       shape->filter = filter;
+}
+
+cpBB
+cpShapeCacheBB(cpShape *shape)
+{
+       return cpShapeUpdate(shape, shape->body->transform);
+}
+
+cpBB
+cpShapeUpdate(cpShape *shape, cpTransform transform)
+{
+       return (shape->bb = shape->klass->cacheData(shape, transform));
+}
+
+cpFloat
+cpShapePointQuery(const cpShape *shape, cpVect p, cpPointQueryInfo *info)
+{
+       cpPointQueryInfo blank = {NULL, cpvzero, INFINITY, cpvzero};
+       if(info){
+               (*info) = blank;
+       } else {
+               info = &blank;
+       }
+       
+       shape->klass->pointQuery(shape, p, info);
+       return info->distance;
+}
+
+
+cpBool
+cpShapeSegmentQuery(const cpShape *shape, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info){
+       cpSegmentQueryInfo blank = {NULL, b, cpvzero, 1.0f};
+       if(info){
+               (*info) = blank;
+       } else {
+               info = &blank;
+       }
+       
+       cpPointQueryInfo nearest;
+       shape->klass->pointQuery(shape, a, &nearest);
+       if(nearest.distance <= radius){
+               info->shape = shape;
+               info->alpha = 0.0;
+               info->normal = cpvnormalize(cpvsub(a, nearest.point));
+       } else {
+               shape->klass->segmentQuery(shape, a, b, radius, info);
+       }
+       
+       return (info->shape != NULL);
+}
+
+cpContactPointSet
+cpShapesCollide(const cpShape *a, const cpShape *b)
+{
+       struct cpContact contacts[CP_MAX_CONTACTS_PER_ARBITER];
+       struct cpCollisionInfo info = cpCollide(a, b, 0, contacts);
+       
+       cpContactPointSet set;
+       set.count = info.count;
+       
+       // cpCollideShapes() may have swapped the contact order. Flip the normal.
+       cpBool swapped = (a != info.a);
+       set.normal = (swapped ? cpvneg(info.n) : info.n);
+       
+       for(int i=0; i<info.count; i++){
+               // cpCollideShapesInfo() returns contacts with absolute positions.
+               cpVect p1 = contacts[i].r1;
+               cpVect p2 = contacts[i].r2;
+               
+               set.points[i].pointA = (swapped ? p2 : p1);
+               set.points[i].pointB = (swapped ? p1 : p2);
+               set.points[i].distance = cpvdot(cpvsub(p2, p1), set.normal);
+       }
+       
+       return set;
+}
+
+cpCircleShape *
+cpCircleShapeAlloc(void)
+{
+       return (cpCircleShape *)cpcalloc(1, sizeof(cpCircleShape));
+}
+
+static cpBB
+cpCircleShapeCacheData(cpCircleShape *circle, cpTransform transform)
+{
+       cpVect c = circle->tc = cpTransformPoint(transform, circle->c);
+       return cpBBNewForCircle(c, circle->r);
+}
+
+static void
+cpCircleShapePointQuery(cpCircleShape *circle, cpVect p, cpPointQueryInfo *info)
+{
+       cpVect delta = cpvsub(p, circle->tc);
+       cpFloat d = cpvlength(delta);
+       cpFloat r = circle->r;
+       
+       info->shape = (cpShape *)circle;
+       cpFloat r_over_d = d > 0.0f ? r/d : r;
+       info->point = cpvadd(circle->tc, cpvmult(delta, r_over_d)); // TODO: div/0
+       info->distance = d - r;
+       
+       // Use up for the gradient if the distance is very small.
+       info->gradient = (d > MAGIC_EPSILON ? cpvmult(delta, 1.0f/d) : cpv(0.0f, 1.0f));
+}
+
+static void
+cpCircleShapeSegmentQuery(cpCircleShape *circle, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info)
+{
+       CircleSegmentQuery((cpShape *)circle, circle->tc, circle->r, a, b, radius, info);
+}
+
+static struct cpShapeMassInfo
+cpCircleShapeMassInfo(cpFloat mass, cpFloat radius, cpVect center)
+{
+       struct cpShapeMassInfo info = {
+               mass, cpMomentForCircle(1.0f, 0.0f, radius, cpvzero),
+               center,
+               cpAreaForCircle(0.0f, radius),
+       };
+       
+       return info;
+}
+
+static const cpShapeClass cpCircleShapeClass = {
+       CP_CIRCLE_SHAPE,
+       (cpShapeCacheDataImpl)cpCircleShapeCacheData,
+       NULL,
+       (cpShapePointQueryImpl)cpCircleShapePointQuery,
+       (cpShapeSegmentQueryImpl)cpCircleShapeSegmentQuery,
+};
+
+cpCircleShape *
+cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset)
+{
+       circle->c = offset;
+       circle->r = radius;
+       
+       cpShapeInit((cpShape *)circle, &cpCircleShapeClass, body, cpCircleShapeMassInfo(0.0f, radius, offset));
+       
+       return circle;
+}
+
+cpShape *
+cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset)
+{
+       return (cpShape *)cpCircleShapeInit(cpCircleShapeAlloc(), body, radius, offset);
+}
+
+cpVect
+cpCircleShapeGetOffset(const cpShape *shape)
+{
+       cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape.");
+       return ((cpCircleShape *)shape)->c;
+}
+
+cpFloat
+cpCircleShapeGetRadius(const cpShape *shape)
+{
+       cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape.");
+       return ((cpCircleShape *)shape)->r;
+}
+
+
+cpSegmentShape *
+cpSegmentShapeAlloc(void)
+{
+       return (cpSegmentShape *)cpcalloc(1, sizeof(cpSegmentShape));
+}
+
+static cpBB
+cpSegmentShapeCacheData(cpSegmentShape *seg, cpTransform transform)
+{
+       seg->ta = cpTransformPoint(transform, seg->a);
+       seg->tb = cpTransformPoint(transform, seg->b);
+       seg->tn = cpTransformVect(transform, seg->n);
+       
+       cpFloat l,r,b,t;
+       
+       if(seg->ta.x < seg->tb.x){
+               l = seg->ta.x;
+               r = seg->tb.x;
+       } else {
+               l = seg->tb.x;
+               r = seg->ta.x;
+       }
+       
+       if(seg->ta.y < seg->tb.y){
+               b = seg->ta.y;
+               t = seg->tb.y;
+       } else {
+               b = seg->tb.y;
+               t = seg->ta.y;
+       }
+       
+       cpFloat rad = seg->r;
+       return cpBBNew(l - rad, b - rad, r + rad, t + rad);
+}
+
+static void
+cpSegmentShapePointQuery(cpSegmentShape *seg, cpVect p, cpPointQueryInfo *info)
+{
+       cpVect closest = cpClosetPointOnSegment(p, seg->ta, seg->tb);
+       
+       cpVect delta = cpvsub(p, closest);
+       cpFloat d = cpvlength(delta);
+       cpFloat r = seg->r;
+       cpVect g = cpvmult(delta, 1.0f/d);
+       
+       info->shape = (cpShape *)seg;
+       info->point = (d ? cpvadd(closest, cpvmult(g, r)) : closest);
+       info->distance = d - r;
+       
+       // Use the segment's normal if the distance is very small.
+       info->gradient = (d > MAGIC_EPSILON ? g : seg->n);
+}
+
+static void
+cpSegmentShapeSegmentQuery(cpSegmentShape *seg, cpVect a, cpVect b, cpFloat r2, cpSegmentQueryInfo *info)
+{
+       cpVect n = seg->tn;
+       cpFloat d = cpvdot(cpvsub(seg->ta, a), n);
+       cpFloat r = seg->r + r2;
+       
+       cpVect flipped_n = (d > 0.0f ? cpvneg(n) : n);
+       cpVect seg_offset = cpvsub(cpvmult(flipped_n, r), a);
+       
+       // Make the endpoints relative to 'a' and move them by the thickness of the segment.
+       cpVect seg_a = cpvadd(seg->ta, seg_offset);
+       cpVect seg_b = cpvadd(seg->tb, seg_offset);
+       cpVect delta = cpvsub(b, a);
+       
+       if(cpvcross(delta, seg_a)*cpvcross(delta, seg_b) <= 0.0f){
+               cpFloat d_offset = d + (d > 0.0f ? -r : r);
+               cpFloat ad = -d_offset;
+               cpFloat bd = cpvdot(delta, n) - d_offset;
+               
+               if(ad*bd < 0.0f){
+                       cpFloat t = ad/(ad - bd);
+                       
+                       info->shape = (cpShape *)seg;
+                       info->point = cpvsub(cpvlerp(a, b, t), cpvmult(flipped_n, r2));
+                       info->normal = flipped_n;
+                       info->alpha = t;
+               }
+       } else if(r != 0.0f){
+               cpSegmentQueryInfo info1 = {NULL, b, cpvzero, 1.0f};
+               cpSegmentQueryInfo info2 = {NULL, b, cpvzero, 1.0f};
+               CircleSegmentQuery((cpShape *)seg, seg->ta, seg->r, a, b, r2, &info1);
+               CircleSegmentQuery((cpShape *)seg, seg->tb, seg->r, a, b, r2, &info2);
+               
+               if(info1.alpha < info2.alpha){
+                       (*info) = info1;
+               } else {
+                       (*info) = info2;
+               }
+       }
+}
+
+static struct cpShapeMassInfo
+cpSegmentShapeMassInfo(cpFloat mass, cpVect a, cpVect b, cpFloat r)
+{
+       struct cpShapeMassInfo info = {
+               mass, cpMomentForBox(1.0f, cpvdist(a, b) + 2.0f*r, 2.0f*r), // TODO is an approximation.
+               cpvlerp(a, b, 0.5f),
+               cpAreaForSegment(a, b, r),
+       };
+       
+       return info;
+}
+
+static const cpShapeClass cpSegmentShapeClass = {
+       CP_SEGMENT_SHAPE,
+       (cpShapeCacheDataImpl)cpSegmentShapeCacheData,
+       NULL,
+       (cpShapePointQueryImpl)cpSegmentShapePointQuery,
+       (cpShapeSegmentQueryImpl)cpSegmentShapeSegmentQuery,
+};
+
+cpSegmentShape *
+cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat r)
+{
+       seg->a = a;
+       seg->b = b;
+       seg->n = cpvrperp(cpvnormalize(cpvsub(b, a)));
+       
+       seg->r = r;
+       
+       seg->a_tangent = cpvzero;
+       seg->b_tangent = cpvzero;
+       
+       cpShapeInit((cpShape *)seg, &cpSegmentShapeClass, body, cpSegmentShapeMassInfo(0.0f, a, b, r));
+       
+       return seg;
+}
+
+cpShape*
+cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat r)
+{
+       return (cpShape *)cpSegmentShapeInit(cpSegmentShapeAlloc(), body, a, b, r);
+}
+
+cpVect
+cpSegmentShapeGetA(const cpShape *shape)
+{
+       cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+       return ((cpSegmentShape *)shape)->a;
+}
+
+cpVect
+cpSegmentShapeGetB(const cpShape *shape)
+{
+       cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+       return ((cpSegmentShape *)shape)->b;
+}
+
+cpVect
+cpSegmentShapeGetNormal(const cpShape *shape)
+{
+       cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+       return ((cpSegmentShape *)shape)->n;
+}
+
+cpFloat
+cpSegmentShapeGetRadius(const cpShape *shape)
+{
+       cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+       return ((cpSegmentShape *)shape)->r;
+}
+
+void
+cpSegmentShapeSetNeighbors(cpShape *shape, cpVect prev, cpVect next)
+{
+       cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+       cpSegmentShape *seg = (cpSegmentShape *)shape;
+       
+       seg->a_tangent = cpvsub(prev, seg->a);
+       seg->b_tangent = cpvsub(next, seg->b);
+}
+
+// Unsafe API (chipmunk_unsafe.h)
+
+// TODO setters should wake the shape up?
+
+void
+cpCircleShapeSetRadius(cpShape *shape, cpFloat radius)
+{
+       cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape.");
+       cpCircleShape *circle = (cpCircleShape *)shape;
+       
+       circle->r = radius;
+       
+       cpFloat mass = shape->massInfo.m;
+       shape->massInfo = cpCircleShapeMassInfo(mass, circle->r, circle->c);
+       if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
+
+void
+cpCircleShapeSetOffset(cpShape *shape, cpVect offset)
+{
+       cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape.");
+       cpCircleShape *circle = (cpCircleShape *)shape;
+       
+       circle->c = offset;
+
+       cpFloat mass = shape->massInfo.m;
+       shape->massInfo = cpCircleShapeMassInfo(shape->massInfo.m, circle->r, circle->c);
+       if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
+
+void
+cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b)
+{
+       cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+       cpSegmentShape *seg = (cpSegmentShape *)shape;
+       
+       seg->a = a;
+       seg->b = b;
+       seg->n = cpvperp(cpvnormalize(cpvsub(b, a)));
+
+       cpFloat mass = shape->massInfo.m;
+       shape->massInfo = cpSegmentShapeMassInfo(shape->massInfo.m, seg->a, seg->b, seg->r);
+       if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
+
+void
+cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius)
+{
+       cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape.");
+       cpSegmentShape *seg = (cpSegmentShape *)shape;
+       
+       seg->r = radius;
+
+       cpFloat mass = shape->massInfo.m;
+       shape->massInfo = cpSegmentShapeMassInfo(shape->massInfo.m, seg->a, seg->b, seg->r);
+       if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body);
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpSimpleMotor.c b/dali-physics/third-party/chipmunk2d/src/cpSimpleMotor.c
new file mode 100644 (file)
index 0000000..6d83f80
--- /dev/null
@@ -0,0 +1,123 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpSimpleMotor *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       // calculate moment of inertia coefficient.
+       joint->iSum = 1.0f/(a->i_inv + b->i_inv);
+}
+
+static void
+applyCachedImpulse(cpSimpleMotor *joint, cpFloat dt_coef)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpFloat j = joint->jAcc*dt_coef;
+       a->w -= j*a->i_inv;
+       b->w += j*b->i_inv;
+}
+
+static void
+applyImpulse(cpSimpleMotor *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       // compute relative rotational velocity
+       cpFloat wr = b->w - a->w + joint->rate;
+       
+       cpFloat jMax = joint->constraint.maxForce*dt;
+       
+       // compute normal impulse       
+       cpFloat j = -wr*joint->iSum;
+       cpFloat jOld = joint->jAcc;
+       joint->jAcc = cpfclamp(jOld + j, -jMax, jMax);
+       j = joint->jAcc - jOld;
+       
+       // apply impulse
+       a->w -= j*a->i_inv;
+       b->w += j*b->i_inv;
+}
+
+static cpFloat
+getImpulse(cpSimpleMotor *joint)
+{
+       return cpfabs(joint->jAcc);
+}
+
+static const cpConstraintClass klass = {
+       (cpConstraintPreStepImpl)preStep,
+       (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+       (cpConstraintApplyImpulseImpl)applyImpulse,
+       (cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpSimpleMotor *
+cpSimpleMotorAlloc(void)
+{
+       return (cpSimpleMotor *)cpcalloc(1, sizeof(cpSimpleMotor));
+}
+
+cpSimpleMotor *
+cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate)
+{
+       cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+       
+       joint->rate = rate;
+       
+       joint->jAcc = 0.0f;
+       
+       return joint;
+}
+
+cpConstraint *
+cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate)
+{
+       return (cpConstraint *)cpSimpleMotorInit(cpSimpleMotorAlloc(), a, b, rate);
+}
+
+cpBool
+cpConstraintIsSimpleMotor(const cpConstraint *constraint)
+{
+       return (constraint->klass == &klass);
+}
+
+cpFloat
+cpSimpleMotorGetRate(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsSimpleMotor(constraint), "Constraint is not a pin joint.");
+       return ((cpSimpleMotor *)constraint)->rate;
+}
+
+void
+cpSimpleMotorSetRate(cpConstraint *constraint, cpFloat rate)
+{
+       cpAssertHard(cpConstraintIsSimpleMotor(constraint), "Constraint is not a pin joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpSimpleMotor *)constraint)->rate = rate;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpSlideJoint.c b/dali-physics/third-party/chipmunk2d/src/cpSlideJoint.c
new file mode 100644 (file)
index 0000000..61afe33
--- /dev/null
@@ -0,0 +1,195 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static void
+preStep(cpSlideJoint *joint, cpFloat dt)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       joint->r1 = cpTransformVect(a->transform, cpvsub(joint->anchorA, a->cog));
+       joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog));
+       
+       cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
+       cpFloat dist = cpvlength(delta);
+       cpFloat pdist = 0.0f;
+       if(dist > joint->max) {
+               pdist = dist - joint->max;
+               joint->n = cpvnormalize(delta);
+       } else if(dist < joint->min) {
+               pdist = joint->min - dist;
+               joint->n = cpvneg(cpvnormalize(delta));
+       } else {
+               joint->n = cpvzero;
+               joint->jnAcc = 0.0f;
+       }
+       
+       // calculate mass normal
+       joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n);
+       
+       // calculate bias velocity
+       cpFloat maxBias = joint->constraint.maxBias;
+       joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias);
+}
+
+static void
+applyCachedImpulse(cpSlideJoint *joint, cpFloat dt_coef)
+{
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpVect j = cpvmult(joint->n, joint->jnAcc*dt_coef);
+       apply_impulses(a, b, joint->r1, joint->r2, j);
+}
+
+static void
+applyImpulse(cpSlideJoint *joint, cpFloat dt)
+{
+       if(cpveql(joint->n, cpvzero)) return;  // early exit
+
+       cpBody *a = joint->constraint.a;
+       cpBody *b = joint->constraint.b;
+       
+       cpVect n = joint->n;
+       cpVect r1 = joint->r1;
+       cpVect r2 = joint->r2;
+               
+       // compute relative velocity
+       cpVect vr = relative_velocity(a, b, r1, r2);
+       cpFloat vrn = cpvdot(vr, n);
+       
+       // compute normal impulse
+       cpFloat jn = (joint->bias - vrn)*joint->nMass;
+       cpFloat jnOld = joint->jnAcc;
+       joint->jnAcc = cpfclamp(jnOld + jn, -joint->constraint.maxForce*dt, 0.0f);
+       jn = joint->jnAcc - jnOld;
+       
+       // apply impulse
+       apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn));
+}
+
+static cpFloat
+getImpulse(cpConstraint *joint)
+{
+       return cpfabs(((cpSlideJoint *)joint)->jnAcc);
+}
+
+static const cpConstraintClass klass = {
+       (cpConstraintPreStepImpl)preStep,
+       (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse,
+       (cpConstraintApplyImpulseImpl)applyImpulse,
+       (cpConstraintGetImpulseImpl)getImpulse,
+};
+
+cpSlideJoint *
+cpSlideJointAlloc(void)
+{
+       return (cpSlideJoint *)cpcalloc(1, sizeof(cpSlideJoint));
+}
+
+cpSlideJoint *
+cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max)
+{
+       cpConstraintInit((cpConstraint *)joint, &klass, a, b);
+       
+       joint->anchorA = anchorA;
+       joint->anchorB = anchorB;
+       joint->min = min;
+       joint->max = max;
+       
+       joint->jnAcc = 0.0f;
+       
+       return joint;
+}
+
+cpConstraint *
+cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max)
+{
+       return (cpConstraint *)cpSlideJointInit(cpSlideJointAlloc(), a, b, anchorA, anchorB, min, max);
+}
+
+cpBool
+cpConstraintIsSlideJoint(const cpConstraint *constraint)
+{
+       return (constraint->klass == &klass);
+}
+
+cpVect
+cpSlideJointGetAnchorA(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+       return ((cpSlideJoint *)constraint)->anchorA;
+}
+
+void
+cpSlideJointSetAnchorA(cpConstraint *constraint, cpVect anchorA)
+{
+       cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpSlideJoint *)constraint)->anchorA = anchorA;
+}
+
+cpVect
+cpSlideJointGetAnchorB(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+       return ((cpSlideJoint *)constraint)->anchorB;
+}
+
+void
+cpSlideJointSetAnchorB(cpConstraint *constraint, cpVect anchorB)
+{
+       cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpSlideJoint *)constraint)->anchorB = anchorB;
+}
+
+cpFloat
+cpSlideJointGetMin(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+       return ((cpSlideJoint *)constraint)->min;
+}
+
+void
+cpSlideJointSetMin(cpConstraint *constraint, cpFloat min)
+{
+       cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpSlideJoint *)constraint)->min = min;
+}
+
+cpFloat
+cpSlideJointGetMax(const cpConstraint *constraint)
+{
+       cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+       return ((cpSlideJoint *)constraint)->max;
+}
+
+void
+cpSlideJointSetMax(cpConstraint *constraint, cpFloat max)
+{
+       cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint.");
+       cpConstraintActivateBodies(constraint);
+       ((cpSlideJoint *)constraint)->max = max;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpSpace.c b/dali-physics/third-party/chipmunk2d/src/cpSpace.c
new file mode 100644 (file)
index 0000000..079752d
--- /dev/null
@@ -0,0 +1,700 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "chipmunk/chipmunk_private.h"
+
+//MARK: Contact Set Helpers
+
+// Equal function for arbiterSet.
+static cpBool
+arbiterSetEql(cpShape **shapes, cpArbiter *arb)
+{
+       cpShape *a = shapes[0];
+       cpShape *b = shapes[1];
+       
+       return ((a == arb->a && b == arb->b) || (b == arb->a && a == arb->b));
+}
+
+//MARK: Collision Handler Set HelperFunctions
+
+// Equals function for collisionHandlers.
+static cpBool
+handlerSetEql(cpCollisionHandler *check, cpCollisionHandler *pair)
+{
+       return (
+               (check->typeA == pair->typeA && check->typeB == pair->typeB) ||
+               (check->typeB == pair->typeA && check->typeA == pair->typeB)
+       );
+}
+
+// Transformation function for collisionHandlers.
+static void *
+handlerSetTrans(cpCollisionHandler *handler, void *unused)
+{
+       cpCollisionHandler *copy = (cpCollisionHandler *)cpcalloc(1, sizeof(cpCollisionHandler));
+       memcpy(copy, handler, sizeof(cpCollisionHandler));
+       
+       return copy;
+}
+
+//MARK: Misc Helper Funcs
+
+// Default collision functions.
+
+static cpBool
+DefaultBegin(cpArbiter *arb, cpSpace *space, void *data){
+       cpBool retA = cpArbiterCallWildcardBeginA(arb, space);
+       cpBool retB = cpArbiterCallWildcardBeginB(arb, space);
+       return retA && retB;
+}
+
+static cpBool
+DefaultPreSolve(cpArbiter *arb, cpSpace *space, void *data){
+       cpBool retA = cpArbiterCallWildcardPreSolveA(arb, space);
+       cpBool retB = cpArbiterCallWildcardPreSolveB(arb, space);
+       return retA && retB;
+}
+
+static void
+DefaultPostSolve(cpArbiter *arb, cpSpace *space, void *data){
+       cpArbiterCallWildcardPostSolveA(arb, space);
+       cpArbiterCallWildcardPostSolveB(arb, space);
+}
+
+static void
+DefaultSeparate(cpArbiter *arb, cpSpace *space, void *data){
+       cpArbiterCallWildcardSeparateA(arb, space);
+       cpArbiterCallWildcardSeparateB(arb, space);
+}
+
+// Use the wildcard identifier since  the default handler should never match any type pair.
+static cpCollisionHandler cpCollisionHandlerDefault = {
+       CP_WILDCARD_COLLISION_TYPE, CP_WILDCARD_COLLISION_TYPE,
+       DefaultBegin, DefaultPreSolve, DefaultPostSolve, DefaultSeparate, NULL
+};
+
+static cpBool AlwaysCollide(cpArbiter *arb, cpSpace *space, void *data){return cpTrue;}
+static void DoNothing(cpArbiter *arb, cpSpace *space, void *data){}
+
+cpCollisionHandler cpCollisionHandlerDoNothing = {
+       CP_WILDCARD_COLLISION_TYPE, CP_WILDCARD_COLLISION_TYPE,
+       AlwaysCollide, AlwaysCollide, DoNothing, DoNothing, NULL
+};
+
+// function to get the estimated velocity of a shape for the cpBBTree.
+static cpVect ShapeVelocityFunc(cpShape *shape){return shape->body->v;}
+
+// Used for disposing of collision handlers.
+static void FreeWrap(void *ptr, void *unused){cpfree(ptr);}
+
+//MARK: Memory Management Functions
+
+cpSpace *
+cpSpaceAlloc(void)
+{
+       return (cpSpace *)cpcalloc(1, sizeof(cpSpace));
+}
+
+cpSpace*
+cpSpaceInit(cpSpace *space)
+{
+#ifndef NDEBUG
+       static cpBool done = cpFalse;
+       if(!done){
+               printf("Initializing cpSpace - Chipmunk v%s (Debug Enabled)\n", cpVersionString);
+               printf("Compile with -DNDEBUG defined to disable debug mode and runtime assertion checks\n");
+               done = cpTrue;
+       }
+#endif
+
+       space->iterations = 10;
+       
+       space->gravity = cpvzero;
+       space->damping = 1.0f;
+       
+       space->collisionSlop = 0.1f;
+       space->collisionBias = cpfpow(1.0f - 0.1f, 60.0f);
+       space->collisionPersistence = 3;
+       
+       space->locked = 0;
+       space->stamp = 0;
+       
+       space->shapeIDCounter = 0;
+       space->staticShapes = cpBBTreeNew((cpSpatialIndexBBFunc)cpShapeGetBB, NULL);
+       space->dynamicShapes = cpBBTreeNew((cpSpatialIndexBBFunc)cpShapeGetBB, space->staticShapes);
+       cpBBTreeSetVelocityFunc(space->dynamicShapes, (cpBBTreeVelocityFunc)ShapeVelocityFunc);
+       
+       space->allocatedBuffers = cpArrayNew(0);
+       
+       space->dynamicBodies = cpArrayNew(0);
+       space->staticBodies = cpArrayNew(0);
+       space->sleepingComponents = cpArrayNew(0);
+       space->rousedBodies = cpArrayNew(0);
+       
+       space->sleepTimeThreshold = INFINITY;
+       space->idleSpeedThreshold = 0.0f;
+       
+       space->arbiters = cpArrayNew(0);
+       space->pooledArbiters = cpArrayNew(0);
+       
+       space->contactBuffersHead = NULL;
+       space->cachedArbiters = cpHashSetNew(0, (cpHashSetEqlFunc)arbiterSetEql);
+       
+       space->constraints = cpArrayNew(0);
+       
+       space->usesWildcards = cpFalse;
+       memcpy(&space->defaultHandler, &cpCollisionHandlerDoNothing, sizeof(cpCollisionHandler));
+       space->collisionHandlers = cpHashSetNew(0, (cpHashSetEqlFunc)handlerSetEql);
+       
+       space->postStepCallbacks = cpArrayNew(0);
+       space->skipPostStep = cpFalse;
+       
+       cpBody *staticBody = cpBodyInit(&space->_staticBody, 0.0f, 0.0f);
+       cpBodySetType(staticBody, CP_BODY_TYPE_STATIC);
+       cpSpaceSetStaticBody(space, staticBody);
+       
+       return space;
+}
+
+cpSpace*
+cpSpaceNew(void)
+{
+       return cpSpaceInit(cpSpaceAlloc());
+}
+
+static void cpBodyActivateWrap(cpBody *body, void *unused){cpBodyActivate(body);}
+
+void
+cpSpaceDestroy(cpSpace *space)
+{
+       cpSpaceEachBody(space, (cpSpaceBodyIteratorFunc)cpBodyActivateWrap, NULL);
+       
+       cpSpatialIndexFree(space->staticShapes);
+       cpSpatialIndexFree(space->dynamicShapes);
+       
+       cpArrayFree(space->dynamicBodies);
+       cpArrayFree(space->staticBodies);
+       cpArrayFree(space->sleepingComponents);
+       cpArrayFree(space->rousedBodies);
+       
+       cpArrayFree(space->constraints);
+       
+       cpHashSetFree(space->cachedArbiters);
+       
+       cpArrayFree(space->arbiters);
+       cpArrayFree(space->pooledArbiters);
+       
+       if(space->allocatedBuffers){
+               cpArrayFreeEach(space->allocatedBuffers, cpfree);
+               cpArrayFree(space->allocatedBuffers);
+       }
+       
+       if(space->postStepCallbacks){
+               cpArrayFreeEach(space->postStepCallbacks, cpfree);
+               cpArrayFree(space->postStepCallbacks);
+       }
+       
+       if(space->collisionHandlers) cpHashSetEach(space->collisionHandlers, FreeWrap, NULL);
+       cpHashSetFree(space->collisionHandlers);
+}
+
+void
+cpSpaceFree(cpSpace *space)
+{
+       if(space){
+               cpSpaceDestroy(space);
+               cpfree(space);
+       }
+}
+
+
+//MARK: Basic properties:
+
+int
+cpSpaceGetIterations(const cpSpace *space)
+{
+       return space->iterations;
+}
+
+void
+cpSpaceSetIterations(cpSpace *space, int iterations)
+{
+       cpAssertHard(iterations > 0, "Iterations must be positive and non-zero.");
+       space->iterations = iterations;
+}
+
+cpVect
+cpSpaceGetGravity(const cpSpace *space)
+{
+       return space->gravity;
+}
+
+void
+cpSpaceSetGravity(cpSpace *space, cpVect gravity)
+{
+       space->gravity = gravity;
+       
+       // Wake up all of the bodies since the gravity changed.
+       cpArray *components = space->sleepingComponents;
+       for(int i=0; i<components->num; i++){
+               cpBodyActivate((cpBody *)components->arr[i]);
+       }
+}
+
+cpFloat
+cpSpaceGetDamping(const cpSpace *space)
+{
+       return space->damping;
+}
+
+void
+cpSpaceSetDamping(cpSpace *space, cpFloat damping)
+{
+       cpAssertHard(damping >= 0.0, "Damping must be positive.");
+       space->damping = damping;
+}
+
+cpFloat
+cpSpaceGetIdleSpeedThreshold(const cpSpace *space)
+{
+       return space->idleSpeedThreshold;
+}
+
+void
+cpSpaceSetIdleSpeedThreshold(cpSpace *space, cpFloat idleSpeedThreshold)
+{
+       space->idleSpeedThreshold = idleSpeedThreshold;
+}
+
+cpFloat
+cpSpaceGetSleepTimeThreshold(const cpSpace *space)
+{
+       return space->sleepTimeThreshold;
+}
+
+void
+cpSpaceSetSleepTimeThreshold(cpSpace *space, cpFloat sleepTimeThreshold)
+{
+       space->sleepTimeThreshold = sleepTimeThreshold;
+}
+
+cpFloat
+cpSpaceGetCollisionSlop(const cpSpace *space)
+{
+       return space->collisionSlop;
+}
+
+void
+cpSpaceSetCollisionSlop(cpSpace *space, cpFloat collisionSlop)
+{
+       space->collisionSlop = collisionSlop;
+}
+
+cpFloat
+cpSpaceGetCollisionBias(const cpSpace *space)
+{
+       return space->collisionBias;
+}
+
+void
+cpSpaceSetCollisionBias(cpSpace *space, cpFloat collisionBias)
+{
+       space->collisionBias = collisionBias;
+}
+
+cpTimestamp
+cpSpaceGetCollisionPersistence(const cpSpace *space)
+{
+       return space->collisionPersistence;
+}
+
+void
+cpSpaceSetCollisionPersistence(cpSpace *space, cpTimestamp collisionPersistence)
+{
+       space->collisionPersistence = collisionPersistence;
+}
+
+cpDataPointer
+cpSpaceGetUserData(const cpSpace *space)
+{
+       return space->userData;
+}
+
+void
+cpSpaceSetUserData(cpSpace *space, cpDataPointer userData)
+{
+       space->userData = userData;
+}
+
+cpBody *
+cpSpaceGetStaticBody(const cpSpace *space)
+{
+       return space->staticBody;
+}
+
+cpFloat
+cpSpaceGetCurrentTimeStep(const cpSpace *space)
+{
+       return space->curr_dt;
+}
+
+void
+cpSpaceSetStaticBody(cpSpace *space, cpBody *body)
+{
+       if(space->staticBody != NULL){
+               cpAssertHard(space->staticBody->shapeList == NULL, "Internal Error: Changing the designated static body while the old one still had shapes attached.");
+               space->staticBody->space = NULL;
+       }
+       
+       space->staticBody = body;
+       body->space = space;
+}
+
+cpBool
+cpSpaceIsLocked(cpSpace *space)
+{
+       return (space->locked > 0);
+}
+
+//MARK: Collision Handler Function Management
+
+static void
+cpSpaceUseWildcardDefaultHandler(cpSpace *space)
+{
+       // Spaces default to using the slightly faster "do nothing" default handler until wildcards are potentially needed.
+       if(!space->usesWildcards){
+               space->usesWildcards = cpTrue;
+               memcpy(&space->defaultHandler, &cpCollisionHandlerDefault, sizeof(cpCollisionHandler));
+       }
+}
+
+cpCollisionHandler *cpSpaceAddDefaultCollisionHandler(cpSpace *space)
+{
+       cpSpaceUseWildcardDefaultHandler(space);
+       return &space->defaultHandler;
+}
+
+cpCollisionHandler *cpSpaceAddCollisionHandler(cpSpace *space, cpCollisionType a, cpCollisionType b)
+{
+       cpHashValue hash = CP_HASH_PAIR(a, b);
+       cpCollisionHandler handler = {a, b, DefaultBegin, DefaultPreSolve, DefaultPostSolve, DefaultSeparate, NULL};
+       return (cpCollisionHandler*)cpHashSetInsert(space->collisionHandlers, hash, &handler, (cpHashSetTransFunc)handlerSetTrans, NULL);
+}
+
+cpCollisionHandler *
+cpSpaceAddWildcardHandler(cpSpace *space, cpCollisionType type)
+{
+       cpSpaceUseWildcardDefaultHandler(space);
+       
+       cpHashValue hash = CP_HASH_PAIR(type, CP_WILDCARD_COLLISION_TYPE);
+       cpCollisionHandler handler = {type, CP_WILDCARD_COLLISION_TYPE, AlwaysCollide, AlwaysCollide, DoNothing, DoNothing, NULL};
+       return (cpCollisionHandler*)cpHashSetInsert(space->collisionHandlers, hash, &handler, (cpHashSetTransFunc)handlerSetTrans, NULL);
+}
+
+
+//MARK: Body, Shape, and Joint Management
+cpShape *
+cpSpaceAddShape(cpSpace *space, cpShape *shape)
+{
+       cpBody *body = shape->body;
+       
+       cpAssertHard(shape->space != space, "You have already added this shape to this space. You must not add it a second time.");
+       cpAssertHard(!shape->space, "You have already added this shape to another space. You cannot add it to a second.");
+//     cpAssertHard(body->space == space, "The shape's body must be added to the space before the shape.");
+       cpAssertSpaceUnlocked(space);
+       
+       cpBool isStatic = (cpBodyGetType(body) == CP_BODY_TYPE_STATIC);
+       if(!isStatic) cpBodyActivate(body);
+       cpBodyAddShape(body, shape);
+       
+       shape->hashid = space->shapeIDCounter++;
+       cpShapeUpdate(shape, body->transform);
+       cpSpatialIndexInsert(isStatic ? space->staticShapes : space->dynamicShapes, shape, shape->hashid);
+       shape->space = space;
+               
+       return shape;
+}
+
+cpBody *
+cpSpaceAddBody(cpSpace *space, cpBody *body)
+{
+       cpAssertHard(body->space != space, "You have already added this body to this space. You must not add it a second time.");
+       cpAssertHard(!body->space, "You have already added this body to another space. You cannot add it to a second.");
+       cpAssertSpaceUnlocked(space);
+       
+       cpArrayPush(cpSpaceArrayForBodyType(space, cpBodyGetType(body)), body);
+       body->space = space;
+       
+       return body;
+}
+
+cpConstraint *
+cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint)
+{
+       cpAssertHard(constraint->space != space, "You have already added this constraint to this space. You must not add it a second time.");
+       cpAssertHard(!constraint->space, "You have already added this constraint to another space. You cannot add it to a second.");
+       cpAssertSpaceUnlocked(space);
+       
+       cpBody *a = constraint->a, *b = constraint->b;
+       cpAssertHard(a != NULL && b != NULL, "Constraint is attached to a NULL body.");
+//     cpAssertHard(a->space == space && b->space == space, "The constraint's bodies must be added to the space before the constraint.");
+       
+       cpBodyActivate(a);
+       cpBodyActivate(b);
+       cpArrayPush(space->constraints, constraint);
+       
+       // Push onto the heads of the bodies' constraint lists
+       constraint->next_a = a->constraintList; a->constraintList = constraint;
+       constraint->next_b = b->constraintList; b->constraintList = constraint;
+       constraint->space = space;
+       
+       return constraint;
+}
+
+struct arbiterFilterContext {
+       cpSpace *space;
+       cpBody *body;
+       cpShape *shape;
+};
+
+static cpBool
+cachedArbitersFilter(cpArbiter *arb, struct arbiterFilterContext *context)
+{
+       cpShape *shape = context->shape;
+       cpBody *body = context->body;
+       
+       
+       // Match on the filter shape, or if it's NULL the filter body
+       if(
+               (body == arb->body_a && (shape == arb->a || shape == NULL)) ||
+               (body == arb->body_b && (shape == arb->b || shape == NULL))
+       ){
+               // Call separate when removing shapes.
+               if(shape && arb->state != CP_ARBITER_STATE_CACHED){
+                       // Invalidate the arbiter since one of the shapes was removed.
+                       arb->state = CP_ARBITER_STATE_INVALIDATED;
+                       
+                       cpCollisionHandler *handler = arb->handler;
+                       handler->separateFunc(arb, context->space, handler->userData);
+               }
+               
+               cpArbiterUnthread(arb);
+               cpArrayDeleteObj(context->space->arbiters, arb);
+               cpArrayPush(context->space->pooledArbiters, arb);
+               
+               return cpFalse;
+       }
+       
+       return cpTrue;
+}
+
+void
+cpSpaceFilterArbiters(cpSpace *space, cpBody *body, cpShape *filter)
+{
+       cpSpaceLock(space); {
+               struct arbiterFilterContext context = {space, body, filter};
+               cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cachedArbitersFilter, &context);
+       } cpSpaceUnlock(space, cpTrue);
+}
+
+void
+cpSpaceRemoveShape(cpSpace *space, cpShape *shape)
+{
+       cpBody *body = shape->body;
+       cpAssertHard(cpSpaceContainsShape(space, shape), "Cannot remove a shape that was not added to the space. (Removed twice maybe?)");
+       cpAssertSpaceUnlocked(space);
+       
+       cpBool isStatic = (cpBodyGetType(body) == CP_BODY_TYPE_STATIC);
+       if(isStatic){
+               cpBodyActivateStatic(body, shape);
+       } else {
+               cpBodyActivate(body);
+       }
+
+       cpBodyRemoveShape(body, shape);
+       cpSpaceFilterArbiters(space, body, shape);
+       cpSpatialIndexRemove(isStatic ? space->staticShapes : space->dynamicShapes, shape, shape->hashid);
+       shape->space = NULL;
+       shape->hashid = 0;
+}
+
+void
+cpSpaceRemoveBody(cpSpace *space, cpBody *body)
+{
+       cpAssertHard(body != cpSpaceGetStaticBody(space), "Cannot remove the designated static body for the space.");
+       cpAssertHard(cpSpaceContainsBody(space, body), "Cannot remove a body that was not added to the space. (Removed twice maybe?)");
+//     cpAssertHard(body->shapeList == NULL, "Cannot remove a body from the space before removing the bodies attached to it.");
+//     cpAssertHard(body->constraintList == NULL, "Cannot remove a body from the space before removing the constraints attached to it.");
+       cpAssertSpaceUnlocked(space);
+       
+       cpBodyActivate(body);
+//     cpSpaceFilterArbiters(space, body, NULL);
+       cpArrayDeleteObj(cpSpaceArrayForBodyType(space, cpBodyGetType(body)), body);
+       body->space = NULL;
+}
+
+void
+cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint)
+{
+       cpAssertHard(cpSpaceContainsConstraint(space, constraint), "Cannot remove a constraint that was not added to the space. (Removed twice maybe?)");
+       cpAssertSpaceUnlocked(space);
+       
+       cpBodyActivate(constraint->a);
+       cpBodyActivate(constraint->b);
+       cpArrayDeleteObj(space->constraints, constraint);
+       
+       cpBodyRemoveConstraint(constraint->a, constraint);
+       cpBodyRemoveConstraint(constraint->b, constraint);
+       constraint->space = NULL;
+}
+
+cpBool cpSpaceContainsShape(cpSpace *space, cpShape *shape)
+{
+       return (shape->space == space);
+}
+
+cpBool cpSpaceContainsBody(cpSpace *space, cpBody *body)
+{
+       return (body->space == space);
+}
+
+cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint)
+{
+       return (constraint->space == space);
+}
+
+//MARK: Iteration
+
+void
+cpSpaceEachBody(cpSpace *space, cpSpaceBodyIteratorFunc func, void *data)
+{
+       cpSpaceLock(space); {
+               cpArray *bodies = space->dynamicBodies;
+               for(int i=0; i<bodies->num; i++){
+                       func((cpBody *)bodies->arr[i], data);
+               }
+               
+               cpArray *otherBodies = space->staticBodies;
+               for(int i=0; i<otherBodies->num; i++){
+                       func((cpBody *)otherBodies->arr[i], data);
+               }
+               
+               cpArray *components = space->sleepingComponents;
+               for(int i=0; i<components->num; i++){
+                       cpBody *root = (cpBody *)components->arr[i];
+                       
+                       cpBody *body = root;
+                       while(body){
+                               cpBody *next = body->sleeping.next;
+                               func(body, data);
+                               body = next;
+                       }
+               }
+       } cpSpaceUnlock(space, cpTrue);
+}
+
+typedef struct spaceShapeContext {
+       cpSpaceShapeIteratorFunc func;
+       void *data;
+} spaceShapeContext;
+
+static void
+spaceEachShapeIterator(cpShape *shape, spaceShapeContext *context)
+{
+       context->func(shape, context->data);
+}
+
+void
+cpSpaceEachShape(cpSpace *space, cpSpaceShapeIteratorFunc func, void *data)
+{
+       cpSpaceLock(space); {
+               spaceShapeContext context = {func, data};
+               cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)spaceEachShapeIterator, &context);
+               cpSpatialIndexEach(space->staticShapes, (cpSpatialIndexIteratorFunc)spaceEachShapeIterator, &context);
+       } cpSpaceUnlock(space, cpTrue);
+}
+
+void
+cpSpaceEachConstraint(cpSpace *space, cpSpaceConstraintIteratorFunc func, void *data)
+{
+       cpSpaceLock(space); {
+               cpArray *constraints = space->constraints;
+               
+               for(int i=0; i<constraints->num; i++){
+                       func((cpConstraint *)constraints->arr[i], data);
+               }
+       } cpSpaceUnlock(space, cpTrue);
+}
+
+//MARK: Spatial Index Management
+
+void 
+cpSpaceReindexStatic(cpSpace *space)
+{
+       cpAssertHard(!space->locked, "You cannot manually reindex objects while the space is locked. Wait until the current query or step is complete.");
+       
+       cpSpatialIndexEach(space->staticShapes, (cpSpatialIndexIteratorFunc)&cpShapeUpdateFunc, NULL);
+       cpSpatialIndexReindex(space->staticShapes);
+}
+
+void
+cpSpaceReindexShape(cpSpace *space, cpShape *shape)
+{
+       cpAssertHard(!space->locked, "You cannot manually reindex objects while the space is locked. Wait until the current query or step is complete.");
+       
+       cpShapeCacheBB(shape);
+       
+       // attempt to rehash the shape in both hashes
+       cpSpatialIndexReindexObject(space->dynamicShapes, shape, shape->hashid);
+       cpSpatialIndexReindexObject(space->staticShapes, shape, shape->hashid);
+}
+
+void
+cpSpaceReindexShapesForBody(cpSpace *space, cpBody *body)
+{
+       CP_BODY_FOREACH_SHAPE(body, shape) cpSpaceReindexShape(space, shape);
+}
+
+
+static void
+copyShapes(cpShape *shape, cpSpatialIndex *index)
+{
+       cpSpatialIndexInsert(index, shape, shape->hashid);
+}
+
+void
+cpSpaceUseSpatialHash(cpSpace *space, cpFloat dim, int count)
+{
+       cpSpatialIndex *staticShapes = cpSpaceHashNew(dim, count, (cpSpatialIndexBBFunc)cpShapeGetBB, NULL);
+       cpSpatialIndex *dynamicShapes = cpSpaceHashNew(dim, count, (cpSpatialIndexBBFunc)cpShapeGetBB, staticShapes);
+       
+       cpSpatialIndexEach(space->staticShapes, (cpSpatialIndexIteratorFunc)copyShapes, staticShapes);
+       cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)copyShapes, dynamicShapes);
+       
+       cpSpatialIndexFree(space->staticShapes);
+       cpSpatialIndexFree(space->dynamicShapes);
+       
+       space->staticShapes = staticShapes;
+       space->dynamicShapes = dynamicShapes;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpSpaceComponent.c b/dali-physics/third-party/chipmunk2d/src/cpSpaceComponent.c
new file mode 100644 (file)
index 0000000..7b2d606
--- /dev/null
@@ -0,0 +1,349 @@
+/* Copyright (c) 2007 Scott Lembcke
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <string.h>
+
+#include "chipmunk/chipmunk_private.h"
+
+//MARK: Sleeping Functions
+
+void
+cpSpaceActivateBody(cpSpace *space, cpBody *body)
+{
+       cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Internal error: Attempting to activate a non-dynamic body.");
+               
+       if(space->locked){
+               // cpSpaceActivateBody() is called again once the space is unlocked
+               if(!cpArrayContains(space->rousedBodies, body)) cpArrayPush(space->rousedBodies, body);
+       } else {
+               cpAssertSoft(body->sleeping.root == NULL && body->sleeping.next == NULL, "Internal error: Activating body non-NULL node pointers.");
+               cpArrayPush(space->dynamicBodies, body);
+
+               CP_BODY_FOREACH_SHAPE(body, shape){
+                       cpSpatialIndexRemove(space->staticShapes, shape, shape->hashid);
+                       cpSpatialIndexInsert(space->dynamicShapes, shape, shape->hashid);
+               }
+               
+               CP_BODY_FOREACH_ARBITER(body, arb){
+                       cpBody *bodyA = arb->body_a;
+                       
+                       // Arbiters are shared between two bodies that are always woken up together.
+                       // You only want to restore the arbiter once, so bodyA is arbitrarily chosen to own the arbiter.
+                       // The edge case is when static bodies are involved as the static bodies never actually sleep.
+                       // If the static body is bodyB then all is good. If the static body is bodyA, that can easily be checked.
+                       if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC){
+                               int numContacts = arb->count;
+                               struct cpContact *contacts = arb->contacts;
+                               
+                               // Restore contact values back to the space's contact buffer memory
+                               arb->contacts = cpContactBufferGetArray(space);
+                               memcpy(arb->contacts, contacts, numContacts*sizeof(struct cpContact));
+                               cpSpacePushContacts(space, numContacts);
+                               
+                               // Reinsert the arbiter into the arbiter cache
+                               const cpShape *a = arb->a, *b = arb->b;
+                               const cpShape *shape_pair[] = {a, b};
+                               cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)a, (cpHashValue)b);
+                               cpHashSetInsert(space->cachedArbiters, arbHashID, shape_pair, NULL, arb);
+                               
+                               // Update the arbiter's state
+                               arb->stamp = space->stamp;
+                               cpArrayPush(space->arbiters, arb);
+                               
+                               cpfree(contacts);
+                       }
+               }
+               
+               CP_BODY_FOREACH_CONSTRAINT(body, constraint){
+                       cpBody *bodyA = constraint->a;
+                       if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC) cpArrayPush(space->constraints, constraint);
+               }
+       }
+}
+
+static void
+cpSpaceDeactivateBody(cpSpace *space, cpBody *body)
+{
+       cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Internal error: Attempting to deactivate a non-dynamic body.");
+       
+       cpArrayDeleteObj(space->dynamicBodies, body);
+       
+       CP_BODY_FOREACH_SHAPE(body, shape){
+               cpSpatialIndexRemove(space->dynamicShapes, shape, shape->hashid);
+               cpSpatialIndexInsert(space->staticShapes, shape, shape->hashid);
+       }
+       
+       CP_BODY_FOREACH_ARBITER(body, arb){
+               cpBody *bodyA = arb->body_a;
+               if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC){
+                       cpSpaceUncacheArbiter(space, arb);
+                       
+                       // Save contact values to a new block of memory so they won't time out
+                       size_t bytes = arb->count*sizeof(struct cpContact);
+                       struct cpContact *contacts = (struct cpContact *)cpcalloc(1, bytes);
+                       memcpy(contacts, arb->contacts, bytes);
+                       arb->contacts = contacts;
+               }
+       }
+               
+       CP_BODY_FOREACH_CONSTRAINT(body, constraint){
+               cpBody *bodyA = constraint->a;
+               if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC) cpArrayDeleteObj(space->constraints, constraint);
+       }
+}
+
+static inline cpBody *
+ComponentRoot(cpBody *body)
+{
+       return (body ? body->sleeping.root : NULL);
+}
+
+void
+cpBodyActivate(cpBody *body)
+{
+       if(body != NULL && cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC){
+               body->sleeping.idleTime = 0.0f;
+               
+               cpBody *root = ComponentRoot(body);
+               if(root && cpBodyIsSleeping(root)){
+                       // TODO should cpBodyIsSleeping(root) be an assertion?
+                       cpAssertSoft(cpBodyGetType(root) == CP_BODY_TYPE_DYNAMIC, "Internal Error: Non-dynamic body component root detected.");
+                       
+                       cpSpace *space = root->space;
+                       cpBody *body = root;
+                       while(body){
+                               cpBody *next = body->sleeping.next;
+                               
+                               body->sleeping.idleTime = 0.0f;
+                               body->sleeping.root = NULL;
+                               body->sleeping.next = NULL;
+                               cpSpaceActivateBody(space, body);
+                               
+                               body = next;
+                       }
+                       
+                       cpArrayDeleteObj(space->sleepingComponents, root);
+               }
+               
+               CP_BODY_FOREACH_ARBITER(body, arb){
+                       // Reset the idle timer of things the body is touching as well.
+                       // That way things don't get left hanging in the air.
+                       cpBody *other = (arb->body_a == body ? arb->body_b : arb->body_a);
+                       if(cpBodyGetType(other) != CP_BODY_TYPE_STATIC) other->sleeping.idleTime = 0.0f;
+               }
+       }
+}
+
+void
+cpBodyActivateStatic(cpBody *body, cpShape *filter)
+{
+       cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_STATIC, "cpBodyActivateStatic() called on a non-static body.");
+       
+       CP_BODY_FOREACH_ARBITER(body, arb){
+               if(!filter || filter == arb->a || filter == arb->b){
+                       cpBodyActivate(arb->body_a == body ? arb->body_b : arb->body_a);
+               }
+       }
+       
+       // TODO: should also activate joints?
+}
+
+static inline void
+cpBodyPushArbiter(cpBody *body, cpArbiter *arb)
+{
+       cpAssertSoft(cpArbiterThreadForBody(arb, body)->next == NULL, "Internal Error: Dangling contact graph pointers detected. (A)");
+       cpAssertSoft(cpArbiterThreadForBody(arb, body)->prev == NULL, "Internal Error: Dangling contact graph pointers detected. (B)");
+       
+       cpArbiter *next = body->arbiterList;
+       cpAssertSoft(next == NULL || cpArbiterThreadForBody(next, body)->prev == NULL, "Internal Error: Dangling contact graph pointers detected. (C)");
+       cpArbiterThreadForBody(arb, body)->next = next;
+       
+       if(next) cpArbiterThreadForBody(next, body)->prev = arb;
+       body->arbiterList = arb;
+}
+
+static inline void
+ComponentAdd(cpBody *root, cpBody *body){
+       body->sleeping.root = root;
+
+       if(body != root){
+               body->sleeping.next = root->sleeping.next;
+               root->sleeping.next = body;
+       }
+}
+
+static inline void
+FloodFillComponent(cpBody *root, cpBody *body)
+{
+       // Kinematic bodies cannot be put to sleep and prevent bodies they are touching from sleeping.
+       // Static bodies are effectively sleeping all the time.
+       if(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC){
+               cpBody *other_root = ComponentRoot(body);
+               if(other_root == NULL){
+                       ComponentAdd(root, body);
+                       CP_BODY_FOREACH_ARBITER(body, arb) FloodFillComponent(root, (body == arb->body_a ? arb->body_b : arb->body_a));
+                       CP_BODY_FOREACH_CONSTRAINT(body, constraint) FloodFillComponent(root, (body == constraint->a ? constraint->b : constraint->a));
+               } else {
+                       cpAssertSoft(other_root == root, "Internal Error: Inconsistency dectected in the contact graph.");
+               }
+       }
+}
+
+static inline cpBool
+ComponentActive(cpBody *root, cpFloat threshold)
+{
+       CP_BODY_FOREACH_COMPONENT(root, body){
+               if(body->sleeping.idleTime < threshold) return cpTrue;
+       }
+       
+       return cpFalse;
+}
+
+void
+cpSpaceProcessComponents(cpSpace *space, cpFloat dt)
+{
+       cpBool sleep = (space->sleepTimeThreshold != INFINITY);
+       cpArray *bodies = space->dynamicBodies;
+       
+#ifndef NDEBUG
+       for(int i=0; i<bodies->num; i++){
+               cpBody *body = (cpBody*)bodies->arr[i];
+               
+               cpAssertSoft(body->sleeping.next == NULL, "Internal Error: Dangling next pointer detected in contact graph.");
+               cpAssertSoft(body->sleeping.root == NULL, "Internal Error: Dangling root pointer detected in contact graph.");
+       }
+#endif
+       
+       // Calculate the kinetic energy of all the bodies.
+       if(sleep){
+               cpFloat dv = space->idleSpeedThreshold;
+               cpFloat dvsq = (dv ? dv*dv : cpvlengthsq(space->gravity)*dt*dt);
+               
+               // update idling and reset component nodes
+               for(int i=0; i<bodies->num; i++){
+                       cpBody *body = (cpBody*)bodies->arr[i];
+                       
+                       // TODO should make a separate array for kinematic bodies.
+                       if(cpBodyGetType(body) != CP_BODY_TYPE_DYNAMIC) continue;
+                       
+                       // Need to deal with infinite mass objects
+                       cpFloat keThreshold = (dvsq ? body->m*dvsq : 0.0f);
+                       body->sleeping.idleTime = (cpBodyKineticEnergy(body) > keThreshold ? 0.0f : body->sleeping.idleTime + dt);
+               }
+       }
+       
+       // Awaken any sleeping bodies found and then push arbiters to the bodies' lists.
+       cpArray *arbiters = space->arbiters;
+       for(int i=0, count=arbiters->num; i<count; i++){
+               cpArbiter *arb = (cpArbiter*)arbiters->arr[i];
+               cpBody *a = arb->body_a, *b = arb->body_b;
+               
+               if(sleep){
+                       // TODO checking cpBodyIsSleepin() redundant?
+                       if(cpBodyGetType(b) == CP_BODY_TYPE_KINEMATIC || cpBodyIsSleeping(a)) cpBodyActivate(a);
+                       if(cpBodyGetType(a) == CP_BODY_TYPE_KINEMATIC || cpBodyIsSleeping(b)) cpBodyActivate(b);
+               }
+               
+               cpBodyPushArbiter(a, arb);
+               cpBodyPushArbiter(b, arb);
+       }
+       
+       if(sleep){
+               // Bodies should be held active if connected by a joint to a kinematic.
+               cpArray *constraints = space->constraints;
+               for(int i=0; i<constraints->num; i++){
+                       cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+                       cpBody *a = constraint->a, *b = constraint->b;
+                       
+                       if(cpBodyGetType(b) == CP_BODY_TYPE_KINEMATIC) cpBodyActivate(a);
+                       if(cpBodyGetType(a) == CP_BODY_TYPE_KINEMATIC) cpBodyActivate(b);
+               }
+               
+               // Generate components and deactivate sleeping ones
+               for(int i=0; i<bodies->num;){
+                       cpBody *body = (cpBody*)bodies->arr[i];
+                       
+                       if(ComponentRoot(body) == NULL){
+                               // Body not in a component yet. Perform a DFS to flood fill mark 
+                               // the component in the contact graph using this body as the root.
+                               FloodFillComponent(body, body);
+                               
+                               // Check if the component should be put to sleep.
+                               if(!ComponentActive(body, space->sleepTimeThreshold)){
+                                       cpArrayPush(space->sleepingComponents, body);
+                                       CP_BODY_FOREACH_COMPONENT(body, other) cpSpaceDeactivateBody(space, other);
+                                       
+                                       // cpSpaceDeactivateBody() removed the current body from the list.
+                                       // Skip incrementing the index counter.
+                                       continue;
+                               }
+                       }
+                       
+                       i++;
+                       
+                       // Only sleeping bodies retain their component node pointers.
+                       body->sleeping.root = NULL;
+                       body->sleeping.next = NULL;
+               }
+       }
+}
+
+void
+cpBodySleep(cpBody *body)
+{
+       cpBodySleepWithGroup(body, NULL);
+}
+
+void
+cpBodySleepWithGroup(cpBody *body, cpBody *group){
+       cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Non-dynamic bodies cannot be put to sleep.");
+       
+       cpSpace *space = body->space;
+       cpAssertHard(!cpSpaceIsLocked(space), "Bodies cannot be put to sleep during a query or a call to cpSpaceStep(). Put these calls into a post-step callback.");
+       cpAssertHard(cpSpaceGetSleepTimeThreshold(space) < INFINITY, "Sleeping is not enabled on the space. You cannot sleep a body without setting a sleep time threshold on the space.");
+       cpAssertHard(group == NULL || cpBodyIsSleeping(group), "Cannot use a non-sleeping body as a group identifier.");
+       
+       if(cpBodyIsSleeping(body)){
+               cpAssertHard(ComponentRoot(body) == ComponentRoot(group), "The body is already sleeping and it's group cannot be reassigned.");
+               return;
+       }
+       
+       CP_BODY_FOREACH_SHAPE(body, shape) cpShapeCacheBB(shape);
+       cpSpaceDeactivateBody(space, body);
+       
+       if(group){
+               cpBody *root = ComponentRoot(group);
+               
+               body->sleeping.root = root;
+               body->sleeping.next = root->sleeping.next;
+               body->sleeping.idleTime = 0.0f;
+               
+               root->sleeping.next = body;
+       } else {
+               body->sleeping.root = body;
+               body->sleeping.next = NULL;
+               body->sleeping.idleTime = 0.0f;
+               
+               cpArrayPush(space->sleepingComponents, body);
+       }
+       
+       cpArrayDeleteObj(space->dynamicBodies, body);
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpSpaceDebug.c b/dali-physics/third-party/chipmunk2d/src/cpSpaceDebug.c
new file mode 100644 (file)
index 0000000..4711ac5
--- /dev/null
@@ -0,0 +1,189 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+#ifndef CP_SPACE_DISABLE_DEBUG_API
+
+static void
+cpSpaceDebugDrawShape(cpShape *shape, cpSpaceDebugDrawOptions *options)
+{
+       cpBody *body = shape->body;
+       cpDataPointer data = options->data;
+       
+       cpSpaceDebugColor outline_color = options->shapeOutlineColor;
+       cpSpaceDebugColor fill_color = options->colorForShape(shape, data);
+       
+       switch(shape->klass->type){
+               case CP_CIRCLE_SHAPE: {
+                       cpCircleShape *circle = (cpCircleShape *)shape;
+                       options->drawCircle(circle->tc, body->a, circle->r, outline_color, fill_color, data);
+                       break;
+               }
+               case CP_SEGMENT_SHAPE: {
+                       cpSegmentShape *seg = (cpSegmentShape *)shape;
+                       options->drawFatSegment(seg->ta, seg->tb, seg->r, outline_color, fill_color, data);
+                       break;
+               }
+               case CP_POLY_SHAPE: {
+                       cpPolyShape *poly = (cpPolyShape *)shape;
+                       
+                       int count = poly->count;
+                       struct cpSplittingPlane *planes = poly->planes;
+                       cpVect *verts = (cpVect *)alloca(count*sizeof(cpVect));
+                       
+                       for(int i=0; i<count; i++) verts[i] = planes[i].v0;
+                       options->drawPolygon(count, verts, poly->r, outline_color, fill_color, data);
+                       break;
+               }
+               default: break;
+       }
+}
+
+static const cpVect spring_verts[] = {
+       {0.00f, 0.0f},
+       {0.20f, 0.0f},
+       {0.25f, 3.0f},
+       {0.30f,-6.0f},
+       {0.35f, 6.0f},
+       {0.40f,-6.0f},
+       {0.45f, 6.0f},
+       {0.50f,-6.0f},
+       {0.55f, 6.0f},
+       {0.60f,-6.0f},
+       {0.65f, 6.0f},
+       {0.70f,-3.0f},
+       {0.75f, 6.0f},
+       {0.80f, 0.0f},
+       {1.00f, 0.0f},
+};
+static const int spring_count = sizeof(spring_verts)/sizeof(cpVect);
+
+static void
+cpSpaceDebugDrawConstraint(cpConstraint *constraint, cpSpaceDebugDrawOptions *options)
+{
+       cpDataPointer data = options->data;
+       cpSpaceDebugColor color = options->constraintColor;
+       
+       cpBody *body_a = constraint->a;
+       cpBody *body_b = constraint->b;
+
+       if(cpConstraintIsPinJoint(constraint)){
+               cpPinJoint *joint = (cpPinJoint *)constraint;
+               
+               cpVect a = cpTransformPoint(body_a->transform, joint->anchorA);
+               cpVect b = cpTransformPoint(body_b->transform, joint->anchorB);
+               
+               options->drawDot(5, a, color, data);
+               options->drawDot(5, b, color, data);
+               options->drawSegment(a, b, color, data);
+       } else if(cpConstraintIsSlideJoint(constraint)){
+               cpSlideJoint *joint = (cpSlideJoint *)constraint;
+       
+               cpVect a = cpTransformPoint(body_a->transform, joint->anchorA);
+               cpVect b = cpTransformPoint(body_b->transform, joint->anchorB);
+               
+               options->drawDot(5, a, color, data);
+               options->drawDot(5, b, color, data);
+               options->drawSegment(a, b, color, data);
+       } else if(cpConstraintIsPivotJoint(constraint)){
+               cpPivotJoint *joint = (cpPivotJoint *)constraint;
+       
+               cpVect a = cpTransformPoint(body_a->transform, joint->anchorA);
+               cpVect b = cpTransformPoint(body_b->transform, joint->anchorB);
+
+               options->drawDot(5, a, color, data);
+               options->drawDot(5, b, color, data);
+       } else if(cpConstraintIsGrooveJoint(constraint)){
+               cpGrooveJoint *joint = (cpGrooveJoint *)constraint;
+       
+               cpVect a = cpTransformPoint(body_a->transform, joint->grv_a);
+               cpVect b = cpTransformPoint(body_a->transform, joint->grv_b);
+               cpVect c = cpTransformPoint(body_b->transform, joint->anchorB);
+               
+               options->drawDot(5, c, color, data);
+               options->drawSegment(a, b, color, data);
+       } else if(cpConstraintIsDampedSpring(constraint)){
+               cpDampedSpring *spring = (cpDampedSpring *)constraint;
+               cpDataPointer data = options->data;
+               cpSpaceDebugColor color = options->constraintColor;
+               
+               cpVect a = cpTransformPoint(body_a->transform, spring->anchorA);
+               cpVect b = cpTransformPoint(body_b->transform, spring->anchorB);
+               
+               options->drawDot(5, a, color, data);
+               options->drawDot(5, b, color, data);
+
+               cpVect delta = cpvsub(b, a);
+               cpFloat cos = delta.x;
+               cpFloat sin = delta.y;
+               cpFloat s = 1.0f/cpvlength(delta);
+               
+               cpVect r1 = cpv(cos, -sin*s);
+               cpVect r2 = cpv(sin,  cos*s);
+               
+               cpVect *verts = (cpVect *)alloca(spring_count*sizeof(cpVect));
+               for(int i=0; i<spring_count; i++){
+                       cpVect v = spring_verts[i];
+                       verts[i] = cpv(cpvdot(v, r1) + a.x, cpvdot(v, r2) + a.y);
+               }
+               
+               for(int i=0; i<spring_count-1; i++){
+                       options->drawSegment(verts[i], verts[i + 1], color, data);
+               }
+       }
+}
+
+void
+cpSpaceDebugDraw(cpSpace *space, cpSpaceDebugDrawOptions *options)
+{
+       if(options->flags & CP_SPACE_DEBUG_DRAW_SHAPES){
+               cpSpaceEachShape(space, (cpSpaceShapeIteratorFunc)cpSpaceDebugDrawShape, options);
+       }
+       
+       if(options->flags & CP_SPACE_DEBUG_DRAW_CONSTRAINTS){
+               cpSpaceEachConstraint(space, (cpSpaceConstraintIteratorFunc)cpSpaceDebugDrawConstraint, options);
+       }
+       
+       if(options->flags & CP_SPACE_DEBUG_DRAW_COLLISION_POINTS){
+               cpArray *arbiters = space->arbiters;
+               cpSpaceDebugColor color = options->collisionPointColor;
+               cpSpaceDebugDrawSegmentImpl draw_seg = options->drawSegment;
+               cpDataPointer data = options->data;
+               
+               for(int i=0; i<arbiters->num; i++){
+                       cpArbiter *arb = (cpArbiter*)arbiters->arr[i];
+                       cpVect n = arb->n;
+                       
+                       for(int j=0; j<arb->count; j++){
+                               cpVect p1 = cpvadd(arb->body_a->p, arb->contacts[j].r1);
+                               cpVect p2 = cpvadd(arb->body_b->p, arb->contacts[j].r2);
+                               
+                               cpFloat d = 2.0f;
+                               cpVect a = cpvadd(p1, cpvmult(n, -d));
+                               cpVect b = cpvadd(p2, cpvmult(n,  d));
+                               draw_seg(a, b, color, data);
+                       }
+               }
+       }
+}
+
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/src/cpSpaceHash.c b/dali-physics/third-party/chipmunk2d/src/cpSpaceHash.c
new file mode 100644 (file)
index 0000000..656c3bd
--- /dev/null
@@ -0,0 +1,634 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+#include "prime.h"
+
+typedef struct cpSpaceHashBin cpSpaceHashBin;
+typedef struct cpHandle cpHandle;
+
+struct cpSpaceHash {
+       cpSpatialIndex spatialIndex;
+       
+       int numcells;
+       cpFloat celldim;
+       
+       cpSpaceHashBin **table;
+       cpHashSet *handleSet;
+       
+       cpSpaceHashBin *pooledBins;
+       cpArray *pooledHandles;
+       cpArray *allocatedBuffers;
+       
+       cpTimestamp stamp;
+};
+
+
+//MARK: Handle Functions
+
+struct cpHandle {
+       void *obj;
+       int retain;
+       cpTimestamp stamp;
+};
+
+static cpHandle*
+cpHandleInit(cpHandle *hand, void *obj)
+{
+       hand->obj = obj;
+       hand->retain = 0;
+       hand->stamp = 0;
+       
+       return hand;
+}
+
+static inline void cpHandleRetain(cpHandle *hand){hand->retain++;}
+
+static inline void
+cpHandleRelease(cpHandle *hand, cpArray *pooledHandles)
+{
+       hand->retain--;
+       if(hand->retain == 0) cpArrayPush(pooledHandles, hand);
+}
+
+static int handleSetEql(void *obj, cpHandle *hand){return (obj == hand->obj);}
+
+static void *
+handleSetTrans(void *obj, cpSpaceHash *hash)
+{
+       if(hash->pooledHandles->num == 0){
+               // handle pool is exhausted, make more
+               int count = CP_BUFFER_BYTES/sizeof(cpHandle);
+               cpAssertHard(count, "Internal Error: Buffer size is too small.");
+               
+               cpHandle *buffer = (cpHandle *)cpcalloc(1, CP_BUFFER_BYTES);
+               cpArrayPush(hash->allocatedBuffers, buffer);
+               
+               for(int i=0; i<count; i++) cpArrayPush(hash->pooledHandles, buffer + i);
+       }
+       
+       cpHandle *hand = cpHandleInit((cpHandle *)cpArrayPop(hash->pooledHandles), obj);
+       cpHandleRetain(hand);
+       
+       return hand;
+}
+
+//MARK: Bin Functions
+
+struct cpSpaceHashBin {
+       cpHandle *handle;
+       cpSpaceHashBin *next;
+};
+
+static inline void
+recycleBin(cpSpaceHash *hash, cpSpaceHashBin *bin)
+{
+       bin->next = hash->pooledBins;
+       hash->pooledBins = bin;
+}
+
+static inline void
+clearTableCell(cpSpaceHash *hash, int idx)
+{
+       cpSpaceHashBin *bin = hash->table[idx];
+       while(bin){
+               cpSpaceHashBin *next = bin->next;
+               
+               cpHandleRelease(bin->handle, hash->pooledHandles);
+               recycleBin(hash, bin);
+               
+               bin = next;
+       }
+       
+       hash->table[idx] = NULL;
+}
+
+static void
+clearTable(cpSpaceHash *hash)
+{
+       for(int i=0; i<hash->numcells; i++) clearTableCell(hash, i);
+}
+
+// Get a recycled or new bin.
+static inline cpSpaceHashBin *
+getEmptyBin(cpSpaceHash *hash)
+{
+       cpSpaceHashBin *bin = hash->pooledBins;
+       
+       if(bin){
+               hash->pooledBins = bin->next;
+               return bin;
+       } else {
+               // Pool is exhausted, make more
+               int count = CP_BUFFER_BYTES/sizeof(cpSpaceHashBin);
+               cpAssertHard(count, "Internal Error: Buffer size is too small.");
+               
+               cpSpaceHashBin *buffer = (cpSpaceHashBin *)cpcalloc(1, CP_BUFFER_BYTES);
+               cpArrayPush(hash->allocatedBuffers, buffer);
+               
+               // push all but the first one, return the first instead
+               for(int i=1; i<count; i++) recycleBin(hash, buffer + i);
+               return buffer;
+       }
+}
+
+//MARK: Memory Management Functions
+
+cpSpaceHash *
+cpSpaceHashAlloc(void)
+{
+       return (cpSpaceHash *)cpcalloc(1, sizeof(cpSpaceHash));
+}
+
+// Frees the old table, and allocate a new one.
+static void
+cpSpaceHashAllocTable(cpSpaceHash *hash, int numcells)
+{
+       cpfree(hash->table);
+       
+       hash->numcells = numcells;
+       hash->table = (cpSpaceHashBin **)cpcalloc(numcells, sizeof(cpSpaceHashBin *));
+}
+
+static inline cpSpatialIndexClass *Klass();
+
+cpSpatialIndex *
+cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+       cpSpatialIndexInit((cpSpatialIndex *)hash, Klass(), bbfunc, staticIndex);
+       
+       cpSpaceHashAllocTable(hash, next_prime(numcells));
+       hash->celldim = celldim;
+       
+       hash->handleSet = cpHashSetNew(0, (cpHashSetEqlFunc)handleSetEql);
+       
+       hash->pooledHandles = cpArrayNew(0);
+       
+       hash->pooledBins = NULL;
+       hash->allocatedBuffers = cpArrayNew(0);
+       
+       hash->stamp = 1;
+       
+       return (cpSpatialIndex *)hash;
+}
+
+cpSpatialIndex *
+cpSpaceHashNew(cpFloat celldim, int cells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+       return cpSpaceHashInit(cpSpaceHashAlloc(), celldim, cells, bbfunc, staticIndex);
+}
+
+static void
+cpSpaceHashDestroy(cpSpaceHash *hash)
+{
+       if(hash->table) clearTable(hash);
+       cpfree(hash->table);
+       
+       cpHashSetFree(hash->handleSet);
+       
+       cpArrayFreeEach(hash->allocatedBuffers, cpfree);
+       cpArrayFree(hash->allocatedBuffers);
+       cpArrayFree(hash->pooledHandles);
+}
+
+//MARK: Helper Functions
+
+static inline cpBool
+containsHandle(cpSpaceHashBin *bin, cpHandle *hand)
+{
+       while(bin){
+               if(bin->handle == hand) return cpTrue;
+               bin = bin->next;
+       }
+       
+       return cpFalse;
+}
+
+// The hash function itself.
+static inline cpHashValue
+hash_func(cpHashValue x, cpHashValue y, cpHashValue n)
+{
+       return (x*1640531513ul ^ y*2654435789ul) % n;
+}
+
+// Much faster than (int)floor(f)
+// Profiling showed floor() to be a sizable performance hog
+static inline int
+floor_int(cpFloat f)
+{
+       int i = (int)f;
+       return (f < 0.0f && f != i ? i - 1 : i);
+}
+
+static inline void
+hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb)
+{
+       // Find the dimensions in cell coordinates.
+       cpFloat dim = hash->celldim;
+       int l = floor_int(bb.l/dim); // Fix by ShiftZ
+       int r = floor_int(bb.r/dim);
+       int b = floor_int(bb.b/dim);
+       int t = floor_int(bb.t/dim);
+       
+       int n = hash->numcells;
+       for(int i=l; i<=r; i++){
+               for(int j=b; j<=t; j++){
+                       cpHashValue idx = hash_func(i,j,n);
+                       cpSpaceHashBin *bin = hash->table[idx];
+                       
+                       // Don't add an object twice to the same cell.
+                       if(containsHandle(bin, hand)) continue;
+
+                       cpHandleRetain(hand);
+                       // Insert a new bin for the handle in this cell.
+                       cpSpaceHashBin *newBin = getEmptyBin(hash);
+                       newBin->handle = hand;
+                       newBin->next = bin;
+                       hash->table[idx] = newBin;
+               }
+       }
+}
+
+//MARK: Basic Operations
+
+static void
+cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue hashid)
+{
+       cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, hashid, obj, (cpHashSetTransFunc)handleSetTrans, hash);
+       hashHandle(hash, hand, hash->spatialIndex.bbfunc(obj));
+}
+
+static void
+cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue hashid)
+{
+       cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, hashid, obj);
+       
+       if(hand){
+               hand->obj = NULL;
+               cpHandleRelease(hand, hash->pooledHandles);
+               
+               cpSpaceHashInsert(hash, obj, hashid);
+       }
+}
+
+static void
+rehash_helper(cpHandle *hand, cpSpaceHash *hash)
+{
+       hashHandle(hash, hand, hash->spatialIndex.bbfunc(hand->obj));
+}
+
+static void
+cpSpaceHashRehash(cpSpaceHash *hash)
+{
+       clearTable(hash);
+       cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)rehash_helper, hash);
+}
+
+static void
+cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue hashid)
+{
+       cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, hashid, obj);
+       
+       if(hand){
+               hand->obj = NULL;
+               cpHandleRelease(hand, hash->pooledHandles);
+       }
+}
+
+typedef struct eachContext {
+       cpSpatialIndexIteratorFunc func;
+       void *data;
+} eachContext;
+
+static void eachHelper(cpHandle *hand, eachContext *context){context->func(hand->obj, context->data);}
+
+static void
+cpSpaceHashEach(cpSpaceHash *hash, cpSpatialIndexIteratorFunc func, void *data)
+{
+       eachContext context = {func, data};
+       cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)eachHelper, &context);
+}
+
+static void
+remove_orphaned_handles(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr)
+{
+       cpSpaceHashBin *bin = *bin_ptr;
+       while(bin){
+               cpHandle *hand = bin->handle;
+               cpSpaceHashBin *next = bin->next;
+               
+               if(!hand->obj){
+                       // orphaned handle, unlink and recycle the bin
+                       (*bin_ptr) = bin->next;
+                       recycleBin(hash, bin);
+                       
+                       cpHandleRelease(hand, hash->pooledHandles);
+               } else {
+                       bin_ptr = &bin->next;
+               }
+               
+               bin = next;
+       }
+}
+
+//MARK: Query Functions
+
+static inline void
+query_helper(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpatialIndexQueryFunc func, void *data)
+{
+       restart:
+       for(cpSpaceHashBin *bin = *bin_ptr; bin; bin = bin->next){
+               cpHandle *hand = bin->handle;
+               void *other = hand->obj;
+               
+               if(hand->stamp == hash->stamp || obj == other){
+                       continue;
+               } else if(other){
+                       func(obj, other, 0, data);
+                       hand->stamp = hash->stamp;
+               } else {
+                       // The object for this handle has been removed
+                       // cleanup this cell and restart the query
+                       remove_orphaned_handles(hash, bin_ptr);
+                       goto restart; // GCC not smart enough/able to tail call an inlined function.
+               }
+       }
+}
+
+static void
+cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
+{
+       // Get the dimensions in cell coordinates.
+       cpFloat dim = hash->celldim;
+       int l = floor_int(bb.l/dim);  // Fix by ShiftZ
+       int r = floor_int(bb.r/dim);
+       int b = floor_int(bb.b/dim);
+       int t = floor_int(bb.t/dim);
+       
+       int n = hash->numcells;
+       cpSpaceHashBin **table = hash->table;
+       
+       // Iterate over the cells and query them.
+       for(int i=l; i<=r; i++){
+               for(int j=b; j<=t; j++){
+                       query_helper(hash, &table[hash_func(i,j,n)], obj, func, data);
+               }
+       }
+       
+       hash->stamp++;
+}
+
+// Similar to struct eachPair above.
+typedef struct queryRehashContext {
+       cpSpaceHash *hash;
+       cpSpatialIndexQueryFunc func;
+       void *data;
+} queryRehashContext;
+
+// Hashset iterator func used with cpSpaceHashQueryRehash().
+static void
+queryRehash_helper(cpHandle *hand, queryRehashContext *context)
+{
+       cpSpaceHash *hash = context->hash;
+       cpSpatialIndexQueryFunc func = context->func;
+       void *data = context->data;
+
+       cpFloat dim = hash->celldim;
+       int n = hash->numcells;
+
+       void *obj = hand->obj;
+       cpBB bb = hash->spatialIndex.bbfunc(obj);
+
+       int l = floor_int(bb.l/dim);
+       int r = floor_int(bb.r/dim);
+       int b = floor_int(bb.b/dim);
+       int t = floor_int(bb.t/dim);
+       
+       cpSpaceHashBin **table = hash->table;
+
+       for(int i=l; i<=r; i++){
+               for(int j=b; j<=t; j++){
+                       cpHashValue idx = hash_func(i,j,n);
+                       cpSpaceHashBin *bin = table[idx];
+                       
+                       if(containsHandle(bin, hand)) continue;
+                       
+                       cpHandleRetain(hand); // this MUST be done first in case the object is removed in func()
+                       query_helper(hash, &bin, obj, func, data);
+                       
+                       cpSpaceHashBin *newBin = getEmptyBin(hash);
+                       newBin->handle = hand;
+                       newBin->next = bin;
+                       table[idx] = newBin;
+               }
+       }
+       
+       // Increment the stamp for each object hashed.
+       hash->stamp++;
+}
+
+static void
+cpSpaceHashReindexQuery(cpSpaceHash *hash, cpSpatialIndexQueryFunc func, void *data)
+{
+       clearTable(hash);
+       
+       queryRehashContext context = {hash, func, data};
+       cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)queryRehash_helper, &context);
+       
+       cpSpatialIndexCollideStatic((cpSpatialIndex *)hash, hash->spatialIndex.staticIndex, func, data);
+}
+
+static inline cpFloat
+segmentQuery_helper(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+       cpFloat t = 1.0f;
+        
+       restart:
+       for(cpSpaceHashBin *bin = *bin_ptr; bin; bin = bin->next){
+               cpHandle *hand = bin->handle;
+               void *other = hand->obj;
+               
+               // Skip over certain conditions
+               if(hand->stamp == hash->stamp){
+                       continue;
+               } else if(other){
+                       t = cpfmin(t, func(obj, other, data));
+                       hand->stamp = hash->stamp;
+               } else {
+                       // The object for this handle has been removed
+                       // cleanup this cell and restart the query
+                       remove_orphaned_handles(hash, bin_ptr);
+                       goto restart; // GCC not smart enough/able to tail call an inlined function.
+               }
+       }
+       
+       return t;
+}
+
+// modified from http://playtechs.blogspot.com/2007/03/raytracing-on-grid.html
+static void
+cpSpaceHashSegmentQuery(cpSpaceHash *hash, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+       a = cpvmult(a, 1.0f/hash->celldim);
+       b = cpvmult(b, 1.0f/hash->celldim);
+       
+       int cell_x = floor_int(a.x), cell_y = floor_int(a.y);
+
+       cpFloat t = 0;
+
+       int x_inc, y_inc;
+       cpFloat temp_v, temp_h;
+
+       if (b.x > a.x){
+               x_inc = 1;
+               temp_h = (cpffloor(a.x + 1.0f) - a.x);
+       } else {
+               x_inc = -1;
+               temp_h = (a.x - cpffloor(a.x));
+       }
+
+       if (b.y > a.y){
+               y_inc = 1;
+               temp_v = (cpffloor(a.y + 1.0f) - a.y);
+       } else {
+               y_inc = -1;
+               temp_v = (a.y - cpffloor(a.y));
+       }
+       
+       // Division by zero is *very* slow on ARM
+       cpFloat dx = cpfabs(b.x - a.x), dy = cpfabs(b.y - a.y);
+       cpFloat dt_dx = (dx ? 1.0f/dx : INFINITY), dt_dy = (dy ? 1.0f/dy : INFINITY);
+       
+       // fix NANs in horizontal directions
+       cpFloat next_h = (temp_h ? temp_h*dt_dx : dt_dx);
+       cpFloat next_v = (temp_v ? temp_v*dt_dy : dt_dy);
+       
+       int n = hash->numcells;
+       cpSpaceHashBin **table = hash->table;
+
+       while(t < t_exit){
+               cpHashValue idx = hash_func(cell_x, cell_y, n);
+               t_exit = cpfmin(t_exit, segmentQuery_helper(hash, &table[idx], obj, func, data));
+
+               if (next_v < next_h){
+                       cell_y += y_inc;
+                       t = next_v;
+                       next_v += dt_dy;
+               } else {
+                       cell_x += x_inc;
+                       t = next_h;
+                       next_h += dt_dx;
+               }
+       }
+       
+       hash->stamp++;
+}
+
+//MARK: Misc
+
+void
+cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells)
+{
+       if(hash->spatialIndex.klass != Klass()){
+               cpAssertWarn(cpFalse, "Ignoring cpSpaceHashResize() call to non-cpSpaceHash spatial index.");
+               return;
+       }
+       
+       clearTable(hash);
+       
+       hash->celldim = celldim;
+       cpSpaceHashAllocTable(hash, next_prime(numcells));
+}
+
+static int
+cpSpaceHashCount(cpSpaceHash *hash)
+{
+       return cpHashSetCount(hash->handleSet);
+}
+
+static int
+cpSpaceHashContains(cpSpaceHash *hash, void *obj, cpHashValue hashid)
+{
+       return cpHashSetFind(hash->handleSet, hashid, obj) != NULL;
+}
+
+static cpSpatialIndexClass klass = {
+       (cpSpatialIndexDestroyImpl)cpSpaceHashDestroy,
+       
+       (cpSpatialIndexCountImpl)cpSpaceHashCount,
+       (cpSpatialIndexEachImpl)cpSpaceHashEach,
+       (cpSpatialIndexContainsImpl)cpSpaceHashContains,
+       
+       (cpSpatialIndexInsertImpl)cpSpaceHashInsert,
+       (cpSpatialIndexRemoveImpl)cpSpaceHashRemove,
+       
+       (cpSpatialIndexReindexImpl)cpSpaceHashRehash,
+       (cpSpatialIndexReindexObjectImpl)cpSpaceHashRehashObject,
+       (cpSpatialIndexReindexQueryImpl)cpSpaceHashReindexQuery,
+       
+       (cpSpatialIndexQueryImpl)cpSpaceHashQuery,
+       (cpSpatialIndexSegmentQueryImpl)cpSpaceHashSegmentQuery,
+};
+
+static inline cpSpatialIndexClass *Klass(){return &klass;}
+
+//MARK: Debug Drawing
+
+//#define CP_BBTREE_DEBUG_DRAW
+#ifdef CP_BBTREE_DEBUG_DRAW
+#include "OpenGL/gl.h"
+#include "OpenGL/glu.h"
+#include <GLUT/glut.h>
+
+void
+cpSpaceHashRenderDebug(cpSpatialIndex *index)
+{
+       if(index->klass != &klass){
+               cpAssertWarn(cpFalse, "Ignoring cpSpaceHashRenderDebug() call to non-spatial hash spatial index.");
+               return;
+       }
+       
+       cpSpaceHash *hash = (cpSpaceHash *)index;
+       cpBB bb = cpBBNew(-320, -240, 320, 240);
+       
+       cpFloat dim = hash->celldim;
+       int n = hash->numcells;
+       
+       int l = (int)floor(bb.l/dim);
+       int r = (int)floor(bb.r/dim);
+       int b = (int)floor(bb.b/dim);
+       int t = (int)floor(bb.t/dim);
+       
+       for(int i=l; i<=r; i++){
+               for(int j=b; j<=t; j++){
+                       int cell_count = 0;
+                       
+                       int index = hash_func(i,j,n);
+                       for(cpSpaceHashBin *bin = hash->table[index]; bin; bin = bin->next)
+                               cell_count++;
+                       
+                       GLfloat v = 1.0f - (GLfloat)cell_count/10.0f;
+                       glColor3f(v,v,v);
+                       glRectf(i*dim, j*dim, (i + 1)*dim, (j + 1)*dim);
+               }
+       }
+}
+#endif
diff --git a/dali-physics/third-party/chipmunk2d/src/cpSpaceQuery.c b/dali-physics/third-party/chipmunk2d/src/cpSpaceQuery.c
new file mode 100644 (file)
index 0000000..1ce4a10
--- /dev/null
@@ -0,0 +1,246 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+//MARK: Nearest Point Query Functions
+
+struct PointQueryContext {
+       cpVect point;
+       cpFloat maxDistance;
+       cpShapeFilter filter;
+       cpSpacePointQueryFunc func;
+};
+
+static cpCollisionID
+NearestPointQuery(struct PointQueryContext *context, cpShape *shape, cpCollisionID id, void *data)
+{
+       if(
+               !cpShapeFilterReject(shape->filter, context->filter)
+       ){
+               cpPointQueryInfo info;
+               cpShapePointQuery(shape, context->point, &info);
+               
+               if(info.shape && info.distance < context->maxDistance) context->func(shape, info.point, info.distance, info.gradient, data);
+       }
+       
+       return id;
+}
+
+void
+cpSpacePointQuery(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryFunc func, void *data)
+{
+       struct PointQueryContext context = {point, maxDistance, filter, func};
+       cpBB bb = cpBBNewForCircle(point, cpfmax(maxDistance, 0.0f));
+       
+       cpSpaceLock(space); {
+               cpSpatialIndexQuery(space->dynamicShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQuery, data);
+               cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQuery, data);
+       } cpSpaceUnlock(space, cpTrue);
+}
+
+static cpCollisionID
+NearestPointQueryNearest(struct PointQueryContext *context, cpShape *shape, cpCollisionID id, cpPointQueryInfo *out)
+{
+       if(
+               !cpShapeFilterReject(shape->filter, context->filter) && !shape->sensor
+       ){
+               cpPointQueryInfo info;
+               cpShapePointQuery(shape, context->point, &info);
+               
+               if(info.distance < out->distance) (*out) = info;
+       }
+       
+       return id;
+}
+
+cpShape *
+cpSpacePointQueryNearest(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpPointQueryInfo *out)
+{
+       cpPointQueryInfo info = {NULL, cpvzero, maxDistance, cpvzero};
+       if(out){
+               (*out) = info;
+  } else {
+               out = &info;
+       }
+       
+       struct PointQueryContext context = {
+               point, maxDistance,
+               filter,
+               NULL
+       };
+       
+       cpBB bb = cpBBNewForCircle(point, cpfmax(maxDistance, 0.0f));
+       cpSpatialIndexQuery(space->dynamicShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQueryNearest, out);
+       cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQueryNearest, out);
+       
+       return (cpShape *)out->shape;
+}
+
+
+//MARK: Segment Query Functions
+
+struct SegmentQueryContext {
+       cpVect start, end;
+       cpFloat radius;
+       cpShapeFilter filter;
+       cpSpaceSegmentQueryFunc func;
+};
+
+static cpFloat
+SegmentQuery(struct SegmentQueryContext *context, cpShape *shape, void *data)
+{
+       cpSegmentQueryInfo info;
+       
+       if(
+               !cpShapeFilterReject(shape->filter, context->filter) &&
+               cpShapeSegmentQuery(shape, context->start, context->end, context->radius, &info)
+       ){
+               context->func(shape, info.point, info.normal, info.alpha, data);
+       }
+       
+       return 1.0f;
+}
+
+void
+cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryFunc func, void *data)
+{
+       struct SegmentQueryContext context = {
+               start, end,
+               radius,
+               filter,
+               func,
+       };
+       
+       cpSpaceLock(space); {
+    cpSpatialIndexSegmentQuery(space->staticShapes, &context, start, end, 1.0f, (cpSpatialIndexSegmentQueryFunc)SegmentQuery, data);
+    cpSpatialIndexSegmentQuery(space->dynamicShapes, &context, start, end, 1.0f, (cpSpatialIndexSegmentQueryFunc)SegmentQuery, data);
+       } cpSpaceUnlock(space, cpTrue);
+}
+
+static cpFloat
+SegmentQueryFirst(struct SegmentQueryContext *context, cpShape *shape, cpSegmentQueryInfo *out)
+{
+       cpSegmentQueryInfo info;
+       
+       if(
+               !cpShapeFilterReject(shape->filter, context->filter) && !shape->sensor &&
+               cpShapeSegmentQuery(shape, context->start, context->end, context->radius, &info) &&
+               info.alpha < out->alpha
+       ){
+               (*out) = info;
+       }
+       
+       return out->alpha;
+}
+
+cpShape *
+cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSegmentQueryInfo *out)
+{
+       cpSegmentQueryInfo info = {NULL, end, cpvzero, 1.0f};
+       if(out){
+               (*out) = info;
+  } else {
+               out = &info;
+       }
+       
+       struct SegmentQueryContext context = {
+               start, end,
+               radius,
+               filter,
+               NULL
+       };
+       
+       cpSpatialIndexSegmentQuery(space->staticShapes, &context, start, end, 1.0f, (cpSpatialIndexSegmentQueryFunc)SegmentQueryFirst, out);
+       cpSpatialIndexSegmentQuery(space->dynamicShapes, &context, start, end, out->alpha, (cpSpatialIndexSegmentQueryFunc)SegmentQueryFirst, out);
+       
+       return (cpShape *)out->shape;
+}
+
+//MARK: BB Query Functions
+
+struct BBQueryContext {
+       cpBB bb;
+       cpShapeFilter filter;
+       cpSpaceBBQueryFunc func;
+};
+
+static cpCollisionID
+BBQuery(struct BBQueryContext *context, cpShape *shape, cpCollisionID id, void *data)
+{
+       if(
+               !cpShapeFilterReject(shape->filter, context->filter) &&
+               cpBBIntersects(context->bb, shape->bb)
+       ){
+               context->func(shape, data);
+       }
+       
+       return id;
+}
+
+void
+cpSpaceBBQuery(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryFunc func, void *data)
+{
+       struct BBQueryContext context = {bb, filter, func};
+       
+       cpSpaceLock(space); {
+    cpSpatialIndexQuery(space->dynamicShapes, &context, bb, (cpSpatialIndexQueryFunc)BBQuery, data);
+    cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)BBQuery, data);
+       } cpSpaceUnlock(space, cpTrue);
+}
+
+//MARK: Shape Query Functions
+
+struct ShapeQueryContext {
+       cpSpaceShapeQueryFunc func;
+       void *data;
+       cpBool anyCollision;
+};
+
+// Callback from the spatial hash.
+static cpCollisionID
+ShapeQuery(cpShape *a, cpShape *b, cpCollisionID id, struct ShapeQueryContext *context)
+{
+       if(cpShapeFilterReject(a->filter, b->filter) || a == b) return id;
+       
+       cpContactPointSet set = cpShapesCollide(a, b);
+       if(set.count){
+               if(context->func) context->func(b, &set, context->data);
+               context->anyCollision = !(a->sensor || b->sensor);
+       }
+       
+       return id;
+}
+
+cpBool
+cpSpaceShapeQuery(cpSpace *space, cpShape *shape, cpSpaceShapeQueryFunc func, void *data)
+{
+       cpBody *body = shape->body;
+       cpBB bb = (body ? cpShapeUpdate(shape, body->transform) : shape->bb);
+       struct ShapeQueryContext context = {func, data, cpFalse};
+       
+       cpSpaceLock(space); {
+    cpSpatialIndexQuery(space->dynamicShapes, shape, bb, (cpSpatialIndexQueryFunc)ShapeQuery, &context);
+    cpSpatialIndexQuery(space->staticShapes, shape, bb, (cpSpatialIndexQueryFunc)ShapeQuery, &context);
+       } cpSpaceUnlock(space, cpTrue);
+       
+       return context.anyCollision;
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpSpaceStep.c b/dali-physics/third-party/chipmunk2d/src/cpSpaceStep.c
new file mode 100644 (file)
index 0000000..85cbb3d
--- /dev/null
@@ -0,0 +1,445 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+//MARK: Post Step Callback Functions
+
+cpPostStepCallback *
+cpSpaceGetPostStepCallback(cpSpace *space, void *key)
+{
+       cpArray *arr = space->postStepCallbacks;
+       for(int i=0; i<arr->num; i++){
+               cpPostStepCallback *callback = (cpPostStepCallback *)arr->arr[i];
+               if(callback && callback->key == key) return callback;
+       }
+       
+       return NULL;
+}
+
+static void PostStepDoNothing(cpSpace *space, void *obj, void *data){}
+
+cpBool
+cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data)
+{
+       cpAssertWarn(space->locked,
+               "Adding a post-step callback when the space is not locked is unnecessary. "
+               "Post-step callbacks will not called until the end of the next call to cpSpaceStep() or the next query.");
+       
+       if(!cpSpaceGetPostStepCallback(space, key)){
+               cpPostStepCallback *callback = (cpPostStepCallback *)cpcalloc(1, sizeof(cpPostStepCallback));
+               callback->func = (func ? func : PostStepDoNothing);
+               callback->key = key;
+               callback->data = data;
+               
+               cpArrayPush(space->postStepCallbacks, callback);
+               return cpTrue;
+       } else {
+               return cpFalse;
+       }
+}
+
+//MARK: Locking Functions
+
+void
+cpSpaceLock(cpSpace *space)
+{
+       space->locked++;
+}
+
+void
+cpSpaceUnlock(cpSpace *space, cpBool runPostStep)
+{
+       space->locked--;
+       cpAssertHard(space->locked >= 0, "Internal Error: Space lock underflow.");
+       
+       if(space->locked == 0){
+               cpArray *waking = space->rousedBodies;
+               
+               for(int i=0, count=waking->num; i<count; i++){
+                       cpSpaceActivateBody(space, (cpBody *)waking->arr[i]);
+                       waking->arr[i] = NULL;
+               }
+               
+               waking->num = 0;
+               
+               if(space->locked == 0 && runPostStep && !space->skipPostStep){
+                       space->skipPostStep = cpTrue;
+                       
+                       cpArray *arr = space->postStepCallbacks;
+                       for(int i=0; i<arr->num; i++){
+                               cpPostStepCallback *callback = (cpPostStepCallback *)arr->arr[i];
+                               cpPostStepFunc func = callback->func;
+                               
+                               // Mark the func as NULL in case calling it calls cpSpaceRunPostStepCallbacks() again.
+                               // TODO: need more tests around this case I think.
+                               callback->func = NULL;
+                               if(func) func(space, callback->key, callback->data);
+                               
+                               arr->arr[i] = NULL;
+                               cpfree(callback);
+                       }
+                       
+                       arr->num = 0;
+                       space->skipPostStep = cpFalse;
+               }
+       }
+}
+
+//MARK: Contact Buffer Functions
+
+struct cpContactBufferHeader {
+       cpTimestamp stamp;
+       cpContactBufferHeader *next;
+       unsigned int numContacts;
+};
+
+#define CP_CONTACTS_BUFFER_SIZE ((CP_BUFFER_BYTES - sizeof(cpContactBufferHeader))/sizeof(struct cpContact))
+typedef struct cpContactBuffer {
+       cpContactBufferHeader header;
+       struct cpContact contacts[CP_CONTACTS_BUFFER_SIZE];
+} cpContactBuffer;
+
+static cpContactBufferHeader *
+cpSpaceAllocContactBuffer(cpSpace *space)
+{
+       cpContactBuffer *buffer = (cpContactBuffer *)cpcalloc(1, sizeof(cpContactBuffer));
+       cpArrayPush(space->allocatedBuffers, buffer);
+       return (cpContactBufferHeader *)buffer;
+}
+
+static cpContactBufferHeader *
+cpContactBufferHeaderInit(cpContactBufferHeader *header, cpTimestamp stamp, cpContactBufferHeader *splice)
+{
+       header->stamp = stamp;
+       header->next = (splice ? splice->next : header);
+       header->numContacts = 0;
+       
+       return header;
+}
+
+void
+cpSpacePushFreshContactBuffer(cpSpace *space)
+{
+       cpTimestamp stamp = space->stamp;
+       
+       cpContactBufferHeader *head = space->contactBuffersHead;
+       
+       if(!head){
+               // No buffers have been allocated, make one
+               space->contactBuffersHead = cpContactBufferHeaderInit(cpSpaceAllocContactBuffer(space), stamp, NULL);
+       } else if(stamp - head->next->stamp > space->collisionPersistence){
+               // The tail buffer is available, rotate the ring
+       cpContactBufferHeader *tail = head->next;
+               space->contactBuffersHead = cpContactBufferHeaderInit(tail, stamp, tail);
+       } else {
+               // Allocate a new buffer and push it into the ring
+               cpContactBufferHeader *buffer = cpContactBufferHeaderInit(cpSpaceAllocContactBuffer(space), stamp, head);
+               space->contactBuffersHead = head->next = buffer;
+       }
+}
+
+
+struct cpContact *
+cpContactBufferGetArray(cpSpace *space)
+{
+       if(space->contactBuffersHead->numContacts + CP_MAX_CONTACTS_PER_ARBITER > CP_CONTACTS_BUFFER_SIZE){
+               // contact buffer could overflow on the next collision, push a fresh one.
+               cpSpacePushFreshContactBuffer(space);
+       }
+       
+       cpContactBufferHeader *head = space->contactBuffersHead;
+       return ((cpContactBuffer *)head)->contacts + head->numContacts;
+}
+
+void
+cpSpacePushContacts(cpSpace *space, int count)
+{
+       cpAssertHard(count <= CP_MAX_CONTACTS_PER_ARBITER, "Internal Error: Contact buffer overflow!");
+       space->contactBuffersHead->numContacts += count;
+}
+
+static void
+cpSpacePopContacts(cpSpace *space, int count){
+       space->contactBuffersHead->numContacts -= count;
+}
+
+//MARK: Collision Detection Functions
+
+static void *
+cpSpaceArbiterSetTrans(cpShape **shapes, cpSpace *space)
+{
+       if(space->pooledArbiters->num == 0){
+               // arbiter pool is exhausted, make more
+               int count = CP_BUFFER_BYTES/sizeof(cpArbiter);
+               cpAssertHard(count, "Internal Error: Buffer size too small.");
+               
+               cpArbiter *buffer = (cpArbiter *)cpcalloc(1, CP_BUFFER_BYTES);
+               cpArrayPush(space->allocatedBuffers, buffer);
+               
+               for(int i=0; i<count; i++) cpArrayPush(space->pooledArbiters, buffer + i);
+       }
+       
+       return cpArbiterInit((cpArbiter *)cpArrayPop(space->pooledArbiters), shapes[0], shapes[1]);
+}
+
+static inline cpBool
+QueryRejectConstraint(cpBody *a, cpBody *b)
+{
+       CP_BODY_FOREACH_CONSTRAINT(a, constraint){
+               if(
+                       !constraint->collideBodies && (
+                               (constraint->a == a && constraint->b == b) ||
+                               (constraint->a == b && constraint->b == a)
+                       )
+               ) return cpTrue;
+       }
+       
+       return cpFalse;
+}
+
+static inline cpBool
+QueryReject(cpShape *a, cpShape *b)
+{
+       return (
+               // BBoxes must overlap
+               !cpBBIntersects(a->bb, b->bb)
+               // Don't collide shapes attached to the same body.
+               || a->body == b->body
+               // Don't collide shapes that are filtered.
+               || cpShapeFilterReject(a->filter, b->filter)
+               // Don't collide bodies if they have a constraint with collideBodies == cpFalse.
+               || QueryRejectConstraint(a->body, b->body)
+       );
+}
+
+// Callback from the spatial hash.
+cpCollisionID
+cpSpaceCollideShapes(cpShape *a, cpShape *b, cpCollisionID id, cpSpace *space)
+{
+       // Reject any of the simple cases
+       if(QueryReject(a,b)) return id;
+       
+       // Narrow-phase collision detection.
+       struct cpCollisionInfo info = cpCollide(a, b, id, cpContactBufferGetArray(space));
+       
+       if(info.count == 0) return info.id; // Shapes are not colliding.
+       cpSpacePushContacts(space, info.count);
+       
+       // Get an arbiter from space->arbiterSet for the two shapes.
+       // This is where the persistant contact magic comes from.
+       const cpShape *shape_pair[] = {info.a, info.b};
+       cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)info.a, (cpHashValue)info.b);
+       cpArbiter *arb = (cpArbiter *)cpHashSetInsert(space->cachedArbiters, arbHashID, shape_pair, (cpHashSetTransFunc)cpSpaceArbiterSetTrans, space);
+       cpArbiterUpdate(arb, &info, space);
+       
+       cpCollisionHandler *handler = arb->handler;
+       
+       // Call the begin function first if it's the first step
+       if(arb->state == CP_ARBITER_STATE_FIRST_COLLISION && !handler->beginFunc(arb, space, handler->userData)){
+               cpArbiterIgnore(arb); // permanently ignore the collision until separation
+       }
+       
+       if(
+               // Ignore the arbiter if it has been flagged
+               (arb->state != CP_ARBITER_STATE_IGNORE) && 
+               // Call preSolve
+               handler->preSolveFunc(arb, space, handler->userData) &&
+               // Check (again) in case the pre-solve() callback called cpArbiterIgnored().
+               arb->state != CP_ARBITER_STATE_IGNORE &&
+               // Process, but don't add collisions for sensors.
+               !(a->sensor || b->sensor) &&
+               // Don't process collisions between two infinite mass bodies.
+               // This includes collisions between two kinematic bodies, or a kinematic body and a static body.
+               !(a->body->m == INFINITY && b->body->m == INFINITY)
+       ){
+               cpArrayPush(space->arbiters, arb);
+       } else {
+               cpSpacePopContacts(space, info.count);
+               
+               arb->contacts = NULL;
+               arb->count = 0;
+               
+               // Normally arbiters are set as used after calling the post-solve callback.
+               // However, post-solve() callbacks are not called for sensors or arbiters rejected from pre-solve.
+               if(arb->state != CP_ARBITER_STATE_IGNORE) arb->state = CP_ARBITER_STATE_NORMAL;
+       }
+       
+       // Time stamp the arbiter so we know it was used recently.
+       arb->stamp = space->stamp;
+       return info.id;
+}
+
+// Hashset filter func to throw away old arbiters.
+cpBool
+cpSpaceArbiterSetFilter(cpArbiter *arb, cpSpace *space)
+{
+       cpTimestamp ticks = space->stamp - arb->stamp;
+       
+       cpBody *a = arb->body_a, *b = arb->body_b;
+       
+       // TODO: should make an arbiter state for this so it doesn't require filtering arbiters for dangling body pointers on body removal.
+       // Preserve arbiters on sensors and rejected arbiters for sleeping objects.
+       // This prevents errant separate callbacks from happenening.
+       if(
+               (cpBodyGetType(a) == CP_BODY_TYPE_STATIC || cpBodyIsSleeping(a)) &&
+               (cpBodyGetType(b) == CP_BODY_TYPE_STATIC || cpBodyIsSleeping(b))
+       ){
+               return cpTrue;
+       }
+       
+       // Arbiter was used last frame, but not this one
+       if(ticks >= 1 && arb->state != CP_ARBITER_STATE_CACHED){
+               arb->state = CP_ARBITER_STATE_CACHED;
+               cpCollisionHandler *handler = arb->handler;
+               handler->separateFunc(arb, space, handler->userData);
+       }
+       
+       if(ticks >= space->collisionPersistence){
+               arb->contacts = NULL;
+               arb->count = 0;
+               
+               cpArrayPush(space->pooledArbiters, arb);
+               return cpFalse;
+       }
+       
+       return cpTrue;
+}
+
+//MARK: All Important cpSpaceStep() Function
+
+ void
+cpShapeUpdateFunc(cpShape *shape, void *unused)
+{
+       cpShapeCacheBB(shape);
+}
+
+void
+cpSpaceStep(cpSpace *space, cpFloat dt)
+{
+       // don't step if the timestep is 0!
+       if(dt == 0.0f) return;
+       
+       space->stamp++;
+       
+       cpFloat prev_dt = space->curr_dt;
+       space->curr_dt = dt;
+               
+       cpArray *bodies = space->dynamicBodies;
+       cpArray *constraints = space->constraints;
+       cpArray *arbiters = space->arbiters;
+       
+       // Reset and empty the arbiter lists.
+       for(int i=0; i<arbiters->num; i++){
+               cpArbiter *arb = (cpArbiter *)arbiters->arr[i];
+               arb->state = CP_ARBITER_STATE_NORMAL;
+               
+               // If both bodies are awake, unthread the arbiter from the contact graph.
+               if(!cpBodyIsSleeping(arb->body_a) && !cpBodyIsSleeping(arb->body_b)){
+                       cpArbiterUnthread(arb);
+               }
+       }
+       arbiters->num = 0;
+
+       cpSpaceLock(space); {
+               // Integrate positions
+               for(int i=0; i<bodies->num; i++){
+                       cpBody *body = (cpBody *)bodies->arr[i];
+                       body->position_func(body, dt);
+               }
+               
+               // Find colliding pairs.
+               cpSpacePushFreshContactBuffer(space);
+               cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)cpShapeUpdateFunc, NULL);
+               cpSpatialIndexReindexQuery(space->dynamicShapes, (cpSpatialIndexQueryFunc)cpSpaceCollideShapes, space);
+       } cpSpaceUnlock(space, cpFalse);
+       
+       // Rebuild the contact graph (and detect sleeping components if sleeping is enabled)
+       cpSpaceProcessComponents(space, dt);
+       
+       cpSpaceLock(space); {
+               // Clear out old cached arbiters and call separate callbacks
+               cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cpSpaceArbiterSetFilter, space);
+
+               // Prestep the arbiters and constraints.
+               cpFloat slop = space->collisionSlop;
+               cpFloat biasCoef = 1.0f - cpfpow(space->collisionBias, dt);
+               for(int i=0; i<arbiters->num; i++){
+                       cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt, slop, biasCoef);
+               }
+
+               for(int i=0; i<constraints->num; i++){
+                       cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+                       
+                       cpConstraintPreSolveFunc preSolve = constraint->preSolve;
+                       if(preSolve) preSolve(constraint, space);
+                       
+                       constraint->klass->preStep(constraint, dt);
+               }
+       
+               // Integrate velocities.
+               cpFloat damping = cpfpow(space->damping, dt);
+               cpVect gravity = space->gravity;
+               for(int i=0; i<bodies->num; i++){
+                       cpBody *body = (cpBody *)bodies->arr[i];
+                       body->velocity_func(body, gravity, damping, dt);
+               }
+               
+               // Apply cached impulses
+               cpFloat dt_coef = (prev_dt == 0.0f ? 0.0f : dt/prev_dt);
+               for(int i=0; i<arbiters->num; i++){
+                       cpArbiterApplyCachedImpulse((cpArbiter *)arbiters->arr[i], dt_coef);
+               }
+               
+               for(int i=0; i<constraints->num; i++){
+                       cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+                       constraint->klass->applyCachedImpulse(constraint, dt_coef);
+               }
+               
+               // Run the impulse solver.
+               for(int i=0; i<space->iterations; i++){
+                       for(int j=0; j<arbiters->num; j++){
+                               cpArbiterApplyImpulse((cpArbiter *)arbiters->arr[j]);
+                       }
+                               
+                       for(int j=0; j<constraints->num; j++){
+                               cpConstraint *constraint = (cpConstraint *)constraints->arr[j];
+                               constraint->klass->applyImpulse(constraint, dt);
+                       }
+               }
+               
+               // Run the constraint post-solve callbacks
+               for(int i=0; i<constraints->num; i++){
+                       cpConstraint *constraint = (cpConstraint *)constraints->arr[i];
+                       
+                       cpConstraintPostSolveFunc postSolve = constraint->postSolve;
+                       if(postSolve) postSolve(constraint, space);
+               }
+               
+               // run the post-solve callbacks
+               for(int i=0; i<arbiters->num; i++){
+                       cpArbiter *arb = (cpArbiter *) arbiters->arr[i];
+                       
+                       cpCollisionHandler *handler = arb->handler;
+                       handler->postSolveFunc(arb, space, handler->userData);
+               }
+       } cpSpaceUnlock(space, cpTrue);
+}
diff --git a/dali-physics/third-party/chipmunk2d/src/cpSpatialIndex.c b/dali-physics/third-party/chipmunk2d/src/cpSpatialIndex.c
new file mode 100644 (file)
index 0000000..3fb7cb5
--- /dev/null
@@ -0,0 +1,69 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+void
+cpSpatialIndexFree(cpSpatialIndex *index)
+{
+       if(index){
+               cpSpatialIndexDestroy(index);
+               cpfree(index);
+       }
+}
+
+cpSpatialIndex *
+cpSpatialIndexInit(cpSpatialIndex *index, cpSpatialIndexClass *klass, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+       index->klass = klass;
+       index->bbfunc = bbfunc;
+       index->staticIndex = staticIndex;
+       
+       if(staticIndex){
+               cpAssertHard(!staticIndex->dynamicIndex, "This static index is already associated with a dynamic index.");
+               staticIndex->dynamicIndex = index;
+       }
+       
+       return index;
+}
+
+typedef struct dynamicToStaticContext {
+       cpSpatialIndexBBFunc bbfunc;
+       cpSpatialIndex *staticIndex;
+       cpSpatialIndexQueryFunc queryFunc;
+       void *data;
+} dynamicToStaticContext;
+
+static void
+dynamicToStaticIter(void *obj, dynamicToStaticContext *context)
+{
+       cpSpatialIndexQuery(context->staticIndex, obj, context->bbfunc(obj), context->queryFunc, context->data);
+}
+
+void
+cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data)
+{
+       if(staticIndex && cpSpatialIndexCount(staticIndex) > 0){
+               dynamicToStaticContext context = {dynamicIndex->bbfunc, staticIndex, func, data};
+               cpSpatialIndexEach(dynamicIndex, (cpSpatialIndexIteratorFunc)dynamicToStaticIter, &context);
+       }
+}
+
diff --git a/dali-physics/third-party/chipmunk2d/src/cpSweep1D.c b/dali-physics/third-party/chipmunk2d/src/cpSweep1D.c
new file mode 100644 (file)
index 0000000..e200cf9
--- /dev/null
@@ -0,0 +1,254 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "chipmunk/chipmunk_private.h"
+
+static inline cpSpatialIndexClass *Klass();
+
+//MARK: Basic Structures
+
+typedef struct Bounds {
+       cpFloat min, max;
+} Bounds;
+
+typedef struct TableCell {
+       void *obj;
+       Bounds bounds;
+} TableCell;
+
+struct cpSweep1D
+{
+       cpSpatialIndex spatialIndex;
+       
+       int num;
+       int max;
+       TableCell *table;
+};
+
+static inline cpBool
+BoundsOverlap(Bounds a, Bounds b)
+{
+       return (a.min <= b.max && b.min <= a.max);
+}
+
+static inline Bounds
+BBToBounds(cpSweep1D *sweep, cpBB bb)
+{
+       Bounds bounds = {bb.l, bb.r};
+       return bounds;
+}
+
+static inline TableCell
+MakeTableCell(cpSweep1D *sweep, void *obj)
+{
+       TableCell cell = {obj, BBToBounds(sweep, sweep->spatialIndex.bbfunc(obj))};
+       return cell;
+}
+
+//MARK: Memory Management Functions
+
+cpSweep1D *
+cpSweep1DAlloc(void)
+{
+       return (cpSweep1D *)cpcalloc(1, sizeof(cpSweep1D));
+}
+
+static void
+ResizeTable(cpSweep1D *sweep, int size)
+{
+       sweep->max = size;
+       sweep->table = (TableCell *)cprealloc(sweep->table, size*sizeof(TableCell));
+}
+
+cpSpatialIndex *
+cpSweep1DInit(cpSweep1D *sweep, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+       cpSpatialIndexInit((cpSpatialIndex *)sweep, Klass(), bbfunc, staticIndex);
+       
+       sweep->num = 0;
+       ResizeTable(sweep, 32);
+       
+       return (cpSpatialIndex *)sweep;
+}
+
+cpSpatialIndex *
+cpSweep1DNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex)
+{
+       return cpSweep1DInit(cpSweep1DAlloc(), bbfunc, staticIndex);
+}
+
+static void
+cpSweep1DDestroy(cpSweep1D *sweep)
+{
+       cpfree(sweep->table);
+       sweep->table = NULL;
+}
+
+//MARK: Misc
+
+static int
+cpSweep1DCount(cpSweep1D *sweep)
+{
+       return sweep->num;
+}
+
+static void
+cpSweep1DEach(cpSweep1D *sweep, cpSpatialIndexIteratorFunc func, void *data)
+{
+       TableCell *table = sweep->table;
+       for(int i=0, count=sweep->num; i<count; i++) func(table[i].obj, data);
+}
+
+static int
+cpSweep1DContains(cpSweep1D *sweep, void *obj, cpHashValue hashid)
+{
+       TableCell *table = sweep->table;
+       for(int i=0, count=sweep->num; i<count; i++){
+               if(table[i].obj == obj) return cpTrue;
+       }
+       
+       return cpFalse;
+}
+
+//MARK: Basic Operations
+
+static void
+cpSweep1DInsert(cpSweep1D *sweep, void *obj, cpHashValue hashid)
+{
+       if(sweep->num == sweep->max) ResizeTable(sweep, sweep->max*2);
+       
+       sweep->table[sweep->num] = MakeTableCell(sweep, obj);
+       sweep->num++;
+}
+
+static void
+cpSweep1DRemove(cpSweep1D *sweep, void *obj, cpHashValue hashid)
+{
+       TableCell *table = sweep->table;
+       for(int i=0, count=sweep->num; i<count; i++){
+               if(table[i].obj == obj){
+                       int num = --sweep->num;
+                       
+                       table[i] = table[num];
+                       table[num].obj = NULL;
+                       
+                       return;
+               }
+       }
+}
+
+//MARK: Reindexing Functions
+
+static void
+cpSweep1DReindexObject(cpSweep1D *sweep, void *obj, cpHashValue hashid)
+{
+       // Nothing to do here
+}
+
+static void
+cpSweep1DReindex(cpSweep1D *sweep)
+{
+       // Nothing to do here
+       // Could perform a sort, but queries are not accelerated anyway.
+}
+
+//MARK: Query Functions
+
+static void
+cpSweep1DQuery(cpSweep1D *sweep, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data)
+{
+       // Implementing binary search here would allow you to find an upper limit
+       // but not a lower limit. Probably not worth the hassle.
+       
+       Bounds bounds = BBToBounds(sweep, bb);
+       
+       TableCell *table = sweep->table;
+       for(int i=0, count=sweep->num; i<count; i++){
+               TableCell cell = table[i];
+               if(BoundsOverlap(bounds, cell.bounds) && obj != cell.obj) func(obj, cell.obj, 0, data);
+       }
+}
+
+static void
+cpSweep1DSegmentQuery(cpSweep1D *sweep, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data)
+{
+       cpBB bb = cpBBExpand(cpBBNew(a.x, a.y, a.x, a.y), b);
+       Bounds bounds = BBToBounds(sweep, bb);
+       
+       TableCell *table = sweep->table;
+       for(int i=0, count=sweep->num; i<count; i++){
+               TableCell cell = table[i];
+               if(BoundsOverlap(bounds, cell.bounds)) func(obj, cell.obj, data);
+       }
+}
+
+//MARK: Reindex/Query
+
+static int
+TableSort(TableCell *a, TableCell *b)
+{
+       return (a->bounds.min < b->bounds.min ? -1 : (a->bounds.min > b->bounds.min ? 1 : 0));
+}
+
+static void
+cpSweep1DReindexQuery(cpSweep1D *sweep, cpSpatialIndexQueryFunc func, void *data)
+{
+       TableCell *table = sweep->table;
+       int count = sweep->num;
+       
+       // Update bounds and sort
+       for(int i=0; i<count; i++) table[i] = MakeTableCell(sweep, table[i].obj);
+       qsort(table, count, sizeof(TableCell), (int (*)(const void *, const void *))TableSort); // TODO: use insertion sort instead
+       
+       for(int i=0; i<count; i++){
+               TableCell cell = table[i];
+               cpFloat max = cell.bounds.max;
+               
+               for(int j=i+1; table[j].bounds.min < max && j<count; j++){
+                       func(cell.obj, table[j].obj, 0, data);
+               }
+       }
+       
+       // Reindex query is also responsible for colliding against the static index.
+       // Fortunately there is a helper function for that.
+       cpSpatialIndexCollideStatic((cpSpatialIndex *)sweep, sweep->spatialIndex.staticIndex, func, data);
+}
+
+static cpSpatialIndexClass klass = {
+       (cpSpatialIndexDestroyImpl)cpSweep1DDestroy,
+       
+       (cpSpatialIndexCountImpl)cpSweep1DCount,
+       (cpSpatialIndexEachImpl)cpSweep1DEach,
+       (cpSpatialIndexContainsImpl)cpSweep1DContains,
+       
+       (cpSpatialIndexInsertImpl)cpSweep1DInsert,
+       (cpSpatialIndexRemoveImpl)cpSweep1DRemove,
+       
+       (cpSpatialIndexReindexImpl)cpSweep1DReindex,
+       (cpSpatialIndexReindexObjectImpl)cpSweep1DReindexObject,
+       (cpSpatialIndexReindexQueryImpl)cpSweep1DReindexQuery,
+       
+       (cpSpatialIndexQueryImpl)cpSweep1DQuery,
+       (cpSpatialIndexSegmentQueryImpl)cpSweep1DSegmentQuery,
+};
+
+static inline cpSpatialIndexClass *Klass(){return &klass;}
+
diff --git a/dali-physics/third-party/chipmunk2d/src/prime.h b/dali-physics/third-party/chipmunk2d/src/prime.h
new file mode 100644 (file)
index 0000000..d470c2c
--- /dev/null
@@ -0,0 +1,68 @@
+/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+// Used for resizing hash tables.
+// Values approximately double.
+// http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
+static int primes[] = {
+       5,
+       13,
+       23,
+       47,
+       97,
+       193,
+       389,
+       769,
+       1543,
+       3079,
+       6151,
+       12289,
+       24593,
+       49157,
+       98317,
+       196613,
+       393241,
+       786433,
+       1572869,
+       3145739,
+       6291469,
+       12582917,
+       25165843,
+       50331653,
+       100663319,
+       201326611,
+       402653189,
+       805306457,
+       1610612741,
+       0,
+};
+
+static inline int
+next_prime(int n)
+{
+       int i = 0;
+       while(n > primes[i]){
+               i++;
+               cpAssertHard(primes[i], "Tried to resize a hash table to a size greater than 1610612741 O_o"); // realistically this should never happen
+       }
+       
+       return primes[i];
+}
index 3930d33..0c5922b 100644 (file)
@@ -49,6 +49,7 @@ static constexpr std::string_view TOKEN_ROOT                = "ROOT";
 static constexpr std::string_view TOKEN_MOTION              = "MOTION";
 static constexpr std::string_view PROPERTY_NAME_POSITION    = "position";
 static constexpr std::string_view PROPERTY_NAME_ORIENTATION = "orientation";
+static constexpr std::string_view TOKEN_OPENING_BRACE       = "{";
 static constexpr std::string_view TOKEN_CLOSING_BRACE       = "}";
 
 enum class Channel
@@ -87,9 +88,10 @@ void trim(std::string& s)
           s.end());
 }
 
-void ParseHierarchy(std::istream& file, std::shared_ptr<Joint>& joint)
+bool ParseHierarchy(std::istream& file, std::shared_ptr<Joint>& joint)
 {
   std::string line;
+  bool        braceExist = false;
   while(std::getline(file, line))
   {
     trim(line);
@@ -142,24 +144,68 @@ void ParseHierarchy(std::istream& file, std::shared_ptr<Joint>& joint)
       joint->children.push_back(child);
       std::getline(stream, token, ' ');
       child->name = token;
-      ParseHierarchy(file, child);
+
+      if(DALI_UNLIKELY(!ParseHierarchy(file, child)))
+      {
+        return false;
+      }
     }
     else if(line == TOKEN_END_SITE.data())
     {
+      bool braceExistEndSite = false;
       while(std::getline(file, line))
       {
         trim(line);
-        if(line == TOKEN_CLOSING_BRACE.data())
+        if(line == TOKEN_OPENING_BRACE.data())
+        {
+          if(DALI_UNLIKELY(braceExistEndSite))
+          {
+            DALI_LOG_ERROR("Parsing error : Joint[%s] End Site opening brace not matched\n", joint->name.c_str());
+            return false;
+          }
+          braceExistEndSite = true;
+        }
+        else if(line == TOKEN_CLOSING_BRACE.data())
         {
+          if(DALI_UNLIKELY(!braceExistEndSite))
+          {
+            DALI_LOG_ERROR("Parsing error : Joint[%s] End Site closing brace not matched\n", joint->name.c_str());
+            return false;
+          }
           break;
         }
       }
+      if(DALI_UNLIKELY(!braceExistEndSite))
+      {
+        DALI_LOG_ERROR("Parsing error : Joint[%s] End Site opening brace not exist\n", joint->name.c_str());
+        return false;
+      }
+    }
+    else if(token == TOKEN_OPENING_BRACE.data())
+    {
+      if(DALI_UNLIKELY(braceExist))
+      {
+        DALI_LOG_ERROR("Parsing error : Joint[%s] opening brace not matched\n", joint->name.c_str());
+        return false;
+      }
+      braceExist = true;
     }
     else if(token == TOKEN_CLOSING_BRACE.data())
     {
+      if(DALI_UNLIKELY(!braceExist))
+      {
+        DALI_LOG_ERROR("Parsing error : Joint[%s] closing brace not matched\n", joint->name.c_str());
+        return false;
+      }
       break;
     }
   }
+  if(DALI_UNLIKELY(!braceExist))
+  {
+    DALI_LOG_ERROR("Parsing error : Joint[%s] opening brace not exist\n", joint->name.c_str());
+    return false;
+  }
+  return true;
 }
 
 void MakeList(std::shared_ptr<Joint>& joint, std::vector<std::shared_ptr<Joint>>& jointList)
@@ -171,7 +217,7 @@ void MakeList(std::shared_ptr<Joint>& joint, std::vector<std::shared_ptr<Joint>>
   }
 }
 
-void ParseMotion(std::istream& file, std::shared_ptr<Joint>& hierarchy, uint32_t& frameCount, float& frameTime)
+bool ParseMotion(std::istream& file, std::shared_ptr<Joint>& hierarchy, uint32_t& frameCount, float& frameTime)
 {
   std::vector<std::shared_ptr<Joint>> jointList;
   MakeList(hierarchy, jointList);
@@ -198,10 +244,33 @@ void ParseMotion(std::istream& file, std::shared_ptr<Joint>& hierarchy, uint32_t
     }
   }
 
+  if(DALI_UNLIKELY(!frameCountLoaded))
+  {
+    DALI_LOG_ERROR("Parsing error : Frames not exist!\n");
+    return false;
+  }
+  if(DALI_UNLIKELY(!frameTimeLoaded))
+  {
+    DALI_LOG_ERROR("Parsing error : Frame Time not exist!\n");
+    return false;
+  }
+
+  uint32_t loadedFrameCount = 0u;
+
   while(std::getline(file, line))
   {
     trim(line);
+    if(DALI_UNLIKELY(line.empty()))
+    {
+      continue;
+    }
     std::istringstream stream(line);
+    if(DALI_UNLIKELY(++loadedFrameCount > frameCount))
+    {
+      // Parse failed. Just skip decoding, and get the number of line for debug.
+      continue;
+    }
+
     for(auto&& joint : jointList)
     {
       Vector3    translation;
@@ -243,11 +312,21 @@ void ParseMotion(std::istream& file, std::shared_ptr<Joint>& hierarchy, uint32_t
       joint->rotations.push_back(rotation[2] * rotation[0] * rotation[1]);
     }
   }
+
+  if(DALI_UNLIKELY(loadedFrameCount != frameCount))
+  {
+    DALI_LOG_ERROR("Parsing error : Motion frame count not matched! expect : %u, loaded : %u\n", frameCount, loadedFrameCount);
+    return false;
+  }
+
+  return true;
 }
 
 bool ParseBvh(std::istream& file, uint32_t& frameCount, float& frameTime, std::shared_ptr<Joint>& rootJoint)
 {
   std::string line;
+  bool        parseHierarchy = false;
+  bool        parseMotion    = false;
   while(std::getline(file, line))
   {
     trim(line);
@@ -267,17 +346,17 @@ bool ParseBvh(std::istream& file, uint32_t& frameCount, float& frameTime, std::s
         {
           std::getline(stream, token, ' ');
           rootJoint->name = token;
-          ParseHierarchy(file, rootJoint);
+          parseHierarchy  = ParseHierarchy(file, rootJoint);
           break;
         }
       }
     }
     if(token == TOKEN_MOTION.data())
     {
-      ParseMotion(file, rootJoint, frameCount, frameTime);
+      parseMotion = ParseMotion(file, rootJoint, frameCount, frameTime);
     }
   }
-  return true;
+  return parseHierarchy && parseMotion;
 }
 
 AnimationDefinition GenerateAnimation(const std::string& animationName, std::shared_ptr<Joint>& hierarchy, uint32_t frameCount, float frameTime, const Vector3& scale)
index 94ae63c..7436b85 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_IMAGE_VISUAL_ACTIONS_DEVEL_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
  *
  */
 #include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
+#include <dali-toolkit/devel-api/visuals/image-visual-actions-devel.h>
 
 namespace Dali
 {
@@ -35,10 +36,12 @@ namespace Action
  */
 enum Type
 {
-  PLAY = VISUAL_ACTION_START_INDEX, ///< Play the animated GIF. This is also Default playback mode.
-  PAUSE,                            ///< Pause the animated GIF.
-  STOP,                             ///< Stop the animated GIF.
-  JUMP_TO                           ///< Jump to the specified frame. Property::INTEGER value should be passed.
+  PLAY = DevelImageVisual::Action::IMAGE_VISUAL_ACTION_END_INDEX, ///< Play the animated GIF. This is also Default playback mode.
+  PAUSE,                                                          ///< Pause the animated GIF.
+  STOP,                                                           ///< Stop the animated GIF.
+  JUMP_TO,                                                        ///< Jump to the specified frame. Property::INTEGER value should be passed.
+
+  ANIMATED_IMAGE_VISUAL_ACTION_END_INDEX = DevelImageVisual::Action::IMAGE_VISUAL_ACTION_END_INDEX + 1000  ///< End of animated image visual action index.
 };
 
 } // namespace Action
index 33c88e0..a175eb3 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_VECTOR_IMAGE_VISUAL_ACTIONS_DEVEL_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@
 
 // EXTERNAL INCLUDES
 #include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
+#include <dali-toolkit/devel-api/visuals/image-visual-actions-devel.h>
+#include <dali-toolkit/devel-api/visuals/animated-image-visual-actions-devel.h>
 #include <dali/public-api/signals/callback.h>
 #include <string>
 
@@ -39,11 +41,14 @@ namespace Action
  */
 enum Type
 {
-  PLAY = VISUAL_ACTION_START_INDEX, ///< Play the animated vector image.
-  PAUSE,                            ///< Pause the animated vector image.
-  STOP,                             ///< Stop the animated vector image. This is also Default playback mode.
-  JUMP_TO,                          ///< Jump to the specified frame. Property::INTEGER value should be passed.
-  SET_DYNAMIC_PROPERTY              ///< Set the dynamic property.
+  // Shared actions with AnimatedImageVisual
+  PLAY    = DevelAnimatedImageVisual::Action::PLAY,    ///< Play the animated vector image.
+  PAUSE   = DevelAnimatedImageVisual::Action::PAUSE,   ///< Pause the animated vector image.
+  STOP    = DevelAnimatedImageVisual::Action::STOP,    ///< Stop the animated vector image. This is also Default playback mode.
+  JUMP_TO = DevelAnimatedImageVisual::Action::JUMP_TO, ///< Jump to the specified frame. Property::INTEGER value should be passed.
+
+  // AnimatedVectorImageVisual only actions
+  SET_DYNAMIC_PROPERTY = DevelAnimatedImageVisual::Action::ANIMATED_IMAGE_VISUAL_ACTION_END_INDEX ///< Set the dynamic property.
 };
 
 } // namespace Action
index 66b4715..f49c2ff 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_DEVEL_API_VISUALS_IMAGE_VISUAL_ACTIONS_DEVEL_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,7 +35,9 @@ namespace Action
  */
 enum Type
 {
-  RELOAD = VISUAL_ACTION_START_INDEX ///< Force reloading of the image, all visuals using this image will get the latest one.
+  RELOAD = VISUAL_ACTION_START_INDEX, ///< Force reloading of the image, all visuals using this image will get the latest one.
+
+  IMAGE_VISUAL_ACTION_END_INDEX = VISUAL_ACTION_START_INDEX + 10000 ///< End of image visual action index.
 };
 
 } // namespace Action
index 6feb609..e942030 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 2;
-const unsigned int TOOLKIT_MICRO_VERSION = 36;
+const unsigned int TOOLKIT_MICRO_VERSION = 37;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index c8afebc..26f467c 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.2.36
+Version:    2.2.37
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT
@@ -120,6 +120,46 @@ Requires:   %{dali2_scene3d} = %{version}-%{release}
 %description -n %{dali2_scene3d}-devel
 Development components for dali-scene3d.
 
+##############################
+# dali-physics-2d
+##############################
+%define dali2_physics2d dali2-physics-2d
+%package -n %{dali2_physics2d}
+Summary:    Physics library 2D
+Group:      System/Libraries
+License:    Apache-2.0
+
+%description -n %{dali2_physics2d}
+Provides functionality for 2D physics simulation. See README.md for more details.
+
+%package -n %{dali2_physics2d}-devel
+Summary:    Development components for dali2-physics-2d
+Group:      Development/Building
+Requires:   %{dali2_physics2d} = %{version}-%{release}
+
+%description -n %{dali2_physics2d}-devel
+Development components for dali2-physics-2d.
+
+##############################
+# dali-physics-3d
+##############################
+%define dali2_physics3d dali2-physics-3d
+%package -n %{dali2_physics3d}
+Summary:    Physics library 3D
+Group:      System/Libraries
+License:    Apache-2.0
+
+%description -n %{dali2_physics3d}
+Provides functionality for 3D physics simulation. See README.md for more details.
+
+%package -n %{dali2_physics3d}-devel
+Summary:    Development components for dali2-physics-3d
+Group:      Development/Building
+Requires:   %{dali2_physics3d} = %{version}-%{release}
+
+%description -n %{dali2_physics3d}-devel
+Development components for dali2-physics-3d.
+
 %define dali_data_rw_dir            %TZ_SYS_SHARE/dali/
 %define dali_data_ro_dir            %TZ_SYS_RO_SHARE/dali/
 
@@ -495,3 +535,36 @@ esac
 %{_includedir}/dali-scene3d/public-api/*
 %{_includedir}/dali-scene3d/dali-scene3d.h
 %{_libdir}/pkgconfig/dali2-scene3d.pc
+
+%files -n %{dali2_physics2d}
+%if 0%{?enable_dali_smack_rules}
+%manifest dali-physics-2d.manifest-smack
+%else
+%manifest dali-physics-2d.manifest
+%endif
+%defattr(-,root,root,-)
+%{_libdir}/libchipmunk.so*
+%license LICENSE
+
+%files -n %{dali2_physics2d}-devel
+%defattr(-,root,root,-)
+%{_includedir}/chipmunk/*
+%{_libdir}/pkgconfig/dali2-physics-2d.pc
+%{_libdir}/pkgconfig/chipmunk2d.pc
+
+%files -n %{dali2_physics3d}
+%if 0%{?enable_dali_smack_rules}
+%manifest dali-physics-3d.manifest-smack
+%else
+%manifest dali-physics-3d.manifest
+%endif
+%defattr(-,root,root,-)
+%{_libdir}/libbullet3.so*
+%license LICENSE
+
+%files -n %{dali2_physics3d}-devel
+%defattr(-,root,root,-)
+%{_includedir}/bullet/*
+%{_libdir}/pkgconfig/dali2-physics-3d.pc
+%{_libdir}/pkgconfig/bullet3.pc
+